ode-0.16/0000775000175200017520000000000013403273061007215 500000000000000ode-0.16/test-driver0000755000175200017520000001104013403272663011334 00000000000000#! /bin/sh # test-driver - basic testsuite driver script. scriptversion=2013-07-13.22; # UTC # Copyright (C) 2011-2014 Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . # Make unconditional expansion of undefined variables an error. This # helps a lot in preventing typo-related bugs. set -u usage_error () { echo "$0: $*" >&2 print_usage >&2 exit 2 } print_usage () { cat <$log_file 2>&1 estatus=$? if test $enable_hard_errors = no && test $estatus -eq 99; then tweaked_estatus=1 else tweaked_estatus=$estatus fi case $tweaked_estatus:$expect_failure in 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; 0:*) col=$grn res=PASS recheck=no gcopy=no;; 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;; *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;; *:*) col=$red res=FAIL recheck=yes gcopy=yes;; esac # Report the test outcome and exit status in the logs, so that one can # know whether the test passed or failed simply by looking at the '.log' # file, without the need of also peaking into the corresponding '.trs' # file (automake bug#11814). echo "$res $test_name (exit status: $estatus)" >>$log_file # Report outcome to console. echo "${col}${res}${std}: $test_name" # Register the test result, and other relevant metadata. echo ":test-result: $res" > $trs_file echo ":global-test-result: $res" >> $trs_file echo ":recheck: $recheck" >> $trs_file echo ":copy-in-global-log: $gcopy" >> $trs_file # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: ode-0.16/OPCODE/0000775000175200017520000000000013403273061010166 500000000000000ode-0.16/OPCODE/OPC_BaseModel.h0000664000175200017520000002601413403272463012623 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* * OPCODE - Optimized Collision Detection * Copyright (C) 2001 Pierre Terdiman * Homepage: http://www.codercorner.com/Opcode.htm */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains base model interface. * \file OPC_BaseModel.h * \author Pierre Terdiman * \date May, 18, 2003 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Include Guard #ifndef __OPC_BASEMODEL_H__ #define __OPC_BASEMODEL_H__ //! Model creation structure struct OPCODE_API OPCODECREATE { //! Constructor inline_ OPCODECREATE(): mIMesh(null), mSettings(SPLIT_SPLATTER_POINTS | SPLIT_GEOM_CENTER), mNoLeaf(true), mQuantized(true), #ifdef __MESHMERIZER_H__ mCollisionHull(false), #endif // __MESHMERIZER_H__ mKeepOriginal(false), mCanRemap(false) { } inline_ OPCODECREATE(MeshInterface *IMesh, const BuildSettings &Settings, bool NoLeaf, bool Quantized): mIMesh(IMesh), mSettings(Settings), mNoLeaf(NoLeaf), mQuantized(Quantized), #ifdef __MESHMERIZER_H__ mCollisionHull(false), #endif // __MESHMERIZER_H__ mKeepOriginal(false), mCanRemap(false) { } MeshInterface* mIMesh; //!< Mesh interface (access to triangles & vertices) (*) BuildSettings mSettings; //!< Builder's settings bool mNoLeaf; //!< true => discard leaf nodes (else use a normal tree) bool mQuantized; //!< true => quantize the tree (else use a normal tree) #ifdef __MESHMERIZER_H__ bool mCollisionHull; //!< true => use convex hull + GJK #endif // __MESHMERIZER_H__ bool mKeepOriginal; //!< true => keep a copy of the original tree (debug purpose) bool mCanRemap; //!< true => allows OPCODE to reorganize client arrays // (*) This pointer is saved internally and used by OPCODE until collision structures are released, // so beware of the object's lifetime. }; enum ModelFlag { OPC_QUANTIZED = (1<<0), //!< Compressed/uncompressed tree OPC_NO_LEAF = (1<<1), //!< Leaf/NoLeaf tree OPC_SINGLE_NODE = (1<<2) //!< Special case for 1-node models }; class OPCODE_API BaseModel { public: // Constructor/Destructor BaseModel(); virtual ~BaseModel(); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Builds a collision model. * \param create [in] model creation structure * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// virtual bool Build(const OPCODECREATE& create) = 0; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Gets the number of bytes used by the tree. * \return amount of bytes used */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// virtual udword GetUsedBytes() const = 0; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Refits the collision model. This can be used to handle dynamic meshes. Usage is: * 1. modify your mesh vertices (keep the topology constant!) * 2. refit the tree (call this method) * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// virtual bool Refit(); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Gets the source tree. * \return generic tree */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ const AABBTree* GetSourceTree() const { return mSource; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Gets the tree. * \return the collision tree */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ const AABBOptimizedTree* GetTree() const { return mTree; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Gets the tree. * \return the collision tree */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ AABBOptimizedTree* GetTree() { return mTree; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Gets the number of nodes in the tree. * Should be 2*N-1 for normal trees and N-1 for optimized ones. * \return number of nodes */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ udword GetNbNodes() const { return mTree->GetNbNodes(); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Checks whether the tree has leaf nodes or not. * \return true if the tree has leaf nodes (normal tree), else false (optimized tree) */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ BOOL HasLeafNodes() const { return !(mModelCode & OPC_NO_LEAF); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Checks whether the tree is quantized or not. * \return true if the tree is quantized */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ BOOL IsQuantized() const { return mModelCode & OPC_QUANTIZED; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Checks whether the model has a single node or not. This special case must be handled separately. * \return true if the model has only 1 node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ BOOL HasSingleNode() const { return mModelCode & OPC_SINGLE_NODE; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Gets the model's code. * \return model's code */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ udword GetModelCode() const { return mModelCode; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Gets the mesh interface. * \return mesh interface */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ const MeshInterface* GetMeshInterface() const { return mIMesh; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Sets the mesh interface. * \param imesh [in] mesh interface */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ void SetMeshInterface(const MeshInterface* imesh) { mIMesh = imesh; } protected: const MeshInterface* mIMesh; //!< User-defined mesh interface udword mModelCode; //!< Model code = combination of ModelFlag(s) AABBTree* mSource; //!< Original source tree AABBOptimizedTree* mTree; //!< Optimized tree owned by the model // Internal methods void ReleaseBase(); bool CreateTree(bool no_leaf, bool quantized); }; #endif //__OPC_BASEMODEL_H__ ode-0.16/OPCODE/OPC_Picking.cpp0000664000175200017520000001231013403272463012701 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* * OPCODE - Optimized Collision Detection * Copyright (C) 2001 Pierre Terdiman * Homepage: http://www.codercorner.com/Opcode.htm */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains code to perform "picking". * \file OPC_Picking.cpp * \author Pierre Terdiman * \date March, 20, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Precompiled Header #include "Stdafx.h" using namespace Opcode; #ifdef OPC_RAYHIT_CALLBACK /* Possible RayCollider usages: - boolean query (shadow feeler) - closest hit - all hits - number of intersection (boolean) */ bool Opcode::SetupAllHits(RayCollider& collider, CollisionFaces& contacts) { struct Local { static void AllContacts(const CollisionFace& hit, void* user_data) { CollisionFaces* CF = (CollisionFaces*)user_data; CF->AddFace(hit); } }; collider.SetFirstContact(false); collider.SetHitCallback(Local::AllContacts); collider.SetUserData(&contacts); return true; } bool Opcode::SetupClosestHit(RayCollider& collider, CollisionFace& closest_contact) { struct Local { static void ClosestContact(const CollisionFace& hit, void* user_data) { CollisionFace* CF = (CollisionFace*)user_data; if(hit.mDistancemDistance) *CF = hit; } }; collider.SetFirstContact(false); collider.SetHitCallback(Local::ClosestContact); collider.SetUserData(&closest_contact); closest_contact.mDistance = MAX_FLOAT; return true; } bool Opcode::SetupShadowFeeler(RayCollider& collider) { collider.SetFirstContact(true); collider.SetHitCallback(null); return true; } bool Opcode::SetupInOutTest(RayCollider& collider) { collider.SetFirstContact(false); collider.SetHitCallback(null); // Results with collider.GetNbIntersections() return true; } bool Opcode::Picking( CollisionFace& picked_face, const Ray& world_ray, const Model& model, const Matrix4x4* world, float min_dist, float max_dist, const Point& view_point, CullModeCallback callback, void* user_data) { struct Local { struct CullData { CollisionFace* Closest; float MinLimit; CullModeCallback Callback; void* UserData; Point ViewPoint; const MeshInterface* IMesh; }; // Called for each stabbed face static void RenderCullingCallback(const CollisionFace& hit, void* user_data) { CullData* Data = (CullData*)user_data; // Discard face if we already have a closer hit if(hit.mDistance>=Data->Closest->mDistance) return; // Discard face if hit point is smaller than min limit. This mainly happens when the face is in front // of the near clip plane (or straddles it). If we keep the face nonetheless, the user can select an // object that he may not even be able to see, which is very annoying. if(hit.mDistance<=Data->MinLimit) return; // This is the index of currently stabbed triangle. udword StabbedFaceIndex = hit.mFaceID; // We may keep it or not, depending on backface culling bool KeepIt = true; // Catch *render* cull mode for this face CullMode CM = (Data->Callback)(StabbedFaceIndex, Data->UserData); if(CM!=CULLMODE_NONE) // Don't even compute culling for double-sided triangles { // Compute backface culling for current face VertexPointers VP; ConversionArea VC; Data->IMesh->GetTriangle(VP, StabbedFaceIndex, VC); if(VP.BackfaceCulling(Data->ViewPoint)) { if(CM==CULLMODE_CW) KeepIt = false; } else { if(CM==CULLMODE_CCW) KeepIt = false; } } if(KeepIt) *Data->Closest = hit; } }; RayCollider RC; RC.SetMaxDist(max_dist); RC.SetTemporalCoherence(false); RC.SetCulling(false); // We need all faces since some of them can be double-sided RC.SetFirstContact(false); RC.SetHitCallback(Local::RenderCullingCallback); picked_face.mFaceID = INVALID_ID; picked_face.mDistance = MAX_FLOAT; picked_face.mU = 0.0f; picked_face.mV = 0.0f; Local::CullData Data; Data.Closest = &picked_face; Data.MinLimit = min_dist; Data.Callback = callback; Data.UserData = user_data; Data.ViewPoint = view_point; Data.IMesh = model.GetMeshInterface(); if(world) { // Get matrices Matrix4x4 InvWorld; InvertPRMatrix(InvWorld, *world); // Compute camera position in mesh space Data.ViewPoint *= InvWorld; } RC.SetUserData(&Data); if(RC.Collide(world_ray, model, world)) { return picked_face.mFaceID!=INVALID_ID; } return false; } #endif ode-0.16/OPCODE/OPC_SphereTriOverlap.h0000664000175200017520000001053513403272463014227 00000000000000 // This is collision detection. If you do another distance test for collision *response*, // if might be useful to simply *skip* the test below completely, and report a collision. // - if sphere-triangle overlap, result is ok // - if they don't, we'll discard them during collision response with a similar test anyway // Overall this approach should run faster. // Original code by David Eberly in Magic. BOOL SphereCollider::SphereTriOverlap(const Point& vert0, const Point& vert1, const Point& vert2) { // Stats mNbVolumePrimTests++; // Early exit if one of the vertices is inside the sphere Point kDiff = vert2 - mCenter; float fC = kDiff.SquareMagnitude(); if(fC <= mRadius2) return TRUE; kDiff = vert1 - mCenter; fC = kDiff.SquareMagnitude(); if(fC <= mRadius2) return TRUE; kDiff = vert0 - mCenter; fC = kDiff.SquareMagnitude(); if(fC <= mRadius2) return TRUE; // Else do the full distance test Point TriEdge0 = vert1 - vert0; Point TriEdge1 = vert2 - vert0; //Point kDiff = vert0 - mCenter; float fA00 = TriEdge0.SquareMagnitude(); float fA01 = TriEdge0 | TriEdge1; float fA11 = TriEdge1.SquareMagnitude(); float fB0 = kDiff | TriEdge0; float fB1 = kDiff | TriEdge1; //float fC = kDiff.SquareMagnitude(); float fDet = fabsf(fA00*fA11 - fA01*fA01); float u = fA01*fB1-fA11*fB0; float v = fA01*fB0-fA00*fB1; float SqrDist; if(u + v <= fDet) { if(u < 0.0f) { if(v < 0.0f) // region 4 { if(fB0 < 0.0f) { // v = 0.0f; if(-fB0>=fA00) { /*u = 1.0f;*/ SqrDist = fA00+2.0f*fB0+fC; } else { u = -fB0/fA00; SqrDist = fB0*u+fC; } } else { // u = 0.0f; if(fB1>=0.0f) { /*v = 0.0f;*/ SqrDist = fC; } else if(-fB1>=fA11) { /*v = 1.0f;*/ SqrDist = fA11+2.0f*fB1+fC; } else { v = -fB1/fA11; SqrDist = fB1*v+fC; } } } else // region 3 { // u = 0.0f; if(fB1>=0.0f) { /*v = 0.0f;*/ SqrDist = fC; } else if(-fB1>=fA11) { /*v = 1.0f;*/ SqrDist = fA11+2.0f*fB1+fC; } else { v = -fB1/fA11; SqrDist = fB1*v+fC; } } } else if(v < 0.0f) // region 5 { // v = 0.0f; if(fB0>=0.0f) { /*u = 0.0f;*/ SqrDist = fC; } else if(-fB0>=fA00) { /*u = 1.0f;*/ SqrDist = fA00+2.0f*fB0+fC; } else { u = -fB0/fA00; SqrDist = fB0*u+fC; } } else // region 0 { // minimum at interior point if(fDet==0.0f) { // u = 0.0f; // v = 0.0f; SqrDist = MAX_FLOAT; } else { float fInvDet = 1.0f/fDet; u *= fInvDet; v *= fInvDet; SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC; } } } else { float fTmp0, fTmp1, fNumer, fDenom; if(u < 0.0f) // region 2 { fTmp0 = fA01 + fB0; fTmp1 = fA11 + fB1; if(fTmp1 > fTmp0) { fNumer = fTmp1 - fTmp0; fDenom = fA00-2.0f*fA01+fA11; if(fNumer >= fDenom) { // u = 1.0f; // v = 0.0f; SqrDist = fA00+2.0f*fB0+fC; } else { u = fNumer/fDenom; v = 1.0f - u; SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC; } } else { // u = 0.0f; if(fTmp1 <= 0.0f) { /*v = 1.0f;*/ SqrDist = fA11+2.0f*fB1+fC; } else if(fB1 >= 0.0f) { /*v = 0.0f;*/ SqrDist = fC; } else { v = -fB1/fA11; SqrDist = fB1*v+fC; } } } else if(v < 0.0f) // region 6 { fTmp0 = fA01 + fB1; fTmp1 = fA00 + fB0; if(fTmp1 > fTmp0) { fNumer = fTmp1 - fTmp0; fDenom = fA00-2.0f*fA01+fA11; if(fNumer >= fDenom) { // v = 1.0f; // u = 0.0f; SqrDist = fA11+2.0f*fB1+fC; } else { v = fNumer/fDenom; u = 1.0f - v; SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC; } } else { // v = 0.0f; if(fTmp1 <= 0.0f) { /*u = 1.0f;*/ SqrDist = fA00+2.0f*fB0+fC; } else if(fB0 >= 0.0f) { /*u = 0.0f;*/ SqrDist = fC; } else { u = -fB0/fA00; SqrDist = fB0*u+fC; } } } else // region 1 { fNumer = fA11 + fB1 - fA01 - fB0; if(fNumer <= 0.0f) { // u = 0.0f; // v = 1.0f; SqrDist = fA11+2.0f*fB1+fC; } else { fDenom = fA00-2.0f*fA01+fA11; if(fNumer >= fDenom) { // u = 1.0f; // v = 0.0f; SqrDist = fA00+2.0f*fB0+fC; } else { u = fNumer/fDenom; v = 1.0f - u; SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC; } } } } return fabsf(SqrDist) < mRadius2; } ode-0.16/OPCODE/Ice/0000775000175200017520000000000013403273061010666 500000000000000ode-0.16/OPCODE/Ice/IcePairs.h0000664000175200017520000000337313403272463012471 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains a simple pair class. * \file IcePairs.h * \author Pierre Terdiman * \date January, 13, 2003 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Include Guard #ifndef __ICEPAIRS_H__ #define __ICEPAIRS_H__ //! A generic couple structure struct ICECORE_API Pair { inline_ Pair() {} inline_ Pair(udword i0, udword i1) : id0(i0), id1(i1) {} udword id0; //!< First index of the pair udword id1; //!< Second index of the pair }; class ICECORE_API Pairs : private Container { public: // Constructor / Destructor Pairs() {} ~Pairs() {} inline_ udword GetNbPairs() const { return GetNbEntries()>>1; } inline_ const Pair* GetPairs() const { return (const Pair*)GetEntries(); } inline_ const Pair* GetPair(udword i) const { return (const Pair*)&GetEntries()[i+i]; } inline_ BOOL HasPairs() const { return IsNotEmpty(); } inline_ void ResetPairs() { Reset(); } inline_ void DeleteLastPair() { DeleteLastEntry(); DeleteLastEntry(); } inline_ void AddPair(const Pair& p) { Add(p.id0).Add(p.id1); } inline_ void AddPair(udword id0, udword id1) { Add(id0).Add(id1); } }; #endif // __ICEPAIRS_H__ ode-0.16/OPCODE/Ice/IceUtils.h0000664000175200017520000002550413403272463012513 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains misc. useful macros & defines. * \file IceUtils.h * \author Pierre Terdiman (collected from various sources) * \date April, 4, 2000 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Include Guard #ifndef __ICEUTILS_H__ #define __ICEUTILS_H__ // #define START_RUNONCE { static bool __RunOnce__ = false; if(!__RunOnce__){ -- not thread safe // #define END_RUNONCE __RunOnce__ = true;}} -- not thread safe //! Reverse all the bits in a 32 bit word (from Steve Baker's Cute Code Collection) //! (each line can be done in any order. inline_ void ReverseBits(udword& n) { n = ((n >> 1) & 0x55555555) | ((n << 1) & 0xaaaaaaaa); n = ((n >> 2) & 0x33333333) | ((n << 2) & 0xcccccccc); n = ((n >> 4) & 0x0f0f0f0f) | ((n << 4) & 0xf0f0f0f0); n = ((n >> 8) & 0x00ff00ff) | ((n << 8) & 0xff00ff00); n = ((n >> 16) & 0x0000ffff) | ((n << 16) & 0xffff0000); // Etc for larger intergers (64 bits in Java) // NOTE: the >> operation must be unsigned! (>>> in java) } //! Count the number of '1' bits in a 32 bit word (from Steve Baker's Cute Code Collection) inline_ udword CountBits(udword n) { // This relies of the fact that the count of n bits can NOT overflow // an n bit interger. EG: 1 bit count takes a 1 bit interger, 2 bit counts // 2 bit interger, 3 bit count requires only a 2 bit interger. // So we add all bit pairs, then each nible, then each byte etc... n = (n & 0x55555555) + ((n & 0xaaaaaaaa) >> 1); n = (n & 0x33333333) + ((n & 0xcccccccc) >> 2); n = (n & 0x0f0f0f0f) + ((n & 0xf0f0f0f0) >> 4); n = (n & 0x00ff00ff) + ((n & 0xff00ff00) >> 8); n = (n & 0x0000ffff) + ((n & 0xffff0000) >> 16); // Etc for larger intergers (64 bits in Java) // NOTE: the >> operation must be unsigned! (>>> in java) return n; } //! Even faster? inline_ udword CountBits2(udword bits) { bits = bits - ((bits >> 1) & 0x55555555); bits = ((bits >> 2) & 0x33333333) + (bits & 0x33333333); bits = ((bits >> 4) + bits) & 0x0F0F0F0F; return (bits * 0x01010101) >> 24; } //! Spread out bits. EG 00001111 -> 0101010101 //! 00001010 -> 0100010000 //! This is used to interleve to intergers to produce a `Morten Key' //! used in Space Filling Curves (See DrDobbs Journal, July 1999) //! Order is important. inline_ void SpreadBits(udword& n) { n = ( n & 0x0000ffff) | (( n & 0xffff0000) << 16); n = ( n & 0x000000ff) | (( n & 0x0000ff00) << 8); n = ( n & 0x000f000f) | (( n & 0x00f000f0) << 4); n = ( n & 0x03030303) | (( n & 0x0c0c0c0c) << 2); n = ( n & 0x11111111) | (( n & 0x22222222) << 1); } // Next Largest Power of 2 // Given a binary integer value x, the next largest power of 2 can be computed by a SWAR algorithm // that recursively "folds" the upper bits into the lower bits. This process yields a bit vector with // the same most significant 1 as x, but all 1's below it. Adding 1 to that value yields the next // largest power of 2. For a 32-bit value: inline_ udword nlpo2(udword x) { x |= (x >> 1); x |= (x >> 2); x |= (x >> 4); x |= (x >> 8); x |= (x >> 16); return x+1; } //! Test to see if a number is an exact power of two (from Steve Baker's Cute Code Collection) inline_ bool IsPowerOfTwo(udword n) { return ((n&(n-1))==0); } //! Zero the least significant '1' bit in a word. (from Steve Baker's Cute Code Collection) inline_ void ZeroLeastSetBit(udword& n) { n&=(n-1); } //! Set the least significant N bits in a word. (from Steve Baker's Cute Code Collection) inline_ void SetLeastNBits(udword& x, udword n) { x|=~(~0<> 31; return (x^y)-y; } //!< Alternative min function inline_ sdword min_(sdword a, sdword b) { sdword delta = b-a; return a + (delta&(delta>>31)); } // Determine if one of the bytes in a 4 byte word is zero inline_ BOOL HasNullByte(udword x) { return ((x + 0xfefefeff) & (~x) & 0x80808080); } // To find the smallest 1 bit in a word EG: ~~~~~~10---0 => 0----010---0 inline_ udword LowestOneBit(udword w) { return ((w) & (~(w)+1)); } // inline_ udword LowestOneBit_(udword w) { return ((w) & (-(w))); } // Most Significant 1 Bit // Given a binary integer value x, the most significant 1 bit (highest numbered element of a bit set) // can be computed using a SWAR algorithm that recursively "folds" the upper bits into the lower bits. // This process yields a bit vector with the same most significant 1 as x, but all 1's below it. // Bitwise AND of the original value with the complement of the "folded" value shifted down by one // yields the most significant bit. For a 32-bit value: inline_ udword msb32(udword x) { x |= (x >> 1); x |= (x >> 2); x |= (x >> 4); x |= (x >> 8); x |= (x >> 16); return (x & ~(x >> 1)); } /* "Just call it repeatedly with various input values and always with the same variable as "memory". The sharpness determines the degree of filtering, where 0 completely filters out the input, and 1 does no filtering at all. I seem to recall from college that this is called an IIR (Infinite Impulse Response) filter. As opposed to the more typical FIR (Finite Impulse Response). Also, I'd say that you can make more intelligent and interesting filters than this, for example filters that remove wrong responses from the mouse because it's being moved too fast. You'd want such a filter to be applied before this one, of course." (JCAB on Flipcode) */ inline_ float FeedbackFilter(float val, float& memory, float sharpness) { ASSERT(sharpness>=0.0f && sharpness<=1.0f && "Invalid sharpness value in feedback filter"); if(sharpness<0.0f) sharpness = 0.0f; else if(sharpness>1.0f) sharpness = 1.0f; return memory = val * sharpness + memory * (1.0f - sharpness); } //! If you can guarantee that your input domain (i.e. value of x) is slightly //! limited (abs(x) must be < ((1<<31u)-32767)), then you can use the //! following code to clamp the resulting value into [-32768,+32767] range: inline_ int ClampToInt16(int x) { // ASSERT(abs(x) < (int)((1<<31u)-32767)); int delta = 32767 - x; x += (delta>>31) & delta; delta = x + 32768; x -= (delta>>31) & delta; return x; } // Generic functions template inline_ void TSwap(Type& a, Type& b) { const Type c = a; a = b; b = c; } template inline_ Type TClamp(const Type& x, const Type& lo, const Type& hi) { return ((xhi) ? hi : x); } template inline_ void TSort(Type& a, Type& b) { if(a>b) TSwap(a, b); } template inline_ void TSort(Type& a, Type& b, Type& c) { if(a>b) TSwap(a, b); if(b>c) TSwap(b, c); if(a>b) TSwap(a, b); if(b>c) TSwap(b, c); } // Prevent nasty user-manipulations (strategy borrowed from Charles Bloom) // #define PREVENT_COPY(curclass) void operator = (const curclass& object) { ASSERT(!"Bad use of operator ="); } // ... actually this is better ! #define PREVENT_COPY(cur_class) private: cur_class(const cur_class& object); cur_class& operator=(const cur_class& object); //! TO BE DOCUMENTED #define OFFSET_OF(Class, Member) (size_t)&(((Class*)0)->Member) //! TO BE DOCUMENTED #ifndef ARRAYSIZE #define ARRAYSIZE(p) (sizeof(p)/sizeof((p)[0])) #endif // #ifndef ARRAYSIZE /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Returns the alignment of the input address. * \fn Alignment() * \param address [in] address to check * \return the best alignment (e.g. 1 for odd addresses, etc) */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// FUNCTION ICECORE_API udword Alignment(udword address); #define IS_ALIGNED_2(x) ((x&1)==0) #define IS_ALIGNED_4(x) ((x&3)==0) #define IS_ALIGNED_8(x) ((x&7)==0) inline_ void _prefetch(void const* ptr) { (void)*(char const volatile *)ptr; } // Compute implicit coords from an index: // The idea is to get back 2D coords from a 1D index. // For example: // // 0 1 2 ... nbu-1 // nbu nbu+1 i ... // // We have i, we're looking for the equivalent (u=2, v=1) location. // i = u + v*nbu // <=> i/nbu = u/nbu + v // Since 0 <= u < nbu, u/nbu = 0 (integer) // Hence: v = i/nbu // Then we simply put it back in the original equation to compute u = i - v*nbu inline_ void Compute2DCoords(udword& u, udword& v, udword i, udword nbu) { v = i / nbu; u = i - (v * nbu); } // In 3D: i = u + v*nbu + w*nbu*nbv // <=> i/(nbu*nbv) = u/(nbu*nbv) + v/nbv + w // u/(nbu*nbv) is null since u/nbu was null already. // v/nbv is null as well for the same reason. // Hence w = i/(nbu*nbv) // Then we're left with a 2D problem: i' = i - w*nbu*nbv = u + v*nbu inline_ void Compute3DCoords(udword& u, udword& v, udword& w, udword i, udword nbu, udword nbu_nbv) { w = i / (nbu_nbv); Compute2DCoords(u, v, i - (w * nbu_nbv), nbu); } #endif // __ICEUTILS_H__ ode-0.16/OPCODE/Ice/IceRay.cpp0000664000175200017520000000470013403272463012474 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains code for rays. * \file IceRay.cpp * \author Pierre Terdiman * \date April, 4, 2000 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Ray class. * A ray is a half-line P(t) = mOrig + mDir * t, with 0 <= t <= +infinity * \class Ray * \author Pierre Terdiman * \version 1.0 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* O = Origin = impact point i = normalized vector along the x axis j = normalized vector along the y axis = actually the normal vector in O D = Direction vector, norm |D| = 1 N = Projection of D on y axis, norm |N| = normal reaction T = Projection of D on x axis, norm |T| = tangential reaction R = Reflexion vector ^y | | | _ _ _| _ _ _ * * *| \ | / \ |N / | R\ | /D \ | / | \ | / _________\|/______*_______>x O T Let define theta = angle between D and N. Then cos(theta) = |N| / |D| = |N| since D is normalized. j|D = |j|*|D|*cos(theta) => |N| = j|D Then we simply have: D = N + T To compute tangential reaction : T = D - N To compute reflexion vector : R = N - T = N - (D-N) = 2*N - D */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Precompiled Header #include "Stdafx.h" using namespace IceMaths; float Ray::SquareDistance(const Point& point, float* t) const { Point Diff = point - mOrig; float fT = Diff | mDir; if(fT<=0.0f) { fT = 0.0f; } else { fT /= mDir.SquareMagnitude(); Diff -= fT*mDir; } if(t) *t = fT; return Diff.SquareMagnitude(); } ode-0.16/OPCODE/Ice/IceIndexedTriangle.h0000664000175200017520000000666613403272463014471 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains a handy indexed triangle class. * \file IceIndexedTriangle.h * \author Pierre Terdiman * \date January, 17, 2000 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #include "ode/common.h" /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Include Guard #ifndef __ICEINDEXEDTRIANGLE_H__ #define __ICEINDEXEDTRIANGLE_H__ // Forward declarations #ifdef _MSC_VER enum CubeIndex; #else typedef int CubeIndex; #endif // An indexed triangle class. class ICEMATHS_API IndexedTriangle { public: //! Constructor inline_ IndexedTriangle() {} //! Constructor inline_ IndexedTriangle(dTriIndex r0, dTriIndex r1, dTriIndex r2) { mVRef[0]=r0; mVRef[1]=r1; mVRef[2]=r2; } //! Copy constructor inline_ IndexedTriangle(const IndexedTriangle& triangle) { mVRef[0] = triangle.mVRef[0]; mVRef[1] = triangle.mVRef[1]; mVRef[2] = triangle.mVRef[2]; } //! Destructor inline_ ~IndexedTriangle() {} //! Vertex-references dTriIndex mVRef[3]; // Methods void Flip(); float Area(const Point* verts) const; float Perimeter(const Point* verts) const; float Compacity(const Point* verts) const; void Normal(const Point* verts, Point& normal) const; void DenormalizedNormal(const Point* verts, Point& normal) const; void Center(const Point* verts, Point& center) const; void CenteredNormal(const Point* verts, Point& normal) const; void RandomPoint(const Point* verts, Point& random) const; bool IsVisible(const Point* verts, const Point& source) const; bool BackfaceCulling(const Point* verts, const Point& source) const; float ComputeOcclusionPotential(const Point* verts, const Point& view) const; bool ReplaceVertex(dTriIndex oldref, dTriIndex newref); bool IsDegenerate() const; bool HasVertex(dTriIndex ref) const; bool HasVertex(dTriIndex ref, dTriIndex* index) const; ubyte FindEdge(dTriIndex vref0, dTriIndex vref1) const; dTriIndex OppositeVertex(dTriIndex vref0, dTriIndex vref1) const; inline_ dTriIndex OppositeVertex(ubyte edgenb) const { return mVRef[2-edgenb]; } void GetVRefs(ubyte edgenb, dTriIndex& vref0, dTriIndex& vref1, dTriIndex& vref2) const; float MinEdgeLength(const Point* verts) const; float MaxEdgeLength(const Point* verts) const; void ComputePoint(const Point* verts, float u, float v, Point& pt, dTriIndex* nearvtx=null) const; float Angle(const IndexedTriangle& tri, const Point* verts) const; inline_ Plane PlaneEquation(const Point* verts) const { return Plane(verts[mVRef[0]], verts[mVRef[1]], verts[mVRef[2]]); } bool Equal(const IndexedTriangle& tri) const; CubeIndex ComputeCubeIndex(const Point* verts) const; }; #endif // __ICEINDEXEDTRIANGLE_H__ ode-0.16/OPCODE/Ice/IceRevisitedRadix.h0000664000175200017520000000503213403272463014333 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains source code from the article "Radix Sort Revisited". * \file IceRevisitedRadix.h * \author Pierre Terdiman * \date April, 4, 2000 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Include Guard #ifndef __ICERADIXSORT_H__ #define __ICERADIXSORT_H__ //! Allocate histograms & offsets locally #define RADIX_LOCAL_RAM enum RadixHint { RADIX_SIGNED, //!< Input values are signed RADIX_UNSIGNED, //!< Input values are unsigned RADIX_FORCE_DWORD = 0x7fffffff }; class ICECORE_API RadixSort { public: // Constructor/Destructor RadixSort(); ~RadixSort(); // Sorting methods RadixSort& Sort(const udword* input, udword nb, RadixHint hint=RADIX_SIGNED); RadixSort& Sort(const float* input, udword nb); //! Access to results. mRanks is a list of indices in sorted order, i.e. in the order you may further process your data inline_ const udword* GetRanks() const { return mRanks; } //! mIndices2 gets trashed on calling the sort routine, but otherwise you can recycle it the way you want. inline_ udword* GetRecyclable() const { return mRanks2; } // Stats udword GetUsedRam() const; //! Returns the total number of calls to the radix sorter. inline_ udword GetNbTotalCalls() const { return mTotalCalls; } //! Returns the number of eraly exits due to temporal coherence. inline_ udword GetNbHits() const { return mNbHits; } private: #ifndef RADIX_LOCAL_RAM udword* mHistogram; //!< Counters for each byte udword* mOffset; //!< Offsets (nearly a cumulative distribution function) #endif udword mCurrentSize; //!< Current size of the indices list udword* mRanks; //!< Two lists, swapped each pass udword* mRanks2; // Stats udword mTotalCalls; //!< Total number of calls to the sort routine udword mNbHits; //!< Number of early exits due to coherence // Internal methods void CheckResize(udword nb); bool Resize(udword nb); }; #endif // __ICERADIXSORT_H__ ode-0.16/OPCODE/Ice/IceRandom.h0000664000175200017520000000305113403272463012624 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains code for random generators. * \file IceRandom.h * \author Pierre Terdiman * \date August, 9, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Include Guard #ifndef __ICERANDOM_H__ #define __ICERANDOM_H__ FUNCTION ICECORE_API void SRand(udword seed); FUNCTION ICECORE_API udword Rand(); //! Returns a unit random floating-point value inline_ float UnitRandomFloat() { return float(Rand()) * ONE_OVER_RAND_MAX; } //! Returns a random index so that 0<= index < max_index ICECORE_API udword GetRandomIndex(udword max_index); class ICECORE_API BasicRandom { public: //! Constructor inline_ BasicRandom(udword seed=0) : mRnd(seed) {} //! Destructor inline_ ~BasicRandom() {} inline_ void SetSeed(udword seed) { mRnd = seed; } inline_ udword GetCurrentValue() const { return mRnd; } inline_ udword Randomize() { mRnd = mRnd * 2147001325 + 715136305; return mRnd; } private: udword mRnd; }; #endif // __ICERANDOM_H__ ode-0.16/OPCODE/Ice/IceTriList.h0000664000175200017520000000427313403272463013005 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains code for a triangle container. * \file IceTrilist.h * \author Pierre Terdiman * \date April, 4, 2000 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Include Guard #ifndef __ICETRILIST_H__ #define __ICETRILIST_H__ class ICEMATHS_API TriList : public Container { public: // Constructor / Destructor TriList() {} ~TriList() {} inline_ udword GetNbTriangles() const { return GetNbEntries()/9; } inline_ Triangle* GetTriangles() const { return (Triangle*)GetEntries(); } void AddTri(const Triangle& tri) { Add(tri.mVerts[0].x).Add(tri.mVerts[0].y).Add(tri.mVerts[0].z); Add(tri.mVerts[1].x).Add(tri.mVerts[1].y).Add(tri.mVerts[1].z); Add(tri.mVerts[2].x).Add(tri.mVerts[2].y).Add(tri.mVerts[2].z); } void AddTri(const Point& p0, const Point& p1, const Point& p2) { Add(p0.x).Add(p0.y).Add(p0.z); Add(p1.x).Add(p1.y).Add(p1.z); Add(p2.x).Add(p2.y).Add(p2.z); } }; class ICEMATHS_API TriangleList : public Container { public: // Constructor / Destructor TriangleList() {} ~TriangleList() {} inline_ udword GetNbTriangles() const { return GetNbEntries()/3; } inline_ IndexedTriangle* GetTriangles() const { return (IndexedTriangle*)GetEntries();} void AddTriangle(const IndexedTriangle& tri) { Add((udword)tri.mVRef[0]).Add((udword)tri.mVRef[1]).Add((udword)tri.mVRef[2]); } void AddTriangle(udword vref0, udword vref1, udword vref2) { Add(vref0).Add(vref1).Add(vref2); } }; #endif //__ICETRILIST_H__ ode-0.16/OPCODE/Ice/IceLSS.h0000664000175200017520000000756113403272463012057 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains code for line-swept spheres. * \file IceLSS.h * \author Pierre Terdiman * \date April, 4, 2000 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Include Guard #ifndef __ICELSS_H__ #define __ICELSS_H__ class ICEMATHS_API LSS : public Segment { public: //! Constructor inline_ LSS() {} //! Constructor inline_ LSS(const Segment& seg, float radius) : Segment(seg), mRadius(radius) {} //! Destructor inline_ ~LSS() {} /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes an OBB surrounding the LSS. * \param box [out] the OBB */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ComputeOBB(OBB& box); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Tests if a point is contained within the LSS. * \param pt [in] the point to test * \return true if inside the LSS * \warning point and LSS must be in same space */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ bool Contains(const Point& pt) const { return SquareDistance(pt) <= mRadius*mRadius; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Tests if a sphere is contained within the LSS. * \param sphere [in] the sphere to test * \return true if inside the LSS * \warning sphere and LSS must be in same space */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ bool Contains(const Sphere& sphere) { float d = mRadius - sphere.mRadius; if(d>=0.0f) return SquareDistance(sphere.mCenter) <= d*d; else return false; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Tests if an LSS is contained within the LSS. * \param lss [in] the LSS to test * \return true if inside the LSS * \warning both LSS must be in same space */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ bool Contains(const LSS& lss) { // We check the LSS contains the two spheres at the start and end of the sweep return Contains(Sphere(lss.mP0, lss.mRadius)) && Contains(Sphere(lss.mP0, lss.mRadius)); } float mRadius; //!< Sphere radius }; #endif // __ICELSS_H__ ode-0.16/OPCODE/Ice/IceIndexedTriangle.cpp0000664000175200017520000005730213403272463015015 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains a handy indexed triangle class. * \file IceIndexedTriangle.cpp * \author Pierre Terdiman * \date January, 17, 2000 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Precompiled Header #include "Stdafx.h" using namespace IceMaths; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains an indexed triangle class. * * \class Triangle * \author Pierre Terdiman * \version 1.0 * \date 08.15.98 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Flips the winding order. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void IndexedTriangle::Flip() { Swap(mVRef[1], mVRef[2]); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the triangle area. * \param verts [in] the list of indexed vertices * \return the area */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// float IndexedTriangle::Area(const Point* verts) const { if(!verts) return 0.0f; const Point& p0 = verts[0]; const Point& p1 = verts[1]; const Point& p2 = verts[2]; return ((p0-p1)^(p0-p2)).Magnitude() * 0.5f; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the triangle perimeter. * \param verts [in] the list of indexed vertices * \return the perimeter */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// float IndexedTriangle::Perimeter(const Point* verts) const { if(!verts) return 0.0f; const Point& p0 = verts[0]; const Point& p1 = verts[1]; const Point& p2 = verts[2]; return p0.Distance(p1) + p0.Distance(p2) + p1.Distance(p2); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the triangle compacity. * \param verts [in] the list of indexed vertices * \return the compacity */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// float IndexedTriangle::Compacity(const Point* verts) const { if(!verts) return 0.0f; float P = Perimeter(verts); if(P==0.0f) return 0.0f; return (4.0f*PI*Area(verts)/(P*P)); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the triangle normal. * \param verts [in] the list of indexed vertices * \param normal [out] the computed normal */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void IndexedTriangle::Normal(const Point* verts, Point& normal) const { if(!verts) return; const Point& p0 = verts[mVRef[0]]; const Point& p1 = verts[mVRef[1]]; const Point& p2 = verts[mVRef[2]]; normal = ((p2-p1)^(p0-p1)).Normalize(); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the triangle denormalized normal. * \param verts [in] the list of indexed vertices * \param normal [out] the computed normal */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void IndexedTriangle::DenormalizedNormal(const Point* verts, Point& normal) const { if(!verts) return; const Point& p0 = verts[mVRef[0]]; const Point& p1 = verts[mVRef[1]]; const Point& p2 = verts[mVRef[2]]; normal = ((p2-p1)^(p0-p1)); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the triangle center. * \param verts [in] the list of indexed vertices * \param center [out] the computed center */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void IndexedTriangle::Center(const Point* verts, Point& center) const { if(!verts) return; const Point& p0 = verts[mVRef[0]]; const Point& p1 = verts[mVRef[1]]; const Point& p2 = verts[mVRef[2]]; center = (p0+p1+p2)*INV3; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the centered normal * \param verts [in] the list of indexed vertices * \param normal [out] the computed centered normal */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void IndexedTriangle::CenteredNormal(const Point* verts, Point& normal) const { if(!verts) return; const Point& p0 = verts[mVRef[0]]; const Point& p1 = verts[mVRef[1]]; const Point& p2 = verts[mVRef[2]]; Point Center = (p0+p1+p2)*INV3; normal = Center + ((p2-p1)^(p0-p1)).Normalize(); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes a random point within the triangle. * \param verts [in] the list of indexed vertices * \param normal [out] the computed centered normal */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void IndexedTriangle::RandomPoint(const Point* verts, Point& random) const { if(!verts) return; // Random barycentric coords float Alpha = UnitRandomFloat(); float Beta = UnitRandomFloat(); float Gamma = UnitRandomFloat(); float OneOverTotal = 1.0f / (Alpha + Beta + Gamma); Alpha *= OneOverTotal; Beta *= OneOverTotal; Gamma *= OneOverTotal; const Point& p0 = verts[mVRef[0]]; const Point& p1 = verts[mVRef[1]]; const Point& p2 = verts[mVRef[2]]; random = Alpha*p0 + Beta*p1 + Gamma*p2; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes backface culling. * \param verts [in] the list of indexed vertices * \param source [in] source point (in local space) from which culling must be computed * \return true if the triangle is visible from the source point */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool IndexedTriangle::IsVisible(const Point* verts, const Point& source) const { // Checkings if(!verts) return false; const Point& p0 = verts[mVRef[0]]; const Point& p1 = verts[mVRef[1]]; const Point& p2 = verts[mVRef[2]]; // Compute denormalized normal Point Normal = (p2 - p1)^(p0 - p1); // Backface culling return (Normal | source) >= 0.0f; // Same as: // Plane PL(verts[mVRef[0]], verts[mVRef[1]], verts[mVRef[2]]); // return PL.Distance(source) > PL.d; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes backface culling. * \param verts [in] the list of indexed vertices * \param source [in] source point (in local space) from which culling must be computed * \return true if the triangle is visible from the source point */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool IndexedTriangle::BackfaceCulling(const Point* verts, const Point& source) const { // Checkings if(!verts) return false; const Point& p0 = verts[mVRef[0]]; const Point& p1 = verts[mVRef[1]]; const Point& p2 = verts[mVRef[2]]; // Compute base // Point Base = (p0 + p1 + p2)*INV3; // Compute denormalized normal Point Normal = (p2 - p1)^(p0 - p1); // Backface culling // return (Normal | (source - Base)) >= 0.0f; return (Normal | (source - p0)) >= 0.0f; // Same as: (but a bit faster) // Plane PL(verts[mVRef[0]], verts[mVRef[1]], verts[mVRef[2]]); // return PL.Distance(source)>0.0f; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the occlusion potential of the triangle. * \param verts [in] the list of indexed vertices * \param source [in] source point (in local space) from which occlusion potential must be computed * \return the occlusion potential */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// float IndexedTriangle::ComputeOcclusionPotential(const Point* verts, const Point& view) const { if(!verts) return 0.0f; // Occlusion potential: -(A * (N|V) / d^2) // A = polygon area // N = polygon normal // V = view vector // d = distance viewpoint-center of polygon float A = Area(verts); Point N; Normal(verts, N); Point C; Center(verts, C); float d = view.Distance(C); return -(A*(N|view))/(d*d); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Replaces a vertex reference with another one. * \param oldref [in] the vertex reference to replace * \param newref [in] the new vertex reference * \return true if success, else false if the input vertex reference doesn't belong to the triangle */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool IndexedTriangle::ReplaceVertex(dTriIndex oldref, dTriIndex newref) { if(mVRef[0]==oldref) { mVRef[0] = newref; return true; } else if(mVRef[1]==oldref) { mVRef[1] = newref; return true; } else if(mVRef[2]==oldref) { mVRef[2] = newref; return true; } return false; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Checks whether the triangle is degenerate or not. A degenerate triangle has two common vertex references. This is a zero-area triangle. * \return true if the triangle is degenerate */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool IndexedTriangle::IsDegenerate() const { if(mVRef[0]==mVRef[1]) return true; if(mVRef[1]==mVRef[2]) return true; if(mVRef[2]==mVRef[0]) return true; return false; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Checks whether the input vertex reference belongs to the triangle or not. * \param ref [in] the vertex reference to look for * \return true if the triangle contains the vertex reference */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool IndexedTriangle::HasVertex(dTriIndex ref) const { if(mVRef[0]==ref) return true; if(mVRef[1]==ref) return true; if(mVRef[2]==ref) return true; return false; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Checks whether the input vertex reference belongs to the triangle or not. * \param ref [in] the vertex reference to look for * \param index [out] the corresponding index in the triangle * \return true if the triangle contains the vertex reference */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool IndexedTriangle::HasVertex(dTriIndex ref, dTriIndex* index) const { if(mVRef[0]==ref) { *index = 0; return true; } if(mVRef[1]==ref) { *index = 1; return true; } if(mVRef[2]==ref) { *index = 2; return true; } return false; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Finds an edge in a tri, given two vertex references. * \param vref0 [in] the edge's first vertex reference * \param vref1 [in] the edge's second vertex reference * \return the edge number between 0 and 2, or 0xff if input refs are wrong. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ubyte IndexedTriangle::FindEdge(dTriIndex vref0, dTriIndex vref1) const { if(mVRef[0]==vref0 && mVRef[1]==vref1) return 0; else if(mVRef[0]==vref1 && mVRef[1]==vref0) return 0; else if(mVRef[0]==vref0 && mVRef[2]==vref1) return 1; else if(mVRef[0]==vref1 && mVRef[2]==vref0) return 1; else if(mVRef[1]==vref0 && mVRef[2]==vref1) return 2; else if(mVRef[1]==vref1 && mVRef[2]==vref0) return 2; return 0xff; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Gets the last reference given the first two. * \param vref0 [in] the first vertex reference * \param vref1 [in] the second vertex reference * \return the last reference, or INVALID_ID if input refs are wrong. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// dTriIndex IndexedTriangle::OppositeVertex(dTriIndex vref0, dTriIndex vref1) const { if(mVRef[0]==vref0 && mVRef[1]==vref1) return mVRef[2]; else if(mVRef[0]==vref1 && mVRef[1]==vref0) return mVRef[2]; else if(mVRef[0]==vref0 && mVRef[2]==vref1) return mVRef[1]; else if(mVRef[0]==vref1 && mVRef[2]==vref0) return mVRef[1]; else if(mVRef[1]==vref0 && mVRef[2]==vref1) return mVRef[0]; else if(mVRef[1]==vref1 && mVRef[2]==vref0) return mVRef[0]; return (dTriIndex)INVALID_ID; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Gets the three sorted vertex references according to an edge number. * edgenb = 0 => edge 0-1, returns references 0, 1, 2 * edgenb = 1 => edge 0-2, returns references 0, 2, 1 * edgenb = 2 => edge 1-2, returns references 1, 2, 0 * * \param edgenb [in] the edge number, 0, 1 or 2 * \param vref0 [out] the returned first vertex reference * \param vref1 [out] the returned second vertex reference * \param vref2 [out] the returned third vertex reference */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void IndexedTriangle::GetVRefs(ubyte edgenb, dTriIndex& vref0, dTriIndex& vref1, dTriIndex& vref2) const { if(edgenb==0) { vref0 = mVRef[0]; vref1 = mVRef[1]; vref2 = mVRef[2]; } else if(edgenb==1) { vref0 = mVRef[0]; vref1 = mVRef[2]; vref2 = mVRef[1]; } else if(edgenb==2) { vref0 = mVRef[1]; vref1 = mVRef[2]; vref2 = mVRef[0]; } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the triangle's smallest edge length. * \param verts [in] the list of indexed vertices * \return the smallest edge length */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// float IndexedTriangle::MinEdgeLength(const Point* verts) const { if(!verts) return 0.0f; float Min = MAX_FLOAT; float Length01 = verts[0].Distance(verts[1]); float Length02 = verts[0].Distance(verts[2]); float Length12 = verts[1].Distance(verts[2]); if(Length01 < Min) Min = Length01; if(Length02 < Min) Min = Length02; if(Length12 < Min) Min = Length12; return Min; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the triangle's largest edge length. * \param verts [in] the list of indexed vertices * \return the largest edge length */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// float IndexedTriangle::MaxEdgeLength(const Point* verts) const { if(!verts) return 0.0f; float Max = MIN_FLOAT; float Length01 = verts[0].Distance(verts[1]); float Length02 = verts[0].Distance(verts[2]); float Length12 = verts[1].Distance(verts[2]); if(Length01 > Max) Max = Length01; if(Length02 > Max) Max = Length02; if(Length12 > Max) Max = Length12; return Max; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes a point on the triangle according to the stabbing information. * \param verts [in] the list of indexed vertices * \param u,v [in] point's barycentric coordinates * \param pt [out] point on triangle * \param nearvtx [out] index of nearest vertex */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void IndexedTriangle::ComputePoint(const Point* verts, float u, float v, Point& pt, dTriIndex* nearvtx) const { // Checkings if(!verts) return; // Get face in local or global space const Point& p0 = verts[mVRef[0]]; const Point& p1 = verts[mVRef[1]]; const Point& p2 = verts[mVRef[2]]; // Compute point coordinates pt = (1.0f - u - v)*p0 + u*p1 + v*p2; // Compute nearest vertex if needed if(nearvtx) { // Compute distance vector Point d(p0.SquareDistance(pt), // Distance^2 from vertex 0 to point on the face p1.SquareDistance(pt), // Distance^2 from vertex 1 to point on the face p2.SquareDistance(pt)); // Distance^2 from vertex 2 to point on the face // Get smallest distance *nearvtx = mVRef[d.SmallestAxis()]; } } //************************************** // Angle between two vectors (in radians) // we use this formula // uv = |u||v| cos(u,v) // u ^ v = w // |w| = |u||v| |sin(u,v)| //************************************** float Angle(const Point& u, const Point& v) { float NormU = u.Magnitude(); // |u| float NormV = v.Magnitude(); // |v| float Product = NormU*NormV; // |u||v| if(Product==0.0f) return 0.0f; float OneOverProduct = 1.0f / Product; // Cosinus float Cosinus = (u|v) * OneOverProduct; // Sinus Point w = u^v; float NormW = w.Magnitude(); float AbsSinus = NormW * OneOverProduct; // Remove degeneracy if(AbsSinus > 1.0f) AbsSinus = 1.0f; if(AbsSinus < -1.0f) AbsSinus = -1.0f; if(Cosinus>=0.0f) return asinf(AbsSinus); else return (PI-asinf(AbsSinus)); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the angle between two triangles. * \param tri [in] the other triangle * \param verts [in] the list of indexed vertices * \return the angle in radians */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// float IndexedTriangle::Angle(const IndexedTriangle& tri, const Point* verts) const { // Checkings if(!verts) return 0.0f; // Compute face normals Point n0, n1; Normal(verts, n0); tri.Normal(verts, n1); // Compute angle float dp = n0|n1; if(dp>1.0f) return 0.0f; if(dp<-1.0f) return PI; return acosf(dp); // return ::Angle(n0,n1); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Checks a triangle is the same as another one. * \param tri [in] the other triangle * \return true if same triangle */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool IndexedTriangle::Equal(const IndexedTriangle& tri) const { // Test all vertex references return (HasVertex(tri.mVRef[0]) && HasVertex(tri.mVRef[1]) && HasVertex(tri.mVRef[2])); } ode-0.16/OPCODE/Ice/Makefile.am0000664000175200017520000000205513403272463012651 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/OPCODE \ -I$(top_srcdir)/include \ -I$(top_builddir)/include noinst_LTLIBRARIES = libIce.la libIce_la_SOURCES = \ IceAABB.cpp IceAABB.h IceAxes.h \ IceBoundingSphere.h IceContainer.cpp IceContainer.h \ IceFPU.h IceHPoint.cpp IceHPoint.h \ IceIndexedTriangle.cpp IceIndexedTriangle.h IceLSS.h \ IceMatrix3x3.cpp IceMatrix3x3.h IceMatrix4x4.cpp \ IceMatrix4x4.h IceMemoryMacros.h IceOBB.cpp \ IceOBB.h IcePairs.h IcePlane.cpp \ IcePlane.h IcePoint.cpp IcePoint.h \ IcePreprocessor.h IceRandom.cpp IceRandom.h \ IceRay.cpp IceRay.h IceRevisitedRadix.cpp \ IceRevisitedRadix.h IceSegment.cpp IceSegment.h \ IceTriangle.cpp IceTriangle.h IceTriList.h \ IceTypes.h IceUtils.cpp IceUtils.h ode-0.16/OPCODE/Ice/IceSegment.cpp0000664000175200017520000000361013403272463013342 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains code for segments. * \file IceSegment.cpp * \author Pierre Terdiman * \date April, 4, 2000 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Segment class. * A segment is defined by S(t) = mP0 * (1 - t) + mP1 * t, with 0 <= t <= 1 * Alternatively, a segment is S(t) = Origin + t * Direction for 0 <= t <= 1. * Direction is not necessarily unit length. The end points are Origin = mP0 and Origin + Direction = mP1. * * \class Segment * \author Pierre Terdiman * \version 1.0 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Precompiled Header #include "Stdafx.h" using namespace IceMaths; float Segment::SquareDistance(const Point& point, float* t) const { Point Diff = point - mP0; Point Dir = mP1 - mP0; float fT = Diff | Dir; if(fT<=0.0f) { fT = 0.0f; } else { float SqrLen= Dir.SquareMagnitude(); if(fT>=SqrLen) { fT = 1.0f; Diff -= Dir; } else { fT /= SqrLen; Diff -= fT*Dir; } } if(t) *t = fT; return Diff.SquareMagnitude(); } ode-0.16/OPCODE/Ice/IcePreprocessor.h0000664000175200017520000000712413403272463014077 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains preprocessor stuff. This should be the first included header. * \file IcePreprocessor.h * \author Pierre Terdiman * \date April, 4, 2000 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Include Guard #ifndef __ICEPREPROCESSOR_H__ #define __ICEPREPROCESSOR_H__ // Check platform #if defined( _WIN32 ) || defined( WIN32 ) // #pragma message("Compiling on Windows...") #define PLATFORM_WINDOWS #else // don't issue pragmas on unknown platforms // #pragma message("Compiling on unknown platform...") #endif // Check compiler #if defined(_MSC_VER) // #pragma message("Compiling with VC++...") #define COMPILER_VISUAL_CPP #else // don't issue pragmas on unknown platforms // #pragma message("Compiling with unknown compiler...") #endif // Check compiler options. If this file is included in user-apps, this // shouldn't be needed, so that they can use what they like best. #ifndef ICE_DONT_CHECK_COMPILER_OPTIONS #ifdef COMPILER_VISUAL_CPP #if defined(_CHAR_UNSIGNED) #endif #if defined(_CPPRTTI) #error Please disable RTTI... #endif #if defined(_CPPUNWIND) #error Please disable exceptions... #endif #if defined(_MT) // Multithreading #endif #endif #endif // Check debug mode #ifdef DEBUG // May be defined instead of _DEBUG. Let's fix it. #ifndef _DEBUG #define _DEBUG #endif #endif #ifdef _DEBUG // Here you may define items for debug builds #endif #ifndef THIS_FILE #define THIS_FILE __FILE__ #endif #ifndef ICE_NO_DLL #ifdef ICECORE_EXPORTS #define ICECORE_API __declspec(dllexport) #else #define ICECORE_API __declspec(dllimport) #endif #else #define ICECORE_API #endif // Don't override new/delete // #define DEFAULT_NEWDELETE #define DONT_TRACK_MEMORY_LEAKS #define FUNCTION extern "C" // Cosmetic stuff [mainly useful with multiple inheritance] #define override(base_class) virtual // Our own inline keyword, so that: // - we can switch to __forceinline to check it's really better or not // - we can remove __forceinline if the compiler doesn't support it // #define inline_ __forceinline // #define inline_ inline // Contributed by Bruce Mitchener #if defined(COMPILER_VISUAL_CPP) #define inline_ __forceinline // #define inline_ inline #elif defined(__GNUC__) && __GNUC__ < 3 #define inline_ inline #elif defined(__GNUC__) #define inline_ inline __attribute__ ((always_inline)) #else #define inline_ inline #endif // Down the hatch #ifdef _MSC_VER #pragma inline_depth( 255 ) #endif #ifdef COMPILER_VISUAL_CPP #pragma intrinsic(memcmp) #pragma intrinsic(memcpy) #pragma intrinsic(memset) #pragma intrinsic(strcat) #pragma intrinsic(strcmp) #pragma intrinsic(strcpy) #pragma intrinsic(strlen) #pragma intrinsic(abs) #pragma intrinsic(labs) #endif // ANSI compliance #ifdef _DEBUG // Remove painful warning in debug inline_ bool __False__(){ return false; } #define for if(__False__()){} else for #else #define for if(0){} else for #endif #endif // __ICEPREPROCESSOR_H__ ode-0.16/OPCODE/Ice/IceHPoint.cpp0000664000175200017520000000755413403272463013154 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains code for homogeneous points. * \file IceHPoint.cpp * \author Pierre Terdiman * \date April, 4, 2000 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Homogeneous point. * * Use it: * - for clipping in homogeneous space (standard way) * - to differentiate between points (w=1) and vectors (w=0). * - in some cases you can also use it instead of Point for padding reasons. * * \class HPoint * \author Pierre Terdiman * \version 1.0 * \warning No cross-product in 4D. * \warning HPoint *= Matrix3x3 doesn't exist, the matrix is first casted to a 4x4 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Precompiled Header #include "Stdafx.h" using namespace IceMaths; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Point Mul = HPoint * Matrix3x3; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Point HPoint::operator*(const Matrix3x3& mat) const { return Point( x * mat.m[0][0] + y * mat.m[1][0] + z * mat.m[2][0], x * mat.m[0][1] + y * mat.m[1][1] + z * mat.m[2][1], x * mat.m[0][2] + y * mat.m[1][2] + z * mat.m[2][2] ); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // HPoint Mul = HPoint * Matrix4x4; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// HPoint HPoint::operator*(const Matrix4x4& mat) const { return HPoint( x * mat.m[0][0] + y * mat.m[1][0] + z * mat.m[2][0] + w * mat.m[3][0], x * mat.m[0][1] + y * mat.m[1][1] + z * mat.m[2][1] + w * mat.m[3][1], x * mat.m[0][2] + y * mat.m[1][2] + z * mat.m[2][2] + w * mat.m[3][2], x * mat.m[0][3] + y * mat.m[1][3] + z * mat.m[2][3] + w * mat.m[3][3]); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // HPoint *= Matrix4x4 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// HPoint& HPoint::operator*=(const Matrix4x4& mat) { float xp = x * mat.m[0][0] + y * mat.m[1][0] + z * mat.m[2][0] + w * mat.m[3][0]; float yp = x * mat.m[0][1] + y * mat.m[1][1] + z * mat.m[2][1] + w * mat.m[3][1]; float zp = x * mat.m[0][2] + y * mat.m[1][2] + z * mat.m[2][2] + w * mat.m[3][2]; float wp = x * mat.m[0][3] + y * mat.m[1][3] + z * mat.m[2][3] + w * mat.m[3][3]; x = xp; y = yp; z = zp; w = wp; return *this; } ode-0.16/OPCODE/Ice/IceSegment.h0000664000175200017520000000510213403272463013005 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains code for segments. * \file IceSegment.h * \author Pierre Terdiman * \date April, 4, 2000 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Include Guard #ifndef __ICESEGMENT_H__ #define __ICESEGMENT_H__ class ICEMATHS_API Segment { public: //! Constructor inline_ Segment() {} //! Constructor inline_ Segment(const Point& p0, const Point& p1) : mP0(p0), mP1(p1) {} //! Copy constructor inline_ Segment(const Segment& seg) : mP0(seg.mP0), mP1(seg.mP1) {} //! Destructor inline_ ~Segment() {} inline_ const Point& GetOrigin() const { return mP0; } inline_ Point ComputeDirection() const { return mP1 - mP0; } inline_ void ComputeDirection(Point& dir) const { dir = mP1 - mP0; } inline_ float ComputeLength() const { return mP1.Distance(mP0); } inline_ float ComputeSquareLength() const { return mP1.SquareDistance(mP0); } inline_ void SetOriginDirection(const Point& origin, const Point& direction) { mP0 = mP1 = origin; mP1 += direction; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes a point on the segment * \param pt [out] point on segment * \param t [in] point's parameter [t=0 => pt = mP0, t=1 => pt = mP1] */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ void ComputePoint(Point& pt, float t) const { pt = mP0 + t * (mP1 - mP0); } float SquareDistance(const Point& point, float* t=null) const; inline_ float Distance(const Point& point, float* t=null) const { return sqrtf(SquareDistance(point, t)); } Point mP0; //!< Start of segment Point mP1; //!< End of segment }; #endif // __ICESEGMENT_H__ ode-0.16/OPCODE/Ice/IceRay.h0000664000175200017520000001112013403272463012133 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains code for rays. * \file IceRay.h * \author Pierre Terdiman * \date April, 4, 2000 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Include Guard #ifndef __ICERAY_H__ #define __ICERAY_H__ class ICEMATHS_API Ray { public: //! Constructor inline_ Ray() {} //! Constructor inline_ Ray(const Point& orig, const Point& dir) : mOrig(orig), mDir(dir) {} //! Copy constructor inline_ Ray(const Ray& ray) : mOrig(ray.mOrig), mDir(ray.mDir) {} //! Destructor inline_ ~Ray() {} float SquareDistance(const Point& point, float* t=null) const; inline_ float Distance(const Point& point, float* t=null) const { return sqrtf(SquareDistance(point, t)); } Point mOrig; //!< Ray origin Point mDir; //!< Normalized direction }; inline_ void ComputeReflexionVector(Point& reflected, const Point& incoming_dir, const Point& outward_normal) { reflected = incoming_dir - outward_normal * 2.0f * (incoming_dir|outward_normal); } inline_ void ComputeReflexionVector(Point& reflected, const Point& source, const Point& impact, const Point& normal) { Point V = impact - source; reflected = V - normal * 2.0f * (V|normal); } inline_ void DecomposeVector(Point& normal_compo, Point& tangent_compo, const Point& outward_dir, const Point& outward_normal) { normal_compo = outward_normal * (outward_dir|outward_normal); tangent_compo = outward_dir - normal_compo; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Transforms a direction vector from world space to local space * \param local_dir [out] direction vector in local space * \param world_dir [in] direction vector in world space * \param world [in] world transform */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ void ComputeLocalDirection(Point& local_dir, const Point& world_dir, const Matrix4x4& world) { // Get world direction back in local space // Matrix3x3 InvWorld = world; // local_dir = InvWorld * world_dir; local_dir = Matrix3x3(world) * world_dir; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Transforms a position vector from world space to local space * \param local_pt [out] position vector in local space * \param world_pt [in] position vector in world space * \param world [in] world transform */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ void ComputeLocalPoint(Point& local_pt, const Point& world_pt, const Matrix4x4& world) { // Get world vertex back in local space Matrix4x4 InvWorld = world; InvWorld.Invert(); local_pt = world_pt * InvWorld; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Transforms a ray from world space to local space * \param local_ray [out] ray in local space * \param world_ray [in] ray in world space * \param world [in] world transform */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ void ComputeLocalRay(Ray& local_ray, const Ray& world_ray, const Matrix4x4& world) { // Get world ray back in local space ComputeLocalDirection(local_ray.mDir, world_ray.mDir, world); ComputeLocalPoint(local_ray.mOrig, world_ray.mOrig, world); } #endif // __ICERAY_H__ ode-0.16/OPCODE/Ice/IceRevisitedRadix.cpp0000664000175200017520000005300213403272463014666 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains source code from the article "Radix Sort Revisited". * \file IceRevisitedRadix.cpp * \author Pierre Terdiman * \date April, 4, 2000 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Revisited Radix Sort. * This is my new radix routine: * - it uses indices and doesn't recopy the values anymore, hence wasting less ram * - it creates all the histograms in one run instead of four * - it sorts words faster than dwords and bytes faster than words * - it correctly sorts negative floating-point values by patching the offsets * - it automatically takes advantage of temporal coherence * - multiple keys support is a side effect of temporal coherence * - it may be worth recoding in asm... (mainly to use FCOMI, FCMOV, etc) [it's probably memory-bound anyway] * * History: * - 08.15.98: very first version * - 04.04.00: recoded for the radix article * - 12.xx.00: code lifting * - 09.18.01: faster CHECK_PASS_VALIDITY thanks to Mark D. Shattuck (who provided other tips, not included here) * - 10.11.01: added local ram support * - 01.20.02: bugfix! In very particular cases the last pass was skipped in the float code-path, leading to incorrect sorting...... * - 01.02.02: - "mIndices" renamed => "mRanks". That's a rank sorter after all. * - ranks are not "reset" anymore, but implicit on first calls * - 07.05.02: - offsets rewritten with one less indirection. * - 11.03.02: - "bool" replaced with RadixHint enum * * \class RadixSort * \author Pierre Terdiman * \version 1.4 * \date August, 15, 1998 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* To do: - add an offset parameter between two input values (avoid some data recopy sometimes) - unroll ? asm ? - 11 bits trick & 3 passes as Michael did - prefetch stuff the day I have a P3 - make a version with 16-bits indices ? */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Precompiled Header #include "Stdafx.h" using namespace IceCore; #define INVALIDATE_RANKS mCurrentSize|=0x80000000 #define VALIDATE_RANKS mCurrentSize&=0x7fffffff #define CURRENT_SIZE (mCurrentSize&0x7fffffff) #define INVALID_RANKS (mCurrentSize&0x80000000) #define CHECK_RESIZE(n) \ if(n!=mPreviousSize) \ { \ if(n>mCurrentSize) Resize(n); \ else ResetRanks(); \ mPreviousSize = n; \ } #define CREATE_HISTOGRAMS(type, buffer) \ /* Clear counters/histograms */ \ ZeroMemory(mHistogram, 256*4*sizeof(udword)); \ \ /* Prepare to count */ \ ubyte* p = (ubyte*)input; \ ubyte* pe = &p[nb*4]; \ udword* h0= &mHistogram[0]; /* Histogram for first pass (LSB) */ \ udword* h1= &mHistogram[256]; /* Histogram for second pass */ \ udword* h2= &mHistogram[512]; /* Histogram for third pass */ \ udword* h3= &mHistogram[768]; /* Histogram for last pass (MSB) */ \ \ bool AlreadySorted = true; /* Optimism... */ \ \ if(INVALID_RANKS) \ { \ /* Prepare for temporal coherence */ \ type* Running = (type*)buffer; \ type PrevVal = *Running; \ \ while(p!=pe) \ { \ /* Read input buffer in previous sorted order */ \ type Val = *Running++; \ /* Check whether already sorted or not */ \ if(ValCurSize) Resize(nb); mCurrentSize = nb; INVALIDATE_RANKS; } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Main sort routine. * This one is for integer values. After the call, mRanks contains a list of indices in sorted order, i.e. in the order you may process your data. * \param input [in] a list of integer values to sort * \param nb [in] number of values to sort, must be < 2^31 * \param hint [in] RADIX_SIGNED to handle negative values, RADIX_UNSIGNED if you know your input buffer only contains positive values * \return Self-Reference */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// RadixSort& RadixSort::Sort(const udword* input, udword nb, RadixHint hint) { // Checkings if(!input || !nb || nb&0x80000000) return *this; // Stats mTotalCalls++; // Resize lists if needed CheckResize(nb); #ifdef RADIX_LOCAL_RAM // Allocate histograms & offsets on the stack udword mHistogram[256*4]; // udword mOffset[256]; udword* mLink[256]; #endif // Create histograms (counters). Counters for all passes are created in one run. // Pros: read input buffer once instead of four times // Cons: mHistogram is 4Kb instead of 1Kb // We must take care of signed/unsigned values for temporal coherence.... I just // have 2 code paths even if just a single opcode changes. Self-modifying code, someone? if(hint==RADIX_UNSIGNED) { CREATE_HISTOGRAMS(udword, input); } else { CREATE_HISTOGRAMS(sdword, input); } // Compute #negative values involved if needed udword NbNegativeValues = 0; if(hint==RADIX_SIGNED) { // An efficient way to compute the number of negatives values we'll have to deal with is simply to sum the 128 // last values of the last histogram. Last histogram because that's the one for the Most Significant Byte, // responsible for the sign. 128 last values because the 128 first ones are related to positive numbers. udword* h3= &mHistogram[768]; for(udword i=128;i<256;i++) NbNegativeValues += h3[i]; // 768 for last histogram, 128 for negative part } // Radix sort, j is the pass number (0=LSB, 3=MSB) for(udword j=0;j<4;j++) { CHECK_PASS_VALIDITY(j); // Sometimes the fourth (negative) pass is skipped because all numbers are negative and the MSB is 0xFF (for example). This is // not a problem, numbers are correctly sorted anyway. if(PerformPass) { // Should we care about negative values? if(j!=3 || hint==RADIX_UNSIGNED) { // Here we deal with positive values only // Create offsets // mOffset[0] = 0; // for(udword i=1;i<256;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1]; mLink[0] = mRanks2; for(udword i=1;i<256;i++) mLink[i] = mLink[i-1] + CurCount[i-1]; } else { // This is a special case to correctly handle negative integers. They're sorted in the right order but at the wrong place. // Create biased offsets, in order for negative numbers to be sorted as well // mOffset[0] = NbNegativeValues; // First positive number takes place after the negative ones mLink[0] = &mRanks2[NbNegativeValues]; // First positive number takes place after the negative ones // for(udword i=1;i<128;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1]; // 1 to 128 for positive numbers for(udword i=1;i<128;i++) mLink[i] = mLink[i-1] + CurCount[i-1]; // 1 to 128 for positive numbers // Fixing the wrong place for negative values // mOffset[128] = 0; mLink[128] = mRanks2; // for(i=129;i<256;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1]; for(udword i=129;i<256;i++) mLink[i] = mLink[i-1] + CurCount[i-1]; } // Perform Radix Sort ubyte* InputBytes = (ubyte*)input; InputBytes += j; if(INVALID_RANKS) { // for(udword i=0;i>24; // Radix byte, same as above. AND is useless here (udword). // ### cmp to be killed. Not good. Later. // if(Radix<128) mRanks2[mOffset[Radix]++] = i; // Number is positive, same as above // else mRanks2[--mOffset[Radix]] = i; // Number is negative, flip the sorting order if(Radix<128) *mLink[Radix]++ = i; // Number is positive, same as above else *(--mLink[Radix]) = i; // Number is negative, flip the sorting order } VALIDATE_RANKS; } else { for(udword i=0;i>24; // Radix byte, same as above. AND is useless here (udword). // ### cmp to be killed. Not good. Later. // if(Radix<128) mRanks2[mOffset[Radix]++] = mRanks[i]; // Number is positive, same as above // else mRanks2[--mOffset[Radix]] = mRanks[i]; // Number is negative, flip the sorting order if(Radix<128) *mLink[Radix]++ = mRanks[i]; // Number is positive, same as above else *(--mLink[Radix]) = mRanks[i]; // Number is negative, flip the sorting order } } // Swap pointers for next pass. Valid indices - the most recent ones - are in mRanks after the swap. udword* Tmp = mRanks; mRanks = mRanks2; mRanks2 = Tmp; } else { // The pass is useless, yet we still have to reverse the order of current list if all values are negative. if(UniqueVal>=128) { if(INVALID_RANKS) { // ###Possible? for(udword i=0;i>31); return FR(y); } //! Computes 1.0f / sqrtf(x). inline_ float frsqrt(float f) { float x = f * 0.5f; udword y = 0x5f3759df - (IR(f) >> 1); // Iteration... const float fy = FR(y); const float result = fy * ( 1.5f - ( x * fy * fy ) ); // Result return result; } //! Computes 1.0f / sqrtf(x). Comes from NVIDIA. inline_ float InvSqrt(const float& x) { const udword tmp = (udword(IEEE_1_0 << 1) + IEEE_1_0 - IR(x)) >> 1; const float y = FR(tmp); return y * (1.47f - 0.47f * x * y * y); } //! Computes 1.0f / sqrtf(x). Comes from Quake3. Looks like the first one I had above. //! See http://www.magic-software.com/3DGEDInvSqrt.html inline_ float RSqrt(float number) { int i; float x2, y; const float threehalfs = 1.5f; x2 = number * 0.5f; y = number; i = IR(y); i = 0x5f3759df - (i >> 1); y = FR(i); y = y * (threehalfs - (x2 * y * y)); return y; } //! TO BE DOCUMENTED inline_ float fsqrt(float f) { udword y = ( ( SIR(f) - 0x3f800000 ) >> 1 ) + 0x3f800000; // Iteration...? // (float&)y = (3.0f - ((float&)y * (float&)y) / f) * (float&)y * 0.5f; // Result return FR(y); } //! Returns the float ranged espilon value. inline_ float fepsilon(float f) { udword b = IR(f) & 0xff800000; udword a = b | 0x00000001; // Result return FR(a) - FR(b); } //! Is the float valid ? inline_ bool IsNAN(float value) { return (IR(value)&0x7f800000) == 0x7f800000; } inline_ bool IsIndeterminate(float value) { return IR(value) == 0xffc00000; } inline_ bool IsPlusInf(float value) { return IR(value) == 0x7f800000; } inline_ bool IsMinusInf(float value) { return IR(value) == 0xff800000; } inline_ bool IsValidFloat(float value) { if(IsNAN(value)) return false; if(IsIndeterminate(value)) return false; if(IsPlusInf(value)) return false; if(IsMinusInf(value)) return false; return true; } #define CHECK_VALID_FLOAT(x) ASSERT(IsValidFloat(x)); /* //! FPU precision setting function. inline_ void SetFPU() { // This function evaluates whether the floating-point // control word is set to single precision/round to nearest/ // exceptions disabled. If these conditions don't hold, the // function changes the control word to set them and returns // TRUE, putting the old control word value in the passback // location pointed to by pwOldCW. { uword wTemp, wSave; __asm fstcw wSave if (wSave & 0x300 || // Not single mode 0x3f != (wSave & 0x3f) || // Exceptions enabled wSave & 0xC00) // Not round to nearest mode { __asm { mov ax, wSave and ax, not 300h ;; single mode or ax, 3fh ;; disable all exceptions and ax, not 0xC00 ;; round to nearest mode mov wTemp, ax fldcw wTemp } } } } */ //! This function computes the slowest possible floating-point value (you can also directly use FLT_EPSILON) inline_ float ComputeFloatEpsilon() { const float f = FR( IR(1.0f) ^ 1 ); return f - 1.0f; // You can check it's the same as FLT_EPSILON } inline_ bool IsFloatZero(float x, float epsilon=1e-6f) { return x*x < epsilon; } #define FCOMI_ST0 _asm _emit 0xdb _asm _emit 0xf0 #define FCOMIP_ST0 _asm _emit 0xdf _asm _emit 0xf0 #define FCMOVB_ST0 _asm _emit 0xda _asm _emit 0xc0 #define FCMOVNB_ST0 _asm _emit 0xdb _asm _emit 0xc0 #define FCOMI_ST1 _asm _emit 0xdb _asm _emit 0xf1 #define FCOMIP_ST1 _asm _emit 0xdf _asm _emit 0xf1 #define FCMOVB_ST1 _asm _emit 0xda _asm _emit 0xc1 #define FCMOVNB_ST1 _asm _emit 0xdb _asm _emit 0xc1 #define FCOMI_ST2 _asm _emit 0xdb _asm _emit 0xf2 #define FCOMIP_ST2 _asm _emit 0xdf _asm _emit 0xf2 #define FCMOVB_ST2 _asm _emit 0xda _asm _emit 0xc2 #define FCMOVNB_ST2 _asm _emit 0xdb _asm _emit 0xc2 #define FCOMI_ST3 _asm _emit 0xdb _asm _emit 0xf3 #define FCOMIP_ST3 _asm _emit 0xdf _asm _emit 0xf3 #define FCMOVB_ST3 _asm _emit 0xda _asm _emit 0xc3 #define FCMOVNB_ST3 _asm _emit 0xdb _asm _emit 0xc3 #define FCOMI_ST4 _asm _emit 0xdb _asm _emit 0xf4 #define FCOMIP_ST4 _asm _emit 0xdf _asm _emit 0xf4 #define FCMOVB_ST4 _asm _emit 0xda _asm _emit 0xc4 #define FCMOVNB_ST4 _asm _emit 0xdb _asm _emit 0xc4 #define FCOMI_ST5 _asm _emit 0xdb _asm _emit 0xf5 #define FCOMIP_ST5 _asm _emit 0xdf _asm _emit 0xf5 #define FCMOVB_ST5 _asm _emit 0xda _asm _emit 0xc5 #define FCMOVNB_ST5 _asm _emit 0xdb _asm _emit 0xc5 #define FCOMI_ST6 _asm _emit 0xdb _asm _emit 0xf6 #define FCOMIP_ST6 _asm _emit 0xdf _asm _emit 0xf6 #define FCMOVB_ST6 _asm _emit 0xda _asm _emit 0xc6 #define FCMOVNB_ST6 _asm _emit 0xdb _asm _emit 0xc6 #define FCOMI_ST7 _asm _emit 0xdb _asm _emit 0xf7 #define FCOMIP_ST7 _asm _emit 0xdf _asm _emit 0xf7 #define FCMOVB_ST7 _asm _emit 0xda _asm _emit 0xc7 #define FCMOVNB_ST7 _asm _emit 0xdb _asm _emit 0xc7 //! A global function to find MAX(a,b) using FCOMI/FCMOV inline_ float FCMax2(float a, float b) { return (a > b) ? a : b; } //! A global function to find MIN(a,b) using FCOMI/FCMOV inline_ float FCMin2(float a, float b) { return (a < b) ? a : b; } //! A global function to find MAX(a,b,c) using FCOMI/FCMOV inline_ float FCMax3(float a, float b, float c) { return (a > b) ? ((a > c) ? a : c) : ((b > c) ? b : c); } //! A global function to find MIN(a,b,c) using FCOMI/FCMOV inline_ float FCMin3(float a, float b, float c) { return (a < b) ? ((a < c) ? a : c) : ((b < c) ? b : c); } inline_ int ConvertToSortable(float f) { int Fi = SIR(f); int Fmask = (Fi>>31); Fi ^= Fmask; Fmask &= ~(1<<31); Fi -= Fmask; return Fi; } enum FPUMode { FPU_FLOOR = 0, FPU_CEIL = 1, FPU_BEST = 2, FPU_FORCE_DWORD = 0x7fffffff }; FUNCTION ICECORE_API FPUMode GetFPUMode(); FUNCTION ICECORE_API void SaveFPU(); FUNCTION ICECORE_API void RestoreFPU(); FUNCTION ICECORE_API void SetFPUFloorMode(); FUNCTION ICECORE_API void SetFPUCeilMode(); FUNCTION ICECORE_API void SetFPUBestMode(); FUNCTION ICECORE_API void SetFPUPrecision24(); FUNCTION ICECORE_API void SetFPUPrecision53(); FUNCTION ICECORE_API void SetFPUPrecision64(); FUNCTION ICECORE_API void SetFPURoundingChop(); FUNCTION ICECORE_API void SetFPURoundingUp(); FUNCTION ICECORE_API void SetFPURoundingDown(); FUNCTION ICECORE_API void SetFPURoundingNear(); FUNCTION ICECORE_API int intChop(const float& f); FUNCTION ICECORE_API int intFloor(const float& f); FUNCTION ICECORE_API int intCeil(const float& f); #endif // __ICEFPU_H__ ode-0.16/OPCODE/Ice/IceUtils.cpp0000664000175200017520000000336113403272463013043 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains misc. useful macros & defines. * \file IceUtils.cpp * \author Pierre Terdiman (collected from various sources) * \date April, 4, 2000 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Precompiled Header #include "Stdafx.h" using namespace IceCore; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Returns the alignment of the input address. * \fn Alignment() * \param address [in] address to check * \return the best alignment (e.g. 1 for odd addresses, etc) */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// udword IceCore::Alignment(udword address) { // Returns 0 for null addresses if(!address) return 0; // Test all bits udword Align = 1; for(udword i=1;i<32;i++) { // Returns as soon as the alignment is broken if(address&Align) return Align; Align<<=1; } // Here all bits are null, except the highest one (else the address would be null) return Align; } ode-0.16/OPCODE/Ice/IcePlane.h0000664000175200017520000001156613403272463012455 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains code for planes. * \file IcePlane.h * \author Pierre Terdiman * \date April, 4, 2000 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Include Guard #ifndef __ICEPLANE_H__ #define __ICEPLANE_H__ #define PLANE_EPSILON (1.0e-7f) class ICEMATHS_API Plane { public: //! Constructor inline_ Plane() { } //! Constructor from a normal and a distance inline_ Plane(float nx, float ny, float nz, float d) { Set(nx, ny, nz, d); } //! Constructor from a point on the plane and a normal inline_ Plane(const Point& p, const Point& n) { Set(p, n); } //! Constructor from three points inline_ Plane(const Point& p0, const Point& p1, const Point& p2) { Set(p0, p1, p2); } //! Constructor from a normal and a distance inline_ Plane(const Point& _n, float _d) { n = _n; d = _d; } //! Copy constructor inline_ Plane(const Plane& plane) : n(plane.n), d(plane.d) { } //! Destructor inline_ ~Plane() { } inline_ Plane& Zero() { n.Zero(); d = 0.0f; return *this; } inline_ Plane& Set(float nx, float ny, float nz, float _d) { n.Set(nx, ny, nz); d = _d; return *this; } inline_ Plane& Set(const Point& p, const Point& _n) { n = _n; d = - p | _n; return *this; } Plane& Set(const Point& p0, const Point& p1, const Point& p2); inline_ float Distance(const Point& p) const { return (p | n) + d; } inline_ bool Belongs(const Point& p) const { return fabsf(Distance(p)) < PLANE_EPSILON; } inline_ void Normalize() { float Denom = 1.0f / n.Magnitude(); n.x *= Denom; n.y *= Denom; n.z *= Denom; d *= Denom; } public: // Members Point n; //!< The normal to the plane float d; //!< The distance from the origin // Cast operators inline_ operator Point() const { return n; } inline_ operator HPoint() const { return HPoint(n, d); } // Arithmetic operators inline_ Plane operator*(const Matrix4x4& m) const { // Old code from Irion. Kept for reference. Plane Ret(*this); return Ret *= m; } inline_ Plane& operator*=(const Matrix4x4& m) { // Old code from Irion. Kept for reference. Point n2 = HPoint(n, 0.0f) * m; d = -((Point) (HPoint( -d*n, 1.0f ) * m) | n2); n = n2; return *this; } }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Transforms a plane by a 4x4 matrix. Same as Plane * Matrix4x4 operator, but faster. * \param transformed [out] transformed plane * \param plane [in] source plane * \param transform [in] transform matrix * \warning the plane normal must be unit-length */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ void TransformPlane(Plane& transformed, const Plane& plane, const Matrix4x4& transform) { // Rotate the normal using the rotation part of the 4x4 matrix transformed.n = plane.n * Matrix3x3(transform); // Compute new d transformed.d = plane.d - (Point(transform.GetTrans())|transformed.n); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Transforms a plane by a 4x4 matrix. Same as Plane * Matrix4x4 operator, but faster. * \param plane [in/out] source plane (transformed on return) * \param transform [in] transform matrix * \warning the plane normal must be unit-length */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ void TransformPlane(Plane& plane, const Matrix4x4& transform) { // Rotate the normal using the rotation part of the 4x4 matrix plane.n *= Matrix3x3(transform); // Compute new d plane.d -= Point(transform.GetTrans())|plane.n; } #endif // __ICEPLANE_H__ ode-0.16/OPCODE/Ice/IceTypes.h0000664000175200017520000001655213403272463012522 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains custom types. * \file IceTypes.h * \author Pierre Terdiman * \date April, 4, 2000 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Include Guard #ifndef __ICETYPES_H__ #define __ICETYPES_H__ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Things to help us compile on non-windows platforms /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #define USE_HANDLE_MANAGER // Constants #define PI 3.1415926535897932384626433832795028841971693993751f //!< PI #define HALFPI 1.57079632679489661923f //!< 0.5 * PI #define TWOPI 6.28318530717958647692f //!< 2.0 * PI #define INVPI 0.31830988618379067154f //!< 1.0 / PI #define RADTODEG 57.2957795130823208768f //!< 180.0 / PI, convert radians to degrees #define DEGTORAD 0.01745329251994329577f //!< PI / 180.0, convert degrees to radians #define EXP 2.71828182845904523536f //!< e #define INVLOG2 3.32192809488736234787f //!< 1.0 / log10(2) #define LN2 0.693147180559945f //!< ln(2) #define INVLN2 1.44269504089f //!< 1.0f / ln(2) #define INV3 0.33333333333333333333f //!< 1/3 #define INV6 0.16666666666666666666f //!< 1/6 #define INV7 0.14285714285714285714f //!< 1/7 #define INV9 0.11111111111111111111f //!< 1/9 #define INV255 0.00392156862745098039f //!< 1/255 #define SQRT2 1.41421356237f //!< sqrt(2) #define INVSQRT2 0.707106781188f //!< 1 / sqrt(2) #define SQRT3 1.73205080757f //!< sqrt(3) #define INVSQRT3 0.577350269189f //!< 1 / sqrt(3) #define null 0 //!< our own NULL pointer // Custom types used in ICE typedef signed char sbyte; //!< sizeof(sbyte) must be 1 typedef unsigned char ubyte; //!< sizeof(ubyte) must be 1 typedef signed short sword; //!< sizeof(sword) must be 2 typedef unsigned short uword; //!< sizeof(uword) must be 2 typedef signed int sdword; //!< sizeof(sdword) must be 4 typedef unsigned int udword; //!< sizeof(udword) must be 4 typedef signed __int64 sqword; //!< sizeof(sqword) must be 8 typedef unsigned __int64 uqword; //!< sizeof(uqword) must be 8 typedef float float32; //!< sizeof(float32) must be 4 typedef double float64; //!< sizeof(float64) must be 4 ICE_COMPILE_TIME_ASSERT(sizeof(ubyte)==1); ICE_COMPILE_TIME_ASSERT(sizeof(sbyte)==1); ICE_COMPILE_TIME_ASSERT(sizeof(sword)==2); ICE_COMPILE_TIME_ASSERT(sizeof(uword)==2); ICE_COMPILE_TIME_ASSERT(sizeof(udword)==4); ICE_COMPILE_TIME_ASSERT(sizeof(sdword)==4); ICE_COMPILE_TIME_ASSERT(sizeof(uqword)==8); ICE_COMPILE_TIME_ASSERT(sizeof(sqword)==8); //! TO BE DOCUMENTED #define DECLARE_ICE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name typedef udword DynID; //!< Dynamic identifier #ifdef USE_HANDLE_MANAGER typedef udword KID; //!< Kernel ID // DECLARE_ICE_HANDLE(KID); #else typedef uword KID; //!< Kernel ID #endif typedef udword RTYPE; //!< Relationship-type (!) between owners and references #define INVALID_ID 0xffffffff //!< Invalid dword ID (counterpart of null pointers) #ifdef USE_HANDLE_MANAGER #define INVALID_KID 0xffffffff //!< Invalid Kernel ID #else #define INVALID_KID 0xffff //!< Invalid Kernel ID #endif #define INVALID_NUMBER 0xDEADBEEF //!< Standard junk value // Define BOOL if needed #ifndef BOOL typedef int BOOL; //!< Another boolean type. #endif //! Union of a float and a sdword typedef union { float f; //!< The float sdword d; //!< The integer }scell; //! Union of a float and a udword typedef union { float f; //!< The float udword d; //!< The integer }ucell; // Type ranges #define MAX_SBYTE 0x7f //!< max possible sbyte value #define MIN_SBYTE 0x80 //!< min possible sbyte value #define MAX_UBYTE 0xff //!< max possible ubyte value #define MIN_UBYTE 0x00 //!< min possible ubyte value #define MAX_SWORD 0x7fff //!< max possible sword value #define MIN_SWORD 0x8000 //!< min possible sword value #define MAX_UWORD 0xffff //!< max possible uword value #define MIN_UWORD 0x0000 //!< min possible uword value #define MAX_SDWORD 0x7fffffff //!< max possible sdword value #define MIN_SDWORD 0x80000000 //!< min possible sdword value #define MAX_UDWORD 0xffffffff //!< max possible udword value #define MIN_UDWORD 0x00000000 //!< min possible udword value #define MAX_FLOAT FLT_MAX //!< max possible float value #define MIN_FLOAT (-FLT_MAX) //!< min possible loat value #define IEEE_1_0 0x3f800000 //!< integer representation of 1.0 #define IEEE_255_0 0x437f0000 //!< integer representation of 255.0 #define IEEE_MAX_FLOAT 0x7f7fffff //!< integer representation of MAX_FLOAT #define IEEE_MIN_FLOAT 0xff7fffff //!< integer representation of MIN_FLOAT #define IEEE_UNDERFLOW_LIMIT 0x1a000000 #define ONE_OVER_RAND_MAX (1.0f / float(RAND_MAX)) //!< Inverse of the max possible value returned by rand() // typedef int (__stdcall* PROC)(); -- Oleh Derevenko: Conflicts with Windows headers in x64 mode //!< A standard procedure call. typedef bool (*ENUMERATION)(udword value, udword param, udword context); //!< ICE standard enumeration call typedef void** VTABLE; //!< A V-Table. #undef MIN #undef MAX #define MIN(a, b) ((a) < (b) ? (a) : (b)) //!< Returns the min value between a and b #define MAX(a, b) ((a) > (b) ? (a) : (b)) //!< Returns the max value between a and b #define MAXMAX(a,b,c) ((a) > (b) ? MAX (a,c) : MAX (b,c)) //!< Returns the max value between a, b and c template inline_ const T& TMin (const T& a, const T& b) { return b < a ? b : a; } template inline_ const T& TMax (const T& a, const T& b) { return a < b ? b : a; } template inline_ void TSetMin (T& a, const T& b) { if(a>b) a = b; } template inline_ void TSetMax (T& a, const T& b) { if(aRelease(); (x) = null; } //!< Safe D3D-style release #define SAFE_DESTRUCT(x) if (x) { (x)->SelfDestruct(); (x) = null; } //!< Safe ICE-style release #ifdef __ICEERROR_H__ #define CHECKALLOC(x) if(!x) return SetIceError("Out of memory.", EC_OUT_OF_MEMORY); //!< Standard alloc checking. HANDLE WITH CARE. #else #define CHECKALLOC(x) if(!x) return false; #endif #endif // __ICEMEMORYMACROS_H__ ode-0.16/OPCODE/Ice/IceTriangle.cpp0000664000175200017520000003015213403272463013506 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains a handy triangle class. * \file IceTriangle.cpp * \author Pierre Terdiman * \date January, 17, 2000 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Precompiled Header #include "Stdafx.h" using namespace IceMaths; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains a triangle class. * * \class Tri * \author Pierre Terdiman * \version 1.0 * \date 08.15.98 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static sdword VPlaneSideEps(const Point& v, const Plane& plane, float epsilon) { // Compute distance from current vertex to the plane float Dist = plane.Distance(v); // Compute side: // 1 = the vertex is on the positive side of the plane // -1 = the vertex is on the negative side of the plane // 0 = the vertex is on the plane (within epsilon) return Dist > epsilon ? 1 : Dist < -epsilon ? -1 : 0; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Flips the winding order. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void Triangle::Flip() { Point Tmp = mVerts[1]; mVerts[1] = mVerts[2]; mVerts[2] = Tmp; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the triangle area. * \return the area */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// float Triangle::Area() const { const Point& p0 = mVerts[0]; const Point& p1 = mVerts[1]; const Point& p2 = mVerts[2]; return ((p0 - p1)^(p0 - p2)).Magnitude() * 0.5f; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the triangle perimeter. * \return the perimeter */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// float Triangle::Perimeter() const { const Point& p0 = mVerts[0]; const Point& p1 = mVerts[1]; const Point& p2 = mVerts[2]; return p0.Distance(p1) + p0.Distance(p2) + p1.Distance(p2); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the triangle compacity. * \return the compacity */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// float Triangle::Compacity() const { float P = Perimeter(); if(P==0.0f) return 0.0f; return (4.0f*PI*Area()/(P*P)); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the triangle normal. * \param normal [out] the computed normal */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void Triangle::Normal(Point& normal) const { const Point& p0 = mVerts[0]; const Point& p1 = mVerts[1]; const Point& p2 = mVerts[2]; normal = ((p0 - p1)^(p0 - p2)).Normalize(); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the triangle denormalized normal. * \param normal [out] the computed normal */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void Triangle::DenormalizedNormal(Point& normal) const { const Point& p0 = mVerts[0]; const Point& p1 = mVerts[1]; const Point& p2 = mVerts[2]; normal = ((p0 - p1)^(p0 - p2)); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the triangle center. * \param center [out] the computed center */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void Triangle::Center(Point& center) const { const Point& p0 = mVerts[0]; const Point& p1 = mVerts[1]; const Point& p2 = mVerts[2]; center = (p0 + p1 + p2)*INV3; } PartVal Triangle::TestAgainstPlane(const Plane& plane, float epsilon) const { bool Pos = false, Neg = false; // Loop through all vertices for(udword i=0;i<3;i++) { // Compute side: sdword Side = VPlaneSideEps(mVerts[i], plane, epsilon); if (Side < 0) Neg = true; else if (Side > 0) Pos = true; } if (!Pos && !Neg) return TRI_ON_PLANE; else if (Pos && Neg) return TRI_INTERSECT; else if (Pos && !Neg) return TRI_PLUS_SPACE; else if (!Pos && Neg) return TRI_MINUS_SPACE; // What?! return TRI_FORCEDWORD; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the triangle moment. * \param m [out] the moment */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* void Triangle::ComputeMoment(Moment& m) { // Compute the area of the triangle m.mArea = Area(); // Compute the centroid Center(m.mCentroid); // Second-order components. Handle zero-area faces. Point& p = mVerts[0]; Point& q = mVerts[1]; Point& r = mVerts[2]; if(m.mArea==0.0f) { // This triangle has zero area. The second order components would be eliminated with the usual formula, so, for the // sake of robustness we use an alternative form. These are the centroid and second-order components of the triangle's vertices. m.mCovariance.m[0][0] = (p.x*p.x + q.x*q.x + r.x*r.x); m.mCovariance.m[0][1] = (p.x*p.y + q.x*q.y + r.x*r.y); m.mCovariance.m[0][2] = (p.x*p.z + q.x*q.z + r.x*r.z); m.mCovariance.m[1][1] = (p.y*p.y + q.y*q.y + r.y*r.y); m.mCovariance.m[1][2] = (p.y*p.z + q.y*q.z + r.y*r.z); m.mCovariance.m[2][2] = (p.z*p.z + q.z*q.z + r.z*r.z); m.mCovariance.m[2][1] = m.mCovariance.m[1][2]; m.mCovariance.m[1][0] = m.mCovariance.m[0][1]; m.mCovariance.m[2][0] = m.mCovariance.m[0][2]; } else { const float OneOverTwelve = 1.0f / 12.0f; m.mCovariance.m[0][0] = m.mArea * (9.0f * m.mCentroid.x*m.mCentroid.x + p.x*p.x + q.x*q.x + r.x*r.x) * OneOverTwelve; m.mCovariance.m[0][1] = m.mArea * (9.0f * m.mCentroid.x*m.mCentroid.y + p.x*p.y + q.x*q.y + r.x*r.y) * OneOverTwelve; m.mCovariance.m[1][1] = m.mArea * (9.0f * m.mCentroid.y*m.mCentroid.y + p.y*p.y + q.y*q.y + r.y*r.y) * OneOverTwelve; m.mCovariance.m[0][2] = m.mArea * (9.0f * m.mCentroid.x*m.mCentroid.z + p.x*p.z + q.x*q.z + r.x*r.z) * OneOverTwelve; m.mCovariance.m[1][2] = m.mArea * (9.0f * m.mCentroid.y*m.mCentroid.z + p.y*p.z + q.y*q.z + r.y*r.z) * OneOverTwelve; m.mCovariance.m[2][2] = m.mArea * (9.0f * m.mCentroid.z*m.mCentroid.z + p.z*p.z + q.z*q.z + r.z*r.z) * OneOverTwelve; m.mCovariance.m[2][1] = m.mCovariance.m[1][2]; m.mCovariance.m[1][0] = m.mCovariance.m[0][1]; m.mCovariance.m[2][0] = m.mCovariance.m[0][2]; } } */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the triangle's smallest edge length. * \return the smallest edge length */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// float Triangle::MinEdgeLength() const { float Min = MAX_FLOAT; float Length01 = mVerts[0].Distance(mVerts[1]); float Length02 = mVerts[0].Distance(mVerts[2]); float Length12 = mVerts[1].Distance(mVerts[2]); if(Length01 < Min) Min = Length01; if(Length02 < Min) Min = Length02; if(Length12 < Min) Min = Length12; return Min; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the triangle's largest edge length. * \return the largest edge length */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// float Triangle::MaxEdgeLength() const { float Max = MIN_FLOAT; float Length01 = mVerts[0].Distance(mVerts[1]); float Length02 = mVerts[0].Distance(mVerts[2]); float Length12 = mVerts[1].Distance(mVerts[2]); if(Length01 > Max) Max = Length01; if(Length02 > Max) Max = Length02; if(Length12 > Max) Max = Length12; return Max; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes a point on the triangle according to the stabbing information. * \param u,v [in] point's barycentric coordinates * \param pt [out] point on triangle * \param nearvtx [out] index of nearest vertex */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void Triangle::ComputePoint(float u, float v, Point& pt, udword* nearvtx) const { // Compute point coordinates pt = (1.0f - u - v)*mVerts[0] + u*mVerts[1] + v*mVerts[2]; // Compute nearest vertex if needed if(nearvtx) { // Compute distance vector Point d(mVerts[0].SquareDistance(pt), // Distance^2 from vertex 0 to point on the face mVerts[1].SquareDistance(pt), // Distance^2 from vertex 1 to point on the face mVerts[2].SquareDistance(pt)); // Distance^2 from vertex 2 to point on the face // Get smallest distance *nearvtx = d.SmallestAxis(); } } void Triangle::Inflate(float fat_coeff, bool constant_border) { // Compute triangle center Point TriangleCenter; Center(TriangleCenter); // Don't normalize? // Normalize => add a constant border, regardless of triangle size // Don't => add more to big triangles for(udword i=0;i<3;i++) { Point v = mVerts[i] - TriangleCenter; if(constant_border) v.Normalize(); mVerts[i] += v * fat_coeff; } } ode-0.16/OPCODE/Ice/IceOBB.cpp0000664000175200017520000003035713403272463012352 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains OBB-related code. * \file IceOBB.cpp * \author Pierre Terdiman * \date January, 29, 2000 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * An Oriented Bounding Box (OBB). * \class OBB * \author Pierre Terdiman * \version 1.0 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Precompiled Header #include "Stdafx.h" using namespace IceMaths; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Tests if a point is contained within the OBB. * \param p [in] the world point to test * \return true if inside the OBB */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool OBB::ContainsPoint(const Point& p) const { // Point in OBB test using lazy evaluation and early exits // Translate to box space Point RelPoint = p - mCenter; // Point * mRot maps from box space to world space // mRot * Point maps from world space to box space (what we need here) float f = mRot.m[0][0] * RelPoint.x + mRot.m[0][1] * RelPoint.y + mRot.m[0][2] * RelPoint.z; if(f >= mExtents.x || f <= -mExtents.x) return false; f = mRot.m[1][0] * RelPoint.x + mRot.m[1][1] * RelPoint.y + mRot.m[1][2] * RelPoint.z; if(f >= mExtents.y || f <= -mExtents.y) return false; f = mRot.m[2][0] * RelPoint.x + mRot.m[2][1] * RelPoint.y + mRot.m[2][2] * RelPoint.z; if(f >= mExtents.z || f <= -mExtents.z) return false; return true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Builds an OBB from an AABB and a world transform. * \param aabb [in] the aabb * \param mat [in] the world transform */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void OBB::Create(const AABB& aabb, const Matrix4x4& mat) { // Note: must be coherent with Rotate() aabb.GetCenter(mCenter); aabb.GetExtents(mExtents); // Here we have the same as OBB::Rotate(mat) where the obb is (mCenter, mExtents, Identity). // So following what's done in Rotate: // - x-form the center mCenter *= mat; // - combine rotation with identity, i.e. just use given matrix mRot = mat; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the obb planes. * \param planes [out] 6 box planes * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool OBB::ComputePlanes(Plane* planes) const { // Checkings if(!planes) return false; Point Axis0 = mRot[0]; Point Axis1 = mRot[1]; Point Axis2 = mRot[2]; // Writes normals planes[0].n = Axis0; planes[1].n = -Axis0; planes[2].n = Axis1; planes[3].n = -Axis1; planes[4].n = Axis2; planes[5].n = -Axis2; // Compute a point on each plane Point p0 = mCenter + Axis0 * mExtents.x; Point p1 = mCenter - Axis0 * mExtents.x; Point p2 = mCenter + Axis1 * mExtents.y; Point p3 = mCenter - Axis1 * mExtents.y; Point p4 = mCenter + Axis2 * mExtents.z; Point p5 = mCenter - Axis2 * mExtents.z; // Compute d planes[0].d = -(planes[0].n|p0); planes[1].d = -(planes[1].n|p1); planes[2].d = -(planes[2].n|p2); planes[3].d = -(planes[3].n|p3); planes[4].d = -(planes[4].n|p4); planes[5].d = -(planes[5].n|p5); return true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the obb points. * \param pts [out] 8 box points * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool OBB::ComputePoints(Point* pts) const { // Checkings if(!pts) return false; Point Axis0 = mRot[0]; Point Axis1 = mRot[1]; Point Axis2 = mRot[2]; Axis0 *= mExtents.x; Axis1 *= mExtents.y; Axis2 *= mExtents.z; // 7+------+6 0 = --- // /| /| 1 = +-- // / | / | 2 = ++- // / 4+---/--+5 3 = -+- // 3+------+2 / y z 4 = --+ // | / | / | / 5 = +-+ // |/ |/ |/ 6 = +++ // 0+------+1 *---x 7 = -++ pts[0] = mCenter - Axis0 - Axis1 - Axis2; pts[1] = mCenter + Axis0 - Axis1 - Axis2; pts[2] = mCenter + Axis0 + Axis1 - Axis2; pts[3] = mCenter - Axis0 + Axis1 - Axis2; pts[4] = mCenter - Axis0 - Axis1 + Axis2; pts[5] = mCenter + Axis0 - Axis1 + Axis2; pts[6] = mCenter + Axis0 + Axis1 + Axis2; pts[7] = mCenter - Axis0 + Axis1 + Axis2; return true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes vertex normals. * \param pts [out] 8 box points * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool OBB::ComputeVertexNormals(Point* pts) const { static const float VertexNormals[] = { -INVSQRT3, -INVSQRT3, -INVSQRT3, INVSQRT3, -INVSQRT3, -INVSQRT3, INVSQRT3, INVSQRT3, -INVSQRT3, -INVSQRT3, INVSQRT3, -INVSQRT3, -INVSQRT3, -INVSQRT3, INVSQRT3, INVSQRT3, -INVSQRT3, INVSQRT3, INVSQRT3, INVSQRT3, INVSQRT3, -INVSQRT3, INVSQRT3, INVSQRT3 }; if(!pts) return false; const Point* VN = (const Point*)VertexNormals; for(udword i=0;i<8;i++) { pts[i] = VN[i] * mRot; } return true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Returns edges. * \return 24 indices (12 edges) indexing the list returned by ComputePoints() */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// const udword* OBB::GetEdges() const { static const udword Indices[] = { 0, 1, 1, 2, 2, 3, 3, 0, 7, 6, 6, 5, 5, 4, 4, 7, 1, 5, 6, 2, 3, 7, 4, 0 }; return Indices; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Returns local edge normals. * \return edge normals in local space */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// const Point* OBB::GetLocalEdgeNormals() const { static const float EdgeNormals[] = { 0, -INVSQRT2, -INVSQRT2, // 0-1 INVSQRT2, 0, -INVSQRT2, // 1-2 0, INVSQRT2, -INVSQRT2, // 2-3 -INVSQRT2, 0, -INVSQRT2, // 3-0 0, INVSQRT2, INVSQRT2, // 7-6 INVSQRT2, 0, INVSQRT2, // 6-5 0, -INVSQRT2, INVSQRT2, // 5-4 -INVSQRT2, 0, INVSQRT2, // 4-7 INVSQRT2, -INVSQRT2, 0, // 1-5 INVSQRT2, INVSQRT2, 0, // 6-2 -INVSQRT2, INVSQRT2, 0, // 3-7 -INVSQRT2, -INVSQRT2, 0 // 4-0 }; return (const Point*)EdgeNormals; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Returns world edge normal * \param edge_index [in] 0 <= edge index < 12 * \param world_normal [out] edge normal in world space */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void OBB::ComputeWorldEdgeNormal(udword edge_index, Point& world_normal) const { ASSERT(edge_index<12); world_normal = GetLocalEdgeNormals()[edge_index] * mRot; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes an LSS surrounding the OBB. * \param lss [out] the LSS */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void OBB::ComputeLSS(LSS& lss) const { Point Axis0 = mRot[0]; Point Axis1 = mRot[1]; Point Axis2 = mRot[2]; switch(mExtents.LargestAxis()) { case 0: lss.mRadius = (mExtents.y + mExtents.z)*0.5f; lss.mP0 = mCenter + Axis0 * (mExtents.x - lss.mRadius); lss.mP1 = mCenter - Axis0 * (mExtents.x - lss.mRadius); break; case 1: lss.mRadius = (mExtents.x + mExtents.z)*0.5f; lss.mP0 = mCenter + Axis1 * (mExtents.y - lss.mRadius); lss.mP1 = mCenter - Axis1 * (mExtents.y - lss.mRadius); break; case 2: lss.mRadius = (mExtents.x + mExtents.y)*0.5f; lss.mP0 = mCenter + Axis2 * (mExtents.z - lss.mRadius); lss.mP1 = mCenter - Axis2 * (mExtents.z - lss.mRadius); break; default: {} } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Checks the OBB is inside another OBB. * \param box [in] the other OBB * \return TRUE if we're inside the other box */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// BOOL OBB::IsInside(const OBB& box) const { // Make a 4x4 from the box & inverse it Matrix4x4 M0Inv; { Matrix4x4 M0 = box.mRot; M0.SetTrans(box.mCenter); InvertPRMatrix(M0Inv, M0); } // With our inversed 4x4, create box1 in space of box0 OBB _1in0; Rotate(M0Inv, _1in0); // This should cancel out box0's rotation, i.e. it's now an AABB. // => Center(0,0,0), Rot(identity) // The two boxes are in the same space so now we can compare them. // Create the AABB of (box1 in space of box0) const Matrix3x3& mtx = _1in0.mRot; float f = fabsf(mtx.m[0][0] * mExtents.x) + fabsf(mtx.m[1][0] * mExtents.y) + fabsf(mtx.m[2][0] * mExtents.z) - box.mExtents.x; if(f > _1in0.mCenter.x) return FALSE; if(-f < _1in0.mCenter.x) return FALSE; f = fabsf(mtx.m[0][1] * mExtents.x) + fabsf(mtx.m[1][1] * mExtents.y) + fabsf(mtx.m[2][1] * mExtents.z) - box.mExtents.y; if(f > _1in0.mCenter.y) return FALSE; if(-f < _1in0.mCenter.y) return FALSE; f = fabsf(mtx.m[0][2] * mExtents.x) + fabsf(mtx.m[1][2] * mExtents.y) + fabsf(mtx.m[2][2] * mExtents.z) - box.mExtents.z; if(f > _1in0.mCenter.z) return FALSE; if(-f < _1in0.mCenter.z) return FALSE; return TRUE; } ode-0.16/OPCODE/Ice/IcePoint.h0000664000175200017520000004645213403272463012511 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains code for 3D vectors. * \file IcePoint.h * \author Pierre Terdiman * \date April, 4, 2000 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Include Guard #ifndef __ICEPOINT_H__ #define __ICEPOINT_H__ // Forward declarations class HPoint; class Plane; class Matrix3x3; class Matrix4x4; #define CROSS2D(a, b) (a.x*b.y - b.x*a.y) const float EPSILON2 = 1.0e-20f; class ICEMATHS_API Point { public: //! Empty constructor inline_ Point() {} //! Constructor from a single float // inline_ Point(float val) : x(val), y(val), z(val) {} // Removed since it introduced the nasty "Point T = *Matrix4x4.GetTrans();" bug....... //! Constructor from floats template inline_ Point(toffsetfloat xx, toffsetfloat yy, toffsetfloat zz) : x((float)xx), y((float)yy), z((float)zz) {} //! Constructor from array inline_ Point(const float f[3]) : x(f[X]), y(f[Y]), z(f[Z]) {} //! Copy constructor inline_ Point(const Point& p) : x(p.x), y(p.y), z(p.z) {} //! Destructor inline_ ~Point() {} //! Clears the vector inline_ Point& Zero() { x = y = z = 0.0f; return *this; } //! + infinity inline_ Point& SetPlusInfinity() { x = y = z = MAX_FLOAT; return *this; } //! - infinity inline_ Point& SetMinusInfinity() { x = y = z = MIN_FLOAT; return *this; } //! Sets positive unit random vector Point& PositiveUnitRandomVector(); //! Sets unit random vector Point& UnitRandomVector(); //! Assignment from values template inline_ Point& Set(toffsetfloat xx, toffsetfloat yy, toffsetfloat zz) { x = (float)xx; y = (float)yy; z = (float)zz; return *this; } //! Assignment from array inline_ Point& Set(const float f[3]) { x = f[X]; y = f[Y]; z = f[Z]; return *this; } //! Assignment from another point inline_ Point& Set(const Point& src) { x = src.x; y = src.y; z = src.z; return *this; } //! Adds a vector inline_ Point& Add(const Point& p) { x += p.x; y += p.y; z += p.z; return *this; } //! Adds a vector inline_ Point& Add(float xx, float yy, float zz) { x += xx; y += yy; z += zz; return *this; } //! Adds a vector inline_ Point& Add(const float f[3]) { x += f[X]; y += f[Y]; z += f[Z]; return *this; } //! Adds vectors inline_ Point& Add(const Point& p, const Point& q) { x = p.x+q.x; y = p.y+q.y; z = p.z+q.z; return *this; } //! Subtracts a vector inline_ Point& Sub(const Point& p) { x -= p.x; y -= p.y; z -= p.z; return *this; } //! Subtracts a vector inline_ Point& Sub(float xx, float yy, float zz) { x -= xx; y -= yy; z -= zz; return *this; } //! Subtracts a vector inline_ Point& Sub(const float f[3]) { x -= f[X]; y -= f[Y]; z -= f[Z]; return *this; } //! Subtracts vectors inline_ Point& Sub(const Point& p, const Point& q) { x = p.x-q.x; y = p.y-q.y; z = p.z-q.z; return *this; } //! this = -this inline_ Point& Neg() { x = -x; y = -y; z = -z; return *this; } //! this = -a inline_ Point& Neg(const Point& a) { x = -a.x; y = -a.y; z = -a.z; return *this; } //! Multiplies by a scalar inline_ Point& Mult(float s) { x *= s; y *= s; z *= s; return *this; } //! this = a * scalar inline_ Point& Mult(const Point& a, float scalar) { x = a.x * scalar; y = a.y * scalar; z = a.z * scalar; return *this; } //! this = a + b * scalar inline_ Point& Mac(const Point& a, const Point& b, float scalar) { x = a.x + b.x * scalar; y = a.y + b.y * scalar; z = a.z + b.z * scalar; return *this; } //! this = this + a * scalar inline_ Point& Mac(const Point& a, float scalar) { x += a.x * scalar; y += a.y * scalar; z += a.z * scalar; return *this; } //! this = a - b * scalar inline_ Point& Msc(const Point& a, const Point& b, float scalar) { x = a.x - b.x * scalar; y = a.y - b.y * scalar; z = a.z - b.z * scalar; return *this; } //! this = this - a * scalar inline_ Point& Msc(const Point& a, float scalar) { x -= a.x * scalar; y -= a.y * scalar; z -= a.z * scalar; return *this; } //! this = a + b * scalarb + c * scalarc inline_ Point& Mac2(const Point& a, const Point& b, float scalarb, const Point& c, float scalarc) { x = a.x + b.x * scalarb + c.x * scalarc; y = a.y + b.y * scalarb + c.y * scalarc; z = a.z + b.z * scalarb + c.z * scalarc; return *this; } //! this = a - b * scalarb - c * scalarc inline_ Point& Msc2(const Point& a, const Point& b, float scalarb, const Point& c, float scalarc) { x = a.x - b.x * scalarb - c.x * scalarc; y = a.y - b.y * scalarb - c.y * scalarc; z = a.z - b.z * scalarb - c.z * scalarc; return *this; } //! this = mat * a inline_ Point& Mult(const Matrix3x3& mat, const Point& a); //! this = mat1 * a1 + mat2 * a2 inline_ Point& Mult2(const Matrix3x3& mat1, const Point& a1, const Matrix3x3& mat2, const Point& a2); //! this = this + mat * a inline_ Point& Mac(const Matrix3x3& mat, const Point& a); //! this = transpose(mat) * a inline_ Point& TransMult(const Matrix3x3& mat, const Point& a); //! Linear interpolate between two vectors: this = a + t * (b - a) inline_ Point& Lerp(const Point& a, const Point& b, float t) { x = a.x + t * (b.x - a.x); y = a.y + t * (b.y - a.y); z = a.z + t * (b.z - a.z); return *this; } //! Hermite interpolate between p1 and p2. p0 and p3 are used for finding gradient at p1 and p2. //! this = p0 * (2t^2 - t^3 - t)/2 //! + p1 * (3t^3 - 5t^2 + 2)/2 //! + p2 * (4t^2 - 3t^3 + t)/2 //! + p3 * (t^3 - t^2)/2 inline_ Point& Herp(const Point& p0, const Point& p1, const Point& p2, const Point& p3, float t) { float t2 = t * t; float t3 = t2 * t; float kp0 = (2.0f * t2 - t3 - t) * 0.5f; float kp1 = (3.0f * t3 - 5.0f * t2 + 2.0f) * 0.5f; float kp2 = (4.0f * t2 - 3.0f * t3 + t) * 0.5f; float kp3 = (t3 - t2) * 0.5f; x = p0.x * kp0 + p1.x * kp1 + p2.x * kp2 + p3.x * kp3; y = p0.y * kp0 + p1.y * kp1 + p2.y * kp2 + p3.y * kp3; z = p0.z * kp0 + p1.z * kp1 + p2.z * kp2 + p3.z * kp3; return *this; } //! this = rotpos * r + linpos inline_ Point& Transform(const Point& r, const Matrix3x3& rotpos, const Point& linpos); //! this = trans(rotpos) * (r - linpos) inline_ Point& InvTransform(const Point& r, const Matrix3x3& rotpos, const Point& linpos); //! Returns MIN(x, y, z); inline_ float Min() const { return MIN(x, MIN(y, z)); } //! Returns MAX(x, y, z); inline_ float Max() const { return MAX(x, MAX(y, z)); } //! Sets each element to be componentwise minimum inline_ Point& Min(const Point& p) { x = MIN(x, p.x); y = MIN(y, p.y); z = MIN(z, p.z); return *this; } //! Sets each element to be componentwise maximum inline_ Point& Max(const Point& p) { x = MAX(x, p.x); y = MAX(y, p.y); z = MAX(z, p.z); return *this; } //! Clamps each element inline_ Point& Clamp(float min, float max) { if(xmax) x=max; if(ymax) y=max; if(zmax) z=max; return *this; } //! Computes square magnitude inline_ float SquareMagnitude() const { return x*x + y*y + z*z; } //! Computes magnitude inline_ float Magnitude() const { return sqrtf(x*x + y*y + z*z); } //! Computes volume inline_ float Volume() const { return x * y * z; } //! Checks the point is near zero inline_ bool ApproxZero() const { return SquareMagnitude() < EPSILON2; } //! Tests for exact zero vector inline_ BOOL IsZero() const { if(IR(x) || IR(y) || IR(z)) return FALSE; return TRUE; } //! Checks point validity inline_ BOOL IsValid() const { if(!IsValidFloat(x)) return FALSE; if(!IsValidFloat(y)) return FALSE; if(!IsValidFloat(z)) return FALSE; return TRUE; } //! Slighty moves the point void Tweak(udword coord_mask, udword tweak_mask) { if(coord_mask&1) { udword Dummy = IR(x); Dummy^=tweak_mask; x = FR(Dummy); } if(coord_mask&2) { udword Dummy = IR(y); Dummy^=tweak_mask; y = FR(Dummy); } if(coord_mask&4) { udword Dummy = IR(z); Dummy^=tweak_mask; z = FR(Dummy); } } #define TWEAKMASK 0x3fffff #define TWEAKNOTMASK ~TWEAKMASK //! Slighty moves the point out inline_ void TweakBigger() { udword Dummy = (IR(x)&TWEAKNOTMASK); if(!IS_NEGATIVE_FLOAT(x)) Dummy+=TWEAKMASK+1; x = FR(Dummy); Dummy = (IR(y)&TWEAKNOTMASK); if(!IS_NEGATIVE_FLOAT(y)) Dummy+=TWEAKMASK+1; y = FR(Dummy); Dummy = (IR(z)&TWEAKNOTMASK); if(!IS_NEGATIVE_FLOAT(z)) Dummy+=TWEAKMASK+1; z = FR(Dummy); } //! Slighty moves the point in inline_ void TweakSmaller() { udword Dummy = (IR(x)&TWEAKNOTMASK); if(IS_NEGATIVE_FLOAT(x)) Dummy+=TWEAKMASK+1; x = FR(Dummy); Dummy = (IR(y)&TWEAKNOTMASK); if(IS_NEGATIVE_FLOAT(y)) Dummy+=TWEAKMASK+1; y = FR(Dummy); Dummy = (IR(z)&TWEAKNOTMASK); if(IS_NEGATIVE_FLOAT(z)) Dummy+=TWEAKMASK+1; z = FR(Dummy); } //! Normalizes the vector inline_ Point& Normalize() { float M = x*x + y*y + z*z; if(M) { M = 1.0f / sqrtf(M); x *= M; y *= M; z *= M; } return *this; } //! Sets vector length inline_ Point& SetLength(float length) { float NewLength = length / Magnitude(); x *= NewLength; y *= NewLength; z *= NewLength; return *this; } //! Clamps vector length inline_ Point& ClampLength(float limit_length) { if(limit_length>=0.0f) // Magnitude must be positive { float CurrentSquareLength = SquareMagnitude(); if(CurrentSquareLength > limit_length * limit_length) { float Coeff = limit_length / sqrtf(CurrentSquareLength); x *= Coeff; y *= Coeff; z *= Coeff; } } return *this; } //! Computes distance to another point inline_ float Distance(const Point& b) const { return sqrtf((x - b.x)*(x - b.x) + (y - b.y)*(y - b.y) + (z - b.z)*(z - b.z)); } //! Computes square distance to another point inline_ float SquareDistance(const Point& b) const { return ((x - b.x)*(x - b.x) + (y - b.y)*(y - b.y) + (z - b.z)*(z - b.z)); } //! Dot product dp = this|a inline_ float Dot(const Point& p) const { return p.x * x + p.y * y + p.z * z; } //! Cross product this = a x b inline_ Point& Cross(const Point& a, const Point& b) { x = a.y * b.z - a.z * b.y; y = a.z * b.x - a.x * b.z; z = a.x * b.y - a.y * b.x; return *this; } //! Vector code ( bitmask = sign(z) | sign(y) | sign(x) ) inline_ udword VectorCode() const { return (IR(x)>>31) | ((IR(y)&SIGN_BITMASK)>>30) | ((IR(z)&SIGN_BITMASK)>>29); } //! Returns largest axis inline_ PointComponent LargestAxis() const { const float* Vals = &x; PointComponent m = X; if(Vals[Y] > Vals[m]) m = Y; if(Vals[Z] > Vals[m]) m = Z; return m; } //! Returns closest axis inline_ PointComponent ClosestAxis() const { const float* Vals = &x; PointComponent m = X; if(AIR(Vals[Y]) > AIR(Vals[m])) m = Y; if(AIR(Vals[Z]) > AIR(Vals[m])) m = Z; return m; } //! Returns smallest axis inline_ PointComponent SmallestAxis() const { const float* Vals = &x; PointComponent m = X; if(Vals[Y] < Vals[m]) m = Y; if(Vals[Z] < Vals[m]) m = Z; return m; } //! Refracts the point Point& Refract(const Point& eye, const Point& n, float refractindex, Point& refracted); //! Projects the point onto a plane Point& ProjectToPlane(const Plane& p); //! Projects the point onto the screen void ProjectToScreen(float halfrenderwidth, float halfrenderheight, const Matrix4x4& mat, HPoint& projected) const; //! Unfolds the point onto a plane according to edge(a,b) Point& Unfold(Plane& p, Point& a, Point& b); //! Hash function from Ville Miettinen inline_ udword GetHashValue() const { const udword* h = (const udword*)(this); udword f = (h[0]+h[1]*11-(h[2]*17)) & 0x7fffffff; // avoid problems with +-0 return (f>>22)^(f>>12)^(f); } //! Stuff magic values in the point, marking it as explicitely not used. void SetNotUsed(); //! Checks the point is marked as not used BOOL IsNotUsed() const; // Arithmetic operators //! Unary operator for Point Negate = - Point inline_ Point operator-() const { return Point(-x, -y, -z); } //! Operator for Point Plus = Point + Point. inline_ Point operator+(const Point& p) const { return Point(x + p.x, y + p.y, z + p.z); } //! Operator for Point Minus = Point - Point. inline_ Point operator-(const Point& p) const { return Point(x - p.x, y - p.y, z - p.z); } //! Operator for Point Mul = Point * Point. inline_ Point operator*(const Point& p) const { return Point(x * p.x, y * p.y, z * p.z); } //! Operator for Point Scale = Point * float. inline_ Point operator*(float s) const { return Point(x * s, y * s, z * s ); } //! Operator for Point Scale = float * Point. inline_ friend Point operator*(float s, const Point& p) { return Point(s * p.x, s * p.y, s * p.z); } //! Operator for Point Div = Point / Point. inline_ Point operator/(const Point& p) const { return Point(x / p.x, y / p.y, z / p.z); } //! Operator for Point Scale = Point / float. inline_ Point operator/(float s) const { s = 1.0f / s; return Point(x * s, y * s, z * s); } //! Operator for Point Scale = float / Point. inline_ friend Point operator/(float s, const Point& p) { return Point(s / p.x, s / p.y, s / p.z); } //! Operator for float DotProd = Point | Point. inline_ float operator|(const Point& p) const { return x*p.x + y*p.y + z*p.z; } //! Operator for Point VecProd = Point ^ Point. inline_ Point operator^(const Point& p) const { return Point( y * p.z - z * p.y, z * p.x - x * p.z, x * p.y - y * p.x ); } //! Operator for Point += Point. inline_ Point& operator+=(const Point& p) { x += p.x; y += p.y; z += p.z; return *this; } //! Operator for Point += float. inline_ Point& operator+=(float s) { x += s; y += s; z += s; return *this; } //! Operator for Point -= Point. inline_ Point& operator-=(const Point& p) { x -= p.x; y -= p.y; z -= p.z; return *this; } //! Operator for Point -= float. inline_ Point& operator-=(float s) { x -= s; y -= s; z -= s; return *this; } //! Operator for Point *= Point. inline_ Point& operator*=(const Point& p) { x *= p.x; y *= p.y; z *= p.z; return *this; } //! Operator for Point *= float. inline_ Point& operator*=(float s) { x *= s; y *= s; z *= s; return *this; } //! Operator for Point /= Point. inline_ Point& operator/=(const Point& p) { x /= p.x; y /= p.y; z /= p.z; return *this; } //! Operator for Point /= float. inline_ Point& operator/=(float s) { s = 1.0f/s; x *= s; y *= s; z *= s; return *this; } // Logical operators //! Operator for "if(Point==Point)" inline_ bool operator==(const Point& p) const { return ( (IR(x)==IR(p.x))&&(IR(y)==IR(p.y))&&(IR(z)==IR(p.z))); } //! Operator for "if(Point!=Point)" inline_ bool operator!=(const Point& p) const { return ( (IR(x)!=IR(p.x))||(IR(y)!=IR(p.y))||(IR(z)!=IR(p.z))); } // Arithmetic operators //! Operator for Point Mul = Point * Matrix3x3. inline_ Point operator*(const Matrix3x3& mat) const { class ShadowMatrix3x3{ public: float m[3][3]; }; // To allow inlining const ShadowMatrix3x3* Mat = (const ShadowMatrix3x3*)&mat; return Point( x * Mat->m[0][0] + y * Mat->m[1][0] + z * Mat->m[2][0], x * Mat->m[0][1] + y * Mat->m[1][1] + z * Mat->m[2][1], x * Mat->m[0][2] + y * Mat->m[1][2] + z * Mat->m[2][2] ); } //! Operator for Point Mul = Point * Matrix4x4. inline_ Point operator*(const Matrix4x4& mat) const { class ShadowMatrix4x4{ public: float m[4][4]; }; // To allow inlining const ShadowMatrix4x4* Mat = (const ShadowMatrix4x4*)&mat; return Point( x * Mat->m[0][0] + y * Mat->m[1][0] + z * Mat->m[2][0] + Mat->m[3][0], x * Mat->m[0][1] + y * Mat->m[1][1] + z * Mat->m[2][1] + Mat->m[3][1], x * Mat->m[0][2] + y * Mat->m[1][2] + z * Mat->m[2][2] + Mat->m[3][2]); } //! Operator for Point *= Matrix3x3. inline_ Point& operator*=(const Matrix3x3& mat) { class ShadowMatrix3x3{ public: float m[3][3]; }; // To allow inlining const ShadowMatrix3x3* Mat = (const ShadowMatrix3x3*)&mat; float xp = x * Mat->m[0][0] + y * Mat->m[1][0] + z * Mat->m[2][0]; float yp = x * Mat->m[0][1] + y * Mat->m[1][1] + z * Mat->m[2][1]; float zp = x * Mat->m[0][2] + y * Mat->m[1][2] + z * Mat->m[2][2]; x = xp; y = yp; z = zp; return *this; } //! Operator for Point *= Matrix4x4. inline_ Point& operator*=(const Matrix4x4& mat) { class ShadowMatrix4x4{ public: float m[4][4]; }; // To allow inlining const ShadowMatrix4x4* Mat = (const ShadowMatrix4x4*)&mat; float xp = x * Mat->m[0][0] + y * Mat->m[1][0] + z * Mat->m[2][0] + Mat->m[3][0]; float yp = x * Mat->m[0][1] + y * Mat->m[1][1] + z * Mat->m[2][1] + Mat->m[3][1]; float zp = x * Mat->m[0][2] + y * Mat->m[1][2] + z * Mat->m[2][2] + Mat->m[3][2]; x = xp; y = yp; z = zp; return *this; } // Cast operators //! Cast a Point to a HPoint. w is set to zero. operator HPoint() const; inline_ operator const float*() const { return &x; } inline_ operator float*() { return &x; } public: float x, y, z; }; FUNCTION ICEMATHS_API void Normalize1(Point& a); FUNCTION ICEMATHS_API void Normalize2(Point& a); #endif //__ICEPOINT_H__ ode-0.16/OPCODE/Ice/IcePlane.cpp0000664000175200017520000000376413403272463013011 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains code for planes. * \file IcePlane.cpp * \author Pierre Terdiman * \date April, 4, 2000 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Plane class. * \class Plane * \author Pierre Terdiman * \version 1.0 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Precompiled Header #include "Stdafx.h" using namespace IceMaths; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the plane equation from 3 points. * \param p0 [in] first point * \param p1 [in] second point * \param p2 [in] third point * \return Self-reference */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Plane& Plane::Set(const Point& p0, const Point& p1, const Point& p2) { Point Edge0 = p1 - p0; Point Edge1 = p2 - p0; n = Edge0 ^ Edge1; n.Normalize(); d = -(p0 | n); return *this; } ode-0.16/OPCODE/Ice/IceContainer.h0000664000175200017520000002372713403272463013342 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains a simple container class. * \file IceContainer.h * \author Pierre Terdiman * \date February, 5, 2000 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Include Guard #ifndef __ICECONTAINER_H__ #define __ICECONTAINER_H__ // #define CONTAINER_STATS enum FindMode { FIND_CLAMP, FIND_WRAP, FIND_FORCE_DWORD = 0x7fffffff }; class ICECORE_API Container { public: // Constructor / Destructor Container(); Container(const Container& object); Container(udword size, float growth_factor); ~Container(); // Management /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * A O(1) method to add a value in the container. The container is automatically resized if needed. * The method is inline, not the resize. The call overhead happens on resizes only, which is not a problem since the resizing operation * costs a lot more than the call overhead... * * \param entry [in] a udword to store in the container * \see Add(float entry) * \see Empty() * \see Contains(udword entry) * \return Self-Reference */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ Container& Add(udword entry) { // Resize if needed if (mCurNbEntries == mMaxNbEntries && !Resize()) { IceAbort(); } // Add new entry mEntries[mCurNbEntries++] = entry; return *this; } inline_ Container& Add(const uword* entries, udword nb) { // Resize if needed if (mCurNbEntries + nb > mMaxNbEntries && !Resize(nb)) { IceAbort(); } // Add new entry CopyMemory(&mEntries[mCurNbEntries], entries, nb*sizeof(uword)); mCurNbEntries+=nb; return *this; } inline_ Container& Add(const udword* entries, udword nb) { // Resize if needed if (mCurNbEntries + nb > mMaxNbEntries && !Resize(nb)) { IceAbort(); } // Add new entry CopyMemory(&mEntries[mCurNbEntries], entries, nb*sizeof(udword)); mCurNbEntries+=nb; return *this; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * A O(1) method to add a value in the container. The container is automatically resized if needed. * The method is inline, not the resize. The call overhead happens on resizes only, which is not a problem since the resizing operation * costs a lot more than the call overhead... * * \param entry [in] a float to store in the container * \see Add(udword entry) * \see Empty() * \see Contains(udword entry) * \return Self-Reference */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ Container& Add(float entry) { // Resize if needed if (mCurNbEntries == mMaxNbEntries && !Resize()) { IceAbort(); } // Add new entry mEntries[mCurNbEntries++] = IR(entry); return *this; } inline_ Container& Add(const float* entries, udword nb) { // Resize if needed if (mCurNbEntries + nb > mMaxNbEntries && !Resize(nb)) { IceAbort(); } // Add new entry CopyMemory(&mEntries[mCurNbEntries], entries, nb*sizeof(float)); mCurNbEntries+=nb; return *this; } //! Add unique [slow] inline_ Container& AddUnique(udword entry) { if(!Contains(entry)) Add(entry); return *this; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Clears the container. All stored values are deleted, and it frees used ram. * \see Reset() * \return Self-Reference */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Container& Empty(); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Resets the container. Stored values are discarded but the buffer is kept so that further calls don't need resizing again. * That's a kind of temporal coherence. * \see Empty() */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ void Reset() { // Avoid the write if possible // ### CMOV if(mCurNbEntries) mCurNbEntries = 0; } // HANDLE WITH CARE inline_ void ForceSize(udword size) { mCurNbEntries = size; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Sets the initial size of the container. If it already contains something, it's discarded. * \param nb [in] Number of entries * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool SetSize(udword nb); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Refits the container and get rid of unused bytes. * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool Refit(); // Checks whether the container already contains a given value. bool Contains(udword entry, udword* location=null) const; // Deletes an entry - doesn't preserve insertion order. bool Delete(udword entry); // Deletes an entry - does preserve insertion order. bool DeleteKeepingOrder(udword entry); //! Deletes the very last entry. inline_ void DeleteLastEntry() { if(mCurNbEntries) mCurNbEntries--; } //! Deletes the entry whose index is given inline_ void DeleteIndex(udword index) { ASSERT(index < mCurNbEntries); mEntries[index] = mEntries[--mCurNbEntries]; } // Helpers Container& FindNext(udword& entry, FindMode find_mode=FIND_CLAMP); Container& FindPrev(udword& entry, FindMode find_mode=FIND_CLAMP); // Data access. inline_ udword GetNbEntries() const { return mCurNbEntries; } //!< Returns the current number of entries. inline_ udword GetEntry(udword i) const { return mEntries[i]; } //!< Returns ith entry inline_ udword* GetEntries() const { return mEntries; } //!< Returns the list of entries. inline_ udword GetFirst() const { return mEntries[0]; } inline_ udword GetLast() const { return mEntries[mCurNbEntries-1]; } // Growth control inline_ udword GetGrowthFactor() const { return mGrowthFactor; } //!< Returns the growth factor inline_ void SetGrowthFactor(udword growth) { mGrowthFactor = growth; } //!< Sets the growth factor inline_ bool IsFull() const { return mCurNbEntries==mMaxNbEntries; } //!< Checks the container is full inline_ BOOL IsNotEmpty() const { return mCurNbEntries; } //!< Checks the container is empty //! Read-access as an array inline_ udword operator[](udword i) const { ASSERT(i>=0 && i=0 && i inline_ void Set(trotationfloat m00, trotationfloat m01, trotationfloat m02, trotationfloat m10, trotationfloat m11, trotationfloat m12, trotationfloat m20, trotationfloat m21, trotationfloat m22) { m[0][0] = (float)m00; m[0][1] = (float)m01; m[0][2] = (float)m02; m[1][0] = (float)m10; m[1][1] = (float)m11; m[1][2] = (float)m12; m[2][0] = (float)m20; m[2][1] = (float)m21; m[2][2] = (float)m22; } //! Sets the scale from a Point. The point is put on the diagonal. inline_ void SetScale(const Point& p) { m[0][0] = p.x; m[1][1] = p.y; m[2][2] = p.z; } //! Sets the scale from floats. Values are put on the diagonal. inline_ void SetScale(float sx, float sy, float sz) { m[0][0] = sx; m[1][1] = sy; m[2][2] = sz; } //! Scales from a Point. Each row is multiplied by a component. inline_ void Scale(const Point& p) { m[0][0] *= p.x; m[0][1] *= p.x; m[0][2] *= p.x; m[1][0] *= p.y; m[1][1] *= p.y; m[1][2] *= p.y; m[2][0] *= p.z; m[2][1] *= p.z; m[2][2] *= p.z; } //! Scales from floats. Each row is multiplied by a value. inline_ void Scale(float sx, float sy, float sz) { m[0][0] *= sx; m[0][1] *= sx; m[0][2] *= sx; m[1][0] *= sy; m[1][1] *= sy; m[1][2] *= sy; m[2][0] *= sz; m[2][1] *= sz; m[2][2] *= sz; } //! Copy from a Matrix3x3 inline_ void Copy(const Matrix3x3& source) { CopyMemory(m, source.m, 9*sizeof(float)); } // Row-column access //! Returns a row. inline_ void GetRow(const udword r, Point& p) const { p.x = m[r][0]; p.y = m[r][1]; p.z = m[r][2]; } //! Returns a row. inline_ const Point& GetRow(const udword r) const { return *(const Point*)&m[r][0]; } //! Returns a row. inline_ Point& GetRow(const udword r) { return *(Point*)&m[r][0]; } //! Sets a row. inline_ void SetRow(const udword r, const Point& p) { m[r][0] = p.x; m[r][1] = p.y; m[r][2] = p.z; } //! Returns a column. inline_ void GetCol(const udword c, Point& p) const { p.x = m[0][c]; p.y = m[1][c]; p.z = m[2][c]; } //! Sets a column. inline_ void SetCol(const udword c, const Point& p) { m[0][c] = p.x; m[1][c] = p.y; m[2][c] = p.z; } //! Computes the trace. The trace is the sum of the 3 diagonal components. inline_ float Trace() const { return m[0][0] + m[1][1] + m[2][2]; } //! Clears the matrix. inline_ void Zero() { ZeroMemory(&m, sizeof(m)); } //! Sets the identity matrix. inline_ void Identity() { Zero(); m[0][0] = m[1][1] = m[2][2] = 1.0f; } //! Checks for identity inline_ bool IsIdentity() const { if(IR(m[0][0])!=IEEE_1_0) return false; if(IR(m[0][1])!=0) return false; if(IR(m[0][2])!=0) return false; if(IR(m[1][0])!=0) return false; if(IR(m[1][1])!=IEEE_1_0) return false; if(IR(m[1][2])!=0) return false; if(IR(m[2][0])!=0) return false; if(IR(m[2][1])!=0) return false; if(IR(m[2][2])!=IEEE_1_0) return false; return true; } //! Checks matrix validity inline_ BOOL IsValid() const { for(udword j=0;j<3;j++) { for(udword i=0;i<3;i++) { if(!IsValidFloat(m[j][i])) return FALSE; } } return TRUE; } //! Makes a skew-symmetric matrix (a.k.a. Star(*) Matrix) //! [ 0.0 -a.z a.y ] //! [ a.z 0.0 -a.x ] //! [ -a.y a.x 0.0 ] //! This is also called a "cross matrix" since for any vectors A and B, //! A^B = Skew(A) * B = - B * Skew(A); inline_ void SkewSymmetric(const Point& a) { m[0][0] = 0.0f; m[0][1] = -a.z; m[0][2] = a.y; m[1][0] = a.z; m[1][1] = 0.0f; m[1][2] = -a.x; m[2][0] = -a.y; m[2][1] = a.x; m[2][2] = 0.0f; } //! Negates the matrix inline_ void Neg() { m[0][0] = -m[0][0]; m[0][1] = -m[0][1]; m[0][2] = -m[0][2]; m[1][0] = -m[1][0]; m[1][1] = -m[1][1]; m[1][2] = -m[1][2]; m[2][0] = -m[2][0]; m[2][1] = -m[2][1]; m[2][2] = -m[2][2]; } //! Neg from another matrix inline_ void Neg(const Matrix3x3& mat) { m[0][0] = -mat.m[0][0]; m[0][1] = -mat.m[0][1]; m[0][2] = -mat.m[0][2]; m[1][0] = -mat.m[1][0]; m[1][1] = -mat.m[1][1]; m[1][2] = -mat.m[1][2]; m[2][0] = -mat.m[2][0]; m[2][1] = -mat.m[2][1]; m[2][2] = -mat.m[2][2]; } //! Add another matrix inline_ void Add(const Matrix3x3& mat) { m[0][0] += mat.m[0][0]; m[0][1] += mat.m[0][1]; m[0][2] += mat.m[0][2]; m[1][0] += mat.m[1][0]; m[1][1] += mat.m[1][1]; m[1][2] += mat.m[1][2]; m[2][0] += mat.m[2][0]; m[2][1] += mat.m[2][1]; m[2][2] += mat.m[2][2]; } //! Sub another matrix inline_ void Sub(const Matrix3x3& mat) { m[0][0] -= mat.m[0][0]; m[0][1] -= mat.m[0][1]; m[0][2] -= mat.m[0][2]; m[1][0] -= mat.m[1][0]; m[1][1] -= mat.m[1][1]; m[1][2] -= mat.m[1][2]; m[2][0] -= mat.m[2][0]; m[2][1] -= mat.m[2][1]; m[2][2] -= mat.m[2][2]; } //! Mac inline_ void Mac(const Matrix3x3& a, const Matrix3x3& b, float s) { m[0][0] = a.m[0][0] + b.m[0][0] * s; m[0][1] = a.m[0][1] + b.m[0][1] * s; m[0][2] = a.m[0][2] + b.m[0][2] * s; m[1][0] = a.m[1][0] + b.m[1][0] * s; m[1][1] = a.m[1][1] + b.m[1][1] * s; m[1][2] = a.m[1][2] + b.m[1][2] * s; m[2][0] = a.m[2][0] + b.m[2][0] * s; m[2][1] = a.m[2][1] + b.m[2][1] * s; m[2][2] = a.m[2][2] + b.m[2][2] * s; } //! Mac inline_ void Mac(const Matrix3x3& a, float s) { m[0][0] += a.m[0][0] * s; m[0][1] += a.m[0][1] * s; m[0][2] += a.m[0][2] * s; m[1][0] += a.m[1][0] * s; m[1][1] += a.m[1][1] * s; m[1][2] += a.m[1][2] * s; m[2][0] += a.m[2][0] * s; m[2][1] += a.m[2][1] * s; m[2][2] += a.m[2][2] * s; } //! this = A * s inline_ void Mult(const Matrix3x3& a, float s) { m[0][0] = a.m[0][0] * s; m[0][1] = a.m[0][1] * s; m[0][2] = a.m[0][2] * s; m[1][0] = a.m[1][0] * s; m[1][1] = a.m[1][1] * s; m[1][2] = a.m[1][2] * s; m[2][0] = a.m[2][0] * s; m[2][1] = a.m[2][1] * s; m[2][2] = a.m[2][2] * s; } inline_ void Add(const Matrix3x3& a, const Matrix3x3& b) { m[0][0] = a.m[0][0] + b.m[0][0]; m[0][1] = a.m[0][1] + b.m[0][1]; m[0][2] = a.m[0][2] + b.m[0][2]; m[1][0] = a.m[1][0] + b.m[1][0]; m[1][1] = a.m[1][1] + b.m[1][1]; m[1][2] = a.m[1][2] + b.m[1][2]; m[2][0] = a.m[2][0] + b.m[2][0]; m[2][1] = a.m[2][1] + b.m[2][1]; m[2][2] = a.m[2][2] + b.m[2][2]; } inline_ void Sub(const Matrix3x3& a, const Matrix3x3& b) { m[0][0] = a.m[0][0] - b.m[0][0]; m[0][1] = a.m[0][1] - b.m[0][1]; m[0][2] = a.m[0][2] - b.m[0][2]; m[1][0] = a.m[1][0] - b.m[1][0]; m[1][1] = a.m[1][1] - b.m[1][1]; m[1][2] = a.m[1][2] - b.m[1][2]; m[2][0] = a.m[2][0] - b.m[2][0]; m[2][1] = a.m[2][1] - b.m[2][1]; m[2][2] = a.m[2][2] - b.m[2][2]; } //! this = a * b inline_ void Mult(const Matrix3x3& a, const Matrix3x3& b) { m[0][0] = a.m[0][0] * b.m[0][0] + a.m[0][1] * b.m[1][0] + a.m[0][2] * b.m[2][0]; m[0][1] = a.m[0][0] * b.m[0][1] + a.m[0][1] * b.m[1][1] + a.m[0][2] * b.m[2][1]; m[0][2] = a.m[0][0] * b.m[0][2] + a.m[0][1] * b.m[1][2] + a.m[0][2] * b.m[2][2]; m[1][0] = a.m[1][0] * b.m[0][0] + a.m[1][1] * b.m[1][0] + a.m[1][2] * b.m[2][0]; m[1][1] = a.m[1][0] * b.m[0][1] + a.m[1][1] * b.m[1][1] + a.m[1][2] * b.m[2][1]; m[1][2] = a.m[1][0] * b.m[0][2] + a.m[1][1] * b.m[1][2] + a.m[1][2] * b.m[2][2]; m[2][0] = a.m[2][0] * b.m[0][0] + a.m[2][1] * b.m[1][0] + a.m[2][2] * b.m[2][0]; m[2][1] = a.m[2][0] * b.m[0][1] + a.m[2][1] * b.m[1][1] + a.m[2][2] * b.m[2][1]; m[2][2] = a.m[2][0] * b.m[0][2] + a.m[2][1] * b.m[1][2] + a.m[2][2] * b.m[2][2]; } //! this = transpose(a) * b inline_ void MultAtB(const Matrix3x3& a, const Matrix3x3& b) { m[0][0] = a.m[0][0] * b.m[0][0] + a.m[1][0] * b.m[1][0] + a.m[2][0] * b.m[2][0]; m[0][1] = a.m[0][0] * b.m[0][1] + a.m[1][0] * b.m[1][1] + a.m[2][0] * b.m[2][1]; m[0][2] = a.m[0][0] * b.m[0][2] + a.m[1][0] * b.m[1][2] + a.m[2][0] * b.m[2][2]; m[1][0] = a.m[0][1] * b.m[0][0] + a.m[1][1] * b.m[1][0] + a.m[2][1] * b.m[2][0]; m[1][1] = a.m[0][1] * b.m[0][1] + a.m[1][1] * b.m[1][1] + a.m[2][1] * b.m[2][1]; m[1][2] = a.m[0][1] * b.m[0][2] + a.m[1][1] * b.m[1][2] + a.m[2][1] * b.m[2][2]; m[2][0] = a.m[0][2] * b.m[0][0] + a.m[1][2] * b.m[1][0] + a.m[2][2] * b.m[2][0]; m[2][1] = a.m[0][2] * b.m[0][1] + a.m[1][2] * b.m[1][1] + a.m[2][2] * b.m[2][1]; m[2][2] = a.m[0][2] * b.m[0][2] + a.m[1][2] * b.m[1][2] + a.m[2][2] * b.m[2][2]; } //! this = a * transpose(b) inline_ void MultABt(const Matrix3x3& a, const Matrix3x3& b) { m[0][0] = a.m[0][0] * b.m[0][0] + a.m[0][1] * b.m[0][1] + a.m[0][2] * b.m[0][2]; m[0][1] = a.m[0][0] * b.m[1][0] + a.m[0][1] * b.m[1][1] + a.m[0][2] * b.m[1][2]; m[0][2] = a.m[0][0] * b.m[2][0] + a.m[0][1] * b.m[2][1] + a.m[0][2] * b.m[2][2]; m[1][0] = a.m[1][0] * b.m[0][0] + a.m[1][1] * b.m[0][1] + a.m[1][2] * b.m[0][2]; m[1][1] = a.m[1][0] * b.m[1][0] + a.m[1][1] * b.m[1][1] + a.m[1][2] * b.m[1][2]; m[1][2] = a.m[1][0] * b.m[2][0] + a.m[1][1] * b.m[2][1] + a.m[1][2] * b.m[2][2]; m[2][0] = a.m[2][0] * b.m[0][0] + a.m[2][1] * b.m[0][1] + a.m[2][2] * b.m[0][2]; m[2][1] = a.m[2][0] * b.m[1][0] + a.m[2][1] * b.m[1][1] + a.m[2][2] * b.m[1][2]; m[2][2] = a.m[2][0] * b.m[2][0] + a.m[2][1] * b.m[2][1] + a.m[2][2] * b.m[2][2]; } //! Makes a rotation matrix mapping vector "from" to vector "to". Matrix3x3& FromTo(const Point& from, const Point& to); //! Set a rotation matrix around the X axis. //! 1 0 0 //! RX = 0 cx sx //! 0 -sx cx void RotX(float angle); //! Set a rotation matrix around the Y axis. //! cy 0 -sy //! RY = 0 1 0 //! sy 0 cy void RotY(float angle); //! Set a rotation matrix around the Z axis. //! cz sz 0 //! RZ = -sz cz 0 //! 0 0 1 void RotZ(float angle); //! cy sx.sy -sy.cx //! RY.RX 0 cx sx //! sy -sx.cy cx.cy void RotYX(float y, float x); //! Make a rotation matrix about an arbitrary axis Matrix3x3& Rot(float angle, const Point& axis); //! Transpose the matrix. void Transpose() { TSwap(m[1][0], m[0][1]); TSwap(m[2][0], m[0][2]); TSwap(m[2][1], m[1][2]); } //! this = Transpose(a) void Transpose(const Matrix3x3& a) { m[0][0] = a.m[0][0]; m[0][1] = a.m[1][0]; m[0][2] = a.m[2][0]; m[1][0] = a.m[0][1]; m[1][1] = a.m[1][1]; m[1][2] = a.m[2][1]; m[2][0] = a.m[0][2]; m[2][1] = a.m[1][2]; m[2][2] = a.m[2][2]; } //! Compute the determinant of the matrix. We use the rule of Sarrus. float Determinant() const { return (m[0][0]*m[1][1]*m[2][2] + m[0][1]*m[1][2]*m[2][0] + m[0][2]*m[1][0]*m[2][1]) - (m[2][0]*m[1][1]*m[0][2] + m[2][1]*m[1][2]*m[0][0] + m[2][2]*m[1][0]*m[0][1]); } /* //! Compute a cofactor. Used for matrix inversion. float CoFactor(ubyte row, ubyte column) const { static const sdword gIndex[3+2] = { 0, 1, 2, 0, 1 }; return (m[gIndex[row+1]][gIndex[column+1]]*m[gIndex[row+2]][gIndex[column+2]] - m[gIndex[row+2]][gIndex[column+1]]*m[gIndex[row+1]][gIndex[column+2]]); } */ //! Invert the matrix. Determinant must be different from zero, else matrix can't be inverted. Matrix3x3& Invert() { float Det = Determinant(); // Must be !=0 float OneOverDet = 1.0f / Det; Matrix3x3 Temp; Temp.m[0][0] = +(m[1][1] * m[2][2] - m[2][1] * m[1][2]) * OneOverDet; Temp.m[1][0] = -(m[1][0] * m[2][2] - m[2][0] * m[1][2]) * OneOverDet; Temp.m[2][0] = +(m[1][0] * m[2][1] - m[2][0] * m[1][1]) * OneOverDet; Temp.m[0][1] = -(m[0][1] * m[2][2] - m[2][1] * m[0][2]) * OneOverDet; Temp.m[1][1] = +(m[0][0] * m[2][2] - m[2][0] * m[0][2]) * OneOverDet; Temp.m[2][1] = -(m[0][0] * m[2][1] - m[2][0] * m[0][1]) * OneOverDet; Temp.m[0][2] = +(m[0][1] * m[1][2] - m[1][1] * m[0][2]) * OneOverDet; Temp.m[1][2] = -(m[0][0] * m[1][2] - m[1][0] * m[0][2]) * OneOverDet; Temp.m[2][2] = +(m[0][0] * m[1][1] - m[1][0] * m[0][1]) * OneOverDet; *this = Temp; return *this; } Matrix3x3& Normalize(); //! this = exp(a) Matrix3x3& Exp(const Matrix3x3& a); void FromQuat(const Quat &q); void FromQuatL2(const Quat &q, float l2); // Arithmetic operators //! Operator for Matrix3x3 Plus = Matrix3x3 + Matrix3x3; inline_ Matrix3x3 operator+(const Matrix3x3& mat) const { return Matrix3x3( m[0][0] + mat.m[0][0], m[0][1] + mat.m[0][1], m[0][2] + mat.m[0][2], m[1][0] + mat.m[1][0], m[1][1] + mat.m[1][1], m[1][2] + mat.m[1][2], m[2][0] + mat.m[2][0], m[2][1] + mat.m[2][1], m[2][2] + mat.m[2][2]); } //! Operator for Matrix3x3 Minus = Matrix3x3 - Matrix3x3; inline_ Matrix3x3 operator-(const Matrix3x3& mat) const { return Matrix3x3( m[0][0] - mat.m[0][0], m[0][1] - mat.m[0][1], m[0][2] - mat.m[0][2], m[1][0] - mat.m[1][0], m[1][1] - mat.m[1][1], m[1][2] - mat.m[1][2], m[2][0] - mat.m[2][0], m[2][1] - mat.m[2][1], m[2][2] - mat.m[2][2]); } //! Operator for Matrix3x3 Mul = Matrix3x3 * Matrix3x3; inline_ Matrix3x3 operator*(const Matrix3x3& mat) const { return Matrix3x3( m[0][0]*mat.m[0][0] + m[0][1]*mat.m[1][0] + m[0][2]*mat.m[2][0], m[0][0]*mat.m[0][1] + m[0][1]*mat.m[1][1] + m[0][2]*mat.m[2][1], m[0][0]*mat.m[0][2] + m[0][1]*mat.m[1][2] + m[0][2]*mat.m[2][2], m[1][0]*mat.m[0][0] + m[1][1]*mat.m[1][0] + m[1][2]*mat.m[2][0], m[1][0]*mat.m[0][1] + m[1][1]*mat.m[1][1] + m[1][2]*mat.m[2][1], m[1][0]*mat.m[0][2] + m[1][1]*mat.m[1][2] + m[1][2]*mat.m[2][2], m[2][0]*mat.m[0][0] + m[2][1]*mat.m[1][0] + m[2][2]*mat.m[2][0], m[2][0]*mat.m[0][1] + m[2][1]*mat.m[1][1] + m[2][2]*mat.m[2][1], m[2][0]*mat.m[0][2] + m[2][1]*mat.m[1][2] + m[2][2]*mat.m[2][2]); } //! Operator for Point Mul = Matrix3x3 * Point; inline_ Point operator*(const Point& v) const { return Point(GetRow(0)|v, GetRow(1)|v, GetRow(2)|v); } //! Operator for Matrix3x3 Mul = Matrix3x3 * float; inline_ Matrix3x3 operator*(float s) const { return Matrix3x3( m[0][0]*s, m[0][1]*s, m[0][2]*s, m[1][0]*s, m[1][1]*s, m[1][2]*s, m[2][0]*s, m[2][1]*s, m[2][2]*s); } //! Operator for Matrix3x3 Mul = float * Matrix3x3; inline_ friend Matrix3x3 operator*(float s, const Matrix3x3& mat) { return Matrix3x3( s*mat.m[0][0], s*mat.m[0][1], s*mat.m[0][2], s*mat.m[1][0], s*mat.m[1][1], s*mat.m[1][2], s*mat.m[2][0], s*mat.m[2][1], s*mat.m[2][2]); } //! Operator for Matrix3x3 Div = Matrix3x3 / float; inline_ Matrix3x3 operator/(float s) const { if (s) s = 1.0f / s; return Matrix3x3( m[0][0]*s, m[0][1]*s, m[0][2]*s, m[1][0]*s, m[1][1]*s, m[1][2]*s, m[2][0]*s, m[2][1]*s, m[2][2]*s); } //! Operator for Matrix3x3 Div = float / Matrix3x3; inline_ friend Matrix3x3 operator/(float s, const Matrix3x3& mat) { return Matrix3x3( s/mat.m[0][0], s/mat.m[0][1], s/mat.m[0][2], s/mat.m[1][0], s/mat.m[1][1], s/mat.m[1][2], s/mat.m[2][0], s/mat.m[2][1], s/mat.m[2][2]); } //! Operator for Matrix3x3 += Matrix3x3 inline_ Matrix3x3& operator+=(const Matrix3x3& mat) { m[0][0] += mat.m[0][0]; m[0][1] += mat.m[0][1]; m[0][2] += mat.m[0][2]; m[1][0] += mat.m[1][0]; m[1][1] += mat.m[1][1]; m[1][2] += mat.m[1][2]; m[2][0] += mat.m[2][0]; m[2][1] += mat.m[2][1]; m[2][2] += mat.m[2][2]; return *this; } //! Operator for Matrix3x3 -= Matrix3x3 inline_ Matrix3x3& operator-=(const Matrix3x3& mat) { m[0][0] -= mat.m[0][0]; m[0][1] -= mat.m[0][1]; m[0][2] -= mat.m[0][2]; m[1][0] -= mat.m[1][0]; m[1][1] -= mat.m[1][1]; m[1][2] -= mat.m[1][2]; m[2][0] -= mat.m[2][0]; m[2][1] -= mat.m[2][1]; m[2][2] -= mat.m[2][2]; return *this; } //! Operator for Matrix3x3 *= Matrix3x3 inline_ Matrix3x3& operator*=(const Matrix3x3& mat) { Point TempRow; GetRow(0, TempRow); m[0][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0]; m[0][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1]; m[0][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2]; GetRow(1, TempRow); m[1][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0]; m[1][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1]; m[1][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2]; GetRow(2, TempRow); m[2][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0]; m[2][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1]; m[2][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2]; return *this; } //! Operator for Matrix3x3 *= float inline_ Matrix3x3& operator*=(float s) { m[0][0] *= s; m[0][1] *= s; m[0][2] *= s; m[1][0] *= s; m[1][1] *= s; m[1][2] *= s; m[2][0] *= s; m[2][1] *= s; m[2][2] *= s; return *this; } //! Operator for Matrix3x3 /= float inline_ Matrix3x3& operator/=(float s) { if (s) s = 1.0f / s; m[0][0] *= s; m[0][1] *= s; m[0][2] *= s; m[1][0] *= s; m[1][1] *= s; m[1][2] *= s; m[2][0] *= s; m[2][1] *= s; m[2][2] *= s; return *this; } // Cast operators //! Cast a Matrix3x3 to a Matrix4x4. operator Matrix4x4() const; //! Cast a Matrix3x3 to a Quat. operator Quat() const; inline_ const Point& operator[](int row) const { return *(const Point*)&m[row][0]; } inline_ Point& operator[](int row) { return *(Point*)&m[row][0]; } public: float m[3][3]; }; #endif // __ICEMATRIX3X3_H__ ode-0.16/OPCODE/Ice/IceMatrix4x4.h0000664000175200017520000005135213403272463013217 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains code for 4x4 matrices. * \file IceMatrix4x4.h * \author Pierre Terdiman * \date April, 4, 2000 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Include Guard #ifndef __ICEMATRIX4X4_H__ #define __ICEMATRIX4X4_H__ // Forward declarations class PRS; class PR; #define MATRIX4X4_EPSILON (1.0e-7f) class ICEMATHS_API Matrix4x4 { // void LUBackwardSubstitution( sdword *indx, float* b ); // void LUDecomposition( sdword* indx, float* d ); public: //! Empty constructor. inline_ Matrix4x4() {} //! Constructor from 16 values inline_ Matrix4x4( float m00, float m01, float m02, float m03, float m10, float m11, float m12, float m13, float m20, float m21, float m22, float m23, float m30, float m31, float m32, float m33) { m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; m[0][3] = m03; m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; m[1][3] = m13; m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; m[2][3] = m23; m[3][0] = m30; m[3][1] = m31; m[3][2] = m32; m[3][3] = m33; } //! Copy constructor inline_ Matrix4x4(const Matrix4x4& mat) { CopyMemory(m, &mat.m, 16*sizeof(float)); } //! Destructor. inline_ ~Matrix4x4() {} //! Assign values (rotation only) template inline_ Matrix4x4& Set( trotationfloat m00, trotationfloat m01, trotationfloat m02, trotationfloat m10, trotationfloat m11, trotationfloat m12, trotationfloat m20, trotationfloat m21, trotationfloat m22) { m[0][0] = (float)m00; m[0][1] = (float)m01; m[0][2] = (float)m02; m[1][0] = (float)m10; m[1][1] = (float)m11; m[1][2] = (float)m12; m[2][0] = (float)m20; m[2][1] = (float)m21; m[2][2] = (float)m22; return *this; } //! Assign values template inline_ Matrix4x4& Set( trotationfloat m00, trotationfloat m01, trotationfloat m02, textrafloat m03, trotationfloat m10, trotationfloat m11, trotationfloat m12, textrafloat m13, trotationfloat m20, trotationfloat m21, trotationfloat m22, textrafloat m23, toffsetfloat m30, toffsetfloat m31, toffsetfloat m32, textrafloat m33) { m[0][0] = (float)m00; m[0][1] = (float)m01; m[0][2] = (float)m02; m[0][3] = (float)m03; m[1][0] = (float)m10; m[1][1] = (float)m11; m[1][2] = (float)m12; m[1][3] = (float)m13; m[2][0] = (float)m20; m[2][1] = (float)m21; m[2][2] = (float)m22; m[2][3] = (float)m23; m[3][0] = (float)m30; m[3][1] = (float)m31; m[3][2] = (float)m32; m[3][3] = (float)m33; return *this; } //! Copy from a Matrix4x4 inline_ void Copy(const Matrix4x4& source) { CopyMemory(m, source.m, 16*sizeof(float)); } // Row-column access //! Returns a row. inline_ void GetRow(const udword r, HPoint& p) const { p.x=m[r][0]; p.y=m[r][1]; p.z=m[r][2]; p.w=m[r][3]; } //! Returns a row. inline_ void GetRow(const udword r, Point& p) const { p.x=m[r][0]; p.y=m[r][1]; p.z=m[r][2]; } //! Returns a row. inline_ const HPoint& GetRow(const udword r) const { return *(const HPoint*)&m[r][0]; } //! Returns a row. inline_ HPoint& GetRow(const udword r) { return *(HPoint*)&m[r][0]; } //! Sets a row. inline_ void SetRow(const udword r, const HPoint& p) { m[r][0]=p.x; m[r][1]=p.y; m[r][2]=p.z; m[r][3]=p.w; } //! Sets a row. inline_ void SetRow(const udword r, const Point& p) { m[r][0]=p.x; m[r][1]=p.y; m[r][2]=p.z; m[r][3]= (r!=3) ? 0.0f : 1.0f; } //! Returns a column. inline_ void GetCol(const udword c, HPoint& p) const { p.x=m[0][c]; p.y=m[1][c]; p.z=m[2][c]; p.w=m[3][c]; } //! Returns a column. inline_ void GetCol(const udword c, Point& p) const { p.x=m[0][c]; p.y=m[1][c]; p.z=m[2][c]; } //! Sets a column. inline_ void SetCol(const udword c, const HPoint& p) { m[0][c]=p.x; m[1][c]=p.y; m[2][c]=p.z; m[3][c]=p.w; } //! Sets a column. inline_ void SetCol(const udword c, const Point& p) { m[0][c]=p.x; m[1][c]=p.y; m[2][c]=p.z; m[3][c]= (c!=3) ? 0.0f : 1.0f; } // Translation //! Returns the translation part of the matrix. inline_ const HPoint& GetTrans() const { return GetRow(3); } //! Gets the translation part of the matrix inline_ void GetTrans(Point& p) const { p.x=m[3][0]; p.y=m[3][1]; p.z=m[3][2]; } //! Sets the translation part of the matrix, from a Point. inline_ void SetTrans(const Point& p) { m[3][0]=p.x; m[3][1]=p.y; m[3][2]=p.z; } //! Sets the translation part of the matrix, from a HPoint. inline_ void SetTrans(const HPoint& p) { m[3][0]=p.x; m[3][1]=p.y; m[3][2]=p.z; m[3][3]=p.w; } //! Sets the translation part of the matrix, from floats. inline_ void SetTrans(float tx, float ty, float tz) { m[3][0]=tx; m[3][1]=ty; m[3][2]=tz; } // Scale //! Sets the scale from a Point. The point is put on the diagonal. inline_ void SetScale(const Point& p) { m[0][0]=p.x; m[1][1]=p.y; m[2][2]=p.z; } //! Sets the scale from floats. Values are put on the diagonal. inline_ void SetScale(float sx, float sy, float sz) { m[0][0]=sx; m[1][1]=sy; m[2][2]=sz; } //! Scales from a Point. Each row is multiplied by a component. void Scale(const Point& p) { m[0][0] *= p.x; m[1][0] *= p.y; m[2][0] *= p.z; m[0][1] *= p.x; m[1][1] *= p.y; m[2][1] *= p.z; m[0][2] *= p.x; m[1][2] *= p.y; m[2][2] *= p.z; } //! Scales from floats. Each row is multiplied by a value. void Scale(float sx, float sy, float sz) { m[0][0] *= sx; m[1][0] *= sy; m[2][0] *= sz; m[0][1] *= sx; m[1][1] *= sy; m[2][1] *= sz; m[0][2] *= sx; m[1][2] *= sy; m[2][2] *= sz; } /* //! Returns a row. inline_ HPoint GetRow(const udword row) const { return mRow[row]; } //! Sets a row. inline_ Matrix4x4& SetRow(const udword row, const HPoint& p) { mRow[row] = p; return *this; } //! Sets a row. Matrix4x4& SetRow(const udword row, const Point& p) { m[row][0] = p.x; m[row][1] = p.y; m[row][2] = p.z; m[row][3] = (row != 3) ? 0.0f : 1.0f; return *this; } //! Returns a column. HPoint GetCol(const udword col) const { HPoint Res; Res.x = m[0][col]; Res.y = m[1][col]; Res.z = m[2][col]; Res.w = m[3][col]; return Res; } //! Sets a column. Matrix4x4& SetCol(const udword col, const HPoint& p) { m[0][col] = p.x; m[1][col] = p.y; m[2][col] = p.z; m[3][col] = p.w; return *this; } //! Sets a column. Matrix4x4& SetCol(const udword col, const Point& p) { m[0][col] = p.x; m[1][col] = p.y; m[2][col] = p.z; m[3][col] = (col != 3) ? 0.0f : 1.0f; return *this; } */ //! Computes the trace. The trace is the sum of the 4 diagonal components. inline_ float Trace() const { return m[0][0] + m[1][1] + m[2][2] + m[3][3]; } //! Computes the trace of the upper 3x3 matrix. inline_ float Trace3x3() const { return m[0][0] + m[1][1] + m[2][2]; } //! Clears the matrix. inline_ void Zero() { ZeroMemory(&m, sizeof(m)); } //! Sets the identity matrix. inline_ void Identity() { Zero(); m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0f; } //! Checks for identity inline_ bool IsIdentity() const { if(IR(m[0][0])!=IEEE_1_0) return false; if(IR(m[0][1])!=0) return false; if(IR(m[0][2])!=0) return false; if(IR(m[0][3])!=0) return false; if(IR(m[1][0])!=0) return false; if(IR(m[1][1])!=IEEE_1_0) return false; if(IR(m[1][2])!=0) return false; if(IR(m[1][3])!=0) return false; if(IR(m[2][0])!=0) return false; if(IR(m[2][1])!=0) return false; if(IR(m[2][2])!=IEEE_1_0) return false; if(IR(m[2][3])!=0) return false; if(IR(m[3][0])!=0) return false; if(IR(m[3][1])!=0) return false; if(IR(m[3][2])!=0) return false; if(IR(m[3][3])!=IEEE_1_0) return false; return true; } //! Checks matrix validity inline_ BOOL IsValid() const { for(udword j=0;j<4;j++) { for(udword i=0;i<4;i++) { if(!IsValidFloat(m[j][i])) return FALSE; } } return TRUE; } //! Sets a rotation matrix around the X axis. void RotX(float angle) { float Cos = cosf(angle), Sin = sinf(angle); Identity(); m[1][1] = m[2][2] = Cos; m[2][1] = -Sin; m[1][2] = Sin; } //! Sets a rotation matrix around the Y axis. void RotY(float angle) { float Cos = cosf(angle), Sin = sinf(angle); Identity(); m[0][0] = m[2][2] = Cos; m[2][0] = Sin; m[0][2] = -Sin; } //! Sets a rotation matrix around the Z axis. void RotZ(float angle) { float Cos = cosf(angle), Sin = sinf(angle); Identity(); m[0][0] = m[1][1] = Cos; m[1][0] = -Sin; m[0][1] = Sin; } //! Makes a rotation matrix about an arbitrary axis Matrix4x4& Rot(float angle, Point& p1, Point& p2); //! Transposes the matrix. void Transpose() { TSwap(m[1][0], m[0][1]); TSwap(m[2][0], m[0][2]); TSwap(m[3][0], m[0][3]); TSwap(m[1][2], m[2][1]); TSwap(m[1][3], m[3][1]); TSwap(m[2][3], m[3][2]); } //! Computes a cofactor. Used for matrix inversion. float CoFactor(udword row, udword col) const; //! Computes the determinant of the matrix. float Determinant() const; //! Inverts the matrix. Determinant must be different from zero, else matrix can't be inverted. Matrix4x4& Invert(); // Matrix& ComputeAxisMatrix(Point& axis, float angle); // Cast operators //! Casts a Matrix4x4 to a Matrix3x3. inline_ operator Matrix3x3() const { return Matrix3x3( m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], m[2][0], m[2][1], m[2][2]); } //! Casts a Matrix4x4 to a Quat. operator Quat() const; //! Casts a Matrix4x4 to a PR. operator PR() const; // Arithmetic operators //! Operator for Matrix4x4 Plus = Matrix4x4 + Matrix4x4; inline_ Matrix4x4 operator+(const Matrix4x4& mat) const { return Matrix4x4( m[0][0]+mat.m[0][0], m[0][1]+mat.m[0][1], m[0][2]+mat.m[0][2], m[0][3]+mat.m[0][3], m[1][0]+mat.m[1][0], m[1][1]+mat.m[1][1], m[1][2]+mat.m[1][2], m[1][3]+mat.m[1][3], m[2][0]+mat.m[2][0], m[2][1]+mat.m[2][1], m[2][2]+mat.m[2][2], m[2][3]+mat.m[2][3], m[3][0]+mat.m[3][0], m[3][1]+mat.m[3][1], m[3][2]+mat.m[3][2], m[3][3]+mat.m[3][3]); } //! Operator for Matrix4x4 Minus = Matrix4x4 - Matrix4x4; inline_ Matrix4x4 operator-(const Matrix4x4& mat) const { return Matrix4x4( m[0][0]-mat.m[0][0], m[0][1]-mat.m[0][1], m[0][2]-mat.m[0][2], m[0][3]-mat.m[0][3], m[1][0]-mat.m[1][0], m[1][1]-mat.m[1][1], m[1][2]-mat.m[1][2], m[1][3]-mat.m[1][3], m[2][0]-mat.m[2][0], m[2][1]-mat.m[2][1], m[2][2]-mat.m[2][2], m[2][3]-mat.m[2][3], m[3][0]-mat.m[3][0], m[3][1]-mat.m[3][1], m[3][2]-mat.m[3][2], m[3][3]-mat.m[3][3]); } //! Operator for Matrix4x4 Mul = Matrix4x4 * Matrix4x4; inline_ Matrix4x4 operator*(const Matrix4x4& mat) const { return Matrix4x4( m[0][0]*mat.m[0][0] + m[0][1]*mat.m[1][0] + m[0][2]*mat.m[2][0] + m[0][3]*mat.m[3][0], m[0][0]*mat.m[0][1] + m[0][1]*mat.m[1][1] + m[0][2]*mat.m[2][1] + m[0][3]*mat.m[3][1], m[0][0]*mat.m[0][2] + m[0][1]*mat.m[1][2] + m[0][2]*mat.m[2][2] + m[0][3]*mat.m[3][2], m[0][0]*mat.m[0][3] + m[0][1]*mat.m[1][3] + m[0][2]*mat.m[2][3] + m[0][3]*mat.m[3][3], m[1][0]*mat.m[0][0] + m[1][1]*mat.m[1][0] + m[1][2]*mat.m[2][0] + m[1][3]*mat.m[3][0], m[1][0]*mat.m[0][1] + m[1][1]*mat.m[1][1] + m[1][2]*mat.m[2][1] + m[1][3]*mat.m[3][1], m[1][0]*mat.m[0][2] + m[1][1]*mat.m[1][2] + m[1][2]*mat.m[2][2] + m[1][3]*mat.m[3][2], m[1][0]*mat.m[0][3] + m[1][1]*mat.m[1][3] + m[1][2]*mat.m[2][3] + m[1][3]*mat.m[3][3], m[2][0]*mat.m[0][0] + m[2][1]*mat.m[1][0] + m[2][2]*mat.m[2][0] + m[2][3]*mat.m[3][0], m[2][0]*mat.m[0][1] + m[2][1]*mat.m[1][1] + m[2][2]*mat.m[2][1] + m[2][3]*mat.m[3][1], m[2][0]*mat.m[0][2] + m[2][1]*mat.m[1][2] + m[2][2]*mat.m[2][2] + m[2][3]*mat.m[3][2], m[2][0]*mat.m[0][3] + m[2][1]*mat.m[1][3] + m[2][2]*mat.m[2][3] + m[2][3]*mat.m[3][3], m[3][0]*mat.m[0][0] + m[3][1]*mat.m[1][0] + m[3][2]*mat.m[2][0] + m[3][3]*mat.m[3][0], m[3][0]*mat.m[0][1] + m[3][1]*mat.m[1][1] + m[3][2]*mat.m[2][1] + m[3][3]*mat.m[3][1], m[3][0]*mat.m[0][2] + m[3][1]*mat.m[1][2] + m[3][2]*mat.m[2][2] + m[3][3]*mat.m[3][2], m[3][0]*mat.m[0][3] + m[3][1]*mat.m[1][3] + m[3][2]*mat.m[2][3] + m[3][3]*mat.m[3][3]); } //! Operator for HPoint Mul = Matrix4x4 * HPoint; inline_ HPoint operator*(const HPoint& v) const { return HPoint(GetRow(0)|v, GetRow(1)|v, GetRow(2)|v, GetRow(3)|v); } //! Operator for Point Mul = Matrix4x4 * Point; inline_ Point operator*(const Point& v) const { return Point( m[0][0]*v.x + m[0][1]*v.y + m[0][2]*v.z + m[0][3], m[1][0]*v.x + m[1][1]*v.y + m[1][2]*v.z + m[1][3], m[2][0]*v.x + m[2][1]*v.y + m[2][2]*v.z + m[2][3] ); } //! Operator for Matrix4x4 Scale = Matrix4x4 * float; inline_ Matrix4x4 operator*(float s) const { return Matrix4x4( m[0][0]*s, m[0][1]*s, m[0][2]*s, m[0][3]*s, m[1][0]*s, m[1][1]*s, m[1][2]*s, m[1][3]*s, m[2][0]*s, m[2][1]*s, m[2][2]*s, m[2][3]*s, m[3][0]*s, m[3][1]*s, m[3][2]*s, m[3][3]*s); } //! Operator for Matrix4x4 Scale = float * Matrix4x4; inline_ friend Matrix4x4 operator*(float s, const Matrix4x4& mat) { return Matrix4x4( s*mat.m[0][0], s*mat.m[0][1], s*mat.m[0][2], s*mat.m[0][3], s*mat.m[1][0], s*mat.m[1][1], s*mat.m[1][2], s*mat.m[1][3], s*mat.m[2][0], s*mat.m[2][1], s*mat.m[2][2], s*mat.m[2][3], s*mat.m[3][0], s*mat.m[3][1], s*mat.m[3][2], s*mat.m[3][3]); } //! Operator for Matrix4x4 Div = Matrix4x4 / float; inline_ Matrix4x4 operator/(float s) const { if(s) s = 1.0f / s; return Matrix4x4( m[0][0]*s, m[0][1]*s, m[0][2]*s, m[0][3]*s, m[1][0]*s, m[1][1]*s, m[1][2]*s, m[1][3]*s, m[2][0]*s, m[2][1]*s, m[2][2]*s, m[2][3]*s, m[3][0]*s, m[3][1]*s, m[3][2]*s, m[3][3]*s); } //! Operator for Matrix4x4 Div = float / Matrix4x4; inline_ friend Matrix4x4 operator/(float s, const Matrix4x4& mat) { return Matrix4x4( s/mat.m[0][0], s/mat.m[0][1], s/mat.m[0][2], s/mat.m[0][3], s/mat.m[1][0], s/mat.m[1][1], s/mat.m[1][2], s/mat.m[1][3], s/mat.m[2][0], s/mat.m[2][1], s/mat.m[2][2], s/mat.m[2][3], s/mat.m[3][0], s/mat.m[3][1], s/mat.m[3][2], s/mat.m[3][3]); } //! Operator for Matrix4x4 += Matrix4x4; inline_ Matrix4x4& operator+=(const Matrix4x4& mat) { m[0][0]+=mat.m[0][0]; m[0][1]+=mat.m[0][1]; m[0][2]+=mat.m[0][2]; m[0][3]+=mat.m[0][3]; m[1][0]+=mat.m[1][0]; m[1][1]+=mat.m[1][1]; m[1][2]+=mat.m[1][2]; m[1][3]+=mat.m[1][3]; m[2][0]+=mat.m[2][0]; m[2][1]+=mat.m[2][1]; m[2][2]+=mat.m[2][2]; m[2][3]+=mat.m[2][3]; m[3][0]+=mat.m[3][0]; m[3][1]+=mat.m[3][1]; m[3][2]+=mat.m[3][2]; m[3][3]+=mat.m[3][3]; return *this; } //! Operator for Matrix4x4 -= Matrix4x4; inline_ Matrix4x4& operator-=(const Matrix4x4& mat) { m[0][0]-=mat.m[0][0]; m[0][1]-=mat.m[0][1]; m[0][2]-=mat.m[0][2]; m[0][3]-=mat.m[0][3]; m[1][0]-=mat.m[1][0]; m[1][1]-=mat.m[1][1]; m[1][2]-=mat.m[1][2]; m[1][3]-=mat.m[1][3]; m[2][0]-=mat.m[2][0]; m[2][1]-=mat.m[2][1]; m[2][2]-=mat.m[2][2]; m[2][3]-=mat.m[2][3]; m[3][0]-=mat.m[3][0]; m[3][1]-=mat.m[3][1]; m[3][2]-=mat.m[3][2]; m[3][3]-=mat.m[3][3]; return *this; } //! Operator for Matrix4x4 *= Matrix4x4; Matrix4x4& operator*=(const Matrix4x4& mat) { HPoint TempRow; GetRow(0, TempRow); m[0][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0]; m[0][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1]; m[0][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2]; m[0][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3]; GetRow(1, TempRow); m[1][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0]; m[1][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1]; m[1][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2]; m[1][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3]; GetRow(2, TempRow); m[2][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0]; m[2][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1]; m[2][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2]; m[2][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3]; GetRow(3, TempRow); m[3][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0]; m[3][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1]; m[3][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2]; m[3][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3]; return *this; } //! Operator for Matrix4x4 *= float; inline_ Matrix4x4& operator*=(float s) { m[0][0]*=s; m[0][1]*=s; m[0][2]*=s; m[0][3]*=s; m[1][0]*=s; m[1][1]*=s; m[1][2]*=s; m[1][3]*=s; m[2][0]*=s; m[2][1]*=s; m[2][2]*=s; m[2][3]*=s; m[3][0]*=s; m[3][1]*=s; m[3][2]*=s; m[3][3]*=s; return *this; } //! Operator for Matrix4x4 /= float; inline_ Matrix4x4& operator/=(float s) { if(s) s = 1.0f / s; m[0][0]*=s; m[0][1]*=s; m[0][2]*=s; m[0][3]*=s; m[1][0]*=s; m[1][1]*=s; m[1][2]*=s; m[1][3]*=s; m[2][0]*=s; m[2][1]*=s; m[2][2]*=s; m[2][3]*=s; m[3][0]*=s; m[3][1]*=s; m[3][2]*=s; m[3][3]*=s; return *this; } inline_ const HPoint& operator[](int row) const { return *(const HPoint*)&m[row][0]; } inline_ HPoint& operator[](int row) { return *(HPoint*)&m[row][0]; } public: float m[4][4]; }; //! Quickly rotates & translates a vector, using the 4x3 part of a 4x4 matrix inline_ void TransformPoint4x3(Point& dest, const Point& source, const Matrix4x4& rot) { dest.x = rot.m[3][0] + source.x * rot.m[0][0] + source.y * rot.m[1][0] + source.z * rot.m[2][0]; dest.y = rot.m[3][1] + source.x * rot.m[0][1] + source.y * rot.m[1][1] + source.z * rot.m[2][1]; dest.z = rot.m[3][2] + source.x * rot.m[0][2] + source.y * rot.m[1][2] + source.z * rot.m[2][2]; } //! Quickly rotates a vector, using the 3x3 part of a 4x4 matrix inline_ void TransformPoint3x3(Point& dest, const Point& source, const Matrix4x4& rot) { dest.x = source.x * rot.m[0][0] + source.y * rot.m[1][0] + source.z * rot.m[2][0]; dest.y = source.x * rot.m[0][1] + source.y * rot.m[1][1] + source.z * rot.m[2][1]; dest.z = source.x * rot.m[0][2] + source.y * rot.m[1][2] + source.z * rot.m[2][2]; } ICEMATHS_API void InvertPRMatrix(Matrix4x4& dest, const Matrix4x4& src); #endif // __ICEMATRIX4X4_H__ ode-0.16/OPCODE/Ice/IceHPoint.h0000664000175200017520000001634613403272463012620 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains code for homogeneous points. * \file IceHPoint.h * \author Pierre Terdiman * \date April, 4, 2000 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Include Guard #ifndef __ICEHPOINT_H__ #define __ICEHPOINT_H__ class ICEMATHS_API HPoint : public Point { public: //! Empty constructor inline_ HPoint() {} //! Constructor from floats inline_ HPoint(float xx, float yy, float zz, float ww=0.0f) : Point(xx, yy, zz), w(ww) {} //! Constructor from array inline_ HPoint(const float f[4]) : Point(f), w(f[3]) {} //! Constructor from a Point inline_ HPoint(const Point& p, float ww=0.0f) : Point(p), w(ww) {} //! Destructor inline_ ~HPoint() {} //! Clear the point inline_ HPoint& Zero() { x = y = z = w = 0.0f; return *this; } //! Assignment from values inline_ HPoint& Set(float xx, float yy, float zz, float ww ) { x = xx; y = yy; z = zz; w = ww; return *this; } //! Assignment from array inline_ HPoint& Set(const float f[4]) { x = f[X]; y = f[Y]; z = f[Z]; w = f[W]; return *this; } //! Assignment from another h-point inline_ HPoint& Set(const HPoint& src) { x = src.x; y = src.y; z = src.z; w = src.w; return *this; } //! Add a vector inline_ HPoint& Add(float xx, float yy, float zz, float ww ) { x += xx; y += yy; z += zz; w += ww; return *this; } //! Add a vector inline_ HPoint& Add(const float f[4]) { x += f[X]; y += f[Y]; z += f[Z]; w += f[W]; return *this; } //! Subtract a vector inline_ HPoint& Sub(float xx, float yy, float zz, float ww ) { x -= xx; y -= yy; z -= zz; w -= ww; return *this; } //! Subtract a vector inline_ HPoint& Sub(const float f[4]) { x -= f[X]; y -= f[Y]; z -= f[Z]; w -= f[W]; return *this; } //! Multiplies by a scalar inline_ HPoint& Mul(float s) { x *= s; y *= s; z *= s; w *= s; return *this; } //! Returns MIN(x, y, z, w); float Min() const { return MIN(x, MIN(y, MIN(z, w))); } //! Returns MAX(x, y, z, w); float Max() const { return MAX(x, MAX(y, MAX(z, w))); } //! Sets each element to be componentwise minimum HPoint& Min(const HPoint& p) { x = MIN(x, p.x); y = MIN(y, p.y); z = MIN(z, p.z); w = MIN(w, p.w); return *this; } //! Sets each element to be componentwise maximum HPoint& Max(const HPoint& p) { x = MAX(x, p.x); y = MAX(y, p.y); z = MAX(z, p.z); w = MAX(w, p.w); return *this; } //! Computes square magnitude inline_ float SquareMagnitude() const { return x*x + y*y + z*z + w*w; } //! Computes magnitude inline_ float Magnitude() const { return sqrtf(x*x + y*y + z*z + w*w); } //! Normalize the vector inline_ HPoint& Normalize() { float M = Magnitude(); if(M) { M = 1.0f / M; x *= M; y *= M; z *= M; w *= M; } return *this; } // Arithmetic operators //! Operator for HPoint Negate = - HPoint; inline_ HPoint operator-() const { return HPoint(-x, -y, -z, -w); } //! Operator for HPoint Plus = HPoint + HPoint; inline_ HPoint operator+(const HPoint& p) const { return HPoint(x + p.x, y + p.y, z + p.z, w + p.w); } //! Operator for HPoint Minus = HPoint - HPoint; inline_ HPoint operator-(const HPoint& p) const { return HPoint(x - p.x, y - p.y, z - p.z, w - p.w); } //! Operator for HPoint Mul = HPoint * HPoint; inline_ HPoint operator*(const HPoint& p) const { return HPoint(x * p.x, y * p.y, z * p.z, w * p.w); } //! Operator for HPoint Scale = HPoint * float; inline_ HPoint operator*(float s) const { return HPoint(x * s, y * s, z * s, w * s); } //! Operator for HPoint Scale = float * HPoint; inline_ friend HPoint operator*(float s, const HPoint& p) { return HPoint(s * p.x, s * p.y, s * p.z, s * p.w); } //! Operator for HPoint Div = HPoint / HPoint; inline_ HPoint operator/(const HPoint& p) const { return HPoint(x / p.x, y / p.y, z / p.z, w / p.w); } //! Operator for HPoint Scale = HPoint / float; inline_ HPoint operator/(float s) const { s = 1.0f / s; return HPoint(x * s, y * s, z * s, w * s); } //! Operator for HPoint Scale = float / HPoint; inline_ friend HPoint operator/(float s, const HPoint& p) { return HPoint(s / p.x, s / p.y, s / p.z, s / p.w); } //! Operator for float DotProd = HPoint | HPoint; inline_ float operator|(const HPoint& p) const { return x*p.x + y*p.y + z*p.z + w*p.w; } // No cross-product in 4D //! Operator for HPoint += HPoint; inline_ HPoint& operator+=(const HPoint& p) { x += p.x; y += p.y; z += p.z; w += p.w; return *this; } //! Operator for HPoint += float; inline_ HPoint& operator+=(float s) { x += s; y += s; z += s; w += s; return *this; } //! Operator for HPoint -= HPoint; inline_ HPoint& operator-=(const HPoint& p) { x -= p.x; y -= p.y; z -= p.z; w -= p.w; return *this; } //! Operator for HPoint -= float; inline_ HPoint& operator-=(float s) { x -= s; y -= s; z -= s; w -= s; return *this; } //! Operator for HPoint *= HPoint; inline_ HPoint& operator*=(const HPoint& p) { x *= p.x; y *= p.y; z *= p.z; w *= p.w; return *this; } //! Operator for HPoint *= float; inline_ HPoint& operator*=(float s) { x*=s; y*=s; z*=s; w*=s; return *this; } //! Operator for HPoint /= HPoint; inline_ HPoint& operator/=(const HPoint& p) { x /= p.x; y /= p.y; z /= p.z; w /= p.w; return *this; } //! Operator for HPoint /= float; inline_ HPoint& operator/=(float s) { s = 1.0f / s; x*=s; y*=s; z*=s; w*=s; return *this; } // Arithmetic operators //! Operator for Point Mul = HPoint * Matrix3x3; Point operator*(const Matrix3x3& mat) const; //! Operator for HPoint Mul = HPoint * Matrix4x4; HPoint operator*(const Matrix4x4& mat) const; // HPoint *= Matrix3x3 doesn't exist, the matrix is first casted to a 4x4 //! Operator for HPoint *= Matrix4x4 HPoint& operator*=(const Matrix4x4& mat); // Logical operators //! Operator for "if(HPoint==HPoint)" inline_ bool operator==(const HPoint& p) const { return ( (x==p.x)&&(y==p.y)&&(z==p.z)&&(w==p.w)); } //! Operator for "if(HPoint!=HPoint)" inline_ bool operator!=(const HPoint& p) const { return ( (x!=p.x)||(y!=p.y)||(z!=p.z)||(w!=p.w)); } // Cast operators //! Cast a HPoint to a Point. w is discarded. #ifdef _MSC_VER inline_ operator Point() const { return Point(x, y, z); } // gcc complains that conversion to a base class will never use a type conversion operator #endif public: float w; }; #endif // __ICEHPOINT_H__ ode-0.16/OPCODE/Ice/IceAxes.h0000664000175200017520000000264313403272463012312 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains axes definition. * \file IceAxes.h * \author Pierre Terdiman * \date January, 29, 2000 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Include Guard #ifndef __ICEAXES_H__ #define __ICEAXES_H__ enum PointComponent { X = 0, Y = 1, Z = 2, W = 3, FORCE_DWORD = 0x7fffffff }; enum AxisOrder { AXES_XYZ = (X)|(Y<<2)|(Z<<4), AXES_XZY = (X)|(Z<<2)|(Y<<4), AXES_YXZ = (Y)|(X<<2)|(Z<<4), AXES_YZX = (Y)|(Z<<2)|(X<<4), AXES_ZXY = (Z)|(X<<2)|(Y<<4), AXES_ZYX = (Z)|(Y<<2)|(X<<4), AXES_FORCE_DWORD = 0x7fffffff }; class ICEMATHS_API Axes { public: inline_ Axes(AxisOrder order) { mAxis0 = (order ) & 3; mAxis1 = (order>>2) & 3; mAxis2 = (order>>4) & 3; } inline_ ~Axes() {} udword mAxis0; udword mAxis1; udword mAxis2; }; #endif // __ICEAXES_H__ ode-0.16/OPCODE/Ice/IceOBB.h0000664000175200017520000002300013403272463012002 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains OBB-related code. (oriented bounding box) * \file IceOBB.h * \author Pierre Terdiman * \date January, 13, 2000 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Include Guard #ifndef __ICEOBB_H__ #define __ICEOBB_H__ // Forward declarations class LSS; class ICEMATHS_API OBB { public: //! Constructor inline_ OBB() {} //! Constructor inline_ OBB(const Point& center, const Point& extents, const Matrix3x3& rot) : mCenter(center), mExtents(extents), mRot(rot) {} //! Destructor inline_ ~OBB() {} /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Setups an empty OBB. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void SetEmpty() { mCenter.Zero(); mExtents.Set(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT); mRot.Identity(); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Tests if a point is contained within the OBB. * \param p [in] the world point to test * \return true if inside the OBB */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool ContainsPoint(const Point& p) const; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Builds an OBB from an AABB and a world transform. * \param aabb [in] the aabb * \param mat [in] the world transform */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void Create(const AABB& aabb, const Matrix4x4& mat); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recomputes the OBB after an arbitrary transform by a 4x4 matrix. * \param mtx [in] the transform matrix * \param obb [out] the transformed OBB */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ void Rotate(const Matrix4x4& mtx, OBB& obb) const { // The extents remain constant obb.mExtents = mExtents; // The center gets x-formed obb.mCenter = mCenter * mtx; // Combine rotations obb.mRot = mRot * Matrix3x3(mtx); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Checks the OBB is valid. * \return true if the box is valid */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ BOOL IsValid() const { // Consistency condition for (Center, Extents) boxes: Extents >= 0.0f if(mExtents.x < 0.0f) return FALSE; if(mExtents.y < 0.0f) return FALSE; if(mExtents.z < 0.0f) return FALSE; return TRUE; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the obb planes. * \param planes [out] 6 box planes * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool ComputePlanes(Plane* planes) const; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the obb points. * \param pts [out] 8 box points * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool ComputePoints(Point* pts) const; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes vertex normals. * \param pts [out] 8 box points * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool ComputeVertexNormals(Point* pts) const; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Returns edges. * \return 24 indices (12 edges) indexing the list returned by ComputePoints() */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// const udword* GetEdges() const; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Returns local edge normals. * \return edge normals in local space */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// const Point* GetLocalEdgeNormals() const; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Returns world edge normal * \param edge_index [in] 0 <= edge index < 12 * \param world_normal [out] edge normal in world space */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ComputeWorldEdgeNormal(udword edge_index, Point& world_normal) const; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes an LSS surrounding the OBB. * \param lss [out] the LSS */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ComputeLSS(LSS& lss) const; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Checks the OBB is inside another OBB. * \param box [in] the other OBB * \return TRUE if we're inside the other box */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// BOOL IsInside(const OBB& box) const; inline_ const Point& GetCenter() const { return mCenter; } inline_ const Point& GetExtents() const { return mExtents; } inline_ const Matrix3x3& GetRot() const { return mRot; } inline_ void GetRotatedExtents(Matrix3x3& extents) const { extents = mRot; extents.Scale(mExtents); } Point mCenter; //!< B for Box Point mExtents; //!< B for Bounding Matrix3x3 mRot; //!< O for Oriented // Orientation is stored in row-major format, // i.e. rows = eigen vectors of the covariance matrix }; #endif // __ICEOBB_H__ ode-0.16/OPCODE/Ice/IceRandom.cpp0000664000175200017520000000213613403272463013162 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains code for random generators. * \file IceRandom.cpp * \author Pierre Terdiman * \date August, 9, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Precompiled Header #include "Stdafx.h" using namespace IceCore; void IceCore:: SRand(udword seed) { srand(seed); } udword IceCore::Rand() { return rand(); } static BasicRandom gRandomGenerator(42); udword IceCore::GetRandomIndex(udword max_index) { // We don't use rand() since it's limited to RAND_MAX udword Index = gRandomGenerator.Randomize(); return Index % max_index; } ode-0.16/OPCODE/Ice/IceContainer.cpp0000664000175200017520000003413413403272463013667 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains a simple container class. * \file IceContainer.cpp * \author Pierre Terdiman * \date February, 5, 2000 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains a list of 32-bits values. * Use this class when you need to store an unknown number of values. The list is automatically * resized and can contains 32-bits entities (dwords or floats) * * \class Container * \author Pierre Terdiman * \version 1.0 * \date 08.15.98 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Precompiled Header #include "Stdafx.h" using namespace IceCore; #define MAX_RESERVE_GROWTH_SIZE 65536U // Static members #ifdef CONTAINER_STATS udword Container::mNbContainers = 0; udword Container::mUsedRam = 0; #endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Constructor. No entries allocated there. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Container::Container() : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null), mGrowthFactor(2) { #ifdef CONTAINER_STATS mNbContainers++; mUsedRam+=sizeof(Container); #endif } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Constructor. Also allocates a given number of entries. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Container::Container(udword size, float growth_factor) : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null), mGrowthFactor(growth_factor) { #ifdef CONTAINER_STATS mNbContainers++; mUsedRam+=sizeof(Container); #endif SetSize(size); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Copy constructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Container::Container(const Container& object) : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null), mGrowthFactor(2) { #ifdef CONTAINER_STATS mNbContainers++; mUsedRam+=sizeof(Container); #endif *this = object; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Destructor. Frees everything and leaves. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Container::~Container() { Empty(); #ifdef CONTAINER_STATS mNbContainers--; mUsedRam-=GetUsedRam(); #endif } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Clears the container. All stored values are deleted, and it frees used ram. * \see Reset() * \return Self-Reference */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Container& Container::Empty() { #ifdef CONTAINER_STATS mUsedRam-=mMaxNbEntries*sizeof(udword); #endif DELETEARRAY(mEntries); mCurNbEntries = mMaxNbEntries = 0; return *this; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Resizes the container. * \param needed [in] assume the container can be added at least "needed" values * \return true if success. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool Container::Resize(udword needed) { #ifdef CONTAINER_STATS // Subtract previous amount of bytes mUsedRam-=mMaxNbEntries*sizeof(udword); #endif if (MAX_UDWORD - mCurNbEntries < needed) { CHECKALLOC(null); } // Get more entries udword NewMaxNbEntries = mMaxNbEntries ? udword(mMaxNbEntries * mGrowthFactor) : 2; // Default nb Entries = 2 if (NewMaxNbEntries <= mMaxNbEntries) NewMaxNbEntries = MAX_UDWORD - mMaxNbEntries < MAX_RESERVE_GROWTH_SIZE ? MAX_UDWORD : mMaxNbEntries + MAX_RESERVE_GROWTH_SIZE; else if (NewMaxNbEntries - mMaxNbEntries > MAX_RESERVE_GROWTH_SIZE) NewMaxNbEntries = mMaxNbEntries + MAX_RESERVE_GROWTH_SIZE; if (NewMaxNbEntries < mCurNbEntries + needed) NewMaxNbEntries = mCurNbEntries + needed; // Get some bytes for new entries udword* NewEntries = new udword[NewMaxNbEntries]; CHECKALLOC(NewEntries); // Copy old data if needed if(mCurNbEntries) CopyMemory(NewEntries, mEntries, mCurNbEntries*sizeof(udword)); // Delete old data DELETEARRAY(mEntries); // Assign new pointer mEntries = NewEntries; mMaxNbEntries = NewMaxNbEntries; #ifdef CONTAINER_STATS // Add current amount of bytes mUsedRam+=mMaxNbEntries*sizeof(udword); #endif return true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Sets the initial size of the container. If it already contains something, it's discarded. * \param nb [in] Number of entries * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool Container::SetSize(udword nb) { // Make sure it's empty Empty(); // Checkings if(!nb) return false; // Initialize for nb entries mMaxNbEntries = nb; // Get some bytes for new entries mEntries = new udword[mMaxNbEntries]; CHECKALLOC(mEntries); #ifdef CONTAINER_STATS // Add current amount of bytes mUsedRam+=mMaxNbEntries*sizeof(udword); #endif return true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Refits the container and get rid of unused bytes. * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool Container::Refit() { #ifdef CONTAINER_STATS // Subtract previous amount of bytes mUsedRam-=mMaxNbEntries*sizeof(udword); #endif // Get just enough entries mMaxNbEntries = mCurNbEntries; if(!mMaxNbEntries) return false; // Get just enough bytes udword* NewEntries = new udword[mMaxNbEntries]; CHECKALLOC(NewEntries); #ifdef CONTAINER_STATS // Add current amount of bytes mUsedRam+=mMaxNbEntries*sizeof(udword); #endif // Copy old data CopyMemory(NewEntries, mEntries, mCurNbEntries*sizeof(udword)); // Delete old data DELETEARRAY(mEntries); // Assign new pointer mEntries = NewEntries; return true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Checks whether the container already contains a given value. * \param entry [in] the value to look for in the container * \param location [out] a possible pointer to store the entry location * \see Add(udword entry) * \see Add(float entry) * \see Empty() * \return true if the value has been found in the container, else false. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool Container::Contains(udword entry, udword* location) const { // Look for the entry for(udword i=0;i&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = OPCODE/Ice ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/ode/src/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libIce_la_LIBADD = am_libIce_la_OBJECTS = IceAABB.lo IceContainer.lo IceHPoint.lo \ IceIndexedTriangle.lo IceMatrix3x3.lo IceMatrix4x4.lo \ IceOBB.lo IcePlane.lo IcePoint.lo IceRandom.lo IceRay.lo \ IceRevisitedRadix.lo IceSegment.lo IceTriangle.lo IceUtils.lo libIce_la_OBJECTS = $(am_libIce_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/ode/src depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) AM_V_CXX = $(am__v_CXX_@AM_V@) am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libIce_la_SOURCES) DIST_SOURCES = $(libIce_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CCD_CFLAGS = @CCD_CFLAGS@ CCD_LIBS = @CCD_LIBS@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXTRA_LIBTOOL_LDFLAGS = @EXTRA_LIBTOOL_LDFLAGS@ FGREP = @FGREP@ GL_LIBS = @GL_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSTDCXX = @LIBSTDCXX@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ ODE_PRECISION = @ODE_PRECISION@ ODE_VERSION = @ODE_VERSION@ ODE_VERSION_INFO = @ODE_VERSION_INFO@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ WINDRES = @WINDRES@ X11_CFLAGS = @X11_CFLAGS@ X11_LIBS = @X11_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_WINDRES = @ac_ct_WINDRES@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/OPCODE \ -I$(top_srcdir)/include \ -I$(top_builddir)/include noinst_LTLIBRARIES = libIce.la libIce_la_SOURCES = \ IceAABB.cpp IceAABB.h IceAxes.h \ IceBoundingSphere.h IceContainer.cpp IceContainer.h \ IceFPU.h IceHPoint.cpp IceHPoint.h \ IceIndexedTriangle.cpp IceIndexedTriangle.h IceLSS.h \ IceMatrix3x3.cpp IceMatrix3x3.h IceMatrix4x4.cpp \ IceMatrix4x4.h IceMemoryMacros.h IceOBB.cpp \ IceOBB.h IcePairs.h IcePlane.cpp \ IcePlane.h IcePoint.cpp IcePoint.h \ IcePreprocessor.h IceRandom.cpp IceRandom.h \ IceRay.cpp IceRay.h IceRevisitedRadix.cpp \ IceRevisitedRadix.h IceSegment.cpp IceSegment.h \ IceTriangle.cpp IceTriangle.h IceTriList.h \ IceTypes.h IceUtils.cpp IceUtils.h all: all-am .SUFFIXES: .SUFFIXES: .cpp .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign OPCODE/Ice/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign OPCODE/Ice/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libIce.la: $(libIce_la_OBJECTS) $(libIce_la_DEPENDENCIES) $(EXTRA_libIce_la_DEPENDENCIES) $(AM_V_CXXLD)$(CXXLINK) $(libIce_la_OBJECTS) $(libIce_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IceAABB.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IceContainer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IceHPoint.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IceIndexedTriangle.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IceMatrix3x3.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IceMatrix4x4.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IceOBB.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IcePlane.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IcePoint.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IceRandom.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IceRay.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IceRevisitedRadix.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IceSegment.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IceTriangle.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IceUtils.Plo@am__quote@ .cpp.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cpp.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cpp.lo: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ode-0.16/OPCODE/Ice/IceBoundingSphere.h0000664000175200017520000001540613403272463014327 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains code to compute the minimal bounding sphere. * \file IceBoundingSphere.h * \author Pierre Terdiman * \date January, 29, 2000 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Include Guard #ifndef __ICEBOUNDINGSPHERE_H__ #define __ICEBOUNDINGSPHERE_H__ enum BSphereMethod { BS_NONE, BS_GEMS, BS_MINIBALL, BS_FORCE_DWORD = 0x7fffffff }; class ICEMATHS_API Sphere { public: //! Constructor inline_ Sphere() {} //! Constructor inline_ Sphere(const Point& center, float radius) : mCenter(center), mRadius(radius) {} //! Constructor Sphere(udword nb_verts, const Point* verts); //! Copy constructor inline_ Sphere(const Sphere& sphere) : mCenter(sphere.mCenter), mRadius(sphere.mRadius) {} //! Destructor inline_ ~Sphere() {} BSphereMethod Compute(udword nb_verts, const Point* verts); bool FastCompute(udword nb_verts, const Point* verts); // Access methods inline_ const Point& GetCenter() const { return mCenter; } inline_ float GetRadius() const { return mRadius; } inline_ const Point& Center() const { return mCenter; } inline_ float Radius() const { return mRadius; } inline_ Sphere& Set(const Point& center, float radius) { mCenter = center; mRadius = radius; return *this; } inline_ Sphere& SetCenter(const Point& center) { mCenter = center; return *this; } inline_ Sphere& SetRadius(float radius) { mRadius = radius; return *this; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Tests if a point is contained within the sphere. * \param p [in] the point to test * \return true if inside the sphere */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ bool Contains(const Point& p) const { return mCenter.SquareDistance(p) <= mRadius*mRadius; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Tests if a sphere is contained within the sphere. * \param sphere [in] the sphere to test * \return true if inside the sphere */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ bool Contains(const Sphere& sphere) const { // If our radius is the smallest, we can't possibly contain the other sphere if(mRadius < sphere.mRadius) return false; // So r is always positive or null now float r = mRadius - sphere.mRadius; return mCenter.SquareDistance(sphere.mCenter) <= r*r; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Tests if a box is contained within the sphere. * \param aabb [in] the box to test * \return true if inside the sphere */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ BOOL Contains(const AABB& aabb) const { // I assume if all 8 box vertices are inside the sphere, so does the whole box. // Sounds ok but maybe there's a better way? float R2 = mRadius * mRadius; #ifdef USE_MIN_MAX const Point& Max = ((ShadowAABB&)&aabb).mMax; const Point& Min = ((ShadowAABB&)&aabb).mMin; #else Point Max; aabb.GetMax(Max); Point Min; aabb.GetMin(Min); #endif Point p; p.x=Max.x; p.y=Max.y; p.z=Max.z; if(mCenter.SquareDistance(p)>=R2) return FALSE; p.x=Min.x; if(mCenter.SquareDistance(p)>=R2) return FALSE; p.x=Max.x; p.y=Min.y; if(mCenter.SquareDistance(p)>=R2) return FALSE; p.x=Min.x; if(mCenter.SquareDistance(p)>=R2) return FALSE; p.x=Max.x; p.y=Max.y; p.z=Min.z; if(mCenter.SquareDistance(p)>=R2) return FALSE; p.x=Min.x; if(mCenter.SquareDistance(p)>=R2) return FALSE; p.x=Max.x; p.y=Min.y; if(mCenter.SquareDistance(p)>=R2) return FALSE; p.x=Min.x; if(mCenter.SquareDistance(p)>=R2) return FALSE; return TRUE; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Tests if the sphere intersects another sphere * \param sphere [in] the other sphere * \return true if spheres overlap */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ bool Intersect(const Sphere& sphere) const { float r = mRadius + sphere.mRadius; return mCenter.SquareDistance(sphere.mCenter) <= r*r; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Checks the sphere is valid. * \return true if the box is valid */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ BOOL IsValid() const { // Consistency condition for spheres: Radius >= 0.0f if(mRadius < 0.0f) return FALSE; return TRUE; } public: Point mCenter; //!< Sphere center float mRadius; //!< Sphere radius }; #endif // __ICEBOUNDINGSPHERE_H__ ode-0.16/OPCODE/Ice/IceAABB.h0000664000175200017520000006145013403272463012100 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains AABB-related code. (axis-aligned bounding box) * \file IceAABB.h * \author Pierre Terdiman * \date January, 13, 2000 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Include Guard #ifndef __ICEAABB_H__ #define __ICEAABB_H__ // Forward declarations class Sphere; //! Declarations of type-independent methods (most of them implemented in the .cpp) #define AABB_COMMON_METHODS \ AABB& Add(const AABB& aabb); \ float MakeCube(AABB& cube) const; \ void MakeSphere(Sphere& sphere) const; \ const sbyte* ComputeOutline(const Point& local_eye, sdword& num) const; \ float ComputeBoxArea(const Point& eye, const Matrix4x4& mat, float width, float height, sdword& num) const; \ bool IsInside(const AABB& box) const; \ bool ComputePlanes(Plane* planes) const; \ bool ComputePoints(Point* pts) const; \ const Point* GetVertexNormals() const; \ const udword* GetEdges() const; \ const Point* GetEdgeNormals() const; \ inline_ BOOL ContainsPoint(const Point& p) const \ { \ if(p.x > GetMax(0) || p.x < GetMin(0)) return FALSE; \ if(p.y > GetMax(1) || p.y < GetMin(1)) return FALSE; \ if(p.z > GetMax(2) || p.z < GetMin(2)) return FALSE; \ return TRUE; \ } enum AABBType { AABB_RENDER = 0, //!< AABB used for rendering. Not visible == not rendered. AABB_UPDATE = 1, //!< AABB used for dynamic updates. Not visible == not updated. AABB_FORCE_DWORD = 0x7fffffff, }; #ifdef USE_MINMAX struct ICEMATHS_API ShadowAABB { Point mMin; Point mMax; }; class ICEMATHS_API AABB { public: //! Constructor inline_ AABB() {} //! Destructor inline_ ~AABB() {} //! Type-independent methods AABB_COMMON_METHODS; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Setups an AABB from min & max vectors. * \param min [in] the min point * \param max [in] the max point */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void SetMinMax(const Point& min, const Point& max) { mMin = min; mMax = max; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Setups an AABB from center & extents vectors. * \param c [in] the center point * \param e [in] the extents vector */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void SetCenterExtents(const Point& c, const Point& e) { mMin = c - e; mMax = c + e; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Setups an empty AABB. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void SetEmpty() { Point p(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT); mMin = -p; mMax = p;} /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Setups a point AABB. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void SetPoint(const Point& pt) { mMin = mMax = pt; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Gets the size of the AABB. The size is defined as the longest extent. * \return the size of the AABB */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// float GetSize() const { Point e; GetExtents(e); return e.Max(); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Extends the AABB. * \param p [in] the next point */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void Extend(const Point& p) { if(p.x > mMax.x) mMax.x = p.x; if(p.x < mMin.x) mMin.x = p.x; if(p.y > mMax.y) mMax.y = p.y; if(p.y < mMin.y) mMin.y = p.y; if(p.z > mMax.z) mMax.z = p.z; if(p.z < mMin.z) mMin.z = p.z; } // Data access //! Get min point of the box inline_ void GetMin(Point& min) const { min = mMin; } //! Get max point of the box inline_ void GetMax(Point& max) const { max = mMax; } //! Get component of the box's min point along a given axis inline_ float GetMin(udword axis) const { return mMin[axis]; } //! Get component of the box's max point along a given axis inline_ float GetMax(udword axis) const { return mMax[axis]; } //! Get box center inline_ void GetCenter(Point& center) const { center = (mMax + mMin)*0.5f; } //! Get box extents inline_ void GetExtents(Point& extents) const { extents = (mMax - mMin)*0.5f; } //! Get component of the box's center along a given axis inline_ float GetCenter(udword axis) const { return (mMax[axis] + mMin[axis])*0.5f; } //! Get component of the box's extents along a given axis inline_ float GetExtents(udword axis) const { return (mMax[axis] - mMin[axis])*0.5f; } //! Get box diagonal inline_ void GetDiagonal(Point& diagonal) const { diagonal = mMax - mMin; } inline_ float GetWidth() const { return mMax.x - mMin.x; } inline_ float GetHeight() const { return mMax.y - mMin.y; } inline_ float GetDepth() const { return mMax.z - mMin.z; } //! Volume inline_ float GetVolume() const { return GetWidth() * GetHeight() * GetDepth(); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the intersection between two AABBs. * \param a [in] the other AABB * \return true on intersection */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ BOOL Intersect(const AABB& a) const { if(mMax.x < a.mMin.x || a.mMax.x < mMin.x || mMax.y < a.mMin.y || a.mMax.y < mMin.y || mMax.z < a.mMin.z || a.mMax.z < mMin.z) return FALSE; return TRUE; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the 1D-intersection between two AABBs, on a given axis. * \param a [in] the other AABB * \param axis [in] the axis (0, 1, 2) * \return true on intersection */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ BOOL Intersect(const AABB& a, udword axis) const { if(mMax[axis] < a.mMin[axis] || a.mMax[axis] < mMin[axis]) return FALSE; return TRUE; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recomputes the AABB after an arbitrary transform by a 4x4 matrix. * Original code by Charles Bloom on the GD-Algorithm list. (I slightly modified it) * \param mtx [in] the transform matrix * \param aabb [out] the transformed AABB [can be *this] */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ void Rotate(const Matrix4x4& mtx, AABB& aabb) const { // The three edges transformed: you can efficiently transform an X-only vector // by just getting the "X" column of the matrix Point vx,vy,vz; mtx.GetRow(0, vx); vx *= (mMax.x - mMin.x); mtx.GetRow(1, vy); vy *= (mMax.y - mMin.y); mtx.GetRow(2, vz); vz *= (mMax.z - mMin.z); // Transform the min point aabb.mMin = aabb.mMax = mMin * mtx; // Take the transformed min & axes and find new extents // Using CPU code in the right place is faster... if(IS_NEGATIVE_FLOAT(vx.x)) aabb.mMin.x += vx.x; else aabb.mMax.x += vx.x; if(IS_NEGATIVE_FLOAT(vx.y)) aabb.mMin.y += vx.y; else aabb.mMax.y += vx.y; if(IS_NEGATIVE_FLOAT(vx.z)) aabb.mMin.z += vx.z; else aabb.mMax.z += vx.z; if(IS_NEGATIVE_FLOAT(vy.x)) aabb.mMin.x += vy.x; else aabb.mMax.x += vy.x; if(IS_NEGATIVE_FLOAT(vy.y)) aabb.mMin.y += vy.y; else aabb.mMax.y += vy.y; if(IS_NEGATIVE_FLOAT(vy.z)) aabb.mMin.z += vy.z; else aabb.mMax.z += vy.z; if(IS_NEGATIVE_FLOAT(vz.x)) aabb.mMin.x += vz.x; else aabb.mMax.x += vz.x; if(IS_NEGATIVE_FLOAT(vz.y)) aabb.mMin.y += vz.y; else aabb.mMax.y += vz.y; if(IS_NEGATIVE_FLOAT(vz.z)) aabb.mMin.z += vz.z; else aabb.mMax.z += vz.z; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Checks the AABB is valid. * \return true if the box is valid */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ BOOL IsValid() const { // Consistency condition for (Min, Max) boxes: min < max if(mMin.x > mMax.x) return FALSE; if(mMin.y > mMax.y) return FALSE; if(mMin.z > mMax.z) return FALSE; return TRUE; } //! Operator for AABB *= float. Scales the extents, keeps same center. inline_ AABB& operator*=(float s) { Point Center; GetCenter(Center); Point Extents; GetExtents(Extents); SetCenterExtents(Center, Extents * s); return *this; } //! Operator for AABB /= float. Scales the extents, keeps same center. inline_ AABB& operator/=(float s) { Point Center; GetCenter(Center); Point Extents; GetExtents(Extents); SetCenterExtents(Center, Extents / s); return *this; } //! Operator for AABB += Point. Translates the box. inline_ AABB& operator+=(const Point& trans) { mMin+=trans; mMax+=trans; return *this; } private: Point mMin; //!< Min point Point mMax; //!< Max point }; #else class ICEMATHS_API AABB { public: //! Constructor inline_ AABB() {} //! Destructor inline_ ~AABB() {} //! Type-independent methods AABB_COMMON_METHODS; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Setups an AABB from min & max vectors. * \param min [in] the min point * \param max [in] the max point */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void SetMinMax(const Point& min, const Point& max) { mCenter = (max + min)*0.5f; mExtents = (max - min)*0.5f; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Setups an AABB from center & extents vectors. * \param c [in] the center point * \param e [in] the extents vector */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void SetCenterExtents(const Point& c, const Point& e) { mCenter = c; mExtents = e; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Setups an empty AABB. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void SetEmpty() { mCenter.Zero(); mExtents.Set(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT);} /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Setups a point AABB. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void SetPoint(const Point& pt) { mCenter = pt; mExtents.Zero(); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Gets the size of the AABB. The size is defined as the longest extent. * \return the size of the AABB */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// float GetSize() const { return mExtents.Max(); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Extends the AABB. * \param p [in] the next point */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void Extend(const Point& p) { Point Max = mCenter + mExtents; Point Min = mCenter - mExtents; if(p.x > Max.x) Max.x = p.x; if(p.x < Min.x) Min.x = p.x; if(p.y > Max.y) Max.y = p.y; if(p.y < Min.y) Min.y = p.y; if(p.z > Max.z) Max.z = p.z; if(p.z < Min.z) Min.z = p.z; SetMinMax(Min, Max); } // Data access //! Get min point of the box inline_ void GetMin(Point& min) const { min = mCenter - mExtents; } //! Get max point of the box inline_ void GetMax(Point& max) const { max = mCenter + mExtents; } //! Get component of the box's min point along a given axis inline_ float GetMin(udword axis) const { return mCenter[axis] - mExtents[axis]; } //! Get component of the box's max point along a given axis inline_ float GetMax(udword axis) const { return mCenter[axis] + mExtents[axis]; } //! Get box center inline_ void GetCenter(Point& center) const { center = mCenter; } //! Get box extents inline_ void GetExtents(Point& extents) const { extents = mExtents; } //! Get component of the box's center along a given axis inline_ float GetCenter(udword axis) const { return mCenter[axis]; } //! Get component of the box's extents along a given axis inline_ float GetExtents(udword axis) const { return mExtents[axis]; } //! Get box diagonal inline_ void GetDiagonal(Point& diagonal) const { diagonal = mExtents * 2.0f; } inline_ float GetWidth() const { return mExtents.x * 2.0f; } inline_ float GetHeight() const { return mExtents.y * 2.0f; } inline_ float GetDepth() const { return mExtents.z * 2.0f; } //! Volume inline_ float GetVolume() const { return mExtents.x * mExtents.y * mExtents.z * 8.0f; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the intersection between two AABBs. * \param a [in] the other AABB * \return true on intersection */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ BOOL Intersect(const AABB& a) const { float tx = mCenter.x - a.mCenter.x; float ex = a.mExtents.x + mExtents.x; if(AIR(tx) > IR(ex)) return FALSE; float ty = mCenter.y - a.mCenter.y; float ey = a.mExtents.y + mExtents.y; if(AIR(ty) > IR(ey)) return FALSE; float tz = mCenter.z - a.mCenter.z; float ez = a.mExtents.z + mExtents.z; if(AIR(tz) > IR(ez)) return FALSE; return TRUE; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * The standard intersection method from Gamasutra. Just here to check its speed against the one above. * \param a [in] the other AABB * \return true on intersection */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ bool GomezIntersect(const AABB& a) { Point T = mCenter - a.mCenter; // Vector from A to B return ((fabsf(T.x) <= (a.mExtents.x + mExtents.x)) && (fabsf(T.y) <= (a.mExtents.y + mExtents.y)) && (fabsf(T.z) <= (a.mExtents.z + mExtents.z))); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the 1D-intersection between two AABBs, on a given axis. * \param a [in] the other AABB * \param axis [in] the axis (0, 1, 2) * \return true on intersection */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ BOOL Intersect(const AABB& a, udword axis) const { float t = mCenter[axis] - a.mCenter[axis]; float e = a.mExtents[axis] + mExtents[axis]; if(AIR(t) > IR(e)) return FALSE; return TRUE; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recomputes the AABB after an arbitrary transform by a 4x4 matrix. * \param mtx [in] the transform matrix * \param aabb [out] the transformed AABB [can be *this] */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ void Rotate(const Matrix4x4& mtx, AABB& aabb) const { // Compute new center aabb.mCenter = mCenter * mtx; // Compute new extents. FPU code & CPU code have been interleaved for improved performance. Point Ex(mtx.m[0][0] * mExtents.x, mtx.m[0][1] * mExtents.x, mtx.m[0][2] * mExtents.x); //IR(Ex.x)&=0x7fffffff; IR(Ex.y)&=0x7fffffff; IR(Ex.z)&=0x7fffffff; Ex.x = FR( AIR(Ex.x) ); Ex.y = FR( AIR(Ex.y) ); Ex.z = FR( AIR(Ex.z) ); Point Ey(mtx.m[1][0] * mExtents.y, mtx.m[1][1] * mExtents.y, mtx.m[1][2] * mExtents.y); //IR(Ey.x)&=0x7fffffff; IR(Ey.y)&=0x7fffffff; IR(Ey.z)&=0x7fffffff; Ey.x = FR( AIR(Ey.x) ); Ey.y = FR( AIR(Ey.y) ); Ey.z = FR( AIR(Ey.z) ); Point Ez(mtx.m[2][0] * mExtents.z, mtx.m[2][1] * mExtents.z, mtx.m[2][2] * mExtents.z); //IR(Ez.x)&=0x7fffffff; IR(Ez.y)&=0x7fffffff; IR(Ez.z)&=0x7fffffff; Ez.x = FR( AIR(Ez.x) ); Ez.y = FR( AIR(Ez.y) ); Ez.z = FR( AIR(Ez.z) ); aabb.mExtents.x = Ex.x + Ey.x + Ez.x; aabb.mExtents.y = Ex.y + Ey.y + Ez.y; aabb.mExtents.z = Ex.z + Ey.z + Ez.z; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Checks the AABB is valid. * \return true if the box is valid */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ BOOL IsValid() const { // Consistency condition for (Center, Extents) boxes: Extents >= 0 if(IS_NEGATIVE_FLOAT(mExtents.x)) return FALSE; if(IS_NEGATIVE_FLOAT(mExtents.y)) return FALSE; if(IS_NEGATIVE_FLOAT(mExtents.z)) return FALSE; return TRUE; } //! Operator for AABB *= float. Scales the extents, keeps same center. inline_ AABB& operator*=(float s) { mExtents*=s; return *this; } //! Operator for AABB /= float. Scales the extents, keeps same center. inline_ AABB& operator/=(float s) { mExtents/=s; return *this; } //! Operator for AABB += Point. Translates the box. inline_ AABB& operator+=(const Point& trans) { mCenter+=trans; return *this; } private: Point mCenter; //!< AABB Center Point mExtents; //!< x, y and z extents }; #endif inline_ void ComputeMinMax(const Point& p, Point& min, Point& max) { if(p.x > max.x) max.x = p.x; if(p.x < min.x) min.x = p.x; if(p.y > max.y) max.y = p.y; if(p.y < min.y) min.y = p.y; if(p.z > max.z) max.z = p.z; if(p.z < min.z) min.z = p.z; } inline_ void ComputeAABB(AABB& aabb, const Point* list, udword nb_pts) { if(list) { Point Maxi(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT); Point Mini(MAX_FLOAT, MAX_FLOAT, MAX_FLOAT); while(nb_pts--) { // _prefetch(list+1); // off by one ? ComputeMinMax(*list++, Mini, Maxi); } aabb.SetMinMax(Mini, Maxi); } } #endif // __ICEAABB_H__ ode-0.16/OPCODE/Ice/IceAABB.cpp0000664000175200017520000003760413403272463012437 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains AABB-related code. * \file IceAABB.cpp * \author Pierre Terdiman * \date January, 29, 2000 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * AABB class. * \class AABB * \author Pierre Terdiman * \version 1.0 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Precompiled Header #include "Stdafx.h" using namespace IceMaths; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the sum of two AABBs. * \param aabb [in] the other AABB * \return Self-Reference */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// AABB& AABB::Add(const AABB& aabb) { // Compute new min & max values Point Min; GetMin(Min); Point Tmp; aabb.GetMin(Tmp); Min.Min(Tmp); Point Max; GetMax(Max); aabb.GetMax(Tmp); Max.Max(Tmp); // Update this SetMinMax(Min, Max); return *this; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Makes a cube from the AABB. * \param cube [out] the cube AABB * \return cube edge length */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// float AABB::MakeCube(AABB& cube) const { Point Ext; GetExtents(Ext); float Max = Ext.Max(); Point Cnt; GetCenter(Cnt); cube.SetCenterExtents(Cnt, Point(Max, Max, Max)); return Max; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Makes a sphere from the AABB. * \param sphere [out] sphere containing the AABB */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void AABB::MakeSphere(Sphere& sphere) const { GetExtents(sphere.mCenter); sphere.mRadius = sphere.mCenter.Magnitude() * 1.00001f; // To make sure sphere::Contains(*this) succeeds GetCenter(sphere.mCenter); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Checks a box is inside another box. * \param box [in] the other AABB * \return true if current box is inside input box */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool AABB::IsInside(const AABB& box) const { if(box.GetMin(0)>GetMin(0)) return false; if(box.GetMin(1)>GetMin(1)) return false; if(box.GetMin(2)>GetMin(2)) return false; if(box.GetMax(0) max.x) ? 2 : 0) // 2 = right + ((local_eye.y < min.y) ? 4 : 0) // 4 = bottom + ((local_eye.y > max.y) ? 8 : 0) // 8 = top + ((local_eye.z < min.z) ? 16 : 0) // 16 = front + ((local_eye.z > max.z) ? 32 : 0); // 32 = back // Look up number of vertices in outline num = (sdword)gIndexList[pos][7]; // Zero indicates invalid case if(!num) return null; return &gIndexList[pos][0]; } // calculateBoxArea: computes the screen-projected 2D area of an oriented 3D bounding box //const Point& eye, //eye point (in bbox object coordinates) //const AABB& box, //3d bbox //const Matrix4x4& mat, //free transformation for bbox //float width, float height, int& num) float AABB::ComputeBoxArea(const Point& eye, const Matrix4x4& mat, float width, float height, sdword& num) const { const sbyte* Outline = ComputeOutline(eye, num); if(!Outline) return -1.0f; // Compute box vertices Point vertexBox[8], dst[8]; ComputePoints(vertexBox); // Transform all outline corners into 2D screen space for(sdword i=0;i #include /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Things to help us compile on non-windows platforms #if defined(__APPLE__) || defined(__MACOSX__) #if __APPLE_CC__ < 1495 #define sqrtf sqrt #define sinf sin #define cosf cos #define acosf acos #define asinf asin #endif #endif #ifndef _MSC_VER #ifndef __int64 #define __int64 long long int #endif #ifndef __stdcall /* this is defined in MinGW and CygWin, so avoid the warning */ #define __stdcall /* */ #endif #endif #if defined(__GNUC__) #define OPCODE_NORETURN __attribute__((noreturn)) #elif defined(_MSC_VER) #define OPCODE_NORETURN __declspec(noreturn) #else // #if !defined(_MSC_VER) #define OPCODE_NORETURN #endif // #if !defined(__GNUC__) /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Compilation messages #ifdef _MSC_VER #if defined(OPCODE_EXPORTS) // #pragma message("Compiling OPCODE") #elif !defined(OPCODE_EXPORTS) // #pragma message("Using OPCODE") /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Automatic linking #ifndef BAN_OPCODE_AUTOLINK #ifdef _DEBUG //#pragma comment(lib, "Opcode_D.lib") #else //#pragma comment(lib, "Opcode.lib") #endif #endif #endif #endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Preprocessor #ifndef ICE_NO_DLL #ifdef OPCODE_EXPORTS #define OPCODE_API// __declspec(dllexport) #else #define OPCODE_API// __declspec(dllimport) #endif #else #define OPCODE_API #endif #include "OPC_Settings.h" #include "OPC_IceHook.h" namespace Opcode { // Bulk-of-the-work #include "OPC_Common.h" #include "OPC_MeshInterface.h" // Builders #include "OPC_TreeBuilders.h" // Trees #include "OPC_AABBTree.h" #include "OPC_OptimizedTree.h" // Models #include "OPC_BaseModel.h" #include "OPC_Model.h" #include "OPC_HybridModel.h" // Colliders #include "OPC_Collider.h" #include "OPC_VolumeCollider.h" #include "OPC_TreeCollider.h" #include "OPC_RayCollider.h" #include "OPC_SphereCollider.h" #include "OPC_OBBCollider.h" #include "OPC_AABBCollider.h" #include "OPC_LSSCollider.h" #include "OPC_PlanesCollider.h" // Usages #include "OPC_Picking.h" typedef void (*OPCODE_AbortHandler)(); FUNCTION OPCODE_API bool InitOpcode(OPCODE_AbortHandler fnAbortHandler=NULL); FUNCTION OPCODE_API bool CloseOpcode(); } #endif // __OPCODE_H__ ode-0.16/OPCODE/OPC_TreeBuilders.h0000664000175200017520000002217713403272463013367 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* * OPCODE - Optimized Collision Detection * Copyright (C) 2001 Pierre Terdiman * Homepage: http://www.codercorner.com/Opcode.htm */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains code for tree builders. * \file OPC_TreeBuilders.h * \author Pierre Terdiman * \date March, 20, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Include Guard #ifndef __OPC_TREEBUILDERS_H__ #define __OPC_TREEBUILDERS_H__ //! Tree splitting rules enum SplittingRules { // Primitive split SPLIT_LARGEST_AXIS = (1<<0), //!< Split along the largest axis SPLIT_SPLATTER_POINTS = (1<<1), //!< Splatter primitive centers (QuickCD-style) SPLIT_BEST_AXIS = (1<<2), //!< Try largest axis, then second, then last SPLIT_BALANCED = (1<<3), //!< Try to keep a well-balanced tree SPLIT_FIFTY = (1<<4), //!< Arbitrary 50-50 split // Node split SPLIT_GEOM_CENTER = (1<<5), //!< Split at geometric center (else split in the middle) // SPLIT_FORCE_DWORD = 0x7fffffff }; //! Simple wrapper around build-related settings [Opcode 1.3] struct OPCODE_API BuildSettings { inline_ BuildSettings() : mLimit(1), mRules(SPLIT_FORCE_DWORD) {} inline_ explicit BuildSettings(udword Rules) : mLimit(1), mRules(Rules) {} udword mLimit; //!< Limit number of primitives / node. If limit is 1, build a complete tree (2*N-1 nodes) udword mRules; //!< Building/Splitting rules (a combination of SplittingRules flags) }; class OPCODE_API AABBTreeBuilder { public: //! Constructor AABBTreeBuilder() : mNbPrimitives(0), mNodeBase(null), mCount(0), mNbInvalidSplits(0) {} //! Destructor virtual ~AABBTreeBuilder() {} /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the AABB of a set of primitives. * \param primitives [in] list of indices of primitives * \param nb_prims [in] number of indices * \param global_box [out] global AABB enclosing the set of input primitives * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// virtual bool ComputeGlobalBox(const dTriIndex* primitives, udword nb_prims, AABB& global_box) const = 0; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the splitting value along a given axis for a given primitive. * \param index [in] index of the primitive to split * \param axis [in] axis index (0,1,2) * \return splitting value */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// virtual float GetSplittingValue(udword index, udword axis) const = 0; virtual Point GetSplittingValues(udword index) const = 0; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the splitting value along a given axis for a given node. * \param primitives [in] list of indices of primitives * \param nb_prims [in] number of indices * \param global_box [in] global AABB enclosing the set of input primitives * \param axis [in] axis index (0,1,2) * \return splitting value */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// virtual float GetSplittingValue(const dTriIndex* /*primitives*/, udword /*nb_prims*/, const AABB& global_box, udword axis) const { // Default split value = middle of the axis (using only the box) return global_box.GetCenter(axis); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Validates node subdivision. This is called each time a node is considered for subdivision, during tree building. * \param primitives [in] list of indices of primitives * \param nb_prims [in] number of indices * \param global_box [in] global AABB enclosing the set of input primitives * \return TRUE if the node should be subdivised */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// virtual BOOL ValidateSubdivision(const dTriIndex* /*primitives*/, udword nb_prims, const AABB& /*global_box*/) { // Check the user-defined limit if(nb_prims<=mSettings.mLimit) return FALSE; return TRUE; } BuildSettings mSettings; //!< Splitting rules & split limit [Opcode 1.3] udword mNbPrimitives; //!< Total number of primitives. void* mNodeBase; //!< Address of node pool [Opcode 1.3] // Stats inline_ void SetCount(udword nb) { mCount=nb; } inline_ void IncreaseCount(udword nb) { mCount+=nb; } inline_ udword GetCount() const { return mCount; } inline_ void SetNbInvalidSplits(udword nb) { mNbInvalidSplits=nb; } inline_ void IncreaseNbInvalidSplits() { mNbInvalidSplits++; } inline_ udword GetNbInvalidSplits() const { return mNbInvalidSplits; } private: udword mCount; //!< Stats: number of nodes created udword mNbInvalidSplits; //!< Stats: number of invalid splits }; class OPCODE_API AABBTreeOfVerticesBuilder : public AABBTreeBuilder { public: //! Constructor AABBTreeOfVerticesBuilder() : mVertexArray(null) {} //! Destructor virtual ~AABBTreeOfVerticesBuilder() {} override(AABBTreeBuilder) bool ComputeGlobalBox(const dTriIndex* primitives, udword nb_prims, AABB& global_box) const; override(AABBTreeBuilder) float GetSplittingValue(udword index, udword axis) const; override(AABBTreeBuilder) Point GetSplittingValues(udword index) const; override(AABBTreeBuilder) float GetSplittingValue(const dTriIndex* primitives, udword nb_prims, const AABB& global_box, udword axis) const; const Point* mVertexArray; //!< Shortcut to an app-controlled array of vertices. }; class OPCODE_API AABBTreeOfAABBsBuilder : public AABBTreeBuilder { public: //! Constructor AABBTreeOfAABBsBuilder() : mAABBArray(null) {} //! Destructor virtual ~AABBTreeOfAABBsBuilder() {} override(AABBTreeBuilder) bool ComputeGlobalBox(const dTriIndex* primitives, udword nb_prims, AABB& global_box) const; override(AABBTreeBuilder) float GetSplittingValue(udword index, udword axis) const; override(AABBTreeBuilder) Point GetSplittingValues(udword index) const; const AABB* mAABBArray; //!< Shortcut to an app-controlled array of AABBs. }; class OPCODE_API AABBTreeOfTrianglesBuilder : public AABBTreeBuilder { public: //! Constructor AABBTreeOfTrianglesBuilder() : mIMesh(null) {} //! Destructor virtual ~AABBTreeOfTrianglesBuilder() {} override(AABBTreeBuilder) bool ComputeGlobalBox(const dTriIndex* primitives, udword nb_prims, AABB& global_box) const; override(AABBTreeBuilder) float GetSplittingValue(udword index, udword axis) const; override(AABBTreeBuilder) float GetSplittingValue(const dTriIndex* primitives, udword nb_prims, const AABB& global_box, udword axis) const; override(AABBTreeBuilder) Point GetSplittingValues(udword index) const; const MeshInterface* mIMesh; //!< Shortcut to an app-controlled mesh interface }; #endif // __OPC_TREEBUILDERS_H__ ode-0.16/OPCODE/OPC_OptimizedTree.cpp0000664000175200017520000010076213403272463014112 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* * OPCODE - Optimized Collision Detection * Copyright (C) 2001 Pierre Terdiman * Homepage: http://www.codercorner.com/Opcode.htm */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains code for optimized trees. Implements 4 trees: * - normal * - no leaf * - quantized * - no leaf / quantized * * \file OPC_OptimizedTree.cpp * \author Pierre Terdiman * \date March, 20, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * A standard AABB tree. * * \class AABBCollisionTree * \author Pierre Terdiman * \version 1.3 * \date March, 20, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * A no-leaf AABB tree. * * \class AABBNoLeafTree * \author Pierre Terdiman * \version 1.3 * \date March, 20, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * A quantized AABB tree. * * \class AABBQuantizedTree * \author Pierre Terdiman * \version 1.3 * \date March, 20, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * A quantized no-leaf AABB tree. * * \class AABBQuantizedNoLeafTree * \author Pierre Terdiman * \version 1.3 * \date March, 20, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Precompiled Header #include "Stdafx.h" using namespace Opcode; //! Compilation flag: //! - true to fix quantized boxes (i.e. make sure they enclose the original ones) //! - false to see the effects of quantization errors (faster, but wrong results in some cases) static const bool gFixQuantized = true; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Builds an implicit tree from a standard one. An implicit tree is a complete tree (2*N-1 nodes) whose negative * box pointers and primitive pointers have been made implicit, hence packing 3 pointers in one. * * Layout for implicit trees: * Node: * - box * - data (32-bits value) * * if data's LSB = 1 => remaining bits are a primitive pointer * else remaining bits are a P-node pointer, and N = P + 1 * * \relates AABBCollisionNode * \fn _BuildCollisionTree(AABBCollisionNode* linear, const udword box_id, udword& current_id, const AABBTreeNode* current_node) * \param linear [in] base address of destination nodes * \param box_id [in] index of destination node * \param current_id [in] current running index * \param current_node [in] current node from input tree */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static void _BuildCollisionTree(AABBCollisionNode* linear, const udword box_id, udword& current_id, const AABBTreeNode* current_node) { // Current node from input tree is "current_node". Must be flattened into "linear[boxid]". // Store the AABB current_node->GetAABB()->GetCenter(linear[box_id].mAABB.mCenter); current_node->GetAABB()->GetExtents(linear[box_id].mAABB.mExtents); // Store remaining info if(current_node->IsLeaf()) { // The input tree must be complete => i.e. one primitive/leaf ASSERT(current_node->GetNbPrimitives()==1); // Get the primitive index from the input tree udword PrimitiveIndex = current_node->GetPrimitives()[0]; // Setup box data as the primitive index, marked as leaf linear[box_id].mData = (PrimitiveIndex<<1)|1; } else { // To make the negative one implicit, we must store P and N in successive order udword PosID = current_id++; // Get a new id for positive child udword NegID = current_id++; // Get a new id for negative child // Setup box data as the forthcoming new P pointer linear[box_id].mData = (size_t)&linear[PosID]; // Make sure it's not marked as leaf ASSERT(!(linear[box_id].mData&1)); // Recurse with new IDs _BuildCollisionTree(linear, PosID, current_id, current_node->GetPos()); _BuildCollisionTree(linear, NegID, current_id, current_node->GetNeg()); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Builds a "no-leaf" tree from a standard one. This is a tree whose leaf nodes have been removed. * * Layout for no-leaf trees: * * Node: * - box * - P pointer => a node (LSB=0) or a primitive (LSB=1) * - N pointer => a node (LSB=0) or a primitive (LSB=1) * * \relates AABBNoLeafNode * \fn _BuildNoLeafTree(AABBNoLeafNode* linear, const udword box_id, udword& current_id, const AABBTreeNode* current_node) * \param linear [in] base address of destination nodes * \param box_id [in] index of destination node * \param current_id [in] current running index * \param current_node [in] current node from input tree */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static void _BuildNoLeafTree(AABBNoLeafNode* linear, const udword box_id, udword& current_id, const AABBTreeNode* current_node) { const AABBTreeNode* P = current_node->GetPos(); const AABBTreeNode* N = current_node->GetNeg(); // Leaf nodes here?! ASSERT(P); ASSERT(N); // Internal node => keep the box current_node->GetAABB()->GetCenter(linear[box_id].mAABB.mCenter); current_node->GetAABB()->GetExtents(linear[box_id].mAABB.mExtents); if(P->IsLeaf()) { // The input tree must be complete => i.e. one primitive/leaf ASSERT(P->GetNbPrimitives()==1); // Get the primitive index from the input tree udword PrimitiveIndex = P->GetPrimitives()[0]; // Setup prev box data as the primitive index, marked as leaf linear[box_id].mPosData = (PrimitiveIndex<<1)|1; } else { // Get a new id for positive child udword PosID = current_id++; // Setup box data linear[box_id].mPosData = (size_t)&linear[PosID]; // Make sure it's not marked as leaf ASSERT(!(linear[box_id].mPosData&1)); // Recurse _BuildNoLeafTree(linear, PosID, current_id, P); } if(N->IsLeaf()) { // The input tree must be complete => i.e. one primitive/leaf ASSERT(N->GetNbPrimitives()==1); // Get the primitive index from the input tree udword PrimitiveIndex = N->GetPrimitives()[0]; // Setup prev box data as the primitive index, marked as leaf linear[box_id].mNegData = (PrimitiveIndex<<1)|1; } else { // Get a new id for negative child udword NegID = current_id++; // Setup box data linear[box_id].mNegData = (size_t)&linear[NegID]; // Make sure it's not marked as leaf ASSERT(!(linear[box_id].mNegData&1)); // Recurse _BuildNoLeafTree(linear, NegID, current_id, N); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Constructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// AABBCollisionTree::AABBCollisionTree() : mNodes(null) { } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Destructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// AABBCollisionTree::~AABBCollisionTree() { DELETEARRAY(mNodes); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Builds the collision tree from a generic AABB tree. * \param tree [in] generic AABB tree * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool AABBCollisionTree::Build(AABBTree* tree) { // Checkings if(!tree) return false; // Check the input tree is complete udword NbTriangles = tree->GetNbPrimitives(); udword NbNodes = tree->GetNbNodes(); if(NbNodes!=NbTriangles*2-1) return false; // Get nodes if(mNbNodes!=NbNodes) // Same number of nodes => keep moving { mNbNodes = NbNodes; DELETEARRAY(mNodes); mNodes = new AABBCollisionNode[NbNodes]; CHECKALLOC(mNodes); } // Build the tree udword CurID = 1; _BuildCollisionTree(mNodes, 0, CurID, tree); ASSERT(CurID==NbNodes); return true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Refits the collision tree after vertices have been modified. * \param mesh_interface [in] mesh interface for current model * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool AABBCollisionTree::Refit(const MeshInterface* /*mesh_interface*/) { ASSERT(!"Not implemented since AABBCollisionTrees have twice as more nodes to refit as AABBNoLeafTrees!"); return false; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Walks the tree and call the user back for each node. * \param callback [in] walking callback * \param user_data [in] callback's user data * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool AABBCollisionTree::Walk(GenericWalkingCallback callback, void* user_data) const { if(!callback) return false; struct Local { static void _Walk(const AABBCollisionNode* current_node, GenericWalkingCallback callback, void* user_data) { if(!current_node || !(callback)(current_node, user_data)) return; if(!current_node->IsLeaf()) { _Walk(current_node->GetPos(), callback, user_data); _Walk(current_node->GetNeg(), callback, user_data); } } }; Local::_Walk(mNodes, callback, user_data); return true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Constructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// AABBNoLeafTree::AABBNoLeafTree() : mNodes(null) { } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Destructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// AABBNoLeafTree::~AABBNoLeafTree() { DELETEARRAY(mNodes); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Builds the collision tree from a generic AABB tree. * \param tree [in] generic AABB tree * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool AABBNoLeafTree::Build(AABBTree* tree) { // Checkings if(!tree) return false; // Check the input tree is complete udword NbTriangles = tree->GetNbPrimitives(); udword NbExistingNodes = tree->GetNbNodes(); if(NbExistingNodes!=NbTriangles*2-1) return false; udword NbNodes = NbTriangles-1; // Get nodes if(mNbNodes!=NbNodes) // Same number of nodes => keep moving { mNbNodes = NbNodes; DELETEARRAY(mNodes); mNodes = new AABBNoLeafNode[NbNodes]; CHECKALLOC(mNodes); } // Build the tree udword CurID = 1; _BuildNoLeafTree(mNodes, 0, CurID, tree); ASSERT(CurID==NbNodes); return true; } inline_ void ComputeMinMax(Point& min, Point& max, const VertexPointers& vp) { // Compute triangle's AABB = a leaf box #ifdef OPC_USE_FCOMI // a 15% speedup on my machine, not much min.x = FCMin3(vp.Vertex[0]->x, vp.Vertex[1]->x, vp.Vertex[2]->x); max.x = FCMax3(vp.Vertex[0]->x, vp.Vertex[1]->x, vp.Vertex[2]->x); min.y = FCMin3(vp.Vertex[0]->y, vp.Vertex[1]->y, vp.Vertex[2]->y); max.y = FCMax3(vp.Vertex[0]->y, vp.Vertex[1]->y, vp.Vertex[2]->y); min.z = FCMin3(vp.Vertex[0]->z, vp.Vertex[1]->z, vp.Vertex[2]->z); max.z = FCMax3(vp.Vertex[0]->z, vp.Vertex[1]->z, vp.Vertex[2]->z); #else min = *vp.Vertex[0]; max = *vp.Vertex[0]; min.Min(*vp.Vertex[1]); max.Max(*vp.Vertex[1]); min.Min(*vp.Vertex[2]); max.Max(*vp.Vertex[2]); #endif } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Refits the collision tree after vertices have been modified. * \param mesh_interface [in] mesh interface for current model * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool AABBNoLeafTree::Refit(const MeshInterface* mesh_interface) { // Checkings if(!mesh_interface) return false; // Bottom-up update VertexPointers VP; ConversionArea VC; Point Min,Max; Point Min_,Max_; udword Index = mNbNodes; while(Index--) { AABBNoLeafNode& Current = mNodes[Index]; if(Current.HasPosLeaf()) { mesh_interface->GetTriangle(VP, Current.GetPosPrimitive(), VC); ComputeMinMax(Min, Max, VP); } else { const CollisionAABB& CurrentBox = Current.GetPos()->mAABB; CurrentBox.GetMin(Min); CurrentBox.GetMax(Max); } if(Current.HasNegLeaf()) { mesh_interface->GetTriangle(VP, Current.GetNegPrimitive(), VC); ComputeMinMax(Min_, Max_, VP); } else { const CollisionAABB& CurrentBox = Current.GetNeg()->mAABB; CurrentBox.GetMin(Min_); CurrentBox.GetMax(Max_); } #ifdef OPC_USE_FCOMI Min.x = FCMin2(Min.x, Min_.x); Max.x = FCMax2(Max.x, Max_.x); Min.y = FCMin2(Min.y, Min_.y); Max.y = FCMax2(Max.y, Max_.y); Min.z = FCMin2(Min.z, Min_.z); Max.z = FCMax2(Max.z, Max_.z); #else Min.Min(Min_); Max.Max(Max_); #endif Current.mAABB.SetMinMax(Min, Max); } return true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Walks the tree and call the user back for each node. * \param callback [in] walking callback * \param user_data [in] callback's user data * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool AABBNoLeafTree::Walk(GenericWalkingCallback callback, void* user_data) const { if(!callback) return false; struct Local { static void _Walk(const AABBNoLeafNode* current_node, GenericWalkingCallback callback, void* user_data) { if(!current_node || !(callback)(current_node, user_data)) return; if(!current_node->HasPosLeaf()) _Walk(current_node->GetPos(), callback, user_data); if(!current_node->HasNegLeaf()) _Walk(current_node->GetNeg(), callback, user_data); } }; Local::_Walk(mNodes, callback, user_data); return true; } // Quantization notes: // - We could use the highest bits of mData to store some more quantized bits. Dequantization code // would be slightly more complex, but number of overlap tests would be reduced (and anyhow those // bits are currently wasted). Of course it's not possible if we move to 16 bits mData. // - Something like "16 bits floats" could be tested, to bypass the int-to-float conversion. // - A dedicated BV-BV test could be used, dequantizing while testing for overlap. (i.e. it's some // lazy-dequantization which may save some work in case of early exits). At the very least some // muls could be saved by precomputing several more matrices. But maybe not worth the pain. // - Do we need to dequantize anyway? Not doing the extents-related muls only implies the box has // been scaled, for example. // - The deeper we move into the hierarchy, the smaller the extents should be. May not need a fixed // number of quantization bits. Even better, could probably be best delta-encoded. // Find max values. Some people asked why I wasn't simply using the first node. Well, I can't. // I'm not looking for (min, max) values like in a standard AABB, I'm looking for the extremal // centers/extents in order to quantize them. The first node would only give a single center and // a single extents. While extents would be the biggest, the center wouldn't. #define FIND_MAX_VALUES \ /* Get max values */ \ Point CMax(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT); \ Point EMax(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT); \ const udword NbNodes = mNbNodes; \ for(udword i=0;iCMax.x) CMax.x = cx; \ float cy = fabsf(Nodes[i].mAABB.mCenter.y); if(cy>CMax.y) CMax.y = cy; \ float cz = fabsf(Nodes[i].mAABB.mCenter.z); if(cz>CMax.z) CMax.z = cz; \ float ex = fabsf(Nodes[i].mAABB.mExtents.x); if(ex>EMax.x) EMax.x = ex; \ float ey = fabsf(Nodes[i].mAABB.mExtents.y); if(ey>EMax.y) EMax.y = ey; \ float ez = fabsf(Nodes[i].mAABB.mExtents.z); if(ez>EMax.z) EMax.z = ez; \ } #define INIT_QUANTIZATION \ udword nbc=15; /* Keep one bit for sign */ \ udword nbe=15; /* Keep one bit for fix */ \ if(!gFixQuantized) nbe++; \ \ /* Compute quantization coeffs */ \ Point CQuantCoeff, EQuantCoeff; \ CQuantCoeff.x = CMax.x!=0.0f ? float((1<Min[j]) \ { \ mNodes[i].mAABB.mExtents[j]++; \ /* Prevent wrapping */ \ if(!mNodes[i].mAABB.mExtents[j]) \ { \ mNodes[i].mAABB.mExtents[j]=0xffff; \ FixMe=false; \ } \ } \ else FixMe=false; \ }while(FixMe); \ } \ } #define REMAP_DATA(member, NodeType) \ /* Fix data */ \ Data = Nodes[i].member; \ if(!(Data&1)) \ { \ /* Compute box number */ \ size_t Nb = ((NodeType *)(Data) - (Nodes)); \ Data = (size_t) &mNodes[Nb]; \ } \ /* ...remapped */ \ mNodes[i].member = Data; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Constructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// AABBQuantizedTree::AABBQuantizedTree() : mNodes(null) { } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Destructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// AABBQuantizedTree::~AABBQuantizedTree() { DELETEARRAY(mNodes); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Builds the collision tree from a generic AABB tree. * \param tree [in] generic AABB tree * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool AABBQuantizedTree::Build(AABBTree* tree) { // Checkings if(!tree) return false; // Check the input tree is complete udword NbTriangles = tree->GetNbPrimitives(); udword NbNodes = tree->GetNbNodes(); if(NbNodes!=NbTriangles*2-1) return false; // Get nodes mNbNodes = NbNodes; DELETEARRAY(mNodes); AABBCollisionNode* Nodes = new AABBCollisionNode[NbNodes]; CHECKALLOC(Nodes); // Build the tree udword CurID = 1; _BuildCollisionTree(Nodes, 0, CurID, tree); // Quantize { mNodes = new AABBQuantizedNode[NbNodes]; if (mNodes != null) { // Get max values FIND_MAX_VALUES // Quantization INIT_QUANTIZATION // Quantize size_t Data; for(udword i=0;iIsLeaf()) { _Walk(current_node->GetPos(), callback, user_data); _Walk(current_node->GetNeg(), callback, user_data); } } }; Local::_Walk(mNodes, callback, user_data); return true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Constructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// AABBQuantizedNoLeafTree::AABBQuantizedNoLeafTree() : mNodes(null) { } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Destructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// AABBQuantizedNoLeafTree::~AABBQuantizedNoLeafTree() { DELETEARRAY(mNodes); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Builds the collision tree from a generic AABB tree. * \param tree [in] generic AABB tree * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool AABBQuantizedNoLeafTree::Build(AABBTree* tree) { // Checkings if(!tree) return false; // Check the input tree is complete udword NbTriangles = tree->GetNbPrimitives(); udword NbExistingNodes = tree->GetNbNodes(); if(NbExistingNodes!=NbTriangles*2-1) return false; // Get nodes udword NbNodes = NbTriangles-1; mNbNodes = NbNodes; DELETEARRAY(mNodes); AABBNoLeafNode* Nodes = new AABBNoLeafNode[NbNodes]; CHECKALLOC(Nodes); // Build the tree udword CurID = 1; _BuildNoLeafTree(Nodes, 0, CurID, tree); ASSERT(CurID==NbNodes); // Quantize { mNodes = new AABBQuantizedNoLeafNode[NbNodes]; if (mNodes != null) { // Get max values FIND_MAX_VALUES // Quantization INIT_QUANTIZATION // Quantize size_t Data; for(udword i=0;iHasPosLeaf()) _Walk(current_node->GetPos(), callback, user_data); if(!current_node->HasNegLeaf()) _Walk(current_node->GetNeg(), callback, user_data); } }; Local::_Walk(mNodes, callback, user_data); return true; } ode-0.16/OPCODE/OPC_PlanesTriOverlap.h0000664000175200017520000000256613403272463014230 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Planes-triangle overlap test. * \param in_clip_mask [in] bitmask for active planes * \return TRUE if triangle overlap planes * \warning THIS IS A CONSERVATIVE TEST !! Some triangles will be returned as intersecting, while they're not! */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ BOOL PlanesCollider::PlanesTriOverlap(udword in_clip_mask) { // Stats mNbVolumePrimTests++; const Plane* p = mPlanes; udword Mask = 1; while(Mask<=in_clip_mask) { if(in_clip_mask & Mask) { float d0 = p->Distance(*mVP.Vertex[0]); float d1 = p->Distance(*mVP.Vertex[1]); float d2 = p->Distance(*mVP.Vertex[2]); if(d0>0.0f && d1>0.0f && d2>0.0f) return FALSE; // if(!(IR(d0)&SIGN_BITMASK) && !(IR(d1)&SIGN_BITMASK) && !(IR(d2)&SIGN_BITMASK)) return FALSE; } Mask+=Mask; p++; } /* for(udword i=0;i<6;i++) { float d0 = p[i].Distance(mLeafVerts[0]); float d1 = p[i].Distance(mLeafVerts[1]); float d2 = p[i].Distance(mLeafVerts[2]); if(d0>0.0f && d1>0.0f && d2>0.0f) return false; } */ return TRUE; } ode-0.16/OPCODE/Makefile.am0000664000175200017520000000415513403272463012154 00000000000000EXTRA_DIST = COPYING \ ReadMe.txt \ README-ODE.txt \ TemporalCoherence.txt SUBDIRS = Ice noinst_LTLIBRARIES = libOPCODE.la AM_CPPFLAGS= -I$(top_srcdir)/include \ -I$(top_builddir)/include libOPCODE_la_SOURCES = OPC_AABBCollider.cpp OPC_AABBCollider.h \ OPC_AABBTree.cpp OPC_AABBTree.h \ OPC_BaseModel.cpp OPC_BaseModel.h \ OPC_Collider.cpp OPC_Collider.h \ OPC_Common.cpp OPC_Common.h \ OPC_HybridModel.cpp OPC_HybridModel.h \ OPC_LSSCollider.cpp OPC_LSSCollider.h \ OPC_MeshInterface.cpp OPC_MeshInterface.h \ OPC_Model.cpp OPC_Model.h \ OPC_OBBCollider.cpp OPC_OBBCollider.h \ Opcode.cpp Opcode.h \ OPC_OptimizedTree.cpp OPC_OptimizedTree.h \ OPC_Picking.cpp OPC_Picking.h \ OPC_PlanesCollider.cpp OPC_PlanesCollider.h \ OPC_RayCollider.cpp OPC_RayCollider.h \ OPC_SphereCollider.cpp OPC_SphereCollider.h \ OPC_TreeBuilders.cpp OPC_TreeBuilders.h \ OPC_TreeCollider.cpp OPC_TreeCollider.h \ OPC_VolumeCollider.cpp OPC_VolumeCollider.h \ OPC_Settings.h \ OPC_SphereAABBOverlap.h \ OPC_BoxBoxOverlap.h \ OPC_SphereTriOverlap.h \ OPC_PlanesAABBOverlap.h \ OPC_TriBoxOverlap.h \ OPC_IceHook.h \ OPC_PlanesTriOverlap.h \ OPC_TriTriOverlap.h \ OPC_LSSAABBOverlap.h \ OPC_RayAABBOverlap.h \ Stdafx.h \ OPC_LSSTriOverlap.h \ OPC_RayTriOverlap.h ode-0.16/OPCODE/TemporalCoherence.txt0000664000175200017520000000236113403272463014255 00000000000000 > Hi John, > > I know I'll forget to tell you this if I don't write it right now.... > > >(2) How is the receiving geometry for the shadow decided? > > I wrote about an LSS-test but actually performing a new VFC test (from the > light's view) is the same. In both cases, here's a trick to take advantage > of temporal coherence : test the world against a slightly larger than > necessary LSS or frustum. Keep the list of touched surfaces. Then next > frame, if the new volume is still contained within the previous one used for > the query, you can reuse the same list immediately. Actually it's a bit > similar to what you did in your sphere-tree, I think. Anyway, now the O(log > N) VFC is O(1) for some frames. It's not worth it for the "real" VFC, but > when you have N virtual frustum to test to drop N shadows, that's another > story. > > Two downsides: > - You need more ram to keep track of one list of meshes / shadow, but > usually it's not a lot. > - By using a larger volume for the query you possibly touch more > faces/surfaces, which will be rendered in the shadow pass. Usually it's not > a problem either since rendering is simply faster than geometric queries > those days. But of course, "your mileage may vary". > > Happy new year ! > > Pierre ode-0.16/OPCODE/OPC_VolumeCollider.h0000664000175200017520000001572313403272463013722 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* * OPCODE - Optimized Collision Detection * Copyright (C) 2001 Pierre Terdiman * Homepage: http://www.codercorner.com/Opcode.htm */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains base volume collider class. * \file OPC_VolumeCollider.h * \author Pierre Terdiman * \date June, 2, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Include Guard #ifndef __OPC_VOLUMECOLLIDER_H__ #define __OPC_VOLUMECOLLIDER_H__ struct OPCODE_API VolumeCache { VolumeCache() : Model(null) {} ~VolumeCache() {} Container TouchedPrimitives; //!< Indices of touched primitives const BaseModel* Model; //!< Owner }; class OPCODE_API VolumeCollider : public Collider { public: // Constructor / Destructor VolumeCollider(); virtual ~VolumeCollider() = 0; // Collision report /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Gets the number of touched primitives after a collision query. * \see GetContactStatus() * \see GetTouchedPrimitives() * \return the number of touched primitives */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ udword GetNbTouchedPrimitives() const { return mTouchedPrimitives ? mTouchedPrimitives->GetNbEntries() : 0; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Gets the list of touched primitives after a collision query. * \see GetContactStatus() * \see GetNbTouchedPrimitives() * \return the list of touched primitives (primitive indices) */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ const udword* GetTouchedPrimitives() const { return mTouchedPrimitives ? mTouchedPrimitives->GetEntries() : null; } // Stats /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Stats: gets the number of Volume-BV overlap tests after a collision query. * \see GetNbVolumePrimTests() * \return the number of Volume-BV tests performed during last query */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ udword GetNbVolumeBVTests() const { return mNbVolumeBVTests; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Stats: gets the number of Volume-Triangle overlap tests after a collision query. * \see GetNbVolumeBVTests() * \return the number of Volume-Triangle tests performed during last query */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ udword GetNbVolumePrimTests() const { return mNbVolumePrimTests; } // Settings /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Validates current settings. You should call this method after all the settings / callbacks have been defined for a collider. * \return null if everything is ok, else a string describing the problem */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// override(Collider) const char* ValidateSettings(); protected: // Touched primitives Container* mTouchedPrimitives; //!< List of touched primitives // Dequantization coeffs Point mCenterCoeff; Point mExtentsCoeff; // Stats udword mNbVolumeBVTests; //!< Number of Volume-BV tests udword mNbVolumePrimTests; //!< Number of Volume-Primitive tests // Internal methods void _Dump(const AABBCollisionNode* node); void _Dump(const AABBNoLeafNode* node); void _Dump(const AABBQuantizedNode* node); void _Dump(const AABBQuantizedNoLeafNode* node); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Initializes a query */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// override(Collider) inline_ void InitQuery() { // Reset stats & contact status mNbVolumeBVTests = 0; mNbVolumePrimTests = 0; Collider::InitQuery(); } inline_ BOOL IsCacheValid(VolumeCache& cache) { // We're going to do a volume-vs-model query. if(cache.Model!=mCurrentModel) { // Cached list was for another model so we can't keep it // Keep track of new owner and reset cache cache.Model = mCurrentModel; return FALSE; } else { // Same models, no problem return TRUE; } } }; #endif // __OPC_VOLUMECOLLIDER_H__ ode-0.16/OPCODE/OPC_PlanesCollider.h0000664000175200017520000001322213403272463013665 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* * OPCODE - Optimized Collision Detection * Copyright (C) 2001 Pierre Terdiman * Homepage: http://www.codercorner.com/Opcode.htm */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains code for a planes collider. * \file OPC_PlanesCollider.h * \author Pierre Terdiman * \date January, 1st, 2002 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Include Guard #ifndef __OPC_PLANESCOLLIDER_H__ #define __OPC_PLANESCOLLIDER_H__ struct OPCODE_API PlanesCache : VolumeCache { PlanesCache() { } }; class OPCODE_API PlanesCollider : public VolumeCollider { public: // Constructor / Destructor PlanesCollider(); virtual ~PlanesCollider(); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Generic collision query for generic OPCODE models. After the call, access the results: * - with GetContactStatus() * - with GetNbTouchedPrimitives() * - with GetTouchedPrimitives() * * \param cache [in/out] a planes cache * \param planes [in] list of planes in world space * \param nb_planes [in] number of planes * \param model [in] Opcode model to collide with * \param worldm [in] model's world matrix, or null * \return true if success * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool Collide(PlanesCache& cache, const Plane* planes, udword nb_planes, const Model& model, const Matrix4x4* worldm=null); // Mutant box-with-planes collision queries inline_ bool Collide(PlanesCache& cache, const OBB& box, const Model& model, const Matrix4x4* worldb=null, const Matrix4x4* worldm=null) { Plane PL[6]; if(worldb) { // Create a new OBB in world space OBB WorldBox; box.Rotate(*worldb, WorldBox); // Compute planes from the sides of the box WorldBox.ComputePlanes(PL); } else { // Compute planes from the sides of the box box.ComputePlanes(PL); } // Collide with box planes return Collide(cache, PL, 6, model, worldm); } // Settings /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Validates current settings. You should call this method after all the settings and callbacks have been defined for a collider. * \return null if everything is ok, else a string describing the problem */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// override(Collider) const char* ValidateSettings(); protected: // Planes in model space udword mNbPlanes; Plane* mPlanes; // Leaf description VertexPointers mVP; ConversionArea mVC; // Internal methods void _Collide(const AABBCollisionNode* node, udword clip_mask); void _Collide(const AABBNoLeafNode* node, udword clip_mask); void _Collide(const AABBQuantizedNode* node, udword clip_mask); void _Collide(const AABBQuantizedNoLeafNode* node, udword clip_mask); void _CollideNoPrimitiveTest(const AABBCollisionNode* node, udword clip_mask); void _CollideNoPrimitiveTest(const AABBNoLeafNode* node, udword clip_mask); void _CollideNoPrimitiveTest(const AABBQuantizedNode* node, udword clip_mask); void _CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node, udword clip_mask); // Overlap tests inline_ BOOL PlanesAABBOverlap(const Point& center, const Point& extents, udword& out_clip_mask, udword in_clip_mask); inline_ BOOL PlanesTriOverlap(udword in_clip_mask); // Init methods BOOL InitQuery(PlanesCache& cache, const Plane* planes, udword nb_planes, const Matrix4x4* worldm=null); }; class OPCODE_API HybridPlanesCollider : public PlanesCollider { public: // Constructor / Destructor HybridPlanesCollider(); virtual ~HybridPlanesCollider(); bool Collide(PlanesCache& cache, const Plane* planes, udword nb_planes, const HybridModel& model, const Matrix4x4* worldm=null); protected: Container mTouchedBoxes; }; #endif // __OPC_PLANESCOLLIDER_H__ ode-0.16/OPCODE/OPC_Model.cpp0000664000175200017520000002066213403272463012366 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* * OPCODE - Optimized Collision Detection * Copyright (C) 2001 Pierre Terdiman * Homepage: http://www.codercorner.com/Opcode.htm */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains code for OPCODE models. * \file OPC_Model.cpp * \author Pierre Terdiman * \date March, 20, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * The main collision wrapper, for all trees. Supported trees are: * - Normal trees (2*N-1 nodes, full size) * - No-leaf trees (N-1 nodes, full size) * - Quantized trees (2*N-1 nodes, half size) * - Quantized no-leaf trees (N-1 nodes, half size) * * Usage: * * 1) Create a static mesh interface using callbacks or pointers. (see OPC_MeshInterface.cpp). * Keep it around in your app, since a pointer to this interface is saved internally and * used until you release the collision structures. * * 2) Build a Model using a creation structure: * * \code * Model Sample; * * OPCODECREATE OPCC; * OPCC.IMesh = ...; * OPCC.Rules = ...; * OPCC.NoLeaf = ...; * OPCC.Quantized = ...; * OPCC.KeepOriginal = ...; * bool Status = Sample.Build(OPCC); * \endcode * * 3) Create a tree collider and set it up: * * \code * AABBTreeCollider TC; * TC.SetFirstContact(...); * TC.SetFullBoxBoxTest(...); * TC.SetFullPrimBoxTest(...); * TC.SetTemporalCoherence(...); * \endcode * * 4) Perform a collision query * * \code * // Setup cache * static BVTCache ColCache; * ColCache.Model0 = &Model0; * ColCache.Model1 = &Model1; * * // Collision query * bool IsOk = TC.Collide(ColCache, World0, World1); * * // Get collision status => if true, objects overlap * BOOL Status = TC.GetContactStatus(); * * // Number of colliding pairs and list of pairs * udword NbPairs = TC.GetNbPairs(); * const Pair* p = TC.GetPairs() * \endcode * * 5) Stats * * \code * Model0.GetUsedBytes() = number of bytes used for this collision tree * TC.GetNbBVBVTests() = number of BV-BV overlap tests performed during last query * TC.GetNbPrimPrimTests() = number of Triangle-Triangle overlap tests performed during last query * TC.GetNbBVPrimTests() = number of Triangle-BV overlap tests performed during last query * \endcode * * \class Model * \author Pierre Terdiman * \version 1.3 * \date March, 20, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Precompiled Header #include "Stdafx.h" using namespace Opcode; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Constructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Model::Model() { #ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE ! mHull = null; #endif // __MESHMERIZER_H__ } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Destructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Model::~Model() { Release(); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Releases the model. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void Model::Release() { ReleaseBase(); #ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE ! DELETESINGLE(mHull); #endif // __MESHMERIZER_H__ } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Builds a collision model. * \param create [in] model creation structure * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool Model::Build(const OPCODECREATE& create) { // 1) Checkings if(!create.mIMesh || !create.mIMesh->IsValid()) return false; // For this model, we only support complete trees if(create.mSettings.mLimit!=1) return SetIceError("OPCODE WARNING: supports complete trees only! Use mLimit = 1.\n", null); // Look for degenerate faces. //udword NbDegenerate = create.mIMesh->CheckTopology(); //if(NbDegenerate) Log("OPCODE WARNING: found %d degenerate faces in model! Collision might report wrong results!\n", NbDegenerate); // We continue nonetheless.... Release(); // Make sure previous tree has been discarded [Opcode 1.3, thanks Adam] // 1-1) Setup mesh interface automatically [Opcode 1.3] SetMeshInterface(create.mIMesh); // Special case for 1-triangle meshes [Opcode 1.3] udword NbTris = create.mIMesh->GetNbTriangles(); if(NbTris==1) { // We don't need to actually create a tree here, since we'll only have a single triangle to deal with anyway. // It's a waste to use a "model" for this but at least it will work. mModelCode |= OPC_SINGLE_NODE; return true; } // 2) Build a generic AABB Tree. mSource = new AABBTree; CHECKALLOC(mSource); // 2-1) Setup a builder. Our primitives here are triangles from input mesh, // so we use an AABBTreeOfTrianglesBuilder..... { AABBTreeOfTrianglesBuilder TB; TB.mIMesh = create.mIMesh; TB.mSettings = create.mSettings; TB.mNbPrimitives = NbTris; if(!mSource->Build(&TB)) return false; } // 3) Create an optimized tree according to user-settings if(!CreateTree(create.mNoLeaf, create.mQuantized)) return false; // 3-2) Create optimized tree if(!mTree->Build(mSource)) return false; // 3-3) Delete generic tree if needed if(!create.mKeepOriginal) DELETESINGLE(mSource); #ifdef __MESHMERIZER_H__ // 4) Convex hull if(create.mCollisionHull) { // Create hull mHull = new CollisionHull; CHECKALLOC(mHull); CONVEXHULLCREATE CHC; // ### doesn't work with strides CHC.NbVerts = create.mIMesh->GetNbVertices(); CHC.Vertices = create.mIMesh->GetVerts(); CHC.UnifyNormals = true; CHC.ReduceVertices = true; CHC.WordFaces = false; mHull->Compute(CHC); } #endif // __MESHMERIZER_H__ return true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Gets the number of bytes used by the tree. * \return amount of bytes used */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// udword Model::GetUsedBytes() const { if(!mTree) return 0; return mTree->GetUsedBytes(); } ode-0.16/OPCODE/OPC_RayAABBOverlap.h0000664000175200017520000000677613403272463013477 00000000000000// Opcode 1.1: ray-AABB overlap tests based on Woo's code // Opcode 1.2: ray-AABB overlap tests based on the separating axis theorem // // The point of intersection is not computed anymore. The distance to impact is not needed anymore // since we now have two different queries for segments or rays. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes a segment-AABB overlap test using the separating axis theorem. Segment is cached within the class. * \param center [in] AABB center * \param extents [in] AABB extents * \return true on overlap */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ BOOL RayCollider::SegmentAABBOverlap(const Point& center, const Point& extents) { // Stats mNbRayBVTests++; float Dx = mData2.x - center.x; if(fabsf(Dx) > extents.x + mFDir.x) return FALSE; float Dy = mData2.y - center.y; if(fabsf(Dy) > extents.y + mFDir.y) return FALSE; float Dz = mData2.z - center.z; if(fabsf(Dz) > extents.z + mFDir.z) return FALSE; float f; f = mData.y * Dz - mData.z * Dy; if(fabsf(f) > extents.y*mFDir.z + extents.z*mFDir.y) return FALSE; f = mData.z * Dx - mData.x * Dz; if(fabsf(f) > extents.x*mFDir.z + extents.z*mFDir.x) return FALSE; f = mData.x * Dy - mData.y * Dx; if(fabsf(f) > extents.x*mFDir.y + extents.y*mFDir.x) return FALSE; return TRUE; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes a ray-AABB overlap test using the separating axis theorem. Ray is cached within the class. * \param center [in] AABB center * \param extents [in] AABB extents * \return true on overlap */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ BOOL RayCollider::RayAABBOverlap(const Point& center, const Point& extents) { // Stats mNbRayBVTests++; // float Dx = mOrigin.x - center.x; if(fabsf(Dx) > extents.x && Dx*mDir.x>=0.0f) return FALSE; // float Dy = mOrigin.y - center.y; if(fabsf(Dy) > extents.y && Dy*mDir.y>=0.0f) return FALSE; // float Dz = mOrigin.z - center.z; if(fabsf(Dz) > extents.z && Dz*mDir.z>=0.0f) return FALSE; float Dx = mOrigin.x - center.x; if(GREATER(Dx, extents.x) && Dx*mDir.x>=0.0f) return FALSE; float Dy = mOrigin.y - center.y; if(GREATER(Dy, extents.y) && Dy*mDir.y>=0.0f) return FALSE; float Dz = mOrigin.z - center.z; if(GREATER(Dz, extents.z) && Dz*mDir.z>=0.0f) return FALSE; // float Dx = mOrigin.x - center.x; if(GREATER(Dx, extents.x) && ((SIR(Dx)-1)^SIR(mDir.x))>=0.0f) return FALSE; // float Dy = mOrigin.y - center.y; if(GREATER(Dy, extents.y) && ((SIR(Dy)-1)^SIR(mDir.y))>=0.0f) return FALSE; // float Dz = mOrigin.z - center.z; if(GREATER(Dz, extents.z) && ((SIR(Dz)-1)^SIR(mDir.z))>=0.0f) return FALSE; float f; f = mDir.y * Dz - mDir.z * Dy; if(fabsf(f) > extents.y*mFDir.z + extents.z*mFDir.y) return FALSE; f = mDir.z * Dx - mDir.x * Dz; if(fabsf(f) > extents.x*mFDir.z + extents.z*mFDir.x) return FALSE; f = mDir.x * Dy - mDir.y * Dx; if(fabsf(f) > extents.x*mFDir.y + extents.y*mFDir.x) return FALSE; return TRUE; } ode-0.16/OPCODE/OPC_Model.h0000664000175200017520000000653713403272463012040 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* * OPCODE - Optimized Collision Detection * Copyright (C) 2001 Pierre Terdiman * Homepage: http://www.codercorner.com/Opcode.htm */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains code for OPCODE models. * \file OPC_Model.h * \author Pierre Terdiman * \date March, 20, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Include Guard #ifndef __OPC_MODEL_H__ #define __OPC_MODEL_H__ class OPCODE_API Model : public BaseModel { public: // Constructor/Destructor Model(); virtual ~Model(); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Builds a collision model. * \param create [in] model creation structure * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// override(BaseModel) bool Build(const OPCODECREATE& create); #ifdef __MESHMERIZER_H__ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Gets the collision hull. * \return the collision hull if it exists */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ const CollisionHull* GetHull() const { return mHull; } #endif // __MESHMERIZER_H__ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Gets the number of bytes used by the tree. * \return amount of bytes used */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// override(BaseModel) udword GetUsedBytes() const; private: #ifdef __MESHMERIZER_H__ CollisionHull* mHull; //!< Possible convex hull #endif // __MESHMERIZER_H__ // Internal methods void Release(); }; #endif //__OPC_MODEL_H__ ode-0.16/OPCODE/OPC_RayCollider.cpp0000664000175200017520000007124013403272463013535 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* * OPCODE - Optimized Collision Detection * Copyright (C) 2001 Pierre Terdiman * Homepage: http://www.codercorner.com/Opcode.htm */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains code for a ray collider. * \file OPC_RayCollider.cpp * \author Pierre Terdiman * \date June, 2, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains a ray-vs-tree collider. * This class performs a stabbing query on an AABB tree, i.e. does a ray-mesh collision. * * HIGHER DISTANCE BOUND: * * If P0 and P1 are two 3D points, let's define: * - d = distance between P0 and P1 * - Origin = P0 * - Direction = (P1 - P0) / d = normalized direction vector * - A parameter t such as a point P on the line (P0,P1) is P = Origin + t * Direction * - t = 0 --> P = P0 * - t = d --> P = P1 * * Then we can define a general "ray" as: * * struct Ray * { * Point Origin; * Point Direction; * }; * * But it actually maps three different things: * - a segment, when 0 <= t <= d * - a half-line, when 0 <= t < +infinity, or -infinity < t <= d * - a line, when -infinity < t < +infinity * * In Opcode, we support segment queries, which yield half-line queries by setting d = +infinity. * We don't support line-queries. If you need them, shift the origin along the ray by an appropriate margin. * * In short, the lower bound is always 0, and you can setup the higher bound "d" with RayCollider::SetMaxDist(). * * Query |segment |half-line |line * --------|-------------------|---------------|---------------- * Usages |-shadow feelers |-raytracing |- * |-sweep tests |-in/out tests | * * FIRST CONTACT: * * - You can setup "first contact" mode or "all contacts" mode with RayCollider::SetFirstContact(). * - In "first contact" mode we return as soon as the ray hits one face. If can be useful e.g. for shadow feelers, where * you want to know whether the path to the light is free or not (a boolean answer is enough). * - In "all contacts" mode we return all faces hit by the ray. * * TEMPORAL COHERENCE: * * - You can enable or disable temporal coherence with RayCollider::SetTemporalCoherence(). * - It currently only works in "first contact" mode. * - If temporal coherence is enabled, the previously hit triangle is cached during the first query. Then, next queries * start by colliding the ray against the cached triangle. If they still collide, we return immediately. * * CLOSEST HIT: * * - You can enable or disable "closest hit" with RayCollider::SetClosestHit(). * - It currently only works in "all contacts" mode. * - If closest hit is enabled, faces are sorted by distance on-the-fly and the closest one only is reported. * * BACKFACE CULLING: * * - You can enable or disable backface culling with RayCollider::SetCulling(). * - If culling is enabled, ray will not hit back faces (only front faces). * * * * \class RayCollider * \author Pierre Terdiman * \version 1.3 * \date June, 2, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * This class describes a face hit by a ray or segment. * This is a particular class dedicated to stabbing queries. * * \class CollisionFace * \author Pierre Terdiman * \version 1.3 * \date March, 20, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * This class is a dedicated collection of CollisionFace. * * \class CollisionFaces * \author Pierre Terdiman * \version 1.3 * \date March, 20, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Precompiled Header #include "Stdafx.h" using namespace Opcode; #include "OPC_RayAABBOverlap.h" #include "OPC_RayTriOverlap.h" #define SET_CONTACT(prim_index, flag) \ mNbIntersections++; \ /* Set contact status */ \ mFlags |= flag; \ /* In any case the contact has been found and recorded in mStabbedFace */ \ mStabbedFace.mFaceID = prim_index; #ifdef OPC_RAYHIT_CALLBACK #define HANDLE_CONTACT(prim_index, flag) \ SET_CONTACT(prim_index, flag) \ \ if(mHitCallback) (mHitCallback)(mStabbedFace, mUserData); #define UPDATE_CACHE \ if(cache && GetContactStatus()) \ { \ *cache = mStabbedFace.mFaceID; \ } #else #define HANDLE_CONTACT(prim_index, flag) \ SET_CONTACT(prim_index, flag) \ \ /* Now we can also record it in mStabbedFaces if available */ \ if(mStabbedFaces) \ { \ /* If we want all faces or if that's the first one we hit */ \ if(!mClosestHit || !mStabbedFaces->GetNbFaces()) \ { \ mStabbedFaces->AddFace(mStabbedFace); \ } \ else \ { \ /* We only keep closest hit */ \ CollisionFace* Current = const_cast(mStabbedFaces->GetFaces()); \ if(Current && mStabbedFace.mDistancemDistance) \ { \ *Current = mStabbedFace; \ } \ } \ } #define UPDATE_CACHE \ if(cache && GetContactStatus() && mStabbedFaces) \ { \ const CollisionFace* Current = mStabbedFaces->GetFaces(); \ if(Current) *cache = Current->mFaceID; \ else *cache = INVALID_ID; \ } #endif #define SEGMENT_PRIM(prim_index, flag) \ /* Request vertices from the app */ \ VertexPointers VP; ConversionArea VC; mIMesh->GetTriangle(VP, prim_index, VC); \ \ /* Perform ray-tri overlap test and return */ \ if(RayTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) \ { \ /* Intersection point is valid if dist < segment's length */ \ /* We know dist>0 so we can use integers */ \ if(IR(mStabbedFace.mDistance)GetTriangle(VP, prim_index, VC); \ \ /* Perform ray-tri overlap test and return */ \ if(RayTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) \ { \ HANDLE_CONTACT(prim_index, flag) \ } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Constructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// RayCollider::RayCollider() : #ifdef OPC_RAYHIT_CALLBACK mHitCallback (null), mUserData (0), #else mStabbedFaces (null), mClosestHit (false), #endif mNbRayBVTests (0), mNbRayPrimTests (0), mNbIntersections (0), mMaxDist (MAX_FLOAT), mCulling (true) { } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Destructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// RayCollider::~RayCollider() { } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Validates current settings. You should call this method after all the settings and callbacks have been defined. * \return null if everything is ok, else a string describing the problem */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// const char* RayCollider::ValidateSettings() { if(mMaxDist<0.0f) return "Higher distance bound must be positive!"; if(TemporalCoherenceEnabled() && !FirstContactEnabled()) return "Temporal coherence only works with ""First contact"" mode!"; #ifndef OPC_RAYHIT_CALLBACK if(mClosestHit && FirstContactEnabled()) return "Closest hit doesn't work with ""First contact"" mode!"; if(TemporalCoherenceEnabled() && mClosestHit) return "Temporal coherence can't guarantee to report closest hit!"; #endif if(SkipPrimitiveTests()) return "SkipPrimitiveTests not possible for RayCollider ! (not implemented)"; return null; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Generic stabbing query for generic OPCODE models. After the call, access the results: * - with GetContactStatus() * - in the user-provided destination array * * \param world_ray [in] stabbing ray in world space * \param model [in] Opcode model to collide with * \param world [in] model's world matrix, or null * \param cache [in] a possibly cached face index, or null * \return true if success * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool RayCollider::Collide(const Ray& world_ray, const Model& model, const Matrix4x4* world, udword* cache) { // Checkings if(!Setup(&model)) return false; // Init collision query if(InitQuery(world_ray, world, cache)) return true; if(!model.HasLeafNodes()) { if(model.IsQuantized()) { const AABBQuantizedNoLeafTree* Tree = static_cast(model.GetTree()); // Setup dequantization coeffs mCenterCoeff = Tree->mCenterCoeff; mExtentsCoeff = Tree->mExtentsCoeff; // Perform stabbing query if(IR(mMaxDist)!=IEEE_MAX_FLOAT) _SegmentStab(Tree->GetNodes()); else _RayStab(Tree->GetNodes()); } else { const AABBNoLeafTree* Tree = static_cast(model.GetTree()); // Perform stabbing query if(IR(mMaxDist)!=IEEE_MAX_FLOAT) _SegmentStab(Tree->GetNodes()); else _RayStab(Tree->GetNodes()); } } else { if(model.IsQuantized()) { const AABBQuantizedTree* Tree = static_cast(model.GetTree()); // Setup dequantization coeffs mCenterCoeff = Tree->mCenterCoeff; mExtentsCoeff = Tree->mExtentsCoeff; // Perform stabbing query if(IR(mMaxDist)!=IEEE_MAX_FLOAT) _SegmentStab(Tree->GetNodes()); else _RayStab(Tree->GetNodes()); } else { const AABBCollisionTree* Tree = static_cast(model.GetTree()); // Perform stabbing query if(IR(mMaxDist)!=IEEE_MAX_FLOAT) _SegmentStab(Tree->GetNodes()); else _RayStab(Tree->GetNodes()); } } // Update cache if needed UPDATE_CACHE; return true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Initializes a stabbing query : * - reset stats & contact status * - compute ray in local space * - check temporal coherence * * \param world_ray [in] stabbing ray in world space * \param world [in] object's world matrix, or null * \param face_id [in] index of previously stabbed triangle * \return TRUE if we can return immediately * \warning SCALE NOT SUPPORTED. The matrix must contain rotation & translation parts only. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// BOOL RayCollider::InitQuery(const Ray& world_ray, const Matrix4x4* world, udword* face_id) { // Reset stats & contact status Collider::InitQuery(); mNbRayBVTests = 0; mNbRayPrimTests = 0; mNbIntersections = 0; #ifndef OPC_RAYHIT_CALLBACK if(mStabbedFaces) mStabbedFaces->Reset(); #endif // Compute ray in local space // The (Origin/Dir) form is needed for the ray-triangle test anyway (even for segment tests) if(world) { Matrix3x3 InvWorld = *world; mDir = InvWorld * world_ray.mDir; Matrix4x4 World; InvertPRMatrix(World, *world); mOrigin = world_ray.mOrig * World; } else { mDir = world_ray.mDir; mOrigin = world_ray.mOrig; } // 4) Special case: 1-triangle meshes [Opcode 1.3] if(mCurrentModel && mCurrentModel->HasSingleNode()) { // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0. if(!SkipPrimitiveTests()) { // Perform overlap test between the unique triangle and the ray (and set contact status if needed) SEGMENT_PRIM(udword(0), OPC_CONTACT) // Return immediately regardless of status return TRUE; } } // Check temporal coherence : // Test previously colliding primitives first if(TemporalCoherenceEnabled() && FirstContactEnabled() && face_id && *face_id!=INVALID_ID) { #ifdef OLD_CODE #ifndef OPC_RAYHIT_CALLBACK if(!mClosestHit) #endif { // Request vertices from the app VertexPointers VP; ConversionArea VC; mIMesh->GetTriangle(VP, *face_id, VC); // Perform ray-cached tri overlap test if(RayTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) { // Intersection point is valid if: // - distance is positive (else it can just be a face behind the orig point) // - distance is smaller than a given max distance (useful for shadow feelers) // if(mStabbedFace.mDistance>0.0f && mStabbedFace.mDistanceAddFace(mStabbedFace); #endif return TRUE; } } } #else // New code // We handle both Segment/ray queries with the same segment code, and a possible infinite limit SEGMENT_PRIM(*face_id, OPC_TEMPORAL_CONTACT) // Return immediately if possible if(GetContactStatus()) return TRUE; #endif } // Precompute data (moved after temporal coherence since only needed for ray-AABB) if(IR(mMaxDist)!=IEEE_MAX_FLOAT) { // For Segment-AABB overlap mData = 0.5f * mDir * mMaxDist; mData2 = mOrigin + mData; // Precompute mFDir; mFDir.x = fabsf(mData.x); mFDir.y = fabsf(mData.y); mFDir.z = fabsf(mData.z); } else { // For Ray-AABB overlap // udword x = SIR(mDir.x)-1; // udword y = SIR(mDir.y)-1; // udword z = SIR(mDir.z)-1; // mData.x = FR(x); // mData.y = FR(y); // mData.z = FR(z); // Precompute mFDir; mFDir.x = fabsf(mDir.x); mFDir.y = fabsf(mDir.y); mFDir.z = fabsf(mDir.z); } return FALSE; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Stabbing query for vanilla AABB trees. * \param world_ray [in] stabbing ray in world space * \param tree [in] AABB tree * \param box_indices [out] indices of stabbed boxes * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool RayCollider::Collide(const Ray& world_ray, const AABBTree* tree, Container& box_indices) { // ### bad design here // This is typically called for a scene tree, full of -AABBs-, not full of triangles. // So we don't really have "primitives" to deal with. Hence it doesn't work with // "FirstContact" + "TemporalCoherence". ASSERT( !(FirstContactEnabled() && TemporalCoherenceEnabled()) ); // Checkings if(!tree) return false; // Init collision query // Basically this is only called to initialize precomputed data if(InitQuery(world_ray)) return true; // Perform stabbing query if(IR(mMaxDist)!=IEEE_MAX_FLOAT) _SegmentStab(tree, box_indices); else _RayStab(tree, box_indices); return true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive stabbing query for normal AABB trees. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void RayCollider::_SegmentStab(const AABBCollisionNode* node) { // Perform Segment-AABB overlap test if(!SegmentAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; if(node->IsLeaf()) { SEGMENT_PRIM(node->GetPrimitive(), OPC_CONTACT) } else { _SegmentStab(node->GetPos()); if(ContactFound()) return; _SegmentStab(node->GetNeg()); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive stabbing query for quantized AABB trees. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void RayCollider::_SegmentStab(const AABBQuantizedNode* node) { // Dequantize box const QuantizedAABB& Box = node->mAABB; const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); // Perform Segment-AABB overlap test if(!SegmentAABBOverlap(Center, Extents)) return; if(node->IsLeaf()) { SEGMENT_PRIM(node->GetPrimitive(), OPC_CONTACT) } else { _SegmentStab(node->GetPos()); if(ContactFound()) return; _SegmentStab(node->GetNeg()); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive stabbing query for no-leaf AABB trees. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void RayCollider::_SegmentStab(const AABBNoLeafNode* node) { // Perform Segment-AABB overlap test if(!SegmentAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; if(node->HasPosLeaf()) { SEGMENT_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } else _SegmentStab(node->GetPos()); if(ContactFound()) return; if(node->HasNegLeaf()) { SEGMENT_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } else _SegmentStab(node->GetNeg()); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive stabbing query for quantized no-leaf AABB trees. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void RayCollider::_SegmentStab(const AABBQuantizedNoLeafNode* node) { // Dequantize box const QuantizedAABB& Box = node->mAABB; const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); // Perform Segment-AABB overlap test if(!SegmentAABBOverlap(Center, Extents)) return; if(node->HasPosLeaf()) { SEGMENT_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } else _SegmentStab(node->GetPos()); if(ContactFound()) return; if(node->HasNegLeaf()) { SEGMENT_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } else _SegmentStab(node->GetNeg()); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive stabbing query for vanilla AABB trees. * \param node [in] current collision node * \param box_indices [out] indices of stabbed boxes */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void RayCollider::_SegmentStab(const AABBTreeNode* node, Container& box_indices) { // Test the box against the segment Point Center, Extents; node->GetAABB()->GetCenter(Center); node->GetAABB()->GetExtents(Extents); if(!SegmentAABBOverlap(Center, Extents)) return; if(node->IsLeaf()) { box_indices.Add(node->GetPrimitives(), node->GetNbPrimitives()); } else { _SegmentStab(node->GetPos(), box_indices); _SegmentStab(node->GetNeg(), box_indices); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive stabbing query for normal AABB trees. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void RayCollider::_RayStab(const AABBCollisionNode* node) { // Perform Ray-AABB overlap test if(!RayAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; if(node->IsLeaf()) { RAY_PRIM(node->GetPrimitive(), OPC_CONTACT) } else { _RayStab(node->GetPos()); if(ContactFound()) return; _RayStab(node->GetNeg()); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive stabbing query for quantized AABB trees. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void RayCollider::_RayStab(const AABBQuantizedNode* node) { // Dequantize box const QuantizedAABB& Box = node->mAABB; const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); // Perform Ray-AABB overlap test if(!RayAABBOverlap(Center, Extents)) return; if(node->IsLeaf()) { RAY_PRIM(node->GetPrimitive(), OPC_CONTACT) } else { _RayStab(node->GetPos()); if(ContactFound()) return; _RayStab(node->GetNeg()); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive stabbing query for no-leaf AABB trees. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void RayCollider::_RayStab(const AABBNoLeafNode* node) { // Perform Ray-AABB overlap test if(!RayAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; if(node->HasPosLeaf()) { RAY_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } else _RayStab(node->GetPos()); if(ContactFound()) return; if(node->HasNegLeaf()) { RAY_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } else _RayStab(node->GetNeg()); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive stabbing query for quantized no-leaf AABB trees. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void RayCollider::_RayStab(const AABBQuantizedNoLeafNode* node) { // Dequantize box const QuantizedAABB& Box = node->mAABB; const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); // Perform Ray-AABB overlap test if(!RayAABBOverlap(Center, Extents)) return; if(node->HasPosLeaf()) { RAY_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } else _RayStab(node->GetPos()); if(ContactFound()) return; if(node->HasNegLeaf()) { RAY_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } else _RayStab(node->GetNeg()); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive stabbing query for vanilla AABB trees. * \param node [in] current collision node * \param box_indices [out] indices of stabbed boxes */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void RayCollider::_RayStab(const AABBTreeNode* node, Container& box_indices) { // Test the box against the ray Point Center, Extents; node->GetAABB()->GetCenter(Center); node->GetAABB()->GetExtents(Extents); if(!RayAABBOverlap(Center, Extents)) return; if(node->IsLeaf()) { mFlags |= OPC_CONTACT; box_indices.Add(node->GetPrimitives(), node->GetNbPrimitives()); } else { _RayStab(node->GetPos(), box_indices); _RayStab(node->GetNeg(), box_indices); } } ode-0.16/OPCODE/OPC_LSSTriOverlap.h0000664000175200017520000005130213403272463013437 00000000000000// Following code from Magic-Software (http://www.magic-software.com/) // A bit modified for Opcode static const float gs_fTolerance = 1e-05f; static float OPC_PointTriangleSqrDist(const Point& point, const Point& p0, const Point& p1, const Point& p2) { // Hook Point TriEdge0 = p1 - p0; Point TriEdge1 = p2 - p0; Point kDiff = p0 - point; float fA00 = TriEdge0.SquareMagnitude(); float fA01 = TriEdge0 | TriEdge1; float fA11 = TriEdge1.SquareMagnitude(); float fB0 = kDiff | TriEdge0; float fB1 = kDiff | TriEdge1; float fC = kDiff.SquareMagnitude(); float fDet = fabsf(fA00*fA11 - fA01*fA01); float fS = fA01*fB1-fA11*fB0; float fT = fA01*fB0-fA00*fB1; float fSqrDist; if(fS + fT <= fDet) { if(fS < 0.0f) { if(fT < 0.0f) // region 4 { if(fB0 < 0.0f) { if(-fB0 >= fA00) fSqrDist = fA00+2.0f*fB0+fC; else fSqrDist = fB0*(-fB0/fA00)+fC; } else { if(fB1 >= 0.0f) fSqrDist = fC; else if(-fB1 >= fA11) fSqrDist = fA11+2.0f*fB1+fC; else fSqrDist = fB1*(-fB1/fA11)+fC; } } else // region 3 { if(fB1 >= 0.0f) fSqrDist = fC; else if(-fB1 >= fA11) fSqrDist = fA11+2.0f*fB1+fC; else fSqrDist = fB1*(-fB1/fA11)+fC; } } else if(fT < 0.0f) // region 5 { if(fB0 >= 0.0f) fSqrDist = fC; else if(-fB0 >= fA00) fSqrDist = fA00+2.0f*fB0+fC; else fSqrDist = fB0*(-fB0/fA00)+fC; } else // region 0 { // minimum at interior point if(fDet==0.0f) { fSqrDist = MAX_FLOAT; } else { float fInvDet = 1.0f/fDet; fS *= fInvDet; fT *= fInvDet; fSqrDist = fS*(fA00*fS+fA01*fT+2.0f*fB0) + fT*(fA01*fS+fA11*fT+2.0f*fB1)+fC; } } } else { float fTmp0, fTmp1, fNumer, fDenom; if(fS < 0.0f) // region 2 { fTmp0 = fA01 + fB0; fTmp1 = fA11 + fB1; if(fTmp1 > fTmp0) { fNumer = fTmp1 - fTmp0; fDenom = fA00-2.0f*fA01+fA11; if(fNumer >= fDenom) { fSqrDist = fA00+2.0f*fB0+fC; } else { fS = fNumer/fDenom; fT = 1.0f - fS; fSqrDist = fS*(fA00*fS+fA01*fT+2.0f*fB0) + fT*(fA01*fS+fA11*fT+2.0f*fB1)+fC; } } else { if(fTmp1 <= 0.0f) fSqrDist = fA11+2.0f*fB1+fC; else if(fB1 >= 0.0f) fSqrDist = fC; else fSqrDist = fB1*(-fB1/fA11)+fC; } } else if(fT < 0.0f) // region 6 { fTmp0 = fA01 + fB1; fTmp1 = fA00 + fB0; if(fTmp1 > fTmp0) { fNumer = fTmp1 - fTmp0; fDenom = fA00-2.0f*fA01+fA11; if(fNumer >= fDenom) { fSqrDist = fA11+2.0f*fB1+fC; } else { fT = fNumer/fDenom; fS = 1.0f - fT; fSqrDist = fS*(fA00*fS+fA01*fT+2.0f*fB0) + fT*(fA01*fS+fA11*fT+2.0f*fB1)+fC; } } else { if(fTmp1 <= 0.0f) fSqrDist = fA00+2.0f*fB0+fC; else if(fB0 >= 0.0f) fSqrDist = fC; else fSqrDist = fB0*(-fB0/fA00)+fC; } } else // region 1 { fNumer = fA11 + fB1 - fA01 - fB0; if(fNumer <= 0.0f) { fSqrDist = fA11+2.0f*fB1+fC; } else { fDenom = fA00-2.0f*fA01+fA11; if(fNumer >= fDenom) { fSqrDist = fA00+2.0f*fB0+fC; } else { fS = fNumer/fDenom; fT = 1.0f - fS; fSqrDist = fS*(fA00*fS+fA01*fT+2.0f*fB0) + fT*(fA01*fS+fA11*fT+2.0f*fB1)+fC; } } } } return fabsf(fSqrDist); } static float OPC_SegmentSegmentSqrDist(const Segment& rkSeg0, const Segment& rkSeg1) { // Hook Point rkSeg0Direction = rkSeg0.ComputeDirection(); Point rkSeg1Direction = rkSeg1.ComputeDirection(); Point kDiff = rkSeg0.mP0 - rkSeg1.mP0; float fA00 = rkSeg0Direction.SquareMagnitude(); float fA01 = -rkSeg0Direction.Dot(rkSeg1Direction); float fA11 = rkSeg1Direction.SquareMagnitude(); float fB0 = kDiff.Dot(rkSeg0Direction); float fC = kDiff.SquareMagnitude(); float fDet = fabsf(fA00*fA11-fA01*fA01); float fB1, fS, fT, fSqrDist, fTmp; if(fDet>=gs_fTolerance) { // line segments are not parallel fB1 = -kDiff.Dot(rkSeg1Direction); fS = fA01*fB1-fA11*fB0; fT = fA01*fB0-fA00*fB1; if(fS >= 0.0f) { if(fS <= fDet) { if(fT >= 0.0f) { if(fT <= fDet) // region 0 (interior) { // minimum at two interior points of 3D lines float fInvDet = 1.0f/fDet; fS *= fInvDet; fT *= fInvDet; fSqrDist = fS*(fA00*fS+fA01*fT+2.0f*fB0) + fT*(fA01*fS+fA11*fT+2.0f*fB1)+fC; } else // region 3 (side) { fTmp = fA01+fB0; if(fTmp>=0.0f) fSqrDist = fA11+2.0f*fB1+fC; else if(-fTmp>=fA00) fSqrDist = fA00+fA11+fC+2.0f*(fB1+fTmp); else fSqrDist = fTmp*(-fTmp/fA00)+fA11+2.0f*fB1+fC; } } else // region 7 (side) { if(fB0>=0.0f) fSqrDist = fC; else if(-fB0>=fA00) fSqrDist = fA00+2.0f*fB0+fC; else fSqrDist = fB0*(-fB0/fA00)+fC; } } else { if ( fT >= 0.0 ) { if ( fT <= fDet ) // region 1 (side) { fTmp = fA01+fB1; if(fTmp>=0.0f) fSqrDist = fA00+2.0f*fB0+fC; else if(-fTmp>=fA11) fSqrDist = fA00+fA11+fC+2.0f*(fB0+fTmp); else fSqrDist = fTmp*(-fTmp/fA11)+fA00+2.0f*fB0+fC; } else // region 2 (corner) { fTmp = fA01+fB0; if ( -fTmp <= fA00 ) { if(fTmp>=0.0f) fSqrDist = fA11+2.0f*fB1+fC; else fSqrDist = fTmp*(-fTmp/fA00)+fA11+2.0f*fB1+fC; } else { fTmp = fA01+fB1; if(fTmp>=0.0f) fSqrDist = fA00+2.0f*fB0+fC; else if(-fTmp>=fA11) fSqrDist = fA00+fA11+fC+2.0f*(fB0+fTmp); else fSqrDist = fTmp*(-fTmp/fA11)+fA00+2.0f*fB0+fC; } } } else // region 8 (corner) { if ( -fB0 < fA00 ) { if(fB0>=0.0f) fSqrDist = fC; else fSqrDist = fB0*(-fB0/fA00)+fC; } else { fTmp = fA01+fB1; if(fTmp>=0.0f) fSqrDist = fA00+2.0f*fB0+fC; else if(-fTmp>=fA11) fSqrDist = fA00+fA11+fC+2.0f*(fB0+fTmp); else fSqrDist = fTmp*(-fTmp/fA11)+fA00+2.0f*fB0+fC; } } } } else { if ( fT >= 0.0f ) { if ( fT <= fDet ) // region 5 (side) { if(fB1>=0.0f) fSqrDist = fC; else if(-fB1>=fA11) fSqrDist = fA11+2.0f*fB1+fC; else fSqrDist = fB1*(-fB1/fA11)+fC; } else // region 4 (corner) { fTmp = fA01+fB0; if ( fTmp < 0.0f ) { if(-fTmp>=fA00) fSqrDist = fA00+fA11+fC+2.0f*(fB1+fTmp); else fSqrDist = fTmp*(-fTmp/fA00)+fA11+2.0f*fB1+fC; } else { if(fB1>=0.0f) fSqrDist = fC; else if(-fB1>=fA11) fSqrDist = fA11+2.0f*fB1+fC; else fSqrDist = fB1*(-fB1/fA11)+fC; } } } else // region 6 (corner) { if ( fB0 < 0.0f ) { if(-fB0>=fA00) fSqrDist = fA00+2.0f*fB0+fC; else fSqrDist = fB0*(-fB0/fA00)+fC; } else { if(fB1>=0.0f) fSqrDist = fC; else if(-fB1>=fA11) fSqrDist = fA11+2.0f*fB1+fC; else fSqrDist = fB1*(-fB1/fA11)+fC; } } } } else { // line segments are parallel if ( fA01 > 0.0f ) { // direction vectors form an obtuse angle if ( fB0 >= 0.0f ) { fSqrDist = fC; } else if ( -fB0 <= fA00 ) { fSqrDist = fB0*(-fB0/fA00)+fC; } else { fB1 = -kDiff.Dot(rkSeg1Direction); fTmp = fA00+fB0; if ( -fTmp >= fA01 ) { fSqrDist = fA00+fA11+fC+2.0f*(fA01+fB0+fB1); } else { fT = -fTmp/fA01; fSqrDist = fA00+2.0f*fB0+fC+fT*(fA11*fT+2.0f*(fA01+fB1)); } } } else { // direction vectors form an acute angle if ( -fB0 >= fA00 ) { fSqrDist = fA00+2.0f*fB0+fC; } else if ( fB0 <= 0.0f ) { fSqrDist = fB0*(-fB0/fA00)+fC; } else { fB1 = -kDiff.Dot(rkSeg1Direction); if ( fB0 >= -fA01 ) { fSqrDist = fA11+2.0f*fB1+fC; } else { fT = -fB0/fA01; fSqrDist = fC+fT*(2.0f*fB1+fA11*fT); } } } } return fabsf(fSqrDist); } inline_ float OPC_SegmentRaySqrDist(const Segment& rkSeg0, const Ray& rkSeg1) { return OPC_SegmentSegmentSqrDist(rkSeg0, Segment(rkSeg1.mOrig, rkSeg1.mOrig + rkSeg1.mDir)); } static float OPC_SegmentTriangleSqrDist(const Segment& segment, const Point& p0, const Point& p1, const Point& p2) { // Hook const Point TriEdge0 = p1 - p0; const Point TriEdge1 = p2 - p0; const Point& rkSegOrigin = segment.GetOrigin(); Point rkSegDirection = segment.ComputeDirection(); Point kDiff = p0 - rkSegOrigin; float fA00 = rkSegDirection.SquareMagnitude(); float fA01 = -rkSegDirection.Dot(TriEdge0); float fA02 = -rkSegDirection.Dot(TriEdge1); float fA11 = TriEdge0.SquareMagnitude(); float fA12 = TriEdge0.Dot(TriEdge1); float fA22 = TriEdge1.Dot(TriEdge1); float fB0 = -kDiff.Dot(rkSegDirection); float fB1 = kDiff.Dot(TriEdge0); float fB2 = kDiff.Dot(TriEdge1); float fCof00 = fA11*fA22-fA12*fA12; float fCof01 = fA02*fA12-fA01*fA22; float fCof02 = fA01*fA12-fA02*fA11; float fDet = fA00*fCof00+fA01*fCof01+fA02*fCof02; Ray kTriSeg; Point kPt; float fSqrDist, fSqrDist0; if(fabsf(fDet)>=gs_fTolerance) { float fCof11 = fA00*fA22-fA02*fA02; float fCof12 = fA02*fA01-fA00*fA12; float fCof22 = fA00*fA11-fA01*fA01; float fInvDet = 1.0f/fDet; float fRhs0 = -fB0*fInvDet; float fRhs1 = -fB1*fInvDet; float fRhs2 = -fB2*fInvDet; float fR = fCof00*fRhs0+fCof01*fRhs1+fCof02*fRhs2; float fS = fCof01*fRhs0+fCof11*fRhs1+fCof12*fRhs2; float fT = fCof02*fRhs0+fCof12*fRhs1+fCof22*fRhs2; if ( fR < 0.0f ) { if ( fS+fT <= 1.0f ) { if ( fS < 0.0f ) { if ( fT < 0.0f ) // region 4m { // min on face s=0 or t=0 or r=0 kTriSeg.mOrig = p0; kTriSeg.mDir = TriEdge1; fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg); kTriSeg.mOrig = p0; kTriSeg.mDir = TriEdge0; fSqrDist0 = OPC_SegmentRaySqrDist(segment, kTriSeg); if(fSqrDist0 1 { if ( fS+fT <= 1.0f ) { if ( fS < 0.0f ) { if ( fT < 0.0f ) // region 4p { // min on face s=0 or t=0 or r=1 kTriSeg.mOrig = p0; kTriSeg.mDir = TriEdge1; fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg); kTriSeg.mOrig = p0; kTriSeg.mDir = TriEdge0; fSqrDist0 = OPC_SegmentRaySqrDist(segment, kTriSeg); if(fSqrDist0Add(udword(prim_index)); //! AABB-triangle test #define AABB_PRIM(prim_index, flag) \ /* Request vertices from the app */ \ VertexPointers VP; ConversionArea VC; mIMesh->GetTriangle(VP, prim_index, VC); \ mLeafVerts[0] = *VP.Vertex[0]; \ mLeafVerts[1] = *VP.Vertex[1]; \ mLeafVerts[2] = *VP.Vertex[2]; \ /* Perform triangle-box overlap test */ \ if(TriBoxOverlap()) \ { \ SET_CONTACT(prim_index, flag) \ } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Constructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// AABBCollider::AABBCollider() { } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Destructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// AABBCollider::~AABBCollider() { } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Generic collision query for generic OPCODE models. After the call, access the results: * - with GetContactStatus() * - with GetNbTouchedPrimitives() * - with GetTouchedPrimitives() * * \param cache [in/out] a box cache * \param box [in] collision AABB in world space * \param model [in] Opcode model to collide with * \return true if success * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool AABBCollider::Collide(AABBCache& cache, const CollisionAABB& box, const Model& model) { // Checkings if(!Setup(&model)) return false; // Init collision query if(InitQuery(cache, box)) return true; if(!model.HasLeafNodes()) { if(model.IsQuantized()) { const AABBQuantizedNoLeafTree* Tree = static_cast(model.GetTree()); // Setup dequantization coeffs mCenterCoeff = Tree->mCenterCoeff; mExtentsCoeff = Tree->mExtentsCoeff; // Perform collision query if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); else _Collide(Tree->GetNodes()); } else { const AABBNoLeafTree* Tree = static_cast(model.GetTree()); // Perform collision query if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); else _Collide(Tree->GetNodes()); } } else { if(model.IsQuantized()) { const AABBQuantizedTree* Tree = static_cast(model.GetTree()); // Setup dequantization coeffs mCenterCoeff = Tree->mCenterCoeff; mExtentsCoeff = Tree->mExtentsCoeff; // Perform collision query if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); else _Collide(Tree->GetNodes()); } else { const AABBCollisionTree* Tree = static_cast(model.GetTree()); // Perform collision query if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); else _Collide(Tree->GetNodes()); } } return true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Initializes a collision query : * - reset stats & contact status * - check temporal coherence * * \param cache [in/out] a box cache * \param box [in] AABB in world space * \return TRUE if we can return immediately */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// BOOL AABBCollider::InitQuery(AABBCache& cache, const CollisionAABB& box) { // 1) Call the base method VolumeCollider::InitQuery(); // 2) Keep track of the query box mBox = box; // 3) Setup destination pointer mTouchedPrimitives = &cache.TouchedPrimitives; // 4) Special case: 1-triangle meshes [Opcode 1.3] if(mCurrentModel && mCurrentModel->HasSingleNode()) { if(!SkipPrimitiveTests()) { // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0. mTouchedPrimitives->Reset(); // Perform overlap test between the unique triangle and the box (and set contact status if needed) AABB_PRIM(udword(0), OPC_CONTACT) // Return immediately regardless of status return TRUE; } } // 5) Check temporal coherence : if(TemporalCoherenceEnabled()) { // Here we use temporal coherence // => check results from previous frame before performing the collision query if(FirstContactEnabled()) { // We're only interested in the first contact found => test the unique previously touched face if(mTouchedPrimitives->GetNbEntries()) { // Get index of previously touched face = the first entry in the array udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0); // Then reset the array: // - if the overlap test below is successful, the index we'll get added back anyway // - if it isn't, then the array should be reset anyway for the normal query mTouchedPrimitives->Reset(); // Perform overlap test between the cached triangle and the box (and set contact status if needed) AABB_PRIM(PreviouslyTouchedFace, OPC_TEMPORAL_CONTACT) // Return immediately if possible if(GetContactStatus()) return TRUE; } // else no face has been touched during previous query // => we'll have to perform a normal query } else { // We're interested in all contacts =>test the new real box N(ew) against the previous fat box P(revious): if(IsCacheValid(cache) && mBox.IsInside(cache.FatBox)) { // - if N is included in P, return previous list // => we simply leave the list (mTouchedFaces) unchanged // Set contact status if needed if(mTouchedPrimitives->GetNbEntries()) mFlags |= OPC_TEMPORAL_CONTACT; // In any case we don't need to do a query return TRUE; } else { // - else do the query using a fat N // Reset cache since we'll about to perform a real query mTouchedPrimitives->Reset(); // Make a fat box so that coherence will work for subsequent frames mBox.mExtents *= cache.FatCoeff; // Update cache with query data (signature for cached faces) cache.FatBox = mBox; } } } else { // Here we don't use temporal coherence => do a normal query mTouchedPrimitives->Reset(); } // 5) Precompute min & max bounds if needed mMin = box.mCenter - box.mExtents; mMax = box.mCenter + box.mExtents; return FALSE; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Collision query for vanilla AABB trees. * \param cache [in/out] a box cache * \param box [in] collision AABB in world space * \param tree [in] AABB tree * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool AABBCollider::Collide(AABBCache& cache, const CollisionAABB& box, const AABBTree* tree) { // This is typically called for a scene tree, full of -AABBs-, not full of triangles. // So we don't really have "primitives" to deal with. Hence it doesn't work with // "FirstContact" + "TemporalCoherence". ASSERT( !(FirstContactEnabled() && TemporalCoherenceEnabled()) ); // Checkings if(!tree) return false; // Init collision query if(InitQuery(cache, box)) return true; // Perform collision query _Collide(tree); return true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Checks the AABB completely contains the box. In which case we can end the query sooner. * \param bc [in] box center * \param be [in] box extents * \return true if the AABB contains the whole box */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ BOOL AABBCollider::AABBContainsBox(const Point& bc, const Point& be) { if(mMin.x > bc.x - be.x) return FALSE; if(mMin.y > bc.y - be.y) return FALSE; if(mMin.z > bc.z - be.z) return FALSE; if(mMax.x < bc.x + be.x) return FALSE; if(mMax.y < bc.y + be.y) return FALSE; if(mMax.z < bc.z + be.z) return FALSE; return TRUE; } #define TEST_BOX_IN_AABB(center, extents) \ if(AABBContainsBox(center, extents)) \ { \ /* Set contact status */ \ mFlags |= OPC_CONTACT; \ _Dump(node); \ return; \ } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for normal AABB trees. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void AABBCollider::_Collide(const AABBCollisionNode* node) { // Perform AABB-AABB overlap test if(!AABBAABBOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; TEST_BOX_IN_AABB(node->mAABB.mCenter, node->mAABB.mExtents) if(node->IsLeaf()) { AABB_PRIM(node->GetPrimitive(), OPC_CONTACT) } else { _Collide(node->GetPos()); if(ContactFound()) return; _Collide(node->GetNeg()); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for normal AABB trees, without primitive tests. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void AABBCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node) { // Perform AABB-AABB overlap test if(!AABBAABBOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; TEST_BOX_IN_AABB(node->mAABB.mCenter, node->mAABB.mExtents) if(node->IsLeaf()) { SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) } else { _CollideNoPrimitiveTest(node->GetPos()); if(ContactFound()) return; _CollideNoPrimitiveTest(node->GetNeg()); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for quantized AABB trees. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void AABBCollider::_Collide(const AABBQuantizedNode* node) { // Dequantize box const QuantizedAABB& Box = node->mAABB; const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); // Perform AABB-AABB overlap test if(!AABBAABBOverlap(Extents, Center)) return; TEST_BOX_IN_AABB(Center, Extents) if(node->IsLeaf()) { AABB_PRIM(node->GetPrimitive(), OPC_CONTACT) } else { _Collide(node->GetPos()); if(ContactFound()) return; _Collide(node->GetNeg()); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for quantized AABB trees, without primitive tests. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void AABBCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node) { // Dequantize box const QuantizedAABB& Box = node->mAABB; const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); // Perform AABB-AABB overlap test if(!AABBAABBOverlap(Extents, Center)) return; TEST_BOX_IN_AABB(Center, Extents) if(node->IsLeaf()) { SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) } else { _CollideNoPrimitiveTest(node->GetPos()); if(ContactFound()) return; _CollideNoPrimitiveTest(node->GetNeg()); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for no-leaf AABB trees. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void AABBCollider::_Collide(const AABBNoLeafNode* node) { // Perform AABB-AABB overlap test if(!AABBAABBOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; TEST_BOX_IN_AABB(node->mAABB.mCenter, node->mAABB.mExtents) if(node->HasPosLeaf()) { AABB_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } else _Collide(node->GetPos()); if(ContactFound()) return; if(node->HasNegLeaf()) { AABB_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } else _Collide(node->GetNeg()); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for no-leaf AABB trees, without primitive tests. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void AABBCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node) { // Perform AABB-AABB overlap test if(!AABBAABBOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; TEST_BOX_IN_AABB(node->mAABB.mCenter, node->mAABB.mExtents) if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } else _CollideNoPrimitiveTest(node->GetPos()); if(ContactFound()) return; if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } else _CollideNoPrimitiveTest(node->GetNeg()); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for quantized no-leaf AABB trees. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void AABBCollider::_Collide(const AABBQuantizedNoLeafNode* node) { // Dequantize box const QuantizedAABB& Box = node->mAABB; const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); // Perform AABB-AABB overlap test if(!AABBAABBOverlap(Extents, Center)) return; TEST_BOX_IN_AABB(Center, Extents) if(node->HasPosLeaf()) { AABB_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } else _Collide(node->GetPos()); if(ContactFound()) return; if(node->HasNegLeaf()) { AABB_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } else _Collide(node->GetNeg()); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for quantized no-leaf AABB trees, without primitive tests. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void AABBCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node) { // Dequantize box const QuantizedAABB& Box = node->mAABB; const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); // Perform AABB-AABB overlap test if(!AABBAABBOverlap(Extents, Center)) return; TEST_BOX_IN_AABB(Center, Extents) if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } else _CollideNoPrimitiveTest(node->GetPos()); if(ContactFound()) return; if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } else _CollideNoPrimitiveTest(node->GetNeg()); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for vanilla AABB trees. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void AABBCollider::_Collide(const AABBTreeNode* node) { // Perform AABB-AABB overlap test Point Center, Extents; node->GetAABB()->GetCenter(Center); node->GetAABB()->GetExtents(Extents); if(!AABBAABBOverlap(Center, Extents)) return; if(node->IsLeaf() || AABBContainsBox(Center, Extents)) { mFlags |= OPC_CONTACT; mTouchedPrimitives->Add(node->GetPrimitives(), node->GetNbPrimitives()); } else { _Collide(node->GetPos()); _Collide(node->GetNeg()); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Constructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// HybridAABBCollider::HybridAABBCollider() { } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Destructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// HybridAABBCollider::~HybridAABBCollider() { } bool HybridAABBCollider::Collide(AABBCache& cache, const CollisionAABB& box, const HybridModel& model) { // We don't want primitive tests here! mFlags |= OPC_NO_PRIMITIVE_TESTS; // Checkings if(!Setup(&model)) return false; // Init collision query if(InitQuery(cache, box)) return true; // Special case for 1-leaf trees if(mCurrentModel && mCurrentModel->HasSingleNode()) { // Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles udword Nb = mIMesh->GetNbTriangles(); // Loop through all triangles for(udword i=0;i(model.GetTree()); // Setup dequantization coeffs mCenterCoeff = Tree->mCenterCoeff; mExtentsCoeff = Tree->mExtentsCoeff; // Perform collision query - we don't want primitive tests here! _CollideNoPrimitiveTest(Tree->GetNodes()); } else { const AABBNoLeafTree* Tree = static_cast(model.GetTree()); // Perform collision query - we don't want primitive tests here! _CollideNoPrimitiveTest(Tree->GetNodes()); } } else { if(model.IsQuantized()) { const AABBQuantizedTree* Tree = static_cast(model.GetTree()); // Setup dequantization coeffs mCenterCoeff = Tree->mCenterCoeff; mExtentsCoeff = Tree->mExtentsCoeff; // Perform collision query - we don't want primitive tests here! _CollideNoPrimitiveTest(Tree->GetNodes()); } else { const AABBCollisionTree* Tree = static_cast(model.GetTree()); // Perform collision query - we don't want primitive tests here! _CollideNoPrimitiveTest(Tree->GetNodes()); } } // We only have a list of boxes so far if(GetContactStatus()) { // Reset contact status, since it currently only reflects collisions with leaf boxes Collider::InitQuery(); // Change dest container so that we can use built-in overlap tests and get collided primitives cache.TouchedPrimitives.Reset(); mTouchedPrimitives = &cache.TouchedPrimitives; // Read touched leaf boxes udword Nb = mTouchedBoxes.GetNbEntries(); const udword* Touched = mTouchedBoxes.GetEntries(); const LeafTriangles* LT = model.GetLeafTriangles(); const udword* Indices = model.GetIndices(); // Loop through touched leaves while(Nb--) { const LeafTriangles& CurrentLeaf = LT[*Touched++]; // Each leaf box has a set of triangles udword NbTris = CurrentLeaf.GetNbTriangles(); if(Indices) { const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()]; // Loop through triangles and test each of them while(NbTris--) { udword TriangleIndex = *T++; AABB_PRIM(TriangleIndex, OPC_CONTACT) } } else { udword BaseIndex = CurrentLeaf.GetTriangleIndex(); // Loop through triangles and test each of them while(NbTris--) { udword TriangleIndex = BaseIndex++; AABB_PRIM(TriangleIndex, OPC_CONTACT) } } } } return true; } ode-0.16/OPCODE/OPC_PlanesAABBOverlap.h0000664000175200017520000000500013403272463014141 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Planes-AABB overlap test. * - original code by Ville Miettinen, from Umbra/dPVS (released on the GD-Algorithms mailing list) * - almost used "as-is", I even left the comments (hence the frustum-related notes) * * \param center [in] box center * \param extents [in] box extents * \param out_clip_mask [out] bitmask for active planes * \param in_clip_mask [in] bitmask for active planes * \return TRUE if boxes overlap planes */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ BOOL PlanesCollider::PlanesAABBOverlap(const Point& center, const Point& extents, udword& out_clip_mask, udword in_clip_mask) { // Stats mNbVolumeBVTests++; const Plane* p = mPlanes; // Evaluate through all active frustum planes. We determine the relation // between the AABB and a plane by using the concept of "near" and "far" // vertices originally described by Zhang (and later by Möller). Our // variant here uses 3 fabs ops, 6 muls, 7 adds and two floating point // comparisons per plane. The routine early-exits if the AABB is found // to be outside any of the planes. The loop also constructs a new output // clip mask. Most FPUs have a native single-cycle fabsf() operation. udword Mask = 1; // current mask index (1,2,4,8,..) udword TmpOutClipMask = 0; // initialize output clip mask into empty. while(Mask<=in_clip_mask) // keep looping while we have active planes left... { if(in_clip_mask & Mask) // if clip plane is active, process it.. { float NP = extents.x*fabsf(p->n.x) + extents.y*fabsf(p->n.y) + extents.z*fabsf(p->n.z); // ### fabsf could be precomputed float MP = center.x*p->n.x + center.y*p->n.y + center.z*p->n.z + p->d; if(NP < MP) // near vertex behind the clip plane... return FALSE; // .. so there is no intersection.. if((-NP) < MP) // near and far vertices on different sides of plane.. TmpOutClipMask |= Mask; // .. so update the clip mask... } Mask+=Mask; // mk = (1<Add(udword(prim_index)); //! Sphere-triangle overlap test #define SPHERE_PRIM(prim_index, flag) \ /* Request vertices from the app */ \ VertexPointers VP; ConversionArea VC; mIMesh->GetTriangle(VP, prim_index, VC); \ \ /* Perform sphere-tri overlap test */ \ if(SphereTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) \ { \ SET_CONTACT(prim_index, flag) \ } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Constructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// SphereCollider::SphereCollider() { mCenter.Zero(); mRadius2 = 0.0f; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Destructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// SphereCollider::~SphereCollider() { } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Generic collision query for generic OPCODE models. After the call, access the results: * - with GetContactStatus() * - with GetNbTouchedPrimitives() * - with GetTouchedPrimitives() * * \param cache [in/out] a sphere cache * \param sphere [in] collision sphere in local space * \param model [in] Opcode model to collide with * \param worlds [in] sphere's world matrix, or null * \param worldm [in] model's world matrix, or null * \return true if success * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool SphereCollider::Collide(SphereCache& cache, const Sphere& sphere, const Model& model, const Matrix4x4* worlds, const Matrix4x4* worldm) { // Checkings if(!Setup(&model)) return false; // Init collision query if(InitQuery(cache, sphere, worlds, worldm)) return true; // Special case for 1-leaf trees if(mCurrentModel && mCurrentModel->HasSingleNode()) { // Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles udword Nb = mIMesh->GetNbTriangles(); // Loop through all triangles for(udword i=0;i(model.GetTree()); // Setup dequantization coeffs mCenterCoeff = Tree->mCenterCoeff; mExtentsCoeff = Tree->mExtentsCoeff; // Perform collision query if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); else _Collide(Tree->GetNodes()); } else { const AABBNoLeafTree* Tree = static_cast(model.GetTree()); // Perform collision query if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); else _Collide(Tree->GetNodes()); } } else { if(model.IsQuantized()) { const AABBQuantizedTree* Tree = static_cast(model.GetTree()); // Setup dequantization coeffs mCenterCoeff = Tree->mCenterCoeff; mExtentsCoeff = Tree->mExtentsCoeff; // Perform collision query if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); else _Collide(Tree->GetNodes()); } else { const AABBCollisionTree* Tree = static_cast(model.GetTree()); // Perform collision query if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); else _Collide(Tree->GetNodes()); } } return true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Initializes a collision query : * - reset stats & contact status * - setup matrices * - check temporal coherence * * \param cache [in/out] a sphere cache * \param sphere [in] sphere in local space * \param worlds [in] sphere's world matrix, or null * \param worldm [in] model's world matrix, or null * \return TRUE if we can return immediately * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// BOOL SphereCollider::InitQuery(SphereCache& cache, const Sphere& sphere, const Matrix4x4* worlds, const Matrix4x4* worldm) { // 1) Call the base method VolumeCollider::InitQuery(); // 2) Compute sphere in model space: // - Precompute R^2 mRadius2 = sphere.mRadius * sphere.mRadius; // - Compute center position mCenter = sphere.mCenter; // -> to world space if(worlds) mCenter *= *worlds; // -> to model space if(worldm) { // Invert model matrix Matrix4x4 InvWorldM; InvertPRMatrix(InvWorldM, *worldm); mCenter *= InvWorldM; } // 3) Setup destination pointer mTouchedPrimitives = &cache.TouchedPrimitives; // 4) Special case: 1-triangle meshes [Opcode 1.3] if(mCurrentModel && mCurrentModel->HasSingleNode()) { if(!SkipPrimitiveTests()) { // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0. mTouchedPrimitives->Reset(); // Perform overlap test between the unique triangle and the sphere (and set contact status if needed) SPHERE_PRIM(udword(0), OPC_CONTACT) // Return immediately regardless of status return TRUE; } } // 5) Check temporal coherence : if(TemporalCoherenceEnabled()) { // Here we use temporal coherence // => check results from previous frame before performing the collision query if(FirstContactEnabled()) { // We're only interested in the first contact found => test the unique previously touched face if(mTouchedPrimitives->GetNbEntries()) { // Get index of previously touched face = the first entry in the array udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0); // Then reset the array: // - if the overlap test below is successful, the index we'll get added back anyway // - if it isn't, then the array should be reset anyway for the normal query mTouchedPrimitives->Reset(); // Perform overlap test between the cached triangle and the sphere (and set contact status if needed) SPHERE_PRIM(PreviouslyTouchedFace, OPC_TEMPORAL_CONTACT) // Return immediately if possible if(GetContactStatus()) return TRUE; } // else no face has been touched during previous query // => we'll have to perform a normal query } else { // We're interested in all contacts =>test the new real sphere N(ew) against the previous fat sphere P(revious): float r = sqrtf(cache.FatRadius2) - sphere.mRadius; if(IsCacheValid(cache) && cache.Center.SquareDistance(mCenter) < r*r) { // - if N is included in P, return previous list // => we simply leave the list (mTouchedFaces) unchanged // Set contact status if needed if(mTouchedPrimitives->GetNbEntries()) mFlags |= OPC_TEMPORAL_CONTACT; // In any case we don't need to do a query return TRUE; } else { // - else do the query using a fat N // Reset cache since we'll about to perform a real query mTouchedPrimitives->Reset(); // Make a fat sphere so that coherence will work for subsequent frames mRadius2 *= cache.FatCoeff; // mRadius2 = (sphere.mRadius * cache.FatCoeff)*(sphere.mRadius * cache.FatCoeff); // Update cache with query data (signature for cached faces) cache.Center = mCenter; cache.FatRadius2 = mRadius2; } } } else { // Here we don't use temporal coherence => do a normal query mTouchedPrimitives->Reset(); } return FALSE; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Collision query for vanilla AABB trees. * \param cache [in/out] a sphere cache * \param sphere [in] collision sphere in world space * \param tree [in] AABB tree * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool SphereCollider::Collide(SphereCache& cache, const Sphere& sphere, const AABBTree* tree) { // This is typically called for a scene tree, full of -AABBs-, not full of triangles. // So we don't really have "primitives" to deal with. Hence it doesn't work with // "FirstContact" + "TemporalCoherence". ASSERT( !(FirstContactEnabled() && TemporalCoherenceEnabled()) ); // Checkings if(!tree) return false; // Init collision query if(InitQuery(cache, sphere)) return true; // Perform collision query _Collide(tree); return true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Checks the sphere completely contains the box. In which case we can end the query sooner. * \param bc [in] box center * \param be [in] box extents * \return true if the sphere contains the whole box */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ BOOL SphereCollider::SphereContainsBox(const Point& bc, const Point& be) { // I assume if all 8 box vertices are inside the sphere, so does the whole box. // Sounds ok but maybe there's a better way? Point p; p.x=bc.x+be.x; p.y=bc.y+be.y; p.z=bc.z+be.z; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; p.x=bc.x-be.x; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; p.x=bc.x+be.x; p.y=bc.y-be.y; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; p.x=bc.x-be.x; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; p.x=bc.x+be.x; p.y=bc.y+be.y; p.z=bc.z-be.z; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; p.x=bc.x-be.x; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; p.x=bc.x+be.x; p.y=bc.y-be.y; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; p.x=bc.x-be.x; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; return TRUE; } #define TEST_BOX_IN_SPHERE(center, extents) \ if(SphereContainsBox(center, extents)) \ { \ /* Set contact status */ \ mFlags |= OPC_CONTACT; \ _Dump(node); \ return; \ } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for normal AABB trees. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void SphereCollider::_Collide(const AABBCollisionNode* node) { // Perform Sphere-AABB overlap test if(!SphereAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; TEST_BOX_IN_SPHERE(node->mAABB.mCenter, node->mAABB.mExtents) if(node->IsLeaf()) { SPHERE_PRIM(node->GetPrimitive(), OPC_CONTACT) } else { _Collide(node->GetPos()); if(ContactFound()) return; _Collide(node->GetNeg()); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for normal AABB trees, without primitive tests. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void SphereCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node) { // Perform Sphere-AABB overlap test if(!SphereAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; TEST_BOX_IN_SPHERE(node->mAABB.mCenter, node->mAABB.mExtents) if(node->IsLeaf()) { SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) } else { _CollideNoPrimitiveTest(node->GetPos()); if(ContactFound()) return; _CollideNoPrimitiveTest(node->GetNeg()); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for quantized AABB trees. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void SphereCollider::_Collide(const AABBQuantizedNode* node) { // Dequantize box const QuantizedAABB& Box = node->mAABB; const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); // Perform Sphere-AABB overlap test if(!SphereAABBOverlap(Center, Extents)) return; TEST_BOX_IN_SPHERE(Center, Extents) if(node->IsLeaf()) { SPHERE_PRIM(node->GetPrimitive(), OPC_CONTACT) } else { _Collide(node->GetPos()); if(ContactFound()) return; _Collide(node->GetNeg()); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for quantized AABB trees, without primitive tests. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void SphereCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node) { // Dequantize box const QuantizedAABB& Box = node->mAABB; const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); // Perform Sphere-AABB overlap test if(!SphereAABBOverlap(Center, Extents)) return; TEST_BOX_IN_SPHERE(Center, Extents) if(node->IsLeaf()) { SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) } else { _CollideNoPrimitiveTest(node->GetPos()); if(ContactFound()) return; _CollideNoPrimitiveTest(node->GetNeg()); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for no-leaf AABB trees. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void SphereCollider::_Collide(const AABBNoLeafNode* node) { // Perform Sphere-AABB overlap test if(!SphereAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; TEST_BOX_IN_SPHERE(node->mAABB.mCenter, node->mAABB.mExtents) if(node->HasPosLeaf()) { SPHERE_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } else _Collide(node->GetPos()); if(ContactFound()) return; if(node->HasNegLeaf()) { SPHERE_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } else _Collide(node->GetNeg()); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for no-leaf AABB trees, without primitive tests. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void SphereCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node) { // Perform Sphere-AABB overlap test if(!SphereAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; TEST_BOX_IN_SPHERE(node->mAABB.mCenter, node->mAABB.mExtents) if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } else _CollideNoPrimitiveTest(node->GetPos()); if(ContactFound()) return; if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } else _CollideNoPrimitiveTest(node->GetNeg()); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for quantized no-leaf AABB trees. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void SphereCollider::_Collide(const AABBQuantizedNoLeafNode* node) { // Dequantize box const QuantizedAABB& Box = node->mAABB; const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); // Perform Sphere-AABB overlap test if(!SphereAABBOverlap(Center, Extents)) return; TEST_BOX_IN_SPHERE(Center, Extents) if(node->HasPosLeaf()) { SPHERE_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } else _Collide(node->GetPos()); if(ContactFound()) return; if(node->HasNegLeaf()) { SPHERE_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } else _Collide(node->GetNeg()); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for quantized no-leaf AABB trees, without primitive tests. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void SphereCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node) { // Dequantize box const QuantizedAABB& Box = node->mAABB; const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); // Perform Sphere-AABB overlap test if(!SphereAABBOverlap(Center, Extents)) return; TEST_BOX_IN_SPHERE(Center, Extents) if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } else _CollideNoPrimitiveTest(node->GetPos()); if(ContactFound()) return; if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } else _CollideNoPrimitiveTest(node->GetNeg()); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for vanilla AABB trees. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void SphereCollider::_Collide(const AABBTreeNode* node) { // Perform Sphere-AABB overlap test Point Center, Extents; node->GetAABB()->GetCenter(Center); node->GetAABB()->GetExtents(Extents); if(!SphereAABBOverlap(Center, Extents)) return; if(node->IsLeaf() || SphereContainsBox(Center, Extents)) { mFlags |= OPC_CONTACT; mTouchedPrimitives->Add(node->GetPrimitives(), node->GetNbPrimitives()); } else { _Collide(node->GetPos()); _Collide(node->GetNeg()); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Constructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// HybridSphereCollider::HybridSphereCollider() { } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Destructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// HybridSphereCollider::~HybridSphereCollider() { } bool HybridSphereCollider::Collide(SphereCache& cache, const Sphere& sphere, const HybridModel& model, const Matrix4x4* worlds, const Matrix4x4* worldm) { // We don't want primitive tests here! mFlags |= OPC_NO_PRIMITIVE_TESTS; // Checkings if(!Setup(&model)) return false; // Init collision query if(InitQuery(cache, sphere, worlds, worldm)) return true; // Special case for 1-leaf trees if(mCurrentModel && mCurrentModel->HasSingleNode()) { // Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles udword Nb = mIMesh->GetNbTriangles(); // Loop through all triangles for(udword i=0;i(model.GetTree()); // Setup dequantization coeffs mCenterCoeff = Tree->mCenterCoeff; mExtentsCoeff = Tree->mExtentsCoeff; // Perform collision query - we don't want primitive tests here! _CollideNoPrimitiveTest(Tree->GetNodes()); } else { const AABBNoLeafTree* Tree = static_cast(model.GetTree()); // Perform collision query - we don't want primitive tests here! _CollideNoPrimitiveTest(Tree->GetNodes()); } } else { if(model.IsQuantized()) { const AABBQuantizedTree* Tree = static_cast(model.GetTree()); // Setup dequantization coeffs mCenterCoeff = Tree->mCenterCoeff; mExtentsCoeff = Tree->mExtentsCoeff; // Perform collision query - we don't want primitive tests here! _CollideNoPrimitiveTest(Tree->GetNodes()); } else { const AABBCollisionTree* Tree = static_cast(model.GetTree()); // Perform collision query - we don't want primitive tests here! _CollideNoPrimitiveTest(Tree->GetNodes()); } } // We only have a list of boxes so far if(GetContactStatus()) { // Reset contact status, since it currently only reflects collisions with leaf boxes Collider::InitQuery(); // Change dest container so that we can use built-in overlap tests and get collided primitives cache.TouchedPrimitives.Reset(); mTouchedPrimitives = &cache.TouchedPrimitives; // Read touched leaf boxes udword Nb = mTouchedBoxes.GetNbEntries(); const udword* Touched = mTouchedBoxes.GetEntries(); const LeafTriangles* LT = model.GetLeafTriangles(); const udword* Indices = model.GetIndices(); // Loop through touched leaves while(Nb--) { const LeafTriangles& CurrentLeaf = LT[*Touched++]; // Each leaf box has a set of triangles udword NbTris = CurrentLeaf.GetNbTriangles(); if(Indices) { const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()]; // Loop through triangles and test each of them while(NbTris--) { udword TriangleIndex = *T++; SPHERE_PRIM(TriangleIndex, OPC_CONTACT) } } else { udword BaseIndex = CurrentLeaf.GetTriangleIndex(); // Loop through triangles and test each of them while(NbTris--) { udword TriangleIndex = BaseIndex++; SPHERE_PRIM(TriangleIndex, OPC_CONTACT) } } } } return true; } ode-0.16/OPCODE/OPC_BoxBoxOverlap.h0000664000175200017520000001712013403272463013520 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * OBB-OBB overlap test using the separating axis theorem. * - original code by Gomez / Gamasutra (similar to Gottschalk's one in RAPID) * - optimized for AABB trees by computing the rotation matrix once (SOLID-fashion) * - the fabs matrix is precomputed as well and epsilon-tweaked (RAPID-style, we found this almost mandatory) * - Class III axes can be disabled... (SOLID & Intel fashion) * - ...or enabled to perform some profiling * - CPU comparisons used when appropriate * - lazy evaluation sometimes saves some work in case of early exits (unlike SOLID) * * \param ea [in] extents from box A * \param ca [in] center from box A * \param eb [in] extents from box B * \param cb [in] center from box B * \return true if boxes overlap */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ BOOL AABBTreeCollider::BoxBoxOverlap(const Point& ea, const Point& ca, const Point& eb, const Point& cb) { // Stats mNbBVBVTests++; float t,t2; // Class I : A's basis vectors float Tx = (mR1to0.m[0][0]*cb.x + mR1to0.m[1][0]*cb.y + mR1to0.m[2][0]*cb.z) + mT1to0.x - ca.x; t = ea.x + eb.x*mAR.m[0][0] + eb.y*mAR.m[1][0] + eb.z*mAR.m[2][0]; if(GREATER(Tx, t)) return FALSE; float Ty = (mR1to0.m[0][1]*cb.x + mR1to0.m[1][1]*cb.y + mR1to0.m[2][1]*cb.z) + mT1to0.y - ca.y; t = ea.y + eb.x*mAR.m[0][1] + eb.y*mAR.m[1][1] + eb.z*mAR.m[2][1]; if(GREATER(Ty, t)) return FALSE; float Tz = (mR1to0.m[0][2]*cb.x + mR1to0.m[1][2]*cb.y + mR1to0.m[2][2]*cb.z) + mT1to0.z - ca.z; t = ea.z + eb.x*mAR.m[0][2] + eb.y*mAR.m[1][2] + eb.z*mAR.m[2][2]; if(GREATER(Tz, t)) return FALSE; // Class II : B's basis vectors t = Tx*mR1to0.m[0][0] + Ty*mR1to0.m[0][1] + Tz*mR1to0.m[0][2]; t2 = ea.x*mAR.m[0][0] + ea.y*mAR.m[0][1] + ea.z*mAR.m[0][2] + eb.x; if(GREATER(t, t2)) return FALSE; t = Tx*mR1to0.m[1][0] + Ty*mR1to0.m[1][1] + Tz*mR1to0.m[1][2]; t2 = ea.x*mAR.m[1][0] + ea.y*mAR.m[1][1] + ea.z*mAR.m[1][2] + eb.y; if(GREATER(t, t2)) return FALSE; t = Tx*mR1to0.m[2][0] + Ty*mR1to0.m[2][1] + Tz*mR1to0.m[2][2]; t2 = ea.x*mAR.m[2][0] + ea.y*mAR.m[2][1] + ea.z*mAR.m[2][2] + eb.z; if(GREATER(t, t2)) return FALSE; // Class III : 9 cross products // Cool trick: always perform the full test for first level, regardless of settings. // That way pathological cases (such as the pencils scene) are quickly rejected anyway ! if(mFullBoxBoxTest || mNbBVBVTests==1) { t = Tz*mR1to0.m[0][1] - Ty*mR1to0.m[0][2]; t2 = ea.y*mAR.m[0][2] + ea.z*mAR.m[0][1] + eb.y*mAR.m[2][0] + eb.z*mAR.m[1][0]; if(GREATER(t, t2)) return FALSE; // L = A0 x B0 t = Tz*mR1to0.m[1][1] - Ty*mR1to0.m[1][2]; t2 = ea.y*mAR.m[1][2] + ea.z*mAR.m[1][1] + eb.x*mAR.m[2][0] + eb.z*mAR.m[0][0]; if(GREATER(t, t2)) return FALSE; // L = A0 x B1 t = Tz*mR1to0.m[2][1] - Ty*mR1to0.m[2][2]; t2 = ea.y*mAR.m[2][2] + ea.z*mAR.m[2][1] + eb.x*mAR.m[1][0] + eb.y*mAR.m[0][0]; if(GREATER(t, t2)) return FALSE; // L = A0 x B2 t = Tx*mR1to0.m[0][2] - Tz*mR1to0.m[0][0]; t2 = ea.x*mAR.m[0][2] + ea.z*mAR.m[0][0] + eb.y*mAR.m[2][1] + eb.z*mAR.m[1][1]; if(GREATER(t, t2)) return FALSE; // L = A1 x B0 t = Tx*mR1to0.m[1][2] - Tz*mR1to0.m[1][0]; t2 = ea.x*mAR.m[1][2] + ea.z*mAR.m[1][0] + eb.x*mAR.m[2][1] + eb.z*mAR.m[0][1]; if(GREATER(t, t2)) return FALSE; // L = A1 x B1 t = Tx*mR1to0.m[2][2] - Tz*mR1to0.m[2][0]; t2 = ea.x*mAR.m[2][2] + ea.z*mAR.m[2][0] + eb.x*mAR.m[1][1] + eb.y*mAR.m[0][1]; if(GREATER(t, t2)) return FALSE; // L = A1 x B2 t = Ty*mR1to0.m[0][0] - Tx*mR1to0.m[0][1]; t2 = ea.x*mAR.m[0][1] + ea.y*mAR.m[0][0] + eb.y*mAR.m[2][2] + eb.z*mAR.m[1][2]; if(GREATER(t, t2)) return FALSE; // L = A2 x B0 t = Ty*mR1to0.m[1][0] - Tx*mR1to0.m[1][1]; t2 = ea.x*mAR.m[1][1] + ea.y*mAR.m[1][0] + eb.x*mAR.m[2][2] + eb.z*mAR.m[0][2]; if(GREATER(t, t2)) return FALSE; // L = A2 x B1 t = Ty*mR1to0.m[2][0] - Tx*mR1to0.m[2][1]; t2 = ea.x*mAR.m[2][1] + ea.y*mAR.m[2][0] + eb.x*mAR.m[1][2] + eb.y*mAR.m[0][2]; if(GREATER(t, t2)) return FALSE; // L = A2 x B2 } return TRUE; } //! A dedicated version when one box is constant inline_ BOOL OBBCollider::BoxBoxOverlap(const Point& extents, const Point& center) { // Stats mNbVolumeBVTests++; float t,t2; // Class I : A's basis vectors float Tx = mTBoxToModel.x - center.x; t = extents.x + mBBx1; if(GREATER(Tx, t)) return FALSE; float Ty = mTBoxToModel.y - center.y; t = extents.y + mBBy1; if(GREATER(Ty, t)) return FALSE; float Tz = mTBoxToModel.z - center.z; t = extents.z + mBBz1; if(GREATER(Tz, t)) return FALSE; // Class II : B's basis vectors t = Tx*mRBoxToModel.m[0][0] + Ty*mRBoxToModel.m[0][1] + Tz*mRBoxToModel.m[0][2]; t2 = extents.x*mAR.m[0][0] + extents.y*mAR.m[0][1] + extents.z*mAR.m[0][2] + mBoxExtents.x; if(GREATER(t, t2)) return FALSE; t = Tx*mRBoxToModel.m[1][0] + Ty*mRBoxToModel.m[1][1] + Tz*mRBoxToModel.m[1][2]; t2 = extents.x*mAR.m[1][0] + extents.y*mAR.m[1][1] + extents.z*mAR.m[1][2] + mBoxExtents.y; if(GREATER(t, t2)) return FALSE; t = Tx*mRBoxToModel.m[2][0] + Ty*mRBoxToModel.m[2][1] + Tz*mRBoxToModel.m[2][2]; t2 = extents.x*mAR.m[2][0] + extents.y*mAR.m[2][1] + extents.z*mAR.m[2][2] + mBoxExtents.z; if(GREATER(t, t2)) return FALSE; // Class III : 9 cross products // Cool trick: always perform the full test for first level, regardless of settings. // That way pathological cases (such as the pencils scene) are quickly rejected anyway ! if(mFullBoxBoxTest || mNbVolumeBVTests==1) { t = Tz*mRBoxToModel.m[0][1] - Ty*mRBoxToModel.m[0][2]; t2 = extents.y*mAR.m[0][2] + extents.z*mAR.m[0][1] + mBB_1; if(GREATER(t, t2)) return FALSE; // L = A0 x B0 t = Tz*mRBoxToModel.m[1][1] - Ty*mRBoxToModel.m[1][2]; t2 = extents.y*mAR.m[1][2] + extents.z*mAR.m[1][1] + mBB_2; if(GREATER(t, t2)) return FALSE; // L = A0 x B1 t = Tz*mRBoxToModel.m[2][1] - Ty*mRBoxToModel.m[2][2]; t2 = extents.y*mAR.m[2][2] + extents.z*mAR.m[2][1] + mBB_3; if(GREATER(t, t2)) return FALSE; // L = A0 x B2 t = Tx*mRBoxToModel.m[0][2] - Tz*mRBoxToModel.m[0][0]; t2 = extents.x*mAR.m[0][2] + extents.z*mAR.m[0][0] + mBB_4; if(GREATER(t, t2)) return FALSE; // L = A1 x B0 t = Tx*mRBoxToModel.m[1][2] - Tz*mRBoxToModel.m[1][0]; t2 = extents.x*mAR.m[1][2] + extents.z*mAR.m[1][0] + mBB_5; if(GREATER(t, t2)) return FALSE; // L = A1 x B1 t = Tx*mRBoxToModel.m[2][2] - Tz*mRBoxToModel.m[2][0]; t2 = extents.x*mAR.m[2][2] + extents.z*mAR.m[2][0] + mBB_6; if(GREATER(t, t2)) return FALSE; // L = A1 x B2 t = Ty*mRBoxToModel.m[0][0] - Tx*mRBoxToModel.m[0][1]; t2 = extents.x*mAR.m[0][1] + extents.y*mAR.m[0][0] + mBB_7; if(GREATER(t, t2)) return FALSE; // L = A2 x B0 t = Ty*mRBoxToModel.m[1][0] - Tx*mRBoxToModel.m[1][1]; t2 = extents.x*mAR.m[1][1] + extents.y*mAR.m[1][0] + mBB_8; if(GREATER(t, t2)) return FALSE; // L = A2 x B1 t = Ty*mRBoxToModel.m[2][0] - Tx*mRBoxToModel.m[2][1]; t2 = extents.x*mAR.m[2][1] + extents.y*mAR.m[2][0] + mBB_9; if(GREATER(t, t2)) return FALSE; // L = A2 x B2 } return TRUE; } //! A special version for 2 axis-aligned boxes inline_ BOOL AABBCollider::AABBAABBOverlap(const Point& extents, const Point& center) { // Stats mNbVolumeBVTests++; float tx = mBox.mCenter.x - center.x; float ex = extents.x + mBox.mExtents.x; if(GREATER(tx, ex)) return FALSE; float ty = mBox.mCenter.y - center.y; float ey = extents.y + mBox.mExtents.y; if(GREATER(ty, ey)) return FALSE; float tz = mBox.mCenter.z - center.z; float ez = extents.z + mBox.mExtents.z; if(GREATER(tz, ez)) return FALSE; return TRUE; } ode-0.16/OPCODE/OPC_LSSCollider.h0000664000175200017520000001106713403272463013111 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* * OPCODE - Optimized Collision Detection * Copyright (C) 2001 Pierre Terdiman * Homepage: http://www.codercorner.com/Opcode.htm */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains code for an LSS collider. * \file OPC_LSSCollider.h * \author Pierre Terdiman * \date December, 28, 2002 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Include Guard #ifndef __OPC_LSSCOLLIDER_H__ #define __OPC_LSSCOLLIDER_H__ struct OPCODE_API LSSCache : VolumeCache { LSSCache() { Previous.mP0 = Point(0.0f, 0.0f, 0.0f); Previous.mP1 = Point(0.0f, 0.0f, 0.0f); Previous.mRadius = 0.0f; FatCoeff = 1.1f; } // Cached faces signature LSS Previous; //!< LSS used when performing the query resulting in cached faces // User settings float FatCoeff; //!< mRadius2 multiplier used to create a fat LSS }; class OPCODE_API LSSCollider : public VolumeCollider { public: // Constructor / Destructor LSSCollider(); virtual ~LSSCollider(); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Generic collision query for generic OPCODE models. After the call, access the results: * - with GetContactStatus() * - with GetNbTouchedPrimitives() * - with GetTouchedPrimitives() * * \param cache [in/out] an lss cache * \param lss [in] collision lss in local space * \param model [in] Opcode model to collide with * \param worldl [in] lss world matrix, or null * \param worldm [in] model's world matrix, or null * \return true if success * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool Collide(LSSCache& cache, const LSS& lss, const Model& model, const Matrix4x4* worldl=null, const Matrix4x4* worldm=null); // bool Collide(LSSCache& cache, const LSS& lss, const AABBTree* tree); protected: // LSS in model space Segment mSeg; //!< Segment float mRadius2; //!< LSS radius squared // Internal methods void _Collide(const AABBCollisionNode* node); void _Collide(const AABBNoLeafNode* node); void _Collide(const AABBQuantizedNode* node); void _Collide(const AABBQuantizedNoLeafNode* node); void _Collide(const AABBTreeNode* node); void _CollideNoPrimitiveTest(const AABBCollisionNode* node); void _CollideNoPrimitiveTest(const AABBNoLeafNode* node); void _CollideNoPrimitiveTest(const AABBQuantizedNode* node); void _CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node); // Overlap tests inline_ BOOL LSSContainsBox(const Point& bc, const Point& be); inline_ BOOL LSSAABBOverlap(const Point& center, const Point& extents); inline_ BOOL LSSTriOverlap(const Point& vert0, const Point& vert1, const Point& vert2); // Init methods BOOL InitQuery(LSSCache& cache, const LSS& lss, const Matrix4x4* worldl=null, const Matrix4x4* worldm=null); }; class OPCODE_API HybridLSSCollider : public LSSCollider { public: // Constructor / Destructor HybridLSSCollider(); virtual ~HybridLSSCollider(); bool Collide(LSSCache& cache, const LSS& lss, const HybridModel& model, const Matrix4x4* worldl=null, const Matrix4x4* worldm=null); protected: Container mTouchedBoxes; }; #endif // __OPC_LSSCOLLIDER_H__ ode-0.16/OPCODE/OPC_OBBCollider.cpp0000664000175200017520000007074713403272463013417 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* * OPCODE - Optimized Collision Detection * Copyright (C) 2001 Pierre Terdiman * Homepage: http://www.codercorner.com/Opcode.htm */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains code for an OBB collider. * \file OPC_OBBCollider.cpp * \author Pierre Terdiman * \date January, 1st, 2002 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains an OBB-vs-tree collider. * * \class OBBCollider * \author Pierre Terdiman * \version 1.3 * \date January, 1st, 2002 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Precompiled Header #include "Stdafx.h" using namespace Opcode; #include "OPC_BoxBoxOverlap.h" #include "OPC_TriBoxOverlap.h" #define SET_CONTACT(prim_index, flag) \ /* Set contact status */ \ mFlags |= flag; \ mTouchedPrimitives->Add(udword(prim_index)); //! OBB-triangle test #define OBB_PRIM(prim_index, flag) \ /* Request vertices from the app */ \ VertexPointers VP; ConversionArea VC; mIMesh->GetTriangle(VP, prim_index, VC); \ /* Transform them in a common space */ \ TransformPoint(mLeafVerts[0], *VP.Vertex[0], mRModelToBox, mTModelToBox); \ TransformPoint(mLeafVerts[1], *VP.Vertex[1], mRModelToBox, mTModelToBox); \ TransformPoint(mLeafVerts[2], *VP.Vertex[2], mRModelToBox, mTModelToBox); \ /* Perform triangle-box overlap test */ \ if(TriBoxOverlap()) \ { \ SET_CONTACT(prim_index, flag) \ } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Constructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// OBBCollider::OBBCollider() : mFullBoxBoxTest(true) { } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Destructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// OBBCollider::~OBBCollider() { } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Validates current settings. You should call this method after all the settings and callbacks have been defined. * \return null if everything is ok, else a string describing the problem */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// const char* OBBCollider::ValidateSettings() { if(TemporalCoherenceEnabled() && !FirstContactEnabled()) return "Temporal coherence only works with ""First contact"" mode!"; return VolumeCollider::ValidateSettings(); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Generic collision query for generic OPCODE models. After the call, access the results: * - with GetContactStatus() * - with GetNbTouchedPrimitives() * - with GetTouchedPrimitives() * * \param cache [in/out] a box cache * \param box [in] collision OBB in local space * \param model [in] Opcode model to collide with * \param worldb [in] OBB's world matrix, or null * \param worldm [in] model's world matrix, or null * \return true if success * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool OBBCollider::Collide(OBBCache& cache, const OBB& box, const Model& model, const Matrix4x4* worldb, const Matrix4x4* worldm) { // Checkings if(!Setup(&model)) return false; // Init collision query if(InitQuery(cache, box, worldb, worldm)) return true; if(!model.HasLeafNodes()) { if(model.IsQuantized()) { const AABBQuantizedNoLeafTree* Tree = static_cast(model.GetTree()); // Setup dequantization coeffs mCenterCoeff = Tree->mCenterCoeff; mExtentsCoeff = Tree->mExtentsCoeff; // Perform collision query if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); else _Collide(Tree->GetNodes()); } else { const AABBNoLeafTree* Tree = static_cast(model.GetTree()); // Perform collision query if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); else _Collide(Tree->GetNodes()); } } else { if(model.IsQuantized()) { const AABBQuantizedTree* Tree = static_cast(model.GetTree()); // Setup dequantization coeffs mCenterCoeff = Tree->mCenterCoeff; mExtentsCoeff = Tree->mExtentsCoeff; // Perform collision query if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); else _Collide(Tree->GetNodes()); } else { const AABBCollisionTree* Tree = static_cast(model.GetTree()); // Perform collision query if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); else _Collide(Tree->GetNodes()); } } return true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Initializes a collision query : * - reset stats & contact status * - setup matrices * - check temporal coherence * * \param cache [in/out] a box cache * \param box [in] obb in local space * \param worldb [in] obb's world matrix, or null * \param worldm [in] model's world matrix, or null * \return TRUE if we can return immediately * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// BOOL OBBCollider::InitQuery(OBBCache& cache, const OBB& box, const Matrix4x4* worldb, const Matrix4x4* worldm) { // 1) Call the base method VolumeCollider::InitQuery(); // 2) Compute obb in world space mBoxExtents = box.mExtents; Matrix4x4 WorldB; if(worldb) { WorldB = Matrix4x4( box.mRot * Matrix3x3(*worldb) ); WorldB.SetTrans(box.mCenter * *worldb); } else { WorldB = box.mRot; WorldB.SetTrans(box.mCenter); } // Setup matrices Matrix4x4 InvWorldB; InvertPRMatrix(InvWorldB, WorldB); if(worldm) { Matrix4x4 InvWorldM; InvertPRMatrix(InvWorldM, *worldm); Matrix4x4 WorldBtoM = WorldB * InvWorldM; Matrix4x4 WorldMtoB = *worldm * InvWorldB; mRModelToBox = WorldMtoB; WorldMtoB.GetTrans(mTModelToBox); mRBoxToModel = WorldBtoM; WorldBtoM.GetTrans(mTBoxToModel); } else { mRModelToBox = InvWorldB; InvWorldB.GetTrans(mTModelToBox); mRBoxToModel = WorldB; WorldB.GetTrans(mTBoxToModel); } // 3) Setup destination pointer mTouchedPrimitives = &cache.TouchedPrimitives; // 4) Special case: 1-triangle meshes [Opcode 1.3] if(mCurrentModel && mCurrentModel->HasSingleNode()) { if(!SkipPrimitiveTests()) { // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0. mTouchedPrimitives->Reset(); // Perform overlap test between the unique triangle and the box (and set contact status if needed) OBB_PRIM(udword(0), OPC_CONTACT) // Return immediately regardless of status return TRUE; } } // 5) Check temporal coherence: if(TemporalCoherenceEnabled()) { // Here we use temporal coherence // => check results from previous frame before performing the collision query if(FirstContactEnabled()) { // We're only interested in the first contact found => test the unique previously touched face if(mTouchedPrimitives->GetNbEntries()) { // Get index of previously touched face = the first entry in the array udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0); // Then reset the array: // - if the overlap test below is successful, the index we'll get added back anyway // - if it isn't, then the array should be reset anyway for the normal query mTouchedPrimitives->Reset(); // Perform overlap test between the cached triangle and the box (and set contact status if needed) OBB_PRIM(PreviouslyTouchedFace, OPC_TEMPORAL_CONTACT) // Return immediately if possible if(GetContactStatus()) return TRUE; } // else no face has been touched during previous query // => we'll have to perform a normal query } else { // ### rewrite this OBB TestBox(mTBoxToModel, mBoxExtents, mRBoxToModel); // We're interested in all contacts =>test the new real box N(ew) against the previous fat box P(revious): if(IsCacheValid(cache) && TestBox.IsInside(cache.FatBox)) { // - if N is included in P, return previous list // => we simply leave the list (mTouchedFaces) unchanged // Set contact status if needed if(mTouchedPrimitives->GetNbEntries()) mFlags |= OPC_TEMPORAL_CONTACT; // In any case we don't need to do a query return TRUE; } else { // - else do the query using a fat N // Reset cache since we'll about to perform a real query mTouchedPrimitives->Reset(); // Make a fat box so that coherence will work for subsequent frames TestBox.mExtents *= cache.FatCoeff; mBoxExtents *= cache.FatCoeff; // Update cache with query data (signature for cached faces) cache.FatBox = TestBox; } } } else { // Here we don't use temporal coherence => do a normal query mTouchedPrimitives->Reset(); } // Now we can precompute box-box data // Precompute absolute box-to-model rotation matrix for(udword i=0;i<3;i++) { for(udword j=0;j<3;j++) { // Epsilon value prevents floating-point inaccuracies (strategy borrowed from RAPID) mAR.m[i][j] = 1e-6f + fabsf(mRBoxToModel.m[i][j]); } } // Precompute bounds for box-in-box test mB0 = mBoxExtents - mTModelToBox; mB1 = - mBoxExtents - mTModelToBox; // Precompute box-box data - Courtesy of Erwin de Vries mBBx1 = mBoxExtents.x*mAR.m[0][0] + mBoxExtents.y*mAR.m[1][0] + mBoxExtents.z*mAR.m[2][0]; mBBy1 = mBoxExtents.x*mAR.m[0][1] + mBoxExtents.y*mAR.m[1][1] + mBoxExtents.z*mAR.m[2][1]; mBBz1 = mBoxExtents.x*mAR.m[0][2] + mBoxExtents.y*mAR.m[1][2] + mBoxExtents.z*mAR.m[2][2]; mBB_1 = mBoxExtents.y*mAR.m[2][0] + mBoxExtents.z*mAR.m[1][0]; mBB_2 = mBoxExtents.x*mAR.m[2][0] + mBoxExtents.z*mAR.m[0][0]; mBB_3 = mBoxExtents.x*mAR.m[1][0] + mBoxExtents.y*mAR.m[0][0]; mBB_4 = mBoxExtents.y*mAR.m[2][1] + mBoxExtents.z*mAR.m[1][1]; mBB_5 = mBoxExtents.x*mAR.m[2][1] + mBoxExtents.z*mAR.m[0][1]; mBB_6 = mBoxExtents.x*mAR.m[1][1] + mBoxExtents.y*mAR.m[0][1]; mBB_7 = mBoxExtents.y*mAR.m[2][2] + mBoxExtents.z*mAR.m[1][2]; mBB_8 = mBoxExtents.x*mAR.m[2][2] + mBoxExtents.z*mAR.m[0][2]; mBB_9 = mBoxExtents.x*mAR.m[1][2] + mBoxExtents.y*mAR.m[0][2]; return FALSE; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Checks the OBB completely contains the box. In which case we can end the query sooner. * \param bc [in] box center * \param be [in] box extents * \return true if the OBB contains the whole box */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ BOOL OBBCollider::OBBContainsBox(const Point& bc, const Point& be) { // I assume if all 8 box vertices are inside the OBB, so does the whole box. // Sounds ok but maybe there's a better way? /* #define TEST_PT(a,b,c) \ p.x=a; p.y=b; p.z=c; p+=bc; \ f = p.x * mRModelToBox.m[0][0] + p.y * mRModelToBox.m[1][0] + p.z * mRModelToBox.m[2][0]; if(f>mB0.x || fmB0.y || fmB0.z || f NCx-NEx) return FALSE; float NCy = bc.x * mRModelToBox.m[0][1] + bc.y * mRModelToBox.m[1][1] + bc.z * mRModelToBox.m[2][1]; float NEy = fabsf(mRModelToBox.m[0][1] * be.x) + fabsf(mRModelToBox.m[1][1] * be.y) + fabsf(mRModelToBox.m[2][1] * be.z); if(mB0.y < NCy+NEy) return FALSE; if(mB1.y > NCy-NEy) return FALSE; float NCz = bc.x * mRModelToBox.m[0][2] + bc.y * mRModelToBox.m[1][2] + bc.z * mRModelToBox.m[2][2]; float NEz = fabsf(mRModelToBox.m[0][2] * be.x) + fabsf(mRModelToBox.m[1][2] * be.y) + fabsf(mRModelToBox.m[2][2] * be.z); if(mB0.z < NCz+NEz) return FALSE; if(mB1.z > NCz-NEz) return FALSE; return TRUE; } #define TEST_BOX_IN_OBB(center, extents) \ if(OBBContainsBox(center, extents)) \ { \ /* Set contact status */ \ mFlags |= OPC_CONTACT; \ _Dump(node); \ return; \ } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for normal AABB trees. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void OBBCollider::_Collide(const AABBCollisionNode* node) { // Perform OBB-AABB overlap test if(!BoxBoxOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; TEST_BOX_IN_OBB(node->mAABB.mCenter, node->mAABB.mExtents) if(node->IsLeaf()) { OBB_PRIM(node->GetPrimitive(), OPC_CONTACT) } else { _Collide(node->GetPos()); if(ContactFound()) return; _Collide(node->GetNeg()); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for normal AABB trees, without primitive tests. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void OBBCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node) { // Perform OBB-AABB overlap test if(!BoxBoxOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; TEST_BOX_IN_OBB(node->mAABB.mCenter, node->mAABB.mExtents) if(node->IsLeaf()) { SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) } else { _CollideNoPrimitiveTest(node->GetPos()); if(ContactFound()) return; _CollideNoPrimitiveTest(node->GetNeg()); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for quantized AABB trees. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void OBBCollider::_Collide(const AABBQuantizedNode* node) { // Dequantize box const QuantizedAABB& Box = node->mAABB; const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); // Perform OBB-AABB overlap test if(!BoxBoxOverlap(Extents, Center)) return; TEST_BOX_IN_OBB(Center, Extents) if(node->IsLeaf()) { OBB_PRIM(node->GetPrimitive(), OPC_CONTACT) } else { _Collide(node->GetPos()); if(ContactFound()) return; _Collide(node->GetNeg()); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for quantized AABB trees, without primitive tests. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void OBBCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node) { // Dequantize box const QuantizedAABB& Box = node->mAABB; const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); // Perform OBB-AABB overlap test if(!BoxBoxOverlap(Extents, Center)) return; TEST_BOX_IN_OBB(Center, Extents) if(node->IsLeaf()) { SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) } else { _CollideNoPrimitiveTest(node->GetPos()); if(ContactFound()) return; _CollideNoPrimitiveTest(node->GetNeg()); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for no-leaf AABB trees. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void OBBCollider::_Collide(const AABBNoLeafNode* node) { // Perform OBB-AABB overlap test if(!BoxBoxOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; TEST_BOX_IN_OBB(node->mAABB.mCenter, node->mAABB.mExtents) if(node->HasPosLeaf()) { OBB_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } else _Collide(node->GetPos()); if(ContactFound()) return; if(node->HasNegLeaf()) { OBB_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } else _Collide(node->GetNeg()); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for no-leaf AABB trees, without primitive tests. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void OBBCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node) { // Perform OBB-AABB overlap test if(!BoxBoxOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; TEST_BOX_IN_OBB(node->mAABB.mCenter, node->mAABB.mExtents) if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } else _CollideNoPrimitiveTest(node->GetPos()); if(ContactFound()) return; if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } else _CollideNoPrimitiveTest(node->GetNeg()); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for quantized no-leaf AABB trees. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void OBBCollider::_Collide(const AABBQuantizedNoLeafNode* node) { // Dequantize box const QuantizedAABB& Box = node->mAABB; const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); // Perform OBB-AABB overlap test if(!BoxBoxOverlap(Extents, Center)) return; TEST_BOX_IN_OBB(Center, Extents) if(node->HasPosLeaf()) { OBB_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } else _Collide(node->GetPos()); if(ContactFound()) return; if(node->HasNegLeaf()) { OBB_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } else _Collide(node->GetNeg()); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for quantized no-leaf AABB trees, without primitive tests. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void OBBCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node) { // Dequantize box const QuantizedAABB& Box = node->mAABB; const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); // Perform OBB-AABB overlap test if(!BoxBoxOverlap(Extents, Center)) return; TEST_BOX_IN_OBB(Center, Extents) if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } else _CollideNoPrimitiveTest(node->GetPos()); if(ContactFound()) return; if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } else _CollideNoPrimitiveTest(node->GetNeg()); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Constructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// HybridOBBCollider::HybridOBBCollider() { } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Destructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// HybridOBBCollider::~HybridOBBCollider() { } bool HybridOBBCollider::Collide(OBBCache& cache, const OBB& box, const HybridModel& model, const Matrix4x4* worldb, const Matrix4x4* worldm) { // We don't want primitive tests here! mFlags |= OPC_NO_PRIMITIVE_TESTS; // Checkings if(!Setup(&model)) return false; // Init collision query if(InitQuery(cache, box, worldb, worldm)) return true; // Special case for 1-leaf trees if(mCurrentModel && mCurrentModel->HasSingleNode()) { // Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles udword Nb = mIMesh->GetNbTriangles(); // Loop through all triangles for(udword i=0;i(model.GetTree()); // Setup dequantization coeffs mCenterCoeff = Tree->mCenterCoeff; mExtentsCoeff = Tree->mExtentsCoeff; // Perform collision query - we don't want primitive tests here! _CollideNoPrimitiveTest(Tree->GetNodes()); } else { const AABBNoLeafTree* Tree = static_cast(model.GetTree()); // Perform collision query - we don't want primitive tests here! _CollideNoPrimitiveTest(Tree->GetNodes()); } } else { if(model.IsQuantized()) { const AABBQuantizedTree* Tree = static_cast(model.GetTree()); // Setup dequantization coeffs mCenterCoeff = Tree->mCenterCoeff; mExtentsCoeff = Tree->mExtentsCoeff; // Perform collision query - we don't want primitive tests here! _CollideNoPrimitiveTest(Tree->GetNodes()); } else { const AABBCollisionTree* Tree = static_cast(model.GetTree()); // Perform collision query - we don't want primitive tests here! _CollideNoPrimitiveTest(Tree->GetNodes()); } } // We only have a list of boxes so far if(GetContactStatus()) { // Reset contact status, since it currently only reflects collisions with leaf boxes Collider::InitQuery(); // Change dest container so that we can use built-in overlap tests and get collided primitives cache.TouchedPrimitives.Reset(); mTouchedPrimitives = &cache.TouchedPrimitives; // Read touched leaf boxes udword Nb = mTouchedBoxes.GetNbEntries(); const udword* Touched = mTouchedBoxes.GetEntries(); const LeafTriangles* LT = model.GetLeafTriangles(); const udword* Indices = model.GetIndices(); // Loop through touched leaves while(Nb--) { const LeafTriangles& CurrentLeaf = LT[*Touched++]; // Each leaf box has a set of triangles udword NbTris = CurrentLeaf.GetNbTriangles(); if(Indices) { const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()]; // Loop through triangles and test each of them while(NbTris--) { udword TriangleIndex = *T++; OBB_PRIM(TriangleIndex, OPC_CONTACT) } } else { udword BaseIndex = CurrentLeaf.GetTriangleIndex(); // Loop through triangles and test each of them while(NbTris--) { udword TriangleIndex = BaseIndex++; OBB_PRIM(TriangleIndex, OPC_CONTACT) } } } } return true; } ode-0.16/OPCODE/OPC_Collider.h0000664000175200017520000002423513403272463012530 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* * OPCODE - Optimized Collision Detection * Copyright (C) 2001 Pierre Terdiman * Homepage: http://www.codercorner.com/Opcode.htm */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains base collider class. * \file OPC_Collider.h * \author Pierre Terdiman * \date June, 2, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Include Guard #ifndef __OPC_COLLIDER_H__ #define __OPC_COLLIDER_H__ enum CollisionFlag { OPC_FIRST_CONTACT = (1<<0), //!< Report all contacts (false) or only first one (true) OPC_TEMPORAL_COHERENCE = (1<<1), //!< Use temporal coherence or not OPC_CONTACT = (1<<2), //!< Final contact status after a collision query OPC_TEMPORAL_HIT = (1<<3), //!< There has been an early exit due to temporal coherence OPC_NO_PRIMITIVE_TESTS = (1<<4), //!< Keep or discard primitive-bv tests in leaf nodes (volume-mesh queries) OPC_CONTACT_FOUND = OPC_FIRST_CONTACT | OPC_CONTACT, OPC_TEMPORAL_CONTACT = OPC_TEMPORAL_HIT | OPC_CONTACT, OPC_FORCE_DWORD = 0x7fffffff }; class OPCODE_API Collider { public: // Constructor / Destructor Collider(); virtual ~Collider(); // Collision report /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Gets the last collision status after a collision query. * \return true if a collision occured */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ BOOL GetContactStatus() const { return mFlags & OPC_CONTACT; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Gets the "first contact" mode. * \return true if "first contact" mode is on */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ BOOL FirstContactEnabled() const { return mFlags & OPC_FIRST_CONTACT; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Gets the temporal coherence mode. * \return true if temporal coherence is on */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ BOOL TemporalCoherenceEnabled() const { return mFlags & OPC_TEMPORAL_COHERENCE; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Checks a first contact has already been found. * \return true if a first contact has been found and we can stop a query */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ BOOL ContactFound() const { return (mFlags&OPC_CONTACT_FOUND)==OPC_CONTACT_FOUND; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Checks there's been an early exit due to temporal coherence; * \return true if a temporal hit has occured */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ BOOL TemporalHit() const { return mFlags & OPC_TEMPORAL_HIT; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Checks primitive tests are enabled; * \return true if primitive tests must be skipped */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ BOOL SkipPrimitiveTests() const { return mFlags & OPC_NO_PRIMITIVE_TESTS; } // Settings /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Reports all contacts (false) or first contact only (true) * \param flag [in] true for first contact, false for all contacts * \see SetTemporalCoherence(bool flag) * \see ValidateSettings() */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ void SetFirstContact(bool flag) { if(flag) mFlags |= OPC_FIRST_CONTACT; else mFlags &= ~OPC_FIRST_CONTACT; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Enable/disable temporal coherence. * \param flag [in] true to enable temporal coherence, false to discard it * \see SetFirstContact(bool flag) * \see ValidateSettings() */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ void SetTemporalCoherence(bool flag) { if(flag) mFlags |= OPC_TEMPORAL_COHERENCE; else mFlags &= ~OPC_TEMPORAL_COHERENCE; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Enable/disable primitive tests. * \param flag [in] true to enable primitive tests, false to discard them */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ void SetPrimitiveTests(bool flag) { if(!flag) mFlags |= OPC_NO_PRIMITIVE_TESTS; else mFlags &= ~OPC_NO_PRIMITIVE_TESTS; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Validates current settings. You should call this method after all the settings / callbacks have been defined for a collider. * \return null if everything is ok, else a string describing the problem */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// virtual const char* ValidateSettings() = 0; protected: udword mFlags; //!< Bit flags const BaseModel* mCurrentModel; //!< Current model for collision query (owner of touched faces) // User mesh interface const MeshInterface* mIMesh; //!< User-defined mesh interface // Internal methods /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Setups current collision model * \param model [in] current collision model * \return TRUE if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ BOOL Setup(const BaseModel* model) { // Keep track of current model mCurrentModel = model; if(!mCurrentModel) return FALSE; mIMesh = model->GetMeshInterface(); return mIMesh!=null; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Initializes a query */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// virtual inline_ void InitQuery() { mFlags &= ~OPC_TEMPORAL_CONTACT; } }; #endif // __OPC_COLLIDER_H__ ode-0.16/OPCODE/OPC_Picking.h0000664000175200017520000000405413403272463012354 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* * OPCODE - Optimized Collision Detection * Copyright (C) 2001 Pierre Terdiman * Homepage: http://www.codercorner.com/Opcode.htm */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains code to perform "picking". * \file OPC_Picking.h * \author Pierre Terdiman * \date March, 20, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Include Guard #ifndef __OPC_PICKING_H__ #define __OPC_PICKING_H__ #ifdef OPC_RAYHIT_CALLBACK enum CullMode { CULLMODE_NONE = 0, CULLMODE_CW = 1, CULLMODE_CCW = 2 }; typedef CullMode (*CullModeCallback)(udword triangle_index, void* user_data); OPCODE_API bool SetupAllHits (RayCollider& collider, CollisionFaces& contacts); OPCODE_API bool SetupClosestHit (RayCollider& collider, CollisionFace& closest_contact); OPCODE_API bool SetupShadowFeeler (RayCollider& collider); OPCODE_API bool SetupInOutTest (RayCollider& collider); OPCODE_API bool Picking( CollisionFace& picked_face, const Ray& world_ray, const Model& model, const Matrix4x4* world, float min_dist, float max_dist, const Point& view_point, CullModeCallback callback, void* user_data); #endif #endif //__OPC_PICKING_H__ ode-0.16/OPCODE/OPC_AABBCollider.h0000664000175200017520000001052713403272463013135 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* * OPCODE - Optimized Collision Detection * Copyright (C) 2001 Pierre Terdiman * Homepage: http://www.codercorner.com/Opcode.htm */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains code for an AABB collider. * \file OPC_AABBCollider.h * \author Pierre Terdiman * \date January, 1st, 2002 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Include Guard #ifndef __OPC_AABBCOLLIDER_H__ #define __OPC_AABBCOLLIDER_H__ struct OPCODE_API AABBCache : VolumeCache { AABBCache() : FatCoeff(1.1f) { FatBox.mCenter.Zero(); FatBox.mExtents.Zero(); } // Cached faces signature CollisionAABB FatBox; //!< Box used when performing the query resulting in cached faces // User settings float FatCoeff; //!< mRadius2 multiplier used to create a fat sphere }; class OPCODE_API AABBCollider : public VolumeCollider { public: // Constructor / Destructor AABBCollider(); virtual ~AABBCollider(); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Generic collision query for generic OPCODE models. After the call, access the results: * - with GetContactStatus() * - with GetNbTouchedPrimitives() * - with GetTouchedPrimitives() * * \param cache [in/out] a box cache * \param box [in] collision AABB in world space * \param model [in] Opcode model to collide with * \return true if success * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool Collide(AABBCache& cache, const CollisionAABB& box, const Model& model); // bool Collide(AABBCache& cache, const CollisionAABB& box, const AABBTree* tree); protected: CollisionAABB mBox; //!< Query box in (center, extents) form Point mMin; //!< Query box min point Point mMax; //!< Query box max point // Leaf description Point mLeafVerts[3]; //!< Triangle vertices // Internal methods void _Collide(const AABBCollisionNode* node); void _Collide(const AABBNoLeafNode* node); void _Collide(const AABBQuantizedNode* node); void _Collide(const AABBQuantizedNoLeafNode* node); void _Collide(const AABBTreeNode* node); void _CollideNoPrimitiveTest(const AABBCollisionNode* node); void _CollideNoPrimitiveTest(const AABBNoLeafNode* node); void _CollideNoPrimitiveTest(const AABBQuantizedNode* node); void _CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node); // Overlap tests inline_ BOOL AABBContainsBox(const Point& bc, const Point& be); inline_ BOOL AABBAABBOverlap(const Point& b, const Point& Pb); inline_ BOOL TriBoxOverlap(); // Init methods BOOL InitQuery(AABBCache& cache, const CollisionAABB& box); }; class OPCODE_API HybridAABBCollider : public AABBCollider { public: // Constructor / Destructor HybridAABBCollider(); virtual ~HybridAABBCollider(); bool Collide(AABBCache& cache, const CollisionAABB& box, const HybridModel& model); protected: Container mTouchedBoxes; }; #endif // __OPC_AABBCOLLIDER_H__ ode-0.16/OPCODE/OPC_BaseModel.cpp0000664000175200017520000001253613403272463013162 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* * OPCODE - Optimized Collision Detection * Copyright (C) 2001 Pierre Terdiman * Homepage: http://www.codercorner.com/Opcode.htm */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains base model interface. * \file OPC_BaseModel.cpp * \author Pierre Terdiman * \date May, 18, 2003 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * The base class for collision models. * * \class BaseModel * \author Pierre Terdiman * \version 1.3 * \date May, 18, 2003 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Precompiled Header #include "Stdafx.h" using namespace Opcode; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Constructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// BaseModel::BaseModel() : mIMesh(null), mModelCode(0), mSource(null), mTree(null) { } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Destructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// BaseModel::~BaseModel() { ReleaseBase(); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Releases everything. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void BaseModel::ReleaseBase() { DELETESINGLE(mSource); DELETESINGLE(mTree); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Creates an optimized tree according to user-settings, and setups mModelCode. * \param no_leaf [in] true for "no leaf" tree * \param quantized [in] true for quantized tree * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool BaseModel::CreateTree(bool no_leaf, bool quantized) { DELETESINGLE(mTree); // Setup model code if(no_leaf) mModelCode |= OPC_NO_LEAF; else mModelCode &= ~OPC_NO_LEAF; if(quantized) mModelCode |= OPC_QUANTIZED; else mModelCode &= ~OPC_QUANTIZED; // Create the correct class if(mModelCode & OPC_NO_LEAF) { if(mModelCode & OPC_QUANTIZED) mTree = new AABBQuantizedNoLeafTree; else mTree = new AABBNoLeafTree; } else { if(mModelCode & OPC_QUANTIZED) mTree = new AABBQuantizedTree; else mTree = new AABBCollisionTree; } CHECKALLOC(mTree); return true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Refits the collision model. This can be used to handle dynamic meshes. Usage is: * 1. modify your mesh vertices (keep the topology constant!) * 2. refit the tree (call this method) * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool BaseModel::Refit() { // Refit the optimized tree return mTree->Refit(mIMesh); // Old code kept for reference : refit the source tree then rebuild ! // if(!mSource) return false; // // Ouch... // mSource->Refit(&mTB); // // Ouch... // return mTree->Build(mSource); } ode-0.16/OPCODE/OPC_HybridModel.cpp0000664000175200017520000004026613403272463013532 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* * OPCODE - Optimized Collision Detection * Copyright (C) 2001 Pierre Terdiman * Homepage: http://www.codercorner.com/Opcode.htm */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains code for hybrid models. * \file OPC_HybridModel.cpp * \author Pierre Terdiman * \date May, 18, 2003 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * An hybrid collision model. * * The problem : * * Opcode really shines for mesh-mesh collision, especially when meshes are deeply overlapping * (it typically outperforms RAPID in those cases). * * Unfortunately this is not the typical scenario in games. * * For close-proximity cases, especially for volume-mesh queries, it's relatively easy to run faster * than Opcode, that suffers from a relatively high setup time. * * In particular, Opcode's "vanilla" trees in those cases -can- run faster. They can also use -less- * memory than the optimized ones, when you let the system stop at ~10 triangles / leaf for example * (i.e. when you don't use "complete" trees). However, those trees tend to fragment memory quite a * lot, increasing cache misses : since they're not "complete", we can't predict the final number of * nodes and we have to allocate nodes on-the-fly. For the same reasons we can't use Opcode's "optimized" * trees here, since they rely on a known layout to perform the "optimization". * * Hybrid trees : * * Hybrid trees try to combine best of both worlds : * * - they use a maximum limit of 16 triangles/leaf. "16" is used so that we'll be able to save the * number of triangles using 4 bits only. * * - they're still "complete" trees thanks to a two-passes building phase. First we create a "vanilla" * AABB-tree with Opcode, limited to 16 triangles/leaf. Then we create a *second* vanilla tree, this * time using the leaves of the first one. The trick is : this second tree is now "complete"... so we * can further transform it into an Opcode's optimized tree. * * - then we run the collision queries on that standard Opcode tree. The only difference is that leaf * nodes contain indices to leaf nodes of another tree. Also, we have to skip all primitive tests in * Opcode optimized trees, since our leaves don't contain triangles anymore. * * - finally, for each collided leaf, we simply loop through 16 triangles max, and collide them with * the bounding volume used in the query (we only support volume-vs-mesh queries here, not mesh-vs-mesh) * * All of that is wrapped in this "hybrid model" that contains the minimal data required for this to work. * It's a mix between old "vanilla" trees, and old "optimized" trees. * * Extra advantages: * * - If we use them for dynamic models, we're left with a very small number of leaf nodes to refit. It * might be a bit faster since we have less nodes to write back. * * - In rigid body simulation, using temporal coherence and sleeping objects greatly reduce the actual * influence of one tree over another (i.e. the speed difference is often invisible). So memory is really * the key element to consider, and in this regard hybrid trees are just better. * * Information to take home: * - they use less ram * - they're not slower (they're faster or slower depending on cases, overall there's no significant * difference *as long as objects don't interpenetrate too much* - in which case Opcode's optimized trees * are still notably faster) * * \class HybridModel * \author Pierre Terdiman * \version 1.3 * \date May, 18, 2003 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Precompiled Header #include "Stdafx.h" using namespace Opcode; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Constructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// HybridModel::HybridModel() : mNbLeaves (0), mTriangles (null), mNbPrimitives (0), mIndices (null) { } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Destructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// HybridModel::~HybridModel() { Release(); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Releases everything. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void HybridModel::Release() { ReleaseBase(); DELETEARRAY(mIndices); DELETEARRAY(mTriangles); mNbLeaves = 0; mNbPrimitives = 0; } struct Internal { Internal() { mNbLeaves = 0; mLeaves = null; mTriangles = null; mBase = null; } ~Internal() { DELETEARRAY(mLeaves); } udword mNbLeaves; AABB* mLeaves; LeafTriangles* mTriangles; const dTriIndex* mBase; }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Builds a collision model. * \param create [in] model creation structure * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool HybridModel::Build(const OPCODECREATE& create) { // 1) Checkings if(!create.mIMesh || !create.mIMesh->IsValid()) return false; // Look for degenerate faces. //udword NbDegenerate = create.mIMesh->CheckTopology(); //if(NbDegenerate) Log("OPCODE WARNING: found %d degenerate faces in model! Collision might report wrong results!\n", NbDegenerate); // We continue nonetheless.... Release(); // Make sure previous tree has been discarded // 1-1) Setup mesh interface automatically SetMeshInterface(create.mIMesh); bool Status = false; AABBTree* LeafTree = null; Internal Data; // 2) Build a generic AABB Tree. mSource = new AABBTree; CHECKALLOC(mSource); // 2-1) Setup a builder. Our primitives here are triangles from input mesh, // so we use an AABBTreeOfTrianglesBuilder..... { AABBTreeOfTrianglesBuilder TB; TB.mIMesh = create.mIMesh; TB.mNbPrimitives = create.mIMesh->GetNbTriangles(); TB.mSettings = create.mSettings; TB.mSettings.mLimit = 16; // ### Hardcoded, but maybe we could let the user choose 8 / 16 / 32 ... if(!mSource->Build(&TB)) goto FreeAndExit; } // 2-2) Here's the trick : create *another* AABB tree using the leaves of the first one (which are boxes, this time) struct Local { // A callback to count leaf nodes static bool CountLeaves(const AABBTreeNode* current, udword /*depth*/, void* user_data) { if(current->IsLeaf()) { Internal* Data = (Internal*)user_data; Data->mNbLeaves++; } return true; } // A callback to setup leaf nodes in our internal structures static bool SetupLeafData(const AABBTreeNode* current, udword /*depth*/, void* user_data) { if(current->IsLeaf()) { Internal* Data = (Internal*)user_data; // Get current leaf's box Data->mLeaves[Data->mNbLeaves] = *current->GetAABB(); // Setup leaf data udword Index = udword((size_t(current->GetPrimitives()) - size_t(Data->mBase)) / sizeof(udword)); Data->mTriangles[Data->mNbLeaves].SetData(current->GetNbPrimitives(), Index); Data->mNbLeaves++; } return true; } }; // Walk the tree & count number of leaves Data.mNbLeaves = 0; mSource->Walk(Local::CountLeaves, &Data); mNbLeaves = Data.mNbLeaves; // Keep track of it // Special case for 1-leaf meshes if(mNbLeaves==1) { mModelCode |= OPC_SINGLE_NODE; Status = true; goto FreeAndExit; } // Allocate our structures Data.mLeaves = new AABB[Data.mNbLeaves]; CHECKALLOC(Data.mLeaves); mTriangles = new LeafTriangles[Data.mNbLeaves]; CHECKALLOC(mTriangles); // Walk the tree again & setup leaf data Data.mTriangles = mTriangles; Data.mBase = mSource->GetIndices(); Data.mNbLeaves = 0; // Reset for incoming walk mSource->Walk(Local::SetupLeafData, &Data); // Handle source indices { bool MustKeepIndices = true; if(create.mCanRemap) { // We try to get rid of source indices (saving more ram!) by reorganizing triangle arrays... // Remap can fail when we use callbacks => keep track of indices in that case (it still // works, only using more memory) if(create.mIMesh->RemapClient(mSource->GetNbPrimitives(), mSource->GetIndices())) { MustKeepIndices = false; } } if(MustKeepIndices) { // Keep track of source indices (from vanilla tree) mNbPrimitives = mSource->GetNbPrimitives(); mIndices = new udword[mNbPrimitives]; CopyMemory(mIndices, mSource->GetIndices(), mNbPrimitives*sizeof(udword)); } } // Now, create our optimized tree using previous leaf nodes LeafTree = new AABBTree; CHECKALLOC(LeafTree); { AABBTreeOfAABBsBuilder TB; // Now using boxes ! TB.mSettings = create.mSettings; TB.mSettings.mLimit = 1; // We now want a complete tree so that we can "optimize" it TB.mNbPrimitives = Data.mNbLeaves; TB.mAABBArray = Data.mLeaves; if(!LeafTree->Build(&TB)) goto FreeAndExit; } // 3) Create an optimized tree according to user-settings if(!CreateTree(create.mNoLeaf, create.mQuantized)) goto FreeAndExit; // 3-2) Create optimized tree if(!mTree->Build(LeafTree)) goto FreeAndExit; // Finally ok... Status = true; FreeAndExit: // Allow me this one... DELETESINGLE(LeafTree); // 3-3) Delete generic tree if needed if(!create.mKeepOriginal) DELETESINGLE(mSource); return Status; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Gets the number of bytes used by the tree. * \return amount of bytes used */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// udword HybridModel::GetUsedBytes() const { udword UsedBytes = 0; if(mTree) UsedBytes += mTree->GetUsedBytes(); if(mIndices) UsedBytes += mNbPrimitives * sizeof(udword); // mIndices if(mTriangles) UsedBytes += mNbLeaves * sizeof(LeafTriangles); // mTriangles return UsedBytes; } inline_ void ComputeMinMax(Point& min, Point& max, const VertexPointers& vp) { // Compute triangle's AABB = a leaf box #ifdef OPC_USE_FCOMI // a 15% speedup on my machine, not much min.x = FCMin3(vp.Vertex[0]->x, vp.Vertex[1]->x, vp.Vertex[2]->x); max.x = FCMax3(vp.Vertex[0]->x, vp.Vertex[1]->x, vp.Vertex[2]->x); min.y = FCMin3(vp.Vertex[0]->y, vp.Vertex[1]->y, vp.Vertex[2]->y); max.y = FCMax3(vp.Vertex[0]->y, vp.Vertex[1]->y, vp.Vertex[2]->y); min.z = FCMin3(vp.Vertex[0]->z, vp.Vertex[1]->z, vp.Vertex[2]->z); max.z = FCMax3(vp.Vertex[0]->z, vp.Vertex[1]->z, vp.Vertex[2]->z); #else min = *vp.Vertex[0]; max = *vp.Vertex[0]; min.Min(*vp.Vertex[1]); max.Max(*vp.Vertex[1]); min.Min(*vp.Vertex[2]); max.Max(*vp.Vertex[2]); #endif } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Refits the collision model. This can be used to handle dynamic meshes. Usage is: * 1. modify your mesh vertices (keep the topology constant!) * 2. refit the tree (call this method) * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool HybridModel::Refit() { if(!mIMesh) return false; if(!mTree) return false; if(IsQuantized()) return false; if(HasLeafNodes()) return false; const LeafTriangles* LT = GetLeafTriangles(); const udword* Indices = GetIndices(); // Bottom-up update VertexPointers VP; ConversionArea VC; Point Min,Max; Point Min_,Max_; udword Index = mTree->GetNbNodes(); AABBNoLeafNode* Nodes = const_cast(static_cast(static_cast(mTree)->GetNodes())); while(Index--) { AABBNoLeafNode& Current = Nodes[Index]; if(Current.HasPosLeaf()) { const LeafTriangles& CurrentLeaf = LT[Current.GetPosPrimitive()]; Min.SetPlusInfinity(); Max.SetMinusInfinity(); Point TmpMin, TmpMax; // Each leaf box has a set of triangles udword NbTris = CurrentLeaf.GetNbTriangles(); if(Indices) { const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()]; // Loop through triangles and test each of them while(NbTris--) { mIMesh->GetTriangle(VP, *T++, VC); ComputeMinMax(TmpMin, TmpMax, VP); Min.Min(TmpMin); Max.Max(TmpMax); } } else { udword BaseIndex = CurrentLeaf.GetTriangleIndex(); // Loop through triangles and test each of them while(NbTris--) { mIMesh->GetTriangle(VP, BaseIndex++, VC); ComputeMinMax(TmpMin, TmpMax, VP); Min.Min(TmpMin); Max.Max(TmpMax); } } } else { const CollisionAABB& CurrentBox = Current.GetPos()->mAABB; CurrentBox.GetMin(Min); CurrentBox.GetMax(Max); } if(Current.HasNegLeaf()) { const LeafTriangles& CurrentLeaf = LT[Current.GetNegPrimitive()]; Min_.SetPlusInfinity(); Max_.SetMinusInfinity(); Point TmpMin, TmpMax; // Each leaf box has a set of triangles udword NbTris = CurrentLeaf.GetNbTriangles(); if(Indices) { const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()]; // Loop through triangles and test each of them while(NbTris--) { mIMesh->GetTriangle(VP, *T++, VC); ComputeMinMax(TmpMin, TmpMax, VP); Min_.Min(TmpMin); Max_.Max(TmpMax); } } else { udword BaseIndex = CurrentLeaf.GetTriangleIndex(); // Loop through triangles and test each of them while(NbTris--) { mIMesh->GetTriangle(VP, BaseIndex++, VC); ComputeMinMax(TmpMin, TmpMax, VP); Min_.Min(TmpMin); Max_.Max(TmpMax); } } } else { const CollisionAABB& CurrentBox = Current.GetNeg()->mAABB; CurrentBox.GetMin(Min_); CurrentBox.GetMax(Max_); } #ifdef OPC_USE_FCOMI Min.x = FCMin2(Min.x, Min_.x); Max.x = FCMax2(Max.x, Max_.x); Min.y = FCMin2(Min.y, Min_.y); Max.y = FCMax2(Max.y, Max_.y); Min.z = FCMin2(Min.z, Min_.z); Max.z = FCMax2(Max.z, Max_.z); #else Min.Min(Min_); Max.Max(Max_); #endif Current.mAABB.SetMinMax(Min, Max); } return true; } ode-0.16/OPCODE/OPC_TriBoxOverlap.h0000664000175200017520000002633313403272463013534 00000000000000 //! This macro quickly finds the min & max values among 3 variables #define FINDMINMAX(x0, x1, x2, min, max) \ min = max = x0; \ if(x1max) max=x1; \ if(x2max) max=x2; //! TO BE DOCUMENTED inline_ BOOL planeBoxOverlap(const Point& normal, const float d, const Point& maxbox) { Point vmin, vmax; for(udword q=0;q<=2;q++) { if(normal[q]>0.0f) { vmin[q]=-maxbox[q]; vmax[q]=maxbox[q]; } else { vmin[q]=maxbox[q]; vmax[q]=-maxbox[q]; } } if((normal|vmin)+d>0.0f) return FALSE; if((normal|vmax)+d>=0.0f) return TRUE; return FALSE; } //! TO BE DOCUMENTED #define AXISTEST_X01(a, b, fa, fb) \ min = a*v0.y - b*v0.z; \ max = a*v2.y - b*v2.z; \ if(min>max) {const float tmp=max; max=min; min=tmp; } \ rad = fa * extents.y + fb * extents.z; \ if(min>rad || max<-rad) return FALSE; //! TO BE DOCUMENTED #define AXISTEST_X2(a, b, fa, fb) \ min = a*v0.y - b*v0.z; \ max = a*v1.y - b*v1.z; \ if(min>max) {const float tmp=max; max=min; min=tmp; } \ rad = fa * extents.y + fb * extents.z; \ if(min>rad || max<-rad) return FALSE; //! TO BE DOCUMENTED #define AXISTEST_Y02(a, b, fa, fb) \ min = b*v0.z - a*v0.x; \ max = b*v2.z - a*v2.x; \ if(min>max) {const float tmp=max; max=min; min=tmp; } \ rad = fa * extents.x + fb * extents.z; \ if(min>rad || max<-rad) return FALSE; //! TO BE DOCUMENTED #define AXISTEST_Y1(a, b, fa, fb) \ min = b*v0.z - a*v0.x; \ max = b*v1.z - a*v1.x; \ if(min>max) {const float tmp=max; max=min; min=tmp; } \ rad = fa * extents.x + fb * extents.z; \ if(min>rad || max<-rad) return FALSE; //! TO BE DOCUMENTED #define AXISTEST_Z12(a, b, fa, fb) \ min = a*v1.x - b*v1.y; \ max = a*v2.x - b*v2.y; \ if(min>max) {const float tmp=max; max=min; min=tmp; } \ rad = fa * extents.x + fb * extents.y; \ if(min>rad || max<-rad) return FALSE; //! TO BE DOCUMENTED #define AXISTEST_Z0(a, b, fa, fb) \ min = a*v0.x - b*v0.y; \ max = a*v1.x - b*v1.y; \ if(min>max) {const float tmp=max; max=min; min=tmp; } \ rad = fa * extents.x + fb * extents.y; \ if(min>rad || max<-rad) return FALSE; // compute triangle edges // - edges lazy evaluated to take advantage of early exits // - fabs precomputed (half less work, possible since extents are always >0) // - customized macros to take advantage of the null component // - axis vector discarded, possibly saves useless movs #define IMPLEMENT_CLASS3_TESTS \ float rad; \ float min, max; \ \ const float fey0 = fabsf(e0.y); \ const float fez0 = fabsf(e0.z); \ AXISTEST_X01(e0.z, e0.y, fez0, fey0); \ const float fex0 = fabsf(e0.x); \ AXISTEST_Y02(e0.z, e0.x, fez0, fex0); \ AXISTEST_Z12(e0.y, e0.x, fey0, fex0); \ \ const float fey1 = fabsf(e1.y); \ const float fez1 = fabsf(e1.z); \ AXISTEST_X01(e1.z, e1.y, fez1, fey1); \ const float fex1 = fabsf(e1.x); \ AXISTEST_Y02(e1.z, e1.x, fez1, fex1); \ AXISTEST_Z0(e1.y, e1.x, fey1, fex1); \ \ const Point e2 = mLeafVerts[0] - mLeafVerts[2]; \ const float fey2 = fabsf(e2.y); \ const float fez2 = fabsf(e2.z); \ AXISTEST_X2(e2.z, e2.y, fez2, fey2); \ const float fex2 = fabsf(e2.x); \ AXISTEST_Y1(e2.z, e2.x, fez2, fex2); \ AXISTEST_Z12(e2.y, e2.x, fey2, fex2); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Triangle-Box overlap test using the separating axis theorem. * This is the code from Tomas Möller, a bit optimized: * - with some more lazy evaluation (faster path on PC) * - with a tiny bit of assembly * - with "SAT-lite" applied if needed * - and perhaps with some more minor modifs... * * \param center [in] box center * \param extents [in] box extents * \return true if triangle & box overlap */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ BOOL AABBTreeCollider::TriBoxOverlap(const Point& center, const Point& extents) { // Stats mNbBVPrimTests++; // use separating axis theorem to test overlap between triangle and box // need to test for overlap in these directions: // 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle // we do not even need to test these) // 2) normal of the triangle // 3) crossproduct(edge from tri, {x,y,z}-directin) // this gives 3x3=9 more tests // move everything so that the boxcenter is in (0,0,0) Point v0, v1, v2; v0.x = mLeafVerts[0].x - center.x; v1.x = mLeafVerts[1].x - center.x; v2.x = mLeafVerts[2].x - center.x; // First, test overlap in the {x,y,z}-directions #ifdef OPC_USE_FCOMI // find min, max of the triangle in x-direction, and test for overlap in X if(FCMin3(v0.x, v1.x, v2.x)>extents.x) return FALSE; if(FCMax3(v0.x, v1.x, v2.x)<-extents.x) return FALSE; // same for Y v0.y = mLeafVerts[0].y - center.y; v1.y = mLeafVerts[1].y - center.y; v2.y = mLeafVerts[2].y - center.y; if(FCMin3(v0.y, v1.y, v2.y)>extents.y) return FALSE; if(FCMax3(v0.y, v1.y, v2.y)<-extents.y) return FALSE; // same for Z v0.z = mLeafVerts[0].z - center.z; v1.z = mLeafVerts[1].z - center.z; v2.z = mLeafVerts[2].z - center.z; if(FCMin3(v0.z, v1.z, v2.z)>extents.z) return FALSE; if(FCMax3(v0.z, v1.z, v2.z)<-extents.z) return FALSE; #else float min,max; // Find min, max of the triangle in x-direction, and test for overlap in X FINDMINMAX(v0.x, v1.x, v2.x, min, max); if(min>extents.x || max<-extents.x) return FALSE; // Same for Y v0.y = mLeafVerts[0].y - center.y; v1.y = mLeafVerts[1].y - center.y; v2.y = mLeafVerts[2].y - center.y; FINDMINMAX(v0.y, v1.y, v2.y, min, max); if(min>extents.y || max<-extents.y) return FALSE; // Same for Z v0.z = mLeafVerts[0].z - center.z; v1.z = mLeafVerts[1].z - center.z; v2.z = mLeafVerts[2].z - center.z; FINDMINMAX(v0.z, v1.z, v2.z, min, max); if(min>extents.z || max<-extents.z) return FALSE; #endif // 2) Test if the box intersects the plane of the triangle // compute plane equation of triangle: normal*x+d=0 // ### could be precomputed since we use the same leaf triangle several times const Point e0 = v1 - v0; const Point e1 = v2 - v1; const Point normal = e0 ^ e1; const float d = -normal|v0; if(!planeBoxOverlap(normal, d, extents)) return FALSE; // 3) "Class III" tests if(mFullPrimBoxTest) { IMPLEMENT_CLASS3_TESTS } return TRUE; } //! A dedicated version where the box is constant inline_ BOOL OBBCollider::TriBoxOverlap() { // Stats mNbVolumePrimTests++; // Hook const Point& extents = mBoxExtents; const Point& v0 = mLeafVerts[0]; const Point& v1 = mLeafVerts[1]; const Point& v2 = mLeafVerts[2]; // use separating axis theorem to test overlap between triangle and box // need to test for overlap in these directions: // 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle // we do not even need to test these) // 2) normal of the triangle // 3) crossproduct(edge from tri, {x,y,z}-directin) // this gives 3x3=9 more tests // Box center is already in (0,0,0) // First, test overlap in the {x,y,z}-directions #ifdef OPC_USE_FCOMI // find min, max of the triangle in x-direction, and test for overlap in X if(FCMin3(v0.x, v1.x, v2.x)>mBoxExtents.x) return FALSE; if(FCMax3(v0.x, v1.x, v2.x)<-mBoxExtents.x) return FALSE; if(FCMin3(v0.y, v1.y, v2.y)>mBoxExtents.y) return FALSE; if(FCMax3(v0.y, v1.y, v2.y)<-mBoxExtents.y) return FALSE; if(FCMin3(v0.z, v1.z, v2.z)>mBoxExtents.z) return FALSE; if(FCMax3(v0.z, v1.z, v2.z)<-mBoxExtents.z) return FALSE; #else float min,max; // Find min, max of the triangle in x-direction, and test for overlap in X FINDMINMAX(v0.x, v1.x, v2.x, min, max); if(min>mBoxExtents.x || max<-mBoxExtents.x) return FALSE; FINDMINMAX(v0.y, v1.y, v2.y, min, max); if(min>mBoxExtents.y || max<-mBoxExtents.y) return FALSE; FINDMINMAX(v0.z, v1.z, v2.z, min, max); if(min>mBoxExtents.z || max<-mBoxExtents.z) return FALSE; #endif // 2) Test if the box intersects the plane of the triangle // compute plane equation of triangle: normal*x+d=0 // ### could be precomputed since we use the same leaf triangle several times const Point e0 = v1 - v0; const Point e1 = v2 - v1; const Point normal = e0 ^ e1; const float d = -normal|v0; if(!planeBoxOverlap(normal, d, mBoxExtents)) return FALSE; // 3) "Class III" tests - here we always do full tests since the box is a primitive (not a BV) { IMPLEMENT_CLASS3_TESTS } return TRUE; } //! ...and another one, jeez inline_ BOOL AABBCollider::TriBoxOverlap() { // Stats mNbVolumePrimTests++; // Hook const Point& center = mBox.mCenter; const Point& extents = mBox.mExtents; // use separating axis theorem to test overlap between triangle and box // need to test for overlap in these directions: // 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle // we do not even need to test these) // 2) normal of the triangle // 3) crossproduct(edge from tri, {x,y,z}-directin) // this gives 3x3=9 more tests // move everything so that the boxcenter is in (0,0,0) Point v0, v1, v2; v0.x = mLeafVerts[0].x - center.x; v1.x = mLeafVerts[1].x - center.x; v2.x = mLeafVerts[2].x - center.x; // First, test overlap in the {x,y,z}-directions #ifdef OPC_USE_FCOMI // find min, max of the triangle in x-direction, and test for overlap in X if(FCMin3(v0.x, v1.x, v2.x)>extents.x) return FALSE; if(FCMax3(v0.x, v1.x, v2.x)<-extents.x) return FALSE; // same for Y v0.y = mLeafVerts[0].y - center.y; v1.y = mLeafVerts[1].y - center.y; v2.y = mLeafVerts[2].y - center.y; if(FCMin3(v0.y, v1.y, v2.y)>extents.y) return FALSE; if(FCMax3(v0.y, v1.y, v2.y)<-extents.y) return FALSE; // same for Z v0.z = mLeafVerts[0].z - center.z; v1.z = mLeafVerts[1].z - center.z; v2.z = mLeafVerts[2].z - center.z; if(FCMin3(v0.z, v1.z, v2.z)>extents.z) return FALSE; if(FCMax3(v0.z, v1.z, v2.z)<-extents.z) return FALSE; #else float min,max; // Find min, max of the triangle in x-direction, and test for overlap in X FINDMINMAX(v0.x, v1.x, v2.x, min, max); if(min>extents.x || max<-extents.x) return FALSE; // Same for Y v0.y = mLeafVerts[0].y - center.y; v1.y = mLeafVerts[1].y - center.y; v2.y = mLeafVerts[2].y - center.y; FINDMINMAX(v0.y, v1.y, v2.y, min, max); if(min>extents.y || max<-extents.y) return FALSE; // Same for Z v0.z = mLeafVerts[0].z - center.z; v1.z = mLeafVerts[1].z - center.z; v2.z = mLeafVerts[2].z - center.z; FINDMINMAX(v0.z, v1.z, v2.z, min, max); if(min>extents.z || max<-extents.z) return FALSE; #endif // 2) Test if the box intersects the plane of the triangle // compute plane equation of triangle: normal*x+d=0 // ### could be precomputed since we use the same leaf triangle several times const Point e0 = v1 - v0; const Point e1 = v2 - v1; const Point normal = e0 ^ e1; const float d = -normal|v0; if(!planeBoxOverlap(normal, d, extents)) return FALSE; // 3) "Class III" tests - here we always do full tests since the box is a primitive (not a BV) { IMPLEMENT_CLASS3_TESTS } return TRUE; } ode-0.16/OPCODE/OPC_MeshInterface.h0000664000175200017520000003571513403272463013515 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* * OPCODE - Optimized Collision Detection * Copyright (C) 2001 Pierre Terdiman * Homepage: http://www.codercorner.com/Opcode.htm */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains a mesh interface. * \file OPC_MeshInterface.h * \author Pierre Terdiman * \date November, 27, 2002 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Include Guard #ifndef __OPC_MESHINTERFACE_H__ #define __OPC_MESHINTERFACE_H__ struct VertexPointers { const Point* Vertex[3]; bool BackfaceCulling(const Point& source) { const Point& p0 = *Vertex[0]; const Point& p1 = *Vertex[1]; const Point& p2 = *Vertex[2]; // Compute normal direction Point Normal = (p2 - p1)^(p0 - p1); // Backface culling return (Normal | (source - p0)) >= 0.0f; } }; struct VertexPointersEx { VertexPointers vp; dTriIndex Index[3]; }; typedef Point ConversionArea[3]; #ifdef OPC_USE_CALLBACKS /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * User-callback, called by OPCODE to request vertices from the app. * \param triangle_index [in] face index for which the system is requesting the vertices * \param triangle [out] triangle's vertices (must be provided by the user) * \param user_data [in] user-defined data from SetCallback() */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// typedef void (*RequestCallback) (udword triangle_index, VertexPointers& triangle, void* user_data); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * User-callback, called by OPCODE to request vertex indices from the app. * \param triangle_index [in] face index for which the system is requesting the vertices * \param triangle [out] triangle's vertices with indices (must be provided by the user) * \param user_data [in] user-defined data from SetExCallback() */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// typedef void (*RequestExCallback) (udword triangle_index, VertexPointersEx& triangle, void* user_data); #endif class OPCODE_API MeshInterface { public: // Constructor / Destructor MeshInterface(); ~MeshInterface(); // Common settings inline_ udword GetNbTriangles() const { return mNbTris; } inline_ udword GetNbVertices() const { return mNbVerts; } inline_ void SetNbTriangles(udword nb) { mNbTris = nb; } inline_ void SetNbVertices(udword nb) { mNbVerts = nb; } #ifdef OPC_USE_CALLBACKS // Callback settings /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Callback control: setups object callback. Must provide triangle-vertices for a given triangle index. * \param callback [in] user-defined callback * \param user_data [in] user-defined data * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool SetCallback(RequestCallback callback, void* user_data); inline_ void* GetUserData() const { return mUserData; } inline_ RequestCallback GetCallback() const { return mObjCallback; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Callback control: setups object callback. Must provide triangle-vertices for a given triangle index. * \param callback [in] user-defined callback * \param user_data [in] user-defined data * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool SetExCallback(RequestExCallback callback, void* user_data); inline_ void* GetExUserData() const { return mExUserData; } inline_ RequestExCallback GetExCallback() const { return mObjExCallback; } #else // Pointers settings /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Pointers control: setups object pointers. Must provide access to faces and vertices for a given object. * \param tris [in] pointer to triangles * \param verts [in] pointer to vertices * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool SetPointers(const IndexedTriangle* tris, const Point* verts); inline_ const IndexedTriangle* GetTris() const { return mTris; } inline_ const Point* GetVerts() const { return mVerts; } #ifdef OPC_USE_STRIDE // Strides settings /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Strides control * \param tri_stride [in] size of a triangle in bytes. The first sizeof(IndexedTriangle) bytes are used to get vertex indices. * \param vertex_stride [in] size of a vertex in bytes. The first sizeof(Point) bytes are used to get vertex position. * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool SetStrides(udword tri_stride=sizeof(IndexedTriangle), udword vertex_stride=sizeof(Point)); inline_ udword GetTriStride() const { return mTriStride; } inline_ udword GetVertexStride() const { return mVertexStride; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Single/Double control * \param value [in] Indicates if mesh data is provided as array of \c single values. If \c false, data is expected to contain \c double elements. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ void SetSingle(bool value) { mFetchTriangle = (value ? &MeshInterface::FetchTriangleFromSingles : &MeshInterface::FetchTriangleFromDoubles); mFetchExTriangle = (value ? &MeshInterface::FetchExTriangleFromSingles : &MeshInterface::FetchExTriangleFromDoubles); } #else inline_ bool SetStrides(udword tri_stride=sizeof(IndexedTriangle), udword vertex_stride=sizeof(Point)) { return true; } inline_ void SetSingle(bool value) {} inline_ udword GetTriStride() const { return sizeof(IndexedTriangle); } inline_ udword GetVertexStride() const { return sizeof(Point); } #endif #endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Fetches a triangle given a triangle index. * \param vp [out] required triangle's vertex pointers * \param index [in] triangle index * \param vc [in,out] storage required for data conversion (pass local variable with same scope as \a vp, as \a vp may point to this memory on return) */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ void GetTriangle(VertexPointers& vp, udword index, ConversionArea vc) const { #ifdef OPC_USE_CALLBACKS (mObjCallback)(index, vp, mUserData); #else #ifdef OPC_USE_STRIDE // Since there was conditional statement "if (Single)" which was unpredictable for compiler // and required both branches to be always generated what made inlining a questionable // benefit, I consider it better to introduce a forced call // but get rig of branching and dead code injection. ((*this).*mFetchTriangle)(vp, index, vc); #else const Point* Verts = GetVerts(); const IndexedTriangle* T = &mTris[index]; vp.Vertex[0] = &Verts[T->mVRef[0]]; vp.Vertex[1] = &Verts[T->mVRef[1]]; vp.Vertex[2] = &Verts[T->mVRef[2]]; #endif #endif } inline_ bool GetExTriangle(VertexPointersEx& vpe, udword index, ConversionArea vc) const { #ifdef OPC_USE_CALLBACKS if (mObjExCallback) { (mObjExCallback)(index, vpe, mUserData); return true; } else { (mObjCallback)(index, vpe.vp, mUserData); return false; } #else #ifdef OPC_USE_STRIDE // Since there was conditional statement "if (Single)" which was unpredictable for compiler // and required both branches to be always generated what made inlining a questionable // benefit, I consider it better to introduce a forced call // but get rig of branching and dead code injection. ((*this).*mFetchExTriangle)(vpe, index, vc); return true; #else const Point* Verts = GetVerts(); const IndexedTriangle* T = &mTris[index]; dTriIndex VertIndex0 = T->mVRef[0]; vpe.Index[0] = VertIndex0; vpe.vp.Vertex[0] = &Verts[VertIndex0]; dTriIndex VertIndex1 = T->mVRef[1]; vpe.Index[1] = VertIndex1; vpe.vp.Vertex[1] = &Verts[VertIndex1]; dTriIndex VertIndex2 = T->mVRef[2]; vpe.Index[2] = VertIndex2; vpe.vp.Vertex[2] = &Verts[VertIndex2]; return true; #endif #endif } private: #ifndef OPC_USE_CALLBACKS #ifdef OPC_USE_STRIDE void FetchTriangleFromSingles(VertexPointers& vp, udword index, ConversionArea vc) const; void FetchTriangleFromDoubles(VertexPointers& vp, udword index, ConversionArea vc) const; void FetchExTriangleFromSingles(VertexPointersEx& vpe, udword index, ConversionArea vc) const; void FetchExTriangleFromDoubles(VertexPointersEx& vpe, udword index, ConversionArea vc) const; #endif #endif public: /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Remaps client's mesh according to a permutation. * \param nb_indices [in] number of indices in the permutation (will be checked against number of triangles) * \param permutation [in] list of triangle indices * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool RemapClient(udword nb_indices, const dTriIndex* permutation) const; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Checks the mesh interface is valid, i.e. things have been setup correctly. * \return true if valid */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool IsValid() const; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Checks the mesh itself is valid. * Currently we only look for degenerate faces. * \return number of degenerate faces */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// udword CheckTopology() const; private: udword mNbTris; //!< Number of triangles in the input model udword mNbVerts; //!< Number of vertices in the input model #ifdef OPC_USE_CALLBACKS // User callback void* mUserData; //!< User-defined data sent to callback RequestCallback mObjCallback; //!< Object callback void* mExUserData; //!< User-defined data sent to ex-callback RequestExCallback mObjExCallback; //!< Object ex-callback #else // User pointers #ifdef OPC_USE_STRIDE udword mTriStride; //!< Possible triangle stride in bytes [Opcode 1.3] udword mVertexStride; //!< Possible vertex stride in bytes [Opcode 1.3] typedef void (MeshInterface:: *TriangleFetchProc)(VertexPointers& vp, udword index, ConversionArea vc) const; TriangleFetchProc mFetchTriangle; typedef void (MeshInterface:: *ExTriangleFetchProc)(VertexPointersEx& vpe, udword index, ConversionArea vc) const; ExTriangleFetchProc mFetchExTriangle; #endif const IndexedTriangle* mTris; //!< Array of indexed triangles const Point* mVerts; //!< Array of vertices #endif }; #endif //__OPC_MESHINTERFACE_H__ ode-0.16/OPCODE/OPC_OBBCollider.h0000664000175200017520000001502613403272463013051 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* * OPCODE - Optimized Collision Detection * Copyright (C) 2001 Pierre Terdiman * Homepage: http://www.codercorner.com/Opcode.htm */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains code for an OBB collider. * \file OPC_OBBCollider.h * \author Pierre Terdiman * \date January, 1st, 2002 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Include Guard #ifndef __OPC_OBBCOLLIDER_H__ #define __OPC_OBBCOLLIDER_H__ struct OPCODE_API OBBCache : VolumeCache { OBBCache() : FatCoeff(1.1f) { FatBox.mCenter.Zero(); FatBox.mExtents.Zero(); FatBox.mRot.Identity(); } // Cached faces signature OBB FatBox; //!< Box used when performing the query resulting in cached faces // User settings float FatCoeff; //!< extents multiplier used to create a fat box }; class OPCODE_API OBBCollider : public VolumeCollider { public: // Constructor / Destructor OBBCollider(); virtual ~OBBCollider(); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Generic collision query for generic OPCODE models. After the call, access the results: * - with GetContactStatus() * - with GetNbTouchedPrimitives() * - with GetTouchedPrimitives() * * \param cache [in/out] a box cache * \param box [in] collision OBB in local space * \param model [in] Opcode model to collide with * \param worldb [in] OBB's world matrix, or null * \param worldm [in] model's world matrix, or null * \return true if success * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool Collide(OBBCache& cache, const OBB& box, const Model& model, const Matrix4x4* worldb=null, const Matrix4x4* worldm=null); // Settings /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Settings: select between full box-box tests or "SAT-lite" tests (where Class III axes are discarded) * \param flag [in] true for full tests, false for coarse tests */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ void SetFullBoxBoxTest(bool flag) { mFullBoxBoxTest = flag; } // Settings /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Validates current settings. You should call this method after all the settings and callbacks have been defined for a collider. * \return null if everything is ok, else a string describing the problem */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// override(Collider) const char* ValidateSettings(); protected: // Precomputed data Matrix3x3 mAR; //!< Absolute rotation matrix Matrix3x3 mRModelToBox; //!< Rotation from model space to obb space Matrix3x3 mRBoxToModel; //!< Rotation from obb space to model space Point mTModelToBox; //!< Translation from model space to obb space Point mTBoxToModel; //!< Translation from obb space to model space Point mBoxExtents; Point mB0; //!< - mTModelToBox + mBoxExtents Point mB1; //!< - mTModelToBox - mBoxExtents float mBBx1; float mBBy1; float mBBz1; float mBB_1; float mBB_2; float mBB_3; float mBB_4; float mBB_5; float mBB_6; float mBB_7; float mBB_8; float mBB_9; // Leaf description Point mLeafVerts[3]; //!< Triangle vertices // Settings bool mFullBoxBoxTest; //!< Perform full BV-BV tests (true) or SAT-lite tests (false) // Internal methods void _Collide(const AABBCollisionNode* node); void _Collide(const AABBNoLeafNode* node); void _Collide(const AABBQuantizedNode* node); void _Collide(const AABBQuantizedNoLeafNode* node); void _CollideNoPrimitiveTest(const AABBCollisionNode* node); void _CollideNoPrimitiveTest(const AABBNoLeafNode* node); void _CollideNoPrimitiveTest(const AABBQuantizedNode* node); void _CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node); // Overlap tests inline_ BOOL OBBContainsBox(const Point& bc, const Point& be); inline_ BOOL BoxBoxOverlap(const Point& extents, const Point& center); inline_ BOOL TriBoxOverlap(); // Init methods BOOL InitQuery(OBBCache& cache, const OBB& box, const Matrix4x4* worldb=null, const Matrix4x4* worldm=null); }; class OPCODE_API HybridOBBCollider : public OBBCollider { public: // Constructor / Destructor HybridOBBCollider(); virtual ~HybridOBBCollider(); bool Collide(OBBCache& cache, const OBB& box, const HybridModel& model, const Matrix4x4* worldb=null, const Matrix4x4* worldm=null); protected: Container mTouchedBoxes; }; #endif // __OPC_OBBCOLLIDER_H__ ode-0.16/OPCODE/README-ODE.txt0000664000175200017520000000113513403272463012216 00000000000000 This is a copy of the OPCODE collision detection library by Pierre Terdiman. See http://www.codercorner.com/Opcode.htm for more information, and read the ReadMe.txt in this directory. If you want to use the TriList (triangle mesh) geometry class in ODE, the OPCODE library must be compiled. If you are using the autotools support to compile ODE, you just have to specify --with-trimesh=opcode when calling ./configure. This code was originally written for and compiled on windows, but it has been ported so that it should compile under unix/gcc too. Your mileage may vary. Russ Smith, April 12 2005. ode-0.16/OPCODE/OPC_OptimizedTree.h0000664000175200017520000002227213403272463013556 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* * OPCODE - Optimized Collision Detection * Copyright (C) 2001 Pierre Terdiman * Homepage: http://www.codercorner.com/Opcode.htm */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains code for optimized trees. * \file OPC_OptimizedTree.h * \author Pierre Terdiman * \date March, 20, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Include Guard #ifndef __OPC_OPTIMIZEDTREE_H__ #define __OPC_OPTIMIZEDTREE_H__ //! Common interface for a node of an implicit tree #define IMPLEMENT_IMPLICIT_NODE(base_class, volume) \ public: \ /* Constructor / Destructor */ \ inline_ base_class() : mData(0) {} \ inline_ ~base_class() {} \ /* Leaf test */ \ inline_ BOOL IsLeaf() const { return (mData&1)!=0; } \ /* Data access */ \ inline_ const base_class* GetPos() const { return (base_class*)mData; } \ inline_ const base_class* GetNeg() const { return ((base_class*)mData)+1; } \ inline_ size_t GetPrimitive() const { return (mData>>1); } \ /* Stats */ \ inline_ udword GetNodeSize() const { return SIZEOFOBJECT; } \ \ volume mAABB; \ size_t mData; //! Common interface for a node of a no-leaf tree #define IMPLEMENT_NOLEAF_NODE(base_class, volume) \ public: \ /* Constructor / Destructor */ \ inline_ base_class() : mPosData(0), mNegData(0) {} \ inline_ ~base_class() {} \ /* Leaf tests */ \ inline_ BOOL HasPosLeaf() const { return (mPosData&1)!=0; } \ inline_ BOOL HasNegLeaf() const { return (mNegData&1)!=0; } \ /* Data access */ \ inline_ const base_class* GetPos() const { return (base_class*)mPosData; } \ inline_ const base_class* GetNeg() const { return (base_class*)mNegData; } \ inline_ size_t GetPosPrimitive() const { return (mPosData>>1); } \ inline_ size_t GetNegPrimitive() const { return (mNegData>>1); } \ /* Stats */ \ inline_ udword GetNodeSize() const { return SIZEOFOBJECT; } \ \ volume mAABB; \ size_t mPosData; \ size_t mNegData; class OPCODE_API AABBCollisionNode { IMPLEMENT_IMPLICIT_NODE(AABBCollisionNode, CollisionAABB) inline_ float GetVolume() const { return mAABB.mExtents.x * mAABB.mExtents.y * mAABB.mExtents.z; } inline_ float GetSize() const { return mAABB.mExtents.SquareMagnitude(); } inline_ udword GetRadius() const { udword* Bits = (udword*)&mAABB.mExtents.x; udword Max = Bits[0]; if(Bits[1]>Max) Max = Bits[1]; if(Bits[2]>Max) Max = Bits[2]; return Max; } // NB: using the square-magnitude or the true volume of the box, seems to yield better results // (assuming UNC-like informed traversal methods). I borrowed this idea from PQP. The usual "size" // otherwise, is the largest box extent. In SOLID that extent is computed on-the-fly each time it's // needed (the best approach IMHO). In RAPID the rotation matrix is permuted so that Extent[0] is // always the greatest, which saves looking for it at runtime. On the other hand, it yields matrices // whose determinant is not 1, i.e. you can't encode them anymore as unit quaternions. Not a very // good strategy. }; class OPCODE_API AABBQuantizedNode { IMPLEMENT_IMPLICIT_NODE(AABBQuantizedNode, QuantizedAABB) inline_ uword GetSize() const { const uword* Bits = mAABB.mExtents; uword Max = Bits[0]; if(Bits[1]>Max) Max = Bits[1]; if(Bits[2]>Max) Max = Bits[2]; return Max; } // NB: for quantized nodes I don't feel like computing a square-magnitude with integers all // over the place.......! }; class OPCODE_API AABBNoLeafNode { IMPLEMENT_NOLEAF_NODE(AABBNoLeafNode, CollisionAABB) }; class OPCODE_API AABBQuantizedNoLeafNode { IMPLEMENT_NOLEAF_NODE(AABBQuantizedNoLeafNode, QuantizedAABB) }; //! Common interface for a collision tree #define IMPLEMENT_COLLISION_TREE(base_class, node) \ public: \ /* Constructor / Destructor */ \ base_class(); \ virtual ~base_class(); \ /* Builds from a standard tree */ \ override(AABBOptimizedTree) bool Build(AABBTree* tree); \ /* Refits the tree */ \ override(AABBOptimizedTree) bool Refit(const MeshInterface* mesh_interface); \ /* Walks the tree */ \ override(AABBOptimizedTree) bool Walk(GenericWalkingCallback callback, void* user_data) const; \ /* Data access */ \ inline_ const node* GetNodes() const { return mNodes; } \ /* Stats */ \ override(AABBOptimizedTree) udword GetUsedBytes() const { return mNbNodes*sizeof(node); } \ private: \ node* mNodes; typedef bool (*GenericWalkingCallback) (const void* current, void* user_data); class OPCODE_API AABBOptimizedTree { public: // Constructor / Destructor AABBOptimizedTree() : mNbNodes (0) {} virtual ~AABBOptimizedTree() {} /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Builds the collision tree from a generic AABB tree. * \param tree [in] generic AABB tree * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// virtual bool Build(AABBTree* tree) = 0; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Refits the collision tree after vertices have been modified. * \param mesh_interface [in] mesh interface for current model * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// virtual bool Refit(const MeshInterface* mesh_interface) = 0; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Walks the tree and call the user back for each node. * \param callback [in] walking callback * \param user_data [in] callback's user data * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// virtual bool Walk(GenericWalkingCallback callback, void* user_data) const = 0; // Data access virtual udword GetUsedBytes() const = 0; inline_ udword GetNbNodes() const { return mNbNodes; } protected: udword mNbNodes; }; class OPCODE_API AABBCollisionTree : public AABBOptimizedTree { IMPLEMENT_COLLISION_TREE(AABBCollisionTree, AABBCollisionNode) }; class OPCODE_API AABBNoLeafTree : public AABBOptimizedTree { IMPLEMENT_COLLISION_TREE(AABBNoLeafTree, AABBNoLeafNode) }; class OPCODE_API AABBQuantizedTree : public AABBOptimizedTree { IMPLEMENT_COLLISION_TREE(AABBQuantizedTree, AABBQuantizedNode) public: Point mCenterCoeff; Point mExtentsCoeff; }; class OPCODE_API AABBQuantizedNoLeafTree : public AABBOptimizedTree { IMPLEMENT_COLLISION_TREE(AABBQuantizedNoLeafTree, AABBQuantizedNoLeafNode) public: Point mCenterCoeff; Point mExtentsCoeff; }; #endif // __OPC_OPTIMIZEDTREE_H__ ode-0.16/OPCODE/OPC_Collider.cpp0000664000175200017520000000541513403272463013062 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* * OPCODE - Optimized Collision Detection * Copyright (C) 2001 Pierre Terdiman * Homepage: http://www.codercorner.com/Opcode.htm */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains base collider class. * \file OPC_Collider.cpp * \author Pierre Terdiman * \date June, 2, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains the abstract class for colliders. * * \class Collider * \author Pierre Terdiman * \version 1.3 * \date June, 2, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Precompiled Header #include "Stdafx.h" using namespace Opcode; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Constructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Collider::Collider() : mFlags (0), mCurrentModel (null), mIMesh (null) { } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Destructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Collider::~Collider() { } ode-0.16/OPCODE/OPC_Common.cpp0000664000175200017520000000525213403272463012554 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* * OPCODE - Optimized Collision Detection * Copyright (C) 2001 Pierre Terdiman * Homepage: http://www.codercorner.com/Opcode.htm */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains common classes & defs used in OPCODE. * \file OPC_Common.cpp * \author Pierre Terdiman * \date March, 20, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * An AABB dedicated to collision detection. * We don't use the generic AABB class included in ICE, since it can be a Min/Max or a Center/Extents one (depends * on compilation flags). Since the Center/Extents model is more efficient in collision detection, it was worth * using an extra special class. * * \class CollisionAABB * \author Pierre Terdiman * \version 1.3 * \date March, 20, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * A quantized AABB. * Center/Extent model, using 16-bits integers. * * \class QuantizedAABB * \author Pierre Terdiman * \version 1.3 * \date March, 20, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Precompiled Header #include "Stdafx.h" using namespace Opcode; ode-0.16/OPCODE/OPC_RayTriOverlap.h0000664000175200017520000000672313403272463013540 00000000000000#define LOCAL_EPSILON 0.000001f /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes a ray-triangle intersection test. * Original code from Tomas Möller's "Fast Minimum Storage Ray-Triangle Intersection". * It's been optimized a bit with integer code, and modified to return a non-intersection if distance from * ray origin to triangle is negative. * * \param vert0 [in] triangle vertex * \param vert1 [in] triangle vertex * \param vert2 [in] triangle vertex * \return true on overlap. mStabbedFace is filled with relevant info. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ BOOL RayCollider::RayTriOverlap(const Point& vert0, const Point& vert1, const Point& vert2) { // Stats mNbRayPrimTests++; // Find vectors for two edges sharing vert0 Point edge1 = vert1 - vert0; Point edge2 = vert2 - vert0; // Begin calculating determinant - also used to calculate U parameter Point pvec = mDir^edge2; // If determinant is near zero, ray lies in plane of triangle float det = edge1|pvec; if(mCulling) { if(det <= LOCAL_EPSILON * FCMin2(edge1.SquareMagnitude(), edge2.SquareMagnitude())) return FALSE; // From here, det is > 0. So we can use integer cmp. // Calculate distance from vert0 to ray origin Point tvec = mOrigin - vert0; // Calculate U parameter and test bounds mStabbedFace.mU = tvec|pvec; // if(IR(u)&0x80000000 || u>det) return FALSE; if(IS_NEGATIVE_FLOAT(mStabbedFace.mU) || IR(mStabbedFace.mU)>IR(det)) return FALSE; // Prepare to test V parameter Point qvec = tvec^edge1; // Calculate V parameter and test bounds mStabbedFace.mV = mDir|qvec; if(IS_NEGATIVE_FLOAT(mStabbedFace.mV) || mStabbedFace.mU+mStabbedFace.mV>det) return FALSE; // Calculate t, scale parameters, ray intersects triangle mStabbedFace.mDistance = edge2|qvec; // Det > 0 so we can early exit here // Intersection point is valid if distance is positive (else it can just be a face behind the orig point) if(IS_NEGATIVE_FLOAT(mStabbedFace.mDistance)) return FALSE; // Else go on float OneOverDet = 1.0f / det; mStabbedFace.mDistance *= OneOverDet; mStabbedFace.mU *= OneOverDet; mStabbedFace.mV *= OneOverDet; } else { // the non-culling branch if(FastFabs(det) <= LOCAL_EPSILON * FCMin2(edge1.SquareMagnitude(), edge2.SquareMagnitude())) return FALSE; float OneOverDet = 1.0f / det; // Calculate distance from vert0 to ray origin Point tvec = mOrigin - vert0; // Calculate U parameter and test bounds mStabbedFace.mU = (tvec|pvec) * OneOverDet; // if(IR(u)&0x80000000 || u>1.0f) return FALSE; if(IS_NEGATIVE_FLOAT(mStabbedFace.mU) || IR(mStabbedFace.mU)>IEEE_1_0) return FALSE; // prepare to test V parameter Point qvec = tvec^edge1; // Calculate V parameter and test bounds mStabbedFace.mV = (mDir|qvec) * OneOverDet; if(IS_NEGATIVE_FLOAT(mStabbedFace.mV) || mStabbedFace.mU+mStabbedFace.mV>1.0f) return FALSE; // Calculate t, ray intersects triangle mStabbedFace.mDistance = (edge2|qvec) * OneOverDet; // Intersection point is valid if distance is positive (else it can just be a face behind the orig point) if(IS_NEGATIVE_FLOAT(mStabbedFace.mDistance)) return FALSE; } return TRUE; } ode-0.16/OPCODE/OPC_AABBTree.cpp0000664000175200017520000005345313403272463012637 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* * OPCODE - Optimized Collision Detection * Copyright (C) 2001 Pierre Terdiman * Homepage: http://www.codercorner.com/Opcode.htm */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains code for a versatile AABB tree. * \file OPC_AABBTree.cpp * \author Pierre Terdiman * \date March, 20, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains a generic AABB tree node. * * \class AABBTreeNode * \author Pierre Terdiman * \version 1.3 * \date March, 20, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains a generic AABB tree. * This is a vanilla AABB tree, without any particular optimization. It contains anonymous references to * user-provided primitives, which can theoretically be anything - triangles, boxes, etc. Each primitive * is surrounded by an AABB, regardless of the primitive's nature. When the primitive is a triangle, the * resulting tree can be converted into an optimized tree. If the primitive is a box, the resulting tree * can be used for culling - VFC or occlusion -, assuming you cull on a mesh-by-mesh basis (modern way). * * \class AABBTree * \author Pierre Terdiman * \version 1.3 * \date March, 20, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Precompiled Header #include "Stdafx.h" using namespace Opcode; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Constructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// AABBTreeNode::AABBTreeNode() : mPos (null), #ifndef OPC_NO_NEG_VANILLA_TREE mNeg (null), #endif mNodePrimitives (null), mNbPrimitives (0) { #ifdef OPC_USE_TREE_COHERENCE mBitmask = 0; #endif } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Destructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// AABBTreeNode::~AABBTreeNode() { // Opcode 1.3: const AABBTreeNode* Pos = GetPos(); #ifndef OPC_NO_NEG_VANILLA_TREE const AABBTreeNode* Neg = GetNeg(); if(!(mPos&1)) DELETESINGLE(Pos); if(!(mNeg&1)) DELETESINGLE(Neg); #else if(!(mPos&1)) DELETEARRAY(Pos); #endif mNodePrimitives = null; // This was just a shortcut to the global list => no release mNbPrimitives = 0; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Splits the node along a given axis. * The list of indices is reorganized according to the split values. * \param axis [in] splitting axis index * \param builder [in] the tree builder * \return the number of primitives assigned to the first child * \warning this method reorganizes the internal list of primitives */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// udword AABBTreeNode::Split(udword axis, AABBTreeBuilder* builder) { // Get node split value float SplitValue = builder->GetSplittingValue(mNodePrimitives, mNbPrimitives, mBV, axis); udword NbPos = 0; // Loop through all node-related primitives. Their indices range from mNodePrimitives[0] to mNodePrimitives[mNbPrimitives-1]. // Those indices map the global list in the tree builder. for(udword i=0;iGetSplittingValue(Index, axis); // Reorganize the list of indices in this order: positive - negative. if(PrimitiveValue > SplitValue) { // Swap entries udword Tmp = mNodePrimitives[i]; mNodePrimitives[i] = mNodePrimitives[NbPos]; mNodePrimitives[NbPos] = Tmp; // Count primitives assigned to positive space NbPos++; } } return NbPos; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Subdivides the node. * * N * / \ * / \ * N/2 N/2 * / \ / \ * N/4 N/4 N/4 N/4 * (etc) * * A well-balanced tree should have a O(log n) depth. * A degenerate tree would have a O(n) depth. * Note a perfectly-balanced tree is not well-suited to collision detection anyway. * * \param builder [in] the tree builder * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool AABBTreeNode::Subdivide(AABBTreeBuilder* builder) { // Checkings if(!builder) return false; // Stop subdividing if we reach a leaf node. This is always performed here, // else we could end in trouble if user overrides this. if(mNbPrimitives==1) return true; // Let the user validate the subdivision if(!builder->ValidateSubdivision(mNodePrimitives, mNbPrimitives, mBV)) return true; bool ValidSplit = true; // Optimism... udword NbPos; if(builder->mSettings.mRules & SPLIT_LARGEST_AXIS) { // Find the largest axis to split along Point Extents; mBV.GetExtents(Extents); // Box extents udword Axis = Extents.LargestAxis(); // Index of largest axis // Split along the axis NbPos = Split(Axis, builder); // Check split validity if(!NbPos || NbPos==mNbPrimitives) ValidSplit = false; } else if(builder->mSettings.mRules & SPLIT_SPLATTER_POINTS) { // Compute the means Point Means(0.0f, 0.0f, 0.0f); for(udword i=0;iGetSplittingValues(Index); } Means/=float(mNbPrimitives); // Compute variances Point Vars(0.0f, 0.0f, 0.0f); for(udword i=0;iGetSplittingValues(Index); Point Delta = Center - Means; Vars += Delta * Delta; } Vars/=float(mNbPrimitives-1); // Choose axis with greatest variance udword Axis = Vars.LargestAxis(); // Split along the axis NbPos = Split(Axis, builder); // Check split validity if(!NbPos || NbPos==mNbPrimitives) ValidSplit = false; } else if(builder->mSettings.mRules & SPLIT_BALANCED) { // Test 3 axis, take the best float Results[3]; NbPos = Split(0, builder); Results[0] = float(NbPos)/float(mNbPrimitives); NbPos = Split(1, builder); Results[1] = float(NbPos)/float(mNbPrimitives); NbPos = Split(2, builder); Results[2] = float(NbPos)/float(mNbPrimitives); Results[0]-=0.5f; Results[0]*=Results[0]; Results[1]-=0.5f; Results[1]*=Results[1]; Results[2]-=0.5f; Results[2]*=Results[2]; udword Min=0; if(Results[1]mSettings.mRules & SPLIT_BEST_AXIS) { // Test largest, then middle, then smallest axis... // Sort axis Point Extents; mBV.GetExtents(Extents); // Box extents udword SortedAxis[] = { 0, 1, 2 }; float* Keys = (float*)&Extents.x; for(udword j=0;j<3;j++) { for(udword i=0;i<2;i++) { if(Keys[SortedAxis[i]]mSettings.mRules & SPLIT_FIFTY) { // Don't even bother splitting (mainly a performance test) NbPos = mNbPrimitives>>1; } else return false; // Unknown splitting rules // Check the subdivision has been successful if(!ValidSplit) { // Here, all boxes lie in the same sub-space. Two strategies: // - if the tree *must* be complete, make an arbitrary 50-50 split // - else stop subdividing // if(builder->mSettings.mRules&SPLIT_COMPLETE) if(builder->mSettings.mLimit==1) { builder->IncreaseNbInvalidSplits(); NbPos = mNbPrimitives>>1; } else return true; } // Now create children and assign their pointers. if(builder->mNodeBase) { // We use a pre-allocated linear pool for complete trees [Opcode 1.3] AABBTreeNode* Pool = (AABBTreeNode*)builder->mNodeBase; udword Count = builder->GetCount() - 1; // Count begins to 1... // Set last bit to tell it shouldn't be freed ### pretty ugly, find a better way. Maybe one bit in mNbPrimitives ASSERT(!(udword(&Pool[Count+0])&1)); ASSERT(!(udword(&Pool[Count+1])&1)); mPos = size_t(&Pool[Count+0])|1; #ifndef OPC_NO_NEG_VANILLA_TREE mNeg = size_t(&Pool[Count+1])|1; #endif } else { // Non-complete trees and/or Opcode 1.2 allocate nodes on-the-fly #ifndef OPC_NO_NEG_VANILLA_TREE mPos = (size_t)new AABBTreeNode; CHECKALLOC(mPos); mNeg = (size_t)new AABBTreeNode; CHECKALLOC(mNeg); #else AABBTreeNode* PosNeg = new AABBTreeNode[2]; CHECKALLOC(PosNeg); mPos = (size_t)PosNeg; #endif } // Update stats builder->IncreaseCount(2); // Assign children AABBTreeNode* Pos = const_cast(GetPos()); AABBTreeNode* Neg = const_cast(GetNeg()); Pos->mNodePrimitives = &mNodePrimitives[0]; Pos->mNbPrimitives = NbPos; Neg->mNodePrimitives = &mNodePrimitives[NbPos]; Neg->mNbPrimitives = mNbPrimitives - NbPos; return true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive hierarchy building in a top-down fashion. * \param builder [in] the tree builder */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void AABBTreeNode::_BuildHierarchy(AABBTreeBuilder* builder) { // 1) Compute the global box for current node. The box is stored in mBV. builder->ComputeGlobalBox(mNodePrimitives, mNbPrimitives, mBV); // 2) Subdivide current node Subdivide(builder); // 3) Recurse AABBTreeNode* Pos = const_cast(GetPos()); AABBTreeNode* Neg = const_cast(GetNeg()); if(Pos) Pos->_BuildHierarchy(builder); if(Neg) Neg->_BuildHierarchy(builder); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Refits the tree (top-down). * \param builder [in] the tree builder */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void AABBTreeNode::_Refit(AABBTreeBuilder* builder) { // 1) Recompute the new global box for current node builder->ComputeGlobalBox(mNodePrimitives, mNbPrimitives, mBV); // 2) Recurse AABBTreeNode* Pos = const_cast(GetPos()); AABBTreeNode* Neg = const_cast(GetNeg()); if(Pos) Pos->_Refit(builder); if(Neg) Neg->_Refit(builder); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Constructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// AABBTree::AABBTree() : mIndices(null), mPool(null), mTotalNbNodes(0) { } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Destructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// AABBTree::~AABBTree() { Release(); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Releases the tree. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void AABBTree::Release() { DELETEARRAY(mPool); DELETEARRAY(mIndices); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Builds a generic AABB tree from a tree builder. * \param builder [in] the tree builder * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool AABBTree::Build(AABBTreeBuilder* builder) { // Checkings if(!builder || !builder->mNbPrimitives) return false; // Release previous tree Release(); // Init stats builder->SetCount(1); builder->SetNbInvalidSplits(0); // Initialize indices. This list will be modified during build. mIndices = new dTriIndex[builder->mNbPrimitives]; CHECKALLOC(mIndices); // Identity permutation for(udword i=0;imNbPrimitives;i++) mIndices[i] = i; // Setup initial node. Here we have a complete permutation of the app's primitives. mNodePrimitives = mIndices; mNbPrimitives = builder->mNbPrimitives; // Use a linear array for complete trees (since we can predict the final number of nodes) [Opcode 1.3] // if(builder->mRules&SPLIT_COMPLETE) if(builder->mSettings.mLimit==1) { // Allocate a pool of nodes mPool = new AABBTreeNode[builder->mNbPrimitives*2 - 1]; builder->mNodeBase = mPool; // ### ugly ! } // Build the hierarchy _BuildHierarchy(builder); // Get back total number of nodes mTotalNbNodes = builder->GetCount(); // For complete trees, check the correct number of nodes has been created [Opcode 1.3] if(mPool) ASSERT(mTotalNbNodes==builder->mNbPrimitives*2 - 1); return true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the depth of the tree. * A well-balanced tree should have a log(n) depth. A degenerate tree O(n) depth. * \return depth of the tree */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// udword AABBTree::ComputeDepth() const { return Walk(null, null); // Use the walking code without callback } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Walks the tree, calling the user back for each node. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// udword AABBTree::Walk(WalkingCallback callback, void* user_data) const { // Call it without callback to compute max depth udword MaxDepth = 0; udword CurrentDepth = 0; struct Local { static void _Walk(const AABBTreeNode* current_node, udword& max_depth, udword& current_depth, WalkingCallback callback, void* user_data) { // Checkings if(!current_node) return; // Entering a new node => increase depth current_depth++; // Keep track of max depth if(current_depth>max_depth) max_depth = current_depth; // Callback if(callback && !(callback)(current_node, current_depth, user_data)) return; // Recurse if(current_node->GetPos()) { _Walk(current_node->GetPos(), max_depth, current_depth, callback, user_data); current_depth--; } if(current_node->GetNeg()) { _Walk(current_node->GetNeg(), max_depth, current_depth, callback, user_data); current_depth--; } } }; Local::_Walk(this, MaxDepth, CurrentDepth, callback, user_data); return MaxDepth; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Refits the tree in a top-down way. * \param builder [in] the tree builder */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool AABBTree::Refit(AABBTreeBuilder* builder) { if(!builder) return false; _Refit(builder); return true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Refits the tree in a bottom-up way. * \param builder [in] the tree builder */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool AABBTree::Refit2(AABBTreeBuilder* builder) { // Checkings if(!builder) return false; ASSERT(mPool); // Bottom-up update Point Min,Max; Point Min_,Max_; udword Index = mTotalNbNodes; while(Index--) { AABBTreeNode& Current = mPool[Index]; if(Current.IsLeaf()) { builder->ComputeGlobalBox(Current.GetPrimitives(), Current.GetNbPrimitives(), *const_cast(Current.GetAABB())); } else { Current.GetPos()->GetAABB()->GetMin(Min); Current.GetPos()->GetAABB()->GetMax(Max); Current.GetNeg()->GetAABB()->GetMin(Min_); Current.GetNeg()->GetAABB()->GetMax(Max_); Min.Min(Min_); Max.Max(Max_); const_cast(Current.GetAABB())->SetMinMax(Min, Max); } } return true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the number of bytes used by the tree. * \return number of bytes used */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// udword AABBTree::GetUsedBytes() const { udword TotalSize = mTotalNbNodes*GetNodeSize(); if(mIndices) TotalSize+=mNbPrimitives*sizeof(udword); return TotalSize; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Checks the tree is a complete tree or not. * A complete tree is made of 2*N-1 nodes, where N is the number of primitives in the tree. * \return true for complete trees */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool AABBTree::IsComplete() const { return (GetNbNodes()==GetNbPrimitives()*2-1); } ode-0.16/OPCODE/OPC_SphereAABBOverlap.h0000664000175200017520000000436413403272463014161 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Sphere-AABB overlap test, based on Jim Arvo's code. * \param center [in] box center * \param extents [in] box extents * \return TRUE on overlap */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ BOOL SphereCollider::SphereAABBOverlap(const Point& center, const Point& extents) { // Stats mNbVolumeBVTests++; float d = 0.0f; //find the square of the distance //from the sphere to the box #ifdef OLDIES for(udword i=0;i<3;i++) { float tmp = mCenter[i] - center[i]; float s = tmp + extents[i]; if(s<0.0f) d += s*s; else { s = tmp - extents[i]; if(s>0.0f) d += s*s; } } #endif //#ifdef NEW_TEST // float tmp = mCenter.x - center.x; // float s = tmp + extents.x; float tmp,s; tmp = mCenter.x - center.x; s = tmp + extents.x; if(s<0.0f) { d += s*s; if(d>mRadius2) return FALSE; } else { s = tmp - extents.x; if(s>0.0f) { d += s*s; if(d>mRadius2) return FALSE; } } tmp = mCenter.y - center.y; s = tmp + extents.y; if(s<0.0f) { d += s*s; if(d>mRadius2) return FALSE; } else { s = tmp - extents.y; if(s>0.0f) { d += s*s; if(d>mRadius2) return FALSE; } } tmp = mCenter.z - center.z; s = tmp + extents.z; if(s<0.0f) { d += s*s; if(d>mRadius2) return FALSE; } else { s = tmp - extents.z; if(s>0.0f) { d += s*s; if(d>mRadius2) return FALSE; } } //#endif #ifdef OLDIES // Point Min = center - extents; // Point Max = center + extents; float d = 0.0f; //find the square of the distance //from the sphere to the box for(udword i=0;i<3;i++) { float Min = center[i] - extents[i]; // if(mCenter[i]Max[i]) if(mCenter[i]>Max) { float s = mCenter[i] - Max; d += s*s; } } } #endif return d <= mRadius2; } ode-0.16/OPCODE/COPYING0000664000175200017520000000166513403272463011156 00000000000000The OPCODE library distributed as part of ODE is licensed under the same terms as ODE (LGPLv2.1+ and BSD). Quoting a public e-mail from the author: Re: TriMesh support and OPCODE added to ODE core Pierre Terdiman wanadoo.fr> 2003-07-01 21:18:44 GMT > If he wants > to explicitly make it clear that OpCode is good under ODE's > license, that would be A-1 Super... "Opcode is good under ODE's license" I didn't put a license to prevent boring questions about licenses, but it seems it's not enough - I still get as many questions, regarding missing license. The only thing that would NOT be good would be renaming it "TopCode", changing the author's name, selling it at a very expensive price, and still managing to make money out of it :) ...I should add a license explicitely against this :) Pierre Source: http://permalink.gmane.org/gmane.comp.lib.ode/3237 ode-0.16/OPCODE/OPC_IceHook.h0000664000175200017520000000347313403272463012315 00000000000000 // Should be included by Opcode.h if needed /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Include Guard #ifndef __OPC_ICEHOOK_H__ #define __OPC_ICEHOOK_H__ #define ICE_DONT_CHECK_COMPILER_OPTIONS // From Windows... typedef int BOOL; #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE 1 #endif #include #include #include #include #include #include #ifndef ASSERT #define ASSERT(exp) {} #endif #define ICE_COMPILE_TIME_ASSERT(exp) extern char ICE_Dummy[ (exp) ? 1 : -1 ] #define Log {} #define SetIceError(a,b) false #define EC_OUTOFMEMORY "Out of memory" extern void OPCODE_NORETURN IceAbort(); #include "Ice/IcePreprocessor.h" #undef ICECORE_API #define ICECORE_API OPCODE_API #include "Ice/IceTypes.h" #include "Ice/IceFPU.h" #include "Ice/IceMemoryMacros.h" namespace IceCore { #include "Ice/IceUtils.h" #include "Ice/IceContainer.h" #include "Ice/IcePairs.h" #include "Ice/IceRevisitedRadix.h" #include "Ice/IceRandom.h" } using namespace IceCore; #define ICEMATHS_API OPCODE_API namespace IceMaths { #include "Ice/IceAxes.h" #include "Ice/IcePoint.h" #include "Ice/IceHPoint.h" #include "Ice/IceMatrix3x3.h" #include "Ice/IceMatrix4x4.h" #include "Ice/IcePlane.h" #include "Ice/IceRay.h" #include "Ice/IceIndexedTriangle.h" #include "Ice/IceTriangle.h" #include "Ice/IceTriList.h" #include "Ice/IceAABB.h" #include "Ice/IceOBB.h" #include "Ice/IceBoundingSphere.h" #include "Ice/IceSegment.h" #include "Ice/IceLSS.h" } using namespace IceMaths; #endif // __OPC_ICEHOOK_H__ ode-0.16/OPCODE/OPC_TriTriOverlap.h0000664000175200017520000002205713403272463013541 00000000000000 //! if OPC_TRITRI_EPSILON_TEST is true then we do a check (if |dv|b) \ { \ const float c=a; \ a=b; \ b=c; \ } //! Edge to edge test based on Franlin Antonio's gem: "Faster Line Segment Intersection", in Graphics Gems III, pp. 199-202 #define EDGE_EDGE_TEST(V0, U0, U1) \ Bx = U0[i0] - U1[i0]; \ By = U0[i1] - U1[i1]; \ Cx = V0[i0] - U0[i0]; \ Cy = V0[i1] - U0[i1]; \ f = Ay*Bx - Ax*By; \ d = By*Cx - Bx*Cy; \ if((f>0.0f && d>=0.0f && d<=f) || (f<0.0f && d<=0.0f && d>=f)) \ { \ const float e=Ax*Cy - Ay*Cx; \ if(f>0.0f) \ { \ if(e>=0.0f && e<=f) return TRUE; \ } \ else \ { \ if(e<=0.0f && e>=f) return TRUE; \ } \ } //! TO BE DOCUMENTED #define EDGE_AGAINST_TRI_EDGES(V0, V1, U0, U1, U2) \ { \ float Bx,By,Cx,Cy,d,f; \ const float Ax = V1[i0] - V0[i0]; \ const float Ay = V1[i1] - V0[i1]; \ /* test edge U0,U1 against V0,V1 */ \ EDGE_EDGE_TEST(V0, U0, U1); \ /* test edge U1,U2 against V0,V1 */ \ EDGE_EDGE_TEST(V0, U1, U2); \ /* test edge U2,U1 against V0,V1 */ \ EDGE_EDGE_TEST(V0, U2, U0); \ } //! TO BE DOCUMENTED #define POINT_IN_TRI(V0, U0, U1, U2) \ { \ /* is T1 completly inside T2? */ \ /* check if V0 is inside tri(U0,U1,U2) */ \ float a = U1[i1] - U0[i1]; \ float b = -(U1[i0] - U0[i0]); \ float c = -a*U0[i0] - b*U0[i1]; \ float d0 = a*V0[i0] + b*V0[i1] + c; \ \ a = U2[i1] - U1[i1]; \ b = -(U2[i0] - U1[i0]); \ c = -a*U1[i0] - b*U1[i1]; \ const float d1 = a*V0[i0] + b*V0[i1] + c; \ \ a = U0[i1] - U2[i1]; \ b = -(U0[i0] - U2[i0]); \ c = -a*U2[i0] - b*U2[i1]; \ const float d2 = a*V0[i0] + b*V0[i1] + c; \ if(d0*d1>0.0f) \ { \ if(d0*d2>0.0f) return TRUE; \ } \ } //! TO BE DOCUMENTED BOOL CoplanarTriTri(const Point& n, const Point& v0, const Point& v1, const Point& v2, const Point& u0, const Point& u1, const Point& u2) { float A[3]; short i0,i1; /* first project onto an axis-aligned plane, that maximizes the area */ /* of the triangles, compute indices: i0,i1. */ A[0] = fabsf(n[0]); A[1] = fabsf(n[1]); A[2] = fabsf(n[2]); if(A[0]>A[1]) { if(A[0]>A[2]) { i0=1; /* A[0] is greatest */ i1=2; } else { i0=0; /* A[2] is greatest */ i1=1; } } else /* A[0]<=A[1] */ { if(A[2]>A[1]) { i0=0; /* A[2] is greatest */ i1=1; } else { i0=0; /* A[1] is greatest */ i1=2; } } /* test all edges of triangle 1 against the edges of triangle 2 */ EDGE_AGAINST_TRI_EDGES(v0, v1, u0, u1, u2); EDGE_AGAINST_TRI_EDGES(v1, v2, u0, u1, u2); EDGE_AGAINST_TRI_EDGES(v2, v0, u0, u1, u2); /* finally, test if tri1 is totally contained in tri2 or vice versa */ POINT_IN_TRI(v0, u0, u1, u2); POINT_IN_TRI(u0, v0, v1, v2); return FALSE; } //! TO BE DOCUMENTED #define NEWCOMPUTE_INTERVALS(VV0, VV1, VV2, D0, D1, D2, D0D1, D0D2, A, B, C, X0, X1) \ { \ if(D0D1>0.0f) \ { \ /* here we know that D0D2<=0.0 */ \ /* that is D0, D1 are on the same side, D2 on the other or on the plane */ \ A=VV2; B=(VV0 - VV2)*D2; C=(VV1 - VV2)*D2; X0=D2 - D0; X1=D2 - D1; \ } \ else if(D0D2>0.0f) \ { \ /* here we know that d0d1<=0.0 */ \ A=VV1; B=(VV0 - VV1)*D1; C=(VV2 - VV1)*D1; X0=D1 - D0; X1=D1 - D2; \ } \ else if(D1*D2>0.0f || D0!=0.0f) \ { \ /* here we know that d0d1<=0.0 or that D0!=0.0 */ \ A=VV0; B=(VV1 - VV0)*D0; C=(VV2 - VV0)*D0; X0=D0 - D1; X1=D0 - D2; \ } \ else if(D1!=0.0f) \ { \ A=VV1; B=(VV0 - VV1)*D1; C=(VV2 - VV1)*D1; X0=D1 - D0; X1=D1 - D2; \ } \ else if(D2!=0.0f) \ { \ A=VV2; B=(VV0 - VV2)*D2; C=(VV1 - VV2)*D2; X0=D2 - D0; X1=D2 - D1; \ } \ else \ { \ /* triangles are coplanar */ \ return CoplanarTriTri(N1, V0, V1, V2, U0, U1, U2); \ } \ } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Triangle/triangle intersection test routine, * by Tomas Moller, 1997. * See article "A Fast Triangle-Triangle Intersection Test", * Journal of Graphics Tools, 2(2), 1997 * * Updated June 1999: removed the divisions -- a little faster now! * Updated October 1999: added {} to CROSS and SUB macros * * int NoDivTriTriIsect(float V0[3],float V1[3],float V2[3], * float U0[3],float U1[3],float U2[3]) * * \param V0 [in] triangle 0, vertex 0 * \param V1 [in] triangle 0, vertex 1 * \param V2 [in] triangle 0, vertex 2 * \param U0 [in] triangle 1, vertex 0 * \param U1 [in] triangle 1, vertex 1 * \param U2 [in] triangle 1, vertex 2 * \return true if triangles overlap */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ BOOL AABBTreeCollider::TriTriOverlap(const Point& V0, const Point& V1, const Point& V2, const Point& U0, const Point& U1, const Point& U2) { // Stats mNbPrimPrimTests++; // Compute plane equation of triangle(V0,V1,V2) Point E1 = V1 - V0; Point E2 = V2 - V0; const Point N1 = E1 ^ E2; const float d1 =-N1 | V0; // Plane equation 1: N1.X+d1=0 // Put U0,U1,U2 into plane equation 1 to compute signed distances to the plane float du0 = (N1|U0) + d1; float du1 = (N1|U1) + d1; float du2 = (N1|U2) + d1; // Coplanarity robustness check #ifdef OPC_TRITRI_EPSILON_TEST float absd1 = FastFabs(d1), sqmagN1 = N1.SquareMagnitude(); if (absd1>=sqmagN1) { if(FastFabs(du0)<=LOCAL_EPSILON*absd1) du0 = 0.0f; if(FastFabs(du1)<=LOCAL_EPSILON*absd1) du1 = 0.0f; if(FastFabs(du2)<=LOCAL_EPSILON*absd1) du2 = 0.0f; } else { if(FastFabs(du0)<=LOCAL_EPSILON*FCMax2(absd1, FCMin2(sqmagN1, U0.SquareMagnitude()))) du0 = 0.0f; if(FastFabs(du1)<=LOCAL_EPSILON*FCMax2(absd1, FCMin2(sqmagN1, U1.SquareMagnitude()))) du1 = 0.0f; if(FastFabs(du2)<=LOCAL_EPSILON*FCMax2(absd1, FCMin2(sqmagN1, U2.SquareMagnitude()))) du2 = 0.0f; } #endif const float du0du1 = du0 * du1; const float du0du2 = du0 * du2; if(du0du1>0.0f && du0du2>0.0f) // same sign on all of them + not equal 0 ? return FALSE; // no intersection occurs // Compute plane of triangle (U0,U1,U2) E1 = U1 - U0; E2 = U2 - U0; const Point N2 = E1 ^ E2; const float d2=-N2 | U0; // plane equation 2: N2.X+d2=0 // put V0,V1,V2 into plane equation 2 float dv0 = (N2|V0) + d2; float dv1 = (N2|V1) + d2; float dv2 = (N2|V2) + d2; #ifdef OPC_TRITRI_EPSILON_TEST float absd2 = FastFabs(d2), sqmagN2 = N2.SquareMagnitude(); if (absd2>=sqmagN2) { if(FastFabs(dv0)<=LOCAL_EPSILON*absd2) dv0 = 0.0f; if(FastFabs(dv1)<=LOCAL_EPSILON*absd2) dv1 = 0.0f; if(FastFabs(dv2)<=LOCAL_EPSILON*absd2) dv2 = 0.0f; } else { if(FastFabs(dv0)<=LOCAL_EPSILON*FCMax2(absd2, FCMin2(sqmagN2, V0.SquareMagnitude()))) dv0 = 0.0f; if(FastFabs(dv1)<=LOCAL_EPSILON*FCMax2(absd2, FCMin2(sqmagN2, V1.SquareMagnitude()))) dv1 = 0.0f; if(FastFabs(dv2)<=LOCAL_EPSILON*FCMax2(absd2, FCMin2(sqmagN2, V2.SquareMagnitude()))) dv2 = 0.0f; } #endif const float dv0dv1 = dv0 * dv1; const float dv0dv2 = dv0 * dv2; if(dv0dv1>0.0f && dv0dv2>0.0f) // same sign on all of them + not equal 0 ? return FALSE; // no intersection occurs // Compute direction of intersection line const Point D = N1^N2; // Compute and index to the largest component of D float max=fabsf(D[0]); short index=0; float bb=fabsf(D[1]); float cc=fabsf(D[2]); if(bb>max) max=bb,index=1; if(cc>max) max=cc,index=2; // This is the simplified projection onto L const float vp0 = V0[index]; const float vp1 = V1[index]; const float vp2 = V2[index]; const float up0 = U0[index]; const float up1 = U1[index]; const float up2 = U2[index]; // Compute interval for triangle 1 float a,b,c,x0,x1; NEWCOMPUTE_INTERVALS(vp0,vp1,vp2,dv0,dv1,dv2,dv0dv1,dv0dv2,a,b,c,x0,x1); // Compute interval for triangle 2 float d,e,f,y0,y1; NEWCOMPUTE_INTERVALS(up0,up1,up2,du0,du1,du2,du0du1,du0du2,d,e,f,y0,y1); const float xx=x0*x1; const float yy=y0*y1; const float xxyy=xx*yy; float isect1[2], isect2[2]; float tmp=a*xxyy; isect1[0]=tmp+b*x1*yy; isect1[1]=tmp+c*x0*yy; tmp=d*xxyy; isect2[0]=tmp+e*xx*y1; isect2[1]=tmp+f*xx*y0; SORT(isect1[0],isect1[1]); SORT(isect2[0],isect2[1]); if(isect1[1]>4; } inline_ void SetData(udword nb, udword index) { ASSERT(nb>0 && nb<=16); nb--; Data = (index<<4)|(nb&15); } }; class OPCODE_API HybridModel : public BaseModel { public: // Constructor/Destructor HybridModel(); virtual ~HybridModel(); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Builds a collision model. * \param create [in] model creation structure * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// override(BaseModel) bool Build(const OPCODECREATE& create); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Gets the number of bytes used by the tree. * \return amount of bytes used */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// override(BaseModel) udword GetUsedBytes() const; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Refits the collision model. This can be used to handle dynamic meshes. Usage is: * 1. modify your mesh vertices (keep the topology constant!) * 2. refit the tree (call this method) * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// override(BaseModel) bool Refit(); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Gets array of triangles. * \return array of triangles */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ const LeafTriangles* GetLeafTriangles() const { return mTriangles; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Gets array of indices. * \return array of indices */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ const udword* GetIndices() const { return mIndices; } private: udword mNbLeaves; //!< Number of leaf nodes in the model LeafTriangles* mTriangles; //!< Array of mNbLeaves leaf descriptors udword mNbPrimitives; //!< Number of primitives in the model udword* mIndices; //!< Array of primitive indices // Internal methods void Release(); }; #endif // __OPC_HYBRIDMODEL_H__ ode-0.16/OPCODE/Opcode.cpp0000664000175200017520000000444413403272463012036 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* * OPCODE - Optimized Collision Detection * Copyright (C) 2001 Pierre Terdiman * Homepage: http://www.codercorner.com/Opcode.htm */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Main file for Opcode.dll. * \file Opcode.cpp * \author Pierre Terdiman * \date March, 20, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* Finding a good name is difficult! Here's the draft for this lib.... Spooky, uh? VOID? Very Optimized Interference Detection ZOID? Zappy's Optimized Interference Detection CID? Custom/Clever Interference Detection AID / ACID! Accurate Interference Detection QUID? Quick Interference Detection RIDE? Realtime Interference DEtection WIDE? Wicked Interference DEtection (....) GUID! KID ! k-dop interference detection :) OPCODE! OPtimized COllision DEtection */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Precompiled Header #include "Stdafx.h" using namespace Opcode; static OPCODE_AbortHandler g_fnAbortHandler = NULL; bool Opcode::InitOpcode(OPCODE_AbortHandler fnAbortHandler/*=NULL*/) { //Log("// Initializing OPCODE\n\n"); // LogAPIInfo(); g_fnAbortHandler = fnAbortHandler; return true; } bool Opcode::CloseOpcode() { //Log("// Closing OPCODE\n\n"); return true; } #ifdef ICE_MAIN void ModuleAttach(HINSTANCE hinstance) { } void ModuleDetach() { } #endif /*extern */ void OPCODE_NORETURN IceAbort() { if (g_fnAbortHandler != NULL) { g_fnAbortHandler(); } abort(); } ode-0.16/OPCODE/OPC_PlanesCollider.cpp0000664000175200017520000006277213403272463014236 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* * OPCODE - Optimized Collision Detection * Copyright (C) 2001 Pierre Terdiman * Homepage: http://www.codercorner.com/Opcode.htm */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains code for a planes collider. * \file OPC_PlanesCollider.cpp * \author Pierre Terdiman * \date January, 1st, 2002 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains a Planes-vs-tree collider. * * \class PlanesCollider * \author Pierre Terdiman * \version 1.3 * \date January, 1st, 2002 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Precompiled Header #include "Stdafx.h" using namespace Opcode; #include "OPC_PlanesAABBOverlap.h" #include "OPC_PlanesTriOverlap.h" #define SET_CONTACT(prim_index, flag) \ /* Set contact status */ \ mFlags |= flag; \ mTouchedPrimitives->Add(udword(prim_index)); //! Planes-triangle test #define PLANES_PRIM(prim_index, flag) \ /* Request vertices from the app */ \ mIMesh->GetTriangle(mVP, prim_index, mVC); \ /* Perform triangle-box overlap test */ \ if(PlanesTriOverlap(clip_mask)) \ { \ SET_CONTACT(prim_index, flag) \ } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Constructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// PlanesCollider::PlanesCollider() : mNbPlanes (0), mPlanes (null) { } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Destructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// PlanesCollider::~PlanesCollider() { DELETEARRAY(mPlanes); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Validates current settings. You should call this method after all the settings and callbacks have been defined. * \return null if everything is ok, else a string describing the problem */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// const char* PlanesCollider::ValidateSettings() { if(TemporalCoherenceEnabled() && !FirstContactEnabled()) return "Temporal coherence only works with ""First contact"" mode!"; return VolumeCollider::ValidateSettings(); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Generic collision query for generic OPCODE models. After the call, access the results: * - with GetContactStatus() * - with GetNbTouchedPrimitives() * - with GetTouchedPrimitives() * * \param cache [in/out] a planes cache * \param planes [in] list of planes in world space * \param nb_planes [in] number of planes * \param model [in] Opcode model to collide with * \param worldm [in] model's world matrix, or null * \return true if success * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool PlanesCollider::Collide(PlanesCache& cache, const Plane* planes, udword nb_planes, const Model& model, const Matrix4x4* worldm) { // Checkings if(!Setup(&model)) return false; // Init collision query if(InitQuery(cache, planes, nb_planes, worldm)) return true; udword PlaneMask = (1<(model.GetTree()); // Setup dequantization coeffs mCenterCoeff = Tree->mCenterCoeff; mExtentsCoeff = Tree->mExtentsCoeff; // Perform collision query if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); else _Collide(Tree->GetNodes(), PlaneMask); } else { const AABBNoLeafTree* Tree = static_cast(model.GetTree()); // Perform collision query if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); else _Collide(Tree->GetNodes(), PlaneMask); } } else { if(model.IsQuantized()) { const AABBQuantizedTree* Tree = static_cast(model.GetTree()); // Setup dequantization coeffs mCenterCoeff = Tree->mCenterCoeff; mExtentsCoeff = Tree->mExtentsCoeff; // Perform collision query if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); else _Collide(Tree->GetNodes(), PlaneMask); } else { const AABBCollisionTree* Tree = static_cast(model.GetTree()); // Perform collision query if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); else _Collide(Tree->GetNodes(), PlaneMask); } } return true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Initializes a collision query : * - reset stats & contact status * - compute planes in model space * - check temporal coherence * * \param cache [in/out] a planes cache * \param planes [in] list of planes * \param nb_planes [in] number of planes * \param worldm [in] model's world matrix, or null * \return TRUE if we can return immediately * \warning SCALE NOT SUPPORTED. The matrix must contain rotation & translation parts only. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// BOOL PlanesCollider::InitQuery(PlanesCache& cache, const Plane* planes, udword nb_planes, const Matrix4x4* worldm) { // 1) Call the base method VolumeCollider::InitQuery(); // 2) Compute planes in model space if(nb_planes>mNbPlanes) { DELETEARRAY(mPlanes); mPlanes = new Plane[nb_planes]; } mNbPlanes = nb_planes; if(worldm) { Matrix4x4 InvWorldM; InvertPRMatrix(InvWorldM, *worldm); // for(udword i=0;iHasSingleNode()) { if(!SkipPrimitiveTests()) { // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0. mTouchedPrimitives->Reset(); // Perform overlap test between the unique triangle and the planes (and set contact status if needed) udword clip_mask = (1< check results from previous frame before performing the collision query if(FirstContactEnabled()) { // We're only interested in the first contact found => test the unique previously touched face if(mTouchedPrimitives->GetNbEntries()) { // Get index of previously touched face = the first entry in the array udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0); // Then reset the array: // - if the overlap test below is successful, the index we'll get added back anyway // - if it isn't, then the array should be reset anyway for the normal query mTouchedPrimitives->Reset(); // Perform overlap test between the cached triangle and the planes (and set contact status if needed) udword clip_mask = (1< we'll have to perform a normal query } else mTouchedPrimitives->Reset(); } else { // Here we don't use temporal coherence => do a normal query mTouchedPrimitives->Reset(); } return FALSE; } #define TEST_CLIP_MASK \ /* If the box is completely included, so are its children. We don't need to do extra tests, we */ \ /* can immediately output a list of visible children. Those ones won't need to be clipped. */ \ if(!OutClipMask) \ { \ /* Set contact status */ \ mFlags |= OPC_CONTACT; \ _Dump(node); \ return; \ } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for normal AABB trees. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void PlanesCollider::_Collide(const AABBCollisionNode* node, udword clip_mask) { // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. udword OutClipMask; if(!PlanesAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents, OutClipMask, clip_mask)) return; TEST_CLIP_MASK // Else the box straddles one or several planes, so we need to recurse down the tree. if(node->IsLeaf()) { PLANES_PRIM(node->GetPrimitive(), OPC_CONTACT) } else { _Collide(node->GetPos(), OutClipMask); if(ContactFound()) return; _Collide(node->GetNeg(), OutClipMask); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for normal AABB trees. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void PlanesCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node, udword clip_mask) { // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. udword OutClipMask; if(!PlanesAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents, OutClipMask, clip_mask)) return; TEST_CLIP_MASK // Else the box straddles one or several planes, so we need to recurse down the tree. if(node->IsLeaf()) { SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) } else { _CollideNoPrimitiveTest(node->GetPos(), OutClipMask); if(ContactFound()) return; _CollideNoPrimitiveTest(node->GetNeg(), OutClipMask); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for quantized AABB trees. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void PlanesCollider::_Collide(const AABBQuantizedNode* node, udword clip_mask) { // Dequantize box const QuantizedAABB& Box = node->mAABB; const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. udword OutClipMask; if(!PlanesAABBOverlap(Center, Extents, OutClipMask, clip_mask)) return; TEST_CLIP_MASK // Else the box straddles one or several planes, so we need to recurse down the tree. if(node->IsLeaf()) { PLANES_PRIM(node->GetPrimitive(), OPC_CONTACT) } else { _Collide(node->GetPos(), OutClipMask); if(ContactFound()) return; _Collide(node->GetNeg(), OutClipMask); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for quantized AABB trees. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void PlanesCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node, udword clip_mask) { // Dequantize box const QuantizedAABB& Box = node->mAABB; const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. udword OutClipMask; if(!PlanesAABBOverlap(Center, Extents, OutClipMask, clip_mask)) return; TEST_CLIP_MASK // Else the box straddles one or several planes, so we need to recurse down the tree. if(node->IsLeaf()) { SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) } else { _CollideNoPrimitiveTest(node->GetPos(), OutClipMask); if(ContactFound()) return; _CollideNoPrimitiveTest(node->GetNeg(), OutClipMask); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for no-leaf AABB trees. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void PlanesCollider::_Collide(const AABBNoLeafNode* node, udword clip_mask) { // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. udword OutClipMask; if(!PlanesAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents, OutClipMask, clip_mask)) return; TEST_CLIP_MASK // Else the box straddles one or several planes, so we need to recurse down the tree. if(node->HasPosLeaf()) { PLANES_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } else _Collide(node->GetPos(), OutClipMask); if(ContactFound()) return; if(node->HasNegLeaf()) { PLANES_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } else _Collide(node->GetNeg(), OutClipMask); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for no-leaf AABB trees. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void PlanesCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node, udword clip_mask) { // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. udword OutClipMask; if(!PlanesAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents, OutClipMask, clip_mask)) return; TEST_CLIP_MASK // Else the box straddles one or several planes, so we need to recurse down the tree. if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } else _CollideNoPrimitiveTest(node->GetPos(), OutClipMask); if(ContactFound()) return; if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } else _CollideNoPrimitiveTest(node->GetNeg(), OutClipMask); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for quantized no-leaf AABB trees. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void PlanesCollider::_Collide(const AABBQuantizedNoLeafNode* node, udword clip_mask) { // Dequantize box const QuantizedAABB& Box = node->mAABB; const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. udword OutClipMask; if(!PlanesAABBOverlap(Center, Extents, OutClipMask, clip_mask)) return; TEST_CLIP_MASK // Else the box straddles one or several planes, so we need to recurse down the tree. if(node->HasPosLeaf()) { PLANES_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } else _Collide(node->GetPos(), OutClipMask); if(ContactFound()) return; if(node->HasNegLeaf()) { PLANES_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } else _Collide(node->GetNeg(), OutClipMask); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for quantized no-leaf AABB trees. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void PlanesCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node, udword clip_mask) { // Dequantize box const QuantizedAABB& Box = node->mAABB; const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. udword OutClipMask; if(!PlanesAABBOverlap(Center, Extents, OutClipMask, clip_mask)) return; TEST_CLIP_MASK // Else the box straddles one or several planes, so we need to recurse down the tree. if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } else _CollideNoPrimitiveTest(node->GetPos(), OutClipMask); if(ContactFound()) return; if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } else _CollideNoPrimitiveTest(node->GetNeg(), OutClipMask); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Constructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// HybridPlanesCollider::HybridPlanesCollider() { } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Destructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// HybridPlanesCollider::~HybridPlanesCollider() { } bool HybridPlanesCollider::Collide(PlanesCache& cache, const Plane* planes, udword nb_planes, const HybridModel& model, const Matrix4x4* worldm) { // We don't want primitive tests here! mFlags |= OPC_NO_PRIMITIVE_TESTS; // Checkings if(!Setup(&model)) return false; // Init collision query if(InitQuery(cache, planes, nb_planes, worldm)) return true; // Special case for 1-leaf trees if(mCurrentModel && mCurrentModel->HasSingleNode()) { // Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles udword Nb = mIMesh->GetNbTriangles(); // Loop through all triangles udword clip_mask = (1<(model.GetTree()); // Setup dequantization coeffs mCenterCoeff = Tree->mCenterCoeff; mExtentsCoeff = Tree->mExtentsCoeff; // Perform collision query - we don't want primitive tests here! _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); } else { const AABBNoLeafTree* Tree = static_cast(model.GetTree()); // Perform collision query - we don't want primitive tests here! _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); } } else { if(model.IsQuantized()) { const AABBQuantizedTree* Tree = static_cast(model.GetTree()); // Setup dequantization coeffs mCenterCoeff = Tree->mCenterCoeff; mExtentsCoeff = Tree->mExtentsCoeff; // Perform collision query - we don't want primitive tests here! _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); } else { const AABBCollisionTree* Tree = static_cast(model.GetTree()); // Perform collision query - we don't want primitive tests here! _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); } } // We only have a list of boxes so far if(GetContactStatus()) { // Reset contact status, since it currently only reflects collisions with leaf boxes Collider::InitQuery(); // Change dest container so that we can use built-in overlap tests and get collided primitives cache.TouchedPrimitives.Reset(); mTouchedPrimitives = &cache.TouchedPrimitives; // Read touched leaf boxes udword Nb = mTouchedBoxes.GetNbEntries(); const udword* Touched = mTouchedBoxes.GetEntries(); const LeafTriangles* LT = model.GetLeafTriangles(); const udword* Indices = model.GetIndices(); // Loop through touched leaves udword clip_mask = (1<>2; } inline_ const CollisionFace* GetFaces() const { return (const CollisionFace*)GetEntries(); } inline_ void Reset() { Container::Reset(); } inline_ void AddFace(const CollisionFace& face) { Add(face.mFaceID).Add(face.mDistance).Add(face.mU).Add(face.mV); } }; #ifdef OPC_RAYHIT_CALLBACK /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * User-callback, called by OPCODE to record a hit. * \param hit [in] current hit * \param user_data [in] user-defined data from SetCallback() */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// typedef void (*HitCallback) (const CollisionFace& hit, void* user_data); #endif class OPCODE_API RayCollider : public Collider { public: // Constructor / Destructor RayCollider(); virtual ~RayCollider(); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Generic stabbing query for generic OPCODE models. After the call, access the results: * - with GetContactStatus() * - in the user-provided destination array * * \param world_ray [in] stabbing ray in world space * \param model [in] Opcode model to collide with * \param world [in] model's world matrix, or null * \param cache [in] a possibly cached face index, or null * \return true if success * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool Collide(const Ray& world_ray, const Model& model, const Matrix4x4* world=null, udword* cache=null); // bool Collide(const Ray& world_ray, const AABBTree* tree, Container& box_indices); // Settings #ifndef OPC_RAYHIT_CALLBACK /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Settings: enable or disable "closest hit" mode. * \param flag [in] true to report closest hit only * \see SetCulling(bool flag) * \see SetMaxDist(float max_dist) * \see SetDestination(StabbedFaces* sf) */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ void SetClosestHit(bool flag) { mClosestHit = flag; } #endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Settings: enable or disable backface culling. * \param flag [in] true to enable backface culling * \see SetClosestHit(bool flag) * \see SetMaxDist(float max_dist) * \see SetDestination(StabbedFaces* sf) */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ void SetCulling(bool flag) { mCulling = flag; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Settings: sets the higher distance bound. * \param max_dist [in] higher distance bound. Default = maximal value, for ray queries (else segment) * \see SetClosestHit(bool flag) * \see SetCulling(bool flag) * \see SetDestination(StabbedFaces* sf) */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ void SetMaxDist(float max_dist=MAX_FLOAT) { mMaxDist = max_dist; } #ifdef OPC_RAYHIT_CALLBACK inline_ void SetHitCallback(HitCallback cb) { mHitCallback = cb; } inline_ void SetUserData(void* user_data) { mUserData = user_data; } #else /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Settings: sets the destination array for stabbed faces. * \param cf [in] destination array, filled during queries * \see SetClosestHit(bool flag) * \see SetCulling(bool flag) * \see SetMaxDist(float max_dist) */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ void SetDestination(CollisionFaces* cf) { mStabbedFaces = cf; } #endif // Stats /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Stats: gets the number of Ray-BV overlap tests after a collision query. * \see GetNbRayPrimTests() * \see GetNbIntersections() * \return the number of Ray-BV tests performed during last query */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ udword GetNbRayBVTests() const { return mNbRayBVTests; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Stats: gets the number of Ray-Triangle overlap tests after a collision query. * \see GetNbRayBVTests() * \see GetNbIntersections() * \return the number of Ray-Triangle tests performed during last query */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ udword GetNbRayPrimTests() const { return mNbRayPrimTests; } // In-out test /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Stats: gets the number of intersection found after a collision query. Can be used for in/out tests. * \see GetNbRayBVTests() * \see GetNbRayPrimTests() * \return the number of valid intersections during last query */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ udword GetNbIntersections() const { return mNbIntersections; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Validates current settings. You should call this method after all the settings and callbacks have been defined for a collider. * \return null if everything is ok, else a string describing the problem */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// override(Collider) const char* ValidateSettings(); protected: // Ray in local space Point mOrigin; //!< Ray origin Point mDir; //!< Ray direction (normalized) Point mFDir; //!< fabsf(mDir) Point mData, mData2; // Stabbed faces CollisionFace mStabbedFace; //!< Current stabbed face #ifdef OPC_RAYHIT_CALLBACK HitCallback mHitCallback; //!< Callback used to record a hit void* mUserData; //!< User-defined data #else CollisionFaces* mStabbedFaces; //!< List of stabbed faces bool mClosestHit; //!< Report closest hit only #endif // Stats udword mNbRayBVTests; //!< Number of Ray-BV tests udword mNbRayPrimTests; //!< Number of Ray-Primitive tests // In-out test udword mNbIntersections; //!< Number of valid intersections // Dequantization coeffs Point mCenterCoeff; Point mExtentsCoeff; // Settings float mMaxDist; //!< Valid segment on the ray bool mCulling; //!< Stab culled faces or not // Internal methods void _SegmentStab(const AABBCollisionNode* node); void _SegmentStab(const AABBNoLeafNode* node); void _SegmentStab(const AABBQuantizedNode* node); void _SegmentStab(const AABBQuantizedNoLeafNode* node); void _SegmentStab(const AABBTreeNode* node, Container& box_indices); void _RayStab(const AABBCollisionNode* node); void _RayStab(const AABBNoLeafNode* node); void _RayStab(const AABBQuantizedNode* node); void _RayStab(const AABBQuantizedNoLeafNode* node); void _RayStab(const AABBTreeNode* node, Container& box_indices); // Overlap tests inline_ BOOL RayAABBOverlap(const Point& center, const Point& extents); inline_ BOOL SegmentAABBOverlap(const Point& center, const Point& extents); inline_ BOOL RayTriOverlap(const Point& vert0, const Point& vert1, const Point& vert2); // Init methods BOOL InitQuery(const Ray& world_ray, const Matrix4x4* world=null, udword* face_id=null); }; #endif // __OPC_RAYCOLLIDER_H__ ode-0.16/OPCODE/Makefile.in0000664000175200017520000006473113403272663012175 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = OPCODE ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/ode/src/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libOPCODE_la_LIBADD = am_libOPCODE_la_OBJECTS = OPC_AABBCollider.lo OPC_AABBTree.lo \ OPC_BaseModel.lo OPC_Collider.lo OPC_Common.lo \ OPC_HybridModel.lo OPC_LSSCollider.lo OPC_MeshInterface.lo \ OPC_Model.lo OPC_OBBCollider.lo Opcode.lo OPC_OptimizedTree.lo \ OPC_Picking.lo OPC_PlanesCollider.lo OPC_RayCollider.lo \ OPC_SphereCollider.lo OPC_TreeBuilders.lo OPC_TreeCollider.lo \ OPC_VolumeCollider.lo libOPCODE_la_OBJECTS = $(am_libOPCODE_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/ode/src depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) AM_V_CXX = $(am__v_CXX_@AM_V@) am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libOPCODE_la_SOURCES) DIST_SOURCES = $(libOPCODE_la_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp COPYING DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CCD_CFLAGS = @CCD_CFLAGS@ CCD_LIBS = @CCD_LIBS@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXTRA_LIBTOOL_LDFLAGS = @EXTRA_LIBTOOL_LDFLAGS@ FGREP = @FGREP@ GL_LIBS = @GL_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSTDCXX = @LIBSTDCXX@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ ODE_PRECISION = @ODE_PRECISION@ ODE_VERSION = @ODE_VERSION@ ODE_VERSION_INFO = @ODE_VERSION_INFO@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ WINDRES = @WINDRES@ X11_CFLAGS = @X11_CFLAGS@ X11_LIBS = @X11_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_WINDRES = @ac_ct_WINDRES@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = COPYING \ ReadMe.txt \ README-ODE.txt \ TemporalCoherence.txt SUBDIRS = Ice noinst_LTLIBRARIES = libOPCODE.la AM_CPPFLAGS = -I$(top_srcdir)/include \ -I$(top_builddir)/include libOPCODE_la_SOURCES = OPC_AABBCollider.cpp OPC_AABBCollider.h \ OPC_AABBTree.cpp OPC_AABBTree.h \ OPC_BaseModel.cpp OPC_BaseModel.h \ OPC_Collider.cpp OPC_Collider.h \ OPC_Common.cpp OPC_Common.h \ OPC_HybridModel.cpp OPC_HybridModel.h \ OPC_LSSCollider.cpp OPC_LSSCollider.h \ OPC_MeshInterface.cpp OPC_MeshInterface.h \ OPC_Model.cpp OPC_Model.h \ OPC_OBBCollider.cpp OPC_OBBCollider.h \ Opcode.cpp Opcode.h \ OPC_OptimizedTree.cpp OPC_OptimizedTree.h \ OPC_Picking.cpp OPC_Picking.h \ OPC_PlanesCollider.cpp OPC_PlanesCollider.h \ OPC_RayCollider.cpp OPC_RayCollider.h \ OPC_SphereCollider.cpp OPC_SphereCollider.h \ OPC_TreeBuilders.cpp OPC_TreeBuilders.h \ OPC_TreeCollider.cpp OPC_TreeCollider.h \ OPC_VolumeCollider.cpp OPC_VolumeCollider.h \ OPC_Settings.h \ OPC_SphereAABBOverlap.h \ OPC_BoxBoxOverlap.h \ OPC_SphereTriOverlap.h \ OPC_PlanesAABBOverlap.h \ OPC_TriBoxOverlap.h \ OPC_IceHook.h \ OPC_PlanesTriOverlap.h \ OPC_TriTriOverlap.h \ OPC_LSSAABBOverlap.h \ OPC_RayAABBOverlap.h \ Stdafx.h \ OPC_LSSTriOverlap.h \ OPC_RayTriOverlap.h all: all-recursive .SUFFIXES: .SUFFIXES: .cpp .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign OPCODE/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign OPCODE/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libOPCODE.la: $(libOPCODE_la_OBJECTS) $(libOPCODE_la_DEPENDENCIES) $(EXTRA_libOPCODE_la_DEPENDENCIES) $(AM_V_CXXLD)$(CXXLINK) $(libOPCODE_la_OBJECTS) $(libOPCODE_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/OPC_AABBCollider.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/OPC_AABBTree.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/OPC_BaseModel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/OPC_Collider.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/OPC_Common.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/OPC_HybridModel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/OPC_LSSCollider.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/OPC_MeshInterface.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/OPC_Model.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/OPC_OBBCollider.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/OPC_OptimizedTree.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/OPC_Picking.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/OPC_PlanesCollider.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/OPC_RayCollider.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/OPC_SphereCollider.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/OPC_TreeBuilders.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/OPC_TreeCollider.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/OPC_VolumeCollider.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Opcode.Plo@am__quote@ .cpp.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cpp.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cpp.lo: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile $(LTLIBRARIES) installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool \ clean-noinstLTLIBRARIES cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ode-0.16/OPCODE/OPC_SphereCollider.h0000664000175200017520000001130113403272463013665 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* * OPCODE - Optimized Collision Detection * Copyright (C) 2001 Pierre Terdiman * Homepage: http://www.codercorner.com/Opcode.htm */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains code for a sphere collider. * \file OPC_SphereCollider.h * \author Pierre Terdiman * \date June, 2, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Include Guard #ifndef __OPC_SPHERECOLLIDER_H__ #define __OPC_SPHERECOLLIDER_H__ struct OPCODE_API SphereCache : VolumeCache { SphereCache() : Center(0.0f,0.0f,0.0f), FatRadius2(0.0f), FatCoeff(1.1f) {} ~SphereCache() {} // Cached faces signature Point Center; //!< Sphere used when performing the query resulting in cached faces float FatRadius2; //!< Sphere used when performing the query resulting in cached faces // User settings float FatCoeff; //!< mRadius2 multiplier used to create a fat sphere }; class OPCODE_API SphereCollider : public VolumeCollider { public: // Constructor / Destructor SphereCollider(); virtual ~SphereCollider(); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Generic collision query for generic OPCODE models. After the call, access the results: * - with GetContactStatus() * - with GetNbTouchedPrimitives() * - with GetTouchedPrimitives() * * \param cache [in/out] a sphere cache * \param sphere [in] collision sphere in local space * \param model [in] Opcode model to collide with * \param worlds [in] sphere's world matrix, or null * \param worldm [in] model's world matrix, or null * \return true if success * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool Collide(SphereCache& cache, const Sphere& sphere, const Model& model, const Matrix4x4* worlds=null, const Matrix4x4* worldm=null); // bool Collide(SphereCache& cache, const Sphere& sphere, const AABBTree* tree); protected: // Sphere in model space Point mCenter; //!< Sphere center float mRadius2; //!< Sphere radius squared // Internal methods void _Collide(const AABBCollisionNode* node); void _Collide(const AABBNoLeafNode* node); void _Collide(const AABBQuantizedNode* node); void _Collide(const AABBQuantizedNoLeafNode* node); void _Collide(const AABBTreeNode* node); void _CollideNoPrimitiveTest(const AABBCollisionNode* node); void _CollideNoPrimitiveTest(const AABBNoLeafNode* node); void _CollideNoPrimitiveTest(const AABBQuantizedNode* node); void _CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node); // Overlap tests inline_ BOOL SphereContainsBox(const Point& bc, const Point& be); inline_ BOOL SphereAABBOverlap(const Point& center, const Point& extents); BOOL SphereTriOverlap(const Point& vert0, const Point& vert1, const Point& vert2); // Init methods BOOL InitQuery(SphereCache& cache, const Sphere& sphere, const Matrix4x4* worlds=null, const Matrix4x4* worldm=null); }; class OPCODE_API HybridSphereCollider : public SphereCollider { public: // Constructor / Destructor HybridSphereCollider(); virtual ~HybridSphereCollider(); bool Collide(SphereCache& cache, const Sphere& sphere, const HybridModel& model, const Matrix4x4* worlds=null, const Matrix4x4* worldm=null); protected: Container mTouchedBoxes; }; #endif // __OPC_SPHERECOLLIDER_H__ ode-0.16/OPCODE/OPC_TreeBuilders.cpp0000664000175200017520000003405713403272463013722 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* * OPCODE - Optimized Collision Detection * Copyright (C) 2001 Pierre Terdiman * Homepage: http://www.codercorner.com/Opcode.htm */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains code for tree builders. * \file OPC_TreeBuilders.cpp * \author Pierre Terdiman * \date March, 20, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * A builder for AABB-trees of vertices. * * \class AABBTreeOfVerticesBuilder * \author Pierre Terdiman * \version 1.3 * \date March, 20, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * A builder for AABB-trees of AABBs. * * \class AABBTreeOfAABBsBuilder * \author Pierre Terdiman * \version 1.3 * \date March, 20, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * A builder for AABB-trees of triangles. * * \class AABBTreeOfTrianglesBuilder * \author Pierre Terdiman * \version 1.3 * \date March, 20, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Precompiled Header #include "Stdafx.h" using namespace Opcode; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the AABB of a set of primitives. * \param primitives [in] list of indices of primitives * \param nb_prims [in] number of indices * \param global_box [out] global AABB enclosing the set of input primitives * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool AABBTreeOfAABBsBuilder::ComputeGlobalBox(const dTriIndex* primitives, udword nb_prims, AABB& global_box) const { // Checkings if(!primitives || !nb_prims) return false; // Initialize global box global_box = mAABBArray[primitives[0]]; // Loop through boxes for(udword i=1;iGetTriangle(VP, *primitives++, VC); // Update global box Min.Min(*VP.Vertex[0]).Min(*VP.Vertex[1]).Min(*VP.Vertex[2]); Max.Max(*VP.Vertex[0]).Max(*VP.Vertex[1]).Max(*VP.Vertex[2]); } global_box.SetMinMax(Min, Max); return true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the splitting value along a given axis for a given primitive. * \param index [in] index of the primitive to split * \return splitting value */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Point AABBTreeOfTrianglesBuilder::GetSplittingValues(udword index) const { VertexPointers VP; ConversionArea VC; mIMesh->GetTriangle(VP, index, VC); return ( *VP.Vertex[0] + *VP.Vertex[1] + *VP.Vertex[2] ) * INV3; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the splitting value along a given axis for a given primitive. * \param index [in] index of the primitive to split * \param axis [in] axis index (0,1,2) * \return splitting value */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// float AABBTreeOfTrianglesBuilder::GetSplittingValue(udword index, udword axis) const { /* // Compute center of triangle Point Center; mTriList[index].Center(mVerts, Center); // Return value return Center[axis];*/ // Compute correct component from center of triangle // return (mVerts[mTriList[index].mVRef[0]][axis] // +mVerts[mTriList[index].mVRef[1]][axis] // +mVerts[mTriList[index].mVRef[2]][axis])*INV3; VertexPointers VP; ConversionArea VC; mIMesh->GetTriangle(VP, index, VC); // Compute correct component from center of triangle return ((*VP.Vertex[0])[axis] +(*VP.Vertex[1])[axis] +(*VP.Vertex[2])[axis])*INV3; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the splitting value along a given axis for a given node. * \param primitives [in] list of indices of primitives * \param nb_prims [in] number of indices * \param global_box [in] global AABB enclosing the set of input primitives * \param axis [in] axis index (0,1,2) * \return splitting value */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// float AABBTreeOfTrianglesBuilder::GetSplittingValue(const dTriIndex* primitives, udword nb_prims, const AABB& global_box, udword axis) const { if(mSettings.mRules&SPLIT_GEOM_CENTER) { // Loop through triangles float SplitValue = 0.0f; VertexPointers VP; ConversionArea VC; for(udword i=0;iGetTriangle(VP, primitives[i], VC); // Update split value SplitValue += (*VP.Vertex[0])[axis]; SplitValue += (*VP.Vertex[1])[axis]; SplitValue += (*VP.Vertex[2])[axis]; } return SplitValue / float(nb_prims*3); } else return AABBTreeBuilder::GetSplittingValue(primitives, nb_prims, global_box, axis); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Computes the AABB of a set of primitives. * \param primitives [in] list of indices of primitives * \param nb_prims [in] number of indices * \param global_box [out] global AABB enclosing the set of input primitives * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool AABBTreeOfVerticesBuilder::ComputeGlobalBox(const dTriIndex* primitives, udword nb_prims, AABB& global_box) const { // Checkings if(!primitives || !nb_prims) return false; // Initialize global box global_box.SetEmpty(); // Loop through vertices for(udword i=0;i 1000 #pragma once #endif // _MSC_VER > 1000 // Insert your headers here #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #include "Opcode.h" //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line. #endif // !defined(AFX_STDAFX_H__EFB95044_1D31_11D5_8B0F_0050BAC83302__INCLUDED_) ode-0.16/OPCODE/OPC_TreeCollider.cpp0000664000175200017520000011354113403272463013702 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* * OPCODE - Optimized Collision Detection * Copyright (C) 2001 Pierre Terdiman * Homepage: http://www.codercorner.com/Opcode.htm */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains code for a tree collider. * \file OPC_TreeCollider.cpp * \author Pierre Terdiman * \date March, 20, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains an AABB tree collider. * This class performs a collision test between two AABB trees. * * \class AABBTreeCollider * \author Pierre Terdiman * \version 1.3 * \date March, 20, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Precompiled Header #include "Stdafx.h" using namespace Opcode; #include "OPC_BoxBoxOverlap.h" #include "OPC_TriBoxOverlap.h" #include "OPC_TriTriOverlap.h" /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Constructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// AABBTreeCollider::AABBTreeCollider() : mIMesh0 (null), mIMesh1 (null), mNbBVBVTests (0), mNbPrimPrimTests (0), mNbBVPrimTests (0), mFullBoxBoxTest (true), mFullPrimBoxTest (true) { } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Destructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// AABBTreeCollider::~AABBTreeCollider() { } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Validates current settings. You should call this method after all the settings and callbacks have been defined. * \return null if everything is ok, else a string describing the problem */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// const char* AABBTreeCollider::ValidateSettings() { if(TemporalCoherenceEnabled() && !FirstContactEnabled()) return "Temporal coherence only works with ""First contact"" mode!"; return null; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Generic collision query for generic OPCODE models. After the call, access the results with: * - GetContactStatus() * - GetNbPairs() * - GetPairs() * * \param cache [in] collision cache for model pointers and a colliding pair of primitives * \param world0 [in] world matrix for first object * \param world1 [in] world matrix for second object * \return true if success * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool AABBTreeCollider::Collide(BVTCache& cache, const Matrix4x4* world0, const Matrix4x4* world1) { // Checkings if(!cache.Model0 || !cache.Model1) return false; if(cache.Model0->HasLeafNodes()!=cache.Model1->HasLeafNodes()) return false; if(cache.Model0->IsQuantized()!=cache.Model1->IsQuantized()) return false; /* Rules: - perform hull test - when hulls collide, disable hull test - if meshes overlap, reset countdown - if countdown reaches 0, enable hull test */ #ifdef __MESHMERIZER_H__ // Handle hulls if(cache.HullTest) { if(cache.Model0->GetHull() && cache.Model1->GetHull()) { struct Local { static Point* SVCallback(const Point& sv, udword& previndex, udword user_data) { CollisionHull* Hull = (CollisionHull*)user_data; previndex = Hull->ComputeSupportingVertex(sv, previndex); return (Point*)&Hull->GetVerts()[previndex]; } }; bool Collide; if(0) { static GJKEngine GJK; -- not thread safe, store in ThreadLocalData static bool GJKInitDone=false; -- not thread safe, to be removed if(!GJKInitDone) { GJK.Enable(GJK_BACKUP_PROCEDURE); GJK.Enable(GJK_DEGENERATE); GJK.Enable(GJK_HILLCLIMBING); GJKInitDone = true; } GJK.SetCallbackObj0(Local::SVCallback); GJK.SetCallbackObj1(Local::SVCallback); GJK.SetUserData0(udword(cache.Model0->GetHull())); GJK.SetUserData1(udword(cache.Model1->GetHull())); Collide = GJK.Collide(*world0, *world1, &cache.SepVector); } else { static SVEngine SVE; -- not thread safe, store in ThreadLocalData SVE.SetCallbackObj0(Local::SVCallback); SVE.SetCallbackObj1(Local::SVCallback); SVE.SetUserData0(udword(cache.Model0->GetHull())); SVE.SetUserData1(udword(cache.Model1->GetHull())); Collide = SVE.Collide(*world0, *world1, &cache.SepVector); } if(!Collide) { // Reset stats & contact status mFlags &= ~OPC_CONTACT; mNbBVBVTests = 0; mNbPrimPrimTests = 0; mNbBVPrimTests = 0; mPairs.Reset(); return true; } } } // Here, hulls collide cache.HullTest = false; #endif // __MESHMERIZER_H__ // Checkings if(!Setup(cache.Model0->GetMeshInterface(), cache.Model1->GetMeshInterface())) return false; // Simple double-dispatch bool Status; if(!cache.Model0->HasLeafNodes()) { if(cache.Model0->IsQuantized()) { const AABBQuantizedNoLeafTree* T0 = static_cast(cache.Model0->GetTree()); const AABBQuantizedNoLeafTree* T1 = static_cast(cache.Model1->GetTree()); Status = Collide(T0, T1, world0, world1, &cache); } else { const AABBNoLeafTree* T0 = static_cast(cache.Model0->GetTree()); const AABBNoLeafTree* T1 = static_cast(cache.Model1->GetTree()); Status = Collide(T0, T1, world0, world1, &cache); } } else { if(cache.Model0->IsQuantized()) { const AABBQuantizedTree* T0 = static_cast(cache.Model0->GetTree()); const AABBQuantizedTree* T1 = static_cast(cache.Model1->GetTree()); Status = Collide(T0, T1, world0, world1, &cache); } else { const AABBCollisionTree* T0 = static_cast(cache.Model0->GetTree()); const AABBCollisionTree* T1 = static_cast(cache.Model1->GetTree()); Status = Collide(T0, T1, world0, world1, &cache); } } #ifdef __MESHMERIZER_H__ if(Status) { // Reset counter as long as overlap occurs if(GetContactStatus()) cache.ResetCountDown(); // Enable hull test again when counter reaches zero cache.CountDown--; if(!cache.CountDown) { cache.ResetCountDown(); cache.HullTest = true; } } #endif return Status; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Initializes a collision query : * - reset stats & contact status * - setup matrices * * \param world0 [in] world matrix for first object * \param world1 [in] world matrix for second object * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void AABBTreeCollider::InitQuery(const Matrix4x4* world0, const Matrix4x4* world1) { // Reset stats & contact status Collider::InitQuery(); mNbBVBVTests = 0; mNbPrimPrimTests = 0; mNbBVPrimTests = 0; mPairs.Reset(); // Setup matrices Matrix4x4 InvWorld0, InvWorld1; if(world0) InvertPRMatrix(InvWorld0, *world0); else InvWorld0.Identity(); if(world1) InvertPRMatrix(InvWorld1, *world1); else InvWorld1.Identity(); Matrix4x4 World0to1 = world0 ? (*world0 * InvWorld1) : InvWorld1; Matrix4x4 World1to0 = world1 ? (*world1 * InvWorld0) : InvWorld0; mR0to1 = World0to1; World0to1.GetTrans(mT0to1); mR1to0 = World1to0; World1to0.GetTrans(mT1to0); // Precompute absolute 1-to-0 rotation matrix for(udword i=0;i<3;i++) { for(udword j=0;j<3;j++) { // Epsilon value prevents floating-point inaccuracies (strategy borrowed from RAPID) mAR.m[i][j] = 1e-6f + fabsf(mR1to0.m[i][j]); } } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Takes advantage of temporal coherence. * \param cache [in] cache for a pair of previously colliding primitives * \return true if we can return immediately * \warning only works for "First Contact" mode */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool AABBTreeCollider::CheckTemporalCoherence(Pair* cache) { // Checkings if(!cache) return false; // Test previously colliding primitives first if(TemporalCoherenceEnabled() && FirstContactEnabled()) { PrimTest(cache->id0, cache->id1); if(GetContactStatus()) return true; } return false; } #define UPDATE_CACHE \ if(cache && GetContactStatus()) \ { \ cache->id0 = mPairs.GetEntry(0); \ cache->id1 = mPairs.GetEntry(1); \ } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Collision query for normal AABB trees. * \param tree0 [in] AABB tree from first object * \param tree1 [in] AABB tree from second object * \param world0 [in] world matrix for first object * \param world1 [in] world matrix for second object * \param cache [in/out] cache for a pair of previously colliding primitives * \return true if success * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool AABBTreeCollider::Collide(const AABBCollisionTree* tree0, const AABBCollisionTree* tree1, const Matrix4x4* world0, const Matrix4x4* world1, Pair* cache) { // Init collision query InitQuery(world0, world1); // Check previous state if(CheckTemporalCoherence(cache)) return true; // Perform collision query _Collide(tree0->GetNodes(), tree1->GetNodes()); UPDATE_CACHE return true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Collision query for no-leaf AABB trees. * \param tree0 [in] AABB tree from first object * \param tree1 [in] AABB tree from second object * \param world0 [in] world matrix for first object * \param world1 [in] world matrix for second object * \param cache [in/out] cache for a pair of previously colliding primitives * \return true if success * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool AABBTreeCollider::Collide(const AABBNoLeafTree* tree0, const AABBNoLeafTree* tree1, const Matrix4x4* world0, const Matrix4x4* world1, Pair* cache) { // Init collision query InitQuery(world0, world1); // Check previous state if(CheckTemporalCoherence(cache)) return true; // Perform collision query _Collide(tree0->GetNodes(), tree1->GetNodes()); UPDATE_CACHE return true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Collision query for quantized AABB trees. * \param tree0 [in] AABB tree from first object * \param tree1 [in] AABB tree from second object * \param world0 [in] world matrix for first object * \param world1 [in] world matrix for second object * \param cache [in/out] cache for a pair of previously colliding primitives * \return true if success * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool AABBTreeCollider::Collide(const AABBQuantizedTree* tree0, const AABBQuantizedTree* tree1, const Matrix4x4* world0, const Matrix4x4* world1, Pair* cache) { // Init collision query InitQuery(world0, world1); // Check previous state if(CheckTemporalCoherence(cache)) return true; // Setup dequantization coeffs mCenterCoeff0 = tree0->mCenterCoeff; mExtentsCoeff0 = tree0->mExtentsCoeff; mCenterCoeff1 = tree1->mCenterCoeff; mExtentsCoeff1 = tree1->mExtentsCoeff; // Dequantize box A const AABBQuantizedNode* N0 = tree0->GetNodes(); const Point a(float(N0->mAABB.mExtents[0]) * mExtentsCoeff0.x, float(N0->mAABB.mExtents[1]) * mExtentsCoeff0.y, float(N0->mAABB.mExtents[2]) * mExtentsCoeff0.z); const Point Pa(float(N0->mAABB.mCenter[0]) * mCenterCoeff0.x, float(N0->mAABB.mCenter[1]) * mCenterCoeff0.y, float(N0->mAABB.mCenter[2]) * mCenterCoeff0.z); // Dequantize box B const AABBQuantizedNode* N1 = tree1->GetNodes(); const Point b(float(N1->mAABB.mExtents[0]) * mExtentsCoeff1.x, float(N1->mAABB.mExtents[1]) * mExtentsCoeff1.y, float(N1->mAABB.mExtents[2]) * mExtentsCoeff1.z); const Point Pb(float(N1->mAABB.mCenter[0]) * mCenterCoeff1.x, float(N1->mAABB.mCenter[1]) * mCenterCoeff1.y, float(N1->mAABB.mCenter[2]) * mCenterCoeff1.z); // Perform collision query _Collide(N0, N1, a, Pa, b, Pb); UPDATE_CACHE return true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Collision query for quantized no-leaf AABB trees. * \param tree0 [in] AABB tree from first object * \param tree1 [in] AABB tree from second object * \param world0 [in] world matrix for first object * \param world1 [in] world matrix for second object * \param cache [in/out] cache for a pair of previously colliding primitives * \return true if success * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool AABBTreeCollider::Collide(const AABBQuantizedNoLeafTree* tree0, const AABBQuantizedNoLeafTree* tree1, const Matrix4x4* world0, const Matrix4x4* world1, Pair* cache) { // Init collision query InitQuery(world0, world1); // Check previous state if(CheckTemporalCoherence(cache)) return true; // Setup dequantization coeffs mCenterCoeff0 = tree0->mCenterCoeff; mExtentsCoeff0 = tree0->mExtentsCoeff; mCenterCoeff1 = tree1->mCenterCoeff; mExtentsCoeff1 = tree1->mExtentsCoeff; // Perform collision query _Collide(tree0->GetNodes(), tree1->GetNodes()); UPDATE_CACHE return true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Standard trees /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // The normal AABB tree can use 2 different descent rules (with different performances) //#define ORIGINAL_CODE //!< UNC-like descent rules #define ALTERNATIVE_CODE //!< Alternative descent rules #ifdef ORIGINAL_CODE /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for normal AABB trees. * \param b0 [in] collision node from first tree * \param b1 [in] collision node from second tree */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void AABBTreeCollider::_Collide(const AABBCollisionNode* b0, const AABBCollisionNode* b1) { // Perform BV-BV overlap test if(!BoxBoxOverlap(b0->mAABB.mExtents, b0->mAABB.mCenter, b1->mAABB.mExtents, b1->mAABB.mCenter)) return; if(b0->IsLeaf() && b1->IsLeaf()) { PrimTest(b0->GetPrimitive(), b1->GetPrimitive()); return; } if(b1->IsLeaf() || (!b0->IsLeaf() && (b0->GetSize() > b1->GetSize()))) { _Collide(b0->GetNeg(), b1); if(ContactFound()) return; _Collide(b0->GetPos(), b1); } else { _Collide(b0, b1->GetNeg()); if(ContactFound()) return; _Collide(b0, b1->GetPos()); } } #endif #ifdef ALTERNATIVE_CODE /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for normal AABB trees. * \param b0 [in] collision node from first tree * \param b1 [in] collision node from second tree */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void AABBTreeCollider::_Collide(const AABBCollisionNode* b0, const AABBCollisionNode* b1) { // Perform BV-BV overlap test if(!BoxBoxOverlap(b0->mAABB.mExtents, b0->mAABB.mCenter, b1->mAABB.mExtents, b1->mAABB.mCenter)) { return; } if(b0->IsLeaf()) { if(b1->IsLeaf()) { PrimTest(b0->GetPrimitive(), b1->GetPrimitive()); } else { _Collide(b0, b1->GetNeg()); if(ContactFound()) return; _Collide(b0, b1->GetPos()); } } else if(b1->IsLeaf()) { _Collide(b0->GetNeg(), b1); if(ContactFound()) return; _Collide(b0->GetPos(), b1); } else { _Collide(b0->GetNeg(), b1->GetNeg()); if(ContactFound()) return; _Collide(b0->GetNeg(), b1->GetPos()); if(ContactFound()) return; _Collide(b0->GetPos(), b1->GetNeg()); if(ContactFound()) return; _Collide(b0->GetPos(), b1->GetPos()); } } #endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // No-leaf trees /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Leaf-leaf test for two primitive indices. * \param id0 [in] index from first leaf-triangle * \param id1 [in] index from second leaf-triangle */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void AABBTreeCollider::PrimTest(udword id0, udword id1) { // Request vertices from the app VertexPointers VP0; VertexPointers VP1; ConversionArea VC0; ConversionArea VC1; mIMesh0->GetTriangle(VP0, id0, VC0); mIMesh1->GetTriangle(VP1, id1, VC1); // Transform from space 1 to space 0 Point u0,u1,u2; TransformPoint(u0, *VP1.Vertex[0], mR1to0, mT1to0); TransformPoint(u1, *VP1.Vertex[1], mR1to0, mT1to0); TransformPoint(u2, *VP1.Vertex[2], mR1to0, mT1to0); // Perform triangle-triangle overlap test if(TriTriOverlap(*VP0.Vertex[0], *VP0.Vertex[1], *VP0.Vertex[2], u0, u1, u2)) { // Keep track of colliding pairs mPairs.Add(id0).Add(id1); // Set contact status mFlags |= OPC_CONTACT; } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Leaf-leaf test for a previously fetched triangle from tree A (in B's space) and a new leaf from B. * \param id1 [in] leaf-triangle index from tree B */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ void AABBTreeCollider::PrimTestTriIndex(udword id1) { // Request vertices from the app VertexPointers VP; ConversionArea VC; mIMesh1->GetTriangle(VP, id1, VC); // Perform triangle-triangle overlap test if(TriTriOverlap(mLeafVerts[0], mLeafVerts[1], mLeafVerts[2], *VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) { // Keep track of colliding pairs mPairs.Add(mLeafIndex).Add(id1); // Set contact status mFlags |= OPC_CONTACT; } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Leaf-leaf test for a previously fetched triangle from tree B (in A's space) and a new leaf from A. * \param id0 [in] leaf-triangle index from tree A */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ void AABBTreeCollider::PrimTestIndexTri(udword id0) { // Request vertices from the app VertexPointers VP; ConversionArea VC; mIMesh0->GetTriangle(VP, id0, VC); // Perform triangle-triangle overlap test if(TriTriOverlap(mLeafVerts[0], mLeafVerts[1], mLeafVerts[2], *VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) { // Keep track of colliding pairs mPairs.Add(id0).Add(mLeafIndex); // Set contact status mFlags |= OPC_CONTACT; } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision of a leaf node from A and a branch from B. * \param b [in] collision node from second tree */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void AABBTreeCollider::_CollideTriBox(const AABBNoLeafNode* b) { // Perform triangle-box overlap test if(!TriBoxOverlap(b->mAABB.mCenter, b->mAABB.mExtents)) return; // Keep same triangle, deal with first child if(b->HasPosLeaf()) PrimTestTriIndex(b->GetPosPrimitive()); else _CollideTriBox(b->GetPos()); if(ContactFound()) return; // Keep same triangle, deal with second child if(b->HasNegLeaf()) PrimTestTriIndex(b->GetNegPrimitive()); else _CollideTriBox(b->GetNeg()); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision of a leaf node from B and a branch from A. * \param b [in] collision node from first tree */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void AABBTreeCollider::_CollideBoxTri(const AABBNoLeafNode* b) { // Perform triangle-box overlap test if(!TriBoxOverlap(b->mAABB.mCenter, b->mAABB.mExtents)) return; // Keep same triangle, deal with first child if(b->HasPosLeaf()) PrimTestIndexTri(b->GetPosPrimitive()); else _CollideBoxTri(b->GetPos()); if(ContactFound()) return; // Keep same triangle, deal with second child if(b->HasNegLeaf()) PrimTestIndexTri(b->GetNegPrimitive()); else _CollideBoxTri(b->GetNeg()); } //! Request triangle vertices from the app and transform them #define FETCH_LEAF(prim_index, imesh, rot, trans) \ mLeafIndex = prim_index; \ /* Request vertices from the app */ \ VertexPointers VP; ConversionArea VC; imesh->GetTriangle(VP, prim_index, VC); \ /* Transform them in a common space */ \ TransformPoint(mLeafVerts[0], *VP.Vertex[0], rot, trans); \ TransformPoint(mLeafVerts[1], *VP.Vertex[1], rot, trans); \ TransformPoint(mLeafVerts[2], *VP.Vertex[2], rot, trans); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for no-leaf AABB trees. * \param a [in] collision node from first tree * \param b [in] collision node from second tree */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void AABBTreeCollider::_Collide(const AABBNoLeafNode* a, const AABBNoLeafNode* b) { // Perform BV-BV overlap test if(!BoxBoxOverlap(a->mAABB.mExtents, a->mAABB.mCenter, b->mAABB.mExtents, b->mAABB.mCenter)) return; // Catch leaf status BOOL BHasPosLeaf = b->HasPosLeaf(); BOOL BHasNegLeaf = b->HasNegLeaf(); if(a->HasPosLeaf()) { FETCH_LEAF(a->GetPosPrimitive(), mIMesh0, mR0to1, mT0to1) if(BHasPosLeaf) PrimTestTriIndex(b->GetPosPrimitive()); else _CollideTriBox(b->GetPos()); if(ContactFound()) return; if(BHasNegLeaf) PrimTestTriIndex(b->GetNegPrimitive()); else _CollideTriBox(b->GetNeg()); } else { if(BHasPosLeaf) { FETCH_LEAF(b->GetPosPrimitive(), mIMesh1, mR1to0, mT1to0) _CollideBoxTri(a->GetPos()); } else _Collide(a->GetPos(), b->GetPos()); if(ContactFound()) return; if(BHasNegLeaf) { FETCH_LEAF(b->GetNegPrimitive(), mIMesh1, mR1to0, mT1to0) _CollideBoxTri(a->GetPos()); } else _Collide(a->GetPos(), b->GetNeg()); } if(ContactFound()) return; if(a->HasNegLeaf()) { FETCH_LEAF(a->GetNegPrimitive(), mIMesh0, mR0to1, mT0to1) if(BHasPosLeaf) PrimTestTriIndex(b->GetPosPrimitive()); else _CollideTriBox(b->GetPos()); if(ContactFound()) return; if(BHasNegLeaf) PrimTestTriIndex(b->GetNegPrimitive()); else _CollideTriBox(b->GetNeg()); } else { if(BHasPosLeaf) { // ### That leaf has possibly already been fetched FETCH_LEAF(b->GetPosPrimitive(), mIMesh1, mR1to0, mT1to0) _CollideBoxTri(a->GetNeg()); } else _Collide(a->GetNeg(), b->GetPos()); if(ContactFound()) return; if(BHasNegLeaf) { // ### That leaf has possibly already been fetched FETCH_LEAF(b->GetNegPrimitive(), mIMesh1, mR1to0, mT1to0) _CollideBoxTri(a->GetNeg()); } else _Collide(a->GetNeg(), b->GetNeg()); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Quantized trees /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for quantized AABB trees. * \param b0 [in] collision node from first tree * \param b1 [in] collision node from second tree * \param a [in] extent from box A * \param Pa [in] center from box A * \param b [in] extent from box B * \param Pb [in] center from box B */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void AABBTreeCollider::_Collide(const AABBQuantizedNode* b0, const AABBQuantizedNode* b1, const Point& a, const Point& Pa, const Point& b, const Point& Pb) { // Perform BV-BV overlap test if(!BoxBoxOverlap(a, Pa, b, Pb)) return; if(b0->IsLeaf() && b1->IsLeaf()) { PrimTest(b0->GetPrimitive(), b1->GetPrimitive()); return; } if(b1->IsLeaf() || (!b0->IsLeaf() && (b0->GetSize() > b1->GetSize()))) { // Dequantize box const QuantizedAABB* Box = &b0->GetNeg()->mAABB; const Point negPa(float(Box->mCenter[0]) * mCenterCoeff0.x, float(Box->mCenter[1]) * mCenterCoeff0.y, float(Box->mCenter[2]) * mCenterCoeff0.z); const Point nega(float(Box->mExtents[0]) * mExtentsCoeff0.x, float(Box->mExtents[1]) * mExtentsCoeff0.y, float(Box->mExtents[2]) * mExtentsCoeff0.z); _Collide(b0->GetNeg(), b1, nega, negPa, b, Pb); if(ContactFound()) return; // Dequantize box Box = &b0->GetPos()->mAABB; const Point posPa(float(Box->mCenter[0]) * mCenterCoeff0.x, float(Box->mCenter[1]) * mCenterCoeff0.y, float(Box->mCenter[2]) * mCenterCoeff0.z); const Point posa(float(Box->mExtents[0]) * mExtentsCoeff0.x, float(Box->mExtents[1]) * mExtentsCoeff0.y, float(Box->mExtents[2]) * mExtentsCoeff0.z); _Collide(b0->GetPos(), b1, posa, posPa, b, Pb); } else { // Dequantize box const QuantizedAABB* Box = &b1->GetNeg()->mAABB; const Point negPb(float(Box->mCenter[0]) * mCenterCoeff1.x, float(Box->mCenter[1]) * mCenterCoeff1.y, float(Box->mCenter[2]) * mCenterCoeff1.z); const Point negb(float(Box->mExtents[0]) * mExtentsCoeff1.x, float(Box->mExtents[1]) * mExtentsCoeff1.y, float(Box->mExtents[2]) * mExtentsCoeff1.z); _Collide(b0, b1->GetNeg(), a, Pa, negb, negPb); if(ContactFound()) return; // Dequantize box Box = &b1->GetPos()->mAABB; const Point posPb(float(Box->mCenter[0]) * mCenterCoeff1.x, float(Box->mCenter[1]) * mCenterCoeff1.y, float(Box->mCenter[2]) * mCenterCoeff1.z); const Point posb(float(Box->mExtents[0]) * mExtentsCoeff1.x, float(Box->mExtents[1]) * mExtentsCoeff1.y, float(Box->mExtents[2]) * mExtentsCoeff1.z); _Collide(b0, b1->GetPos(), a, Pa, posb, posPb); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Quantized no-leaf trees /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision of a leaf node from A and a quantized branch from B. * \param leaf [in] leaf triangle from first tree * \param b [in] collision node from second tree */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void AABBTreeCollider::_CollideTriBox(const AABBQuantizedNoLeafNode* b) { // Dequantize box const QuantizedAABB* bb = &b->mAABB; const Point Pb(float(bb->mCenter[0]) * mCenterCoeff1.x, float(bb->mCenter[1]) * mCenterCoeff1.y, float(bb->mCenter[2]) * mCenterCoeff1.z); const Point eb(float(bb->mExtents[0]) * mExtentsCoeff1.x, float(bb->mExtents[1]) * mExtentsCoeff1.y, float(bb->mExtents[2]) * mExtentsCoeff1.z); // Perform triangle-box overlap test if(!TriBoxOverlap(Pb, eb)) return; if(b->HasPosLeaf()) PrimTestTriIndex(b->GetPosPrimitive()); else _CollideTriBox(b->GetPos()); if(ContactFound()) return; if(b->HasNegLeaf()) PrimTestTriIndex(b->GetNegPrimitive()); else _CollideTriBox(b->GetNeg()); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision of a leaf node from B and a quantized branch from A. * \param b [in] collision node from first tree * \param leaf [in] leaf triangle from second tree */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void AABBTreeCollider::_CollideBoxTri(const AABBQuantizedNoLeafNode* b) { // Dequantize box const QuantizedAABB* bb = &b->mAABB; const Point Pa(float(bb->mCenter[0]) * mCenterCoeff0.x, float(bb->mCenter[1]) * mCenterCoeff0.y, float(bb->mCenter[2]) * mCenterCoeff0.z); const Point ea(float(bb->mExtents[0]) * mExtentsCoeff0.x, float(bb->mExtents[1]) * mExtentsCoeff0.y, float(bb->mExtents[2]) * mExtentsCoeff0.z); // Perform triangle-box overlap test if(!TriBoxOverlap(Pa, ea)) return; if(b->HasPosLeaf()) PrimTestIndexTri(b->GetPosPrimitive()); else _CollideBoxTri(b->GetPos()); if(ContactFound()) return; if(b->HasNegLeaf()) PrimTestIndexTri(b->GetNegPrimitive()); else _CollideBoxTri(b->GetNeg()); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for quantized no-leaf AABB trees. * \param a [in] collision node from first tree * \param b [in] collision node from second tree */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void AABBTreeCollider::_Collide(const AABBQuantizedNoLeafNode* a, const AABBQuantizedNoLeafNode* b) { // Dequantize box A const QuantizedAABB* ab = &a->mAABB; const Point Pa(float(ab->mCenter[0]) * mCenterCoeff0.x, float(ab->mCenter[1]) * mCenterCoeff0.y, float(ab->mCenter[2]) * mCenterCoeff0.z); const Point ea(float(ab->mExtents[0]) * mExtentsCoeff0.x, float(ab->mExtents[1]) * mExtentsCoeff0.y, float(ab->mExtents[2]) * mExtentsCoeff0.z); // Dequantize box B const QuantizedAABB* bb = &b->mAABB; const Point Pb(float(bb->mCenter[0]) * mCenterCoeff1.x, float(bb->mCenter[1]) * mCenterCoeff1.y, float(bb->mCenter[2]) * mCenterCoeff1.z); const Point eb(float(bb->mExtents[0]) * mExtentsCoeff1.x, float(bb->mExtents[1]) * mExtentsCoeff1.y, float(bb->mExtents[2]) * mExtentsCoeff1.z); // Perform BV-BV overlap test if(!BoxBoxOverlap(ea, Pa, eb, Pb)) return; // Catch leaf status BOOL BHasPosLeaf = b->HasPosLeaf(); BOOL BHasNegLeaf = b->HasNegLeaf(); if(a->HasPosLeaf()) { FETCH_LEAF(a->GetPosPrimitive(), mIMesh0, mR0to1, mT0to1) if(BHasPosLeaf) PrimTestTriIndex(b->GetPosPrimitive()); else _CollideTriBox(b->GetPos()); if(ContactFound()) return; if(BHasNegLeaf) PrimTestTriIndex(b->GetNegPrimitive()); else _CollideTriBox(b->GetNeg()); } else { if(BHasPosLeaf) { FETCH_LEAF(b->GetPosPrimitive(), mIMesh1, mR1to0, mT1to0) _CollideBoxTri(a->GetPos()); } else _Collide(a->GetPos(), b->GetPos()); if(ContactFound()) return; if(BHasNegLeaf) { FETCH_LEAF(b->GetNegPrimitive(), mIMesh1, mR1to0, mT1to0) _CollideBoxTri(a->GetPos()); } else _Collide(a->GetPos(), b->GetNeg()); } if(ContactFound()) return; if(a->HasNegLeaf()) { FETCH_LEAF(a->GetNegPrimitive(), mIMesh0, mR0to1, mT0to1) if(BHasPosLeaf) PrimTestTriIndex(b->GetPosPrimitive()); else _CollideTriBox(b->GetPos()); if(ContactFound()) return; if(BHasNegLeaf) PrimTestTriIndex(b->GetNegPrimitive()); else _CollideTriBox(b->GetNeg()); } else { if(BHasPosLeaf) { // ### That leaf has possibly already been fetched FETCH_LEAF(b->GetPosPrimitive(), mIMesh1, mR1to0, mT1to0) _CollideBoxTri(a->GetNeg()); } else _Collide(a->GetNeg(), b->GetPos()); if(ContactFound()) return; if(BHasNegLeaf) { // ### That leaf has possibly already been fetched FETCH_LEAF(b->GetNegPrimitive(), mIMesh1, mR1to0, mT1to0) _CollideBoxTri(a->GetNeg()); } else _Collide(a->GetNeg(), b->GetNeg()); } } ode-0.16/OPCODE/OPC_LSSAABBOverlap.h0000664000175200017520000003760513403272463013400 00000000000000 // Following code from Magic-Software (http://www.magic-software.com/) // A bit modified for Opcode inline_ float OPC_PointAABBSqrDist(const Point& point, const Point& center, const Point& extents) { // Compute coordinates of point in box coordinate system Point Closest = point - center; float SqrDistance = 0.0f; if(Closest.x < -extents.x) { float Delta = Closest.x + extents.x; SqrDistance += Delta*Delta; } else if(Closest.x > extents.x) { float Delta = Closest.x - extents.x; SqrDistance += Delta*Delta; } if(Closest.y < -extents.y) { float Delta = Closest.y + extents.y; SqrDistance += Delta*Delta; } else if(Closest.y > extents.y) { float Delta = Closest.y - extents.y; SqrDistance += Delta*Delta; } if(Closest.z < -extents.z) { float Delta = Closest.z + extents.z; SqrDistance += Delta*Delta; } else if(Closest.z > extents.z) { float Delta = Closest.z - extents.z; SqrDistance += Delta*Delta; } return SqrDistance; } static void Face(int i0, int i1, int i2, Point& rkPnt, const Point& rkDir, const Point& extents, const Point& rkPmE, float* pfLParam, float& rfSqrDistance) { Point kPpE; float fLSqr, fInv, fTmp, fParam, fT, fDelta; kPpE[i1] = rkPnt[i1] + extents[i1]; kPpE[i2] = rkPnt[i2] + extents[i2]; if(rkDir[i0]*kPpE[i1] >= rkDir[i1]*rkPmE[i0]) { if(rkDir[i0]*kPpE[i2] >= rkDir[i2]*rkPmE[i0]) { // v[i1] >= -e[i1], v[i2] >= -e[i2] (distance = 0) if(pfLParam) { rkPnt[i0] = extents[i0]; fInv = 1.0f/rkDir[i0]; rkPnt[i1] -= rkDir[i1]*rkPmE[i0]*fInv; rkPnt[i2] -= rkDir[i2]*rkPmE[i0]*fInv; *pfLParam = -rkPmE[i0]*fInv; } } else { // v[i1] >= -e[i1], v[i2] < -e[i2] fLSqr = rkDir[i0]*rkDir[i0] + rkDir[i2]*rkDir[i2]; fTmp = fLSqr*kPpE[i1] - rkDir[i1]*(rkDir[i0]*rkPmE[i0] + rkDir[i2]*kPpE[i2]); if(fTmp <= 2.0f*fLSqr*extents[i1]) { fT = fTmp/fLSqr; fLSqr += rkDir[i1]*rkDir[i1]; fTmp = kPpE[i1] - fT; fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*fTmp + rkDir[i2]*kPpE[i2]; fParam = -fDelta/fLSqr; rfSqrDistance += rkPmE[i0]*rkPmE[i0] + fTmp*fTmp + kPpE[i2]*kPpE[i2] + fDelta*fParam; if(pfLParam) { *pfLParam = fParam; rkPnt[i0] = extents[i0]; rkPnt[i1] = fT - extents[i1]; rkPnt[i2] = -extents[i2]; } } else { fLSqr += rkDir[i1]*rkDir[i1]; fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*rkPmE[i1] + rkDir[i2]*kPpE[i2]; fParam = -fDelta/fLSqr; rfSqrDistance += rkPmE[i0]*rkPmE[i0] + rkPmE[i1]*rkPmE[i1] + kPpE[i2]*kPpE[i2] + fDelta*fParam; if(pfLParam) { *pfLParam = fParam; rkPnt[i0] = extents[i0]; rkPnt[i1] = extents[i1]; rkPnt[i2] = -extents[i2]; } } } } else { if ( rkDir[i0]*kPpE[i2] >= rkDir[i2]*rkPmE[i0] ) { // v[i1] < -e[i1], v[i2] >= -e[i2] fLSqr = rkDir[i0]*rkDir[i0] + rkDir[i1]*rkDir[i1]; fTmp = fLSqr*kPpE[i2] - rkDir[i2]*(rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1]); if(fTmp <= 2.0f*fLSqr*extents[i2]) { fT = fTmp/fLSqr; fLSqr += rkDir[i2]*rkDir[i2]; fTmp = kPpE[i2] - fT; fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1] + rkDir[i2]*fTmp; fParam = -fDelta/fLSqr; rfSqrDistance += rkPmE[i0]*rkPmE[i0] + kPpE[i1]*kPpE[i1] + fTmp*fTmp + fDelta*fParam; if(pfLParam) { *pfLParam = fParam; rkPnt[i0] = extents[i0]; rkPnt[i1] = -extents[i1]; rkPnt[i2] = fT - extents[i2]; } } else { fLSqr += rkDir[i2]*rkDir[i2]; fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1] + rkDir[i2]*rkPmE[i2]; fParam = -fDelta/fLSqr; rfSqrDistance += rkPmE[i0]*rkPmE[i0] + kPpE[i1]*kPpE[i1] + rkPmE[i2]*rkPmE[i2] + fDelta*fParam; if(pfLParam) { *pfLParam = fParam; rkPnt[i0] = extents[i0]; rkPnt[i1] = -extents[i1]; rkPnt[i2] = extents[i2]; } } } else { // v[i1] < -e[i1], v[i2] < -e[i2] fLSqr = rkDir[i0]*rkDir[i0]+rkDir[i2]*rkDir[i2]; fTmp = fLSqr*kPpE[i1] - rkDir[i1]*(rkDir[i0]*rkPmE[i0] + rkDir[i2]*kPpE[i2]); if(fTmp >= 0.0f) { // v[i1]-edge is closest if ( fTmp <= 2.0f*fLSqr*extents[i1] ) { fT = fTmp/fLSqr; fLSqr += rkDir[i1]*rkDir[i1]; fTmp = kPpE[i1] - fT; fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*fTmp + rkDir[i2]*kPpE[i2]; fParam = -fDelta/fLSqr; rfSqrDistance += rkPmE[i0]*rkPmE[i0] + fTmp*fTmp + kPpE[i2]*kPpE[i2] + fDelta*fParam; if(pfLParam) { *pfLParam = fParam; rkPnt[i0] = extents[i0]; rkPnt[i1] = fT - extents[i1]; rkPnt[i2] = -extents[i2]; } } else { fLSqr += rkDir[i1]*rkDir[i1]; fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*rkPmE[i1] + rkDir[i2]*kPpE[i2]; fParam = -fDelta/fLSqr; rfSqrDistance += rkPmE[i0]*rkPmE[i0] + rkPmE[i1]*rkPmE[i1] + kPpE[i2]*kPpE[i2] + fDelta*fParam; if(pfLParam) { *pfLParam = fParam; rkPnt[i0] = extents[i0]; rkPnt[i1] = extents[i1]; rkPnt[i2] = -extents[i2]; } } return; } fLSqr = rkDir[i0]*rkDir[i0] + rkDir[i1]*rkDir[i1]; fTmp = fLSqr*kPpE[i2] - rkDir[i2]*(rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1]); if(fTmp >= 0.0f) { // v[i2]-edge is closest if(fTmp <= 2.0f*fLSqr*extents[i2]) { fT = fTmp/fLSqr; fLSqr += rkDir[i2]*rkDir[i2]; fTmp = kPpE[i2] - fT; fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1] + rkDir[i2]*fTmp; fParam = -fDelta/fLSqr; rfSqrDistance += rkPmE[i0]*rkPmE[i0] + kPpE[i1]*kPpE[i1] + fTmp*fTmp + fDelta*fParam; if(pfLParam) { *pfLParam = fParam; rkPnt[i0] = extents[i0]; rkPnt[i1] = -extents[i1]; rkPnt[i2] = fT - extents[i2]; } } else { fLSqr += rkDir[i2]*rkDir[i2]; fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1] + rkDir[i2]*rkPmE[i2]; fParam = -fDelta/fLSqr; rfSqrDistance += rkPmE[i0]*rkPmE[i0] + kPpE[i1]*kPpE[i1] + rkPmE[i2]*rkPmE[i2] + fDelta*fParam; if(pfLParam) { *pfLParam = fParam; rkPnt[i0] = extents[i0]; rkPnt[i1] = -extents[i1]; rkPnt[i2] = extents[i2]; } } return; } // (v[i1],v[i2])-corner is closest fLSqr += rkDir[i2]*rkDir[i2]; fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1] + rkDir[i2]*kPpE[i2]; fParam = -fDelta/fLSqr; rfSqrDistance += rkPmE[i0]*rkPmE[i0] + kPpE[i1]*kPpE[i1] + kPpE[i2]*kPpE[i2] + fDelta*fParam; if(pfLParam) { *pfLParam = fParam; rkPnt[i0] = extents[i0]; rkPnt[i1] = -extents[i1]; rkPnt[i2] = -extents[i2]; } } } } static void CaseNoZeros(Point& rkPnt, const Point& rkDir, const Point& extents, float* pfLParam, float& rfSqrDistance) { Point kPmE(rkPnt.x - extents.x, rkPnt.y - extents.y, rkPnt.z - extents.z); float fProdDxPy, fProdDyPx, fProdDzPx, fProdDxPz, fProdDzPy, fProdDyPz; fProdDxPy = rkDir.x*kPmE.y; fProdDyPx = rkDir.y*kPmE.x; if(fProdDyPx >= fProdDxPy) { fProdDzPx = rkDir.z*kPmE.x; fProdDxPz = rkDir.x*kPmE.z; if(fProdDzPx >= fProdDxPz) { // line intersects x = e0 Face(0, 1, 2, rkPnt, rkDir, extents, kPmE, pfLParam, rfSqrDistance); } else { // line intersects z = e2 Face(2, 0, 1, rkPnt, rkDir, extents, kPmE, pfLParam, rfSqrDistance); } } else { fProdDzPy = rkDir.z*kPmE.y; fProdDyPz = rkDir.y*kPmE.z; if(fProdDzPy >= fProdDyPz) { // line intersects y = e1 Face(1, 2, 0, rkPnt, rkDir, extents, kPmE, pfLParam, rfSqrDistance); } else { // line intersects z = e2 Face(2, 0, 1, rkPnt, rkDir, extents, kPmE, pfLParam, rfSqrDistance); } } } static void Case0(int i0, int i1, int i2, Point& rkPnt, const Point& rkDir, const Point& extents, float* pfLParam, float& rfSqrDistance) { float fPmE0 = rkPnt[i0] - extents[i0]; float fPmE1 = rkPnt[i1] - extents[i1]; float fProd0 = rkDir[i1]*fPmE0; float fProd1 = rkDir[i0]*fPmE1; float fDelta, fInvLSqr, fInv; if(fProd0 >= fProd1) { // line intersects P[i0] = e[i0] rkPnt[i0] = extents[i0]; float fPpE1 = rkPnt[i1] + extents[i1]; fDelta = fProd0 - rkDir[i0]*fPpE1; if(fDelta >= 0.0f) { fInvLSqr = 1.0f/(rkDir[i0]*rkDir[i0] + rkDir[i1]*rkDir[i1]); rfSqrDistance += fDelta*fDelta*fInvLSqr; if(pfLParam) { rkPnt[i1] = -extents[i1]; *pfLParam = -(rkDir[i0]*fPmE0+rkDir[i1]*fPpE1)*fInvLSqr; } } else { if(pfLParam) { fInv = 1.0f/rkDir[i0]; rkPnt[i1] -= fProd0*fInv; *pfLParam = -fPmE0*fInv; } } } else { // line intersects P[i1] = e[i1] rkPnt[i1] = extents[i1]; float fPpE0 = rkPnt[i0] + extents[i0]; fDelta = fProd1 - rkDir[i1]*fPpE0; if(fDelta >= 0.0f) { fInvLSqr = 1.0f/(rkDir[i0]*rkDir[i0] + rkDir[i1]*rkDir[i1]); rfSqrDistance += fDelta*fDelta*fInvLSqr; if(pfLParam) { rkPnt[i0] = -extents[i0]; *pfLParam = -(rkDir[i0]*fPpE0+rkDir[i1]*fPmE1)*fInvLSqr; } } else { if(pfLParam) { fInv = 1.0f/rkDir[i1]; rkPnt[i0] -= fProd1*fInv; *pfLParam = -fPmE1*fInv; } } } if(rkPnt[i2] < -extents[i2]) { fDelta = rkPnt[i2] + extents[i2]; rfSqrDistance += fDelta*fDelta; rkPnt[i2] = -extents[i2]; } else if ( rkPnt[i2] > extents[i2] ) { fDelta = rkPnt[i2] - extents[i2]; rfSqrDistance += fDelta*fDelta; rkPnt[i2] = extents[i2]; } } static void Case00(int i0, int i1, int i2, Point& rkPnt, const Point& rkDir, const Point& extents, float* pfLParam, float& rfSqrDistance) { float fDelta; if(pfLParam) *pfLParam = (extents[i0] - rkPnt[i0])/rkDir[i0]; rkPnt[i0] = extents[i0]; if(rkPnt[i1] < -extents[i1]) { fDelta = rkPnt[i1] + extents[i1]; rfSqrDistance += fDelta*fDelta; rkPnt[i1] = -extents[i1]; } else if(rkPnt[i1] > extents[i1]) { fDelta = rkPnt[i1] - extents[i1]; rfSqrDistance += fDelta*fDelta; rkPnt[i1] = extents[i1]; } if(rkPnt[i2] < -extents[i2]) { fDelta = rkPnt[i2] + extents[i2]; rfSqrDistance += fDelta*fDelta; rkPnt[i1] = -extents[i2]; } else if(rkPnt[i2] > extents[i2]) { fDelta = rkPnt[i2] - extents[i2]; rfSqrDistance += fDelta*fDelta; rkPnt[i2] = extents[i2]; } } static void Case000(Point& rkPnt, const Point& extents, float& rfSqrDistance) { float fDelta; if(rkPnt.x < -extents.x) { fDelta = rkPnt.x + extents.x; rfSqrDistance += fDelta*fDelta; rkPnt.x = -extents.x; } else if(rkPnt.x > extents.x) { fDelta = rkPnt.x - extents.x; rfSqrDistance += fDelta*fDelta; rkPnt.x = extents.x; } if(rkPnt.y < -extents.y) { fDelta = rkPnt.y + extents.y; rfSqrDistance += fDelta*fDelta; rkPnt.y = -extents.y; } else if(rkPnt.y > extents.y) { fDelta = rkPnt.y - extents.y; rfSqrDistance += fDelta*fDelta; rkPnt.y = extents.y; } if(rkPnt.z < -extents.z) { fDelta = rkPnt.z + extents.z; rfSqrDistance += fDelta*fDelta; rkPnt.z = -extents.z; } else if(rkPnt.z > extents.z) { fDelta = rkPnt.z - extents.z; rfSqrDistance += fDelta*fDelta; rkPnt.z = extents.z; } } static float SqrDistance(const Ray& rkLine, const Point& center, const Point& extents, float* pfLParam) { // compute coordinates of line in box coordinate system Point kDiff = rkLine.mOrig - center; Point kPnt = kDiff; Point kDir = rkLine.mDir; #if 0 // Apply reflections so that direction vector has nonnegative components. bool bReflect[3]; for(int i=0;i<3;i++) { if(kDir[i]<0.0f) { kPnt[i] = -kPnt[i]; kDir[i] = -kDir[i]; bReflect[i] = true; } else { bReflect[i] = false; } } #endif float fSqrDistance = 0.0f; if(kDir.x>0.0f) { if(kDir.y>0.0f) { if(kDir.z>0.0f) CaseNoZeros(kPnt, kDir, extents, pfLParam, fSqrDistance); // (+,+,+) else Case0(0, 1, 2, kPnt, kDir, extents, pfLParam, fSqrDistance); // (+,+,0) } else { if(kDir.z>0.0f) Case0(0, 2, 1, kPnt, kDir, extents, pfLParam, fSqrDistance); // (+,0,+) else Case00(0, 1, 2, kPnt, kDir, extents, pfLParam, fSqrDistance); // (+,0,0) } } else { if(kDir.y>0.0f) { if(kDir.z>0.0f) Case0(1, 2, 0, kPnt, kDir, extents, pfLParam, fSqrDistance); // (0,+,+) else Case00(1, 0, 2, kPnt, kDir, extents, pfLParam, fSqrDistance); // (0,+,0) } else { if(kDir.z>0.0f) Case00(2, 0, 1, kPnt, kDir, extents, pfLParam, fSqrDistance); // (0,0,+) else { Case000(kPnt, extents, fSqrDistance); // (0,0,0) if(pfLParam) *pfLParam = 0.0f; } } } return fSqrDistance; } inline_ float OPC_SegmentOBBSqrDist(const Segment& segment, const Point& c0, const Point& e0) { float fLP; float fSqrDistance = SqrDistance(Ray(segment.GetOrigin(), segment.ComputeDirection()), c0, e0, &fLP); if(fLP>=0.0f) { if(fLP<=1.0f) return fSqrDistance; else return OPC_PointAABBSqrDist(segment.mP1, c0, e0); } else return OPC_PointAABBSqrDist(segment.mP0, c0, e0); } inline_ BOOL LSSCollider::LSSAABBOverlap(const Point& center, const Point& extents) { // Stats mNbVolumeBVTests++; float s2 = OPC_SegmentOBBSqrDist(mSeg, center, extents); if(s2 IR(y) #else #define GREATER(x, y) fabsf(x) > (y) #endif class OPCODE_API CollisionAABB { public: //! Constructor inline_ CollisionAABB() {} //! Constructor inline_ CollisionAABB(const AABB& b) { b.GetCenter(mCenter); b.GetExtents(mExtents); } //! Destructor inline_ ~CollisionAABB() {} //! Get min point of the box inline_ void GetMin(Point& min) const { min = mCenter - mExtents; } //! Get max point of the box inline_ void GetMax(Point& max) const { max = mCenter + mExtents; } //! Get component of the box's min point along a given axis inline_ float GetMin(udword axis) const { return mCenter[axis] - mExtents[axis]; } //! Get component of the box's max point along a given axis inline_ float GetMax(udword axis) const { return mCenter[axis] + mExtents[axis]; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Setups an AABB from min & max vectors. * \param min [in] the min point * \param max [in] the max point */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ void SetMinMax(const Point& min, const Point& max) { mCenter = (max + min)*0.5f; mExtents = (max - min)*0.5f; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Checks a box is inside another box. * \param box [in] the other box * \return true if current box is inside input box */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ BOOL IsInside(const CollisionAABB& box) const { if(box.GetMin(0)>GetMin(0)) return FALSE; if(box.GetMin(1)>GetMin(1)) return FALSE; if(box.GetMin(2)>GetMin(2)) return FALSE; if(box.GetMax(0)Add(udword(prim_index)); //! LSS-triangle overlap test #define LSS_PRIM(prim_index, flag) \ /* Request vertices from the app */ \ VertexPointers VP; ConversionArea VC; mIMesh->GetTriangle(VP, prim_index, VC); \ \ /* Perform LSS-tri overlap test */ \ if(LSSTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) \ { \ SET_CONTACT(prim_index, flag) \ } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Constructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// LSSCollider::LSSCollider() { // mCenter.Zero(); // mRadius2 = 0.0f; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Destructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// LSSCollider::~LSSCollider() { } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Generic collision query for generic OPCODE models. After the call, access the results: * - with GetContactStatus() * - with GetNbTouchedPrimitives() * - with GetTouchedPrimitives() * * \param cache [in/out] an lss cache * \param lss [in] collision lss in local space * \param model [in] Opcode model to collide with * \param worldl [in] lss world matrix, or null * \param worldm [in] model's world matrix, or null * \return true if success * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool LSSCollider::Collide(LSSCache& cache, const LSS& lss, const Model& model, const Matrix4x4* worldl, const Matrix4x4* worldm) { // Checkings if(!Setup(&model)) return false; // Init collision query if(InitQuery(cache, lss, worldl, worldm)) return true; if(!model.HasLeafNodes()) { if(model.IsQuantized()) { const AABBQuantizedNoLeafTree* Tree = static_cast(model.GetTree()); // Setup dequantization coeffs mCenterCoeff = Tree->mCenterCoeff; mExtentsCoeff = Tree->mExtentsCoeff; // Perform collision query if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); else _Collide(Tree->GetNodes()); } else { const AABBNoLeafTree* Tree = static_cast(model.GetTree()); // Perform collision query if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); else _Collide(Tree->GetNodes()); } } else { if(model.IsQuantized()) { const AABBQuantizedTree* Tree = static_cast(model.GetTree()); // Setup dequantization coeffs mCenterCoeff = Tree->mCenterCoeff; mExtentsCoeff = Tree->mExtentsCoeff; // Perform collision query if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); else _Collide(Tree->GetNodes()); } else { const AABBCollisionTree* Tree = static_cast(model.GetTree()); // Perform collision query if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); else _Collide(Tree->GetNodes()); } } return true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Initializes a collision query : * - reset stats & contact status * - setup matrices * - check temporal coherence * * \param cache [in/out] an lss cache * \param lss [in] lss in local space * \param worldl [in] lss world matrix, or null * \param worldm [in] model's world matrix, or null * \return TRUE if we can return immediately * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// BOOL LSSCollider::InitQuery(LSSCache& cache, const LSS& lss, const Matrix4x4* worldl, const Matrix4x4* worldm) { // 1) Call the base method VolumeCollider::InitQuery(); // 2) Compute LSS in model space: // - Precompute R^2 mRadius2 = lss.mRadius * lss.mRadius; // - Compute segment mSeg.mP0 = lss.mP0; mSeg.mP1 = lss.mP1; // -> to world space if(worldl) { mSeg.mP0 *= *worldl; mSeg.mP1 *= *worldl; } // -> to model space if(worldm) { // Invert model matrix Matrix4x4 InvWorldM; InvertPRMatrix(InvWorldM, *worldm); mSeg.mP0 *= InvWorldM; mSeg.mP1 *= InvWorldM; } // 3) Setup destination pointer mTouchedPrimitives = &cache.TouchedPrimitives; // 4) Special case: 1-triangle meshes [Opcode 1.3] if(mCurrentModel && mCurrentModel->HasSingleNode()) { if(!SkipPrimitiveTests()) { // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0. mTouchedPrimitives->Reset(); // Perform overlap test between the unique triangle and the LSS (and set contact status if needed) LSS_PRIM(udword(0), OPC_CONTACT) // Return immediately regardless of status return TRUE; } } // 5) Check temporal coherence : if(TemporalCoherenceEnabled()) { // Here we use temporal coherence // => check results from previous frame before performing the collision query if(FirstContactEnabled()) { // We're only interested in the first contact found => test the unique previously touched face if(mTouchedPrimitives->GetNbEntries()) { // Get index of previously touched face = the first entry in the array udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0); // Then reset the array: // - if the overlap test below is successful, the index we'll get added back anyway // - if it isn't, then the array should be reset anyway for the normal query mTouchedPrimitives->Reset(); // Perform overlap test between the cached triangle and the LSS (and set contact status if needed) LSS_PRIM(PreviouslyTouchedFace, OPC_TEMPORAL_CONTACT) // Return immediately if possible if(GetContactStatus()) return TRUE; } // else no face has been touched during previous query // => we'll have to perform a normal query } else { // We're interested in all contacts =>test the new real LSS N(ew) against the previous fat LSS P(revious): // ### rewrite this LSS Test(mSeg, lss.mRadius); // in model space LSS Previous(cache.Previous, sqrtf(cache.Previous.mRadius)); // if(cache.Previous.Contains(Test)) if(IsCacheValid(cache) && Previous.Contains(Test)) { // - if N is included in P, return previous list // => we simply leave the list (mTouchedFaces) unchanged // Set contact status if needed if(mTouchedPrimitives->GetNbEntries()) mFlags |= OPC_TEMPORAL_CONTACT; // In any case we don't need to do a query return TRUE; } else { // - else do the query using a fat N // Reset cache since we'll about to perform a real query mTouchedPrimitives->Reset(); // Make a fat sphere so that coherence will work for subsequent frames mRadius2 *= cache.FatCoeff; // mRadius2 = (lss.mRadius * cache.FatCoeff)*(lss.mRadius * cache.FatCoeff); // Update cache with query data (signature for cached faces) cache.Previous.mP0 = mSeg.mP0; cache.Previous.mP1 = mSeg.mP1; cache.Previous.mRadius = mRadius2; } } } else { // Here we don't use temporal coherence => do a normal query mTouchedPrimitives->Reset(); } return FALSE; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Collision query for vanilla AABB trees. * \param cache [in/out] an lss cache * \param lss [in] collision lss in world space * \param tree [in] AABB tree * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool LSSCollider::Collide(LSSCache& cache, const LSS& lss, const AABBTree* tree) { // This is typically called for a scene tree, full of -AABBs-, not full of triangles. // So we don't really have "primitives" to deal with. Hence it doesn't work with // "FirstContact" + "TemporalCoherence". ASSERT( !(FirstContactEnabled() && TemporalCoherenceEnabled()) ); // Checkings if(!tree) return false; // Init collision query if(InitQuery(cache, lss)) return true; // Perform collision query _Collide(tree); return true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Checks the LSS completely contains the box. In which case we can end the query sooner. * \param bc [in] box center * \param be [in] box extents * \return true if the LSS contains the whole box */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ BOOL LSSCollider::LSSContainsBox(const Point& bc, const Point& be) { // Not implemented return FALSE; } #define TEST_BOX_IN_LSS(center, extents) \ if(LSSContainsBox(center, extents)) \ { \ /* Set contact status */ \ mFlags |= OPC_CONTACT; \ _Dump(node); \ return; \ } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for normal AABB trees. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void LSSCollider::_Collide(const AABBCollisionNode* node) { // Perform LSS-AABB overlap test if(!LSSAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; TEST_BOX_IN_LSS(node->mAABB.mCenter, node->mAABB.mExtents) if(node->IsLeaf()) { LSS_PRIM(node->GetPrimitive(), OPC_CONTACT) } else { _Collide(node->GetPos()); if(ContactFound()) return; _Collide(node->GetNeg()); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for normal AABB trees, without primitive tests. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void LSSCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node) { // Perform LSS-AABB overlap test if(!LSSAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; TEST_BOX_IN_LSS(node->mAABB.mCenter, node->mAABB.mExtents) if(node->IsLeaf()) { SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) } else { _CollideNoPrimitiveTest(node->GetPos()); if(ContactFound()) return; _CollideNoPrimitiveTest(node->GetNeg()); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for quantized AABB trees. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void LSSCollider::_Collide(const AABBQuantizedNode* node) { // Dequantize box const QuantizedAABB& Box = node->mAABB; const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); // Perform LSS-AABB overlap test if(!LSSAABBOverlap(Center, Extents)) return; TEST_BOX_IN_LSS(Center, Extents) if(node->IsLeaf()) { LSS_PRIM(node->GetPrimitive(), OPC_CONTACT) } else { _Collide(node->GetPos()); if(ContactFound()) return; _Collide(node->GetNeg()); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for quantized AABB trees, without primitive tests. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void LSSCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node) { // Dequantize box const QuantizedAABB& Box = node->mAABB; const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); // Perform LSS-AABB overlap test if(!LSSAABBOverlap(Center, Extents)) return; TEST_BOX_IN_LSS(Center, Extents) if(node->IsLeaf()) { SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) } else { _CollideNoPrimitiveTest(node->GetPos()); if(ContactFound()) return; _CollideNoPrimitiveTest(node->GetNeg()); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for no-leaf AABB trees. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void LSSCollider::_Collide(const AABBNoLeafNode* node) { // Perform LSS-AABB overlap test if(!LSSAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; TEST_BOX_IN_LSS(node->mAABB.mCenter, node->mAABB.mExtents) if(node->HasPosLeaf()) { LSS_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } else _Collide(node->GetPos()); if(ContactFound()) return; if(node->HasNegLeaf()) { LSS_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } else _Collide(node->GetNeg()); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for no-leaf AABB trees, without primitive tests. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void LSSCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node) { // Perform LSS-AABB overlap test if(!LSSAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; TEST_BOX_IN_LSS(node->mAABB.mCenter, node->mAABB.mExtents) if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } else _CollideNoPrimitiveTest(node->GetPos()); if(ContactFound()) return; if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } else _CollideNoPrimitiveTest(node->GetNeg()); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for quantized no-leaf AABB trees. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void LSSCollider::_Collide(const AABBQuantizedNoLeafNode* node) { // Dequantize box const QuantizedAABB& Box = node->mAABB; const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); // Perform LSS-AABB overlap test if(!LSSAABBOverlap(Center, Extents)) return; TEST_BOX_IN_LSS(Center, Extents) if(node->HasPosLeaf()) { LSS_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } else _Collide(node->GetPos()); if(ContactFound()) return; if(node->HasNegLeaf()) { LSS_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } else _Collide(node->GetNeg()); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for quantized no-leaf AABB trees, without primitive tests. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void LSSCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node) { // Dequantize box const QuantizedAABB& Box = node->mAABB; const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); // Perform LSS-AABB overlap test if(!LSSAABBOverlap(Center, Extents)) return; TEST_BOX_IN_LSS(Center, Extents) if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } else _CollideNoPrimitiveTest(node->GetPos()); if(ContactFound()) return; if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } else _CollideNoPrimitiveTest(node->GetNeg()); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Recursive collision query for vanilla AABB trees. * \param node [in] current collision node */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void LSSCollider::_Collide(const AABBTreeNode* node) { // Perform LSS-AABB overlap test Point Center, Extents; node->GetAABB()->GetCenter(Center); node->GetAABB()->GetExtents(Extents); if(!LSSAABBOverlap(Center, Extents)) return; if(node->IsLeaf() || LSSContainsBox(Center, Extents)) { mFlags |= OPC_CONTACT; mTouchedPrimitives->Add(node->GetPrimitives(), node->GetNbPrimitives()); } else { _Collide(node->GetPos()); _Collide(node->GetNeg()); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Constructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// HybridLSSCollider::HybridLSSCollider() { } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Destructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// HybridLSSCollider::~HybridLSSCollider() { } bool HybridLSSCollider::Collide(LSSCache& cache, const LSS& lss, const HybridModel& model, const Matrix4x4* worldl, const Matrix4x4* worldm) { // We don't want primitive tests here! mFlags |= OPC_NO_PRIMITIVE_TESTS; // Checkings if(!Setup(&model)) return false; // Init collision query if(InitQuery(cache, lss, worldl, worldm)) return true; // Special case for 1-leaf trees if(mCurrentModel && mCurrentModel->HasSingleNode()) { // Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles udword Nb = mIMesh->GetNbTriangles(); // Loop through all triangles for(udword i=0;i(model.GetTree()); // Setup dequantization coeffs mCenterCoeff = Tree->mCenterCoeff; mExtentsCoeff = Tree->mExtentsCoeff; // Perform collision query - we don't want primitive tests here! _CollideNoPrimitiveTest(Tree->GetNodes()); } else { const AABBNoLeafTree* Tree = static_cast(model.GetTree()); // Perform collision query - we don't want primitive tests here! _CollideNoPrimitiveTest(Tree->GetNodes()); } } else { if(model.IsQuantized()) { const AABBQuantizedTree* Tree = static_cast(model.GetTree()); // Setup dequantization coeffs mCenterCoeff = Tree->mCenterCoeff; mExtentsCoeff = Tree->mExtentsCoeff; // Perform collision query - we don't want primitive tests here! _CollideNoPrimitiveTest(Tree->GetNodes()); } else { const AABBCollisionTree* Tree = static_cast(model.GetTree()); // Perform collision query - we don't want primitive tests here! _CollideNoPrimitiveTest(Tree->GetNodes()); } } // We only have a list of boxes so far if(GetContactStatus()) { // Reset contact status, since it currently only reflects collisions with leaf boxes Collider::InitQuery(); // Change dest container so that we can use built-in overlap tests and get collided primitives cache.TouchedPrimitives.Reset(); mTouchedPrimitives = &cache.TouchedPrimitives; // Read touched leaf boxes udword Nb = mTouchedBoxes.GetNbEntries(); const udword* Touched = mTouchedBoxes.GetEntries(); const LeafTriangles* LT = model.GetLeafTriangles(); const udword* Indices = model.GetIndices(); // Loop through touched leaves while(Nb--) { const LeafTriangles& CurrentLeaf = LT[*Touched++]; // Each leaf box has a set of triangles udword NbTris = CurrentLeaf.GetNbTriangles(); if(Indices) { const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()]; // Loop through triangles and test each of them while(NbTris--) { udword TriangleIndex = *T++; LSS_PRIM(TriangleIndex, OPC_CONTACT) } } else { udword BaseIndex = CurrentLeaf.GetTriangleIndex(); // Loop through triangles and test each of them while(NbTris--) { udword TriangleIndex = BaseIndex++; LSS_PRIM(TriangleIndex, OPC_CONTACT) } } } } return true; } ode-0.16/OPCODE/OPC_VolumeCollider.cpp0000664000175200017520000001114313403272463014245 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* * OPCODE - Optimized Collision Detection * Copyright (C) 2001 Pierre Terdiman * Homepage: http://www.codercorner.com/Opcode.htm */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains base volume collider class. * \file OPC_VolumeCollider.cpp * \author Pierre Terdiman * \date June, 2, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains the abstract class for volume colliders. * * \class VolumeCollider * \author Pierre Terdiman * \version 1.3 * \date June, 2, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Precompiled Header #include "Stdafx.h" using namespace Opcode; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Constructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// VolumeCollider::VolumeCollider() : mTouchedPrimitives (null), mNbVolumeBVTests (0), mNbVolumePrimTests (0) { } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Destructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// VolumeCollider::~VolumeCollider() { mTouchedPrimitives = null; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Validates current settings. You should call this method after all the settings / callbacks have been defined for a collider. * \return null if everything is ok, else a string describing the problem */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// const char* VolumeCollider::ValidateSettings() { return null; } // Pretty dumb way to dump - to do better - one day... #define IMPLEMENT_NOLEAFDUMP(type) \ void VolumeCollider::_Dump(const type* node) \ { \ if(node->HasPosLeaf()) mTouchedPrimitives->Add(udword(node->GetPosPrimitive())); \ else _Dump(node->GetPos()); \ \ if(ContactFound()) return; \ \ if(node->HasNegLeaf()) mTouchedPrimitives->Add(udword(node->GetNegPrimitive())); \ else _Dump(node->GetNeg()); \ } #define IMPLEMENT_LEAFDUMP(type) \ void VolumeCollider::_Dump(const type* node) \ { \ if(node->IsLeaf()) \ { \ mTouchedPrimitives->Add(udword(node->GetPrimitive())); \ } \ else \ { \ _Dump(node->GetPos()); \ \ if(ContactFound()) return; \ \ _Dump(node->GetNeg()); \ } \ } IMPLEMENT_NOLEAFDUMP(AABBNoLeafNode) IMPLEMENT_NOLEAFDUMP(AABBQuantizedNoLeafNode) IMPLEMENT_LEAFDUMP(AABBCollisionNode) IMPLEMENT_LEAFDUMP(AABBQuantizedNode) ode-0.16/OPCODE/OPC_MeshInterface.cpp0000664000175200017520000004135413403272463014044 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* * OPCODE - Optimized Collision Detection * Copyright (C) 2001 Pierre Terdiman * Homepage: http://www.codercorner.com/Opcode.htm */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains a mesh interface. * \file OPC_MeshInterface.cpp * \author Pierre Terdiman * \date November, 27, 2002 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * This structure holds 3 vertex-pointers. It's mainly used by collision callbacks so that the app doesn't have * to return 3 vertices to OPCODE (36 bytes) but only 3 pointers (12 bytes). It seems better but I never profiled * the alternative. * * \class VertexPointers * \author Pierre Terdiman * \version 1.3 * \date March, 20, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * This class is an interface between us and user-defined meshes. Meshes can be defined in a lot of ways, and here we * try to support most of them. * * Basically you have two options: * - callbacks, if OPC_USE_CALLBACKS is defined in OPC_Settings.h. * - else pointers. * * If using pointers, you can also use strides or not. Strides are used when OPC_USE_STRIDE is defined. * * * CALLBACKS: * * Using callbacks is the most generic way to feed OPCODE with your meshes. Indeed, you just have to give * access to three vertices at the end of the day. It's up to you to fetch them from your database, using * whatever method you want. Hence your meshes can lie in system memory or AGP, be indexed or not, use 16 * or 32-bits indices, you can decompress them on-the-fly if needed, etc. On the other hand, a callback is * called each time OPCODE needs access to a particular triangle, so there might be a slight overhead. * * To make things clear: geometry & topology are NOT stored in the collision system, * in order to save some ram. So, when the system needs them to perform accurate intersection * tests, you're requested to provide the triangle-vertices corresponding to a given face index. * * Ex: * * \code * static void ColCallback(udword triangle_index, VertexPointers& triangle, udword user_data) * { * // Get back Mesh0 or Mesh1 (you also can use 2 different callbacks) * Mesh* MyMesh = (Mesh*)user_data; * // Get correct triangle in the app-controlled database * const Triangle* Tri = MyMesh->GetTriangle(triangle_index); * // Setup pointers to vertices for the collision system * triangle.Vertex[0] = MyMesh->GetVertex(Tri->mVRef[0]); * triangle.Vertex[1] = MyMesh->GetVertex(Tri->mVRef[1]); * triangle.Vertex[2] = MyMesh->GetVertex(Tri->mVRef[2]); * } * * // Setup callbacks * MeshInterface0->SetCallback(ColCallback, udword(Mesh0)); * MeshInterface1->SetCallback(ColCallback, udword(Mesh1)); * \endcode * * Of course, you should make this callback as fast as possible. And you're also not supposed * to modify the geometry *after* the collision trees have been built. The alternative was to * store the geometry & topology in the collision system as well (as in RAPID) but we have found * this approach to waste a lot of ram in many cases. * * * POINTERS: * * If you're internally using the following canonical structures: * - a vertex made of three 32-bits floating point values * - a triangle made of three 32-bits integer vertex references * ...then you may want to use pointers instead of callbacks. This is the same, except OPCODE will directly * use provided pointers to access the topology and geometry, without using a callback. It might be faster, * but probably not as safe. Pointers have been introduced in OPCODE 1.2. * * Ex: * * \code * // Setup pointers * MeshInterface0->SetPointers(Mesh0->GetFaces(), Mesh0->GetVerts()); * MeshInterface1->SetPointers(Mesh1->GetFaces(), Mesh1->GetVerts()); * \endcode * * * STRIDES: * * If your vertices are D3D-like entities interleaving a position, a normal and/or texture coordinates * (i.e. if your vertices are FVFs), you might want to use a vertex stride to skip extra data OPCODE * doesn't need. Using a stride shouldn't be notably slower than not using it, but it might increase * cache misses. Please also note that you *shouldn't* read from AGP or video-memory buffers ! * * * In any case, compilation flags are here to select callbacks/pointers/strides at compile time, so * choose what's best for your application. All of this has been wrapped into this MeshInterface. * * \class MeshInterface * \author Pierre Terdiman * \version 1.3 * \date November, 27, 2002 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Precompiled Header #include "Stdafx.h" using namespace Opcode; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Constructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// MeshInterface::MeshInterface() : mNbTris (0), mNbVerts (0), #ifdef OPC_USE_CALLBACKS mUserData (null), mObjCallback (null), mExUserData (null), mObjExCallback (null), #else #ifdef OPC_USE_STRIDE mTriStride (sizeof(IndexedTriangle)), mVertexStride (sizeof(Point)), mFetchTriangle (&MeshInterface::FetchTriangleFromSingles), mFetchExTriangle (&MeshInterface::FetchExTriangleFromSingles), #endif mTris (null), mVerts (null) #endif { } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Destructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// MeshInterface::~MeshInterface() { } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Checks the mesh interface is valid, i.e. things have been setup correctly. * \return true if valid */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool MeshInterface::IsValid() const { if(!mNbTris || !mNbVerts) return false; #ifdef OPC_USE_CALLBACKS if(!mObjCallback) return false; #else if(!mTris || !mVerts) return false; #endif return true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Checks the mesh itself is valid. * Currently we only look for degenerate faces. * \return number of degenerate faces */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// udword MeshInterface::CheckTopology() const { // Check topology. If the model contains degenerate faces, collision report can be wrong in some cases. // e.g. it happens with the standard MAX teapot. So clean your meshes first... If you don't have a mesh cleaner // you can try this: www.codercorner.com/Consolidation.zip udword NbDegenerate = 0; VertexPointers VP; ConversionArea VC; // Using callbacks, we don't have access to vertex indices. Nevertheless we still can check for // redundant vertex pointers, which cover all possibilities (callbacks/pointers/strides). for(udword i=0;imVRef[0] * VertexStride); vp.Vertex[1] = (const Point*)(((ubyte*)Verts) + T->mVRef[1] * VertexStride); vp.Vertex[2] = (const Point*)(((ubyte*)Verts) + T->mVRef[2] * VertexStride); } void MeshInterface::FetchTriangleFromDoubles(VertexPointers& vp, udword index, ConversionArea vc) const { const IndexedTriangle* T = (const IndexedTriangle*)(((ubyte*)mTris) + index * mTriStride); const Point* Verts = GetVerts(); udword VertexStride = GetVertexStride(); for (int i = 0; i < 3; i++){ const double* v = (const double*)(((ubyte*)Verts) + T->mVRef[i] * VertexStride); vc[i].x = (float)v[0]; vc[i].y = (float)v[1]; vc[i].z = (float)v[2]; vp.Vertex[i] = &vc[i]; } } void MeshInterface::FetchExTriangleFromSingles(VertexPointersEx& vpe, udword index, ConversionArea vc) const { const IndexedTriangle* T = (const IndexedTriangle*)(((ubyte*)mTris) + index * mTriStride); const Point* Verts = GetVerts(); udword VertexStride = GetVertexStride(); dTriIndex VertIndex0 = T->mVRef[0]; vpe.Index[0] = VertIndex0; vpe.vp.Vertex[0] = (const Point*)(((ubyte*)Verts) + VertIndex0 * VertexStride); dTriIndex VertIndex1 = T->mVRef[1]; vpe.Index[1] = VertIndex1; vpe.vp.Vertex[1] = (const Point*)(((ubyte*)Verts) + VertIndex1 * VertexStride); dTriIndex VertIndex2 = T->mVRef[2]; vpe.Index[2] = VertIndex2; vpe.vp.Vertex[2] = (const Point*)(((ubyte*)Verts) + VertIndex2 * VertexStride); } void MeshInterface::FetchExTriangleFromDoubles(VertexPointersEx& vpe, udword index, ConversionArea vc) const { const IndexedTriangle* T = (const IndexedTriangle*)(((ubyte*)mTris) + index * mTriStride); const Point* Verts = GetVerts(); udword VertexStride = GetVertexStride(); for (int i = 0; i < 3; i++){ dTriIndex VertIndex = T->mVRef[i]; vpe.Index[i] = VertIndex; const double* v = (const double*)(((ubyte*)Verts) + VertIndex * VertexStride); vc[i].x = (float)v[0]; vc[i].y = (float)v[1]; vc[i].z = (float)v[2]; vpe.vp.Vertex[i] = &vc[i]; } } #endif #endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Remaps client's mesh according to a permutation. * \param nb_indices [in] number of indices in the permutation (will be checked against number of triangles) * \param permutation [in] list of triangle indices * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool MeshInterface::RemapClient(udword nb_indices, const dTriIndex* permutation) const { // Checkings if(!nb_indices || !permutation) return false; if(nb_indices!=mNbTris) return false; #ifdef OPC_USE_CALLBACKS // We can't really do that using callbacks return false; #else IndexedTriangle* Tmp = new IndexedTriangle[mNbTris]; CHECKALLOC(Tmp); #ifdef OPC_USE_STRIDE udword Stride = mTriStride; #else udword Stride = sizeof(IndexedTriangle); #endif for(udword i=0;i RayCollider, AABBSphereCollider => SphereCollider - the sphere query now only returns a list of faces (extra info discarded). On the other hand it's a lot faster. - OBB, AABB and planes queries. Original OBB and AABB queries contributed by Erwin de Vries. - cosmetic changes in OPC_BoxBoxOverlap.h contributed by Gottfried Chen - some inlining problems fixed - faster ray-mesh tests using the separating axis theorem - new split value in AABB tree construction (contributed by Igor Kravtchenko). Provides faster queries most of the time. - improved temporal coherence for sphere & AABB queries (works in "All contacts" mode) Notes: - Everything in the "Ice code" directory (in VC++) is basically copy-pasted from my engine, with a lot of code removed until there was no link error anymore. Don't expect those files to be cute or anything, they've never been meant to be released and they're often updated/modified/messy. - Some experimental features have been removed as well. Else I would never have released the 1.2... - Not as polished/optimal as I would like it to be, but that's life. I promised myself to release it before october 2002 (one YEAR later ?!).... That's the only reason why it's there. - Some people reported ColDet was faster. Uh, come on. They were using Opcode in "All contacts" mode whereas ColDet was doing "first contact"... OPCODE distribution 1.1 (october 2001) ----------------------- New in Opcode 1.1: - stabbing queries - sphere queries - abtract base class for colliders - settings validation methods - compilation flags now grouped in OPC_Settings.h - smaller files, new VC++ virtual dirs (cleaner) Notes: - "override(baseclass)" is a personal cosmetic thing. It's the same as "virtual", but provides more info. - I code in 1600*1200, so some lines may look a bit long.. - This version is not as polished as the previous one due to lack of time. The stabbing & sphere queries can still be optimized: for example by trying other atomic overlap tests. I'm using my first ray-AABB code, but the newer one seems better. Tim Schröder's one is good as well. See: www.codercorner.com/RayAABB.cpp - The trees can easily be compressed even more, I save this for later (lack of time, lack of time!) - I removed various tests before releasing this one: - a separation line, a.k.a. "front" in QuickCD, because gains were unclear - distance queries in a PQP style, because it was way too slow - support for deformable models, too slow as well - You can easily use Opcode to do your player-vs-world collision detection, in a Nettle/Telemachos way. If someone out there wants to donate some art / level for the cause, I'd be glad to release a demo. (current demo uses copyrighted art I'm not allowed to spread) - Sorry for the lack of real docs and/or solid examples. I just don't have enough time. OPCODE distribution 1.0 (march 2001) ----------------------- - First release =============================================================================== WHAT ? OPCODE means OPtimized COllision DEtection. So this is a collision detection package similar to RAPID. Here's a quick list of features: - C++ interface, developed for Windows systems using VC++ 6.0 - Works on arbitrary meshes (convex or non-convex), even polygon soups - Current implementation uses AABB-trees - Introduces Primitive-BV overlap tests during recursive collision queries (whereas standard libraries only rely on Primitive-Primitive and BV-BV tests) - Introduces no-leaf trees, i.e. collision trees whose leaf nodes have been removed - Supports collision queries on quantized trees (decompressed on-the-fly) - Supports "first contact" or "all contacts" modes (à la RAPID) - Uses temporal coherence for "first contact" mode (~10 to 20 times faster, useful in rigid body simulation during bisection) - Memory footprint is 7.2 times smaller than RAPID's one, which is ideal for console games with limited ram (actually, if you use the unmodified RAPID code using double precision, it's more like 13 times smaller...) - And yet it often runs faster than RAPID (according to RDTSC, sometimes more than 5 times faster when objects are deeply overlapping) - Performance is usually close to RAPID's one in close-proximity situations - Stabbing, planes & volume queries (sphere, AABB, OBB, LSS) - Sweep-and-prune - Now works with deformable meshes - Hybrid trees What it can be used for: - standard mesh-mesh collision detection (similar to RAPID, SOLID, QuickCD, PQP, ColDet...) - N-body collisions (similar to V-Collide) - camera-vs-world collisions (similar to Telemachos/Paul Nettle/Stan Melax articles) - shadow feelers to speed up lightmap computations - in-out tests to speed up voxelization processes - picking - rigid body simulation - view frustum culling - etc WHY ? - Because RAPID uses too many bytes. - Because the idea was nice... WHEN ? It's been coded in march 2001 following a thread on the GD-Algorithms list. GDAlgorithms-list mailing list GDAlgorithms-list@lists.sourceforge.net http://lists.sourceforge.net/lists/listinfo/gdalgorithms-list WHO ? Pierre Terdiman June, 1, 2003 p.terdiman@wanadoo.fr p.terdiman@codercorner.com http://www.codercorner.com http://www.codercorner.com/Opcode.htm ode-0.16/OPCODE/OPC_TreeCollider.h0000664000175200017520000003217413403272463013351 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* * OPCODE - Optimized Collision Detection * Copyright (C) 2001 Pierre Terdiman * Homepage: http://www.codercorner.com/Opcode.htm */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains code for a tree collider. * \file OPC_TreeCollider.h * \author Pierre Terdiman * \date March, 20, 2001 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Include Guard #ifndef __OPC_TREECOLLIDER_H__ #define __OPC_TREECOLLIDER_H__ //! This structure holds cached information used by the algorithm. //! Two model pointers and two colliding primitives are cached. Model pointers are assigned //! to their respective meshes, and the pair of colliding primitives is used for temporal //! coherence. That is, in case temporal coherence is enabled, those two primitives are //! tested for overlap before everything else. If they still collide, we're done before //! even entering the recursive collision code. struct OPCODE_API BVTCache : Pair { //! Constructor inline_ BVTCache() { ResetCache(); ResetCountDown(); } void ResetCache() { Model0 = null; Model1 = null; id0 = 0; id1 = 1; #ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE ! HullTest = true; SepVector.pid = 0; SepVector.qid = 0; SepVector.SV = Point(1.0f, 0.0f, 0.0f); #endif // __MESHMERIZER_H__ } #ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE ! inline_ void ResetCountDown() { CountDown = 50; } #else void ResetCountDown(){}; #endif // __MESHMERIZER_H__ const Model* Model0; //!< Model for first object const Model* Model1; //!< Model for second object #ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE ! SVCache SepVector; udword CountDown; bool HullTest; #endif // __MESHMERIZER_H__ }; class OPCODE_API AABBTreeCollider : public Collider { public: // Constructor / Destructor AABBTreeCollider(); virtual ~AABBTreeCollider(); // Generic collision query /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Generic collision query for generic OPCODE models. After the call, access the results with: * - GetContactStatus() * - GetNbPairs() * - GetPairs() * * \param cache [in] collision cache for model pointers and a colliding pair of primitives * \param world0 [in] world matrix for first object, or null * \param world1 [in] world matrix for second object, or null * \return true if success * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool Collide(BVTCache& cache, const Matrix4x4* world0=null, const Matrix4x4* world1=null); // Collision queries bool Collide(const AABBCollisionTree* tree0, const AABBCollisionTree* tree1, const Matrix4x4* world0=null, const Matrix4x4* world1=null, Pair* cache=null); bool Collide(const AABBNoLeafTree* tree0, const AABBNoLeafTree* tree1, const Matrix4x4* world0=null, const Matrix4x4* world1=null, Pair* cache=null); bool Collide(const AABBQuantizedTree* tree0, const AABBQuantizedTree* tree1, const Matrix4x4* world0=null, const Matrix4x4* world1=null, Pair* cache=null); bool Collide(const AABBQuantizedNoLeafTree* tree0, const AABBQuantizedNoLeafTree* tree1, const Matrix4x4* world0=null, const Matrix4x4* world1=null, Pair* cache=null); // Settings /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Settings: selects between full box-box tests or "SAT-lite" tests (where Class III axes are discarded) * \param flag [in] true for full tests, false for coarse tests * \see SetFullPrimBoxTest(bool flag) */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ void SetFullBoxBoxTest(bool flag) { mFullBoxBoxTest = flag; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Settings: selects between full triangle-box tests or "SAT-lite" tests (where Class III axes are discarded) * \param flag [in] true for full tests, false for coarse tests * \see SetFullBoxBoxTest(bool flag) */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ void SetFullPrimBoxTest(bool flag) { mFullPrimBoxTest = flag; } // Stats /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Stats: gets the number of BV-BV overlap tests after a collision query. * \see GetNbPrimPrimTests() * \see GetNbBVPrimTests() * \return the number of BV-BV tests performed during last query */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ udword GetNbBVBVTests() const { return mNbBVBVTests; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Stats: gets the number of Triangle-Triangle overlap tests after a collision query. * \see GetNbBVBVTests() * \see GetNbBVPrimTests() * \return the number of Triangle-Triangle tests performed during last query */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ udword GetNbPrimPrimTests() const { return mNbPrimPrimTests; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Stats: gets the number of BV-Triangle overlap tests after a collision query. * \see GetNbBVBVTests() * \see GetNbPrimPrimTests() * \return the number of BV-Triangle tests performed during last query */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ udword GetNbBVPrimTests() const { return mNbBVPrimTests; } // Data access /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Gets the number of contacts after a collision query. * \see GetContactStatus() * \see GetPairs() * \return the number of contacts / colliding pairs. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ udword GetNbPairs() const { return mPairs.GetNbEntries()>>1; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Gets the pairs of colliding triangles after a collision query. * \see GetContactStatus() * \see GetNbPairs() * \return the list of colliding pairs (triangle indices) */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline_ const Pair* GetPairs() const { return (const Pair*)mPairs.GetEntries(); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Validates current settings. You should call this method after all the settings and callbacks have been defined for a collider. * \return null if everything is ok, else a string describing the problem */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// override(Collider) const char* ValidateSettings(); protected: // Colliding pairs Container mPairs; //!< Pairs of colliding primitives // User mesh interfaces const MeshInterface* mIMesh0; //!< User-defined mesh interface for object0 const MeshInterface* mIMesh1; //!< User-defined mesh interface for object1 // Stats udword mNbBVBVTests; //!< Number of BV-BV tests udword mNbPrimPrimTests; //!< Number of Primitive-Primitive tests udword mNbBVPrimTests; //!< Number of BV-Primitive tests // Precomputed data Matrix3x3 mAR; //!< Absolute rotation matrix Matrix3x3 mR0to1; //!< Rotation from object0 to object1 Matrix3x3 mR1to0; //!< Rotation from object1 to object0 Point mT0to1; //!< Translation from object0 to object1 Point mT1to0; //!< Translation from object1 to object0 // Dequantization coeffs Point mCenterCoeff0; Point mExtentsCoeff0; Point mCenterCoeff1; Point mExtentsCoeff1; // Leaf description Point mLeafVerts[3]; //!< Triangle vertices udword mLeafIndex; //!< Triangle index // Settings bool mFullBoxBoxTest; //!< Perform full BV-BV tests (true) or SAT-lite tests (false) bool mFullPrimBoxTest; //!< Perform full Primitive-BV tests (true) or SAT-lite tests (false) // Internal methods // Standard AABB trees void _Collide(const AABBCollisionNode* b0, const AABBCollisionNode* b1); // Quantized AABB trees void _Collide(const AABBQuantizedNode* b0, const AABBQuantizedNode* b1, const Point& a, const Point& Pa, const Point& b, const Point& Pb); // No-leaf AABB trees void _CollideTriBox(const AABBNoLeafNode* b); void _CollideBoxTri(const AABBNoLeafNode* b); void _Collide(const AABBNoLeafNode* a, const AABBNoLeafNode* b); // Quantized no-leaf AABB trees void _CollideTriBox(const AABBQuantizedNoLeafNode* b); void _CollideBoxTri(const AABBQuantizedNoLeafNode* b); void _Collide(const AABBQuantizedNoLeafNode* a, const AABBQuantizedNoLeafNode* b); // Overlap tests void PrimTest(udword id0, udword id1); inline_ void PrimTestTriIndex(udword id1); inline_ void PrimTestIndexTri(udword id0); inline_ BOOL BoxBoxOverlap(const Point& ea, const Point& ca, const Point& eb, const Point& cb); inline_ BOOL TriBoxOverlap(const Point& center, const Point& extents); inline_ BOOL TriTriOverlap(const Point& V0, const Point& V1, const Point& V2, const Point& U0, const Point& U1, const Point& U2); // Init methods void InitQuery(const Matrix4x4* world0=null, const Matrix4x4* world1=null); bool CheckTemporalCoherence(Pair* cache); inline_ BOOL Setup(const MeshInterface* mi0, const MeshInterface* mi1) { mIMesh0 = mi0; mIMesh1 = mi1; if(!mIMesh0 || !mIMesh1) return FALSE; return TRUE; } }; #endif // __OPC_TREECOLLIDER_H__ ode-0.16/libccd/0000775000175200017520000000000013403273061010435 500000000000000ode-0.16/libccd/src/0000775000175200017520000000000013403273061011224 500000000000000ode-0.16/libccd/src/ccd/0000775000175200017520000000000013403273061011755 500000000000000ode-0.16/libccd/src/ccd/polytope.h0000664000175200017520000002043613403272463013733 00000000000000/*** * libccd * --------------------------------- * Copyright (c)2010 Daniel Fiser * * * This file is part of libccd. * * Distributed under the OSI-approved BSD License (the "License"); * see accompanying file BDS-LICENSE for details or see * . * * This software is distributed WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the License for more information. */ #ifndef __CCD_POLYTOPE_H__ #define __CCD_POLYTOPE_H__ #include #include #include #include #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #define CCD_PT_VERTEX 1 #define CCD_PT_EDGE 2 #define CCD_PT_FACE 3 #define __CCD_PT_EL \ int type; /*! type of element */ \ ccd_real_t dist; /*! distance from origin */ \ ccd_vec3_t witness; /*! witness point of projection of origin */ \ ccd_list_t list; /*! list of elements of same type */ /** * General polytope element. * Could be vertex, edge or triangle. */ struct _ccd_pt_el_t { __CCD_PT_EL }; typedef struct _ccd_pt_el_t ccd_pt_el_t; struct _ccd_pt_edge_t; struct _ccd_pt_face_t; /** * Polytope's vertex. */ struct _ccd_pt_vertex_t { __CCD_PT_EL int id; ccd_support_t v; ccd_list_t edges; //!< List of edges }; typedef struct _ccd_pt_vertex_t ccd_pt_vertex_t; /** * Polytope's edge. */ struct _ccd_pt_edge_t { __CCD_PT_EL ccd_pt_vertex_t *vertex[2]; //!< Reference to vertices struct _ccd_pt_face_t *faces[2]; //!< Reference to faces ccd_list_t vertex_list[2]; //!< List items in vertices' lists }; typedef struct _ccd_pt_edge_t ccd_pt_edge_t; /** * Polytope's triangle faces. */ struct _ccd_pt_face_t { __CCD_PT_EL ccd_pt_edge_t *edge[3]; //!< Reference to surrounding edges }; typedef struct _ccd_pt_face_t ccd_pt_face_t; /** * Struct containing polytope. */ struct _ccd_pt_t { ccd_list_t vertices; //!< List of vertices ccd_list_t edges; //!< List of edges ccd_list_t faces; //!< List of faces ccd_pt_el_t *nearest; ccd_real_t nearest_dist; int nearest_type; }; typedef struct _ccd_pt_t ccd_pt_t; void ccdPtInit(ccd_pt_t *pt); void ccdPtDestroy(ccd_pt_t *pt); /** * Returns vertices surrounding given triangle face. */ _ccd_inline void ccdPtFaceVec3(const ccd_pt_face_t *face, ccd_vec3_t **a, ccd_vec3_t **b, ccd_vec3_t **c); _ccd_inline void ccdPtFaceVertices(const ccd_pt_face_t *face, ccd_pt_vertex_t **a, ccd_pt_vertex_t **b, ccd_pt_vertex_t **c); _ccd_inline void ccdPtFaceEdges(const ccd_pt_face_t *f, ccd_pt_edge_t **a, ccd_pt_edge_t **b, ccd_pt_edge_t **c); _ccd_inline void ccdPtEdgeVec3(const ccd_pt_edge_t *e, ccd_vec3_t **a, ccd_vec3_t **b); _ccd_inline void ccdPtEdgeVertices(const ccd_pt_edge_t *e, ccd_pt_vertex_t **a, ccd_pt_vertex_t **b); _ccd_inline void ccdPtEdgeFaces(const ccd_pt_edge_t *e, ccd_pt_face_t **f1, ccd_pt_face_t **f2); /** * Adds vertex to polytope and returns pointer to newly created vertex. */ ccd_pt_vertex_t *ccdPtAddVertex(ccd_pt_t *pt, const ccd_support_t *v); _ccd_inline ccd_pt_vertex_t *ccdPtAddVertexCoords(ccd_pt_t *pt, ccd_real_t x, ccd_real_t y, ccd_real_t z); /** * Adds edge to polytope. */ ccd_pt_edge_t *ccdPtAddEdge(ccd_pt_t *pt, ccd_pt_vertex_t *v1, ccd_pt_vertex_t *v2); /** * Adds face to polytope. */ ccd_pt_face_t *ccdPtAddFace(ccd_pt_t *pt, ccd_pt_edge_t *e1, ccd_pt_edge_t *e2, ccd_pt_edge_t *e3); /** * Deletes vertex from polytope. * Returns 0 on success, -1 otherwise. */ _ccd_inline int ccdPtDelVertex(ccd_pt_t *pt, ccd_pt_vertex_t *); _ccd_inline int ccdPtDelEdge(ccd_pt_t *pt, ccd_pt_edge_t *); _ccd_inline int ccdPtDelFace(ccd_pt_t *pt, ccd_pt_face_t *); /** * Recompute distances from origin for all elements in pt. */ void ccdPtRecomputeDistances(ccd_pt_t *pt); /** * Returns nearest element to origin. */ ccd_pt_el_t *ccdPtNearest(ccd_pt_t *pt); void ccdPtDumpSVT(ccd_pt_t *pt, const char *fn); void ccdPtDumpSVT2(ccd_pt_t *pt, FILE *); /**** INLINES ****/ _ccd_inline ccd_pt_vertex_t *ccdPtAddVertexCoords(ccd_pt_t *pt, ccd_real_t x, ccd_real_t y, ccd_real_t z) { ccd_support_t s; ccdVec3Set(&s.v, x, y, z); return ccdPtAddVertex(pt, &s); } _ccd_inline int ccdPtDelVertex(ccd_pt_t *pt, ccd_pt_vertex_t *v) { // test if any edge is connected to this vertex if (!ccdListEmpty(&v->edges)) return -1; // delete vertex from main list ccdListDel(&v->list); if ((void *)pt->nearest == (void *)v){ pt->nearest = NULL; } free(v); return 0; } _ccd_inline int ccdPtDelEdge(ccd_pt_t *pt, ccd_pt_edge_t *e) { // text if any face is connected to this edge (faces[] is always // aligned to lower indices) if (e->faces[0] != NULL) return -1; // disconnect edge from lists of edges in vertex struct ccdListDel(&e->vertex_list[0]); ccdListDel(&e->vertex_list[1]); // disconnect edge from main list ccdListDel(&e->list); if ((void *)pt->nearest == (void *)e){ pt->nearest = NULL; } free(e); return 0; } _ccd_inline int ccdPtDelFace(ccd_pt_t *pt, ccd_pt_face_t *f) { ccd_pt_edge_t *e; size_t i; // remove face from edges' recerence lists for (i = 0; i < 3; i++){ e = f->edge[i]; if (e->faces[0] == f){ e->faces[0] = e->faces[1]; } e->faces[1] = NULL; } // remove face from list of all faces ccdListDel(&f->list); if ((void *)pt->nearest == (void *)f){ pt->nearest = NULL; } free(f); return 0; } _ccd_inline void ccdPtFaceVec3(const ccd_pt_face_t *face, ccd_vec3_t **a, ccd_vec3_t **b, ccd_vec3_t **c) { *a = &face->edge[0]->vertex[0]->v.v; *b = &face->edge[0]->vertex[1]->v.v; if (face->edge[1]->vertex[0] != face->edge[0]->vertex[0] && face->edge[1]->vertex[0] != face->edge[0]->vertex[1]){ *c = &face->edge[1]->vertex[0]->v.v; }else{ *c = &face->edge[1]->vertex[1]->v.v; } } _ccd_inline void ccdPtFaceVertices(const ccd_pt_face_t *face, ccd_pt_vertex_t **a, ccd_pt_vertex_t **b, ccd_pt_vertex_t **c) { *a = face->edge[0]->vertex[0]; *b = face->edge[0]->vertex[1]; if (face->edge[1]->vertex[0] != face->edge[0]->vertex[0] && face->edge[1]->vertex[0] != face->edge[0]->vertex[1]){ *c = face->edge[1]->vertex[0]; }else{ *c = face->edge[1]->vertex[1]; } } _ccd_inline void ccdPtFaceEdges(const ccd_pt_face_t *f, ccd_pt_edge_t **a, ccd_pt_edge_t **b, ccd_pt_edge_t **c) { *a = f->edge[0]; *b = f->edge[1]; *c = f->edge[2]; } _ccd_inline void ccdPtEdgeVec3(const ccd_pt_edge_t *e, ccd_vec3_t **a, ccd_vec3_t **b) { *a = &e->vertex[0]->v.v; *b = &e->vertex[1]->v.v; } _ccd_inline void ccdPtEdgeVertices(const ccd_pt_edge_t *e, ccd_pt_vertex_t **a, ccd_pt_vertex_t **b) { *a = e->vertex[0]; *b = e->vertex[1]; } _ccd_inline void ccdPtEdgeFaces(const ccd_pt_edge_t *e, ccd_pt_face_t **f1, ccd_pt_face_t **f2) { *f1 = e->faces[0]; *f2 = e->faces[1]; } #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif /* __CCD_POLYTOPE_H__ */ ode-0.16/libccd/src/ccd/compiler.h0000664000175200017520000000311313403272463013663 00000000000000/*** * libccd * --------------------------------- * Copyright (c)2010 Daniel Fiser * * * This file is part of libccd. * * Distributed under the OSI-approved BSD License (the "License"); * see accompanying file BDS-LICENSE for details or see * . * * This software is distributed WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the License for more information. */ #ifndef __CCD_COMPILER_H__ #define __CCD_COMPILER_H__ #include #define ccd_offsetof(TYPE, MEMBER) offsetof(TYPE, MEMBER) #define ccd_container_of(ptr, type, member) \ (type *)( (char *)ptr - ccd_offsetof(type, member)) /** * Marks inline function. */ #ifdef __GNUC__ /*# define _ccd_inline static inline __attribute__((always_inline))*/ # define _ccd_inline static inline #else /* __GNUC__ */ # define _ccd_inline static __inline #endif /* __GNUC__ */ /** * __prefetch(x) - prefetches the cacheline at "x" for read * __prefetchw(x) - prefetches the cacheline at "x" for write */ #ifdef __GNUC__ # define _ccd_prefetch(x) __builtin_prefetch(x) # define _ccd_prefetchw(x) __builtin_prefetch(x,1) #else /* __GNUC__ */ # define _ccd_prefetch(x) ((void)0) # define _ccd_prefetchw(x) ((void)0) #endif /* __GNUC__ */ #ifdef __ICC /* disable unused parameter warning */ # pragma warning(disable:869) /* disable annoying "operands are evaluated in unspecified order" warning */ # pragma warning(disable:981) #endif /* __ICC */ #endif /* __CCD_COMPILER_H__ */ ode-0.16/libccd/src/ccd/ccd.h0000664000175200017520000001143213403272463012605 00000000000000/*** * libccd * --------------------------------- * Copyright (c)2010,2011 Daniel Fiser * * * This file is part of libccd. * * Distributed under the OSI-approved BSD License (the "License"); * see accompanying file BDS-LICENSE for details or see * . * * This software is distributed WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the License for more information. */ #ifndef __CCD_H__ #define __CCD_H__ #include #include #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /** * Type of *support* function that takes pointer to 3D object and direction * and returns (via vec argument) furthest point from object in specified * direction. */ typedef void (*ccd_support_fn)(const void *obj, const ccd_vec3_t *dir, ccd_vec3_t *vec); /** * Returns (via dir argument) first direction vector that will be used in * initialization of algorithm. */ typedef void (*ccd_first_dir_fn)(const void *obj1, const void *obj2, ccd_vec3_t *dir); /** * Returns (via center argument) geometric center (some point near center) * of given object. */ typedef void (*ccd_center_fn)(const void *obj1, ccd_vec3_t *center); /** * Main structure of CCD algorithm. */ struct _ccd_t { ccd_first_dir_fn first_dir; /*!< Returns initial direction where first !< support point will be searched*/ ccd_support_fn support1; /*!< Function that returns support point of !< first object*/ ccd_support_fn support2; /*!< Function that returns support point of !< second object*/ ccd_center_fn center1; /*!< Function that returns geometric center of !< first object*/ ccd_center_fn center2; /*!< Function that returns geometric center of !< second object*/ unsigned long max_iterations; /*!< Maximal number of iterations*/ ccd_real_t epa_tolerance; ccd_real_t mpr_tolerance; /*!< Boundary tolerance for MPR algorithm*/ }; typedef struct _ccd_t ccd_t; /** * Default first direction. */ void ccdFirstDirDefault(const void *o1, const void *o2, ccd_vec3_t *dir); #define CCD_INIT(ccd) \ do { \ (ccd)->first_dir = ccdFirstDirDefault; \ (ccd)->support1 = NULL; \ (ccd)->support2 = NULL; \ (ccd)->center1 = NULL; \ (ccd)->center2 = NULL; \ \ (ccd)->max_iterations = (unsigned long)-1; \ (ccd)->epa_tolerance = CCD_REAL(0.0001); \ (ccd)->mpr_tolerance = CCD_REAL(0.0001); \ } while(0) /** * Returns true if two given objects interest. */ int ccdGJKIntersect(const void *obj1, const void *obj2, const ccd_t *ccd); /** * This function computes separation vector of two objects. Separation * vector is minimal translation of obj2 to get obj1 and obj2 speparated * (without intersection). * Returns 0 if obj1 and obj2 intersect and sep is filled with translation * vector. If obj1 and obj2 don't intersect -1 is returned. */ int ccdGJKSeparate(const void *obj1, const void *obj2, const ccd_t *ccd, ccd_vec3_t *sep); /** * Computes penetration of obj2 into obj1. * Depth of penetration, direction and position is returned. It means that * if obj2 is translated by distance depth in direction dir objects will * have touching contact, pos should be position in global coordinates * where force should take a place. * * CCD+EPA algorithm is used. * * Returns 0 if obj1 and obj2 intersect and depth, dir and pos are filled * if given non-NULL pointers. * If obj1 and obj2 don't intersect -1 is returned. */ int ccdGJKPenetration(const void *obj1, const void *obj2, const ccd_t *ccd, ccd_real_t *depth, ccd_vec3_t *dir, ccd_vec3_t *pos); /** * Returns true if two given objects intersect - MPR algorithm is used. */ int ccdMPRIntersect(const void *obj1, const void *obj2, const ccd_t *ccd); /** * Computes penetration of obj2 into obj1. * Depth of penetration, direction and position is returned, i.e. if obj2 * is translated by computed depth in resulting direction obj1 and obj2 * would have touching contact. Position is point in global coordinates * where force should be take a place. * * Minkowski Portal Refinement algorithm is used (MPR, a.k.a. XenoCollide, * see Game Programming Gem 7). * * Returns 0 if obj1 and obj2 intersect, otherwise -1 is returned. */ int ccdMPRPenetration(const void *obj1, const void *obj2, const ccd_t *ccd, ccd_real_t *depth, ccd_vec3_t *dir, ccd_vec3_t *pos); #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif /* __CCD_H__ */ ode-0.16/libccd/src/ccd/precision.h.in0000664000175200017520000000036213403272463014454 00000000000000#ifndef __CCD_PRECISION_H__ #define __CCD_PRECISION_H__ /* define either CCD_SINGLE or CCD_DOUBLE */ #if defined(CCD_IDESINGLE) #define CCD_SINGLE #elif defined(CCD_IDEDOUBLE) #define CCD_DOUBLE #else #define @CCD_PRECISION@ #endif #endif ode-0.16/libccd/src/ccd/simplex.h0000664000175200017520000000531313403272463013536 00000000000000/*** * libccd * --------------------------------- * Copyright (c)2010 Daniel Fiser * * * This file is part of libccd. * * Distributed under the OSI-approved BSD License (the "License"); * see accompanying file BDS-LICENSE for details or see * . * * This software is distributed WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the License for more information. */ #ifndef __CCD_SIMPLEX_H__ #define __CCD_SIMPLEX_H__ #include #include #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ struct _ccd_simplex_t { ccd_support_t ps[4]; int last; /*!< index of last added point*/ }; typedef struct _ccd_simplex_t ccd_simplex_t; _ccd_inline void ccdSimplexInit(ccd_simplex_t *s); _ccd_inline int ccdSimplexSize(const ccd_simplex_t *s); _ccd_inline const ccd_support_t *ccdSimplexLast(const ccd_simplex_t *s); _ccd_inline const ccd_support_t *ccdSimplexPoint(const ccd_simplex_t *s, int idx); _ccd_inline ccd_support_t *ccdSimplexPointW(ccd_simplex_t *s, int idx); _ccd_inline void ccdSimplexAdd(ccd_simplex_t *s, const ccd_support_t *v); _ccd_inline void ccdSimplexSet(ccd_simplex_t *s, size_t pos, const ccd_support_t *a); _ccd_inline void ccdSimplexSetSize(ccd_simplex_t *s, int size); _ccd_inline void ccdSimplexSwap(ccd_simplex_t *s, size_t pos1, size_t pos2); /**** INLINES ****/ _ccd_inline void ccdSimplexInit(ccd_simplex_t *s) { s->last = -1; } _ccd_inline int ccdSimplexSize(const ccd_simplex_t *s) { return s->last + 1; } _ccd_inline const ccd_support_t *ccdSimplexLast(const ccd_simplex_t *s) { return ccdSimplexPoint(s, s->last); } _ccd_inline const ccd_support_t *ccdSimplexPoint(const ccd_simplex_t *s, int idx) { /* here is no check on boundaries */ return &s->ps[idx]; } _ccd_inline ccd_support_t *ccdSimplexPointW(ccd_simplex_t *s, int idx) { return &s->ps[idx]; } _ccd_inline void ccdSimplexAdd(ccd_simplex_t *s, const ccd_support_t *v) { /* here is no check on boundaries in sake of speed */ ++s->last; ccdSupportCopy(s->ps + s->last, v); } _ccd_inline void ccdSimplexSet(ccd_simplex_t *s, size_t pos, const ccd_support_t *a) { ccdSupportCopy(s->ps + pos, a); } _ccd_inline void ccdSimplexSetSize(ccd_simplex_t *s, int size) { s->last = size - 1; } _ccd_inline void ccdSimplexSwap(ccd_simplex_t *s, size_t pos1, size_t pos2) { ccd_support_t supp; ccdSupportCopy(&supp, &s->ps[pos1]); ccdSupportCopy(&s->ps[pos1], &s->ps[pos2]); ccdSupportCopy(&s->ps[pos2], &supp); } #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif /* __CCD_SIMPLEX_H__ */ ode-0.16/libccd/src/ccd/dbg.h0000664000175200017520000000326113403272463012611 00000000000000/*** * libccd * --------------------------------- * Copyright (c)2010 Daniel Fiser * * * This file is part of libccd. * * Distributed under the OSI-approved BSD License (the "License"); * see accompanying file BDS-LICENSE for details or see * . * * This software is distributed WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the License for more information. */ #ifndef __CCD_DBG_H__ #define __CCD_DBG_H__ /** * Some macros which can be used for printing debug info to stderr if macro * NDEBUG not defined. * * DBG_PROLOGUE can be specified as string and this string will be * prepended to output text */ #ifndef NDEBUG #include #ifndef DBG_PROLOGUE # define DBG_PROLOGUE #endif # define DBG(format, ...) do { \ fprintf(stderr, DBG_PROLOGUE "%s :: " format "\n", __func__, ## __VA_ARGS__); \ fflush(stderr); \ } while (0) # define DBG2(str) do { \ fprintf(stderr, DBG_PROLOGUE "%s :: " str "\n", __func__); \ fflush(stderr); \ } while (0) # define DBG_VEC3(vec, prefix) do {\ fprintf(stderr, DBG_PROLOGUE "%s :: %s[%lf %lf %lf]\n", \ __func__, prefix, ccdVec3X(vec), ccdVec3Y(vec), ccdVec3Z(vec)); \ fflush(stderr); \ } while (0) /* # define DBG_VEC3(vec, prefix) do {\ fprintf(stderr, DBG_PROLOGUE "%s :: %s[%.20lf %.20lf %.20lf]\n", \ __func__, prefix, ccdVec3X(vec), ccdVec3Y(vec), ccdVec3Z(vec)); \ fflush(stderr); \ } while (0) */ #else # define DBG(format, ...) # define DBG2(str) # define DBG_VEC3(v, prefix) #endif #endif /* __CCD_DBG_H__ */ ode-0.16/libccd/src/ccd/alloc.h0000664000175200017520000000256313403272463013153 00000000000000/*** * libccd * --------------------------------- * Copyright (c)2010 Daniel Fiser * * * This file is part of libccd. * * Distributed under the OSI-approved BSD License (the "License"); * see accompanying file BDS-LICENSE for details or see * . * * This software is distributed WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the License for more information. */ #ifndef __CCD_ALLOC_H__ #define __CCD_ALLOC_H__ #include #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /** * Functions and macros required for memory allocation. */ /* Memory allocation: */ #define __CCD_ALLOC_MEMORY(type, ptr_old, size) \ (type *)ccdRealloc((void *)ptr_old, (size)) /** Allocate memory for one element of type. */ #define CCD_ALLOC(type) \ __CCD_ALLOC_MEMORY(type, NULL, sizeof(type)) /** Allocate memory for array of elements of type type. */ #define CCD_ALLOC_ARR(type, num_elements) \ __CCD_ALLOC_MEMORY(type, NULL, sizeof(type) * (num_elements)) #define CCD_REALLOC_ARR(ptr, type, num_elements) \ __CCD_ALLOC_MEMORY(type, ptr, sizeof(type) * (num_elements)) void *ccdRealloc(void *ptr, size_t size); #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif /* __CCD_ALLOC_H__ */ ode-0.16/libccd/src/ccd/quat.h0000664000175200017520000001301713403272463013027 00000000000000/*** * libccd * --------------------------------- * Copyright (c)2010 Daniel Fiser * * * This file is part of libccd. * * Distributed under the OSI-approved BSD License (the "License"); * see accompanying file BDS-LICENSE for details or see * . * * This software is distributed WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the License for more information. */ #ifndef __CCD_QUAT_H__ #define __CCD_QUAT_H__ #include #include #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ struct _ccd_quat_t { ccd_real_t q[4]; //!< x, y, z, w }; typedef struct _ccd_quat_t ccd_quat_t; #define CCD_QUAT(name, x, y, z, w) \ ccd_quat_t name = { {x, y, z, w} } _ccd_inline ccd_real_t ccdQuatLen2(const ccd_quat_t *q); _ccd_inline ccd_real_t ccdQuatLen(const ccd_quat_t *q); _ccd_inline void ccdQuatSet(ccd_quat_t *q, ccd_real_t x, ccd_real_t y, ccd_real_t z, ccd_real_t w); _ccd_inline void ccdQuatCopy(ccd_quat_t *dest, const ccd_quat_t *src); _ccd_inline int ccdQuatNormalize(ccd_quat_t *q); _ccd_inline void ccdQuatSetAngleAxis(ccd_quat_t *q, ccd_real_t angle, const ccd_vec3_t *axis); _ccd_inline void ccdQuatScale(ccd_quat_t *q, ccd_real_t k); /** * q = q * q2 */ _ccd_inline void ccdQuatMul(ccd_quat_t *q, const ccd_quat_t *q2); /** * q = a * b */ _ccd_inline void ccdQuatMul2(ccd_quat_t *q, const ccd_quat_t *a, const ccd_quat_t *b); /** * Inverts quaternion. * Returns 0 on success. */ _ccd_inline int ccdQuatInvert(ccd_quat_t *q); _ccd_inline int ccdQuatInvert2(ccd_quat_t *dest, const ccd_quat_t *src); /** * Rotate vector v by quaternion q. */ _ccd_inline void ccdQuatRotVec(ccd_vec3_t *v, const ccd_quat_t *q); /**** INLINES ****/ _ccd_inline ccd_real_t ccdQuatLen2(const ccd_quat_t *q) { ccd_real_t len; len = q->q[0] * q->q[0]; len += q->q[1] * q->q[1]; len += q->q[2] * q->q[2]; len += q->q[3] * q->q[3]; return len; } _ccd_inline ccd_real_t ccdQuatLen(const ccd_quat_t *q) { return CCD_SQRT(ccdQuatLen2(q)); } _ccd_inline void ccdQuatSet(ccd_quat_t *q, ccd_real_t x, ccd_real_t y, ccd_real_t z, ccd_real_t w) { q->q[0] = x; q->q[1] = y; q->q[2] = z; q->q[3] = w; } _ccd_inline void ccdQuatCopy(ccd_quat_t *dest, const ccd_quat_t *src) { *dest = *src; } _ccd_inline int ccdQuatNormalize(ccd_quat_t *q) { ccd_real_t len = ccdQuatLen(q); if (len < CCD_EPS) return 0; ccdQuatScale(q, CCD_ONE / len); return 1; } _ccd_inline void ccdQuatSetAngleAxis(ccd_quat_t *q, ccd_real_t angle, const ccd_vec3_t *axis) { ccd_real_t a, x, y, z, n, s; a = angle/2; x = ccdVec3X(axis); y = ccdVec3Y(axis); z = ccdVec3Z(axis); n = CCD_SQRT(x*x + y*y + z*z); // axis==0? (treat this the same as angle==0 with an arbitrary axis) if (n < CCD_EPS){ q->q[0] = q->q[1] = q->q[2] = CCD_ZERO; q->q[3] = CCD_ONE; }else{ s = sin(a)/n; q->q[3] = cos(a); q->q[0] = x*s; q->q[1] = y*s; q->q[2] = z*s; ccdQuatNormalize(q); } } _ccd_inline void ccdQuatScale(ccd_quat_t *q, ccd_real_t k) { size_t i; for (i = 0; i < 4; i++) q->q[i] *= k; } _ccd_inline void ccdQuatMul(ccd_quat_t *q, const ccd_quat_t *q2) { ccd_quat_t a; ccdQuatCopy(&a, q); ccdQuatMul2(q, &a, q2); } _ccd_inline void ccdQuatMul2(ccd_quat_t *q, const ccd_quat_t *a, const ccd_quat_t *b) { q->q[0] = a->q[3] * b->q[0] + a->q[0] * b->q[3] + a->q[1] * b->q[2] - a->q[2] * b->q[1]; q->q[1] = a->q[3] * b->q[1] + a->q[1] * b->q[3] - a->q[0] * b->q[2] + a->q[2] * b->q[0]; q->q[2] = a->q[3] * b->q[2] + a->q[2] * b->q[3] + a->q[0] * b->q[1] - a->q[1] * b->q[0]; q->q[3] = a->q[3] * b->q[3] - a->q[0] * b->q[0] - a->q[1] * b->q[1] - a->q[2] * b->q[2]; } _ccd_inline int ccdQuatInvert(ccd_quat_t *q) { ccd_real_t len2 = ccdQuatLen2(q); if (len2 < CCD_EPS) return -1; len2 = CCD_ONE / len2; q->q[0] = -q->q[0] * len2; q->q[1] = -q->q[1] * len2; q->q[2] = -q->q[2] * len2; q->q[3] = q->q[3] * len2; return 0; } _ccd_inline int ccdQuatInvert2(ccd_quat_t *dest, const ccd_quat_t *src) { ccdQuatCopy(dest, src); return ccdQuatInvert(dest); } _ccd_inline void ccdQuatRotVec(ccd_vec3_t *v, const ccd_quat_t *q) { // original version: 31 mul + 21 add // optimized version: 18 mul + 12 add // formula: v = v + 2 * cross(q.xyz, cross(q.xyz, v) + q.w * v) ccd_real_t cross1_x, cross1_y, cross1_z, cross2_x, cross2_y, cross2_z; ccd_real_t x, y, z, w; ccd_real_t vx, vy, vz; vx = ccdVec3X(v); vy = ccdVec3Y(v); vz = ccdVec3Z(v); w = q->q[3]; x = q->q[0]; y = q->q[1]; z = q->q[2]; cross1_x = y * vz - z * vy + w * vx; cross1_y = z * vx - x * vz + w * vy; cross1_z = x * vy - y * vx + w * vz; cross2_x = y * cross1_z - z * cross1_y; cross2_y = z * cross1_x - x * cross1_z; cross2_z = x * cross1_y - y * cross1_x; ccdVec3Set(v, vx + 2 * cross2_x, vy + 2 * cross2_y, vz + 2 * cross2_z); } #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif /* __CCD_QUAT_H__ */ ode-0.16/libccd/src/ccd/list.h0000664000175200017520000000726513403272463013040 00000000000000/*** * libccd * --------------------------------- * Copyright (c)2010 Daniel Fiser * * * This file is part of libccd. * * Distributed under the OSI-approved BSD License (the "License"); * see accompanying file BDS-LICENSE for details or see * . * * This software is distributed WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the License for more information. */ #ifndef __CCD_LIST_H__ #define __CCD_LIST_H__ #include #include #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ struct _ccd_list_t { struct _ccd_list_t *next, *prev; }; typedef struct _ccd_list_t ccd_list_t; /** * Get the struct for this entry. * @ptr: the &ccd_list_t pointer. * @type: the type of the struct this is embedded in. * @member: the name of the list_struct within the struct. */ #define ccdListEntry(ptr, type, member) \ ccd_container_of(ptr, type, member) /** * Iterates over list. */ #define ccdListForEach(list, item) \ for (item = (list)->next; \ _ccd_prefetch((item)->next), item != (list); \ item = (item)->next) /** * Iterates over list safe against remove of list entry */ #define ccdListForEachSafe(list, item, tmp) \ for (item = (list)->next, tmp = (item)->next; \ item != (list); \ item = tmp, tmp = (item)->next) /** * Iterates over list of given type. * @pos: the type * to use as a loop cursor. * @head: the head for your list. * @member: the name of the list_struct within the struct. */ #define ccdListForEachEntry(head, pos, postype, member) \ for (pos = ccdListEntry((head)->next, postype, member); \ _ccd_prefetch(pos->member.next), &pos->member != (head); \ pos = ccdListEntry(pos->member.next, postype, member)) /** * Iterates over list of given type safe against removal of list entry * @pos: the type * to use as a loop cursor. * @n: another type * to use as temporary storage * @head: the head for your list. * @member: the name of the list_struct within the struct. */ #define ccdListForEachEntrySafe(head, pos, postype, n, ntype, member) \ for (pos = ccdListEntry((head)->next, postype, member), \ n = ccdListEntry(pos->member.next, postype, member); \ &pos->member != (head); \ pos = n, n = ccdListEntry(n->member.next, ntype, member)) /** * Initialize list. */ _ccd_inline void ccdListInit(ccd_list_t *l); _ccd_inline ccd_list_t *ccdListNext(ccd_list_t *l); _ccd_inline ccd_list_t *ccdListPrev(ccd_list_t *l); /** * Returns true if list is empty. */ _ccd_inline int ccdListEmpty(const ccd_list_t *head); /** * Appends item to end of the list l. */ _ccd_inline void ccdListAppend(ccd_list_t *l, ccd_list_t *item); /** * Removes item from list. */ _ccd_inline void ccdListDel(ccd_list_t *item); /// /// INLINES: /// _ccd_inline void ccdListInit(ccd_list_t *l) { l->next = l; l->prev = l; } _ccd_inline ccd_list_t *ccdListNext(ccd_list_t *l) { return l->next; } _ccd_inline ccd_list_t *ccdListPrev(ccd_list_t *l) { return l->prev; } _ccd_inline int ccdListEmpty(const ccd_list_t *head) { return head->next == head; } _ccd_inline void ccdListAppend(ccd_list_t *l, ccd_list_t *newccd) { newccd->prev = l->prev; newccd->next = l; l->prev->next = newccd; l->prev = newccd; } _ccd_inline void ccdListDel(ccd_list_t *item) { item->next->prev = item->prev; item->prev->next = item->next; item->next = item; item->prev = item; } #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif /* __CCD_LIST_H__ */ ode-0.16/libccd/src/ccd/support.h0000664000175200017520000000271113403272463013570 00000000000000/*** * libccd * --------------------------------- * Copyright (c)2010 Daniel Fiser * * * This file is part of libccd. * * Distributed under the OSI-approved BSD License (the "License"); * see accompanying file BDS-LICENSE for details or see * . * * This software is distributed WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the License for more information. */ #ifndef __CCD_SUPPORT_H__ #define __CCD_SUPPORT_H__ #include #include #include #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ struct _ccd_support_t { ccd_vec3_t v; /*!< Support point in minkowski sum*/ ccd_vec3_t v1; /*!< Support point in obj1*/ ccd_vec3_t v2; /*!< Support point in obj2*/ }; typedef struct _ccd_support_t ccd_support_t; _ccd_inline void ccdSupportCopy(ccd_support_t *, const ccd_support_t *s); /** * Computes support point of obj1 and obj2 in direction dir. * Support point is returned via supp. */ void __ccdSupport(const void *obj1, const void *obj2, const ccd_vec3_t *dir, const ccd_t *ccd, ccd_support_t *supp); /**** INLINES ****/ _ccd_inline void ccdSupportCopy(ccd_support_t *d, const ccd_support_t *s) { *d = *s; } #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif /* __CCD_SUPPORT_H__ */ ode-0.16/libccd/src/ccd/vec3.h0000664000175200017520000002003613403272463012714 00000000000000/*** * libccd * --------------------------------- * Copyright (c)2010,2011 Daniel Fiser * * * This file is part of libccd. * * Distributed under the OSI-approved BSD License (the "License"); * see accompanying file BDS-LICENSE for details or see * . * * This software is distributed WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the License for more information. */ #ifndef __CCD_VEC3_H__ #define __CCD_VEC3_H__ #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #ifndef CCD_SINGLE # ifndef CCD_DOUBLE # error You must define CCD_SINGLE or CCD_DOUBLE # endif /* CCD_DOUBLE */ #endif /* CCD_SINGLE */ #if defined(_MSC_VER) && _MSC_VER < 1700 /* Define fmin, fmax, fminf, fmaxf which are missing from MSVC (up to VS2005 at least) */ static __inline double fmin(double x, double y) { return __min(x, y); } static __inline double fmax(double x, double y) { return __max(x, y); } static __inline float fminf(float x, float y) { return __min(x, y); } static __inline float fmaxf(float x, float y) { return __max(x, y); } #endif /* #if defined(_MSC_VER) */ #ifdef CCD_SINGLE # ifdef CCD_DOUBLE # error You can define either CCD_SINGLE or CCD_DOUBLE, not both! # endif /* CCD_DOUBLE */ typedef float ccd_real_t; /*# define CCD_EPS 1E-6*/ # define CCD_EPS FLT_EPSILON # define CCD_REAL_MAX FLT_MAX # define CCD_REAL(x) (x ## f) /*!< form a constant */ # define CCD_SQRT(x) (sqrtf(x)) /*!< square root */ # define CCD_FABS(x) (fabsf(x)) /*!< absolute value */ # define CCD_FMAX(x, y) (fmaxf((x), (y))) /*!< maximum of two floats */ # define CCD_FMIN(x, y) (fminf((x), (y))) /*!< minimum of two floats */ #endif /* CCD_SINGLE */ #ifdef CCD_DOUBLE typedef double ccd_real_t; /*# define CCD_EPS 1E-10*/ # define CCD_EPS DBL_EPSILON # define CCD_REAL_MAX DBL_MAX # define CCD_REAL(x) (x) /*!< form a constant */ # define CCD_SQRT(x) (sqrt(x)) /*!< square root */ # define CCD_FABS(x) (fabs(x)) /*!< absolute value */ # define CCD_FMAX(x, y) (fmax((x), (y))) /*!< maximum of two floats */ # define CCD_FMIN(x, y) (fmin((x), (y))) /*!< minimum of two floats */ #endif /* CCD_DOUBLE */ #define CCD_ONE CCD_REAL(1.) #define CCD_ZERO CCD_REAL(0.) struct _ccd_vec3_t { ccd_real_t v[3]; }; typedef struct _ccd_vec3_t ccd_vec3_t; /** * Holds origin (0,0,0) - this variable is meant to be read-only! */ extern ccd_vec3_t *ccd_vec3_origin; /** * Array of points uniformly distributed on unit sphere. */ extern ccd_vec3_t *ccd_points_on_sphere; extern size_t ccd_points_on_sphere_len; /** Returns sign of value. */ _ccd_inline int ccdSign(ccd_real_t val); /** Returns true if val is zero. **/ _ccd_inline int ccdIsZero(ccd_real_t val); /** Returns true if a and b equal. **/ _ccd_inline int ccdEq(ccd_real_t a, ccd_real_t b); #define CCD_VEC3_STATIC(x, y, z) \ { { (x), (y), (z) } } #define CCD_VEC3(name, x, y, z) \ ccd_vec3_t name = CCD_VEC3_STATIC((x), (y), (z)) _ccd_inline ccd_real_t ccdVec3X(const ccd_vec3_t *v); _ccd_inline ccd_real_t ccdVec3Y(const ccd_vec3_t *v); _ccd_inline ccd_real_t ccdVec3Z(const ccd_vec3_t *v); /** * Returns true if a and b equal. */ _ccd_inline int ccdVec3Eq(const ccd_vec3_t *a, const ccd_vec3_t *b); /** * Returns squared length of vector. */ _ccd_inline ccd_real_t ccdVec3Len2(const ccd_vec3_t *v); /** * Returns distance between a and b. */ _ccd_inline ccd_real_t ccdVec3Dist2(const ccd_vec3_t *a, const ccd_vec3_t *b); _ccd_inline void ccdVec3Set(ccd_vec3_t *v, ccd_real_t x, ccd_real_t y, ccd_real_t z); /** * v = w */ _ccd_inline void ccdVec3Copy(ccd_vec3_t *v, const ccd_vec3_t *w); /** * Subtracts coordinates of vector w from vector v. v = v - w */ _ccd_inline void ccdVec3Sub(ccd_vec3_t *v, const ccd_vec3_t *w); /** * Adds coordinates of vector w to vector v. v = v + w */ _ccd_inline void ccdVec3Add(ccd_vec3_t *v, const ccd_vec3_t *w); /** * d = v - w */ _ccd_inline void ccdVec3Sub2(ccd_vec3_t *d, const ccd_vec3_t *v, const ccd_vec3_t *w); /** * d = d * k; */ _ccd_inline void ccdVec3Scale(ccd_vec3_t *d, ccd_real_t k); /** * Normalizes given vector to unit length. */ _ccd_inline void ccdVec3Normalize(ccd_vec3_t *d); /** * Dot product of two vectors. */ _ccd_inline ccd_real_t ccdVec3Dot(const ccd_vec3_t *a, const ccd_vec3_t *b); /** * Cross product: d = a x b. */ _ccd_inline void ccdVec3Cross(ccd_vec3_t *d, const ccd_vec3_t *a, const ccd_vec3_t *b); /** * Returns distance2 of point P to segment ab. * If witness is non-NULL it is filled with coordinates of point from which * was computed distance to point P. */ ccd_real_t ccdVec3PointSegmentDist2(const ccd_vec3_t *P, const ccd_vec3_t *a, const ccd_vec3_t *b, ccd_vec3_t *witness); /** * Returns distance2 of point P from triangle formed by triplet a, b, c. * If witness vector is provided it is filled with coordinates of point * from which was computed distance to point P. */ ccd_real_t ccdVec3PointTriDist2(const ccd_vec3_t *P, const ccd_vec3_t *a, const ccd_vec3_t *b, const ccd_vec3_t *c, ccd_vec3_t *witness); /**** INLINES ****/ _ccd_inline int ccdSign(ccd_real_t val) { if (ccdIsZero(val)){ return 0; }else if (val < CCD_ZERO){ return -1; } return 1; } _ccd_inline int ccdIsZero(ccd_real_t val) { return CCD_FABS(val) < CCD_EPS; } _ccd_inline int ccdEq(ccd_real_t _a, ccd_real_t _b) { ccd_real_t ab; ccd_real_t a, b; ab = CCD_FABS(_a - _b); if (CCD_FABS(ab) < CCD_EPS) return 1; a = CCD_FABS(_a); b = CCD_FABS(_b); if (b > a){ return ab < CCD_EPS * b; }else{ return ab < CCD_EPS * a; } } _ccd_inline ccd_real_t ccdVec3X(const ccd_vec3_t *v) { return v->v[0]; } _ccd_inline ccd_real_t ccdVec3Y(const ccd_vec3_t *v) { return v->v[1]; } _ccd_inline ccd_real_t ccdVec3Z(const ccd_vec3_t *v) { return v->v[2]; } _ccd_inline int ccdVec3Eq(const ccd_vec3_t *a, const ccd_vec3_t *b) { return ccdEq(ccdVec3X(a), ccdVec3X(b)) && ccdEq(ccdVec3Y(a), ccdVec3Y(b)) && ccdEq(ccdVec3Z(a), ccdVec3Z(b)); } _ccd_inline ccd_real_t ccdVec3Len2(const ccd_vec3_t *v) { return ccdVec3Dot(v, v); } _ccd_inline ccd_real_t ccdVec3Dist2(const ccd_vec3_t *a, const ccd_vec3_t *b) { ccd_vec3_t ab; ccdVec3Sub2(&ab, a, b); return ccdVec3Len2(&ab); } _ccd_inline void ccdVec3Set(ccd_vec3_t *v, ccd_real_t x, ccd_real_t y, ccd_real_t z) { v->v[0] = x; v->v[1] = y; v->v[2] = z; } _ccd_inline void ccdVec3Copy(ccd_vec3_t *v, const ccd_vec3_t *w) { *v = *w; } _ccd_inline void ccdVec3Sub(ccd_vec3_t *v, const ccd_vec3_t *w) { v->v[0] -= w->v[0]; v->v[1] -= w->v[1]; v->v[2] -= w->v[2]; } _ccd_inline void ccdVec3Sub2(ccd_vec3_t *d, const ccd_vec3_t *v, const ccd_vec3_t *w) { d->v[0] = v->v[0] - w->v[0]; d->v[1] = v->v[1] - w->v[1]; d->v[2] = v->v[2] - w->v[2]; } _ccd_inline void ccdVec3Add(ccd_vec3_t *v, const ccd_vec3_t *w) { v->v[0] += w->v[0]; v->v[1] += w->v[1]; v->v[2] += w->v[2]; } _ccd_inline void ccdVec3Scale(ccd_vec3_t *d, ccd_real_t k) { d->v[0] *= k; d->v[1] *= k; d->v[2] *= k; } _ccd_inline void ccdVec3Normalize(ccd_vec3_t *d) { ccd_real_t k = CCD_ONE / CCD_SQRT(ccdVec3Len2(d)); ccdVec3Scale(d, k); } _ccd_inline ccd_real_t ccdVec3Dot(const ccd_vec3_t *a, const ccd_vec3_t *b) { ccd_real_t dot; dot = a->v[0] * b->v[0]; dot += a->v[1] * b->v[1]; dot += a->v[2] * b->v[2]; return dot; } _ccd_inline void ccdVec3Cross(ccd_vec3_t *d, const ccd_vec3_t *a, const ccd_vec3_t *b) { d->v[0] = (a->v[1] * b->v[2]) - (a->v[2] * b->v[1]); d->v[1] = (a->v[2] * b->v[0]) - (a->v[0] * b->v[2]); d->v[2] = (a->v[0] * b->v[1]) - (a->v[1] * b->v[0]); } #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif /* __CCD_VEC3_H__ */ ode-0.16/libccd/src/Makefile.am0000664000175200017520000000073713403272463013214 00000000000000SUBDIRS = testsuites AM_CPPFLAGS = -I$(top_srcdir)/src/custom AM_CFLAGS = -std=c99 noinst_LTLIBRARIES = libccd.la libccd_la_SOURCES = alloc.c ccd/alloc.h \ ccd/compiler.h \ ccd/dbg.h \ ccd.c ccd/ccd.h \ ccd/list.h \ polytope.c ccd/polytope.h \ ccd/quat.h custom/ccdcustom/quat.h \ ccd/simplex.h \ support.c ccd/support.h \ vec3.c ccd/vec3.h custom/ccdcustom/vec3.h \ mpr.c nodist_libccd_la_SOURCES = ccd/precision.h EXTRA_DIST = ccd/precision.h.in ode-0.16/libccd/src/polytope.c0000664000175200017520000001615313403272463013176 00000000000000/*** * libccd * --------------------------------- * Copyright (c)2010 Daniel Fiser * * * This file is part of libccd. * * Distributed under the OSI-approved BSD License (the "License"); * see accompanying file BDS-LICENSE for details or see * . * * This software is distributed WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the License for more information. */ #include #include #include #include #ifdef HAVE_CONFIG_H #include "config.h" #endif _ccd_inline void _ccdPtNearestUpdate(ccd_pt_t *pt, ccd_pt_el_t *el) { if (ccdEq(pt->nearest_dist, el->dist)){ if (el->type < pt->nearest_type){ pt->nearest = el; pt->nearest_dist = el->dist; pt->nearest_type = el->type; } }else if (el->dist < pt->nearest_dist){ pt->nearest = el; pt->nearest_dist = el->dist; pt->nearest_type = el->type; } } static void _ccdPtNearestRenew(ccd_pt_t *pt) { ccd_pt_vertex_t *v; ccd_pt_edge_t *e; ccd_pt_face_t *f; pt->nearest_dist = CCD_REAL_MAX; pt->nearest_type = 3; pt->nearest = NULL; ccdListForEachEntry(&pt->vertices, v, ccd_pt_vertex_t, list){ _ccdPtNearestUpdate(pt, (ccd_pt_el_t *)v); } ccdListForEachEntry(&pt->edges, e, ccd_pt_edge_t, list){ _ccdPtNearestUpdate(pt, (ccd_pt_el_t *)e); } ccdListForEachEntry(&pt->faces, f, ccd_pt_face_t, list){ _ccdPtNearestUpdate(pt, (ccd_pt_el_t *)f); } } void ccdPtInit(ccd_pt_t *pt) { ccdListInit(&pt->vertices); ccdListInit(&pt->edges); ccdListInit(&pt->faces); pt->nearest = NULL; pt->nearest_dist = CCD_REAL_MAX; pt->nearest_type = 3; } void ccdPtDestroy(ccd_pt_t *pt) { ccd_pt_face_t *f, *f2; ccd_pt_edge_t *e, *e2; ccd_pt_vertex_t *v, *v2; // first delete all faces ccdListForEachEntrySafe(&pt->faces, f, ccd_pt_face_t, f2, ccd_pt_face_t, list){ ccdPtDelFace(pt, f); } // delete all edges ccdListForEachEntrySafe(&pt->edges, e, ccd_pt_edge_t, e2, ccd_pt_edge_t, list){ ccdPtDelEdge(pt, e); } // delete all vertices ccdListForEachEntrySafe(&pt->vertices, v, ccd_pt_vertex_t, v2, ccd_pt_vertex_t, list){ ccdPtDelVertex(pt, v); } } ccd_pt_vertex_t *ccdPtAddVertex(ccd_pt_t *pt, const ccd_support_t *v) { ccd_pt_vertex_t *vert; vert = CCD_ALLOC(ccd_pt_vertex_t); vert->type = CCD_PT_VERTEX; ccdSupportCopy(&vert->v, v); vert->dist = ccdVec3Len2(&vert->v.v); ccdVec3Copy(&vert->witness, &vert->v.v); ccdListInit(&vert->edges); // add vertex to list ccdListAppend(&pt->vertices, &vert->list); // update position in .nearest array _ccdPtNearestUpdate(pt, (ccd_pt_el_t *)vert); return vert; } ccd_pt_edge_t *ccdPtAddEdge(ccd_pt_t *pt, ccd_pt_vertex_t *v1, ccd_pt_vertex_t *v2) { const ccd_vec3_t *a, *b; ccd_pt_edge_t *edge; edge = CCD_ALLOC(ccd_pt_edge_t); edge->type = CCD_PT_EDGE; edge->vertex[0] = v1; edge->vertex[1] = v2; edge->faces[0] = edge->faces[1] = NULL; a = &edge->vertex[0]->v.v; b = &edge->vertex[1]->v.v; edge->dist = ccdVec3PointSegmentDist2(ccd_vec3_origin, a, b, &edge->witness); ccdListAppend(&edge->vertex[0]->edges, &edge->vertex_list[0]); ccdListAppend(&edge->vertex[1]->edges, &edge->vertex_list[1]); ccdListAppend(&pt->edges, &edge->list); // update position in .nearest array _ccdPtNearestUpdate(pt, (ccd_pt_el_t *)edge); return edge; } ccd_pt_face_t *ccdPtAddFace(ccd_pt_t *pt, ccd_pt_edge_t *e1, ccd_pt_edge_t *e2, ccd_pt_edge_t *e3) { const ccd_vec3_t *a, *b, *c; ccd_pt_face_t *face; ccd_pt_edge_t *e; size_t i; face = CCD_ALLOC(ccd_pt_face_t); face->type = CCD_PT_FACE; face->edge[0] = e1; face->edge[1] = e2; face->edge[2] = e3; // obtain triplet of vertices a = &face->edge[0]->vertex[0]->v.v; b = &face->edge[0]->vertex[1]->v.v; e = face->edge[1]; if (e->vertex[0] != face->edge[0]->vertex[0] && e->vertex[0] != face->edge[0]->vertex[1]){ c = &e->vertex[0]->v.v; }else{ c = &e->vertex[1]->v.v; } face->dist = ccdVec3PointTriDist2(ccd_vec3_origin, a, b, c, &face->witness); for (i = 0; i < 3; i++){ if (face->edge[i]->faces[0] == NULL){ face->edge[i]->faces[0] = face; }else{ face->edge[i]->faces[1] = face; } } ccdListAppend(&pt->faces, &face->list); // update position in .nearest array _ccdPtNearestUpdate(pt, (ccd_pt_el_t *)face); return face; } void ccdPtRecomputeDistances(ccd_pt_t *pt) { ccd_pt_vertex_t *v; ccd_pt_edge_t *e; ccd_pt_face_t *f; const ccd_vec3_t *a, *b, *c; ccd_real_t dist; ccdListForEachEntry(&pt->vertices, v, ccd_pt_vertex_t, list){ dist = ccdVec3Len2(&v->v.v); v->dist = dist; ccdVec3Copy(&v->witness, &v->v.v); } ccdListForEachEntry(&pt->edges, e, ccd_pt_edge_t, list){ a = &e->vertex[0]->v.v; b = &e->vertex[1]->v.v; dist = ccdVec3PointSegmentDist2(ccd_vec3_origin, a, b, &e->witness); e->dist = dist; } ccdListForEachEntry(&pt->faces, f, ccd_pt_face_t, list){ // obtain triplet of vertices a = &f->edge[0]->vertex[0]->v.v; b = &f->edge[0]->vertex[1]->v.v; e = f->edge[1]; if (e->vertex[0] != f->edge[0]->vertex[0] && e->vertex[0] != f->edge[0]->vertex[1]){ c = &e->vertex[0]->v.v; }else{ c = &e->vertex[1]->v.v; } dist = ccdVec3PointTriDist2(ccd_vec3_origin, a, b, c, &f->witness); f->dist = dist; } } ccd_pt_el_t *ccdPtNearest(ccd_pt_t *pt) { if (!pt->nearest){ _ccdPtNearestRenew(pt); } return pt->nearest; } void ccdPtDumpSVT(ccd_pt_t *pt, const char *fn) { FILE *fout; fout = fopen(fn, "a"); if (fout == NULL) return; ccdPtDumpSVT2(pt, fout); fclose(fout); } void ccdPtDumpSVT2(ccd_pt_t *pt, FILE *fout) { ccd_pt_vertex_t *v, *a, *b, *c; ccd_pt_edge_t *e; ccd_pt_face_t *f; size_t i; fprintf(fout, "-----\n"); fprintf(fout, "Points:\n"); i = 0; ccdListForEachEntry(&pt->vertices, v, ccd_pt_vertex_t, list){ v->id = i++; fprintf(fout, "%lf %lf %lf\n", ccdVec3X(&v->v.v), ccdVec3Y(&v->v.v), ccdVec3Z(&v->v.v)); } fprintf(fout, "Edges:\n"); ccdListForEachEntry(&pt->edges, e, ccd_pt_edge_t, list){ fprintf(fout, "%d %d\n", e->vertex[0]->id, e->vertex[1]->id); } fprintf(fout, "Faces:\n"); ccdListForEachEntry(&pt->faces, f, ccd_pt_face_t, list){ a = f->edge[0]->vertex[0]; b = f->edge[0]->vertex[1]; c = f->edge[1]->vertex[0]; if (c == a || c == b){ c = f->edge[1]->vertex[1]; } fprintf(fout, "%d %d %d\n", a->id, b->id, c->id); } } ode-0.16/libccd/src/config.h.in0000664000175200017520000000466013403272666013207 00000000000000/* src/config.h.in. Generated from configure.ac by autoheader. */ /* Define to 1 if you have the `clock_gettime' function. */ #undef HAVE_CLOCK_GETTIME /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H /* Define to 1 if you have the header file. */ #undef HAVE_FLOAT_H /* Define to 1 if you have the `fork' function. */ #undef HAVE_FORK /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the `m' library (-lm). */ #undef HAVE_LIBM /* Define to 1 if you have the `rt' library (-lrt). */ #undef HAVE_LIBRT /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to 1 if you have the `vfork' function. */ #undef HAVE_VFORK /* Define to 1 if you have the header file. */ #undef HAVE_VFORK_H /* Define to 1 if `fork' works. */ #undef HAVE_WORKING_FORK /* Define to 1 if `vfork' works. */ #undef HAVE_WORKING_VFORK /* Define to the sub-directory where libtool stores uninstalled libraries. */ #undef LT_OBJDIR /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Version number of package */ #undef VERSION /* Define to `int' if does not define. */ #undef pid_t /* Define to `unsigned int' if does not define. */ #undef size_t /* Define as `fork' if `vfork' does not work. */ #undef vfork ode-0.16/libccd/src/support.c0000664000175200017520000000172613403272463013037 00000000000000/*** * libccd * --------------------------------- * Copyright (c)2010 Daniel Fiser * * * This file is part of libccd. * * Distributed under the OSI-approved BSD License (the "License"); * see accompanying file BDS-LICENSE for details or see * . * * This software is distributed WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the License for more information. */ #include #ifdef HAVE_CONFIG_H #include "config.h" #endif void __ccdSupport(const void *obj1, const void *obj2, const ccd_vec3_t *_dir, const ccd_t *ccd, ccd_support_t *supp) { ccd_vec3_t dir; ccdVec3Copy(&dir, _dir); ccd->support1(obj1, &dir, &supp->v1); ccdVec3Scale(&dir, -CCD_ONE); ccd->support2(obj2, &dir, &supp->v2); ccdVec3Sub2(&supp->v, &supp->v1, &supp->v2); } ode-0.16/libccd/src/vec3.c0000664000175200017520000002124113403272463012155 00000000000000/*** * libccd * --------------------------------- * Copyright (c)2010 Daniel Fiser * * * This file is part of libccd. * * Distributed under the OSI-approved BSD License (the "License"); * see accompanying file BDS-LICENSE for details or see * . * * This software is distributed WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the License for more information. */ #include #include #include #ifdef HAVE_CONFIG_H #include "config.h" #endif static CCD_VEC3(__ccd_vec3_origin, CCD_ZERO, CCD_ZERO, CCD_ZERO); ccd_vec3_t *ccd_vec3_origin = &__ccd_vec3_origin; static ccd_vec3_t points_on_sphere[] = { CCD_VEC3_STATIC(CCD_REAL( 0.000000), CCD_REAL(-0.000000), CCD_REAL(-1.000000)), CCD_VEC3_STATIC(CCD_REAL( 0.723608), CCD_REAL(-0.525725), CCD_REAL(-0.447219)), CCD_VEC3_STATIC(CCD_REAL(-0.276388), CCD_REAL(-0.850649), CCD_REAL(-0.447219)), CCD_VEC3_STATIC(CCD_REAL(-0.894426), CCD_REAL(-0.000000), CCD_REAL(-0.447216)), CCD_VEC3_STATIC(CCD_REAL(-0.276388), CCD_REAL( 0.850649), CCD_REAL(-0.447220)), CCD_VEC3_STATIC(CCD_REAL( 0.723608), CCD_REAL( 0.525725), CCD_REAL(-0.447219)), CCD_VEC3_STATIC(CCD_REAL( 0.276388), CCD_REAL(-0.850649), CCD_REAL( 0.447220)), CCD_VEC3_STATIC(CCD_REAL(-0.723608), CCD_REAL(-0.525725), CCD_REAL( 0.447219)), CCD_VEC3_STATIC(CCD_REAL(-0.723608), CCD_REAL( 0.525725), CCD_REAL( 0.447219)), CCD_VEC3_STATIC(CCD_REAL( 0.276388), CCD_REAL( 0.850649), CCD_REAL( 0.447219)), CCD_VEC3_STATIC(CCD_REAL( 0.894426), CCD_REAL( 0.000000), CCD_REAL( 0.447216)), CCD_VEC3_STATIC(CCD_REAL(-0.000000), CCD_REAL( 0.000000), CCD_REAL( 1.000000)), CCD_VEC3_STATIC(CCD_REAL( 0.425323), CCD_REAL(-0.309011), CCD_REAL(-0.850654)), CCD_VEC3_STATIC(CCD_REAL(-0.162456), CCD_REAL(-0.499995), CCD_REAL(-0.850654)), CCD_VEC3_STATIC(CCD_REAL( 0.262869), CCD_REAL(-0.809012), CCD_REAL(-0.525738)), CCD_VEC3_STATIC(CCD_REAL( 0.425323), CCD_REAL( 0.309011), CCD_REAL(-0.850654)), CCD_VEC3_STATIC(CCD_REAL( 0.850648), CCD_REAL(-0.000000), CCD_REAL(-0.525736)), CCD_VEC3_STATIC(CCD_REAL(-0.525730), CCD_REAL(-0.000000), CCD_REAL(-0.850652)), CCD_VEC3_STATIC(CCD_REAL(-0.688190), CCD_REAL(-0.499997), CCD_REAL(-0.525736)), CCD_VEC3_STATIC(CCD_REAL(-0.162456), CCD_REAL( 0.499995), CCD_REAL(-0.850654)), CCD_VEC3_STATIC(CCD_REAL(-0.688190), CCD_REAL( 0.499997), CCD_REAL(-0.525736)), CCD_VEC3_STATIC(CCD_REAL( 0.262869), CCD_REAL( 0.809012), CCD_REAL(-0.525738)), CCD_VEC3_STATIC(CCD_REAL( 0.951058), CCD_REAL( 0.309013), CCD_REAL( 0.000000)), CCD_VEC3_STATIC(CCD_REAL( 0.951058), CCD_REAL(-0.309013), CCD_REAL( 0.000000)), CCD_VEC3_STATIC(CCD_REAL( 0.587786), CCD_REAL(-0.809017), CCD_REAL( 0.000000)), CCD_VEC3_STATIC(CCD_REAL( 0.000000), CCD_REAL(-1.000000), CCD_REAL( 0.000000)), CCD_VEC3_STATIC(CCD_REAL(-0.587786), CCD_REAL(-0.809017), CCD_REAL( 0.000000)), CCD_VEC3_STATIC(CCD_REAL(-0.951058), CCD_REAL(-0.309013), CCD_REAL(-0.000000)), CCD_VEC3_STATIC(CCD_REAL(-0.951058), CCD_REAL( 0.309013), CCD_REAL(-0.000000)), CCD_VEC3_STATIC(CCD_REAL(-0.587786), CCD_REAL( 0.809017), CCD_REAL(-0.000000)), CCD_VEC3_STATIC(CCD_REAL(-0.000000), CCD_REAL( 1.000000), CCD_REAL(-0.000000)), CCD_VEC3_STATIC(CCD_REAL( 0.587786), CCD_REAL( 0.809017), CCD_REAL(-0.000000)), CCD_VEC3_STATIC(CCD_REAL( 0.688190), CCD_REAL(-0.499997), CCD_REAL( 0.525736)), CCD_VEC3_STATIC(CCD_REAL(-0.262869), CCD_REAL(-0.809012), CCD_REAL( 0.525738)), CCD_VEC3_STATIC(CCD_REAL(-0.850648), CCD_REAL( 0.000000), CCD_REAL( 0.525736)), CCD_VEC3_STATIC(CCD_REAL(-0.262869), CCD_REAL( 0.809012), CCD_REAL( 0.525738)), CCD_VEC3_STATIC(CCD_REAL( 0.688190), CCD_REAL( 0.499997), CCD_REAL( 0.525736)), CCD_VEC3_STATIC(CCD_REAL( 0.525730), CCD_REAL( 0.000000), CCD_REAL( 0.850652)), CCD_VEC3_STATIC(CCD_REAL( 0.162456), CCD_REAL(-0.499995), CCD_REAL( 0.850654)), CCD_VEC3_STATIC(CCD_REAL(-0.425323), CCD_REAL(-0.309011), CCD_REAL( 0.850654)), CCD_VEC3_STATIC(CCD_REAL(-0.425323), CCD_REAL( 0.309011), CCD_REAL( 0.850654)), CCD_VEC3_STATIC(CCD_REAL( 0.162456), CCD_REAL( 0.499995), CCD_REAL( 0.850654)) }; ccd_vec3_t *ccd_points_on_sphere = points_on_sphere; size_t ccd_points_on_sphere_len = sizeof(points_on_sphere) / sizeof(ccd_vec3_t); _ccd_inline ccd_real_t __ccdVec3PointSegmentDist2(const ccd_vec3_t *P, const ccd_vec3_t *x0, const ccd_vec3_t *b, ccd_vec3_t *witness) { // The computation comes from solving equation of segment: // S(t) = x0 + t.d // where - x0 is initial point of segment // - d is direction of segment from x0 (|d| > 0) // - t belongs to <0, 1> interval // // Than, distance from a segment to some point P can be expressed: // D(t) = |x0 + t.d - P|^2 // which is distance from any point on segment. Minimization // of this function brings distance from P to segment. // Minimization of D(t) leads to simple quadratic equation that's // solving is straightforward. // // Bonus of this method is witness point for free. ccd_real_t dist, t; ccd_vec3_t d, a; // direction of segment ccdVec3Sub2(&d, b, x0); // precompute vector from P to x0 ccdVec3Sub2(&a, x0, P); t = -CCD_REAL(1.) * ccdVec3Dot(&a, &d); t /= ccdVec3Len2(&d); if (t < CCD_ZERO || ccdIsZero(t)){ dist = ccdVec3Dist2(x0, P); if (witness) ccdVec3Copy(witness, x0); }else if (t > CCD_ONE || ccdEq(t, CCD_ONE)){ dist = ccdVec3Dist2(b, P); if (witness) ccdVec3Copy(witness, b); }else{ if (witness){ ccdVec3Copy(witness, &d); ccdVec3Scale(witness, t); ccdVec3Add(witness, x0); dist = ccdVec3Dist2(witness, P); }else{ // recycling variables ccdVec3Scale(&d, t); ccdVec3Add(&d, &a); dist = ccdVec3Len2(&d); } } return dist; } ccd_real_t ccdVec3PointSegmentDist2(const ccd_vec3_t *P, const ccd_vec3_t *x0, const ccd_vec3_t *b, ccd_vec3_t *witness) { return __ccdVec3PointSegmentDist2(P, x0, b, witness); } ccd_real_t ccdVec3PointTriDist2(const ccd_vec3_t *P, const ccd_vec3_t *x0, const ccd_vec3_t *B, const ccd_vec3_t *C, ccd_vec3_t *witness) { // Computation comes from analytic expression for triangle (x0, B, C) // T(s, t) = x0 + s.d1 + t.d2, where d1 = B - x0 and d2 = C - x0 and // Then equation for distance is: // D(s, t) = | T(s, t) - P |^2 // This leads to minimization of quadratic function of two variables. // The solution from is taken only if s is between 0 and 1, t is // between 0 and 1 and t + s < 1, otherwise distance from segment is // computed. ccd_vec3_t d1, d2, a; ccd_real_t u, v, w, p, q, r; ccd_real_t s, t, dist, dist2; ccd_vec3_t witness2; ccdVec3Sub2(&d1, B, x0); ccdVec3Sub2(&d2, C, x0); ccdVec3Sub2(&a, x0, P); u = ccdVec3Dot(&a, &a); v = ccdVec3Dot(&d1, &d1); w = ccdVec3Dot(&d2, &d2); p = ccdVec3Dot(&a, &d1); q = ccdVec3Dot(&a, &d2); r = ccdVec3Dot(&d1, &d2); s = (q * r - w * p) / (w * v - r * r); t = (-s * r - q) / w; if ((ccdIsZero(s) || s > CCD_ZERO) && (ccdEq(s, CCD_ONE) || s < CCD_ONE) && (ccdIsZero(t) || t > CCD_ZERO) && (ccdEq(t, CCD_ONE) || t < CCD_ONE) && (ccdEq(t + s, CCD_ONE) || t + s < CCD_ONE)){ if (witness){ ccdVec3Scale(&d1, s); ccdVec3Scale(&d2, t); ccdVec3Copy(witness, x0); ccdVec3Add(witness, &d1); ccdVec3Add(witness, &d2); dist = ccdVec3Dist2(witness, P); }else{ dist = s * s * v; dist += t * t * w; dist += CCD_REAL(2.) * s * t * r; dist += CCD_REAL(2.) * s * p; dist += CCD_REAL(2.) * t * q; dist += u; } }else{ dist = __ccdVec3PointSegmentDist2(P, x0, B, witness); dist2 = __ccdVec3PointSegmentDist2(P, x0, C, &witness2); if (dist2 < dist){ dist = dist2; if (witness) ccdVec3Copy(witness, &witness2); } dist2 = __ccdVec3PointSegmentDist2(P, B, C, &witness2); if (dist2 < dist){ dist = dist2; if (witness) ccdVec3Copy(witness, &witness2); } } return dist; } ode-0.16/libccd/src/testsuites/0000775000175200017520000000000013403273061013440 500000000000000ode-0.16/libccd/src/testsuites/spheresphere.c0000664000175200017520000000320113403272463016222 00000000000000#include #include #include "support.h" #include TEST(spheresphereSetUp) { } TEST(spheresphereTearDown) { } TEST(spheresphereAlignedX) { ccd_t ccd; CCD_SPHERE(s1); CCD_SPHERE(s2); size_t i; int res; CCD_INIT(&ccd); ccd.support1 = ccdSupport; ccd.support2 = ccdSupport; s1.radius = 0.35; s2.radius = .5; ccdVec3Set(&s1.pos, -5., 0., 0.); for (i = 0; i < 100; i++){ res = ccdGJKIntersect(&s1, &s2, &ccd); if (i < 42 || i > 58){ assertFalse(res); }else{ assertTrue(res); } s1.pos.v[0] += 0.1; } } TEST(spheresphereAlignedY) { ccd_t ccd; CCD_SPHERE(s1); CCD_SPHERE(s2); size_t i; int res; CCD_INIT(&ccd); ccd.support1 = ccdSupport; ccd.support2 = ccdSupport; s1.radius = 0.35; s2.radius = .5; ccdVec3Set(&s1.pos, 0., -5., 0.); for (i = 0; i < 100; i++){ res = ccdGJKIntersect(&s1, &s2, &ccd); if (i < 42 || i > 58){ assertFalse(res); }else{ assertTrue(res); } s1.pos.v[1] += 0.1; } } TEST(spheresphereAlignedZ) { ccd_t ccd; CCD_SPHERE(s1); CCD_SPHERE(s2); size_t i; int res; CCD_INIT(&ccd); ccd.support1 = ccdSupport; ccd.support2 = ccdSupport; s1.radius = 0.35; s2.radius = .5; ccdVec3Set(&s1.pos, 0., 0., -5.); for (i = 0; i < 100; i++){ res = ccdGJKIntersect(&s1, &s2, &ccd); if (i < 42 || i > 58){ assertFalse(res); }else{ assertTrue(res); } s1.pos.v[2] += 0.1; } } ode-0.16/libccd/src/testsuites/common.h0000664000175200017520000000066613403272463015036 00000000000000#ifndef TEST_COMMON #define TEST_COMMON #include #include void svtObj(void *o, FILE *out, const char *color, const char *name); void svtObjPen(void *o1, void *o2, FILE *out, const char *name, ccd_real_t depth, const ccd_vec3_t *dir, const ccd_vec3_t *pos); void recPen(ccd_real_t depth, const ccd_vec3_t *dir, const ccd_vec3_t *pos, FILE *out, const char *note); #endif ode-0.16/libccd/src/testsuites/boxbox.h0000664000175200017520000000101213403272463015031 00000000000000#ifndef BOX_BOX #define BOX_BOX #include TEST(boxboxSetUp); TEST(boxboxTearDown); TEST(boxboxAlignedX); TEST(boxboxAlignedY); TEST(boxboxAlignedZ); TEST(boxboxRot); TEST(boxboxSeparate); TEST(boxboxPenetration); TEST_SUITE(TSBoxBox) { TEST_ADD(boxboxSetUp), TEST_ADD(boxboxAlignedX), TEST_ADD(boxboxAlignedY), TEST_ADD(boxboxAlignedZ), TEST_ADD(boxboxRot), TEST_ADD(boxboxSeparate), TEST_ADD(boxboxPenetration), TEST_ADD(boxboxTearDown), TEST_SUITE_CLOSURE }; #endif ode-0.16/libccd/src/testsuites/common.c0000664000175200017520000001234413403272463015025 00000000000000#include "common.h" #include #include #include "support.h" static void svtCyl(ccd_cyl_t *c, FILE *out, const char *color, const char *name) { ccd_vec3_t v[32]; ccd_quat_t rot; ccd_vec3_t axis, vpos, vpos2; ccd_real_t angle, x, y; size_t i; ccdVec3Set(&axis, 0., 0., 1.); ccdVec3Set(&vpos, 0., c->radius, 0.); angle = 0.; for (i = 0; i < 16; i++){ angle = (ccd_real_t)i * (2. * M_PI / 16.); ccdQuatSetAngleAxis(&rot, angle, &axis); ccdVec3Copy(&vpos2, &vpos); ccdQuatRotVec(&vpos2, &rot); x = ccdVec3X(&vpos2); y = ccdVec3Y(&vpos2); ccdVec3Set(&v[i], x, y, c->height / 2.); ccdVec3Set(&v[i + 16], x, y, -c->height / 2.); } for (i = 0; i < 32; i++){ ccdQuatRotVec(&v[i], &c->quat); ccdVec3Add(&v[i], &c->pos); } fprintf(out, "-----\n"); if (name) fprintf(out, "Name: %s\n", name); fprintf(out, "Face color: %s\n", color); fprintf(out, "Edge color: %s\n", color); fprintf(out, "Point color: %s\n", color); fprintf(out, "Points:\n"); for (i = 0; i < 32; i++){ fprintf(out, "%lf %lf %lf\n", ccdVec3X(&v[i]), ccdVec3Y(&v[i]), ccdVec3Z(&v[i])); } fprintf(out, "Edges:\n"); fprintf(out, "0 16\n"); fprintf(out, "0 31\n"); for (i = 1; i < 16; i++){ fprintf(out, "0 %d\n", i); fprintf(out, "16 %d\n", i + 16); if (i != 0){ fprintf(out, "%d %d\n", i - 1, i); fprintf(out, "%d %d\n", i + 16 - 1, i + 16); } fprintf(out, "%d %d\n", i, i + 16); fprintf(out, "%d %d\n", i, i + 16 - 1); } fprintf(out, "Faces:\n"); for (i = 2; i < 16; i++){ fprintf(out, "0 %d %d\n", i, i -1); fprintf(out, "16 %d %d\n", i + 16, i + 16 -1); } fprintf(out, "0 16 31\n"); fprintf(out, "0 31 15\n"); for (i = 1; i < 16; i++){ fprintf(out, "%d %d %d\n", i, i + 16, i + 16 - 1); fprintf(out, "%d %d %d\n", i, i + 16 - 1, i - 1); } fprintf(out, "-----\n"); } static void svtBox(ccd_box_t *b, FILE *out, const char *color, const char *name) { ccd_vec3_t v[8]; size_t i; ccdVec3Set(&v[0], b->x * 0.5, b->y * 0.5, b->z * 0.5); ccdVec3Set(&v[1], b->x * 0.5, b->y * -0.5, b->z * 0.5); ccdVec3Set(&v[2], b->x * 0.5, b->y * 0.5, b->z * -0.5); ccdVec3Set(&v[3], b->x * 0.5, b->y * -0.5, b->z * -0.5); ccdVec3Set(&v[4], b->x * -0.5, b->y * 0.5, b->z * 0.5); ccdVec3Set(&v[5], b->x * -0.5, b->y * -0.5, b->z * 0.5); ccdVec3Set(&v[6], b->x * -0.5, b->y * 0.5, b->z * -0.5); ccdVec3Set(&v[7], b->x * -0.5, b->y * -0.5, b->z * -0.5); for (i = 0; i < 8; i++){ ccdQuatRotVec(&v[i], &b->quat); ccdVec3Add(&v[i], &b->pos); } fprintf(out, "-----\n"); if (name) fprintf(out, "Name: %s\n", name); fprintf(out, "Face color: %s\n", color); fprintf(out, "Edge color: %s\n", color); fprintf(out, "Point color: %s\n", color); fprintf(out, "Points:\n"); for (i = 0; i < 8; i++){ fprintf(out, "%lf %lf %lf\n", ccdVec3X(&v[i]), ccdVec3Y(&v[i]), ccdVec3Z(&v[i])); } fprintf(out, "Edges:\n"); fprintf(out, "0 1\n 0 2\n2 3\n3 1\n1 2\n6 2\n1 7\n1 5\n"); fprintf(out, "5 0\n0 4\n4 2\n6 4\n6 5\n5 7\n6 7\n7 2\n7 3\n4 5\n"); fprintf(out, "Faces:\n"); fprintf(out, "0 2 1\n1 2 3\n6 2 4\n4 2 0\n4 0 5\n5 0 1\n"); fprintf(out, "5 1 7\n7 1 3\n6 4 5\n6 5 7\n2 6 7\n2 7 3\n"); fprintf(out, "-----\n"); } void svtObj(void *_o, FILE *out, const char *color, const char *name) { ccd_obj_t *o = (ccd_obj_t *)_o; if (o->type == CCD_OBJ_CYL){ svtCyl((ccd_cyl_t *)o, out, color, name); }else if (o->type == CCD_OBJ_BOX){ svtBox((ccd_box_t *)o, out, color, name); } } void svtObjPen(void *o1, void *o2, FILE *out, const char *name, ccd_real_t depth, const ccd_vec3_t *dir, const ccd_vec3_t *pos) { ccd_vec3_t sep; char oname[500]; ccdVec3Copy(&sep, dir); ccdVec3Scale(&sep, depth); ccdVec3Add(&sep, pos); fprintf(out, "------\n"); if (name) fprintf(out, "Name: %s\n", name); fprintf(out, "Point color: 0.1 0.1 0.9\n"); fprintf(out, "Points:\n%lf %lf %lf\n", ccdVec3X(pos), ccdVec3Y(pos), ccdVec3Z(pos)); fprintf(out, "------\n"); fprintf(out, "Point color: 0.1 0.9 0.9\n"); fprintf(out, "Edge color: 0.1 0.9 0.9\n"); fprintf(out, "Points:\n%lf %lf %lf\n", ccdVec3X(pos), ccdVec3Y(pos), ccdVec3Z(pos)); fprintf(out, "%lf %lf %lf\n", ccdVec3X(&sep), ccdVec3Y(&sep), ccdVec3Z(&sep)); fprintf(out, "Edges: 0 1\n"); oname[0] = 0x0; if (name) sprintf(oname, "%s o1", name); svtObj(o1, out, "0.9 0.1 0.1", oname); oname[0] = 0x0; if (name) sprintf(oname, "%s o1", name); svtObj(o2, out, "0.1 0.9 0.1", oname); } void recPen(ccd_real_t depth, const ccd_vec3_t *dir, const ccd_vec3_t *pos, FILE *out, const char *note) { if (!note) note = ""; fprintf(out, "# %s: depth: %lf\n", note, depth); fprintf(out, "# %s: dir: [%lf %lf %lf]\n", note, ccdVec3X(dir), ccdVec3Y(dir), ccdVec3Z(dir)); fprintf(out, "# %s: pos: [%lf %lf %lf]\n", note, ccdVec3X(pos), ccdVec3Y(pos), ccdVec3Z(pos)); fprintf(out, "#\n"); } ode-0.16/libccd/src/testsuites/Makefile.am0000664000175200017520000000112313403272463015416 00000000000000SUBDIRS = cu AM_CPPFLAGS = -I $(srcdir)/.. -I $(builddir)/.. -I $(srcdir)/cu LDADD = $(builddir)/cu/libcu.la $(builddir)/../libccd.la check_PROGRAMS = test bench bench2 test_SOURCES = main.c \ common.c common.h \ support.c support.h \ vec3.c vec3.h \ polytope.c polytope.h \ boxbox.c boxbox.h \ spheresphere.c spheresphere.h \ cylcyl.c cylcyl.h \ boxcyl.c boxcyl.h \ mpr_boxbox.c mpr_boxbox.h \ mpr_cylcyl.c mpr_cylcyl.h \ mpr_boxcyl.c mpr_boxcyl.h bench_SOURCES = bench.c \ support.c support.h bench2_SOURCES = bench2.c \ support.c support.h ode-0.16/libccd/src/testsuites/main.c0000664000175200017520000000117513403272463014461 00000000000000#include "vec3.h" #include "polytope.h" #include "boxbox.h" #include "spheresphere.h" #include "cylcyl.h" #include "boxcyl.h" #include "mpr_boxbox.h" #include "mpr_cylcyl.h" #include "mpr_boxcyl.h" TEST_SUITES { TEST_SUITE_ADD(TSVec3), TEST_SUITE_ADD(TSPt), TEST_SUITE_ADD(TSBoxBox), TEST_SUITE_ADD(TSSphereSphere), TEST_SUITE_ADD(TSCylCyl), TEST_SUITE_ADD(TSBoxCyl), TEST_SUITE_ADD(TSMPRBoxBox), TEST_SUITE_ADD(TSMPRCylCyl), TEST_SUITE_ADD(TSMPRBoxCyl), TEST_SUITES_CLOSURE }; int main(int argc, char *argv[]) { CU_SET_OUT_PREFIX("regressions/"); CU_RUN(argc, argv); return 0; } ode-0.16/libccd/src/testsuites/cylcyl.h0000664000175200017520000000066313403272463015042 00000000000000#ifndef CYL_CYL #define CYL_CYL #include TEST(cylcylSetUp); TEST(cylcylTearDown); TEST(cylcylAlignedX); TEST(cylcylAlignedY); TEST(cylcylAlignedZ); TEST(cylcylPenetrationEPA); TEST_SUITE(TSCylCyl) { TEST_ADD(cylcylSetUp), TEST_ADD(cylcylAlignedX), TEST_ADD(cylcylAlignedY), TEST_ADD(cylcylAlignedZ), TEST_ADD(cylcylPenetrationEPA), TEST_ADD(cylcylTearDown), TEST_SUITE_CLOSURE }; #endif ode-0.16/libccd/src/testsuites/mpr_boxcyl.h0000664000175200017520000000036213403272463015715 00000000000000#ifndef MPR_TEST_BOXCYL_H #define MPR_TEST_BOXCYL_H #include TEST(mprBoxcylIntersect); TEST(mprBoxcylPen); TEST_SUITE(TSMPRBoxCyl){ TEST_ADD(mprBoxcylIntersect), TEST_ADD(mprBoxcylPen), TEST_SUITE_CLOSURE }; #endif ode-0.16/libccd/src/testsuites/polytope.c0000664000175200017520000003044613403272463015413 00000000000000//#undef NDEBUG #include #include #include TEST(ptSetUp) { } TEST(ptTearDown) { } TEST(ptCreate1) { ccd_pt_t pt; ccd_pt_vertex_t *v[3]; ccd_pt_edge_t *e[3]; ccd_pt_face_t *f; ccd_vec3_t u; int res; size_t i; DBG2("------"); ccdPtInit(&pt); ccdPtDestroy(&pt); ccdPtInit(&pt); ccdVec3Set(&u, -1., -1., 0.); v[0] = ccdPtAddVertexCoords(&pt, -1., -1., 0.); assertTrue(ccdVec3Eq(&u, &v[0]->v.v)); ccdVec3Set(&u, 1., 0., 0.); v[1] = ccdPtAddVertexCoords(&pt, 1., 0., 0.); assertTrue(ccdVec3Eq(&u, &v[1]->v.v)); ccdVec3Set(&u, 0., 0., 1.); v[2] = ccdPtAddVertexCoords(&pt, 0., 0., 1.); assertTrue(ccdVec3Eq(&u, &v[2]->v.v)); for (i = 0; i < 3; i++){ assertTrue(ccdEq(v[i]->dist, ccdVec3Len2(&v[i]->v.v))); } e[0] = ccdPtAddEdge(&pt, v[0], v[1]); e[1] = ccdPtAddEdge(&pt, v[1], v[2]); e[2] = ccdPtAddEdge(&pt, v[2], v[0]); for (i = 0; i < 3; i++){ DBG("e[%d]->dist: %lf", i, e[i]->dist); DBG_VEC3(&e[i]->witness, " ->witness: "); } f = ccdPtAddFace(&pt, e[0], e[1], e[2]); DBG("f->dist: %lf", f->dist); DBG_VEC3(&f->witness, " ->witness: "); for (i = 0; i < 3; i++){ res = ccdPtDelVertex(&pt, v[i]); assertFalse(res == 0); res = ccdPtDelEdge(&pt, e[i]); assertFalse(res == 0); } ccdPtDelFace(&pt, f); for (i = 0; i < 3; i++){ res = ccdPtDelVertex(&pt, v[i]); assertFalse(res == 0); } for (i = 0; i < 3; i++){ res = ccdPtDelEdge(&pt, e[i]); assertTrue(res == 0); } for (i = 0; i < 3; i++){ res = ccdPtDelVertex(&pt, v[i]); assertTrue(res == 0); } v[0] = ccdPtAddVertexCoords(&pt, -1., -1., 0.); v[1] = ccdPtAddVertexCoords(&pt, 1., 0., 0.); v[2] = ccdPtAddVertexCoords(&pt, 0., 0., 1.); e[0] = ccdPtAddEdge(&pt, v[0], v[1]); e[1] = ccdPtAddEdge(&pt, v[1], v[2]); e[2] = ccdPtAddEdge(&pt, v[2], v[0]); f = ccdPtAddFace(&pt, e[0], e[1], e[2]); ccdPtDestroy(&pt); } TEST(ptCreate2) { ccd_pt_t pt; ccd_pt_vertex_t *v[4]; ccd_pt_edge_t *e[6]; ccd_pt_face_t *f[4]; ccd_vec3_t u; int res; size_t i; DBG2("------"); ccdPtInit(&pt); ccdVec3Set(&u, -1., -1., 0.); v[0] = ccdPtAddVertexCoords(&pt, -1., -1., 0.); assertTrue(ccdVec3Eq(&u, &v[0]->v.v)); ccdVec3Set(&u, 1., 0., 0.); v[1] = ccdPtAddVertexCoords(&pt, 1., 0., 0.); assertTrue(ccdVec3Eq(&u, &v[1]->v.v)); ccdVec3Set(&u, 0., 0., 1.); v[2] = ccdPtAddVertexCoords(&pt, 0., 0., 1.); assertTrue(ccdVec3Eq(&u, &v[2]->v.v)); ccdVec3Set(&u, 0., 1., 0.); v[3] = ccdPtAddVertexCoords(&pt, 0., 1., 0.); assertTrue(ccdVec3Eq(&u, &v[3]->v.v)); for (i = 0; i < 4; i++){ assertTrue(ccdEq(v[i]->dist, ccdVec3Len2(&v[i]->v.v))); } for (i = 0; i < 4; i++){ DBG("v[%d]->dist: %lf", i, v[i]->dist); DBG_VEC3(&v[i]->witness, " ->witness: "); } e[0] = ccdPtAddEdge(&pt, v[0], v[1]); e[1] = ccdPtAddEdge(&pt, v[1], v[2]); e[2] = ccdPtAddEdge(&pt, v[2], v[0]); e[3] = ccdPtAddEdge(&pt, v[3], v[0]); e[4] = ccdPtAddEdge(&pt, v[3], v[1]); e[5] = ccdPtAddEdge(&pt, v[3], v[2]); for (i = 0; i < 6; i++){ DBG("e[%d]->dist: %lf", i, e[i]->dist); DBG_VEC3(&e[i]->witness, " ->witness: "); } f[0] = ccdPtAddFace(&pt, e[0], e[1], e[2]); f[1] = ccdPtAddFace(&pt, e[3], e[4], e[0]); f[2] = ccdPtAddFace(&pt, e[4], e[5], e[1]); f[3] = ccdPtAddFace(&pt, e[5], e[3], e[2]); for (i = 0; i < 4; i++){ DBG("f[%d]->dist: %lf", i, f[i]->dist); DBG_VEC3(&f[i]->witness, " ->witness: "); } for (i = 0; i < 4; i++){ res = ccdPtDelVertex(&pt, v[i]); assertFalse(res == 0); } for (i = 0; i < 6; i++){ res = ccdPtDelEdge(&pt, e[i]); assertFalse(res == 0); } res = ccdPtDelFace(&pt, f[0]); for (i = 0; i < 6; i++){ res = ccdPtDelEdge(&pt, e[i]); assertFalse(res == 0); } res = ccdPtDelFace(&pt, f[1]); assertTrue(ccdPtDelEdge(&pt, e[0]) == 0); assertFalse(ccdPtDelEdge(&pt, e[1]) == 0); assertFalse(ccdPtDelEdge(&pt, e[2]) == 0); assertFalse(ccdPtDelEdge(&pt, e[3]) == 0); assertFalse(ccdPtDelEdge(&pt, e[4]) == 0); assertFalse(ccdPtDelEdge(&pt, e[5]) == 0); for (i = 0; i < 4; i++){ res = ccdPtDelVertex(&pt, v[i]); assertFalse(res == 0); } res = ccdPtDelFace(&pt, f[2]); assertTrue(ccdPtDelEdge(&pt, e[1]) == 0); assertTrue(ccdPtDelEdge(&pt, e[4]) == 0); assertFalse(ccdPtDelEdge(&pt, e[2]) == 0); assertFalse(ccdPtDelEdge(&pt, e[3]) == 0); assertFalse(ccdPtDelEdge(&pt, e[5]) == 0); assertTrue(ccdPtDelVertex(&pt, v[1]) == 0); assertFalse(ccdPtDelVertex(&pt, v[0]) == 0); assertFalse(ccdPtDelVertex(&pt, v[2]) == 0); assertFalse(ccdPtDelVertex(&pt, v[3]) == 0); res = ccdPtDelFace(&pt, f[3]); assertTrue(ccdPtDelEdge(&pt, e[2]) == 0); assertTrue(ccdPtDelEdge(&pt, e[3]) == 0); assertTrue(ccdPtDelEdge(&pt, e[5]) == 0); assertTrue(ccdPtDelVertex(&pt, v[0]) == 0); assertTrue(ccdPtDelVertex(&pt, v[2]) == 0); assertTrue(ccdPtDelVertex(&pt, v[3]) == 0); v[0] = ccdPtAddVertexCoords(&pt, -1., -1., 0.); v[1] = ccdPtAddVertexCoords(&pt, 1., 0., 0.); v[2] = ccdPtAddVertexCoords(&pt, 0., 0., 1.); v[3] = ccdPtAddVertexCoords(&pt, 0., 1., 0.); e[0] = ccdPtAddEdge(&pt, v[0], v[1]); e[1] = ccdPtAddEdge(&pt, v[1], v[2]); e[2] = ccdPtAddEdge(&pt, v[2], v[0]); e[3] = ccdPtAddEdge(&pt, v[3], v[0]); e[4] = ccdPtAddEdge(&pt, v[3], v[1]); e[5] = ccdPtAddEdge(&pt, v[3], v[2]); f[0] = ccdPtAddFace(&pt, e[0], e[1], e[2]); f[1] = ccdPtAddFace(&pt, e[3], e[4], e[0]); f[2] = ccdPtAddFace(&pt, e[4], e[5], e[1]); f[3] = ccdPtAddFace(&pt, e[5], e[3], e[2]); ccdPtDestroy(&pt); } TEST(ptNearest) { ccd_pt_t pt; ccd_pt_vertex_t *v[4]; ccd_pt_edge_t *e[6]; ccd_pt_face_t *f[4]; ccd_pt_el_t *nearest; DBG2("------"); ccdPtInit(&pt); v[0] = ccdPtAddVertexCoords(&pt, -1., -1., 0.); v[1] = ccdPtAddVertexCoords(&pt, 1., 0., 0.); v[2] = ccdPtAddVertexCoords(&pt, 0., 0., 1.); v[3] = ccdPtAddVertexCoords(&pt, 0., 1., 0.); e[0] = ccdPtAddEdge(&pt, v[0], v[1]); e[1] = ccdPtAddEdge(&pt, v[1], v[2]); e[2] = ccdPtAddEdge(&pt, v[2], v[0]); e[3] = ccdPtAddEdge(&pt, v[3], v[0]); e[4] = ccdPtAddEdge(&pt, v[3], v[1]); e[5] = ccdPtAddEdge(&pt, v[3], v[2]); f[0] = ccdPtAddFace(&pt, e[0], e[1], e[2]); f[1] = ccdPtAddFace(&pt, e[3], e[4], e[0]); f[2] = ccdPtAddFace(&pt, e[4], e[5], e[1]); f[3] = ccdPtAddFace(&pt, e[5], e[3], e[2]); nearest = ccdPtNearest(&pt); //DBG("nearest->type: %d", nearest->type); //DBG(" ->dist: %lf", nearest->dist); //DBG_VEC3(&nearest->witness, " ->witness: "); assertEquals(nearest->type, CCD_PT_FACE); assertEquals(nearest, (ccd_pt_el_t *)f[1]); assertTrue(ccdPtDelFace(&pt, f[1]) == 0); nearest = ccdPtNearest(&pt); //DBG("nearest->type: %d", nearest->type); //DBG(" ->dist: %lf", nearest->dist); //DBG_VEC3(&nearest->witness, " ->witness: "); assertEquals(nearest->type, CCD_PT_FACE); assertTrue(nearest == (ccd_pt_el_t *)f[0] || nearest == (ccd_pt_el_t *)f[3]); assertTrue(ccdPtDelFace(&pt, (ccd_pt_face_t *)nearest) == 0); nearest = ccdPtNearest(&pt); //DBG("nearest->type: %d", nearest->type); //DBG(" ->dist: %lf", nearest->dist); //DBG_VEC3(&nearest->witness, " ->witness: "); assertEquals(nearest->type, CCD_PT_FACE); assertTrue(nearest == (ccd_pt_el_t *)f[0] || nearest == (ccd_pt_el_t *)f[3]); assertTrue(ccdPtDelFace(&pt, (ccd_pt_face_t *)nearest) == 0); nearest = ccdPtNearest(&pt); //DBG("nearest->type: %d", nearest->type); //DBG(" ->dist: %lf", nearest->dist); //DBG_VEC3(&nearest->witness, " ->witness: "); assertEquals(nearest->type, CCD_PT_EDGE); assertTrue(nearest == (ccd_pt_el_t *)e[0] || nearest == (ccd_pt_el_t *)e[3]); assertTrue(ccdPtDelEdge(&pt, (ccd_pt_edge_t *)nearest) == 0); nearest = ccdPtNearest(&pt); //DBG("nearest->type: %d", nearest->type); //DBG(" ->dist: %lf", nearest->dist); //DBG_VEC3(&nearest->witness, " ->witness: "); assertEquals(nearest->type, CCD_PT_EDGE); assertTrue(nearest == (ccd_pt_el_t *)e[0] || nearest == (ccd_pt_el_t *)e[3]); assertTrue(ccdPtDelEdge(&pt, (ccd_pt_edge_t *)nearest) == 0); nearest = ccdPtNearest(&pt); //DBG("nearest->type: %d", nearest->type); //DBG(" ->dist: %lf", nearest->dist); //DBG_VEC3(&nearest->witness, " ->witness: "); assertEquals(nearest->type, CCD_PT_FACE); assertEquals(nearest, (ccd_pt_el_t *)f[2]); assertTrue(ccdPtDelFace(&pt, f[2]) == 0); nearest = ccdPtNearest(&pt); //DBG("nearest->type: %d", nearest->type); //DBG(" ->dist: %lf", nearest->dist); //DBG_VEC3(&nearest->witness, " ->witness: "); assertEquals(nearest->type, CCD_PT_EDGE); assertTrue(nearest == (ccd_pt_el_t *)e[1] || nearest == (ccd_pt_el_t *)e[4] || nearest == (ccd_pt_el_t *)e[5]); assertTrue(ccdPtDelEdge(&pt, (ccd_pt_edge_t *)nearest) == 0); nearest = ccdPtNearest(&pt); //DBG("nearest->type: %d", nearest->type); //DBG(" ->dist: %lf", nearest->dist); //DBG_VEC3(&nearest->witness, " ->witness: "); assertEquals(nearest->type, CCD_PT_EDGE); assertTrue(nearest == (ccd_pt_el_t *)e[1] || nearest == (ccd_pt_el_t *)e[4] || nearest == (ccd_pt_el_t *)e[5]); assertTrue(ccdPtDelEdge(&pt, (ccd_pt_edge_t *)nearest) == 0); nearest = ccdPtNearest(&pt); //DBG("nearest->type: %d", nearest->type); //DBG(" ->dist: %lf", nearest->dist); //DBG_VEC3(&nearest->witness, " ->witness: "); assertEquals(nearest->type, CCD_PT_EDGE); assertTrue(nearest == (ccd_pt_el_t *)e[1] || nearest == (ccd_pt_el_t *)e[4] || nearest == (ccd_pt_el_t *)e[5]); assertTrue(ccdPtDelEdge(&pt, (ccd_pt_edge_t *)nearest) == 0); nearest = ccdPtNearest(&pt); //DBG("nearest->type: %d", nearest->type); //DBG(" ->dist: %lf", nearest->dist); //DBG_VEC3(&nearest->witness, " ->witness: "); assertEquals(nearest->type, CCD_PT_EDGE); assertTrue(nearest == (ccd_pt_el_t *)e[2]); assertTrue(ccdPtDelEdge(&pt, (ccd_pt_edge_t *)nearest) == 0); nearest = ccdPtNearest(&pt); //DBG("nearest->type: %d", nearest->type); //DBG(" ->dist: %lf", nearest->dist); //DBG_VEC3(&nearest->witness, " ->witness: "); assertEquals(nearest->type, CCD_PT_VERTEX); assertTrue(nearest == (ccd_pt_el_t *)v[1] || nearest == (ccd_pt_el_t *)v[2] || nearest == (ccd_pt_el_t *)v[3]); assertTrue(ccdPtDelVertex(&pt, (ccd_pt_vertex_t *)nearest) == 0); nearest = ccdPtNearest(&pt); //DBG("nearest->type: %d", nearest->type); //DBG(" ->dist: %lf", nearest->dist); //DBG_VEC3(&nearest->witness, " ->witness: "); assertEquals(nearest->type, CCD_PT_VERTEX); assertTrue(nearest == (ccd_pt_el_t *)v[1] || nearest == (ccd_pt_el_t *)v[2] || nearest == (ccd_pt_el_t *)v[3]); assertTrue(ccdPtDelVertex(&pt, (ccd_pt_vertex_t *)nearest) == 0); nearest = ccdPtNearest(&pt); //DBG("nearest->type: %d", nearest->type); //DBG(" ->dist: %lf", nearest->dist); //DBG_VEC3(&nearest->witness, " ->witness: "); assertEquals(nearest->type, CCD_PT_VERTEX); assertTrue(nearest == (ccd_pt_el_t *)v[1] || nearest == (ccd_pt_el_t *)v[2] || nearest == (ccd_pt_el_t *)v[3]); assertTrue(ccdPtDelVertex(&pt, (ccd_pt_vertex_t *)nearest) == 0); nearest = ccdPtNearest(&pt); //DBG("nearest->type: %d", nearest->type); //DBG(" ->dist: %lf", nearest->dist); //DBG_VEC3(&nearest->witness, " ->witness: "); assertEquals(nearest->type, CCD_PT_VERTEX); assertTrue(nearest == (ccd_pt_el_t *)v[0]); assertTrue(ccdPtDelVertex(&pt, (ccd_pt_vertex_t *)nearest) == 0); nearest = ccdPtNearest(&pt); assertTrue(nearest == NULL); ccdPtDestroy(&pt); } ode-0.16/libccd/src/testsuites/bench.c0000664000175200017520000001455013403272463014615 00000000000000#define CU_ENABLE_TIMER #include #include #include #include #include "support.h" TEST_SUITES { TEST_SUITES_CLOSURE }; static int bench_num = 1; static size_t cycles = 10000; static void runBench(const void *o1, const void *o2, const ccd_t *ccd) { ccd_real_t depth; ccd_vec3_t dir, pos; int res; size_t i; const struct timespec *timer; cuTimerStart(); for (i = 0; i < cycles; i++){ res = ccdGJKPenetration(o1, o2, ccd, &depth, &dir, &pos); } timer = cuTimerStop(); fprintf(stdout, "%02d: %ld %ld\n", bench_num, (long)timer->tv_sec, (long)timer->tv_nsec); fflush(stdout); bench_num++; } static void boxbox(void) { fprintf(stdout, "%s:\n", __func__); ccd_t ccd; CCD_BOX(box1); CCD_BOX(box2); ccd_vec3_t axis; ccd_quat_t rot; box1.x = box1.y = box1.z = 1.; box2.x = 0.5; box2.y = 1.; box2.z = 1.5; bench_num = 1; CCD_INIT(&ccd); ccd.support1 = ccdSupport; ccd.support2 = ccdSupport; runBench(&box1, &box2, &ccd); runBench(&box2, &box1, &ccd); ccdVec3Set(&box1.pos, -0.3, 0.5, 1.); runBench(&box1, &box2, &ccd); runBench(&box2, &box1, &ccd); box1.x = box1.y = box1.z = 1.; box2.x = box2.y = box2.z = 1.; ccdVec3Set(&axis, 0., 0., 1.); ccdQuatSetAngleAxis(&box1.quat, M_PI / 4., &axis); ccdVec3Set(&box1.pos, 0., 0., 0.); runBench(&box1, &box2, &ccd); runBench(&box2, &box1, &ccd); box1.x = box1.y = box1.z = 1.; box2.x = box2.y = box2.z = 1.; ccdVec3Set(&axis, 0., 0., 1.); ccdQuatSetAngleAxis(&box1.quat, M_PI / 4., &axis); ccdVec3Set(&box1.pos, -0.5, 0., 0.); runBench(&box1, &box2, &ccd); runBench(&box2, &box1, &ccd); box1.x = box1.y = box1.z = 1.; box2.x = box2.y = box2.z = 1.; ccdVec3Set(&axis, 0., 0., 1.); ccdQuatSetAngleAxis(&box1.quat, M_PI / 4., &axis); ccdVec3Set(&box1.pos, -0.5, 0.5, 0.); runBench(&box1, &box2, &ccd); runBench(&box2, &box1, &ccd); box1.x = box1.y = box1.z = 1.; ccdVec3Set(&axis, 0., 1., 1.); ccdQuatSetAngleAxis(&box1.quat, M_PI / 4., &axis); ccdVec3Set(&box1.pos, -0.5, 0.1, 0.4); runBench(&box1, &box2, &ccd); runBench(&box2, &box1, &ccd); box1.x = box1.y = box1.z = 1.; ccdVec3Set(&axis, 0., 1., 1.); ccdQuatSetAngleAxis(&box1.quat, M_PI / 4., &axis); ccdVec3Set(&axis, 1., 1., 1.); ccdQuatSetAngleAxis(&rot, M_PI / 4., &axis); ccdQuatMul(&box1.quat, &rot); ccdVec3Set(&box1.pos, -0.5, 0.1, 0.4); runBench(&box1, &box2, &ccd); runBench(&box2, &box1, &ccd); box1.x = box1.y = box1.z = 1.; box2.x = 0.2; box2.y = 0.5; box2.z = 1.; box2.x = box2.y = box2.z = 1.; ccdVec3Set(&axis, 0., 0., 1.); ccdQuatSetAngleAxis(&box1.quat, M_PI / 4., &axis); ccdVec3Set(&axis, 1., 0., 0.); ccdQuatSetAngleAxis(&rot, M_PI / 4., &axis); ccdQuatMul(&box1.quat, &rot); ccdVec3Set(&box1.pos, -1.3, 0., 0.); ccdVec3Set(&box2.pos, 0., 0., 0.); runBench(&box1, &box2, &ccd); runBench(&box2, &box1, &ccd); fprintf(stdout, "\n----\n\n"); } void cylcyl(void) { fprintf(stdout, "%s:\n", __func__); ccd_t ccd; CCD_CYL(cyl1); CCD_CYL(cyl2); ccd_vec3_t axis; cyl1.radius = 0.35; cyl1.height = 0.5; cyl2.radius = 0.5; cyl2.height = 1.; CCD_INIT(&ccd); ccd.support1 = ccdSupport; ccd.support2 = ccdSupport; runBench(&cyl1, &cyl2, &ccd); runBench(&cyl2, &cyl1, &ccd); ccdVec3Set(&cyl1.pos, 0.3, 0.1, 0.1); runBench(&cyl1, &cyl2, &ccd); runBench(&cyl2, &cyl1, &ccd); ccdVec3Set(&axis, 0., 1., 1.); ccdQuatSetAngleAxis(&cyl2.quat, M_PI / 4., &axis); ccdVec3Set(&cyl2.pos, 0., 0., 0.); runBench(&cyl1, &cyl2, &ccd); runBench(&cyl2, &cyl1, &ccd); ccdVec3Set(&axis, 0., 1., 1.); ccdQuatSetAngleAxis(&cyl2.quat, M_PI / 4., &axis); ccdVec3Set(&cyl2.pos, -0.2, 0.7, 0.2); runBench(&cyl1, &cyl2, &ccd); runBench(&cyl2, &cyl1, &ccd); ccdVec3Set(&axis, 0.567, 1.2, 1.); ccdQuatSetAngleAxis(&cyl2.quat, M_PI / 4., &axis); ccdVec3Set(&cyl2.pos, 0.6, -0.7, 0.2); runBench(&cyl1, &cyl2, &ccd); runBench(&cyl2, &cyl1, &ccd); ccdVec3Set(&axis, -4.567, 1.2, 0.); ccdQuatSetAngleAxis(&cyl2.quat, M_PI / 3., &axis); ccdVec3Set(&cyl2.pos, 0.6, -0.7, 0.2); runBench(&cyl1, &cyl2, &ccd); runBench(&cyl2, &cyl1, &ccd); fprintf(stdout, "\n----\n\n"); } void boxcyl(void) { fprintf(stdout, "%s:\n", __func__); ccd_t ccd; CCD_BOX(box); CCD_CYL(cyl); ccd_vec3_t axis; box.x = 0.5; box.y = 1.; box.z = 1.5; cyl.radius = 0.4; cyl.height = 0.7; CCD_INIT(&ccd); ccd.support1 = ccdSupport; ccd.support2 = ccdSupport; runBench(&box, &cyl, &ccd); runBench(&cyl, &box, &ccd); ccdVec3Set(&cyl.pos, .6, 0., 0.); runBench(&box, &cyl, &ccd); runBench(&cyl, &box, &ccd); ccdVec3Set(&cyl.pos, .6, 0.6, 0.); runBench(&box, &cyl, &ccd); runBench(&cyl, &box, &ccd); ccdVec3Set(&cyl.pos, .6, 0.6, 0.5); runBench(&box, &cyl, &ccd); runBench(&cyl, &box, &ccd); ccdVec3Set(&axis, 0., 1., 0.); ccdQuatSetAngleAxis(&cyl.quat, M_PI / 3., &axis); ccdVec3Set(&cyl.pos, .6, 0.6, 0.5); runBench(&box, &cyl, &ccd); runBench(&cyl, &box, &ccd); ccdVec3Set(&axis, 0.67, 1.1, 0.12); ccdQuatSetAngleAxis(&cyl.quat, M_PI / 4., &axis); ccdVec3Set(&cyl.pos, .6, 0., 0.5); runBench(&box, &cyl, &ccd); runBench(&cyl, &box, &ccd); ccdVec3Set(&axis, -0.1, 2.2, -1.); ccdQuatSetAngleAxis(&cyl.quat, M_PI / 5., &axis); ccdVec3Set(&cyl.pos, .6, 0., 0.5); ccdVec3Set(&axis, 1., 1., 0.); ccdQuatSetAngleAxis(&box.quat, -M_PI / 4., &axis); ccdVec3Set(&box.pos, .6, 0., 0.5); runBench(&box, &cyl, &ccd); runBench(&cyl, &box, &ccd); ccdVec3Set(&axis, -0.1, 2.2, -1.); ccdQuatSetAngleAxis(&cyl.quat, M_PI / 5., &axis); ccdVec3Set(&cyl.pos, .6, 0., 0.5); ccdVec3Set(&axis, 1., 1., 0.); ccdQuatSetAngleAxis(&box.quat, -M_PI / 4., &axis); ccdVec3Set(&box.pos, .9, 0.8, 0.5); runBench(&box, &cyl, &ccd); runBench(&cyl, &box, &ccd); fprintf(stdout, "\n----\n\n"); } int main(int argc, char *argv[]) { if (argc > 1){ cycles = atol(argv[1]); } fprintf(stdout, "Cycles: %u\n", cycles); fprintf(stdout, "\n"); boxbox(); cylcyl(); boxcyl(); return 0; } ode-0.16/libccd/src/testsuites/polytope.h0000664000175200017520000000051613403272463015413 00000000000000#ifndef TEST_POLYTOPE_H #define TEST_POLYTOPE_H #include TEST(ptSetUp); TEST(ptTearDown); TEST(ptCreate1); TEST(ptCreate2); TEST(ptNearest); TEST_SUITE(TSPt) { TEST_ADD(ptSetUp), TEST_ADD(ptCreate1), TEST_ADD(ptCreate2), TEST_ADD(ptNearest), TEST_ADD(ptTearDown), TEST_SUITE_CLOSURE }; #endif ode-0.16/libccd/src/testsuites/boxbox.c0000664000175200017520000002574313403272463015045 00000000000000#include #include #include #include "support.h" #include #include #include "common.h" TEST(boxboxSetUp) { } TEST(boxboxTearDown) { } TEST(boxboxAlignedX) { size_t i; ccd_t ccd; CCD_BOX(box1); CCD_BOX(box2); int res; CCD_INIT(&ccd); ccd.support1 = ccdSupport; ccd.support2 = ccdSupport; //ccd.max_iterations = 20; box1.x = 1; box1.y = 2; box1.z = 1; box2.x = 2; box2.y = 1; box2.z = 2; ccdVec3Set(&box1.pos, -5., 0., 0.); ccdVec3Set(&box2.pos, 0., 0., 0.); ccdQuatSet(&box1.quat, 0., 0., 0., 1.); ccdQuatSet(&box2.quat, 0., 0., 0., 1.); for (i = 0; i < 100; i++){ res = ccdGJKIntersect(&box1, &box2, &ccd); if (i < 35 || i > 65){ assertFalse(res); }else if (i != 35 && i != 65){ assertTrue(res); } box1.pos.v[0] += 0.1; } box1.x = 0.1; box1.y = 0.2; box1.z = 0.1; box2.x = 0.2; box2.y = 0.1; box2.z = 0.2; ccdVec3Set(&box1.pos, -0.5, 0., 0.); ccdVec3Set(&box2.pos, 0., 0., 0.); ccdQuatSet(&box1.quat, 0., 0., 0., 1.); ccdQuatSet(&box2.quat, 0., 0., 0., 1.); for (i = 0; i < 100; i++){ res = ccdGJKIntersect(&box1, &box2, &ccd); if (i < 35 || i > 65){ assertFalse(res); }else if (i != 35 && i != 65){ assertTrue(res); } box1.pos.v[0] += 0.01; } box1.x = 1; box1.y = 2; box1.z = 1; box2.x = 2; box2.y = 1; box2.z = 2; ccdVec3Set(&box1.pos, -5., -0.1, 0.); ccdVec3Set(&box2.pos, 0., 0., 0.); ccdQuatSet(&box1.quat, 0., 0., 0., 1.); ccdQuatSet(&box2.quat, 0., 0., 0., 1.); for (i = 0; i < 100; i++){ res = ccdGJKIntersect(&box1, &box2, &ccd); if (i < 35 || i > 65){ assertFalse(res); }else if (i != 35 && i != 65){ assertTrue(res); } box1.pos.v[0] += 0.1; } } TEST(boxboxAlignedY) { size_t i; ccd_t ccd; CCD_BOX(box1); CCD_BOX(box2); int res; CCD_INIT(&ccd); ccd.support1 = ccdSupport; ccd.support2 = ccdSupport; box1.x = 1; box1.y = 2; box1.z = 1; box2.x = 2; box2.y = 1; box2.z = 2; ccdVec3Set(&box1.pos, 0., -5., 0.); ccdVec3Set(&box2.pos, 0., 0., 0.); ccdQuatSet(&box1.quat, 0., 0., 0., 1.); ccdQuatSet(&box2.quat, 0., 0., 0., 1.); for (i = 0; i < 100; i++){ res = ccdGJKIntersect(&box1, &box2, &ccd); if (i < 35 || i > 65){ assertFalse(res); }else if (i != 35 && i != 65){ assertTrue(res); } box1.pos.v[1] += 0.1; } } TEST(boxboxAlignedZ) { size_t i; ccd_t ccd; CCD_BOX(box1); CCD_BOX(box2); int res; CCD_INIT(&ccd); ccd.support1 = ccdSupport; ccd.support2 = ccdSupport; box1.x = 1; box1.y = 2; box1.z = 1; box2.x = 2; box2.y = 1; box2.z = 2; ccdVec3Set(&box1.pos, 0., 0., -5.); ccdVec3Set(&box2.pos, 0., 0., 0.); ccdQuatSet(&box1.quat, 0., 0., 0., 1.); ccdQuatSet(&box2.quat, 0., 0., 0., 1.); for (i = 0; i < 100; i++){ res = ccdGJKIntersect(&box1, &box2, &ccd); if (i < 35 || i > 65){ assertFalse(res); }else if (i != 35 && i != 65){ assertTrue(res); } box1.pos.v[2] += 0.1; } } TEST(boxboxRot) { size_t i; ccd_t ccd; CCD_BOX(box1); CCD_BOX(box2); int res; ccd_vec3_t axis; ccd_real_t angle; CCD_INIT(&ccd); ccd.support1 = ccdSupport; ccd.support2 = ccdSupport; box1.x = 1; box1.y = 2; box1.z = 1; box2.x = 2; box2.y = 1; box2.z = 2; ccdVec3Set(&box1.pos, -5., 0.5, 0.); ccdVec3Set(&box2.pos, 0., 0., 0.); ccdQuatSet(&box2.quat, 0., 0., 0., 1.); ccdVec3Set(&axis, 0., 1., 0.); ccdQuatSetAngleAxis(&box1.quat, M_PI / 4., &axis); for (i = 0; i < 100; i++){ res = ccdGJKIntersect(&box1, &box2, &ccd); if (i < 33 || i > 67){ assertFalse(res); }else if (i != 33 && i != 67){ assertTrue(res); } box1.pos.v[0] += 0.1; } box1.x = 1; box1.y = 1; box1.z = 1; box2.x = 1; box2.y = 1; box2.z = 1; ccdVec3Set(&box1.pos, -1.01, 0., 0.); ccdVec3Set(&box2.pos, 0., 0., 0.); ccdQuatSet(&box1.quat, 0., 0., 0., 1.); ccdQuatSet(&box2.quat, 0., 0., 0., 1.); ccdVec3Set(&axis, 0., 1., 0.); angle = 0.; for (i = 0; i < 30; i++){ res = ccdGJKIntersect(&box1, &box2, &ccd); if (i != 0 && i != 10 && i != 20){ assertTrue(res); }else{ assertFalse(res); } angle += M_PI / 20.; ccdQuatSetAngleAxis(&box1.quat, angle, &axis); } } static void pConf(ccd_box_t *box1, ccd_box_t *box2, const ccd_vec3_t *v) { fprintf(stdout, "# box1.pos: [%lf %lf %lf]\n", ccdVec3X(&box1->pos), ccdVec3Y(&box1->pos), ccdVec3Z(&box1->pos)); fprintf(stdout, "# box1->quat: [%lf %lf %lf %lf]\n", box1->quat.q[0], box1->quat.q[1], box1->quat.q[2], box1->quat.q[3]); fprintf(stdout, "# box2->pos: [%lf %lf %lf]\n", ccdVec3X(&box2->pos), ccdVec3Y(&box2->pos), ccdVec3Z(&box2->pos)); fprintf(stdout, "# box2->quat: [%lf %lf %lf %lf]\n", box2->quat.q[0], box2->quat.q[1], box2->quat.q[2], box2->quat.q[3]); fprintf(stdout, "# sep: [%lf %lf %lf]\n", ccdVec3X(v), ccdVec3Y(v), ccdVec3Z(v)); fprintf(stdout, "#\n"); } TEST(boxboxSeparate) { ccd_t ccd; CCD_BOX(box1); CCD_BOX(box2); int res; ccd_vec3_t sep, expsep, expsep2, axis; fprintf(stderr, "\n\n\n---- boxboxSeparate ----\n\n\n"); box1.x = box1.y = box1.z = 1.; box2.x = 0.5; box2.y = 1.; box2.z = 1.5; CCD_INIT(&ccd); ccd.support1 = ccdSupport; ccd.support2 = ccdSupport; ccdVec3Set(&box1.pos, -0.5, 0.5, 0.2); res = ccdGJKIntersect(&box1, &box2, &ccd); assertTrue(res); res = ccdGJKSeparate(&box1, &box2, &ccd, &sep); assertTrue(res == 0); ccdVec3Set(&expsep, 0.25, 0., 0.); assertTrue(ccdVec3Eq(&sep, &expsep)); ccdVec3Scale(&sep, -1.); ccdVec3Add(&box1.pos, &sep); res = ccdGJKSeparate(&box1, &box2, &ccd, &sep); assertTrue(res == 0); ccdVec3Set(&expsep, 0., 0., 0.); assertTrue(ccdVec3Eq(&sep, &expsep)); ccdVec3Set(&box1.pos, -0.3, 0.5, 1.); res = ccdGJKSeparate(&box1, &box2, &ccd, &sep); assertTrue(res == 0); ccdVec3Set(&expsep, 0., 0., -0.25); assertTrue(ccdVec3Eq(&sep, &expsep)); box1.x = box1.y = box1.z = 1.; box2.x = box2.y = box2.z = 1.; ccdVec3Set(&axis, 0., 0., 1.); ccdQuatSetAngleAxis(&box1.quat, M_PI / 4., &axis); ccdVec3Set(&box1.pos, 0., 0., 0.); res = ccdGJKSeparate(&box1, &box2, &ccd, &sep); assertTrue(res == 0); ccdVec3Set(&expsep, 0., 0., 1.); ccdVec3Set(&expsep2, 0., 0., -1.); assertTrue(ccdVec3Eq(&sep, &expsep) || ccdVec3Eq(&sep, &expsep2)); box1.x = box1.y = box1.z = 1.; ccdVec3Set(&axis, 0., 0., 1.); ccdQuatSetAngleAxis(&box1.quat, M_PI / 4., &axis); ccdVec3Set(&box1.pos, -0.5, 0., 0.); res = ccdGJKSeparate(&box1, &box2, &ccd, &sep); assertTrue(res == 0); pConf(&box1, &box2, &sep); box1.x = box1.y = box1.z = 1.; ccdVec3Set(&axis, 0., 1., 1.); ccdQuatSetAngleAxis(&box1.quat, M_PI / 4., &axis); ccdVec3Set(&box1.pos, -0.5, 0.1, 0.4); res = ccdGJKSeparate(&box1, &box2, &ccd, &sep); assertTrue(res == 0); pConf(&box1, &box2, &sep); } #define TOSVT() \ svtObjPen(&box1, &box2, stdout, "Pen 1", depth, &dir, &pos); \ ccdVec3Scale(&dir, depth); \ ccdVec3Add(&box2.pos, &dir); \ svtObjPen(&box1, &box2, stdout, "Pen 1", depth, &dir, &pos) TEST(boxboxPenetration) { ccd_t ccd; CCD_BOX(box1); CCD_BOX(box2); int res; ccd_vec3_t axis; ccd_quat_t rot; ccd_real_t depth; ccd_vec3_t dir, pos; fprintf(stderr, "\n\n\n---- boxboxPenetration ----\n\n\n"); box1.x = box1.y = box1.z = 1.; box2.x = 0.5; box2.y = 1.; box2.z = 1.5; CCD_INIT(&ccd); ccd.support1 = ccdSupport; ccd.support2 = ccdSupport; ccdVec3Set(&box2.pos, 0.1, 0., 0.); res = ccdGJKPenetration(&box1, &box2, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 1"); //TOSVT(); ccdVec3Set(&box1.pos, -0.3, 0.5, 1.); res = ccdGJKPenetration(&box1, &box2, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 2"); //TOSVT(); <<< box1.x = box1.y = box1.z = 1.; box2.x = box2.y = box2.z = 1.; ccdVec3Set(&axis, 0., 0., 1.); ccdQuatSetAngleAxis(&box1.quat, M_PI / 4., &axis); ccdVec3Set(&box1.pos, 0.1, 0., 0.1); res = ccdGJKPenetration(&box1, &box2, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 3"); //TOSVT(); box1.x = box1.y = box1.z = 1.; box2.x = box2.y = box2.z = 1.; ccdVec3Set(&axis, 0., 0., 1.); ccdQuatSetAngleAxis(&box1.quat, M_PI / 4., &axis); ccdVec3Set(&box1.pos, -0.5, 0., 0.); res = ccdGJKPenetration(&box1, &box2, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 4"); //TOSVT(); box1.x = box1.y = box1.z = 1.; box2.x = box2.y = box2.z = 1.; ccdVec3Set(&axis, 0., 0., 1.); ccdQuatSetAngleAxis(&box1.quat, M_PI / 4., &axis); ccdVec3Set(&box1.pos, -0.5, 0.5, 0.); res = ccdGJKPenetration(&box1, &box2, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 5"); //TOSVT(); box1.x = box1.y = box1.z = 1.; box2.x = box2.y = box2.z = 1.; ccdVec3Set(&box2.pos, 0.1, 0., 0.); box1.x = box1.y = box1.z = 1.; ccdVec3Set(&axis, 0., 1., 1.); ccdQuatSetAngleAxis(&box1.quat, M_PI / 4., &axis); ccdVec3Set(&box1.pos, -0.5, 0.1, 0.4); res = ccdGJKPenetration(&box1, &box2, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 6"); //TOSVT(); box1.x = box1.y = box1.z = 1.; ccdVec3Set(&axis, 0., 1., 1.); ccdQuatSetAngleAxis(&box1.quat, M_PI / 4., &axis); ccdVec3Set(&axis, 1., 1., 1.); ccdQuatSetAngleAxis(&rot, M_PI / 4., &axis); ccdQuatMul(&box1.quat, &rot); ccdVec3Set(&box1.pos, -0.5, 0.1, 0.4); res = ccdGJKPenetration(&box1, &box2, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 7"); //TOSVT(); <<< box1.x = box1.y = box1.z = 1.; box2.x = 0.2; box2.y = 0.5; box2.z = 1.; box2.x = box2.y = box2.z = 1.; ccdVec3Set(&axis, 0., 0., 1.); ccdQuatSetAngleAxis(&box1.quat, M_PI / 4., &axis); ccdVec3Set(&axis, 1., 0., 0.); ccdQuatSetAngleAxis(&rot, M_PI / 4., &axis); ccdQuatMul(&box1.quat, &rot); ccdVec3Set(&box1.pos, -1.3, 0., 0.); ccdVec3Set(&box2.pos, 0., 0., 0.); res = ccdGJKPenetration(&box1, &box2, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 8"); //TOSVT(); } ode-0.16/libccd/src/testsuites/mpr_cylcyl.h0000664000175200017520000000055413403272463015717 00000000000000#ifndef MPR_CYL_CYL #define MPR_CYL_CYL #include TEST(mprCylcylAlignedX); TEST(mprCylcylAlignedY); TEST(mprCylcylAlignedZ); TEST(mprCylcylPenetration); TEST_SUITE(TSMPRCylCyl) { TEST_ADD(mprCylcylAlignedX), TEST_ADD(mprCylcylAlignedY), TEST_ADD(mprCylcylAlignedZ), TEST_ADD(mprCylcylPenetration), TEST_SUITE_CLOSURE }; #endif ode-0.16/libccd/src/testsuites/mpr_boxbox.c0000664000175200017520000003035413403272463015715 00000000000000#include #include #include #include "support.h" #include #include #include "common.h" TEST(mprBoxboxAlignedX) { size_t i; ccd_t ccd; CCD_BOX(box1); CCD_BOX(box2); int res; CCD_INIT(&ccd); ccd.support1 = ccdSupport; ccd.support2 = ccdSupport; ccd.center1 = ccdObjCenter; ccd.center2 = ccdObjCenter; box1.x = 1; box1.y = 2; box1.z = 1; box2.x = 2; box2.y = 1; box2.z = 2; ccdVec3Set(&box1.pos, -5., 0., 0.); ccdVec3Set(&box2.pos, 0., 0., 0.); ccdQuatSet(&box1.quat, 0., 0., 0., 1.); ccdQuatSet(&box2.quat, 0., 0., 0., 1.); for (i = 0; i < 100; i++){ res = ccdMPRIntersect(&box1, &box2, &ccd); if (i < 35 || i > 65){ assertFalse(res); }else if (i != 35 && i != 65){ assertTrue(res); } box1.pos.v[0] += 0.1; } box1.x = 0.1; box1.y = 0.2; box1.z = 0.1; box2.x = 0.2; box2.y = 0.1; box2.z = 0.2; ccdVec3Set(&box1.pos, -0.5, 0., 0.); ccdVec3Set(&box2.pos, 0., 0., 0.); ccdQuatSet(&box1.quat, 0., 0., 0., 1.); ccdQuatSet(&box2.quat, 0., 0., 0., 1.); for (i = 0; i < 100; i++){ res = ccdMPRIntersect(&box1, &box2, &ccd); if (i < 35 || i > 65){ assertFalse(res); }else if (i != 35 && i != 65){ assertTrue(res); } box1.pos.v[0] += 0.01; } box1.x = 1; box1.y = 2; box1.z = 1; box2.x = 2; box2.y = 1; box2.z = 2; ccdVec3Set(&box1.pos, -5., -0.1, 0.); ccdVec3Set(&box2.pos, 0., 0., 0.); ccdQuatSet(&box1.quat, 0., 0., 0., 1.); ccdQuatSet(&box2.quat, 0., 0., 0., 1.); for (i = 0; i < 100; i++){ res = ccdMPRIntersect(&box1, &box2, &ccd); if (i < 35 || i > 65){ assertFalse(res); }else if (i != 35 && i != 65){ assertTrue(res); } box1.pos.v[0] += 0.1; } } TEST(mprBoxboxAlignedY) { size_t i; ccd_t ccd; CCD_BOX(box1); CCD_BOX(box2); int res; CCD_INIT(&ccd); ccd.support1 = ccdSupport; ccd.support2 = ccdSupport; ccd.center1 = ccdObjCenter; ccd.center2 = ccdObjCenter; box1.x = 1; box1.y = 2; box1.z = 1; box2.x = 2; box2.y = 1; box2.z = 2; ccdVec3Set(&box1.pos, 0., -5., 0.); ccdVec3Set(&box2.pos, 0., 0., 0.); ccdQuatSet(&box1.quat, 0., 0., 0., 1.); ccdQuatSet(&box2.quat, 0., 0., 0., 1.); for (i = 0; i < 100; i++){ res = ccdMPRIntersect(&box1, &box2, &ccd); if (i < 35 || i > 65){ assertFalse(res); }else if (i != 35 && i != 65){ assertTrue(res); } box1.pos.v[1] += 0.1; } } TEST(mprBoxboxAlignedZ) { size_t i; ccd_t ccd; CCD_BOX(box1); CCD_BOX(box2); int res; CCD_INIT(&ccd); ccd.support1 = ccdSupport; ccd.support2 = ccdSupport; ccd.center1 = ccdObjCenter; ccd.center2 = ccdObjCenter; box1.x = 1; box1.y = 2; box1.z = 1; box2.x = 2; box2.y = 1; box2.z = 2; ccdVec3Set(&box1.pos, 0., 0., -5.); ccdVec3Set(&box2.pos, 0., 0., 0.); ccdQuatSet(&box1.quat, 0., 0., 0., 1.); ccdQuatSet(&box2.quat, 0., 0., 0., 1.); for (i = 0; i < 100; i++){ res = ccdMPRIntersect(&box1, &box2, &ccd); if (i < 35 || i > 65){ assertFalse(res); }else if (i != 35 && i != 65){ assertTrue(res); } box1.pos.v[2] += 0.1; } } TEST(mprBoxboxRot) { size_t i; ccd_t ccd; CCD_BOX(box1); CCD_BOX(box2); int res; ccd_vec3_t axis; ccd_real_t angle; CCD_INIT(&ccd); ccd.support1 = ccdSupport; ccd.support2 = ccdSupport; ccd.center1 = ccdObjCenter; ccd.center2 = ccdObjCenter; box1.x = 1; box1.y = 2; box1.z = 1; box2.x = 2; box2.y = 1; box2.z = 2; ccdVec3Set(&box1.pos, -5., 0.5, 0.); ccdVec3Set(&box2.pos, 0., 0., 0.); ccdQuatSet(&box2.quat, 0., 0., 0., 1.); ccdVec3Set(&axis, 0., 1., 0.); ccdQuatSetAngleAxis(&box1.quat, M_PI / 4., &axis); for (i = 0; i < 100; i++){ res = ccdMPRIntersect(&box1, &box2, &ccd); if (i < 33 || i > 67){ assertFalse(res); }else if (i != 33 && i != 67){ assertTrue(res); } box1.pos.v[0] += 0.1; } box1.x = 1; box1.y = 1; box1.z = 1; box2.x = 1; box2.y = 1; box2.z = 1; ccdVec3Set(&box1.pos, -1.01, 0., 0.); ccdVec3Set(&box2.pos, 0., 0., 0.); ccdQuatSet(&box1.quat, 0., 0., 0., 1.); ccdQuatSet(&box2.quat, 0., 0., 0., 1.); ccdVec3Set(&axis, 0., 1., 0.); angle = 0.; for (i = 0; i < 30; i++){ res = ccdMPRIntersect(&box1, &box2, &ccd); if (i != 0 && i != 10 && i != 20){ assertTrue(res); }else{ assertFalse(res); } angle += M_PI / 20.; ccdQuatSetAngleAxis(&box1.quat, angle, &axis); } } static void pConf(ccd_box_t *box1, ccd_box_t *box2, const ccd_vec3_t *v) { fprintf(stdout, "# box1.pos: [%lf %lf %lf]\n", ccdVec3X(&box1->pos), ccdVec3Y(&box1->pos), ccdVec3Z(&box1->pos)); fprintf(stdout, "# box1->quat: [%lf %lf %lf %lf]\n", box1->quat.q[0], box1->quat.q[1], box1->quat.q[2], box1->quat.q[3]); fprintf(stdout, "# box2->pos: [%lf %lf %lf]\n", ccdVec3X(&box2->pos), ccdVec3Y(&box2->pos), ccdVec3Z(&box2->pos)); fprintf(stdout, "# box2->quat: [%lf %lf %lf %lf]\n", box2->quat.q[0], box2->quat.q[1], box2->quat.q[2], box2->quat.q[3]); fprintf(stdout, "# sep: [%lf %lf %lf]\n", ccdVec3X(v), ccdVec3Y(v), ccdVec3Z(v)); fprintf(stdout, "#\n"); } TEST(mprBoxboxSeparate) { ccd_t ccd; CCD_BOX(box1); CCD_BOX(box2); int res; ccd_vec3_t sep, expsep, expsep2, axis; fprintf(stderr, "\n\n\n---- boxboxSeparate ----\n\n\n"); box1.x = box1.y = box1.z = 1.; box2.x = 0.5; box2.y = 1.; box2.z = 1.5; CCD_INIT(&ccd); ccd.support1 = ccdSupport; ccd.support2 = ccdSupport; ccdVec3Set(&box1.pos, -0.5, 0.5, 0.2); res = ccdMPRIntersect(&box1, &box2, &ccd); assertTrue(res); res = ccdGJKSeparate(&box1, &box2, &ccd, &sep); assertTrue(res == 0); ccdVec3Set(&expsep, 0.25, 0., 0.); assertTrue(ccdVec3Eq(&sep, &expsep)); ccdVec3Scale(&sep, -1.); ccdVec3Add(&box1.pos, &sep); res = ccdGJKSeparate(&box1, &box2, &ccd, &sep); assertTrue(res == 0); ccdVec3Set(&expsep, 0., 0., 0.); assertTrue(ccdVec3Eq(&sep, &expsep)); ccdVec3Set(&box1.pos, -0.3, 0.5, 1.); res = ccdGJKSeparate(&box1, &box2, &ccd, &sep); assertTrue(res == 0); ccdVec3Set(&expsep, 0., 0., -0.25); assertTrue(ccdVec3Eq(&sep, &expsep)); box1.x = box1.y = box1.z = 1.; box2.x = box2.y = box2.z = 1.; ccdVec3Set(&axis, 0., 0., 1.); ccdQuatSetAngleAxis(&box1.quat, M_PI / 4., &axis); ccdVec3Set(&box1.pos, 0., 0., 0.); res = ccdGJKSeparate(&box1, &box2, &ccd, &sep); assertTrue(res == 0); ccdVec3Set(&expsep, 0., 0., 1.); ccdVec3Set(&expsep2, 0., 0., -1.); assertTrue(ccdVec3Eq(&sep, &expsep) || ccdVec3Eq(&sep, &expsep2)); box1.x = box1.y = box1.z = 1.; ccdVec3Set(&axis, 0., 0., 1.); ccdQuatSetAngleAxis(&box1.quat, M_PI / 4., &axis); ccdVec3Set(&box1.pos, -0.5, 0., 0.); res = ccdGJKSeparate(&box1, &box2, &ccd, &sep); assertTrue(res == 0); pConf(&box1, &box2, &sep); box1.x = box1.y = box1.z = 1.; ccdVec3Set(&axis, 0., 1., 1.); ccdQuatSetAngleAxis(&box1.quat, M_PI / 4., &axis); ccdVec3Set(&box1.pos, -0.5, 0.1, 0.4); res = ccdGJKSeparate(&box1, &box2, &ccd, &sep); assertTrue(res == 0); pConf(&box1, &box2, &sep); } #define TOSVT() \ svtObjPen(&box1, &box2, stdout, "Pen 1", depth, &dir, &pos); \ ccdVec3Scale(&dir, depth); \ ccdVec3Add(&box2.pos, &dir); \ svtObjPen(&box1, &box2, stdout, "Pen 1", depth, &dir, &pos) TEST(mprBoxboxPenetration) { ccd_t ccd; CCD_BOX(box1); CCD_BOX(box2); int res; ccd_vec3_t axis; ccd_quat_t rot; ccd_real_t depth; ccd_vec3_t dir, pos; fprintf(stderr, "\n\n\n---- boxboxPenetration ----\n\n\n"); box1.x = box1.y = box1.z = 1.; box2.x = 0.5; box2.y = 1.; box2.z = 1.5; CCD_INIT(&ccd); ccd.support1 = ccdSupport; ccd.support2 = ccdSupport; ccd.center1 = ccdObjCenter; ccd.center2 = ccdObjCenter; /* ccdVec3Set(&box2.pos, 0., 0., 0.); res = ccdMPRPenetration(&box1, &box2, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 1"); TOSVT(); */ ccdVec3Set(&box2.pos, 0.1, 0., 0.); res = ccdMPRPenetration(&box1, &box2, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 1"); //TOSVT(); ccdVec3Set(&box1.pos, -0.3, 0.5, 1.); res = ccdMPRPenetration(&box1, &box2, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 2"); //TOSVT(); box1.x = box1.y = box1.z = 1.; box2.x = box2.y = box2.z = 1.; ccdVec3Set(&axis, 0., 0., 1.); ccdQuatSetAngleAxis(&box1.quat, M_PI / 4., &axis); ccdVec3Set(&box1.pos, 0.1, 0., 0.1); res = ccdMPRPenetration(&box1, &box2, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 3"); //TOSVT(); box1.x = box1.y = box1.z = 1.; box2.x = box2.y = box2.z = 1.; ccdVec3Set(&axis, 0., 0., 1.); ccdQuatSetAngleAxis(&box1.quat, M_PI / 4., &axis); ccdVec3Set(&box1.pos, -0.5, 0., 0.); res = ccdMPRPenetration(&box1, &box2, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 4"); //TOSVT(); box1.x = box1.y = box1.z = 1.; box2.x = box2.y = box2.z = 1.; ccdVec3Set(&axis, 0., 0., 1.); ccdQuatSetAngleAxis(&box1.quat, M_PI / 4., &axis); ccdVec3Set(&box1.pos, -0.5, 0.5, 0.); res = ccdMPRPenetration(&box1, &box2, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 5"); //TOSVT(); box1.x = box1.y = box1.z = 1.; box2.x = box2.y = box2.z = 1.; ccdVec3Set(&box2.pos, 0.1, 0., 0.); box1.x = box1.y = box1.z = 1.; ccdVec3Set(&axis, 0., 1., 1.); ccdQuatSetAngleAxis(&box1.quat, M_PI / 4., &axis); ccdVec3Set(&box1.pos, -0.5, 0.1, 0.4); res = ccdMPRPenetration(&box1, &box2, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 6"); //TOSVT(); box1.x = box1.y = box1.z = 1.; ccdVec3Set(&axis, 0., 1., 1.); ccdQuatSetAngleAxis(&box1.quat, M_PI / 4., &axis); ccdVec3Set(&axis, 1., 1., 1.); ccdQuatSetAngleAxis(&rot, M_PI / 4., &axis); ccdQuatMul(&box1.quat, &rot); ccdVec3Set(&box1.pos, -0.5, 0.1, 0.4); res = ccdMPRPenetration(&box1, &box2, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 7"); //TOSVT(); box1.x = box1.y = box1.z = 1.; box2.x = 0.2; box2.y = 0.5; box2.z = 1.; box2.x = box2.y = box2.z = 1.; ccdVec3Set(&axis, 0., 0., 1.); ccdQuatSetAngleAxis(&box1.quat, M_PI / 4., &axis); ccdVec3Set(&axis, 1., 0., 0.); ccdQuatSetAngleAxis(&rot, M_PI / 4., &axis); ccdQuatMul(&box1.quat, &rot); ccdVec3Set(&box1.pos, -1.3, 0., 0.); ccdVec3Set(&box2.pos, 0., 0., 0.); res = ccdMPRPenetration(&box1, &box2, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 8"); //TOSVT(); box1.x = box1.y = box1.z = 1.; box2.x = 0.5; box2.y = 0.5; box2.z = .5; ccdVec3Set(&box1.pos, 0., 0., 0.); ccdQuatSet(&box1.quat, 0., 0., 0., 1.); ccdVec3Set(&box2.pos, 0., 0.73, 0.); ccdQuatSet(&box2.quat, 0., 0., 0., 1.); res = ccdMPRPenetration(&box1, &box2, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 9"); //TOSVT(); box1.x = box1.y = box1.z = 1.; box2.x = 0.5; box2.y = 0.5; box2.z = .5; ccdVec3Set(&box1.pos, 0., 0., 0.); ccdQuatSet(&box1.quat, 0., 0., 0., 1.); ccdVec3Set(&box2.pos, 0.3, 0.738, 0.); ccdQuatSet(&box2.quat, 0., 0., 0., 1.); res = ccdMPRPenetration(&box1, &box2, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 10"); //TOSVT(); } ode-0.16/libccd/src/testsuites/mpr_boxbox.h0000664000175200017520000000072713403272463015723 00000000000000#ifndef MPR_BOX_BOX #define MPR_BOX_BOX #include TEST(mprBoxboxAlignedX); TEST(mprBoxboxAlignedY); TEST(mprBoxboxAlignedZ); TEST(mprBoxboxRot); TEST(mprBoxboxSeparate); TEST(mprBoxboxPenetration); TEST_SUITE(TSMPRBoxBox) { TEST_ADD(mprBoxboxAlignedX), TEST_ADD(mprBoxboxAlignedY), TEST_ADD(mprBoxboxAlignedZ), TEST_ADD(mprBoxboxRot), //TEST_ADD(mprBoxboxSeparate), TEST_ADD(mprBoxboxPenetration), TEST_SUITE_CLOSURE }; #endif ode-0.16/libccd/src/testsuites/mpr_cylcyl.c0000664000175200017520000001013513403272463015706 00000000000000#include #include #include #include "support.h" #include "common.h" TEST(mprCylcylAlignedX) { ccd_t ccd; CCD_CYL(c1); CCD_CYL(c2); size_t i; int res; CCD_INIT(&ccd); ccd.support1 = ccdSupport; ccd.support2 = ccdSupport; ccd.center1 = ccdObjCenter; ccd.center2 = ccdObjCenter; c1.radius = 0.35; c1.height = 0.5; c2.radius = 0.5; c2.height = 1.; ccdVec3Set(&c1.pos, -5., 0., 0.); for (i = 0; i < 100; i++){ res = ccdMPRIntersect(&c1, &c2, &ccd); if (i < 42 || i > 58){ assertFalse(res); }else{ assertTrue(res); } c1.pos.v[0] += 0.1; } } TEST(mprCylcylAlignedY) { ccd_t ccd; CCD_CYL(c1); CCD_CYL(c2); size_t i; int res; CCD_INIT(&ccd); ccd.support1 = ccdSupport; ccd.support2 = ccdSupport; ccd.center1 = ccdObjCenter; ccd.center2 = ccdObjCenter; c1.radius = 0.35; c1.height = 0.5; c2.radius = 0.5; c2.height = 1.; ccdVec3Set(&c1.pos, 0., -5., 0.); for (i = 0; i < 100; i++){ res = ccdMPRIntersect(&c1, &c2, &ccd); if (i < 42 || i > 58){ assertFalse(res); }else{ assertTrue(res); } c1.pos.v[1] += 0.1; } } TEST(mprCylcylAlignedZ) { ccd_t ccd; CCD_CYL(c1); CCD_CYL(c2); size_t i; int res; CCD_INIT(&ccd); ccd.support1 = ccdSupport; ccd.support2 = ccdSupport; ccd.center1 = ccdObjCenter; ccd.center2 = ccdObjCenter; c1.radius = 0.35; c1.height = 0.5; c2.radius = 0.5; c2.height = 1.; ccdVec3Set(&c1.pos, 0., 0., -5.); for (i = 0; i < 100; i++){ res = ccdMPRIntersect(&c1, &c2, &ccd); if (i < 43 || i > 57){ assertFalse(res); }else{ assertTrue(res); } c1.pos.v[2] += 0.1; } } #define TOSVT() \ svtObjPen(&cyl1, &cyl2, stdout, "Pen 1", depth, &dir, &pos); \ ccdVec3Scale(&dir, depth); \ ccdVec3Add(&cyl2.pos, &dir); \ svtObjPen(&cyl1, &cyl2, stdout, "Pen 1", depth, &dir, &pos) TEST(mprCylcylPenetration) { ccd_t ccd; CCD_CYL(cyl1); CCD_CYL(cyl2); int res; ccd_vec3_t axis; ccd_real_t depth; ccd_vec3_t dir, pos; fprintf(stderr, "\n\n\n---- mprCylcylPenetration ----\n\n\n"); cyl1.radius = 0.35; cyl1.height = 0.5; cyl2.radius = 0.5; cyl2.height = 1.; CCD_INIT(&ccd); ccd.support1 = ccdSupport; ccd.support2 = ccdSupport; ccd.center1 = ccdObjCenter; ccd.center2 = ccdObjCenter; ccdVec3Set(&cyl2.pos, 0., 0., 0.3); res = ccdMPRPenetration(&cyl1, &cyl2, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 1"); //TOSVT(); ccdVec3Set(&cyl1.pos, 0.3, 0.1, 0.1); res = ccdMPRPenetration(&cyl1, &cyl2, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 2"); //TOSVT(); ccdVec3Set(&axis, 0., 1., 1.); ccdQuatSetAngleAxis(&cyl2.quat, M_PI / 4., &axis); ccdVec3Set(&cyl2.pos, 0., 0., 0.); res = ccdMPRPenetration(&cyl1, &cyl2, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 3"); //TOSVT(); ccdVec3Set(&axis, 0., 1., 1.); ccdQuatSetAngleAxis(&cyl2.quat, M_PI / 4., &axis); ccdVec3Set(&cyl2.pos, -0.2, 0.7, 0.2); res = ccdMPRPenetration(&cyl1, &cyl2, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 4"); //TOSVT(); ccdVec3Set(&axis, 0.567, 1.2, 1.); ccdQuatSetAngleAxis(&cyl2.quat, M_PI / 4., &axis); ccdVec3Set(&cyl2.pos, 0.6, -0.7, 0.2); res = ccdMPRPenetration(&cyl1, &cyl2, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 5"); //TOSVT(); ccdVec3Set(&axis, -4.567, 1.2, 0.); ccdQuatSetAngleAxis(&cyl2.quat, M_PI / 3., &axis); ccdVec3Set(&cyl2.pos, 0.6, -0.7, 0.2); res = ccdMPRPenetration(&cyl1, &cyl2, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 6"); //TOSVT(); } ode-0.16/libccd/src/testsuites/cylcyl.c0000664000175200017520000000757713403272463015050 00000000000000#include #include #include #include "support.h" #include "common.h" TEST(cylcylSetUp) { } TEST(cylcylTearDown) { } TEST(cylcylAlignedX) { ccd_t ccd; CCD_CYL(c1); CCD_CYL(c2); size_t i; int res; CCD_INIT(&ccd); ccd.support1 = ccdSupport; ccd.support2 = ccdSupport; c1.radius = 0.35; c1.height = 0.5; c2.radius = 0.5; c2.height = 1.; ccdVec3Set(&c1.pos, -5., 0., 0.); for (i = 0; i < 100; i++){ res = ccdGJKIntersect(&c1, &c2, &ccd); if (i < 42 || i > 58){ assertFalse(res); }else{ assertTrue(res); } c1.pos.v[0] += 0.1; } } TEST(cylcylAlignedY) { ccd_t ccd; CCD_CYL(c1); CCD_CYL(c2); size_t i; int res; CCD_INIT(&ccd); ccd.support1 = ccdSupport; ccd.support2 = ccdSupport; c1.radius = 0.35; c1.height = 0.5; c2.radius = 0.5; c2.height = 1.; ccdVec3Set(&c1.pos, 0., -5., 0.); for (i = 0; i < 100; i++){ res = ccdGJKIntersect(&c1, &c2, &ccd); if (i < 42 || i > 58){ assertFalse(res); }else{ assertTrue(res); } c1.pos.v[1] += 0.1; } } TEST(cylcylAlignedZ) { ccd_t ccd; CCD_CYL(c1); CCD_CYL(c2); size_t i; int res; CCD_INIT(&ccd); ccd.support1 = ccdSupport; ccd.support2 = ccdSupport; c1.radius = 0.35; c1.height = 0.5; c2.radius = 0.5; c2.height = 1.; ccdVec3Set(&c1.pos, 0., 0., -5.); for (i = 0; i < 100; i++){ res = ccdGJKIntersect(&c1, &c2, &ccd); if (i < 43 || i > 57){ assertFalse(res); }else{ assertTrue(res); } c1.pos.v[2] += 0.1; } } #define TOSVT() \ svtObjPen(&cyl1, &cyl2, stdout, "Pen 1", depth, &dir, &pos); \ ccdVec3Scale(&dir, depth); \ ccdVec3Add(&cyl2.pos, &dir); \ svtObjPen(&cyl1, &cyl2, stdout, "Pen 1", depth, &dir, &pos) TEST(cylcylPenetrationEPA) { ccd_t ccd; CCD_CYL(cyl1); CCD_CYL(cyl2); int res; ccd_vec3_t axis; ccd_real_t depth; ccd_vec3_t dir, pos; fprintf(stderr, "\n\n\n---- cylcylPenetration ----\n\n\n"); cyl1.radius = 0.35; cyl1.height = 0.5; cyl2.radius = 0.5; cyl2.height = 1.; CCD_INIT(&ccd); ccd.support1 = ccdSupport; ccd.support2 = ccdSupport; ccdVec3Set(&cyl2.pos, 0., 0., 0.3); res = ccdGJKPenetration(&cyl1, &cyl2, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 1"); //TOSVT(); ccdVec3Set(&cyl1.pos, 0.3, 0.1, 0.1); res = ccdGJKPenetration(&cyl1, &cyl2, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 2"); //TOSVT(); <<< ccdVec3Set(&axis, 0., 1., 1.); ccdQuatSetAngleAxis(&cyl2.quat, M_PI / 4., &axis); ccdVec3Set(&cyl2.pos, 0., 0., 0.); res = ccdGJKPenetration(&cyl1, &cyl2, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 3"); //TOSVT(); ccdVec3Set(&axis, 0., 1., 1.); ccdQuatSetAngleAxis(&cyl2.quat, M_PI / 4., &axis); ccdVec3Set(&cyl2.pos, -0.2, 0.7, 0.2); res = ccdGJKPenetration(&cyl1, &cyl2, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 4"); //TOSVT(); ccdVec3Set(&axis, 0.567, 1.2, 1.); ccdQuatSetAngleAxis(&cyl2.quat, M_PI / 4., &axis); ccdVec3Set(&cyl2.pos, 0.6, -0.7, 0.2); res = ccdGJKPenetration(&cyl1, &cyl2, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 5"); //TOSVT(); ccdVec3Set(&axis, -4.567, 1.2, 0.); ccdQuatSetAngleAxis(&cyl2.quat, M_PI / 3., &axis); ccdVec3Set(&cyl2.pos, 0.6, -0.7, 0.2); res = ccdGJKPenetration(&cyl1, &cyl2, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 6"); //TOSVT(); } ode-0.16/libccd/src/testsuites/bench2.c0000664000175200017520000001505013403272463014673 00000000000000#define CU_ENABLE_TIMER #include #include #include #include #include "support.h" TEST_SUITES { TEST_SUITES_CLOSURE }; static int bench_num = 1; static size_t cycles = 10000; static void runBench(const void *o1, const void *o2, const ccd_t *ccd) { ccd_real_t depth; ccd_vec3_t dir, pos; int res; size_t i; const struct timespec *timer; cuTimerStart(); for (i = 0; i < cycles; i++){ res = ccdMPRPenetration(o1, o2, ccd, &depth, &dir, &pos); } timer = cuTimerStop(); fprintf(stdout, "%02d: %ld %ld\n", bench_num, (long)timer->tv_sec, (long)timer->tv_nsec); fflush(stdout); bench_num++; } static void boxbox(void) { fprintf(stdout, "%s:\n", __func__); ccd_t ccd; CCD_BOX(box1); CCD_BOX(box2); ccd_vec3_t axis; ccd_quat_t rot; box1.x = box1.y = box1.z = 1.; box2.x = 0.5; box2.y = 1.; box2.z = 1.5; bench_num = 1; CCD_INIT(&ccd); ccd.support1 = ccdSupport; ccd.support2 = ccdSupport; ccd.center1 = ccdObjCenter; ccd.center2 = ccdObjCenter; runBench(&box1, &box2, &ccd); runBench(&box2, &box1, &ccd); ccdVec3Set(&box1.pos, -0.3, 0.5, 1.); runBench(&box1, &box2, &ccd); runBench(&box2, &box1, &ccd); box1.x = box1.y = box1.z = 1.; box2.x = box2.y = box2.z = 1.; ccdVec3Set(&axis, 0., 0., 1.); ccdQuatSetAngleAxis(&box1.quat, M_PI / 4., &axis); ccdVec3Set(&box1.pos, 0., 0., 0.); runBench(&box1, &box2, &ccd); runBench(&box2, &box1, &ccd); box1.x = box1.y = box1.z = 1.; box2.x = box2.y = box2.z = 1.; ccdVec3Set(&axis, 0., 0., 1.); ccdQuatSetAngleAxis(&box1.quat, M_PI / 4., &axis); ccdVec3Set(&box1.pos, -0.5, 0., 0.); runBench(&box1, &box2, &ccd); runBench(&box2, &box1, &ccd); box1.x = box1.y = box1.z = 1.; box2.x = box2.y = box2.z = 1.; ccdVec3Set(&axis, 0., 0., 1.); ccdQuatSetAngleAxis(&box1.quat, M_PI / 4., &axis); ccdVec3Set(&box1.pos, -0.5, 0.5, 0.); runBench(&box1, &box2, &ccd); runBench(&box2, &box1, &ccd); box1.x = box1.y = box1.z = 1.; ccdVec3Set(&axis, 0., 1., 1.); ccdQuatSetAngleAxis(&box1.quat, M_PI / 4., &axis); ccdVec3Set(&box1.pos, -0.5, 0.1, 0.4); runBench(&box1, &box2, &ccd); runBench(&box2, &box1, &ccd); box1.x = box1.y = box1.z = 1.; ccdVec3Set(&axis, 0., 1., 1.); ccdQuatSetAngleAxis(&box1.quat, M_PI / 4., &axis); ccdVec3Set(&axis, 1., 1., 1.); ccdQuatSetAngleAxis(&rot, M_PI / 4., &axis); ccdQuatMul(&box1.quat, &rot); ccdVec3Set(&box1.pos, -0.5, 0.1, 0.4); runBench(&box1, &box2, &ccd); runBench(&box2, &box1, &ccd); box1.x = box1.y = box1.z = 1.; box2.x = 0.2; box2.y = 0.5; box2.z = 1.; box2.x = box2.y = box2.z = 1.; ccdVec3Set(&axis, 0., 0., 1.); ccdQuatSetAngleAxis(&box1.quat, M_PI / 4., &axis); ccdVec3Set(&axis, 1., 0., 0.); ccdQuatSetAngleAxis(&rot, M_PI / 4., &axis); ccdQuatMul(&box1.quat, &rot); ccdVec3Set(&box1.pos, -1.3, 0., 0.); ccdVec3Set(&box2.pos, 0., 0., 0.); runBench(&box1, &box2, &ccd); runBench(&box2, &box1, &ccd); fprintf(stdout, "\n----\n\n"); } void cylcyl(void) { fprintf(stdout, "%s:\n", __func__); ccd_t ccd; CCD_CYL(cyl1); CCD_CYL(cyl2); ccd_vec3_t axis; cyl1.radius = 0.35; cyl1.height = 0.5; cyl2.radius = 0.5; cyl2.height = 1.; CCD_INIT(&ccd); ccd.support1 = ccdSupport; ccd.support2 = ccdSupport; ccd.center1 = ccdObjCenter; ccd.center2 = ccdObjCenter; runBench(&cyl1, &cyl2, &ccd); runBench(&cyl2, &cyl1, &ccd); ccdVec3Set(&cyl1.pos, 0.3, 0.1, 0.1); runBench(&cyl1, &cyl2, &ccd); runBench(&cyl2, &cyl1, &ccd); ccdVec3Set(&axis, 0., 1., 1.); ccdQuatSetAngleAxis(&cyl2.quat, M_PI / 4., &axis); ccdVec3Set(&cyl2.pos, 0., 0., 0.); runBench(&cyl1, &cyl2, &ccd); runBench(&cyl2, &cyl1, &ccd); ccdVec3Set(&axis, 0., 1., 1.); ccdQuatSetAngleAxis(&cyl2.quat, M_PI / 4., &axis); ccdVec3Set(&cyl2.pos, -0.2, 0.7, 0.2); runBench(&cyl1, &cyl2, &ccd); runBench(&cyl2, &cyl1, &ccd); ccdVec3Set(&axis, 0.567, 1.2, 1.); ccdQuatSetAngleAxis(&cyl2.quat, M_PI / 4., &axis); ccdVec3Set(&cyl2.pos, 0.6, -0.7, 0.2); runBench(&cyl1, &cyl2, &ccd); runBench(&cyl2, &cyl1, &ccd); ccdVec3Set(&axis, -4.567, 1.2, 0.); ccdQuatSetAngleAxis(&cyl2.quat, M_PI / 3., &axis); ccdVec3Set(&cyl2.pos, 0.6, -0.7, 0.2); runBench(&cyl1, &cyl2, &ccd); runBench(&cyl2, &cyl1, &ccd); fprintf(stdout, "\n----\n\n"); } void boxcyl(void) { fprintf(stdout, "%s:\n", __func__); ccd_t ccd; CCD_BOX(box); CCD_CYL(cyl); ccd_vec3_t axis; box.x = 0.5; box.y = 1.; box.z = 1.5; cyl.radius = 0.4; cyl.height = 0.7; CCD_INIT(&ccd); ccd.support1 = ccdSupport; ccd.support2 = ccdSupport; ccd.center1 = ccdObjCenter; ccd.center2 = ccdObjCenter; runBench(&box, &cyl, &ccd); runBench(&cyl, &box, &ccd); ccdVec3Set(&cyl.pos, .6, 0., 0.); runBench(&box, &cyl, &ccd); runBench(&cyl, &box, &ccd); ccdVec3Set(&cyl.pos, .6, 0.6, 0.); runBench(&box, &cyl, &ccd); runBench(&cyl, &box, &ccd); ccdVec3Set(&cyl.pos, .6, 0.6, 0.5); runBench(&box, &cyl, &ccd); runBench(&cyl, &box, &ccd); ccdVec3Set(&axis, 0., 1., 0.); ccdQuatSetAngleAxis(&cyl.quat, M_PI / 3., &axis); ccdVec3Set(&cyl.pos, .6, 0.6, 0.5); runBench(&box, &cyl, &ccd); runBench(&cyl, &box, &ccd); ccdVec3Set(&axis, 0.67, 1.1, 0.12); ccdQuatSetAngleAxis(&cyl.quat, M_PI / 4., &axis); ccdVec3Set(&cyl.pos, .6, 0., 0.5); runBench(&box, &cyl, &ccd); runBench(&cyl, &box, &ccd); ccdVec3Set(&axis, -0.1, 2.2, -1.); ccdQuatSetAngleAxis(&cyl.quat, M_PI / 5., &axis); ccdVec3Set(&cyl.pos, .6, 0., 0.5); ccdVec3Set(&axis, 1., 1., 0.); ccdQuatSetAngleAxis(&box.quat, -M_PI / 4., &axis); ccdVec3Set(&box.pos, .6, 0., 0.5); runBench(&box, &cyl, &ccd); runBench(&cyl, &box, &ccd); ccdVec3Set(&axis, -0.1, 2.2, -1.); ccdQuatSetAngleAxis(&cyl.quat, M_PI / 5., &axis); ccdVec3Set(&cyl.pos, .6, 0., 0.5); ccdVec3Set(&axis, 1., 1., 0.); ccdQuatSetAngleAxis(&box.quat, -M_PI / 4., &axis); ccdVec3Set(&box.pos, .9, 0.8, 0.5); runBench(&box, &cyl, &ccd); runBench(&cyl, &box, &ccd); fprintf(stdout, "\n----\n\n"); } int main(int argc, char *argv[]) { if (argc > 1){ cycles = atol(argv[1]); } fprintf(stdout, "Cycles: %u\n", cycles); fprintf(stdout, "\n"); boxbox(); cylcyl(); boxcyl(); return 0; } ode-0.16/libccd/src/testsuites/support.c0000664000175200017520000000514213403272463015247 00000000000000/*** * libccd * --------------------------------- * Copyright (c)2010 Daniel Fiser * * * This file is part of libccd. * * Distributed under the OSI-approved BSD License (the "License"); * see accompanying file BDS-LICENSE for details or see * . * * This software is distributed WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the License for more information. */ #include #include #include #include "support.h" void ccdSupport(const void *_obj, const ccd_vec3_t *_dir, ccd_vec3_t *v) { // Support function is made according to Gino van den Bergen's paper // A Fast and Robust CCD Implementation for Collision Detection of // Convex Objects ccd_obj_t *obj = (ccd_obj_t *)_obj; ccd_vec3_t dir; ccd_quat_t qinv; ccdVec3Copy(&dir, _dir); ccdQuatInvert2(&qinv, &obj->quat); ccdQuatRotVec(&dir, &qinv); if (obj->type == CCD_OBJ_BOX){ ccd_box_t *box = (ccd_box_t *)obj; ccdVec3Set(v, ccdSign(ccdVec3X(&dir)) * box->x * CCD_REAL(0.5), ccdSign(ccdVec3Y(&dir)) * box->y * CCD_REAL(0.5), ccdSign(ccdVec3Z(&dir)) * box->z * CCD_REAL(0.5)); }else if (obj->type == CCD_OBJ_SPHERE){ ccd_sphere_t *sphere = (ccd_sphere_t *)obj; ccd_real_t len; len = ccdVec3Len2(&dir); if (len - CCD_EPS > CCD_ZERO){ ccdVec3Copy(v, &dir); ccdVec3Scale(v, sphere->radius / CCD_SQRT(len)); }else{ ccdVec3Set(v, CCD_ZERO, CCD_ZERO, CCD_ZERO); } }else if (obj->type == CCD_OBJ_CYL){ ccd_cyl_t *cyl = (ccd_cyl_t *)obj; ccd_real_t zdist, rad; zdist = dir.v[0] * dir.v[0] + dir.v[1] * dir.v[1]; zdist = CCD_SQRT(zdist); if (ccdIsZero(zdist)){ ccdVec3Set(v, CCD_ZERO, CCD_ZERO, ccdSign(ccdVec3Z(&dir)) * cyl->height * CCD_REAL(0.5)); }else{ rad = cyl->radius / zdist; ccdVec3Set(v, rad * ccdVec3X(&dir), rad * ccdVec3Y(&dir), ccdSign(ccdVec3Z(&dir)) * cyl->height * CCD_REAL(0.5)); } } // transform support vertex ccdQuatRotVec(v, &obj->quat); ccdVec3Add(v, &obj->pos); } void ccdObjCenter(const void *_obj, ccd_vec3_t *center) { ccd_obj_t *obj = (ccd_obj_t *)_obj; ccdVec3Set(center, CCD_ZERO, CCD_ZERO, CCD_ZERO); // rotation is not needed ccdVec3Add(center, &obj->pos); } ode-0.16/libccd/src/testsuites/vec3.c0000664000175200017520000001773013403272463014401 00000000000000#include #include #include TEST(vec3SetUp) { } TEST(vec3TearDown) { } TEST(vec3PointSegmentDist) { ccd_vec3_t P, a, b, w, ew; ccd_real_t dist; ccdVec3Set(&a, 0., 0., 0.); ccdVec3Set(&b, 1., 0., 0.); // extereme w == a ccdVec3Set(&P, -1., 0., 0.); dist = ccdVec3PointSegmentDist2(&P, &a, &b, &w); assertTrue(ccdEq(dist, 1.)); assertTrue(ccdVec3Eq(&w, &a)); ccdVec3Set(&P, -0.5, 0., 0.); dist = ccdVec3PointSegmentDist2(&P, &a, &b, &w); assertTrue(ccdEq(dist, 0.5 * 0.5)); assertTrue(ccdVec3Eq(&w, &a)); ccdVec3Set(&P, -0.1, 0., 0.); dist = ccdVec3PointSegmentDist2(&P, &a, &b, &w); assertTrue(ccdEq(dist, .1 * .1)); assertTrue(ccdVec3Eq(&w, &a)); ccdVec3Set(&P, 0., 0., 0.); dist = ccdVec3PointSegmentDist2(&P, &a, &b, &w); assertTrue(ccdEq(dist, 0.)); assertTrue(ccdVec3Eq(&w, &a)); ccdVec3Set(&P, -1., 1., 0.); dist = ccdVec3PointSegmentDist2(&P, &a, &b, &w); assertTrue(ccdEq(dist, 2.)); assertTrue(ccdVec3Eq(&w, &a)); ccdVec3Set(&P, -0.5, 0.5, 0.); dist = ccdVec3PointSegmentDist2(&P, &a, &b, &w); assertTrue(ccdEq(dist, 0.5)); assertTrue(ccdVec3Eq(&w, &a)); ccdVec3Set(&P, -0.1, -1., 2.); dist = ccdVec3PointSegmentDist2(&P, &a, &b, &w); assertTrue(ccdEq(dist, 5.01)); assertTrue(ccdVec3Eq(&w, &a)); // extereme w == b ccdVec3Set(&P, 2., 0., 0.); dist = ccdVec3PointSegmentDist2(&P, &a, &b, &w); assertTrue(ccdEq(dist, 1.)); assertTrue(ccdVec3Eq(&w, &b)); ccdVec3Set(&P, 1.5, 0., 0.); dist = ccdVec3PointSegmentDist2(&P, &a, &b, &w); assertTrue(ccdEq(dist, 0.5 * 0.5)); assertTrue(ccdVec3Eq(&w, &b)); ccdVec3Set(&P, 1.1, 0., 0.); dist = ccdVec3PointSegmentDist2(&P, &a, &b, &w); assertTrue(ccdEq(dist, .1 * .1)); assertTrue(ccdVec3Eq(&w, &b)); ccdVec3Set(&P, 1., 0., 0.); dist = ccdVec3PointSegmentDist2(&P, &a, &b, &w); assertTrue(ccdEq(dist, 0.)); assertTrue(ccdVec3Eq(&w, &b)); ccdVec3Set(&P, 2., 1., 0.); dist = ccdVec3PointSegmentDist2(&P, &a, &b, &w); assertTrue(ccdEq(dist, 2.)); assertTrue(ccdVec3Eq(&w, &b)); ccdVec3Set(&P, 1.5, 0.5, 0.); dist = ccdVec3PointSegmentDist2(&P, &a, &b, &w); assertTrue(ccdEq(dist, 0.5)); assertTrue(ccdVec3Eq(&w, &b)); ccdVec3Set(&P, 1.1, -1., 2.); dist = ccdVec3PointSegmentDist2(&P, &a, &b, &w); assertTrue(ccdEq(dist, 5.01)); assertTrue(ccdVec3Eq(&w, &b)); // inside segment ccdVec3Set(&P, .5, 0., 0.); dist = ccdVec3PointSegmentDist2(&P, &a, &b, &w); assertTrue(ccdEq(dist, 0.)); assertTrue(ccdVec3Eq(&w, &P)); ccdVec3Set(&P, .9, 0., 0.); dist = ccdVec3PointSegmentDist2(&P, &a, &b, &w); assertTrue(ccdEq(dist, 0.)); assertTrue(ccdVec3Eq(&w, &P)); ccdVec3Set(&P, .5, 1., 0.); dist = ccdVec3PointSegmentDist2(&P, &a, &b, &w); assertTrue(ccdEq(dist, 1.)); ccdVec3Set(&ew, 0.5, 0., 0.); assertTrue(ccdVec3Eq(&w, &ew)); ccdVec3Set(&P, .5, 1., 1.); dist = ccdVec3PointSegmentDist2(&P, &a, &b, &w); assertTrue(ccdEq(dist, 2.)); ccdVec3Set(&ew, 0.5, 0., 0.); assertTrue(ccdVec3Eq(&w, &ew)); ccdVec3Set(&a, -.5, 2., 1.); ccdVec3Set(&b, 1., 1.5, 0.5); // extereme w == a ccdVec3Set(&P, -10., 0., 0.); dist = ccdVec3PointSegmentDist2(&P, &a, &b, &w); assertTrue(ccdEq(dist, 9.5 * 9.5 + 2. * 2. + 1.)); assertTrue(ccdVec3Eq(&w, &a)); ccdVec3Set(&P, -10., 9.2, 3.4); dist = ccdVec3PointSegmentDist2(&P, &a, &b, &w); assertTrue(ccdEq(dist, 9.5 * 9.5 + 7.2 * 7.2 + 2.4 * 2.4)); assertTrue(ccdVec3Eq(&w, &a)); // extereme w == b ccdVec3Set(&P, 10., 0., 0.); dist = ccdVec3PointSegmentDist2(&P, &a, &b, &w); assertTrue(ccdEq(dist, 9. * 9. + 1.5 * 1.5 + 0.5 * 0.5)); assertTrue(ccdVec3Eq(&w, &b)); ccdVec3Set(&P, 10., 9.2, 3.4); dist = ccdVec3PointSegmentDist2(&P, &a, &b, &w); assertTrue(ccdEq(dist, 9. * 9. + 7.7 * 7.7 + 2.9 * 2.9)); assertTrue(ccdVec3Eq(&w, &b)); // inside ab ccdVec3Set(&a, -.1, 1., 1.); ccdVec3Set(&b, 1., 1., 1.); ccdVec3Set(&P, 0., 0., 0.); dist = ccdVec3PointSegmentDist2(&P, &a, &b, &w); assertTrue(ccdEq(dist, 2.)); ccdVec3Set(&ew, 0., 1., 1.); assertTrue(ccdVec3Eq(&w, &ew)); } TEST(vec3PointTriDist) { ccd_vec3_t P, a, b, c, w, P0; ccd_real_t dist; ccdVec3Set(&a, -1., 0., 0.); ccdVec3Set(&b, 0., 1., 1.); ccdVec3Set(&c, -1., 0., 1.); ccdVec3Set(&P, -1., 0., 0.); dist = ccdVec3PointTriDist2(&P, &a, &b, &c, &w); assertTrue(ccdEq(dist, 0.)); assertTrue(ccdVec3Eq(&w, &a)); ccdVec3Set(&P, 0., 1., 1.); dist = ccdVec3PointTriDist2(&P, &a, &b, &c, &w); assertTrue(ccdEq(dist, 0.)); assertTrue(ccdVec3Eq(&w, &b)); ccdVec3Set(&P, -1., 0., 1.); dist = ccdVec3PointTriDist2(&P, &a, &b, &c, &w); assertTrue(ccdEq(dist, 0.)); assertTrue(ccdVec3Eq(&w, &c)); ccdVec3Set(&P, 0., 0., 0.); dist = ccdVec3PointTriDist2(&P, &a, &b, &c, NULL); assertTrue(ccdEq(dist, 2./3.)); // region 4 ccdVec3Set(&P, -2., 0., 0.); dist = ccdVec3PointTriDist2(&P, &a, &b, &c, &w); assertTrue(ccdEq(dist, ccdVec3Dist2(&P, &a))); assertTrue(ccdVec3Eq(&w, &a)); ccdVec3Set(&P, -2., 0.2, -1.); dist = ccdVec3PointTriDist2(&P, &a, &b, &c, &w); assertTrue(ccdEq(dist, ccdVec3Dist2(&P, &a))); assertTrue(ccdVec3Eq(&w, &a)); // region 2 ccdVec3Set(&P, -1.3, 0., 1.2); dist = ccdVec3PointTriDist2(&P, &a, &b, &c, &w); assertTrue(ccdEq(dist, ccdVec3Dist2(&P, &c))); assertTrue(ccdVec3Eq(&w, &c)); ccdVec3Set(&P, -1.2, 0.2, 1.1); dist = ccdVec3PointTriDist2(&P, &a, &b, &c, &w); assertTrue(ccdEq(dist, ccdVec3Dist2(&P, &c))); assertTrue(ccdVec3Eq(&w, &c)); // region 6 ccdVec3Set(&P, 0.3, 1., 1.); dist = ccdVec3PointTriDist2(&P, &a, &b, &c, &w); assertTrue(ccdEq(dist, ccdVec3Dist2(&P, &b))); assertTrue(ccdVec3Eq(&w, &b)); ccdVec3Set(&P, .1, 1., 1.); dist = ccdVec3PointTriDist2(&P, &a, &b, &c, &w); assertTrue(ccdEq(dist, ccdVec3Dist2(&P, &b))); assertTrue(ccdVec3Eq(&w, &b)); // region 1 ccdVec3Set(&P, 0., 1., 2.); dist = ccdVec3PointTriDist2(&P, &a, &b, &c, &w); assertTrue(ccdEq(dist, 1.)); assertTrue(ccdVec3Eq(&w, &b)); ccdVec3Set(&P, -1., 0., 2.); dist = ccdVec3PointTriDist2(&P, &a, &b, &c, &w); assertTrue(ccdEq(dist, 1.)); assertTrue(ccdVec3Eq(&w, &c)); ccdVec3Set(&P, -0.5, 0.5, 2.); dist = ccdVec3PointTriDist2(&P, &a, &b, &c, &w); assertTrue(ccdEq(dist, 1.)); ccdVec3Set(&P0, -0.5, 0.5, 1.); assertTrue(ccdVec3Eq(&w, &P0)); // region 3 ccdVec3Set(&P, -2., -1., 0.7); dist = ccdVec3PointTriDist2(&P, &a, &b, &c, &w); assertTrue(ccdEq(dist, 2.)); ccdVec3Set(&P0, -1., 0., 0.7); assertTrue(ccdVec3Eq(&w, &P0)); // region 5 ccdVec3Set(&P, 0., 0., 0.); dist = ccdVec3PointTriDist2(&P, &a, &b, &c, &w); assertTrue(ccdEq(dist, 2./3.)); ccdVec3Set(&P0, -2./3., 1./3., 1./3.); assertTrue(ccdVec3Eq(&w, &P0)); // region 0 ccdVec3Set(&P, -0.5, 0.5, 0.5); dist = ccdVec3PointTriDist2(&P, &a, &b, &c, &w); assertTrue(ccdEq(dist, 0.)); assertTrue(ccdVec3Eq(&w, &P)); ccdVec3Set(&P, -0.5, 0.5, 0.7); dist = ccdVec3PointTriDist2(&P, &a, &b, &c, &w); assertTrue(ccdEq(dist, 0.)); assertTrue(ccdVec3Eq(&w, &P)); ccdVec3Set(&P, -0.5, 0.5, 0.9); dist = ccdVec3PointTriDist2(&P, &a, &b, &c, &w); assertTrue(ccdEq(dist, 0.)); assertTrue(ccdVec3Eq(&w, &P)); ccdVec3Set(&P, 0., 0., 0.5); dist = ccdVec3PointTriDist2(&P, &a, &b, &c, &w); assertTrue(ccdEq(dist, 0.5)); ccdVec3Set(&P0, -.5, .5, .5); assertTrue(ccdVec3Eq(&w, &P0)); ccdVec3Set(&a, -1., 0., 0.); ccdVec3Set(&b, 0., 1., -1.); ccdVec3Set(&c, 0., 1., 1.); ccdVec3Set(&P, 0., 0., 0.); dist = ccdVec3PointTriDist2(&P, &a, &b, &c, &w); assertTrue(ccdEq(dist, 0.5)); ccdVec3Set(&P0, -.5, .5, 0.); assertTrue(ccdVec3Eq(&w, &P0)); //fprintf(stderr, "dist: %lf\n", dist); } ode-0.16/libccd/src/testsuites/mpr_boxcyl.c0000664000175200017520000001117213403272463015711 00000000000000#include #include "common.h" #include #include "support.h" #define TOSVT() \ svtObjPen(&box, &cyl, stdout, "Pen 1", depth, &dir, &pos); \ ccdVec3Scale(&dir, depth); \ ccdVec3Add(&cyl.pos, &dir); \ svtObjPen(&box, &cyl, stdout, "Pen 1", depth, &dir, &pos) TEST(mprBoxcylIntersect) { ccd_t ccd; CCD_BOX(box); CCD_CYL(cyl); int res; ccd_vec3_t axis; box.x = 0.5; box.y = 1.; box.z = 1.5; cyl.radius = 0.4; cyl.height = 0.7; CCD_INIT(&ccd); ccd.support1 = ccdSupport; ccd.support2 = ccdSupport; ccd.center1 = ccdObjCenter; ccd.center2 = ccdObjCenter; ccdVec3Set(&cyl.pos, 0.1, 0., 0.); res = ccdMPRIntersect(&box, &cyl, &ccd); assertTrue(res); ccdVec3Set(&cyl.pos, .6, 0., 0.); res = ccdMPRIntersect(&box, &cyl, &ccd); assertTrue(res); ccdVec3Set(&cyl.pos, .6, 0.6, 0.); res = ccdMPRIntersect(&box, &cyl, &ccd); assertTrue(res); ccdVec3Set(&cyl.pos, .6, 0.6, 0.5); res = ccdMPRIntersect(&box, &cyl, &ccd); assertTrue(res); ccdVec3Set(&axis, 0., 1., 0.); ccdQuatSetAngleAxis(&cyl.quat, M_PI / 3., &axis); ccdVec3Set(&cyl.pos, .6, 0.6, 0.5); res = ccdMPRIntersect(&box, &cyl, &ccd); assertTrue(res); ccdVec3Set(&axis, 0.67, 1.1, 0.12); ccdQuatSetAngleAxis(&cyl.quat, M_PI / 4., &axis); ccdVec3Set(&cyl.pos, .6, 0., 0.5); res = ccdMPRIntersect(&box, &cyl, &ccd); assertTrue(res); ccdVec3Set(&axis, -0.1, 2.2, -1.); ccdQuatSetAngleAxis(&cyl.quat, M_PI / 5., &axis); ccdVec3Set(&cyl.pos, .6, 0., 0.5); ccdVec3Set(&axis, 1., 1., 0.); ccdQuatSetAngleAxis(&box.quat, -M_PI / 4., &axis); ccdVec3Set(&box.pos, .6, 0., 0.5); res = ccdMPRIntersect(&box, &cyl, &ccd); assertTrue(res); ccdVec3Set(&axis, -0.1, 2.2, -1.); ccdQuatSetAngleAxis(&cyl.quat, M_PI / 5., &axis); ccdVec3Set(&cyl.pos, .6, 0., 0.5); ccdVec3Set(&axis, 1., 1., 0.); ccdQuatSetAngleAxis(&box.quat, -M_PI / 4., &axis); ccdVec3Set(&box.pos, .9, 0.8, 0.5); res = ccdMPRIntersect(&box, &cyl, &ccd); assertTrue(res); } TEST(mprBoxcylPen) { ccd_t ccd; CCD_BOX(box); CCD_CYL(cyl); int res; ccd_vec3_t axis; ccd_real_t depth; ccd_vec3_t dir, pos; box.x = 0.5; box.y = 1.; box.z = 1.5; cyl.radius = 0.4; cyl.height = 0.7; CCD_INIT(&ccd); ccd.support1 = ccdSupport; ccd.support2 = ccdSupport; ccd.center1 = ccdObjCenter; ccd.center2 = ccdObjCenter; ccdVec3Set(&cyl.pos, 0.1, 0., 0.); res = ccdMPRPenetration(&box, &cyl, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 1"); //TOSVT(); ccdVec3Set(&cyl.pos, .6, 0., 0.); res = ccdMPRPenetration(&box, &cyl, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 2"); //TOSVT(); ccdVec3Set(&cyl.pos, .6, 0.6, 0.); res = ccdMPRPenetration(&box, &cyl, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 3"); //TOSVT(); ccdVec3Set(&cyl.pos, .6, 0.6, 0.5); res = ccdMPRPenetration(&box, &cyl, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 4"); //TOSVT(); ccdVec3Set(&axis, 0., 1., 0.); ccdQuatSetAngleAxis(&cyl.quat, M_PI / 3., &axis); ccdVec3Set(&cyl.pos, .6, 0.6, 0.5); res = ccdMPRPenetration(&box, &cyl, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 5"); //TOSVT(); ccdVec3Set(&axis, 0.67, 1.1, 0.12); ccdQuatSetAngleAxis(&cyl.quat, M_PI / 4., &axis); ccdVec3Set(&cyl.pos, .6, 0., 0.5); res = ccdMPRPenetration(&box, &cyl, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 6"); //TOSVT(); ccdVec3Set(&axis, -0.1, 2.2, -1.); ccdQuatSetAngleAxis(&cyl.quat, M_PI / 5., &axis); ccdVec3Set(&cyl.pos, .6, 0., 0.5); ccdVec3Set(&axis, 1., 1., 0.); ccdQuatSetAngleAxis(&box.quat, -M_PI / 4., &axis); ccdVec3Set(&box.pos, .6, 0., 0.5); res = ccdMPRPenetration(&box, &cyl, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 7"); //TOSVT(); ccdVec3Set(&axis, -0.1, 2.2, -1.); ccdQuatSetAngleAxis(&cyl.quat, M_PI / 5., &axis); ccdVec3Set(&cyl.pos, .6, 0., 0.5); ccdVec3Set(&axis, 1., 1., 0.); ccdQuatSetAngleAxis(&box.quat, -M_PI / 4., &axis); ccdVec3Set(&box.pos, .9, 0.8, 0.5); res = ccdMPRPenetration(&box, &cyl, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 8"); //TOSVT(); } ode-0.16/libccd/src/testsuites/cu/0000775000175200017520000000000013403273061014047 500000000000000ode-0.16/libccd/src/testsuites/cu/Makefile.am0000664000175200017520000000013513403272463016027 00000000000000AM_CPPFLAGS = -DCU_ENABLE_TIMER check_LTLIBRARIES = libcu.la libcu_la_SOURCES = cu.c cu.h ode-0.16/libccd/src/testsuites/cu/cu.c0000664000175200017520000002470313403272463014555 00000000000000/*** * CU - C unit testing framework * --------------------------------- * Copyright (c)2007,2008,2009 Daniel Fiser * * * This file is part of CU. * * CU is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 3 of * the License, or (at your option) any later version. * * CU is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include "cu.h" /** Declared here, because I didn't find header file where it is declared */ char *strsignal(int sig); const char *cu_current_test; const char *cu_current_test_suite; int cu_success_test_suites = 0; int cu_fail_test_suites = 0; int cu_success_tests = 0; int cu_fail_tests = 0; int cu_success_checks = 0; int cu_fail_checks = 0; char cu_out_prefix[CU_OUT_PREFIX_LENGTH+1] = ""; /* globally used file descriptor for reading/writing messages */ int fd; /* indicate if test was failed */ int test_failed; /* codes of messages */ #define CHECK_FAILED '0' #define CHECK_SUCCEED '1' #define TEST_FAILED '2' #define TEST_SUCCEED '3' #define TEST_SUITE_FAILED '4' #define TEST_SUITE_SUCCEED '5' #define END '6' #define TEST_NAME '7' /* predefined messages */ #define MSG_CHECK_SUCCEED write(fd, "1\n", 2) #define MSG_TEST_FAILED write(fd, "2\n", 2) #define MSG_TEST_SUCCEED write(fd, "3\n", 2) #define MSG_TEST_SUITE_FAILED write(fd, "4\n", 2) #define MSG_TEST_SUITE_SUCCEED write(fd, "5\n", 2) #define MSG_END write(fd, "6\n", 2) /* length of buffers */ #define BUF_LEN 1000 #define MSGBUF_LEN 300 static void redirect_out_err(const char *testName); static void close_out_err(void); static void run_test_suite(const char *ts_name, cu_test_suite_t *ts); static void receive_messages(void); static void cu_run_fork(const char *ts_name, cu_test_suite_t *test_suite); static void cu_print_results(void); void cu_run(int argc, char *argv[]) { cu_test_suites_t *tss; int i; char found = 0; if (argc > 1){ for (i=1; i < argc; i++){ tss = cu_test_suites; while (tss->name != NULL && tss->test_suite != NULL){ if (strcmp(argv[i], tss->name) == 0){ found = 1; cu_run_fork(tss->name, tss->test_suite); break; } tss++; } if (tss->name == NULL || tss->test_suite == NULL){ fprintf(stderr, "ERROR: Could not find test suite '%s'\n", argv[i]); } } if (found == 1) cu_print_results(); }else{ tss = cu_test_suites; while (tss->name != NULL && tss->test_suite != NULL){ cu_run_fork(tss->name, tss->test_suite); tss++; } cu_print_results(); } } static void cu_run_fork(const char *ts_name, cu_test_suite_t *ts) { int pipefd[2]; int pid; int status; if (pipe(pipefd) == -1){ perror("Pipe error"); exit(-1); } fprintf(stdout, " -> %s [IN PROGESS]\n", ts_name); fflush(stdout); pid = fork(); if (pid < 0){ perror("Fork error"); exit(-1); } if (pid == 0){ /* close read end of pipe */ close(pipefd[0]); fd = pipefd[1]; /* run testsuite, messages go to fd */ run_test_suite(ts_name, ts); MSG_END; close(fd); /* stop process where running testsuite */ exit(0); }else{ /* close write end of pipe */ close(pipefd[1]); fd = pipefd[0]; /* receive and interpret all messages */ receive_messages(); /* wait for children */ wait(&status); if (!WIFEXITED(status)){ /* if child process ends up abnormaly */ if (WIFSIGNALED(status)){ fprintf(stdout, "Test suite was terminated by signal %d (%s).\n", WTERMSIG(status), strsignal(WTERMSIG(status))); }else{ fprintf(stdout, "Test suite terminated abnormaly!\n"); } /* mark this test suite as failed, because was terminated * prematurely */ cu_fail_test_suites++; } close(fd); fprintf(stdout, " -> %s [DONE]\n\n", ts_name); fflush(stdout); } } static void run_test_suite(const char *ts_name, cu_test_suite_t *ts) { int test_suite_failed = 0; char buffer[MSGBUF_LEN]; int len; /* set up current test suite name for later messaging... */ cu_current_test_suite = ts_name; /* redirect stdout and stderr */ redirect_out_err(cu_current_test_suite); while (ts->name != NULL && ts->func != NULL){ test_failed = 0; /* set up name of test for later messaging */ cu_current_test = ts->name; /* send message what test is currently running */ len = snprintf(buffer, MSGBUF_LEN, "%c --> Running %s...\n", TEST_NAME, cu_current_test); write(fd, buffer, len); /* run test */ (*(ts->func))(); if (test_failed){ MSG_TEST_FAILED; test_suite_failed = 1; }else{ MSG_TEST_SUCCEED; } ts++; /* next test in test suite */ } if (test_suite_failed){ MSG_TEST_SUITE_FAILED; }else{ MSG_TEST_SUITE_SUCCEED; } /* close redirected stdout and stderr */ close_out_err(); } static void receive_messages(void) { char buf[BUF_LEN]; /* buffer */ int buf_len; /* how many chars stored in buf */ char bufout[MSGBUF_LEN]; /* buffer which can be printed out */ int bufout_len; int state = 0; /* 0 - waiting for code, 1 - copy msg to stdout */ int i; int end = 0; /* end of messages? */ bufout_len = 0; while((buf_len = read(fd, buf, BUF_LEN)) > 0 && !end){ for (i=0; i < buf_len; i++){ /* Prepare message for printing out */ if (state == 1 || state == 2){ if (bufout_len < MSGBUF_LEN) bufout[bufout_len++] = buf[i]; } /* reset state on '\n' in msg */ if (buf[i] == '\n'){ /* copy messages out */ if (state == 1) write(1, bufout, bufout_len); if (state == 2) write(2, bufout, bufout_len); state = 0; bufout_len = 0; continue; } if (state == 0){ if (buf[i] == CHECK_FAILED){ cu_fail_checks++; state = 2; }else if (buf[i] == TEST_NAME){ state = 1; }else if (buf[i] == CHECK_SUCCEED){ cu_success_checks++; }else if (buf[i] == TEST_FAILED){ cu_fail_tests++; }else if (buf[i] == TEST_SUCCEED){ cu_success_tests++; }else if (buf[i] == TEST_SUITE_FAILED){ cu_fail_test_suites++; }else if (buf[i] == TEST_SUITE_SUCCEED){ cu_success_test_suites++; }else if (buf[i] == END){ end = 1; break; } } } } } void cu_success_assertation(void) { MSG_CHECK_SUCCEED; } void cu_fail_assertation(const char *file, int line, const char *msg) { char buf[MSGBUF_LEN]; int len; len = snprintf(buf, MSGBUF_LEN, "%c%s:%d (%s::%s) :: %s\n", CHECK_FAILED, file, line, cu_current_test_suite, cu_current_test, msg); write(fd, buf, len); /* enable test_failed flag */ test_failed = 1; } static void cu_print_results(void) { fprintf(stdout, "\n"); fprintf(stdout, "==================================================\n"); fprintf(stdout, "| | failed | succeed | total |\n"); fprintf(stdout, "|------------------------------------------------|\n"); fprintf(stdout, "| assertations: | %6d | %7d | %5d |\n", cu_fail_checks, cu_success_checks, cu_success_checks+cu_fail_checks); fprintf(stdout, "| tests: | %6d | %7d | %5d |\n", cu_fail_tests, cu_success_tests, cu_success_tests+cu_fail_tests); fprintf(stdout, "| tests suites: | %6d | %7d | %5d |\n", cu_fail_test_suites, cu_success_test_suites, cu_success_test_suites+cu_fail_test_suites); fprintf(stdout, "==================================================\n"); } void cu_set_out_prefix(const char *str) { strncpy(cu_out_prefix, str, CU_OUT_PREFIX_LENGTH); } static void redirect_out_err(const char *test_name) { char buf[100]; snprintf(buf, 99, "%stmp.%s.out", cu_out_prefix, test_name); if (freopen(buf, "w", stdout) == NULL){ perror("Redirecting of stdout failed"); exit(-1); } snprintf(buf, 99, "%stmp.%s.err", cu_out_prefix, test_name); if (freopen(buf, "w", stderr) == NULL){ perror("Redirecting of stderr failed"); exit(-1); } } static void close_out_err(void) { fclose(stdout); fclose(stderr); } #ifdef CU_ENABLE_TIMER /* global variables for timer functions */ struct timespec __cu_timer; static struct timespec __cu_timer_start, __cu_timer_stop; const struct timespec *cuTimer(void) { return &__cu_timer; } void cuTimerStart(void) { clock_gettime(CLOCK_MONOTONIC, &__cu_timer_start); } const struct timespec *cuTimerStop(void) { clock_gettime(CLOCK_MONOTONIC, &__cu_timer_stop); /* store into t difference between time_start and time_end */ if (__cu_timer_stop.tv_nsec > __cu_timer_start.tv_nsec){ __cu_timer.tv_nsec = __cu_timer_stop.tv_nsec - __cu_timer_start.tv_nsec; __cu_timer.tv_sec = __cu_timer_stop.tv_sec - __cu_timer_start.tv_sec; }else{ __cu_timer.tv_nsec = __cu_timer_stop.tv_nsec + 1000000000L - __cu_timer_start.tv_nsec; __cu_timer.tv_sec = __cu_timer_stop.tv_sec - 1 - __cu_timer_start.tv_sec; } return &__cu_timer; } #endif /* CU_ENABLE_TIMER */ ode-0.16/libccd/src/testsuites/cu/COPYING.LESSER0000664000175200017520000001672713403272463016040 00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. ode-0.16/libccd/src/testsuites/cu/COPYING0000664000175200017520000010451313403272463015033 00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . ode-0.16/libccd/src/testsuites/cu/cu.h0000664000175200017520000000747613403272463014572 00000000000000/*** * CU - C unit testing framework * --------------------------------- * Copyright (c)2007,2008,2009 Daniel Fiser * * * This file is part of CU. * * CU is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 3 of * the License, or (at your option) any later version. * * CU is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #ifndef _CU_H_ #define _CU_H_ #ifdef CU_ENABLE_TIMER # include #endif /* CU_ENABLE_TIMER */ #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /***** PUBLIC API *****/ /** * Define test */ #define TEST(name) \ void name(void) /** * Define testsuite */ #define TEST_SUITE(name) \ cu_test_suite_t test_suite_##name[] = /** * Must be on the end of list of tests. */ #define TEST_SUITE_CLOSURE \ { NULL, NULL } #define TEST_SUITES \ cu_test_suites_t cu_test_suites[] = #define TEST_SUITES_CLOSURE \ { NULL, NULL } #define TEST_SUITE_ADD(name) \ { #name, test_suite_##name } /** * Add test to testsuite */ #define TEST_ADD(name) \ { #name, name } #define CU_RUN(argc, argv) \ cu_run(argc, argv) /** * Set prefix for files printed out. Must contain trailing /. */ #define CU_SET_OUT_PREFIX(str) \ cu_set_out_prefix(str) /** * Assertations * Assertations with suffix 'M' (e.g. assertTrueM) is variation of macro * where is possible to specify error message. */ #define assertTrueM(a, message) \ if (a){ \ cu_success_assertation(); \ }else{ \ cu_fail_assertation(__FILE__, __LINE__, message); \ } #define assertTrue(a) \ assertTrueM((a), #a " is not true") #define assertFalseM(a, message) \ assertTrueM(!(a), message) #define assertFalse(a) \ assertFalseM((a), #a " is not false") #define assertEqualsM(a,b,message) \ assertTrueM((a) == (b), message) #define assertEquals(a,b) \ assertEqualsM((a), (b), #a " not equals " #b) #define assertNotEqualsM(a,b,message) \ assertTrueM((a) != (b), message) #define assertNotEquals(a,b) \ assertNotEqualsM((a), (b), #a " equals " #b) /***** PUBLIC API END *****/ #include #define CU_MAX_NAME_LENGTH 30 typedef void (*cu_test_func_t)(void); typedef struct _cu_test_suite_t { const char *name; cu_test_func_t func; } cu_test_suite_t; typedef struct _cu_test_suites_t { const char *name; cu_test_suite_t *test_suite; } cu_test_suites_t; extern cu_test_suites_t cu_test_suites[]; extern const char *cu_current_test; extern const char *cu_current_test_suite; extern int cu_success_test_suites; extern int cu_fail_test_suites; extern int cu_success_tests; extern int cu_fail_tests; extern int cu_success_checks; extern int cu_fail_checks; #define CU_OUT_PREFIX_LENGTH 30 extern char cu_out_prefix[CU_OUT_PREFIX_LENGTH+1]; void cu_run(int argc, char *argv[]); void cu_success_assertation(void); void cu_fail_assertation(const char *file, int line, const char *msg); void cu_set_out_prefix(const char *str); /** Timer **/ #ifdef CU_ENABLE_TIMER extern struct timespec __cu_timer; /** * Returns value of timer. (as timespec struct) */ const struct timespec *cuTimer(void); /** * Starts timer. */ void cuTimerStart(void); /** * Stops timer and record elapsed time from last call of cuTimerStart(). * Returns current value of timer. */ const struct timespec *cuTimerStop(void); #endif /* CU_ENABLE_TIMER */ #ifdef __cplusplus } #endif /* __cplusplus */ #endif ode-0.16/libccd/src/testsuites/cu/Makefile.in0000664000175200017520000004202513403272666016051 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = src/testsuites/cu ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/src/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = libcu_la_LIBADD = am_libcu_la_OBJECTS = cu.lo libcu_la_OBJECTS = $(am_libcu_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/src depcomp = $(SHELL) $(top_srcdir)/../depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libcu_la_SOURCES) DIST_SOURCES = $(libcu_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/../depcomp \ COPYING COPYING.LESSER DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CCD_PRECISION = @CCD_PRECISION@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -DCU_ENABLE_TIMER check_LTLIBRARIES = libcu.la libcu_la_SOURCES = cu.c cu.h all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/testsuites/cu/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/testsuites/cu/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-checkLTLIBRARIES: -test -z "$(check_LTLIBRARIES)" || rm -f $(check_LTLIBRARIES) @list='$(check_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libcu.la: $(libcu_la_OBJECTS) $(libcu_la_DEPENDENCIES) $(EXTRA_libcu_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libcu_la_OBJECTS) $(libcu_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cu.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_LTLIBRARIES) check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-checkLTLIBRARIES clean-generic clean-libtool \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ clean-checkLTLIBRARIES clean-generic clean-libtool \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ode-0.16/libccd/src/testsuites/boxcyl.c0000664000175200017520000001077013403272463015036 00000000000000#include #include "common.h" #include #include "support.h" #define TOSVT() \ svtObjPen(&box, &cyl, stdout, "Pen 1", depth, &dir, &pos); \ ccdVec3Scale(&dir, depth); \ ccdVec3Add(&cyl.pos, &dir); \ svtObjPen(&box, &cyl, stdout, "Pen 1", depth, &dir, &pos) TEST(boxcylIntersect) { ccd_t ccd; CCD_BOX(box); CCD_CYL(cyl); int res; ccd_vec3_t axis; box.x = 0.5; box.y = 1.; box.z = 1.5; cyl.radius = 0.4; cyl.height = 0.7; CCD_INIT(&ccd); ccd.support1 = ccdSupport; ccd.support2 = ccdSupport; ccdVec3Set(&cyl.pos, 0.1, 0., 0.); res = ccdGJKIntersect(&box, &cyl, &ccd); assertTrue(res); ccdVec3Set(&cyl.pos, .6, 0., 0.); res = ccdGJKIntersect(&box, &cyl, &ccd); assertTrue(res); ccdVec3Set(&cyl.pos, .6, 0.6, 0.); res = ccdGJKIntersect(&box, &cyl, &ccd); assertTrue(res); ccdVec3Set(&cyl.pos, .6, 0.6, 0.5); res = ccdGJKIntersect(&box, &cyl, &ccd); assertTrue(res); ccdVec3Set(&axis, 0., 1., 0.); ccdQuatSetAngleAxis(&cyl.quat, M_PI / 3., &axis); ccdVec3Set(&cyl.pos, .6, 0.6, 0.5); res = ccdGJKIntersect(&box, &cyl, &ccd); assertTrue(res); ccdVec3Set(&axis, 0.67, 1.1, 0.12); ccdQuatSetAngleAxis(&cyl.quat, M_PI / 4., &axis); ccdVec3Set(&cyl.pos, .6, 0., 0.5); res = ccdGJKIntersect(&box, &cyl, &ccd); assertTrue(res); ccdVec3Set(&axis, -0.1, 2.2, -1.); ccdQuatSetAngleAxis(&cyl.quat, M_PI / 5., &axis); ccdVec3Set(&cyl.pos, .6, 0., 0.5); ccdVec3Set(&axis, 1., 1., 0.); ccdQuatSetAngleAxis(&box.quat, -M_PI / 4., &axis); ccdVec3Set(&box.pos, .6, 0., 0.5); res = ccdGJKIntersect(&box, &cyl, &ccd); assertTrue(res); ccdVec3Set(&axis, -0.1, 2.2, -1.); ccdQuatSetAngleAxis(&cyl.quat, M_PI / 5., &axis); ccdVec3Set(&cyl.pos, .6, 0., 0.5); ccdVec3Set(&axis, 1., 1., 0.); ccdQuatSetAngleAxis(&box.quat, -M_PI / 4., &axis); ccdVec3Set(&box.pos, .9, 0.8, 0.5); res = ccdGJKIntersect(&box, &cyl, &ccd); assertTrue(res); } TEST(boxcylPenEPA) { ccd_t ccd; CCD_BOX(box); CCD_CYL(cyl); int res; ccd_vec3_t axis; ccd_real_t depth; ccd_vec3_t dir, pos; box.x = 0.5; box.y = 1.; box.z = 1.5; cyl.radius = 0.4; cyl.height = 0.7; CCD_INIT(&ccd); ccd.support1 = ccdSupport; ccd.support2 = ccdSupport; ccdVec3Set(&cyl.pos, 0.1, 0., 0.); res = ccdGJKPenetration(&box, &cyl, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 1"); //TOSVT(); ccdVec3Set(&cyl.pos, .6, 0., 0.); res = ccdGJKPenetration(&box, &cyl, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 2"); //TOSVT(); <<< ccdVec3Set(&cyl.pos, .6, 0.6, 0.); res = ccdGJKPenetration(&box, &cyl, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 3"); //TOSVT(); ccdVec3Set(&cyl.pos, .6, 0.6, 0.5); res = ccdGJKPenetration(&box, &cyl, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 4"); //TOSVT(); ccdVec3Set(&axis, 0., 1., 0.); ccdQuatSetAngleAxis(&cyl.quat, M_PI / 3., &axis); ccdVec3Set(&cyl.pos, .6, 0.6, 0.5); res = ccdGJKPenetration(&box, &cyl, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 5"); //TOSVT(); ccdVec3Set(&axis, 0.67, 1.1, 0.12); ccdQuatSetAngleAxis(&cyl.quat, M_PI / 4., &axis); ccdVec3Set(&cyl.pos, .6, 0., 0.5); res = ccdGJKPenetration(&box, &cyl, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 6"); //TOSVT(); ccdVec3Set(&axis, -0.1, 2.2, -1.); ccdQuatSetAngleAxis(&cyl.quat, M_PI / 5., &axis); ccdVec3Set(&cyl.pos, .6, 0., 0.5); ccdVec3Set(&axis, 1., 1., 0.); ccdQuatSetAngleAxis(&box.quat, -M_PI / 4., &axis); ccdVec3Set(&box.pos, .6, 0., 0.5); res = ccdGJKPenetration(&box, &cyl, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 7"); //TOSVT(); ccdVec3Set(&axis, -0.1, 2.2, -1.); ccdQuatSetAngleAxis(&cyl.quat, M_PI / 5., &axis); ccdVec3Set(&cyl.pos, .6, 0., 0.5); ccdVec3Set(&axis, 1., 1., 0.); ccdQuatSetAngleAxis(&box.quat, -M_PI / 4., &axis); ccdVec3Set(&box.pos, .9, 0.8, 0.5); res = ccdGJKPenetration(&box, &cyl, &ccd, &depth, &dir, &pos); assertTrue(res == 0); recPen(depth, &dir, &pos, stdout, "Pen 8"); //TOSVT(); } ode-0.16/libccd/src/testsuites/spheresphere.h0000664000175200017520000000067613403272463016244 00000000000000#ifndef SPHERE_SPHERE #define SPHERE_SPHERE #include TEST(spheresphereSetUp); TEST(spheresphereTearDown); TEST(spheresphereAlignedX); TEST(spheresphereAlignedY); TEST(spheresphereAlignedZ); TEST_SUITE(TSSphereSphere) { TEST_ADD(spheresphereSetUp), TEST_ADD(spheresphereAlignedX), TEST_ADD(spheresphereAlignedY), TEST_ADD(spheresphereAlignedZ), TEST_ADD(spheresphereTearDown), TEST_SUITE_CLOSURE }; #endif ode-0.16/libccd/src/testsuites/Makefile.in0000664000175200017520000005717413403272666015455 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ check_PROGRAMS = test$(EXEEXT) bench$(EXEEXT) bench2$(EXEEXT) subdir = src/testsuites ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/src/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am_bench_OBJECTS = bench.$(OBJEXT) support.$(OBJEXT) bench_OBJECTS = $(am_bench_OBJECTS) bench_LDADD = $(LDADD) bench_DEPENDENCIES = $(builddir)/cu/libcu.la $(builddir)/../libccd.la AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = am_bench2_OBJECTS = bench2.$(OBJEXT) support.$(OBJEXT) bench2_OBJECTS = $(am_bench2_OBJECTS) bench2_LDADD = $(LDADD) bench2_DEPENDENCIES = $(builddir)/cu/libcu.la $(builddir)/../libccd.la am_test_OBJECTS = main.$(OBJEXT) common.$(OBJEXT) support.$(OBJEXT) \ vec3.$(OBJEXT) polytope.$(OBJEXT) boxbox.$(OBJEXT) \ spheresphere.$(OBJEXT) cylcyl.$(OBJEXT) boxcyl.$(OBJEXT) \ mpr_boxbox.$(OBJEXT) mpr_cylcyl.$(OBJEXT) mpr_boxcyl.$(OBJEXT) test_OBJECTS = $(am_test_OBJECTS) test_LDADD = $(LDADD) test_DEPENDENCIES = $(builddir)/cu/libcu.la $(builddir)/../libccd.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/src depcomp = $(SHELL) $(top_srcdir)/../depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(bench_SOURCES) $(bench2_SOURCES) $(test_SOURCES) DIST_SOURCES = $(bench_SOURCES) $(bench2_SOURCES) $(test_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/../depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CCD_PRECISION = @CCD_PRECISION@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = cu AM_CPPFLAGS = -I $(srcdir)/.. -I $(builddir)/.. -I $(srcdir)/cu LDADD = $(builddir)/cu/libcu.la $(builddir)/../libccd.la test_SOURCES = main.c \ common.c common.h \ support.c support.h \ vec3.c vec3.h \ polytope.c polytope.h \ boxbox.c boxbox.h \ spheresphere.c spheresphere.h \ cylcyl.c cylcyl.h \ boxcyl.c boxcyl.h \ mpr_boxbox.c mpr_boxbox.h \ mpr_cylcyl.c mpr_cylcyl.h \ mpr_boxcyl.c mpr_boxcyl.h bench_SOURCES = bench.c \ support.c support.h bench2_SOURCES = bench2.c \ support.c support.h all: all-recursive .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/testsuites/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/testsuites/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list bench$(EXEEXT): $(bench_OBJECTS) $(bench_DEPENDENCIES) $(EXTRA_bench_DEPENDENCIES) @rm -f bench$(EXEEXT) $(AM_V_CCLD)$(LINK) $(bench_OBJECTS) $(bench_LDADD) $(LIBS) bench2$(EXEEXT): $(bench2_OBJECTS) $(bench2_DEPENDENCIES) $(EXTRA_bench2_DEPENDENCIES) @rm -f bench2$(EXEEXT) $(AM_V_CCLD)$(LINK) $(bench2_OBJECTS) $(bench2_LDADD) $(LIBS) test$(EXEEXT): $(test_OBJECTS) $(test_DEPENDENCIES) $(EXTRA_test_DEPENDENCIES) @rm -f test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_OBJECTS) $(test_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bench.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bench2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/boxbox.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/boxcyl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cylcyl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpr_boxbox.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpr_boxcyl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpr_cylcyl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/polytope.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spheresphere.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/support.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vec3.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-checkPROGRAMS clean-generic clean-libtool \ mostlyclean-am distclean: distclean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(am__recursive_targets) check-am install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-checkPROGRAMS clean-generic clean-libtool \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ode-0.16/libccd/src/testsuites/support.h0000664000175200017520000000472213403272463015257 00000000000000/*** * libccd * --------------------------------- * Copyright (c)2010 Daniel Fiser * * * This file is part of libccd. * * Distributed under the OSI-approved BSD License (the "License"); * see accompanying file BDS-LICENSE for details or see * . * * This software is distributed WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the License for more information. */ /*** * Some support() functions for some convex shapes. */ #ifndef __CCD_SUPPORT_H__ #define __CCD_SUPPORT_H__ #include #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #define CCD_OBJ_BOX 1 #define CCD_OBJ_SPHERE 2 #define CCD_OBJ_CYL 3 #define __CCD_OBJ__ \ int type; \ ccd_vec3_t pos; \ ccd_quat_t quat; struct _ccd_obj_t { __CCD_OBJ__ }; typedef struct _ccd_obj_t ccd_obj_t; struct _ccd_box_t { __CCD_OBJ__ ccd_real_t x, y, z; //!< Lengths of box's edges }; typedef struct _ccd_box_t ccd_box_t; struct _ccd_sphere_t { __CCD_OBJ__ ccd_real_t radius; }; typedef struct _ccd_sphere_t ccd_sphere_t; struct _ccd_cyl_t { __CCD_OBJ__ ccd_real_t radius; ccd_real_t height; }; typedef struct _ccd_cyl_t ccd_cyl_t; #define CCD_BOX(name) \ ccd_box_t name = { .type = CCD_OBJ_BOX, \ .pos = { .v = { 0., 0., 0. } }, \ .quat = { .q = { 0., 0., 0., 1. } }, \ .x = 0., \ .y = 0., \ .z = 0. } #define CCD_SPHERE(name) \ ccd_sphere_t name = { .type = CCD_OBJ_SPHERE, \ .pos = { .v = { 0., 0., 0. } }, \ .quat = { .q = { 0., 0., 0., 1. } }, \ .radius = 0. } #define CCD_CYL(name) \ ccd_cyl_t name = { .type = CCD_OBJ_CYL, \ .pos = { .v = { 0., 0., 0. } }, \ .quat = { .q = { 0., 0., 0., 1. } }, \ .radius = 0., \ .height = 0. } /** * Returns supporting vertex via v. * Supporting vertex is fathest vertex from object in direction dir. */ void ccdSupport(const void *obj, const ccd_vec3_t *dir, ccd_vec3_t *v); /** * Returns center of object. */ void ccdObjCenter(const void *obj, ccd_vec3_t *center); #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif /* __CCD_SUPPORT_H__ */ ode-0.16/libccd/src/testsuites/vec3.h0000664000175200017520000000051013403272463014372 00000000000000#ifndef TEST_VEC3_H #define TEST_VEC3_H #include TEST(vec3SetUp); TEST(vec3TearDown); TEST(vec3PointSegmentDist); TEST(vec3PointTriDist); TEST_SUITE(TSVec3) { TEST_ADD(vec3SetUp), TEST_ADD(vec3PointSegmentDist), TEST_ADD(vec3PointTriDist), TEST_ADD(vec3TearDown), TEST_SUITE_CLOSURE }; #endif ode-0.16/libccd/src/testsuites/boxcyl.h0000664000175200017520000000034113403272463015034 00000000000000#ifndef TEST_BOXCYL_H #define TEST_BOXCYL_H #include TEST(boxcylIntersect); TEST(boxcylPenEPA); TEST_SUITE(TSBoxCyl){ TEST_ADD(boxcylIntersect), TEST_ADD(boxcylPenEPA), TEST_SUITE_CLOSURE }; #endif ode-0.16/libccd/src/Makefile.in0000664000175200017520000005501613403272666013232 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = src ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libccd_la_LIBADD = am_libccd_la_OBJECTS = alloc.lo ccd.lo polytope.lo support.lo vec3.lo \ mpr.lo nodist_libccd_la_OBJECTS = libccd_la_OBJECTS = $(am_libccd_la_OBJECTS) \ $(nodist_libccd_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/../depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libccd_la_SOURCES) $(nodist_libccd_la_SOURCES) DIST_SOURCES = $(libccd_la_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ $(LISP)config.h.in # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \ $(top_srcdir)/../depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CCD_PRECISION = @CCD_PRECISION@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = testsuites AM_CPPFLAGS = -I$(top_srcdir)/src/custom AM_CFLAGS = -std=c99 noinst_LTLIBRARIES = libccd.la libccd_la_SOURCES = alloc.c ccd/alloc.h \ ccd/compiler.h \ ccd/dbg.h \ ccd.c ccd/ccd.h \ ccd/list.h \ polytope.c ccd/polytope.h \ ccd/quat.h custom/ccdcustom/quat.h \ ccd/simplex.h \ support.c ccd/support.h \ vec3.c ccd/vec3.h custom/ccdcustom/vec3.h \ mpr.c nodist_libccd_la_SOURCES = ccd/precision.h EXTRA_DIST = ccd/precision.h.in all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): config.h: stamp-h1 @test -f $@ || rm -f stamp-h1 @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status src/config.h $(srcdir)/config.h.in: $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f stamp-h1 touch $@ distclean-hdr: -rm -f config.h stamp-h1 clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libccd.la: $(libccd_la_OBJECTS) $(libccd_la_DEPENDENCIES) $(EXTRA_libccd_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libccd_la_OBJECTS) $(libccd_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alloc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ccd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/polytope.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/support.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vec3.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile $(LTLIBRARIES) config.h installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-hdr distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(am__recursive_targets) all install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool \ clean-noinstLTLIBRARIES cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-hdr \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs installdirs-am maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ode-0.16/libccd/src/alloc.c0000664000175200017520000000155513403272463012415 00000000000000/*** * libccd * --------------------------------- * Copyright (c)2010 Daniel Fiser * * * This file is part of libccd. * * Distributed under the OSI-approved BSD License (the "License"); * see accompanying file BDS-LICENSE for details or see * . * * This software is distributed WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the License for more information. */ #include #include #ifdef HAVE_CONFIG_H #include "config.h" #endif void *ccdRealloc(void *ptr, size_t size) { void *ret = realloc(ptr, size); if (ret == NULL && size != 0){ fprintf(stderr, "Fatal error: Allocation of memory failed!\n"); fflush(stderr); exit(-1); } return ret; } ode-0.16/libccd/src/custom/0000775000175200017520000000000013403273061012536 500000000000000ode-0.16/libccd/src/custom/ccdcustom/0000775000175200017520000000000013403273061014522 500000000000000ode-0.16/libccd/src/custom/ccdcustom/quat.h0000664000175200017520000000347313403272463015601 00000000000000/*** * libccd * --------------------------------- * Copyright (c)2010 Daniel Fiser * * * This file is part of libccd. * * Distributed under the OSI-approved BSD License (the "License"); * see accompanying file BDS-LICENSE for details or see * . * * This software is distributed WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the License for more information. */ #ifndef __CCD_CUSTOM_QUAT_H__ #define __CCD_CUSTOM_QUAT_H__ #include #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /** * Rotate vector s by quaternion q and put result into d. */ _ccd_inline void ccdQuatRotVec2(ccd_vec3_t *d, const ccd_vec3_t *s, const ccd_quat_t *q); _ccd_inline void ccdQuatRotVec2(ccd_vec3_t *d, const ccd_vec3_t *s, const ccd_quat_t *q) { #ifndef dLIBCCD_USE_SYSTEM // original version: 31 mul + 21 add // optimized version: 18 mul + 12 add // formula: d = s + 2 * cross(q.xyz, cross(q.xyz, v) + q.w * s) ccd_real_t cross1_x, cross1_y, cross1_z, cross2_x, cross2_y, cross2_z; ccd_real_t x, y, z, w; ccd_real_t vx, vy, vz; vx = ccdVec3X(s); vy = ccdVec3Y(s); vz = ccdVec3Z(s); w = q->q[3]; x = q->q[0]; y = q->q[1]; z = q->q[2]; cross1_x = y * vz - z * vy + w * vx; cross1_y = z * vx - x * vz + w * vy; cross1_z = x * vy - y * vx + w * vz; cross2_x = y * cross1_z - z * cross1_y; cross2_y = z * cross1_x - x * cross1_z; cross2_z = x * cross1_y - y * cross1_x; ccdVec3Set(d, vx + 2 * cross2_x, vy + 2 * cross2_y, vz + 2 * cross2_z); #else ccdVec3Copy(d, s); ccdQuatRotVec(d, q); #endif } #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif /* __CCD_QUAT_H__ */ ode-0.16/libccd/src/custom/ccdcustom/vec3.h0000664000175200017520000000500613403272463015461 00000000000000/*** * libccd * --------------------------------- * Copyright (c)2010,2011 Daniel Fiser * * * This file is part of libccd. * * Distributed under the OSI-approved BSD License (the "License"); * see accompanying file BDS-LICENSE for details or see * . * * This software is distributed WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the License for more information. */ #ifndef __CCD_CUSTOM_VEC3_H__ #define __CCD_CUSTOM_VEC3_H__ #include #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #ifdef CCD_SINGLE # define CCD_ATAN2(x, y) (atan2f((x), (y))) /*!< atan2 of two floats */ #endif /* CCD_SINGLE */ #ifdef CCD_DOUBLE # define CCD_ATAN2(x, y) (atan2((x), (y))) /*!< atan2 of two floats */ #endif /* CCD_DOUBLE */ /** * d = v + w */ _ccd_inline void ccdVec3Add2(ccd_vec3_t *d, const ccd_vec3_t *v, const ccd_vec3_t *w); /** * d = s * k; */ _ccd_inline void ccdVec3CopyScaled(ccd_vec3_t *d, const ccd_vec3_t *s, ccd_real_t k); /** * d = v + s * k; */ _ccd_inline void ccdVec3AddScaled(ccd_vec3_t *d, const ccd_vec3_t *v, const ccd_vec3_t *s, ccd_real_t k); /** * Normalizes given vector to unit length. */ _ccd_inline int ccdVec3SafeNormalize(ccd_vec3_t *d); _ccd_inline void ccdVec3Add2(ccd_vec3_t *d, const ccd_vec3_t *v, const ccd_vec3_t *w) { #ifndef dLIBCCD_USE_SYSTEM d->v[0] = v->v[0] + w->v[0]; d->v[1] = v->v[1] + w->v[1]; d->v[2] = v->v[2] + w->v[2]; #else ccdVec3Copy(d, v); ccdVec3Add(d, w); #endif } _ccd_inline void ccdVec3CopyScaled(ccd_vec3_t *d, const ccd_vec3_t *s, ccd_real_t k) { #ifndef dLIBCCD_USE_SYSTEM d->v[0] = s->v[0] * k; d->v[1] = s->v[1] * k; d->v[2] = s->v[2] * k; #else ccdVec3Copy(d, s); ccdVec3Scale(d, k); #endif } _ccd_inline void ccdVec3AddScaled(ccd_vec3_t *d, const ccd_vec3_t *v, const ccd_vec3_t *s, ccd_real_t k) { #ifndef dLIBCCD_USE_SYSTEM d->v[0] = v->v[0] + s->v[0] * k; d->v[1] = v->v[1] + s->v[1] * k; d->v[2] = v->v[2] + s->v[2] * k; #else ccdVec3Copy(d, s); ccdVec3Scale(d, k); ccdVec3Add(d, v); #endif } _ccd_inline int ccdVec3SafeNormalize(ccd_vec3_t *d) { int result = -1; ccd_real_t len = CCD_SQRT(ccdVec3Len2(d)); if (len >= CCD_EPS) { ccdVec3Scale(d, CCD_ONE / len); result = 0; } return result; } #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif /* __CCD_CUSTOM_VEC3_H__ */ ode-0.16/libccd/src/ccd.c0000664000175200017520000007305313403272463012056 00000000000000/*** * libccd * --------------------------------- * Copyright (c)2010 Daniel Fiser * * * This file is part of libccd. * * Distributed under the OSI-approved BSD License (the "License"); * see accompanying file BDS-LICENSE for details or see * . * * This software is distributed WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the License for more information. */ #include #include #include #include #include #include #include #include #ifdef HAVE_CONFIG_H #include "config.h" #endif /** Performs GJK algorithm. Returns 0 if intersection was found and simplex * is filled with resulting polytope. */ static int __ccdGJK(const void *obj1, const void *obj2, const ccd_t *ccd, ccd_simplex_t *simplex); /** Performs GJK+EPA algorithm. Returns 0 if intersection was found and * pt is filled with resulting polytope and nearest with pointer to * nearest element (vertex, edge, face) of polytope to origin. */ static int __ccdGJKEPA(const void *obj1, const void *obj2, const ccd_t *ccd, ccd_pt_t *pt, ccd_pt_el_t **nearest); /** Returns true if simplex contains origin. * This function also alteres simplex and dir according to further * processing of GJK algorithm. */ static int doSimplex(ccd_simplex_t *simplex, ccd_vec3_t *dir); static int doSimplex2(ccd_simplex_t *simplex, ccd_vec3_t *dir); static int doSimplex3(ccd_simplex_t *simplex, ccd_vec3_t *dir); static int doSimplex4(ccd_simplex_t *simplex, ccd_vec3_t *dir); /** d = a x b x c */ _ccd_inline void tripleCross(const ccd_vec3_t *a, const ccd_vec3_t *b, const ccd_vec3_t *c, ccd_vec3_t *d); /** Transforms simplex to polytope. It is assumed that simplex has 4 * vertices. */ static int simplexToPolytope4(const void *obj1, const void *obj2, const ccd_t *ccd, ccd_simplex_t *simplex, ccd_pt_t *pt, ccd_pt_el_t **nearest); /** Transforms simplex to polytope, three vertices required */ static int simplexToPolytope3(const void *obj1, const void *obj2, const ccd_t *ccd, const ccd_simplex_t *simplex, ccd_pt_t *pt, ccd_pt_el_t **nearest); /** Transforms simplex to polytope, two vertices required */ static int simplexToPolytope2(const void *obj1, const void *obj2, const ccd_t *ccd, const ccd_simplex_t *simplex, ccd_pt_t *pt, ccd_pt_el_t **nearest); /** Expands polytope using new vertex v. */ static void expandPolytope(ccd_pt_t *pt, ccd_pt_el_t *el, const ccd_support_t *newv); /** Finds next support point (at stores it in out argument). * Returns 0 on success, -1 otherwise */ static int nextSupport(const void *obj1, const void *obj2, const ccd_t *ccd, const ccd_pt_el_t *el, ccd_support_t *out); void ccdFirstDirDefault(const void *o1, const void *o2, ccd_vec3_t *dir) { ccdVec3Set(dir, CCD_ONE, CCD_ZERO, CCD_ZERO); } int ccdGJKIntersect(const void *obj1, const void *obj2, const ccd_t *ccd) { ccd_simplex_t simplex; return __ccdGJK(obj1, obj2, ccd, &simplex) == 0; } int ccdGJKSeparate(const void *obj1, const void *obj2, const ccd_t *ccd, ccd_vec3_t *sep) { ccd_pt_t polytope; ccd_pt_el_t *nearest; int ret; ccdPtInit(&polytope); ret = __ccdGJKEPA(obj1, obj2, ccd, &polytope, &nearest); // set separation vector if (nearest) ccdVec3Copy(sep, &nearest->witness); ccdPtDestroy(&polytope); return ret; } static int penEPAPosCmp(const void *a, const void *b) { ccd_pt_vertex_t *v1, *v2; v1 = *(ccd_pt_vertex_t **)a; v2 = *(ccd_pt_vertex_t **)b; if (ccdEq(v1->dist, v2->dist)){ return 0; }else if (v1->dist < v2->dist){ return -1; }else{ return 1; } } static void penEPAPos(const ccd_pt_t *pt, const ccd_pt_el_t *nearest, ccd_vec3_t *pos) { ccd_pt_vertex_t *v; ccd_pt_vertex_t **vs; size_t i, len; ccd_real_t scale; // compute median len = 0; ccdListForEachEntry(&pt->vertices, v, ccd_pt_vertex_t, list){ len++; } vs = CCD_ALLOC_ARR(ccd_pt_vertex_t *, len); i = 0; ccdListForEachEntry(&pt->vertices, v, ccd_pt_vertex_t, list){ vs[i++] = v; } qsort(vs, len, sizeof(ccd_pt_vertex_t *), penEPAPosCmp); ccdVec3Set(pos, CCD_ZERO, CCD_ZERO, CCD_ZERO); scale = CCD_ZERO; if (len % 2 == 1) len++; for (i = 0; i < len / 2; i++){ ccdVec3Add(pos, &vs[i]->v.v1); ccdVec3Add(pos, &vs[i]->v.v2); scale += CCD_REAL(2.); } ccdVec3Scale(pos, CCD_ONE / scale); free(vs); } int ccdGJKPenetration(const void *obj1, const void *obj2, const ccd_t *ccd, ccd_real_t *depth, ccd_vec3_t *dir, ccd_vec3_t *pos) { ccd_pt_t polytope; ccd_pt_el_t *nearest; int ret; ccdPtInit(&polytope); ret = __ccdGJKEPA(obj1, obj2, ccd, &polytope, &nearest); // set separation vector if (ret == 0 && nearest){ // store normalized direction vector ccdVec3Copy(dir, &nearest->witness); ret = ccdVec3SafeNormalize(dir); if (ret == 0) { // compute depth of penetration *depth = CCD_SQRT(nearest->dist); // compute position penEPAPos(&polytope, nearest, pos); } } ccdPtDestroy(&polytope); return ret; } static int __ccdGJK(const void *obj1, const void *obj2, const ccd_t *ccd, ccd_simplex_t *simplex) { unsigned long iterations; ccd_vec3_t dir; // direction vector ccd_support_t last; // last support point int do_simplex_res; // initialize simplex struct ccdSimplexInit(simplex); // get first direction ccd->first_dir(obj1, obj2, &dir); // get first support point __ccdSupport(obj1, obj2, &dir, ccd, &last); // and add this point to simplex as last one ccdSimplexAdd(simplex, &last); // set up direction vector to as (O - last) which is exactly -last ccdVec3Copy(&dir, &last.v); ccdVec3Scale(&dir, -CCD_ONE); // start iterations for (iterations = 0UL; iterations < ccd->max_iterations; ++iterations) { // obtain support point __ccdSupport(obj1, obj2, &dir, ccd, &last); // check if farthest point in Minkowski difference in direction dir // isn't somewhere before origin (the test on negative dot product) // - because if it is, objects are not intersecting at all. if (ccdVec3Dot(&last.v, &dir) < CCD_ZERO){ return -1; // intersection not found } // add last support vector to simplex ccdSimplexAdd(simplex, &last); // if doSimplex returns 1 if objects intersect, -1 if objects don't // intersect and 0 if algorithm should continue do_simplex_res = doSimplex(simplex, &dir); if (do_simplex_res == 1){ return 0; // intersection found }else if (do_simplex_res == -1){ return -1; // intersection not found } if (ccdIsZero(ccdVec3Len2(&dir))){ return -1; // intersection not found } } // intersection wasn't found return -1; } static int __ccdGJKEPA(const void *obj1, const void *obj2, const ccd_t *ccd, ccd_pt_t *polytope, ccd_pt_el_t **nearest) { ccd_simplex_t simplex; ccd_support_t supp; // support point int ret, size; *nearest = NULL; // run GJK and obtain terminal simplex ret = __ccdGJK(obj1, obj2, ccd, &simplex); if (ret != 0) return -1; // transform simplex to polytope - simplex won't be used anymore size = ccdSimplexSize(&simplex); if (size == 4){ if (simplexToPolytope4(obj1, obj2, ccd, &simplex, polytope, nearest) != 0){ return 0;// touch contact } }else if (size == 3){ if (simplexToPolytope3(obj1, obj2, ccd, &simplex, polytope, nearest) != 0){ return 0; // touch contact } }else{ // size == 2 if (simplexToPolytope2(obj1, obj2, ccd, &simplex, polytope, nearest) != 0){ return 0; // touch contact } } while (1){ // get triangle nearest to origin *nearest = ccdPtNearest(polytope); // get next support point if (nextSupport(obj1, obj2, ccd, *nearest, &supp) != 0) break; // expand nearest triangle using new point - supp expandPolytope(polytope, *nearest, &supp); } return 0; } static int doSimplex2(ccd_simplex_t *simplex, ccd_vec3_t *dir) { const ccd_support_t *A, *B; ccd_vec3_t AB, AO, tmp; ccd_real_t dot; // get last added as A A = ccdSimplexLast(simplex); // get the other point B = ccdSimplexPoint(simplex, 0); // compute AB oriented segment ccdVec3Sub2(&AB, &B->v, &A->v); // compute AO vector ccdVec3Copy(&AO, &A->v); ccdVec3Scale(&AO, -CCD_ONE); // dot product AB . AO dot = ccdVec3Dot(&AB, &AO); // check if origin doesn't lie on AB segment ccdVec3Cross(&tmp, &AB, &AO); if (ccdIsZero(ccdVec3Len2(&tmp)) && dot > CCD_ZERO){ return 1; } // check if origin is in area where AB segment is if (ccdIsZero(dot) || dot < CCD_ZERO){ // origin is in outside are of A ccdSimplexSet(simplex, 0, A); ccdSimplexSetSize(simplex, 1); ccdVec3Copy(dir, &AO); }else{ // origin is in area where AB segment is // keep simplex untouched and set direction to // AB x AO x AB tripleCross(&AB, &AO, &AB, dir); } return 0; } static int doSimplex3(ccd_simplex_t *simplex, ccd_vec3_t *dir) { const ccd_support_t *A, *B, *C; ccd_vec3_t AO, AB, AC, ABC, tmp; ccd_real_t dot, dist; // get last added as A A = ccdSimplexLast(simplex); // get the other points B = ccdSimplexPoint(simplex, 1); C = ccdSimplexPoint(simplex, 0); // check touching contact dist = ccdVec3PointTriDist2(ccd_vec3_origin, &A->v, &B->v, &C->v, NULL); if (ccdIsZero(dist)){ return 1; } // check if triangle is really triangle (has area > 0) // if not simplex can't be expanded and thus no itersection is found if (ccdVec3Eq(&A->v, &B->v) || ccdVec3Eq(&A->v, &C->v)){ return -1; } // compute AO vector ccdVec3Copy(&AO, &A->v); ccdVec3Scale(&AO, -CCD_ONE); // compute AB and AC segments and ABC vector (perpendircular to triangle) ccdVec3Sub2(&AB, &B->v, &A->v); ccdVec3Sub2(&AC, &C->v, &A->v); ccdVec3Cross(&ABC, &AB, &AC); ccdVec3Cross(&tmp, &ABC, &AC); dot = ccdVec3Dot(&tmp, &AO); if (ccdIsZero(dot) || dot > CCD_ZERO){ dot = ccdVec3Dot(&AC, &AO); if (ccdIsZero(dot) || dot > CCD_ZERO){ // C is already in place ccdSimplexSet(simplex, 1, A); ccdSimplexSetSize(simplex, 2); tripleCross(&AC, &AO, &AC, dir); }else{ ccd_do_simplex3_45: dot = ccdVec3Dot(&AB, &AO); if (ccdIsZero(dot) || dot > CCD_ZERO){ ccdSimplexSet(simplex, 0, B); ccdSimplexSet(simplex, 1, A); ccdSimplexSetSize(simplex, 2); tripleCross(&AB, &AO, &AB, dir); }else{ ccdSimplexSet(simplex, 0, A); ccdSimplexSetSize(simplex, 1); ccdVec3Copy(dir, &AO); } } }else{ ccdVec3Cross(&tmp, &AB, &ABC); dot = ccdVec3Dot(&tmp, &AO); if (ccdIsZero(dot) || dot > CCD_ZERO){ goto ccd_do_simplex3_45; }else{ dot = ccdVec3Dot(&ABC, &AO); if (ccdIsZero(dot) || dot > CCD_ZERO){ ccdVec3Copy(dir, &ABC); }else{ ccd_support_t Ctmp; ccdSupportCopy(&Ctmp, C); ccdSimplexSet(simplex, 0, B); ccdSimplexSet(simplex, 1, &Ctmp); ccdVec3Copy(dir, &ABC); ccdVec3Scale(dir, -CCD_ONE); } } } return 0; } static int doSimplex4(ccd_simplex_t *simplex, ccd_vec3_t *dir) { const ccd_support_t *A, *B, *C, *D; ccd_vec3_t AO, AB, AC, AD, ABC, ACD, ADB; int B_on_ACD, C_on_ADB, D_on_ABC; int AB_O, AC_O, AD_O; ccd_real_t dist; // get last added as A A = ccdSimplexLast(simplex); // get the other points B = ccdSimplexPoint(simplex, 2); C = ccdSimplexPoint(simplex, 1); D = ccdSimplexPoint(simplex, 0); // check if tetrahedron is really tetrahedron (has volume > 0) // if it is not simplex can't be expanded and thus no intersection is // found dist = ccdVec3PointTriDist2(&A->v, &B->v, &C->v, &D->v, NULL); if (ccdIsZero(dist)){ return -1; } // check if origin lies on some of tetrahedron's face - if so objects // intersect dist = ccdVec3PointTriDist2(ccd_vec3_origin, &A->v, &B->v, &C->v, NULL); if (ccdIsZero(dist)) return 1; dist = ccdVec3PointTriDist2(ccd_vec3_origin, &A->v, &C->v, &D->v, NULL); if (ccdIsZero(dist)) return 1; dist = ccdVec3PointTriDist2(ccd_vec3_origin, &A->v, &B->v, &D->v, NULL); if (ccdIsZero(dist)) return 1; dist = ccdVec3PointTriDist2(ccd_vec3_origin, &B->v, &C->v, &D->v, NULL); if (ccdIsZero(dist)) return 1; // compute AO, AB, AC, AD segments and ABC, ACD, ADB normal vectors ccdVec3Copy(&AO, &A->v); ccdVec3Scale(&AO, -CCD_ONE); ccdVec3Sub2(&AB, &B->v, &A->v); ccdVec3Sub2(&AC, &C->v, &A->v); ccdVec3Sub2(&AD, &D->v, &A->v); ccdVec3Cross(&ABC, &AB, &AC); ccdVec3Cross(&ACD, &AC, &AD); ccdVec3Cross(&ADB, &AD, &AB); // side (positive or negative) of B, C, D relative to planes ACD, ADB // and ABC respectively B_on_ACD = ccdSign(ccdVec3Dot(&ACD, &AB)); C_on_ADB = ccdSign(ccdVec3Dot(&ADB, &AC)); D_on_ABC = ccdSign(ccdVec3Dot(&ABC, &AD)); // whether origin is on same side of ACD, ADB, ABC as B, C, D // respectively AB_O = ccdSign(ccdVec3Dot(&ACD, &AO)) == B_on_ACD; AC_O = ccdSign(ccdVec3Dot(&ADB, &AO)) == C_on_ADB; AD_O = ccdSign(ccdVec3Dot(&ABC, &AO)) == D_on_ABC; if (AB_O && AC_O && AD_O){ // origin is in tetrahedron return 1; // rearrange simplex to triangle and call doSimplex3() }else if (!AB_O){ // B is farthest from the origin among all of the tetrahedron's // points, so remove it from the list and go on with the triangle // case // D and C are in place ccdSimplexSet(simplex, 2, A); ccdSimplexSetSize(simplex, 3); }else if (!AC_O){ // C is farthest ccdSimplexSet(simplex, 1, D); ccdSimplexSet(simplex, 0, B); ccdSimplexSet(simplex, 2, A); ccdSimplexSetSize(simplex, 3); }else{ // (!AD_O) ccdSimplexSet(simplex, 0, C); ccdSimplexSet(simplex, 1, B); ccdSimplexSet(simplex, 2, A); ccdSimplexSetSize(simplex, 3); } return doSimplex3(simplex, dir); } static int doSimplex(ccd_simplex_t *simplex, ccd_vec3_t *dir) { if (ccdSimplexSize(simplex) == 2){ // simplex contains segment only one segment return doSimplex2(simplex, dir); }else if (ccdSimplexSize(simplex) == 3){ // simplex contains triangle return doSimplex3(simplex, dir); }else{ // ccdSimplexSize(simplex) == 4 // tetrahedron - this is the only shape which can encapsule origin // so doSimplex4() also contains test on it return doSimplex4(simplex, dir); } } _ccd_inline void tripleCross(const ccd_vec3_t *a, const ccd_vec3_t *b, const ccd_vec3_t *c, ccd_vec3_t *d) { ccd_vec3_t e; ccdVec3Cross(&e, a, b); ccdVec3Cross(d, &e, c); } /** Transforms simplex to polytope. It is assumed that simplex has 4 * vertices! */ static int simplexToPolytope4(const void *obj1, const void *obj2, const ccd_t *ccd, ccd_simplex_t *simplex, ccd_pt_t *pt, ccd_pt_el_t **nearest) { const ccd_support_t *a, *b, *c, *d; int use_polytope3; ccd_real_t dist; ccd_pt_vertex_t *v[4]; ccd_pt_edge_t *e[6]; size_t i; a = ccdSimplexPoint(simplex, 0); b = ccdSimplexPoint(simplex, 1); c = ccdSimplexPoint(simplex, 2); d = ccdSimplexPoint(simplex, 3); // check if origin lies on some of tetrahedron's face - if so use // simplexToPolytope3() use_polytope3 = 0; dist = ccdVec3PointTriDist2(ccd_vec3_origin, &a->v, &b->v, &c->v, NULL); if (ccdIsZero(dist)){ use_polytope3 = 1; } dist = ccdVec3PointTriDist2(ccd_vec3_origin, &a->v, &c->v, &d->v, NULL); if (ccdIsZero(dist)){ use_polytope3 = 1; ccdSimplexSet(simplex, 1, c); ccdSimplexSet(simplex, 2, d); } dist = ccdVec3PointTriDist2(ccd_vec3_origin, &a->v, &b->v, &d->v, NULL); if (ccdIsZero(dist)){ use_polytope3 = 1; ccdSimplexSet(simplex, 2, d); } dist = ccdVec3PointTriDist2(ccd_vec3_origin, &b->v, &c->v, &d->v, NULL); if (ccdIsZero(dist)){ use_polytope3 = 1; ccdSimplexSet(simplex, 0, b); ccdSimplexSet(simplex, 1, c); ccdSimplexSet(simplex, 2, d); } if (use_polytope3){ ccdSimplexSetSize(simplex, 3); return simplexToPolytope3(obj1, obj2, ccd, simplex, pt, nearest); } // no touching contact - simply create tetrahedron for (i = 0; i < 4; i++){ v[i] = ccdPtAddVertex(pt, ccdSimplexPoint(simplex, i)); } e[0] = ccdPtAddEdge(pt, v[0], v[1]); e[1] = ccdPtAddEdge(pt, v[1], v[2]); e[2] = ccdPtAddEdge(pt, v[2], v[0]); e[3] = ccdPtAddEdge(pt, v[3], v[0]); e[4] = ccdPtAddEdge(pt, v[3], v[1]); e[5] = ccdPtAddEdge(pt, v[3], v[2]); ccdPtAddFace(pt, e[0], e[1], e[2]); ccdPtAddFace(pt, e[3], e[4], e[0]); ccdPtAddFace(pt, e[4], e[5], e[1]); ccdPtAddFace(pt, e[5], e[3], e[2]); return 0; } /** Transforms simplex to polytope, three vertices required */ static int simplexToPolytope3(const void *obj1, const void *obj2, const ccd_t *ccd, const ccd_simplex_t *simplex, ccd_pt_t *pt, ccd_pt_el_t **nearest) { const ccd_support_t *a, *b, *c; ccd_support_t d, d2; ccd_vec3_t ab, ac, dir; ccd_pt_vertex_t *v[5]; ccd_pt_edge_t *e[9]; ccd_real_t dist, dist2; *nearest = NULL; a = ccdSimplexPoint(simplex, 0); b = ccdSimplexPoint(simplex, 1); c = ccdSimplexPoint(simplex, 2); // If only one triangle left from previous GJK run origin lies on this // triangle. So it is necessary to expand triangle into two // tetrahedrons connected with base (which is exactly abc triangle). // get next support point in direction of normal of triangle ccdVec3Sub2(&ab, &b->v, &a->v); ccdVec3Sub2(&ac, &c->v, &a->v); ccdVec3Cross(&dir, &ab, &ac); __ccdSupport(obj1, obj2, &dir, ccd, &d); dist = ccdVec3PointTriDist2(&d.v, &a->v, &b->v, &c->v, NULL); // and second one take in opposite direction ccdVec3Scale(&dir, -CCD_ONE); __ccdSupport(obj1, obj2, &dir, ccd, &d2); dist2 = ccdVec3PointTriDist2(&d2.v, &a->v, &b->v, &c->v, NULL); // check if face isn't already on edge of minkowski sum and thus we // have touching contact if (ccdIsZero(dist) || ccdIsZero(dist2)){ v[0] = ccdPtAddVertex(pt, a); v[1] = ccdPtAddVertex(pt, b); v[2] = ccdPtAddVertex(pt, c); e[0] = ccdPtAddEdge(pt, v[0], v[1]); e[1] = ccdPtAddEdge(pt, v[1], v[2]); e[2] = ccdPtAddEdge(pt, v[2], v[0]); *nearest = (ccd_pt_el_t *)ccdPtAddFace(pt, e[0], e[1], e[2]); return -1; } // form polyhedron v[0] = ccdPtAddVertex(pt, a); v[1] = ccdPtAddVertex(pt, b); v[2] = ccdPtAddVertex(pt, c); v[3] = ccdPtAddVertex(pt, &d); v[4] = ccdPtAddVertex(pt, &d2); e[0] = ccdPtAddEdge(pt, v[0], v[1]); e[1] = ccdPtAddEdge(pt, v[1], v[2]); e[2] = ccdPtAddEdge(pt, v[2], v[0]); e[3] = ccdPtAddEdge(pt, v[3], v[0]); e[4] = ccdPtAddEdge(pt, v[3], v[1]); e[5] = ccdPtAddEdge(pt, v[3], v[2]); e[6] = ccdPtAddEdge(pt, v[4], v[0]); e[7] = ccdPtAddEdge(pt, v[4], v[1]); e[8] = ccdPtAddEdge(pt, v[4], v[2]); ccdPtAddFace(pt, e[3], e[4], e[0]); ccdPtAddFace(pt, e[4], e[5], e[1]); ccdPtAddFace(pt, e[5], e[3], e[2]); ccdPtAddFace(pt, e[6], e[7], e[0]); ccdPtAddFace(pt, e[7], e[8], e[1]); ccdPtAddFace(pt, e[8], e[6], e[2]); return 0; } /** Transforms simplex to polytope, two vertices required */ static int simplexToPolytope2(const void *obj1, const void *obj2, const ccd_t *ccd, const ccd_simplex_t *simplex, ccd_pt_t *pt, ccd_pt_el_t **nearest) { const ccd_support_t *a, *b; ccd_vec3_t ab, ac, dir; ccd_support_t supp[4]; ccd_pt_vertex_t *v[6]; ccd_pt_edge_t *e[12]; size_t i; int found; a = ccdSimplexPoint(simplex, 0); b = ccdSimplexPoint(simplex, 1); // This situation is a bit tricky. If only one segment comes from // previous run of GJK - it means that either this segment is on // minkowski edge (and thus we have touch contact) or it it isn't and // therefore segment is somewhere *inside* minkowski sum and it *must* // be possible to fully enclose this segment with polyhedron formed by // at least 8 triangle faces. // get first support point (any) found = 0; for (i = 0; i < ccd_points_on_sphere_len; i++){ __ccdSupport(obj1, obj2, &ccd_points_on_sphere[i], ccd, &supp[0]); if (!ccdVec3Eq(&a->v, &supp[0].v) && !ccdVec3Eq(&b->v, &supp[0].v)){ found = 1; break; } } if (!found) goto simplexToPolytope2_touching_contact; // get second support point in opposite direction than supp[0] ccdVec3Copy(&dir, &supp[0].v); ccdVec3Scale(&dir, -CCD_ONE); __ccdSupport(obj1, obj2, &dir, ccd, &supp[1]); if (ccdVec3Eq(&a->v, &supp[1].v) || ccdVec3Eq(&b->v, &supp[1].v)) goto simplexToPolytope2_touching_contact; // next will be in direction of normal of triangle a,supp[0],supp[1] ccdVec3Sub2(&ab, &supp[0].v, &a->v); ccdVec3Sub2(&ac, &supp[1].v, &a->v); ccdVec3Cross(&dir, &ab, &ac); __ccdSupport(obj1, obj2, &dir, ccd, &supp[2]); if (ccdVec3Eq(&a->v, &supp[2].v) || ccdVec3Eq(&b->v, &supp[2].v)) goto simplexToPolytope2_touching_contact; // and last one will be in opposite direction ccdVec3Scale(&dir, -CCD_ONE); __ccdSupport(obj1, obj2, &dir, ccd, &supp[3]); if (ccdVec3Eq(&a->v, &supp[3].v) || ccdVec3Eq(&b->v, &supp[3].v)) goto simplexToPolytope2_touching_contact; goto simplexToPolytope2_not_touching_contact; simplexToPolytope2_touching_contact: v[0] = ccdPtAddVertex(pt, a); v[1] = ccdPtAddVertex(pt, b); *nearest = (ccd_pt_el_t *)ccdPtAddEdge(pt, v[0], v[1]); return -1; simplexToPolytope2_not_touching_contact: // form polyhedron v[0] = ccdPtAddVertex(pt, a); v[1] = ccdPtAddVertex(pt, &supp[0]); v[2] = ccdPtAddVertex(pt, b); v[3] = ccdPtAddVertex(pt, &supp[1]); v[4] = ccdPtAddVertex(pt, &supp[2]); v[5] = ccdPtAddVertex(pt, &supp[3]); e[0] = ccdPtAddEdge(pt, v[0], v[1]); e[1] = ccdPtAddEdge(pt, v[1], v[2]); e[2] = ccdPtAddEdge(pt, v[2], v[3]); e[3] = ccdPtAddEdge(pt, v[3], v[0]); e[4] = ccdPtAddEdge(pt, v[4], v[0]); e[5] = ccdPtAddEdge(pt, v[4], v[1]); e[6] = ccdPtAddEdge(pt, v[4], v[2]); e[7] = ccdPtAddEdge(pt, v[4], v[3]); e[8] = ccdPtAddEdge(pt, v[5], v[0]); e[9] = ccdPtAddEdge(pt, v[5], v[1]); e[10] = ccdPtAddEdge(pt, v[5], v[2]); e[11] = ccdPtAddEdge(pt, v[5], v[3]); ccdPtAddFace(pt, e[4], e[5], e[0]); ccdPtAddFace(pt, e[5], e[6], e[1]); ccdPtAddFace(pt, e[6], e[7], e[2]); ccdPtAddFace(pt, e[7], e[4], e[3]); ccdPtAddFace(pt, e[8], e[9], e[0]); ccdPtAddFace(pt, e[9], e[10], e[1]); ccdPtAddFace(pt, e[10], e[11], e[2]); ccdPtAddFace(pt, e[11], e[8], e[3]); return 0; } /** Expands polytope's tri by new vertex v. Triangle tri is replaced by * three triangles each with one vertex in v. */ static void expandPolytope(ccd_pt_t *pt, ccd_pt_el_t *el, const ccd_support_t *newv) { ccd_pt_vertex_t *v[5]; ccd_pt_edge_t *e[8] = {0}; ccd_pt_face_t *f[2]; // element can be either segment or triangle if (el->type == CCD_PT_EDGE){ // In this case, segment should be replaced by new point. // Simpliest case is when segment stands alone and in this case // this segment is replaced by two other segments both connected to // newv. // Segment can be also connected to max two faces and in that case // each face must be replaced by two other faces. To do this // correctly it is necessary to have correctly ordered edges and // vertices which is exactly what is done in following code. // ccdPtEdgeVertices((const ccd_pt_edge_t *)el, &v[0], &v[2]); ccdPtEdgeFaces((ccd_pt_edge_t *)el, &f[0], &f[1]); if (f[0]){ ccdPtFaceEdges(f[0], &e[0], &e[1], &e[2]); if (e[0] == (ccd_pt_edge_t *)el){ e[0] = e[2]; }else if (e[1] == (ccd_pt_edge_t *)el){ e[1] = e[2]; } ccdPtEdgeVertices(e[0], &v[1], &v[3]); if (v[1] != v[0] && v[3] != v[0]){ e[2] = e[0]; e[0] = e[1]; e[1] = e[2]; if (v[1] == v[2]) v[1] = v[3]; }else{ if (v[1] == v[0]) v[1] = v[3]; } if (f[1]){ ccdPtFaceEdges(f[1], &e[2], &e[3], &e[4]); if (e[2] == (ccd_pt_edge_t *)el){ e[2] = e[4]; }else if (e[3] == (ccd_pt_edge_t *)el){ e[3] = e[4]; } ccdPtEdgeVertices(e[2], &v[3], &v[4]); if (v[3] != v[2] && v[4] != v[2]){ e[4] = e[2]; e[2] = e[3]; e[3] = e[4]; if (v[3] == v[0]) v[3] = v[4]; }else{ if (v[3] == v[2]) v[3] = v[4]; } } v[4] = ccdPtAddVertex(pt, newv); ccdPtDelFace(pt, f[0]); if (f[1]){ ccdPtDelFace(pt, f[1]); ccdPtDelEdge(pt, (ccd_pt_edge_t *)el); } e[4] = ccdPtAddEdge(pt, v[4], v[2]); e[5] = ccdPtAddEdge(pt, v[4], v[0]); e[6] = ccdPtAddEdge(pt, v[4], v[1]); if (f[1]) e[7] = ccdPtAddEdge(pt, v[4], v[3]); ccdPtAddFace(pt, e[1], e[4], e[6]); ccdPtAddFace(pt, e[0], e[6], e[5]); if (f[1]){ ccdPtAddFace(pt, e[3], e[5], e[7]); ccdPtAddFace(pt, e[4], e[7], e[2]); }else{ ccdPtAddFace(pt, e[4], e[5], (ccd_pt_edge_t *)el); } } }else{ // el->type == CCD_PT_FACE // replace triangle by tetrahedron without base (base would be the // triangle that will be removed) // get triplet of surrounding edges and vertices of triangle face ccdPtFaceEdges((const ccd_pt_face_t *)el, &e[0], &e[1], &e[2]); ccdPtEdgeVertices(e[0], &v[0], &v[1]); ccdPtEdgeVertices(e[1], &v[2], &v[3]); // following code sorts edges to have e[0] between vertices 0-1, // e[1] between 1-2 and e[2] between 2-0 if (v[2] != v[1] && v[3] != v[1]){ // swap e[1] and e[2] e[3] = e[1]; e[1] = e[2]; e[2] = e[3]; } if (v[3] != v[0] && v[3] != v[1]) v[2] = v[3]; // remove triangle face ccdPtDelFace(pt, (ccd_pt_face_t *)el); // expand triangle to tetrahedron v[3] = ccdPtAddVertex(pt, newv); e[3] = ccdPtAddEdge(pt, v[3], v[0]); e[4] = ccdPtAddEdge(pt, v[3], v[1]); e[5] = ccdPtAddEdge(pt, v[3], v[2]); ccdPtAddFace(pt, e[3], e[4], e[0]); ccdPtAddFace(pt, e[4], e[5], e[1]); ccdPtAddFace(pt, e[5], e[3], e[2]); } } /** Finds next support point (at stores it in out argument). * Returns 0 on success, -1 otherwise */ static int nextSupport(const void *obj1, const void *obj2, const ccd_t *ccd, const ccd_pt_el_t *el, ccd_support_t *out) { ccd_vec3_t *a, *b, *c; ccd_real_t dist; if (el->type == CCD_PT_VERTEX) return -1; // touch contact if (ccdIsZero(el->dist)) return -1; __ccdSupport(obj1, obj2, &el->witness, ccd, out); if (el->type == CCD_PT_EDGE){ // fetch end points of edge ccdPtEdgeVec3((ccd_pt_edge_t *)el, &a, &b); // get distance from segment dist = ccdVec3PointSegmentDist2(&out->v, a, b, NULL); }else{ // el->type == CCD_PT_FACE // fetch vertices of triangle face ccdPtFaceVec3((ccd_pt_face_t *)el, &a, &b, &c); // check if new point can significantly expand polytope dist = ccdVec3PointTriDist2(&out->v, a, b, c, NULL); } if (dist < ccd->epa_tolerance) return -1; return 0; } ode-0.16/libccd/src/mpr.c0000664000175200017520000004502613403272463012122 00000000000000/*** * libccd * --------------------------------- * Copyright (c)2010,2011 Daniel Fiser * * * This file is part of libccd. * * Distributed under the OSI-approved BSD License (the "License"); * see accompanying file BDS-LICENSE for details or see * . * * This software is distributed WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the License for more information. */ #include #include #include #include #include #ifdef HAVE_CONFIG_H #include "config.h" #endif /** Finds origin (center) of Minkowski difference (actually it can be any * interior point of Minkowski difference. */ _ccd_inline void findOrigin(const void *obj1, const void *obj2, const ccd_t *ccd, ccd_support_t *center); /** Discovers initial portal - that is tetrahedron that intersects with * origin ray (ray from center of Minkowski diff to (0,0,0). * * Returns -1 if already recognized that origin is outside Minkowski * portal. * Returns 1 if origin lies on v1 of simplex (only v0 and v1 are present * in simplex). * Returns 2 if origin lies on v0-v1 segment. * Returns 0 if portal was built. */ static int discoverPortal(const void *obj1, const void *obj2, const ccd_t *ccd, ccd_simplex_t *portal); /** Expands portal towards origin and determine if objects intersect. * Already established portal must be given as argument. * If intersection is found 0 is returned, -1 otherwise */ static int refinePortal(const void *obj1, const void *obj2, const ccd_t *ccd, ccd_simplex_t *portal); /** Finds penetration info by expanding provided portal. */ static int findPenetr(const void *obj1, const void *obj2, const ccd_t *ccd, ccd_simplex_t *portal, ccd_real_t *depth, ccd_vec3_t *dir, ccd_vec3_t *pos); /** Finds penetration info if origin lies on portal's v1 */ static void findPenetrTouch(const void *obj1, const void *obj2, const ccd_t *ccd, ccd_simplex_t *portal, ccd_real_t *depth, ccd_vec3_t *dir, ccd_vec3_t *pos); /** Find penetration info if origin lies on portal's segment v0-v1 */ static int findPenetrSegment(const void *obj1, const void *obj2, const ccd_t *ccd, ccd_simplex_t *portal, ccd_real_t *depth, ccd_vec3_t *dir, ccd_vec3_t *pos); /** Finds position vector from fully established portal */ static int findPos(const void *obj1, const void *obj2, const ccd_t *ccd, const ccd_simplex_t *portal, ccd_vec3_t *pos); /** Extends portal with new support point. * Portal must have face v1-v2-v3 arranged to face outside portal. */ _ccd_inline void expandPortal(ccd_simplex_t *portal, const ccd_support_t *v4); /** Fill dir with direction outside portal. Portal's v1-v2-v3 face must be * arranged in correct order! */ _ccd_inline int portalDir(const ccd_simplex_t *portal, ccd_vec3_t *dir); /** Returns true if portal encapsules origin (0,0,0), dir is direction of * v1-v2-v3 face. */ _ccd_inline int portalEncapsulesOrigin(const ccd_simplex_t *portal, const ccd_vec3_t *dir); /** Returns true if portal with new point v4 would reach specified * tolerance (i.e. returns true if portal can _not_ significantly expand * within Minkowski difference). * * v4 is candidate for new point in portal, dir is direction in which v4 * was obtained. */ _ccd_inline int portalReachTolerance(const ccd_simplex_t *portal, const ccd_support_t *v4, const ccd_vec3_t *dir, const ccd_t *ccd); /** Returns true if portal expanded by new point v4 could possibly contain * origin, dir is direction in which v4 was obtained. */ _ccd_inline int portalCanEncapsuleOrigin(const ccd_simplex_t *portal, const ccd_support_t *v4, const ccd_vec3_t *dir); int ccdMPRIntersect(const void *obj1, const void *obj2, const ccd_t *ccd) { ccd_simplex_t portal; int res; // Phase 1: Portal discovery - find portal that intersects with origin // ray (ray from center of Minkowski diff to origin of coordinates) res = discoverPortal(obj1, obj2, ccd, &portal); if (res < 0) return 0; if (res > 0) return 1; // Phase 2: Portal refinement res = refinePortal(obj1, obj2, ccd, &portal); return (res == 0 ? 1 : 0); } int ccdMPRPenetration(const void *obj1, const void *obj2, const ccd_t *ccd, ccd_real_t *depth, ccd_vec3_t *dir, ccd_vec3_t *pos) { ccd_simplex_t portal; int res; // Phase 1: Portal discovery res = discoverPortal(obj1, obj2, ccd, &portal); if (res < 0){ // Origin isn't inside portal - no collision. return -1; }else if (res == 1){ // Touching contact on portal's v1. findPenetrTouch(obj1, obj2, ccd, &portal, depth, dir, pos); }else if (res == 2){ // Origin lies on v0-v1 segment. if (findPenetrSegment(obj1, obj2, ccd, &portal, depth, dir, pos) != 0) { return -1; } }else if (res == 0){ // Phase 2: Portal refinement res = refinePortal(obj1, obj2, ccd, &portal); if (res < 0) { return -1; } // Phase 3. Penetration info if (findPenetr(obj1, obj2, ccd, &portal, depth, dir, pos) != 0) { return -1; } } return 0; } _ccd_inline void findOrigin(const void *obj1, const void *obj2, const ccd_t *ccd, ccd_support_t *center) { ccd->center1(obj1, ¢er->v1); ccd->center2(obj2, ¢er->v2); ccdVec3Sub2(¢er->v, ¢er->v1, ¢er->v2); } static int discoverPortal(const void *obj1, const void *obj2, const ccd_t *ccd, ccd_simplex_t *portal) { ccd_vec3_t dir, va, vb; ccd_real_t dot; int cont; // vertex 0 is center of portal findOrigin(obj1, obj2, ccd, ccdSimplexPointW(portal, 0)); ccdSimplexSetSize(portal, 1); if (ccdVec3Eq(&ccdSimplexPoint(portal, 0)->v, ccd_vec3_origin)){ // Portal's center lies on origin (0,0,0) => we know that objects // intersect but we would need to know penetration info. // So move center little bit... ccdVec3Set(&va, CCD_EPS * CCD_REAL(10.), CCD_ZERO, CCD_ZERO); ccdVec3Add(&ccdSimplexPointW(portal, 0)->v, &va); } // vertex 1 = support in direction of origin ccdVec3Copy(&dir, &ccdSimplexPoint(portal, 0)->v); ccdVec3Scale(&dir, CCD_REAL(-1.)); if (ccdVec3SafeNormalize(&dir) != 0) { return -1; } __ccdSupport(obj1, obj2, &dir, ccd, ccdSimplexPointW(portal, 1)); ccdSimplexSetSize(portal, 2); // test if origin isn't outside of v1 dot = ccdVec3Dot(&ccdSimplexPoint(portal, 1)->v, &dir); if (ccdIsZero(dot) || dot < CCD_ZERO) return -1; // vertex 2 ccdVec3Cross(&dir, &ccdSimplexPoint(portal, 0)->v, &ccdSimplexPoint(portal, 1)->v); if (ccdIsZero(ccdVec3Len2(&dir))){ if (ccdVec3Eq(&ccdSimplexPoint(portal, 1)->v, ccd_vec3_origin)){ // origin lies on v1 return 1; }else{ // origin lies on v0-v1 segment return 2; } } if (ccdVec3SafeNormalize(&dir) != 0) { return -1; } __ccdSupport(obj1, obj2, &dir, ccd, ccdSimplexPointW(portal, 2)); dot = ccdVec3Dot(&ccdSimplexPoint(portal, 2)->v, &dir); if (ccdIsZero(dot) || dot < CCD_ZERO) { return -1; } ccdSimplexSetSize(portal, 3); // vertex 3 direction ccdVec3Sub2(&va, &ccdSimplexPoint(portal, 1)->v, &ccdSimplexPoint(portal, 0)->v); ccdVec3Sub2(&vb, &ccdSimplexPoint(portal, 2)->v, &ccdSimplexPoint(portal, 0)->v); ccdVec3Cross(&dir, &va, &vb); if (ccdVec3SafeNormalize(&dir) != 0) { return -1; } // it is better to form portal faces to be oriented "outside" origin dot = ccdVec3Dot(&dir, &ccdSimplexPoint(portal, 0)->v); if (dot > CCD_ZERO){ ccdSimplexSwap(portal, 1, 2); ccdVec3Scale(&dir, CCD_REAL(-1.)); } while (ccdSimplexSize(portal) < 4){ __ccdSupport(obj1, obj2, &dir, ccd, ccdSimplexPointW(portal, 3)); dot = ccdVec3Dot(&ccdSimplexPoint(portal, 3)->v, &dir); if (ccdIsZero(dot) || dot < CCD_ZERO) { return -1; } cont = 0; // test if origin is outside (v1, v0, v3) - set v2 as v3 and // continue ccdVec3Cross(&va, &ccdSimplexPoint(portal, 1)->v, &ccdSimplexPoint(portal, 3)->v); dot = ccdVec3Dot(&va, &ccdSimplexPoint(portal, 0)->v); if (dot < CCD_ZERO && !ccdIsZero(dot)){ ccdSimplexSet(portal, 2, ccdSimplexPoint(portal, 3)); cont = 1; } if (!cont){ // test if origin is outside (v3, v0, v2) - set v1 as v3 and // continue ccdVec3Cross(&va, &ccdSimplexPoint(portal, 3)->v, &ccdSimplexPoint(portal, 2)->v); dot = ccdVec3Dot(&va, &ccdSimplexPoint(portal, 0)->v); if (dot < CCD_ZERO && !ccdIsZero(dot)){ ccdSimplexSet(portal, 1, ccdSimplexPoint(portal, 3)); cont = 1; } } if (cont){ ccdVec3Sub2(&va, &ccdSimplexPoint(portal, 1)->v, &ccdSimplexPoint(portal, 0)->v); ccdVec3Sub2(&vb, &ccdSimplexPoint(portal, 2)->v, &ccdSimplexPoint(portal, 0)->v); ccdVec3Cross(&dir, &va, &vb); if (ccdVec3SafeNormalize(&dir) != 0) { return -1; } }else{ ccdSimplexSetSize(portal, 4); } } return 0; } static int refinePortal(const void *obj1, const void *obj2, const ccd_t *ccd, ccd_simplex_t *portal) { ccd_vec3_t dir; ccd_support_t v4; while (1){ // compute direction outside the portal (from v0 throught v1,v2,v3 // face) if (portalDir(portal, &dir) != 0) { return -1; } // test if origin is inside the portal if (portalEncapsulesOrigin(portal, &dir)) return 0; // get next support point __ccdSupport(obj1, obj2, &dir, ccd, &v4); // test if v4 can expand portal to contain origin and if portal // expanding doesn't reach given tolerance if (!portalCanEncapsuleOrigin(portal, &v4, &dir) || portalReachTolerance(portal, &v4, &dir, ccd)){ return -1; } // v1-v2-v3 triangle must be rearranged to face outside Minkowski // difference (direction from v0). expandPortal(portal, &v4); } return -1; } static int findPenetr(const void *obj1, const void *obj2, const ccd_t *ccd, ccd_simplex_t *portal, ccd_real_t *depth, ccd_vec3_t *pdir, ccd_vec3_t *pos) { ccd_vec3_t dir; ccd_support_t v4; unsigned long iterations; iterations = 0UL; while (1){ // compute portal direction and obtain next support point if (portalDir(portal, &dir) != 0) { return -1; } __ccdSupport(obj1, obj2, &dir, ccd, &v4); // reached tolerance -> find penetration info if (portalReachTolerance(portal, &v4, &dir, ccd) || iterations > ccd->max_iterations){ *depth = ccdVec3PointTriDist2(ccd_vec3_origin, &ccdSimplexPoint(portal, 1)->v, &ccdSimplexPoint(portal, 2)->v, &ccdSimplexPoint(portal, 3)->v, pdir); *depth = CCD_SQRT(*depth); if (ccdVec3SafeNormalize(pdir) != 0) { return -1; } // barycentric coordinates: if (findPos(obj1, obj2, ccd, portal, pos) != 0) { return -1; } return 0; } expandPortal(portal, &v4); iterations++; } } static void findPenetrTouch(const void *obj1, const void *obj2, const ccd_t *ccd, ccd_simplex_t *portal, ccd_real_t *depth, ccd_vec3_t *dir, ccd_vec3_t *pos) { // Touching contact on portal's v1 - so depth is zero and direction // is unimportant and pos can be guessed *depth = CCD_REAL(0.); ccdVec3Copy(dir, ccd_vec3_origin); ccdVec3Copy(pos, &ccdSimplexPoint(portal, 1)->v1); ccdVec3Add(pos, &ccdSimplexPoint(portal, 1)->v2); ccdVec3Scale(pos, 0.5); } static int findPenetrSegment(const void *obj1, const void *obj2, const ccd_t *ccd, ccd_simplex_t *portal, ccd_real_t *depth, ccd_vec3_t *dir, ccd_vec3_t *pos) { /* ccd_vec3_t vec; ccd_real_t k; */ // Origin lies on v0-v1 segment. // Depth is distance to v1, direction also and position must be // computed ccdVec3Copy(pos, &ccdSimplexPoint(portal, 1)->v1); ccdVec3Add(pos, &ccdSimplexPoint(portal, 1)->v2); ccdVec3Scale(pos, CCD_REAL(0.5)); /* ccdVec3Sub2(&vec, &ccdSimplexPoint(portal, 1)->v, &ccdSimplexPoint(portal, 0)->v); k = CCD_SQRT(ccdVec3Len2(&ccdSimplexPoint(portal, 0)->v)); k /= CCD_SQRT(ccdVec3Len2(&vec)); ccdVec3Scale(&vec, -k); ccdVec3Add(pos, &vec); */ ccdVec3Copy(dir, &ccdSimplexPoint(portal, 1)->v); *depth = CCD_SQRT(ccdVec3Len2(dir)); if (ccdVec3SafeNormalize(dir) != 0) { return -1; } return 0; } static int findPos(const void *obj1, const void *obj2, const ccd_t *ccd, const ccd_simplex_t *portal, ccd_vec3_t *pos) { ccd_vec3_t dir; size_t i; ccd_real_t b[4], sum, inv; ccd_vec3_t vec, p1, p2; if (portalDir(portal, &dir) != 0) { return -1; } // use barycentric coordinates of tetrahedron to find origin ccdVec3Cross(&vec, &ccdSimplexPoint(portal, 1)->v, &ccdSimplexPoint(portal, 2)->v); b[0] = ccdVec3Dot(&vec, &ccdSimplexPoint(portal, 3)->v); ccdVec3Cross(&vec, &ccdSimplexPoint(portal, 3)->v, &ccdSimplexPoint(portal, 2)->v); b[1] = ccdVec3Dot(&vec, &ccdSimplexPoint(portal, 0)->v); ccdVec3Cross(&vec, &ccdSimplexPoint(portal, 0)->v, &ccdSimplexPoint(portal, 1)->v); b[2] = ccdVec3Dot(&vec, &ccdSimplexPoint(portal, 3)->v); ccdVec3Cross(&vec, &ccdSimplexPoint(portal, 2)->v, &ccdSimplexPoint(portal, 1)->v); b[3] = ccdVec3Dot(&vec, &ccdSimplexPoint(portal, 0)->v); sum = b[0] + b[1] + b[2] + b[3]; if (ccdIsZero(sum) || sum < CCD_ZERO){ b[0] = CCD_REAL(0.); ccdVec3Cross(&vec, &ccdSimplexPoint(portal, 2)->v, &ccdSimplexPoint(portal, 3)->v); b[1] = ccdVec3Dot(&vec, &dir); ccdVec3Cross(&vec, &ccdSimplexPoint(portal, 3)->v, &ccdSimplexPoint(portal, 1)->v); b[2] = ccdVec3Dot(&vec, &dir); ccdVec3Cross(&vec, &ccdSimplexPoint(portal, 1)->v, &ccdSimplexPoint(portal, 2)->v); b[3] = ccdVec3Dot(&vec, &dir); sum = b[1] + b[2] + b[3]; } inv = CCD_REAL(1.) / sum; ccdVec3Copy(&p1, ccd_vec3_origin); ccdVec3Copy(&p2, ccd_vec3_origin); for (i = 0; i < 4; i++){ ccdVec3Copy(&vec, &ccdSimplexPoint(portal, i)->v1); ccdVec3Scale(&vec, b[i]); ccdVec3Add(&p1, &vec); ccdVec3Copy(&vec, &ccdSimplexPoint(portal, i)->v2); ccdVec3Scale(&vec, b[i]); ccdVec3Add(&p2, &vec); } ccdVec3Scale(&p1, inv); ccdVec3Scale(&p2, inv); ccdVec3Copy(pos, &p1); ccdVec3Add(pos, &p2); ccdVec3Scale(pos, 0.5); return 0; } _ccd_inline void expandPortal(ccd_simplex_t *portal, const ccd_support_t *v4) { ccd_real_t dot; ccd_vec3_t v4v0; ccdVec3Cross(&v4v0, &v4->v, &ccdSimplexPoint(portal, 0)->v); dot = ccdVec3Dot(&ccdSimplexPoint(portal, 1)->v, &v4v0); if (dot > CCD_ZERO){ dot = ccdVec3Dot(&ccdSimplexPoint(portal, 2)->v, &v4v0); if (dot > CCD_ZERO){ ccdSimplexSet(portal, 1, v4); }else{ ccdSimplexSet(portal, 3, v4); } }else{ dot = ccdVec3Dot(&ccdSimplexPoint(portal, 3)->v, &v4v0); if (dot > CCD_ZERO){ ccdSimplexSet(portal, 2, v4); }else{ ccdSimplexSet(portal, 1, v4); } } } _ccd_inline int portalDir(const ccd_simplex_t *portal, ccd_vec3_t *dir) { ccd_vec3_t v2v1, v3v1; ccdVec3Sub2(&v2v1, &ccdSimplexPoint(portal, 2)->v, &ccdSimplexPoint(portal, 1)->v); ccdVec3Sub2(&v3v1, &ccdSimplexPoint(portal, 3)->v, &ccdSimplexPoint(portal, 1)->v); ccdVec3Cross(dir, &v2v1, &v3v1); if (ccdVec3SafeNormalize(dir) != 0) { return -1; } return 0; } _ccd_inline int portalEncapsulesOrigin(const ccd_simplex_t *portal, const ccd_vec3_t *dir) { ccd_real_t dot; dot = ccdVec3Dot(dir, &ccdSimplexPoint(portal, 1)->v); return ccdIsZero(dot) || dot > CCD_ZERO; } _ccd_inline int portalReachTolerance(const ccd_simplex_t *portal, const ccd_support_t *v4, const ccd_vec3_t *dir, const ccd_t *ccd) { ccd_real_t dv1, dv2, dv3, dv4; ccd_real_t dot1, dot2, dot3; // find the smallest dot product of dir and {v1-v4, v2-v4, v3-v4} dv1 = ccdVec3Dot(&ccdSimplexPoint(portal, 1)->v, dir); dv2 = ccdVec3Dot(&ccdSimplexPoint(portal, 2)->v, dir); dv3 = ccdVec3Dot(&ccdSimplexPoint(portal, 3)->v, dir); dv4 = ccdVec3Dot(&v4->v, dir); dot1 = dv4 - dv1; dot2 = dv4 - dv2; dot3 = dv4 - dv3; dot1 = CCD_FMIN(dot1, dot2); dot1 = CCD_FMIN(dot1, dot3); return ccdEq(dot1, ccd->mpr_tolerance) || dot1 < ccd->mpr_tolerance; } _ccd_inline int portalCanEncapsuleOrigin(const ccd_simplex_t *portal, const ccd_support_t *v4, const ccd_vec3_t *dir) { ccd_real_t dot; dot = ccdVec3Dot(&v4->v, dir); return ccdIsZero(dot) || dot > CCD_ZERO; } ode-0.16/libccd/BSD-LICENSE0000664000175200017520000000402113403272463011772 00000000000000libccd ------- Copyright (c)2010 Daniel Fiser , Intelligent and Mobile Robotics Group, Department of Cybernetics, Faculty of Electrical Engineering, Czech Technical University in Prague. All rights reserved. This work was supported by SYMBRION and REPLICATOR projects. The SYMBRION project is funded by European Commission within the work "Future and Emergent Technologies Proactive" under grant agreement no. 216342. The REPLICATOR project is funded within the work programme "Cognitive Systems, Interaction, Robotics" under grant agreement no. 216240. http://www.symbrion.eu/ http://www.replicators.eu/ Redistribution and use 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 University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 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 HOLDER 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. ode-0.16/libccd/aclocal.m40000664000175200017520000133044513403272665012240 00000000000000# generated automatically by aclocal 1.15 -*- Autoconf -*- # Copyright (C) 1996-2014 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, [m4_warning([this file was generated for autoconf 2.69. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) # libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # # Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. m4_define([_LT_COPYING], [dnl # Copyright (C) 2014 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program or library that is built # using GNU Libtool, you may include this file under the same # distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ]) # serial 58 LT_INIT # LT_PREREQ(VERSION) # ------------------ # Complain and exit if this libtool version is less that VERSION. m4_defun([LT_PREREQ], [m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, [m4_default([$3], [m4_fatal([Libtool version $1 or higher is required], 63)])], [$2])]) # _LT_CHECK_BUILDDIR # ------------------ # Complain if the absolute build directory name contains unusual characters m4_defun([_LT_CHECK_BUILDDIR], [case `pwd` in *\ * | *\ *) AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; esac ]) # LT_INIT([OPTIONS]) # ------------------ AC_DEFUN([LT_INIT], [AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl AC_BEFORE([$0], [LT_LANG])dnl AC_BEFORE([$0], [LT_OUTPUT])dnl AC_BEFORE([$0], [LTDL_INIT])dnl m4_require([_LT_CHECK_BUILDDIR])dnl dnl Autoconf doesn't catch unexpanded LT_ macros by default: m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 dnl unless we require an AC_DEFUNed macro: AC_REQUIRE([LTOPTIONS_VERSION])dnl AC_REQUIRE([LTSUGAR_VERSION])dnl AC_REQUIRE([LTVERSION_VERSION])dnl AC_REQUIRE([LTOBSOLETE_VERSION])dnl m4_require([_LT_PROG_LTMAIN])dnl _LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) dnl Parse OPTIONS _LT_SET_OPTIONS([$0], [$1]) # This can be used to rebuild libtool when needed LIBTOOL_DEPS=$ltmain # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' AC_SUBST(LIBTOOL)dnl _LT_SETUP # Only expand once: m4_define([LT_INIT]) ])# LT_INIT # Old names: AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PROG_LIBTOOL], []) dnl AC_DEFUN([AM_PROG_LIBTOOL], []) # _LT_PREPARE_CC_BASENAME # ----------------------- m4_defun([_LT_PREPARE_CC_BASENAME], [ # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in @S|@*""; do case $cc_temp in compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } ])# _LT_PREPARE_CC_BASENAME # _LT_CC_BASENAME(CC) # ------------------- # It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME, # but that macro is also expanded into generated libtool script, which # arranges for $SED and $ECHO to be set by different means. m4_defun([_LT_CC_BASENAME], [m4_require([_LT_PREPARE_CC_BASENAME])dnl AC_REQUIRE([_LT_DECL_SED])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl func_cc_basename $1 cc_basename=$func_cc_basename_result ]) # _LT_FILEUTILS_DEFAULTS # ---------------------- # It is okay to use these file commands and assume they have been set # sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'. m4_defun([_LT_FILEUTILS_DEFAULTS], [: ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} ])# _LT_FILEUTILS_DEFAULTS # _LT_SETUP # --------- m4_defun([_LT_SETUP], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl _LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl dnl _LT_DECL([], [host_alias], [0], [The host system])dnl _LT_DECL([], [host], [0])dnl _LT_DECL([], [host_os], [0])dnl dnl _LT_DECL([], [build_alias], [0], [The build system])dnl _LT_DECL([], [build], [0])dnl _LT_DECL([], [build_os], [0])dnl dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl dnl AC_REQUIRE([AC_PROG_LN_S])dnl test -z "$LN_S" && LN_S="ln -s" _LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl dnl AC_REQUIRE([LT_CMD_MAX_LEN])dnl _LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl _LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl m4_require([_LT_CMD_RELOAD])dnl m4_require([_LT_CHECK_MAGIC_METHOD])dnl m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl m4_require([_LT_CMD_OLD_ARCHIVE])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_WITH_SYSROOT])dnl m4_require([_LT_CMD_TRUNCATE])dnl _LT_CONFIG_LIBTOOL_INIT([ # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi ]) if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi _LT_CHECK_OBJDIR m4_require([_LT_TAG_COMPILER])dnl case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a '.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld=$lt_cv_prog_gnu_ld old_CC=$CC old_CFLAGS=$CFLAGS # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o _LT_CC_BASENAME([$compiler]) # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then _LT_PATH_MAGIC fi ;; esac # Use C for the default configuration in the libtool script LT_SUPPORTED_TAG([CC]) _LT_LANG_C_CONFIG _LT_LANG_DEFAULT_CONFIG _LT_CONFIG_COMMANDS ])# _LT_SETUP # _LT_PREPARE_SED_QUOTE_VARS # -------------------------- # Define a few sed substitution that help us do robust quoting. m4_defun([_LT_PREPARE_SED_QUOTE_VARS], [# Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([["`\\]]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ]) # _LT_PROG_LTMAIN # --------------- # Note that this code is called both from 'configure', and 'config.status' # now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, # 'config.status' has no value for ac_aux_dir unless we are using Automake, # so we pass a copy along to make sure it has a sensible value anyway. m4_defun([_LT_PROG_LTMAIN], [m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl _LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) ltmain=$ac_aux_dir/ltmain.sh ])# _LT_PROG_LTMAIN # So that we can recreate a full libtool script including additional # tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS # in macros and then make a single call at the end using the 'libtool' # label. # _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) # ---------------------------------------- # Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL_INIT], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_INIT], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_INIT]) # _LT_CONFIG_LIBTOOL([COMMANDS]) # ------------------------------ # Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) # _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) # ----------------------------------------------------- m4_defun([_LT_CONFIG_SAVE_COMMANDS], [_LT_CONFIG_LIBTOOL([$1]) _LT_CONFIG_LIBTOOL_INIT([$2]) ]) # _LT_FORMAT_COMMENT([COMMENT]) # ----------------------------- # Add leading comment marks to the start of each line, and a trailing # full-stop to the whole comment if one is not present already. m4_define([_LT_FORMAT_COMMENT], [m4_ifval([$1], [ m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) )]) # _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) # ------------------------------------------------------------------- # CONFIGNAME is the name given to the value in the libtool script. # VARNAME is the (base) name used in the configure script. # VALUE may be 0, 1 or 2 for a computed quote escaped value based on # VARNAME. Any other value will be used directly. m4_define([_LT_DECL], [lt_if_append_uniq([lt_decl_varnames], [$2], [, ], [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], [m4_ifval([$1], [$1], [$2])]) lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) m4_ifval([$4], [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) lt_dict_add_subkey([lt_decl_dict], [$2], [tagged?], [m4_ifval([$5], [yes], [no])])]) ]) # _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) # -------------------------------------------------------- m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) # lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_tag_varnames], [_lt_decl_filter([tagged?], [yes], $@)]) # _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) # --------------------------------------------------------- m4_define([_lt_decl_filter], [m4_case([$#], [0], [m4_fatal([$0: too few arguments: $#])], [1], [m4_fatal([$0: too few arguments: $#: $1])], [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], [lt_dict_filter([lt_decl_dict], $@)])[]dnl ]) # lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) # -------------------------------------------------- m4_define([lt_decl_quote_varnames], [_lt_decl_filter([value], [1], $@)]) # lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_dquote_varnames], [_lt_decl_filter([value], [2], $@)]) # lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_varnames_tagged], [m4_assert([$# <= 2])dnl _$0(m4_quote(m4_default([$1], [[, ]])), m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) m4_define([_lt_decl_varnames_tagged], [m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) # lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_all_varnames], [_$0(m4_quote(m4_default([$1], [[, ]])), m4_if([$2], [], m4_quote(lt_decl_varnames), m4_quote(m4_shift($@))))[]dnl ]) m4_define([_lt_decl_all_varnames], [lt_join($@, lt_decl_varnames_tagged([$1], lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl ]) # _LT_CONFIG_STATUS_DECLARE([VARNAME]) # ------------------------------------ # Quote a variable value, and forward it to 'config.status' so that its # declaration there will have the same value as in 'configure'. VARNAME # must have a single quote delimited value for this to work. m4_define([_LT_CONFIG_STATUS_DECLARE], [$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) # _LT_CONFIG_STATUS_DECLARATIONS # ------------------------------ # We delimit libtool config variables with single quotes, so when # we write them to config.status, we have to be sure to quote all # embedded single quotes properly. In configure, this macro expands # each variable declared with _LT_DECL (and _LT_TAGDECL) into: # # ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], [m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAGS # ---------------- # Output comment and list of tags supported by the script m4_defun([_LT_LIBTOOL_TAGS], [_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl available_tags='_LT_TAGS'dnl ]) # _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) # ----------------------------------- # Extract the dictionary values for VARNAME (optionally with TAG) and # expand to a commented shell variable setting: # # # Some comment about what VAR is for. # visible_name=$lt_internal_name m4_define([_LT_LIBTOOL_DECLARE], [_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [description])))[]dnl m4_pushdef([_libtool_name], m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), [0], [_libtool_name=[$]$1], [1], [_libtool_name=$lt_[]$1], [2], [_libtool_name=$lt_[]$1], [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl ]) # _LT_LIBTOOL_CONFIG_VARS # ----------------------- # Produce commented declarations of non-tagged libtool config variables # suitable for insertion in the LIBTOOL CONFIG section of the 'libtool' # script. Tagged libtool config variables (even for the LIBTOOL CONFIG # section) are produced by _LT_LIBTOOL_TAG_VARS. m4_defun([_LT_LIBTOOL_CONFIG_VARS], [m4_foreach([_lt_var], m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAG_VARS(TAG) # ------------------------- m4_define([_LT_LIBTOOL_TAG_VARS], [m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) # _LT_TAGVAR(VARNAME, [TAGNAME]) # ------------------------------ m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) # _LT_CONFIG_COMMANDS # ------------------- # Send accumulated output to $CONFIG_STATUS. Thanks to the lists of # variables for single and double quote escaping we saved from calls # to _LT_DECL, we can put quote escaped variables declarations # into 'config.status', and then the shell code to quote escape them in # for loops in 'config.status'. Finally, any additional code accumulated # from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. m4_defun([_LT_CONFIG_COMMANDS], [AC_PROVIDE_IFELSE([LT_OUTPUT], dnl If the libtool generation code has been placed in $CONFIG_LT, dnl instead of duplicating it all over again into config.status, dnl then we will have config.status run $CONFIG_LT later, so it dnl needs to know what name is stored there: [AC_CONFIG_COMMANDS([libtool], [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], dnl If the libtool generation code is destined for config.status, dnl expand the accumulated commands and init code now: [AC_CONFIG_COMMANDS([libtool], [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) ])#_LT_CONFIG_COMMANDS # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], [ # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' _LT_CONFIG_STATUS_DECLARATIONS LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$[]1 _LTECHO_EOF' } # Quote evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_quote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_dquote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done _LT_OUTPUT_LIBTOOL_INIT ]) # _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) # ------------------------------------ # Generate a child script FILE with all initialization necessary to # reuse the environment learned by the parent script, and make the # file executable. If COMMENT is supplied, it is inserted after the # '#!' sequence but before initialization text begins. After this # macro, additional text can be appended to FILE to form the body of # the child script. The macro ends with non-zero status if the # file could not be fully written (such as if the disk is full). m4_ifdef([AS_INIT_GENERATED], [m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], [m4_defun([_LT_GENERATED_FILE_INIT], [m4_require([AS_PREPARE])]dnl [m4_pushdef([AS_MESSAGE_LOG_FD])]dnl [lt_write_fail=0 cat >$1 <<_ASEOF || lt_write_fail=1 #! $SHELL # Generated by $as_me. $2 SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$1 <<\_ASEOF || lt_write_fail=1 AS_SHELL_SANITIZE _AS_PREPARE exec AS_MESSAGE_FD>&1 _ASEOF test 0 = "$lt_write_fail" && chmod +x $1[]dnl m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT # LT_OUTPUT # --------- # This macro allows early generation of the libtool script (before # AC_OUTPUT is called), incase it is used in configure for compilation # tests. AC_DEFUN([LT_OUTPUT], [: ${CONFIG_LT=./config.lt} AC_MSG_NOTICE([creating $CONFIG_LT]) _LT_GENERATED_FILE_INIT(["$CONFIG_LT"], [# Run this file to recreate a libtool stub with the current configuration.]) cat >>"$CONFIG_LT" <<\_LTEOF lt_cl_silent=false exec AS_MESSAGE_LOG_FD>>config.log { echo AS_BOX([Running $as_me.]) } >&AS_MESSAGE_LOG_FD lt_cl_help="\ '$as_me' creates a local libtool stub from the current configuration, for use in further configure time tests before the real libtool is generated. Usage: $[0] [[OPTIONS]] -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files Report bugs to ." lt_cl_version="\ m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) configured by $[0], generated by m4_PACKAGE_STRING. Copyright (C) 2011 Free Software Foundation, Inc. This config.lt script is free software; the Free Software Foundation gives unlimited permision to copy, distribute and modify it." while test 0 != $[#] do case $[1] in --version | --v* | -V ) echo "$lt_cl_version"; exit 0 ;; --help | --h* | -h ) echo "$lt_cl_help"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --quiet | --q* | --silent | --s* | -q ) lt_cl_silent=: ;; -*) AC_MSG_ERROR([unrecognized option: $[1] Try '$[0] --help' for more information.]) ;; *) AC_MSG_ERROR([unrecognized argument: $[1] Try '$[0] --help' for more information.]) ;; esac shift done if $lt_cl_silent; then exec AS_MESSAGE_FD>/dev/null fi _LTEOF cat >>"$CONFIG_LT" <<_LTEOF _LT_OUTPUT_LIBTOOL_COMMANDS_INIT _LTEOF cat >>"$CONFIG_LT" <<\_LTEOF AC_MSG_NOTICE([creating $ofile]) _LT_OUTPUT_LIBTOOL_COMMANDS AS_EXIT(0) _LTEOF chmod +x "$CONFIG_LT" # configure is writing to config.log, but config.lt does its own redirection, # appending to config.log, which fails on DOS, as config.log is still kept # open by configure. Here we exec the FD to /dev/null, effectively closing # config.log, so it can be properly (re)opened and appended to by config.lt. lt_cl_success=: test yes = "$silent" && lt_config_lt_args="$lt_config_lt_args --quiet" exec AS_MESSAGE_LOG_FD>/dev/null $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false exec AS_MESSAGE_LOG_FD>>config.log $lt_cl_success || AS_EXIT(1) ])# LT_OUTPUT # _LT_CONFIG(TAG) # --------------- # If TAG is the built-in tag, create an initial libtool script with a # default configuration from the untagged config vars. Otherwise add code # to config.status for appending the configuration named by TAG from the # matching tagged config vars. m4_defun([_LT_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_CONFIG_SAVE_COMMANDS([ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl m4_if(_LT_TAG, [C], [ # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi cfgfile=${ofile}T trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # Generated automatically by $as_me ($PACKAGE) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # Provide generalized library-building support services. # Written by Gordon Matzigkeit, 1996 _LT_COPYING _LT_LIBTOOL_TAGS # Configured defaults for sys_lib_dlsearch_path munging. : \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} # ### BEGIN LIBTOOL CONFIG _LT_LIBTOOL_CONFIG_VARS _LT_LIBTOOL_TAG_VARS # ### END LIBTOOL CONFIG _LT_EOF cat <<'_LT_EOF' >> "$cfgfile" # ### BEGIN FUNCTIONS SHARED WITH CONFIGURE _LT_PREPARE_MUNGE_PATH_LIST _LT_PREPARE_CC_BASENAME # ### END FUNCTIONS SHARED WITH CONFIGURE _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac _LT_PROG_LTMAIN # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ], [cat <<_LT_EOF >> "$ofile" dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded dnl in a comment (ie after a #). # ### BEGIN LIBTOOL TAG CONFIG: $1 _LT_LIBTOOL_TAG_VARS(_LT_TAG) # ### END LIBTOOL TAG CONFIG: $1 _LT_EOF ])dnl /m4_if ], [m4_if([$1], [], [ PACKAGE='$PACKAGE' VERSION='$VERSION' RM='$RM' ofile='$ofile'], []) ])dnl /_LT_CONFIG_SAVE_COMMANDS ])# _LT_CONFIG # LT_SUPPORTED_TAG(TAG) # --------------------- # Trace this macro to discover what tags are supported by the libtool # --tag option, using: # autoconf --trace 'LT_SUPPORTED_TAG:$1' AC_DEFUN([LT_SUPPORTED_TAG], []) # C support is built-in for now m4_define([_LT_LANG_C_enabled], []) m4_define([_LT_TAGS], []) # LT_LANG(LANG) # ------------- # Enable libtool support for the given language if not already enabled. AC_DEFUN([LT_LANG], [AC_BEFORE([$0], [LT_OUTPUT])dnl m4_case([$1], [C], [_LT_LANG(C)], [C++], [_LT_LANG(CXX)], [Go], [_LT_LANG(GO)], [Java], [_LT_LANG(GCJ)], [Fortran 77], [_LT_LANG(F77)], [Fortran], [_LT_LANG(FC)], [Windows Resource], [_LT_LANG(RC)], [m4_ifdef([_LT_LANG_]$1[_CONFIG], [_LT_LANG($1)], [m4_fatal([$0: unsupported language: "$1"])])])dnl ])# LT_LANG # _LT_LANG(LANGNAME) # ------------------ m4_defun([_LT_LANG], [m4_ifdef([_LT_LANG_]$1[_enabled], [], [LT_SUPPORTED_TAG([$1])dnl m4_append([_LT_TAGS], [$1 ])dnl m4_define([_LT_LANG_]$1[_enabled], [])dnl _LT_LANG_$1_CONFIG($1)])dnl ])# _LT_LANG m4_ifndef([AC_PROG_GO], [ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_GO. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # m4_defun([AC_PROG_GO], [AC_LANG_PUSH(Go)dnl AC_ARG_VAR([GOC], [Go compiler command])dnl AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl _AC_ARG_VAR_LDFLAGS()dnl AC_CHECK_TOOL(GOC, gccgo) if test -z "$GOC"; then if test -n "$ac_tool_prefix"; then AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) fi fi if test -z "$GOC"; then AC_CHECK_PROG(GOC, gccgo, gccgo, false) fi ])#m4_defun ])#m4_ifndef # _LT_LANG_DEFAULT_CONFIG # ----------------------- m4_defun([_LT_LANG_DEFAULT_CONFIG], [AC_PROVIDE_IFELSE([AC_PROG_CXX], [LT_LANG(CXX)], [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) AC_PROVIDE_IFELSE([AC_PROG_F77], [LT_LANG(F77)], [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) AC_PROVIDE_IFELSE([AC_PROG_FC], [LT_LANG(FC)], [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal dnl pulling things in needlessly. AC_PROVIDE_IFELSE([AC_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([LT_PROG_GCJ], [LT_LANG(GCJ)], [m4_ifdef([AC_PROG_GCJ], [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([A][M_PROG_GCJ], [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([LT_PROG_GCJ], [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) AC_PROVIDE_IFELSE([AC_PROG_GO], [LT_LANG(GO)], [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) AC_PROVIDE_IFELSE([LT_PROG_RC], [LT_LANG(RC)], [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) ])# _LT_LANG_DEFAULT_CONFIG # Obsolete macros: AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_CXX], []) dnl AC_DEFUN([AC_LIBTOOL_F77], []) dnl AC_DEFUN([AC_LIBTOOL_FC], []) dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) dnl AC_DEFUN([AC_LIBTOOL_RC], []) # _LT_TAG_COMPILER # ---------------- m4_defun([_LT_TAG_COMPILER], [AC_REQUIRE([AC_PROG_CC])dnl _LT_DECL([LTCC], [CC], [1], [A C compiler])dnl _LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl _LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl _LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC ])# _LT_TAG_COMPILER # _LT_COMPILER_BOILERPLATE # ------------------------ # Check for compiler boilerplate output or warnings with # the simple compiler test code. m4_defun([_LT_COMPILER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ])# _LT_COMPILER_BOILERPLATE # _LT_LINKER_BOILERPLATE # ---------------------- # Check for linker boilerplate output or warnings with # the simple link test code. m4_defun([_LT_LINKER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ])# _LT_LINKER_BOILERPLATE # _LT_REQUIRED_DARWIN_CHECKS # ------------------------- m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ case $host_os in rhapsody* | darwin*) AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) AC_CHECK_TOOL([LIPO], [lipo], [:]) AC_CHECK_TOOL([OTOOL], [otool], [:]) AC_CHECK_TOOL([OTOOL64], [otool64], [:]) _LT_DECL([], [DSYMUTIL], [1], [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) _LT_DECL([], [NMEDIT], [1], [Tool to change global to local symbols on Mac OS X]) _LT_DECL([], [LIPO], [1], [Tool to manipulate fat objects and archives on Mac OS X]) _LT_DECL([], [OTOOL], [1], [ldd/readelf like tool for Mach-O binaries on Mac OS X]) _LT_DECL([], [OTOOL64], [1], [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], [lt_cv_apple_cc_single_mod=no if test -z "$LT_MULTI_MODULE"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test 0 = "$_lt_result"; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -rf libconftest.dylib* rm -f conftest.* fi]) AC_CACHE_CHECK([for -exported_symbols_list linker flag], [lt_cv_ld_exported_symbols_list], [lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [lt_cv_ld_exported_symbols_list=yes], [lt_cv_ld_exported_symbols_list=no]) LDFLAGS=$save_LDFLAGS ]) AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], [lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then lt_cv_ld_force_load=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM ]) case $host_os in rhapsody* | darwin1.[[012]]) _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; 10.[[012]][[,.]]*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test yes = "$lt_cv_apple_cc_single_mod"; then _lt_dar_single_mod='$single_module' fi if test yes = "$lt_cv_ld_exported_symbols_list"; then _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' fi if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ]) # _LT_DARWIN_LINKER_FEATURES([TAG]) # --------------------------------- # Checks for linker and compiler features on darwin m4_defun([_LT_DARWIN_LINKER_FEATURES], [ m4_require([_LT_REQUIRED_DARWIN_CHECKS]) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported if test yes = "$lt_cv_ld_force_load"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) else _LT_TAGVAR(whole_archive_flag_spec, $1)='' fi _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined case $cc_basename in ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" m4_if([$1], [CXX], [ if test yes != "$lt_cv_apple_cc_single_mod"; then _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" fi ],[]) else _LT_TAGVAR(ld_shlibs, $1)=no fi ]) # _LT_SYS_MODULE_PATH_AIX([TAGNAME]) # ---------------------------------- # Links a minimal program and checks the executable # for the system default hardcoded library path. In most cases, # this is /usr/lib:/lib, but when the MPI compilers are used # the location of the communication and MPI libs are included too. # If we don't find anything, use the default library path according # to the aix ld manual. # Store the results from the different compilers for each TAGNAME. # Allow to override them for all tags through lt_cv_aix_libpath. m4_defun([_LT_SYS_MODULE_PATH_AIX], [m4_require([_LT_DECL_SED])dnl if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ lt_aix_libpath_sed='[ /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }]' _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi],[]) if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib fi ]) aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) fi ])# _LT_SYS_MODULE_PATH_AIX # _LT_SHELL_INIT(ARG) # ------------------- m4_define([_LT_SHELL_INIT], [m4_divert_text([M4SH-INIT], [$1 ])])# _LT_SHELL_INIT # _LT_PROG_ECHO_BACKSLASH # ----------------------- # Find how we can fake an echo command that does not interpret backslash. # In particular, with Autoconf 2.60 or later we add some code to the start # of the generated configure script that will find a shell with a builtin # printf (that we can use as an echo command). m4_defun([_LT_PROG_ECHO_BACKSLASH], [ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO AC_MSG_CHECKING([how to print strings]) # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $[]1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } case $ECHO in printf*) AC_MSG_RESULT([printf]) ;; print*) AC_MSG_RESULT([print -r]) ;; *) AC_MSG_RESULT([cat]) ;; esac m4_ifdef([_AS_DETECT_SUGGESTED], [_AS_DETECT_SUGGESTED([ test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test "X`printf %s $ECHO`" = "X$ECHO" \ || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) _LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) _LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) ])# _LT_PROG_ECHO_BACKSLASH # _LT_WITH_SYSROOT # ---------------- AC_DEFUN([_LT_WITH_SYSROOT], [AC_MSG_CHECKING([for sysroot]) AC_ARG_WITH([sysroot], [AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@], [Search for dependent libraries within DIR (or the compiler's sysroot if not specified).])], [], [with_sysroot=no]) dnl lt_sysroot will always be passed unquoted. We quote it here dnl in case the user passed a directory name. lt_sysroot= case $with_sysroot in #( yes) if test yes = "$GCC"; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) AC_MSG_RESULT([$with_sysroot]) AC_MSG_ERROR([The sysroot must be an absolute path.]) ;; esac AC_MSG_RESULT([${lt_sysroot:-no}]) _LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl [dependent libraries, and where our libraries should be installed.])]) # _LT_ENABLE_LOCK # --------------- m4_defun([_LT_ENABLE_LOCK], [AC_ARG_ENABLE([libtool-lock], [AS_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) test no = "$enable_libtool_lock" || enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out what ABI is being produced by ac_compile, and set mode # options accordingly. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE=32 ;; *ELF-64*) HPUX_IA64_MODE=64 ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then if test yes = "$lt_cv_prog_gnu_ld"; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; mips64*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then emul=elf case `/usr/bin/file conftest.$ac_objext` in *32-bit*) emul="${emul}32" ;; *64-bit*) emul="${emul}64" ;; esac case `/usr/bin/file conftest.$ac_objext` in *MSB*) emul="${emul}btsmip" ;; *LSB*) emul="${emul}ltsmip" ;; esac case `/usr/bin/file conftest.$ac_objext` in *N32*) emul="${emul}n32" ;; esac LD="${LD-ld} -m $emul" fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. Note that the listed cases only cover the # situations where additional linker options are needed (such as when # doing 32-bit compilation for a host where ld defaults to 64-bit, or # vice versa); the common cases where no linker options are needed do # not appear in the list. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `/usr/bin/file conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*linux*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*linux*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_PUSH(C) AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) if test yes != "$lt_cv_cc_needs_belf"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS=$SAVE_CFLAGS fi ;; *-*solaris*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*|x86_64-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD=${LD-ld}_sol2 fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks=$enable_libtool_lock ])# _LT_ENABLE_LOCK # _LT_PROG_AR # ----------- m4_defun([_LT_PROG_AR], [AC_CHECK_TOOLS(AR, [ar], false) : ${AR=ar} : ${AR_FLAGS=cru} _LT_DECL([], [AR], [1], [The archiver]) _LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], [lt_cv_ar_at_file=no AC_COMPILE_IFELSE([AC_LANG_PROGRAM], [echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([lt_ar_try]) if test 0 -eq "$ac_status"; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a AC_TRY_EVAL([lt_ar_try]) if test 0 -ne "$ac_status"; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a ]) ]) if test no = "$lt_cv_ar_at_file"; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi _LT_DECL([], [archiver_list_spec], [1], [How to feed a file listing to the archiver]) ])# _LT_PROG_AR # _LT_CMD_OLD_ARCHIVE # ------------------- m4_defun([_LT_CMD_OLD_ARCHIVE], [_LT_PROG_AR AC_CHECK_TOOL(STRIP, strip, :) test -z "$STRIP" && STRIP=: _LT_DECL([], [STRIP], [1], [A symbol stripping program]) AC_CHECK_TOOL(RANLIB, ranlib, :) test -z "$RANLIB" && RANLIB=: _LT_DECL([], [RANLIB], [1], [Commands used to install an old-style archive]) # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in bitrig* | openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac _LT_DECL([], [old_postinstall_cmds], [2]) _LT_DECL([], [old_postuninstall_cmds], [2]) _LT_TAGDECL([], [old_archive_cmds], [2], [Commands used to build an old-style archive]) _LT_DECL([], [lock_old_archive_extraction], [0], [Whether to use a lock for old archive extraction]) ])# _LT_CMD_OLD_ARCHIVE # _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------------------- # Check whether the given compiler option works AC_DEFUN([_LT_COMPILER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi fi $RM conftest* ]) if test yes = "[$]$2"; then m4_if([$5], , :, [$5]) else m4_if([$6], , :, [$6]) fi ])# _LT_COMPILER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) # _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------- # Check whether the given linker option works AC_DEFUN([_LT_LINKER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $3" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&AS_MESSAGE_LOG_FD $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi else $2=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS ]) if test yes = "[$]$2"; then m4_if([$4], , :, [$4]) else m4_if([$5], , :, [$5]) fi ])# _LT_LINKER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) # LT_CMD_MAX_LEN #--------------- AC_DEFUN([LT_CMD_MAX_LEN], [AC_REQUIRE([AC_CANONICAL_HOST])dnl # find the maximum length of command line arguments AC_MSG_CHECKING([the maximum length of command line arguments]) AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl i=0 teststring=ABCD case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test X`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test 17 != "$i" # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac ]) if test -n "$lt_cv_sys_max_cmd_len"; then AC_MSG_RESULT($lt_cv_sys_max_cmd_len) else AC_MSG_RESULT(none) fi max_cmd_len=$lt_cv_sys_max_cmd_len _LT_DECL([], [max_cmd_len], [0], [What is the maximum length of a command?]) ])# LT_CMD_MAX_LEN # Old name: AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) # _LT_HEADER_DLFCN # ---------------- m4_defun([_LT_HEADER_DLFCN], [AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl ])# _LT_HEADER_DLFCN # _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, # ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) # ---------------------------------------------------------------- m4_defun([_LT_TRY_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test yes = "$cross_compiling"; then : [$4] else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF [#line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; }] _LT_EOF if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) $1 ;; x$lt_dlneed_uscore) $2 ;; x$lt_dlunknown|x*) $3 ;; esac else : # compilation failed $3 fi fi rm -fr conftest* ])# _LT_TRY_DLOPEN_SELF # LT_SYS_DLOPEN_SELF # ------------------ AC_DEFUN([LT_SYS_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test yes != "$enable_dlopen"; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen=load_add_on lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen=LoadLibrary lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen=dlopen lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[ lt_cv_dlopen=dyld lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ]) ;; tpf*) # Don't try to run any link tests for TPF. We know it's impossible # because TPF is a cross-compiler, and we know how we open DSOs. lt_cv_dlopen=dlopen lt_cv_dlopen_libs= lt_cv_dlopen_self=no ;; *) AC_CHECK_FUNC([shl_load], [lt_cv_dlopen=shl_load], [AC_CHECK_LIB([dld], [shl_load], [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld], [AC_CHECK_FUNC([dlopen], [lt_cv_dlopen=dlopen], [AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl], [AC_CHECK_LIB([svld], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld], [AC_CHECK_LIB([dld], [dld_link], [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld]) ]) ]) ]) ]) ]) ;; esac if test no = "$lt_cv_dlopen"; then enable_dlopen=no else enable_dlopen=yes fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS=$CPPFLAGS test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS=$LDFLAGS wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS=$LIBS LIBS="$lt_cv_dlopen_libs $LIBS" AC_CACHE_CHECK([whether a program can dlopen itself], lt_cv_dlopen_self, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) if test yes = "$lt_cv_dlopen_self"; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) ]) fi CPPFLAGS=$save_CPPFLAGS LDFLAGS=$save_LDFLAGS LIBS=$save_LIBS ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi _LT_DECL([dlopen_support], [enable_dlopen], [0], [Whether dlopen is supported]) _LT_DECL([dlopen_self], [enable_dlopen_self], [0], [Whether dlopen of programs is supported]) _LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], [Whether dlopen of statically linked programs is supported]) ])# LT_SYS_DLOPEN_SELF # Old name: AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) # _LT_COMPILER_C_O([TAGNAME]) # --------------------------- # Check to see if options -c and -o are simultaneously supported by compiler. # This macro does not hard code the compiler like AC_PROG_CC_C_O. m4_defun([_LT_COMPILER_C_O], [m4_require([_LT_DECL_SED])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes fi fi chmod u+w . 2>&AS_MESSAGE_LOG_FD $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* ]) _LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], [Does compiler simultaneously support -c and -o options?]) ])# _LT_COMPILER_C_O # _LT_COMPILER_FILE_LOCKS([TAGNAME]) # ---------------------------------- # Check to see if we can do hard links to lock some files if needed m4_defun([_LT_COMPILER_FILE_LOCKS], [m4_require([_LT_ENABLE_LOCK])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_COMPILER_C_O([$1]) hard_links=nottested if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no AC_MSG_RESULT([$hard_links]) if test no = "$hard_links"; then AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe]) need_locks=warn fi else need_locks=no fi _LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) ])# _LT_COMPILER_FILE_LOCKS # _LT_CHECK_OBJDIR # ---------------- m4_defun([_LT_CHECK_OBJDIR], [AC_CACHE_CHECK([for objdir], [lt_cv_objdir], [rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null]) objdir=$lt_cv_objdir _LT_DECL([], [objdir], [0], [The name of the directory that contains temporary libtool files])dnl m4_pattern_allow([LT_OBJDIR])dnl AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/", [Define to the sub-directory where libtool stores uninstalled libraries.]) ])# _LT_CHECK_OBJDIR # _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) # -------------------------------------- # Check hardcoding attributes. m4_defun([_LT_LINKER_HARDCODE_LIBPATH], [AC_MSG_CHECKING([how to hardcode library paths into programs]) _LT_TAGVAR(hardcode_action, $1)= if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || test -n "$_LT_TAGVAR(runpath_var, $1)" || test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then # We can hardcode non-existent directories. if test no != "$_LT_TAGVAR(hardcode_direct, $1)" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" && test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then # Linking always hardcodes the temporary library directory. _LT_TAGVAR(hardcode_action, $1)=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. _LT_TAGVAR(hardcode_action, $1)=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. _LT_TAGVAR(hardcode_action, $1)=unsupported fi AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) if test relink = "$_LT_TAGVAR(hardcode_action, $1)" || test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then # Fast installation is not supported enable_fast_install=no elif test yes = "$shlibpath_overrides_runpath" || test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi _LT_TAGDECL([], [hardcode_action], [0], [How to hardcode a shared library path into an executable]) ])# _LT_LINKER_HARDCODE_LIBPATH # _LT_CMD_STRIPLIB # ---------------- m4_defun([_LT_CMD_STRIPLIB], [m4_require([_LT_DECL_EGREP]) striplib= old_striplib= AC_MSG_CHECKING([whether stripping libraries is possible]) if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP"; then striplib="$STRIP -x" old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ;; *) AC_MSG_RESULT([no]) ;; esac fi _LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) _LT_DECL([], [striplib], [1]) ])# _LT_CMD_STRIPLIB # _LT_PREPARE_MUNGE_PATH_LIST # --------------------------- # Make sure func_munge_path_list() is defined correctly. m4_defun([_LT_PREPARE_MUNGE_PATH_LIST], [[# func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x@S|@2 in x) ;; *:) eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\" ;; x:*) eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\" ;; *::*) eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\" ;; *) eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\" ;; esac } ]])# _LT_PREPARE_PATH_LIST # _LT_SYS_DYNAMIC_LINKER([TAG]) # ----------------------------- # PORTME Fill in your ld.so characteristics m4_defun([_LT_SYS_DYNAMIC_LINKER], [AC_REQUIRE([AC_CANONICAL_HOST])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_OBJDUMP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ if test yes = "$GCC"; then case $host_os in darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; *) lt_awk_arg='/^libraries:/' ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;; *) lt_sed_strip_eq='s|=/|/|g' ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary... lt_tmp_lt_search_path_spec= lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` # ...but if some path component already ends with the multilib dir we assume # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). case "$lt_multi_os_dir; $lt_search_path_spec " in "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) lt_multi_os_dir= ;; esac for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" elif test -n "$lt_multi_os_dir"; then test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS = " "; FS = "/|\n";} { lt_foo = ""; lt_count = 0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo = "/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[[lt_foo]]++; } if (lt_freq[[lt_foo]] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi]) library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown AC_ARG_VAR([LT_SYS_LIBRARY_PATH], [User-defined run-time library search path.]) case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='$libname$release$shared_ext$major' ;; aix[[4-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line '#! .'. This would cause the generated library to # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[[01]] | aix4.[[01]].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # Using Import Files as archive members, it is possible to support # filename-based versioning of shared library archives on AIX. While # this would work for both with and without runtime linking, it will # prevent static linking of such archives. So we do filename-based # shared library versioning with .so extension only, which is used # when both runtime linking and shared linking is enabled. # Unfortunately, runtime linking may impact performance, so we do # not want this to be the default eventually. Also, we use the # versioned .so libs for executables only if there is the -brtl # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. # To allow for filename-based versioning support, we need to create # libNAME.so.V as an archive file, containing: # *) an Import File, referring to the versioned filename of the # archive as well as the shared archive member, telling the # bitwidth (32 or 64) of that shared object, and providing the # list of exported symbols of that shared object, eventually # decorated with the 'weak' keyword # *) the shared object with the F_LOADONLY flag set, to really avoid # it being seen by the linker. # At run time we better use the real file rather than another symlink, # but for link time we create the symlink libNAME.so -> libNAME.so.V case $with_aix_soname,$aix_use_runtimelinking in # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. aix,yes) # traditional libtool dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; aix,no) # traditional AIX only dynamic_linker='AIX lib.a[(]lib.so.V[)]' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' ;; svr4,*) # full svr4 only dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,yes) # both, prefer svr4 dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # unpreferred sharedlib libNAME.a needs extra handling postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,no) # both, prefer aix dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]" library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' ;; esac shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[[45]]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' library_names_spec='$libname.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[[23]].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[[01]]* | freebsdelf3.[[01]]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[[3-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; linux*android*) version_type=none # Android doesn't support versioned libraries. need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext' soname_spec='$libname$release$shared_ext' finish_cmds= shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes dynamic_linker='Android linker' # Don't embed -rpath directories since the linker doesn't support them. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], [lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], [lt_cv_shlibpath_overrides_runpath=yes])]) LDFLAGS=$save_LDFLAGS libdir=$save_libdir ]) shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not # being certain /sbin/ldconfig is available, command # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, # even though it is searched at run-time. Try to do the best guess by # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd* | bitrig*) version_type=sunos sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then need_version=no else need_version=yes fi library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no # OS/2 can only load a DLL with a base name of 8 characters or less. soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; v=$($ECHO $release$versuffix | tr -d .-); n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); $ECHO $n$v`$shared_ext' library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' shlibpath_var=BEGINLIBPATH sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=sco need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac AC_MSG_RESULT([$dynamic_linker]) test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi # remember unaugmented sys_lib_dlsearch_path content for libtool script decls... configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec # ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" # to be used as default LT_SYS_LIBRARY_PATH value in generated libtool configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH _LT_DECL([], [variables_saved_for_relink], [1], [Variables whose values should be saved in libtool wrapper scripts and restored at link time]) _LT_DECL([], [need_lib_prefix], [0], [Do we need the "lib" prefix for modules?]) _LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) _LT_DECL([], [version_type], [0], [Library versioning type]) _LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) _LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) _LT_DECL([], [shlibpath_overrides_runpath], [0], [Is shlibpath searched before the hard-coded library search path?]) _LT_DECL([], [libname_spec], [1], [Format of library name prefix]) _LT_DECL([], [library_names_spec], [1], [[List of archive names. First name is the real one, the rest are links. The last name is the one that the linker finds with -lNAME]]) _LT_DECL([], [soname_spec], [1], [[The coded name of the library, if different from the real name]]) _LT_DECL([], [install_override_mode], [1], [Permission mode override for installation of shared libraries]) _LT_DECL([], [postinstall_cmds], [2], [Command to use after installation of a shared archive]) _LT_DECL([], [postuninstall_cmds], [2], [Command to use after uninstallation of a shared archive]) _LT_DECL([], [finish_cmds], [2], [Commands used to finish a libtool library installation in a directory]) _LT_DECL([], [finish_eval], [1], [[As "finish_cmds", except a single script fragment to be evaled but not shown]]) _LT_DECL([], [hardcode_into_libs], [0], [Whether we should hardcode library paths into libraries]) _LT_DECL([], [sys_lib_search_path_spec], [2], [Compile-time system search path for libraries]) _LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2], [Detected run-time system search path for libraries]) _LT_DECL([], [configure_time_lt_sys_library_path], [2], [Explicit LT_SYS_LIBRARY_PATH set during ./configure time]) ])# _LT_SYS_DYNAMIC_LINKER # _LT_PATH_TOOL_PREFIX(TOOL) # -------------------------- # find a file program that can recognize shared library AC_DEFUN([_LT_PATH_TOOL_PREFIX], [m4_require([_LT_DECL_EGREP])dnl AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [case $MAGIC_CMD in [[\\/*] | ?:[\\/]*]) lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD=$MAGIC_CMD lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="m4_if([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$1"; then lt_cv_path_MAGIC_CMD=$ac_dir/"$1" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS=$lt_save_ifs MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac]) MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else AC_MSG_RESULT(no) fi _LT_DECL([], [MAGIC_CMD], [0], [Used to examine libraries when file_magic_cmd begins with "file"])dnl ])# _LT_PATH_TOOL_PREFIX # Old name: AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) # _LT_PATH_MAGIC # -------------- # find a file program that can recognize a shared library m4_defun([_LT_PATH_MAGIC], [_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) else MAGIC_CMD=: fi fi ])# _LT_PATH_MAGIC # LT_PATH_LD # ---------- # find the pathname to the GNU or non-GNU linker AC_DEFUN([LT_PATH_LD], [AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PROG_ECHO_BACKSLASH])dnl AC_ARG_WITH([gnu-ld], [AS_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], [test no = "$withval" || with_gnu_ld=yes], [with_gnu_ld=no])dnl ac_prog=ld if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by $CC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]]* | ?:[[\\/]]*) re_direlt='/[[^/]][[^/]]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test yes = "$with_gnu_ld"; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &1 conftest.i cat conftest.i conftest.i >conftest2.i : ${lt_DD:=$DD} AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd], [if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: fi]) rm -f conftest.i conftest2.i conftest.out]) ])# _LT_PATH_DD # _LT_CMD_TRUNCATE # ---------------- # find command to truncate a binary pipe m4_defun([_LT_CMD_TRUNCATE], [m4_require([_LT_PATH_DD]) AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin], [printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i lt_cv_truncate_bin= if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" fi rm -f conftest.i conftest2.i conftest.out test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"]) _LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1], [Command to truncate a binary pipe]) ])# _LT_CMD_TRUNCATE # _LT_CHECK_MAGIC_METHOD # ---------------------- # how to check for library dependencies # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_MAGIC_METHOD], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) AC_CACHE_CHECK([how to recognize dependent libraries], lt_cv_deplibs_check_method, [lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # 'unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # that responds to the $file_magic_cmd with a given extended regex. # If you have 'file' or equivalent on your system and you're not sure # whether 'pass_all' will *always* work, you probably want this one. case $host_os in aix[[4-9]]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[[45]]*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. if ( file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[[3-9]]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd* | bitrig*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; os2*) lt_cv_deplibs_check_method=pass_all ;; esac ]) file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown _LT_DECL([], [deplibs_check_method], [1], [Method to check whether dependent libraries are shared objects]) _LT_DECL([], [file_magic_cmd], [1], [Command to use when deplibs_check_method = "file_magic"]) _LT_DECL([], [file_magic_glob], [1], [How to find potential files when deplibs_check_method = "file_magic"]) _LT_DECL([], [want_nocaseglob], [1], [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) ])# _LT_CHECK_MAGIC_METHOD # LT_PATH_NM # ---------- # find the pathname to a BSD- or MS-compatible name lister AC_DEFUN([LT_PATH_NM], [AC_REQUIRE([AC_PROG_CC])dnl AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM=$NM else lt_nm_to_check=${ac_tool_prefix}nm if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. tmp_nm=$ac_dir/$lt_tmp_nm if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then # Check to see if the nm accepts a BSD-compat flag. # Adding the 'sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty case $build_os in mingw*) lt_bad_file=conftest.nm/nofile ;; *) lt_bad_file=/dev/null ;; esac case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in *$lt_bad_file* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break 2 ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break 2 ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS=$lt_save_ifs done : ${lt_cv_path_NM=no} fi]) if test no != "$lt_cv_path_NM"; then NM=$lt_cv_path_NM else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols -headers" ;; *) DUMPBIN=: ;; esac fi AC_SUBST([DUMPBIN]) if test : != "$DUMPBIN"; then NM=$DUMPBIN fi fi test -z "$NM" && NM=nm AC_SUBST([NM]) _LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], [lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) cat conftest.out >&AS_MESSAGE_LOG_FD if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest*]) ])# LT_PATH_NM # Old names: AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_PROG_NM], []) dnl AC_DEFUN([AC_PROG_NM], []) # _LT_CHECK_SHAREDLIB_FROM_LINKLIB # -------------------------------- # how to determine the name of the shared library # associated with a specific link library. # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) m4_require([_LT_DECL_DLLTOOL]) AC_CACHE_CHECK([how to associate runtime and link libraries], lt_cv_sharedlib_from_linklib_cmd, [lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh; # decide which one to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd=$ECHO ;; esac ]) sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO _LT_DECL([], [sharedlib_from_linklib_cmd], [1], [Command to associate shared and link libraries]) ])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB # _LT_PATH_MANIFEST_TOOL # ---------------------- # locate the manifest tool m4_defun([_LT_PATH_MANIFEST_TOOL], [AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], [lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&AS_MESSAGE_LOG_FD if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest*]) if test yes != "$lt_cv_path_mainfest_tool"; then MANIFEST_TOOL=: fi _LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl ])# _LT_PATH_MANIFEST_TOOL # _LT_DLL_DEF_P([FILE]) # --------------------- # True iff FILE is a Windows DLL '.def' file. # Keep in sync with func_dll_def_p in the libtool script AC_DEFUN([_LT_DLL_DEF_P], [dnl test DEF = "`$SED -n dnl -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl -e q dnl Only consider the first "real" line $1`" dnl ])# _LT_DLL_DEF_P # LT_LIB_M # -------- # check for math library AC_DEFUN([LT_LIB_M], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in *-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw) AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") ;; *) AC_CHECK_LIB(m, cos, LIBM=-lm) ;; esac AC_SUBST([LIBM]) ])# LT_LIB_M # Old name: AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_CHECK_LIBM], []) # _LT_COMPILER_NO_RTTI([TAGNAME]) # ------------------------------- m4_defun([_LT_COMPILER_NO_RTTI], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= if test yes = "$GCC"; then case $cc_basename in nvcc*) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; *) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; esac _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], lt_cv_prog_compiler_rtti_exceptions, [-fno-rtti -fno-exceptions], [], [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) fi _LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], [Compiler flag to turn off builtin functions]) ])# _LT_COMPILER_NO_RTTI # _LT_CMD_GLOBAL_SYMBOLS # ---------------------- m4_defun([_LT_CMD_GLOBAL_SYMBOLS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([LT_PATH_NM])dnl AC_REQUIRE([LT_PATH_LD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_TAG_COMPILER])dnl # Check for command to grab the raw symbol name followed by C symbol from nm. AC_MSG_CHECKING([command to parse $NM output from $compiler object]) AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [ # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[[BCDEGRST]]' # Regexp to match symbols that can be accessed directly from C. sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[[BCDT]]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[[ABCDGISTW]]' ;; hpux*) if test ia64 = "$host_cpu"; then symcode='[[ABCDEGRST]]' fi ;; irix* | nonstopux*) symcode='[[BCDEGRST]]' ;; osf*) symcode='[[BCDEGQRST]]' ;; solaris*) symcode='[[BDRT]]' ;; sco3.2v5*) symcode='[[DT]]' ;; sysv4.2uw2*) symcode='[[DT]]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[[ABDT]]' ;; sysv4) symcode='[[DFNSTU]]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[[ABCDGIRSTW]]' ;; esac if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Gets list of data symbols to import. lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" # Adjust the below global symbol transforms to fixup imported variables. lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" lt_c_name_lib_hook="\ -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" else # Disable hooks by default. lt_cv_sys_global_symbol_to_import= lt_cdecl_hook= lt_c_name_hook= lt_c_name_lib_hook= fi # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n"\ $lt_cdecl_hook\ " -e 's/^T .* \(.*\)$/extern int \1();/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ $lt_c_name_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" # Transform an extracted symbol line into symbol name with lib prefix and # symbol address. lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ $lt_c_name_lib_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function, # D for any global variable and I for any imported variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK ['"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ " /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ " /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ " {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ " s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx]" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if AC_TRY_EVAL(ac_compile); then # Now try to grab the symbols. nlist=conftest.nm if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE /* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT@&t@_DLSYM_CONST #elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT@&t@_DLSYM_CONST #else # define LT@&t@_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT@&t@_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[[]] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS=conftstm.$ac_objext CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD fi else echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test yes = "$pipe_works"; then break else lt_cv_sys_global_symbol_pipe= fi done ]) if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then AC_MSG_RESULT(failed) else AC_MSG_RESULT(ok) fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then nm_file_list_spec='@' fi _LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], [Take the output of nm and produce a listing of raw symbols and C names]) _LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], [Transform the output of nm in a proper C declaration]) _LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1], [Transform the output of nm into a list of symbols to manually relocate]) _LT_DECL([global_symbol_to_c_name_address], [lt_cv_sys_global_symbol_to_c_name_address], [1], [Transform the output of nm in a C name address pair]) _LT_DECL([global_symbol_to_c_name_address_lib_prefix], [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], [Transform the output of nm in a C name address pair when lib prefix is needed]) _LT_DECL([nm_interface], [lt_cv_nm_interface], [1], [The name lister interface]) _LT_DECL([], [nm_file_list_spec], [1], [Specify filename containing input files for $NM]) ]) # _LT_CMD_GLOBAL_SYMBOLS # _LT_COMPILER_PIC([TAGNAME]) # --------------------------- m4_defun([_LT_COMPILER_PIC], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_wl, $1)= _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)= m4_if([$1], [CXX], [ # C++ specific cases for pic, static, wl, etc. if test yes = "$GXX"; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else case $host_os in aix[[4-9]]*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; dgux*) case $cc_basename in ec++*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; ghcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' if test ia64 != "$host_cpu"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # KAI C++ Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64, which still supported -KPIC. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL 8.0, 9.0 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' ;; *) ;; esac ;; netbsd* | netbsdelf*-gnu) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; cxx*) # Digital/Compaq C++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; lcc*) # Lucid _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ], [ if test yes = "$GCC"; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' case $cc_basename in nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; hpux9* | hpux10* | hpux11*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC (with -KPIC) is the default. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64, which still supported -KPIC. ecc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # Lahey Fortran 8.1. lf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' ;; nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; tcc*) # Fabrice Bellard et al's Tiny C Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; ccc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All Alpha code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='' ;; *Sun\ F* | *Sun*Fortran*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ;; *Intel*\ [[CF]]*Compiler*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; *Portland\ Group*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; esac ;; newsos6) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All OSF/1 code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; rdos*) _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; solaris*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; *) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; esac ;; sunos4*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; unicos*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; uts4*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ]) case $host_os in # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" ;; esac AC_CACHE_CHECK([for $compiler option to produce PIC], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) _LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) # # Check to make sure the PIC flag actually works. # if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in "" | " "*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; esac], [_LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) fi _LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], [Additional compiler flags for building library objects]) _LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], [How to pass a linker flag through the compiler]) # # Check to make sure the static flag actually works. # wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" _LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), $lt_tmp_static_flag, [], [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) _LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], [Compiler flag to prevent dynamic linking]) ])# _LT_COMPILER_PIC # _LT_LINKER_SHLIBS([TAGNAME]) # ---------------------------- # See if the linker supports building shared libraries. m4_defun([_LT_LINKER_SHLIBS], [AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) m4_if([$1], [CXX], [ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] case $host_os in aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi ;; pw32*) _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl*) _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] ;; esac ;; linux* | k*bsd*-gnu | gnu*) _LT_TAGVAR(link_all_deplibs, $1)=no ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac ], [ runpath_var= _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_cmds, $1)= _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(old_archive_from_new_cmds, $1)= _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= _LT_TAGVAR(thread_safe_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list _LT_TAGVAR(include_expsyms, $1)= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ' (' and ')$', so one must not match beginning or # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', # as well as any symbol that contains 'd'. _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. dnl Note also adjust exclude_expsyms for C++ above. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test yes != "$GCC"; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd* | bitrig*) with_gnu_ld=no ;; linux* | k*bsd*-gnu | gnu*) _LT_TAGVAR(link_all_deplibs, $1)=no ;; esac _LT_TAGVAR(ld_shlibs, $1)=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test yes = "$with_gnu_ld"; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test yes = "$lt_use_gnu_ld_interface"; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='$wl' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi supports_anon_versioning=no case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[[3-9]]*) # On AIX/PPC, the GNU linker is very broken if test ia64 != "$host_cpu"; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test linux-dietlibc = "$host_os"; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test no = "$tmp_diet" then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 _LT_TAGVAR(whole_archive_flag_spec, $1)= tmp_sharedflag='--shared' ;; nagfor*) # NAGFOR 5.3 tmp_sharedflag='-Wl,-shared' ;; xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi case $cc_basename in tcc*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' ;; xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; sunos4*) _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then runpath_var= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. _LT_TAGVAR(hardcode_minus_L, $1)=yes if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_TAGVAR(hardcode_direct, $1)=unsupported fi ;; aix[[4-9]]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then aix_use_runtimelinking=yes break fi done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # traditional, no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no ;; esac if test yes = "$GCC"; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi ;; esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag="$shared_flag "'$wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_TAGVAR(always_export_symbols, $1)=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; bsdi[[45]]*) _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' # FIXME: Should let the user specify the lib program. _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; hpux9*) if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' ;; hpux10*) if test yes,no = "$GCC,$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes fi ;; hpux11*) if test yes,no = "$GCC,$with_gnu_ld"; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) m4_if($1, [], [ # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) _LT_LINKER_OPTION([if $CC understands -b], _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) ;; esac fi if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], [lt_cv_irix_exported_symbol], [save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" AC_LINK_IFELSE( [AC_LANG_SOURCE( [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], [C++], [[int foo (void) { return 0; }]], [Fortran 77], [[ subroutine foo end]], [Fortran], [[ subroutine foo end]])])], [lt_cv_irix_exported_symbol=yes], [lt_cv_irix_exported_symbol=no]) LDFLAGS=$save_LDFLAGS]) if test yes = "$lt_cv_irix_exported_symbol"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' fi _LT_TAGVAR(link_all_deplibs, $1)=no else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes _LT_TAGVAR(link_all_deplibs, $1)=yes ;; linux*) case $cc_basename in tcc*) # Fabrice Bellard et al's Tiny C Compiler _LT_TAGVAR(ld_shlibs, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; newsos6) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *nto* | *qnx*) ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' fi else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; osf3*) if test yes = "$GCC"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test yes = "$GCC"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; solaris*) _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' if test yes = "$GCC"; then wlarc='$wl' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='$wl' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. GCC discards it without '$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test yes = "$GCC"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' else _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' fi ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes ;; sunos4*) if test sequent = "$host_vendor"; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4) case $host_vendor in sni) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' _LT_TAGVAR(hardcode_direct, $1)=no ;; motorola) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4.3*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes _LT_TAGVAR(ld_shlibs, $1)=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(ld_shlibs, $1)=no ;; esac if test sni = "$host_vendor"; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym' ;; esac fi fi ]) AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no _LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld _LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl _LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl _LT_DECL([], [extract_expsyms_cmds], [2], [The commands to extract the exported symbol list from a shared archive]) # # Do we need to explicitly link libc? # case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in x|xyes) # Assume -lc should be added _LT_TAGVAR(archive_cmds_need_lc, $1)=yes if test yes,yes = "$GCC,$enable_shared"; then case $_LT_TAGVAR(archive_cmds, $1) in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. AC_CACHE_CHECK([whether -lc should be explicitly linked in], [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), [$RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if AC_TRY_EVAL(ac_compile) 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) _LT_TAGVAR(allow_undefined_flag, $1)= if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) then lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no else lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes fi _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* ]) _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) ;; esac fi ;; esac _LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], [Whether or not to add -lc for building shared libraries]) _LT_TAGDECL([allow_libtool_libs_with_static_runtimes], [enable_shared_with_static_runtimes], [0], [Whether or not to disallow shared libs when runtime libs are static]) _LT_TAGDECL([], [export_dynamic_flag_spec], [1], [Compiler flag to allow reflexive dlopens]) _LT_TAGDECL([], [whole_archive_flag_spec], [1], [Compiler flag to generate shared objects directly from archives]) _LT_TAGDECL([], [compiler_needs_object], [1], [Whether the compiler copes with passing no objects directly]) _LT_TAGDECL([], [old_archive_from_new_cmds], [2], [Create an old-style archive from a shared archive]) _LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], [Create a temporary old-style archive to link instead of a shared archive]) _LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) _LT_TAGDECL([], [archive_expsym_cmds], [2]) _LT_TAGDECL([], [module_cmds], [2], [Commands used to build a loadable module if different from building a shared archive.]) _LT_TAGDECL([], [module_expsym_cmds], [2]) _LT_TAGDECL([], [with_gnu_ld], [1], [Whether we are building with GNU ld or not]) _LT_TAGDECL([], [allow_undefined_flag], [1], [Flag that allows shared libraries with undefined symbols to be built]) _LT_TAGDECL([], [no_undefined_flag], [1], [Flag that enforces no undefined symbols]) _LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], [Flag to hardcode $libdir into a binary during linking. This must work even if $libdir does not exist]) _LT_TAGDECL([], [hardcode_libdir_separator], [1], [Whether we need a single "-rpath" flag with a separated argument]) _LT_TAGDECL([], [hardcode_direct], [0], [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_direct_absolute], [0], [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes DIR into the resulting binary and the resulting library dependency is "absolute", i.e impossible to change by setting $shlibpath_var if the library is relocated]) _LT_TAGDECL([], [hardcode_minus_L], [0], [Set to "yes" if using the -LDIR flag during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_shlibpath_var], [0], [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_automatic], [0], [Set to "yes" if building a shared library automatically hardcodes DIR into the library and all subsequent libraries and executables linked against it]) _LT_TAGDECL([], [inherit_rpath], [0], [Set to yes if linker adds runtime paths of dependent libraries to runtime path list]) _LT_TAGDECL([], [link_all_deplibs], [0], [Whether libtool must link a program against all its dependency libraries]) _LT_TAGDECL([], [always_export_symbols], [0], [Set to "yes" if exported symbols are required]) _LT_TAGDECL([], [export_symbols_cmds], [2], [The commands to list exported symbols]) _LT_TAGDECL([], [exclude_expsyms], [1], [Symbols that should not be listed in the preloaded symbols]) _LT_TAGDECL([], [include_expsyms], [1], [Symbols that must always be exported]) _LT_TAGDECL([], [prelink_cmds], [2], [Commands necessary for linking programs (against libraries) with templates]) _LT_TAGDECL([], [postlink_cmds], [2], [Commands necessary for finishing linking programs]) _LT_TAGDECL([], [file_list_spec], [1], [Specify filename containing input files]) dnl FIXME: Not yet implemented dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], dnl [Compiler flag to generate thread safe objects]) ])# _LT_LINKER_SHLIBS # _LT_LANG_C_CONFIG([TAG]) # ------------------------ # Ensure that the configuration variables for a C compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to 'libtool'. m4_defun([_LT_LANG_C_CONFIG], [m4_require([_LT_DECL_EGREP])dnl lt_save_CC=$CC AC_LANG_PUSH(C) # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' _LT_TAG_COMPILER # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) LT_SYS_DLOPEN_SELF _LT_CMD_STRIPLIB # Report what library types will actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_CONFIG($1) fi AC_LANG_POP CC=$lt_save_CC ])# _LT_LANG_C_CONFIG # _LT_LANG_CXX_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a C++ compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to 'libtool'. m4_defun([_LT_LANG_CXX_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl if test -n "$CXX" && ( test no != "$CXX" && ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || (test g++ != "$CXX"))); then AC_PROG_CXXCPP else _lt_caught_CXX_error=yes fi AC_LANG_PUSH(C++) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_caught_CXX_error"; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} CFLAGS=$CXXFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test yes = "$GXX"; then _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi if test yes = "$GXX"; then # Set up default GNU C++ configuration LT_PATH_LD # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test yes = "$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='$wl' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) _LT_TAGVAR(ld_shlibs, $1)=yes case $host_os in aix3*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aix[[4-9]]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no ;; esac if test yes = "$GXX"; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag=$shared_flag' $wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. _LT_TAGVAR(always_export_symbols, $1)=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. # The "-G" linker flag allows undefined symbols. _LT_TAGVAR(no_undefined_flag, $1)='-bernotok' # Determine the default libpath from the value encoded in an empty # executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in ,cl* | no,cl*) # Native MSVC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ func_to_tool_file "$lt_outputfile"~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF _LT_TAGVAR(ld_shlibs, $1)=no ;; freebsd-elf*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_TAGVAR(ld_shlibs, $1)=yes ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; hpux9*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; hpux10*|hpux11*) if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) ;; *) _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' fi fi _LT_TAGVAR(link_all_deplibs, $1)=yes ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' ;; cxx*) # Compaq C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; m88k*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) _LT_TAGVAR(ld_shlibs, $1)=yes ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; cxx*) case $host in osf3*) _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' ;; *) _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ $RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' ;; esac _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes,no = "$GXX,$with_gnu_ld"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' case $host in osf3*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test yes,no = "$GXX,$with_gnu_ld"; then _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # g++ 2.7 appears to require '-G' NOT '-shared' on this # platform. _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ '"$_LT_TAGVAR(old_archive_cmds, $1)" _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ '"$_LT_TAGVAR(reload_cmds, $1)" ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no _LT_TAGVAR(GCC, $1)=$GXX _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test yes != "$_lt_caught_CXX_error" AC_LANG_POP ])# _LT_LANG_CXX_CONFIG # _LT_FUNC_STRIPNAME_CNF # ---------------------- # func_stripname_cnf prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # # This function is identical to the (non-XSI) version of func_stripname, # except this one can be used by m4 code that may be executed by configure, # rather than the libtool script. m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl AC_REQUIRE([_LT_DECL_SED]) AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) func_stripname_cnf () { case @S|@2 in .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;; *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;; esac } # func_stripname_cnf ])# _LT_FUNC_STRIPNAME_CNF # _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) # --------------------------------- # Figure out "hidden" library dependencies from verbose # compiler output when linking a shared library. # Parse the compiler output and extract the necessary # objects, libraries and library flags. m4_defun([_LT_SYS_HIDDEN_LIBDEPS], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl # Dependencies to place before and after the object being linked: _LT_TAGVAR(predep_objects, $1)= _LT_TAGVAR(postdep_objects, $1)= _LT_TAGVAR(predeps, $1)= _LT_TAGVAR(postdeps, $1)= _LT_TAGVAR(compiler_lib_search_path, $1)= dnl we can't use the lt_simple_compile_test_code here, dnl because it contains code intended for an executable, dnl not a library. It's possible we should let each dnl tag define a new lt_????_link_test_code variable, dnl but it's only used here... m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF int a; void foo (void) { a = 0; } _LT_EOF ], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF ], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer*4 a a=0 return end _LT_EOF ], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer a a=0 return end _LT_EOF ], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF public class foo { private int a; public void bar (void) { a = 0; } }; _LT_EOF ], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF package foo func foo() { } _LT_EOF ]) _lt_libdeps_save_CFLAGS=$CFLAGS case "$CC $CFLAGS " in #( *\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; *\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; *\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; esac dnl Parse the compiler output and extract the necessary dnl objects, libraries and library flags. if AC_TRY_EVAL(ac_compile); then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case $prev$p in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test x-L = "$p" || test x-R = "$p"; then prev=$p continue fi # Expand the sysroot to ease extracting the directories later. if test -z "$prev"; then case $p in -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; esac fi case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac if test no = "$pre_test_object_deps_done"; then case $prev in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p else _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$_LT_TAGVAR(postdeps, $1)"; then _LT_TAGVAR(postdeps, $1)=$prev$p else _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p" fi fi prev= ;; *.lto.$objext) ;; # Ignore GCC LTO objects *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test no = "$pre_test_object_deps_done"; then if test -z "$_LT_TAGVAR(predep_objects, $1)"; then _LT_TAGVAR(predep_objects, $1)=$p else _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" fi else if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then _LT_TAGVAR(postdep_objects, $1)=$p else _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling $1 test program" fi $RM -f confest.$objext CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken m4_if([$1], [CXX], [case $host_os in interix[[3-9]]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. _LT_TAGVAR(predep_objects,$1)= _LT_TAGVAR(postdep_objects,$1)= _LT_TAGVAR(postdeps,$1)= ;; esac ]) case " $_LT_TAGVAR(postdeps, $1) " in *" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; esac _LT_TAGVAR(compiler_lib_search_dirs, $1)= if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'` fi _LT_TAGDECL([], [compiler_lib_search_dirs], [1], [The directories searched by this compiler when creating a shared library]) _LT_TAGDECL([], [predep_objects], [1], [Dependencies to place before and after the objects being linked to create a shared library]) _LT_TAGDECL([], [postdep_objects], [1]) _LT_TAGDECL([], [predeps], [1]) _LT_TAGDECL([], [postdeps], [1]) _LT_TAGDECL([], [compiler_lib_search_path], [1], [The library search path used internally by the compiler when linking a shared library]) ])# _LT_SYS_HIDDEN_LIBDEPS # _LT_LANG_F77_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a Fortran 77 compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_F77_CONFIG], [AC_LANG_PUSH(Fortran 77) if test -z "$F77" || test no = "$F77"; then _lt_disable_F77=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for f77 test sources. ac_ext=f # Object file extension for compiled f77 test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the F77 compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_disable_F77"; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${F77-"f77"} CFLAGS=$FFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) GCC=$G77 if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)=$G77 _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test yes != "$_lt_disable_F77" AC_LANG_POP ])# _LT_LANG_F77_CONFIG # _LT_LANG_FC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for a Fortran compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_FC_CONFIG], [AC_LANG_PUSH(Fortran) if test -z "$FC" || test no = "$FC"; then _lt_disable_FC=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for fc test sources. ac_ext=${ac_fc_srcext-f} # Object file extension for compiled fc test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the FC compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_disable_FC"; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${FC-"f95"} CFLAGS=$FCFLAGS compiler=$CC GCC=$ac_cv_fc_compiler_gnu _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test yes != "$_lt_disable_FC" AC_LANG_POP ])# _LT_LANG_FC_CONFIG # _LT_LANG_GCJ_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Java Compiler compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_GCJ_CONFIG], [AC_REQUIRE([LT_PROG_GCJ])dnl AC_LANG_SAVE # Source file extension for Java test sources. ac_ext=java # Object file extension for compiled Java test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="class foo {}" # Code to be used in simple link tests lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GCJ-"gcj"} CFLAGS=$GCJFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)=$LD _LT_CC_BASENAME([$compiler]) # GCJ did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GCJ_CONFIG # _LT_LANG_GO_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Go compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_GO_CONFIG], [AC_REQUIRE([LT_PROG_GO])dnl AC_LANG_SAVE # Source file extension for Go test sources. ac_ext=go # Object file extension for compiled Go test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="package main; func main() { }" # Code to be used in simple link tests lt_simple_link_test_code='package main; func main() { }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GOC-"gccgo"} CFLAGS=$GOFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)=$LD _LT_CC_BASENAME([$compiler]) # Go did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GO_CONFIG # _LT_LANG_RC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for the Windows resource compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_RC_CONFIG], [AC_REQUIRE([LT_PROG_RC])dnl AC_LANG_SAVE # Source file extension for RC test sources. ac_ext=rc # Object file extension for compiled RC test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # Code to be used in simple link tests lt_simple_link_test_code=$lt_simple_compile_test_code # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC= CC=${RC-"windres"} CFLAGS= compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes if test -n "$compiler"; then : _LT_CONFIG($1) fi GCC=$lt_save_GCC AC_LANG_RESTORE CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_RC_CONFIG # LT_PROG_GCJ # ----------- AC_DEFUN([LT_PROG_GCJ], [m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj,) test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS)])])[]dnl ]) # Old name: AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_GCJ], []) # LT_PROG_GO # ---------- AC_DEFUN([LT_PROG_GO], [AC_CHECK_TOOL(GOC, gccgo,) ]) # LT_PROG_RC # ---------- AC_DEFUN([LT_PROG_RC], [AC_CHECK_TOOL(RC, windres,) ]) # Old name: AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_RC], []) # _LT_DECL_EGREP # -------------- # If we don't have a new enough Autoconf to choose the best grep # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_EGREP], [AC_REQUIRE([AC_PROG_EGREP])dnl AC_REQUIRE([AC_PROG_FGREP])dnl test -z "$GREP" && GREP=grep _LT_DECL([], [GREP], [1], [A grep program that handles long lines]) _LT_DECL([], [EGREP], [1], [An ERE matcher]) _LT_DECL([], [FGREP], [1], [A literal string matcher]) dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too AC_SUBST([GREP]) ]) # _LT_DECL_OBJDUMP # -------------- # If we don't have a new enough Autoconf to choose the best objdump # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_OBJDUMP], [AC_CHECK_TOOL(OBJDUMP, objdump, false) test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) AC_SUBST([OBJDUMP]) ]) # _LT_DECL_DLLTOOL # ---------------- # Ensure DLLTOOL variable is set. m4_defun([_LT_DECL_DLLTOOL], [AC_CHECK_TOOL(DLLTOOL, dlltool, false) test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program]) AC_SUBST([DLLTOOL]) ]) # _LT_DECL_SED # ------------ # Check for a fully-functional sed program, that truncates # as few characters as possible. Prefer GNU sed if found. m4_defun([_LT_DECL_SED], [AC_PROG_SED test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" _LT_DECL([], [SED], [1], [A sed program that does not truncate output]) _LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], [Sed that helps us avoid accidentally triggering echo(1) options like -n]) ])# _LT_DECL_SED m4_ifndef([AC_PROG_SED], [ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_SED. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # m4_defun([AC_PROG_SED], [AC_MSG_CHECKING([for a sed that does not truncate output]) AC_CACHE_VAL(lt_cv_path_SED, [# Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done IFS=$as_save_IFS lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f "$lt_ac_sed" && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test 10 -lt "$lt_ac_count" && break lt_ac_count=`expr $lt_ac_count + 1` if test "$lt_ac_count" -gt "$lt_ac_max"; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done ]) SED=$lt_cv_path_SED AC_SUBST([SED]) AC_MSG_RESULT([$SED]) ])#AC_PROG_SED ])#m4_ifndef # Old name: AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_SED], []) # _LT_CHECK_SHELL_FEATURES # ------------------------ # Find out whether the shell is Bourne or XSI compatible, # or has some other useful features. m4_defun([_LT_CHECK_SHELL_FEATURES], [if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi _LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac _LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl _LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl ])# _LT_CHECK_SHELL_FEATURES # _LT_PATH_CONVERSION_FUNCTIONS # ----------------------------- # Determine what file name conversion functions should be used by # func_to_host_file (and, implicitly, by func_to_host_path). These are needed # for certain cross-compile configurations and native mingw. m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_MSG_CHECKING([how to convert $build file names to $host format]) AC_CACHE_VAL(lt_cv_to_host_file_cmd, [case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac ]) to_host_file_cmd=$lt_cv_to_host_file_cmd AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) _LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], [0], [convert $build file names to $host format])dnl AC_MSG_CHECKING([how to convert $build file names to toolchain format]) AC_CACHE_VAL(lt_cv_to_tool_file_cmd, [#assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac ]) to_tool_file_cmd=$lt_cv_to_tool_file_cmd AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) _LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], [0], [convert $build files to toolchain format])dnl ])# _LT_PATH_CONVERSION_FUNCTIONS # Helper functions for option handling. -*- Autoconf -*- # # Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software # Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 8 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) # _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) # ------------------------------------------ m4_define([_LT_MANGLE_OPTION], [[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) # _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) # --------------------------------------- # Set option OPTION-NAME for macro MACRO-NAME, and if there is a # matching handler defined, dispatch to it. Other OPTION-NAMEs are # saved as a flag. m4_define([_LT_SET_OPTION], [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), _LT_MANGLE_DEFUN([$1], [$2]), [m4_warning([Unknown $1 option '$2'])])[]dnl ]) # _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) # ------------------------------------------------------------ # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. m4_define([_LT_IF_OPTION], [m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) # _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) # ------------------------------------------------------- # Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME # are set. m4_define([_LT_UNLESS_OPTIONS], [m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), [m4_define([$0_found])])])[]dnl m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 ])[]dnl ]) # _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) # ---------------------------------------- # OPTION-LIST is a space-separated list of Libtool options associated # with MACRO-NAME. If any OPTION has a matching handler declared with # LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about # the unknown option and exit. m4_defun([_LT_SET_OPTIONS], [# Set options m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [_LT_SET_OPTION([$1], _LT_Option)]) m4_if([$1],[LT_INIT],[ dnl dnl Simply set some default values (i.e off) if boolean options were not dnl specified: _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no ]) _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no ]) dnl dnl If no reference was made to various pairs of opposing options, then dnl we run the default mode handler for the pair. For example, if neither dnl 'shared' nor 'disable-shared' was passed, we enable building of shared dnl archives by default: _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], [_LT_ENABLE_FAST_INSTALL]) _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], [_LT_WITH_AIX_SONAME([aix])]) ]) ])# _LT_SET_OPTIONS # _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) # ----------------------------------------- m4_define([_LT_MANGLE_DEFUN], [[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) # LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) # ----------------------------------------------- m4_define([LT_OPTION_DEFINE], [m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl ])# LT_OPTION_DEFINE # dlopen # ------ LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes ]) AU_DEFUN([AC_LIBTOOL_DLOPEN], [_LT_SET_OPTION([LT_INIT], [dlopen]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'dlopen' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) # win32-dll # --------- # Declare package support for building win32 dll's. LT_OPTION_DEFINE([LT_INIT], [win32-dll], [enable_win32_dll=yes case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) ;; esac test -z "$AS" && AS=as _LT_DECL([], [AS], [1], [Assembler program])dnl test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl ])# win32-dll AU_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_REQUIRE([AC_CANONICAL_HOST])dnl _LT_SET_OPTION([LT_INIT], [win32-dll]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'win32-dll' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) # _LT_ENABLE_SHARED([DEFAULT]) # ---------------------------- # implement the --enable-shared flag, and supports the 'shared' and # 'disable-shared' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_SHARED], [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([shared], [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS=$lt_save_ifs ;; esac], [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) _LT_DECL([build_libtool_libs], [enable_shared], [0], [Whether or not to build shared libraries]) ])# _LT_ENABLE_SHARED LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) # Old names: AC_DEFUN([AC_ENABLE_SHARED], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) ]) AC_DEFUN([AC_DISABLE_SHARED], [_LT_SET_OPTION([LT_INIT], [disable-shared]) ]) AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_SHARED], []) dnl AC_DEFUN([AM_DISABLE_SHARED], []) # _LT_ENABLE_STATIC([DEFAULT]) # ---------------------------- # implement the --enable-static flag, and support the 'static' and # 'disable-static' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_STATIC], [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([static], [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS=$lt_save_ifs ;; esac], [enable_static=]_LT_ENABLE_STATIC_DEFAULT) _LT_DECL([build_old_libs], [enable_static], [0], [Whether or not to build static libraries]) ])# _LT_ENABLE_STATIC LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) # Old names: AC_DEFUN([AC_ENABLE_STATIC], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) ]) AC_DEFUN([AC_DISABLE_STATIC], [_LT_SET_OPTION([LT_INIT], [disable-static]) ]) AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_STATIC], []) dnl AC_DEFUN([AM_DISABLE_STATIC], []) # _LT_ENABLE_FAST_INSTALL([DEFAULT]) # ---------------------------------- # implement the --enable-fast-install flag, and support the 'fast-install' # and 'disable-fast-install' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_FAST_INSTALL], [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([fast-install], [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS=$lt_save_ifs ;; esac], [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) _LT_DECL([fast_install], [enable_fast_install], [0], [Whether or not to optimize for fast installation])dnl ])# _LT_ENABLE_FAST_INSTALL LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) # Old names: AU_DEFUN([AC_ENABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'fast-install' option into LT_INIT's first parameter.]) ]) AU_DEFUN([AC_DISABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'disable-fast-install' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) # _LT_WITH_AIX_SONAME([DEFAULT]) # ---------------------------------- # implement the --with-aix-soname flag, and support the `aix-soname=aix' # and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT # is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. m4_define([_LT_WITH_AIX_SONAME], [m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl shared_archive_member_spec= case $host,$enable_shared in power*-*-aix[[5-9]]*,yes) AC_MSG_CHECKING([which variant of shared library versioning to provide]) AC_ARG_WITH([aix-soname], [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], [case $withval in aix|svr4|both) ;; *) AC_MSG_ERROR([Unknown argument to --with-aix-soname]) ;; esac lt_cv_with_aix_soname=$with_aix_soname], [AC_CACHE_VAL([lt_cv_with_aix_soname], [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) with_aix_soname=$lt_cv_with_aix_soname]) AC_MSG_RESULT([$with_aix_soname]) if test aix != "$with_aix_soname"; then # For the AIX way of multilib, we name the shared archive member # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, # the AIX toolchain works better with OBJECT_MODE set (default 32). if test 64 = "${OBJECT_MODE-32}"; then shared_archive_member_spec=shr_64 else shared_archive_member_spec=shr fi fi ;; *) with_aix_soname=aix ;; esac _LT_DECL([], [shared_archive_member_spec], [0], [Shared archive member basename, for filename based shared library versioning on AIX])dnl ])# _LT_WITH_AIX_SONAME LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) # _LT_WITH_PIC([MODE]) # -------------------- # implement the --with-pic flag, and support the 'pic-only' and 'no-pic' # LT_INIT options. # MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'. m4_define([_LT_WITH_PIC], [AC_ARG_WITH([pic], [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], [lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for lt_pkg in $withval; do IFS=$lt_save_ifs if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS=$lt_save_ifs ;; esac], [pic_mode=m4_default([$1], [default])]) _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl ])# _LT_WITH_PIC LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) # Old name: AU_DEFUN([AC_LIBTOOL_PICMODE], [_LT_SET_OPTION([LT_INIT], [pic-only]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'pic-only' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) m4_define([_LTDL_MODE], []) LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], [m4_define([_LTDL_MODE], [nonrecursive])]) LT_OPTION_DEFINE([LTDL_INIT], [recursive], [m4_define([_LTDL_MODE], [recursive])]) LT_OPTION_DEFINE([LTDL_INIT], [subproject], [m4_define([_LTDL_MODE], [subproject])]) m4_define([_LTDL_TYPE], []) LT_OPTION_DEFINE([LTDL_INIT], [installable], [m4_define([_LTDL_TYPE], [installable])]) LT_OPTION_DEFINE([LTDL_INIT], [convenience], [m4_define([_LTDL_TYPE], [convenience])]) # ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # # Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software # Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 6 ltsugar.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) # lt_join(SEP, ARG1, [ARG2...]) # ----------------------------- # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their # associated separator. # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier # versions in m4sugar had bugs. m4_define([lt_join], [m4_if([$#], [1], [], [$#], [2], [[$2]], [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) m4_define([_lt_join], [m4_if([$#$2], [2], [], [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) # lt_car(LIST) # lt_cdr(LIST) # ------------ # Manipulate m4 lists. # These macros are necessary as long as will still need to support # Autoconf-2.59, which quotes differently. m4_define([lt_car], [[$1]]) m4_define([lt_cdr], [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], [$#], 1, [], [m4_dquote(m4_shift($@))])]) m4_define([lt_unquote], $1) # lt_append(MACRO-NAME, STRING, [SEPARATOR]) # ------------------------------------------ # Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. # Note that neither SEPARATOR nor STRING are expanded; they are appended # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). # No SEPARATOR is output if MACRO-NAME was previously undefined (different # than defined and empty). # # This macro is needed until we can rely on Autoconf 2.62, since earlier # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. m4_define([lt_append], [m4_define([$1], m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) # ---------------------------------------------------------- # Produce a SEP delimited list of all paired combinations of elements of # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list # has the form PREFIXmINFIXSUFFIXn. # Needed until we can rely on m4_combine added in Autoconf 2.62. m4_define([lt_combine], [m4_if(m4_eval([$# > 3]), [1], [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl [[m4_foreach([_Lt_prefix], [$2], [m4_foreach([_Lt_suffix], ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) # ----------------------------------------------------------------------- # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. m4_define([lt_if_append_uniq], [m4_ifdef([$1], [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], [lt_append([$1], [$2], [$3])$4], [$5])], [lt_append([$1], [$2], [$3])$4])]) # lt_dict_add(DICT, KEY, VALUE) # ----------------------------- m4_define([lt_dict_add], [m4_define([$1($2)], [$3])]) # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) # -------------------------------------------- m4_define([lt_dict_add_subkey], [m4_define([$1($2:$3)], [$4])]) # lt_dict_fetch(DICT, KEY, [SUBKEY]) # ---------------------------------- m4_define([lt_dict_fetch], [m4_ifval([$3], m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) # ----------------------------------------------------------------- m4_define([lt_if_dict_fetch], [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], [$5], [$6])]) # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) # -------------------------------------------------------------- m4_define([lt_dict_filter], [m4_if([$5], [], [], [lt_join(m4_quote(m4_default([$4], [[, ]])), lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl ]) # ltversion.m4 -- version numbers -*- Autoconf -*- # # Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # @configure_input@ # serial 4179 ltversion.m4 # This file is part of GNU Libtool m4_define([LT_PACKAGE_VERSION], [2.4.6]) m4_define([LT_PACKAGE_REVISION], [2.4.6]) AC_DEFUN([LTVERSION_VERSION], [macro_version='2.4.6' macro_revision='2.4.6' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) # lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # # Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software # Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 5 lt~obsolete.m4 # These exist entirely to fool aclocal when bootstrapping libtool. # # In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), # which have later been changed to m4_define as they aren't part of the # exported API, or moved to Autoconf or Automake where they belong. # # The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN # in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us # using a macro with the same name in our local m4/libtool.m4 it'll # pull the old libtool.m4 in (it doesn't see our shiny new m4_define # and doesn't know about Autoconf macros at all.) # # So we provide this file, which has a silly filename so it's always # included after everything else. This provides aclocal with the # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything # because those macros already exist, or will be overwritten later. # We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. # # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. # Yes, that means every name once taken will need to remain here until # we give up compatibility with versions before 1.7, at which point # we need to keep only those names which we still refer to. # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) # Copyright (C) 2002-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.15' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.15], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.15])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to # '$srcdir', '$srcdir/..', or '$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is '.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl # Expand $ac_aux_dir to an absolute path. am_aux_dir=`cd "$ac_aux_dir" && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ([2.52])dnl m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl m4_define([_AM_COND_VALUE_$1], [$2])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], [$1], [CXX], [depcc="$CXX" am_compiler_list=], [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], [$1], [UPC], [depcc="$UPC" am_compiler_list=], [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES. AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE([dependency-tracking], [dnl AS_HELP_STRING( [--enable-dependency-tracking], [do not reject slow dependency extractors]) AS_HELP_STRING( [--disable-dependency-tracking], [speeds up one-time build])]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl AC_SUBST([am__nodep])dnl _AM_SUBST_NOTMAKE([am__nodep])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "$am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking # is enabled. FIXME. This creates each '.P' file that we will # need in order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC]) [_AM_PROG_CC_C_O ]) # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.65])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [AC_DIAGNOSE([obsolete], [$0: two- and three-arguments forms are deprecated.]) m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if( m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), [ok:ok],, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) AM_MISSING_PROG([AUTOCONF], [autoconf]) AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) AM_MISSING_PROG([AUTOHEADER], [autoheader]) AM_MISSING_PROG([MAKEINFO], [makeinfo]) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # AC_SUBST([mkdir_p], ['$(MKDIR_P)']) # We need awk for the "check" target (and possibly the TAP driver). The # system "awk" is bad on some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES([CC])], [m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES([CXX])], [m4_define([AC_PROG_CXX], m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES([OBJC])], [m4_define([AC_PROG_OBJC], m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], [_AM_DEPENDENCIES([OBJCXX])], [m4_define([AC_PROG_OBJCXX], m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl ]) AC_REQUIRE([AM_SILENT_RULES])dnl dnl The testsuite driver may need to know about EXEEXT, so add the dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) fi fi dnl The trailing newline in this macro's definition is deliberate, for dnl backward compatibility and to allow trailing 'dnl'-style comments dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. ]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi AC_SUBST([install_sh])]) # Copyright (C) 2003-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MAKE_INCLUDE() # ----------------- # Check to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it is modern enough. # If it is, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= AC_MSG_WARN(['missing' script is too old or missing]) fi ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # -------------------- # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), [1])]) # _AM_SET_OPTIONS(OPTIONS) # ------------------------ # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Copyright (C) 1999-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_CC_C_O # --------------- # Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC # to automatically call this. AC_DEFUN([_AM_PROG_CC_C_O], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([compile])dnl AC_LANG_PUSH([C])dnl AC_CACHE_CHECK( [whether $CC understands -c and -o together], [am_cv_prog_cc_c_o], [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i]) if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi AC_LANG_POP([C])]) # For backward compatibility. AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) # Copyright (C) 2001-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_RUN_LOG(COMMAND) # ------------------- # Run COMMAND, save the exit status in ac_status, and log it. # (This has been adapted from Autoconf's _AC_RUN_LOG macro.) AC_DEFUN([AM_RUN_LOG], [{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD (exit $ac_status); }]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[[\\\"\#\$\&\'\`$am_lf]]*) AC_MSG_ERROR([unsafe absolute working directory name]);; esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi if test "$[2]" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT([yes]) # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi AC_CONFIG_COMMANDS_PRE( [AC_MSG_CHECKING([that generated files are newer than configure]) if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi AC_MSG_RESULT([done])]) rm -f conftest.file ]) # Copyright (C) 2009-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SILENT_RULES([DEFAULT]) # -------------------------- # Enable less verbose build rules; with the default set to DEFAULT # ("yes" being less verbose, "no" or empty being verbose). AC_DEFUN([AM_SILENT_RULES], [AC_ARG_ENABLE([silent-rules], [dnl AS_HELP_STRING( [--enable-silent-rules], [less verbose build output (undo: "make V=1")]) AS_HELP_STRING( [--disable-silent-rules], [verbose build output (undo: "make V=0")])dnl ]) case $enable_silent_rules in @%:@ ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; esac dnl dnl A few 'make' implementations (e.g., NonStop OS and NextStep) dnl do not support nested variable expansions. dnl See automake bug#9928 and bug#10237. am_make=${MAKE-make} AC_CACHE_CHECK([whether $am_make supports nested variables], [am_cv_make_support_nested_variables], [if AS_ECHO([['TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi]) if test $am_cv_make_support_nested_variables = yes; then dnl Using '$V' instead of '$(V)' breaks IRIX make. AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AC_SUBST([AM_V])dnl AM_SUBST_NOTMAKE([AM_V])dnl AC_SUBST([AM_DEFAULT_V])dnl AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl AC_SUBST([AM_DEFAULT_VERBOSITY])dnl AM_BACKSLASH='\' AC_SUBST([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) # Copyright (C) 2001-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor 'install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in "make install-strip", and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) # -------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of 'v7', 'ustar', or 'pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar # AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' m4_if([$1], [v7], [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], [m4_case([$1], [ustar], [# The POSIX 1988 'ustar' format is defined with fixed-size fields. # There is notably a 21 bits limit for the UID and the GID. In fact, # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 # and bug#13588). am_max_uid=2097151 # 2^21 - 1 am_max_gid=$am_max_uid # The $UID and $GID variables are not portable, so we need to resort # to the POSIX-mandated id(1) utility. Errors in the 'id' calls # below are definitely unexpected, so allow the users to see them # (that is, avoid stderr redirection). am_uid=`id -u || echo unknown` am_gid=`id -g || echo unknown` AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) if test $am_uid -le $am_max_uid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) if test $am_gid -le $am_max_gid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi], [pax], [], [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Go ahead even if we have the value already cached. We do so because we # need to set the values for the 'am__tar' and 'am__untar' variables. _am_tools=${am_cv_prog_tar_$1-$_am_tools} for _am_tool in $_am_tools; do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works. rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR ode-0.16/libccd/configure0000775000175200017520000217303213403272666012306 00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for libccd 1.0. # # Report bugs to . # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org and danfis@danfis.cz $0: about your system, including any error possibly output $0: before this message. Then install a modern shell, or $0: manually run the script under such a shell if you do $0: have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" SHELL=${CONFIG_SHELL-/bin/sh} test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='libccd' PACKAGE_TARNAME='libccd' PACKAGE_VERSION='1.0' PACKAGE_STRING='libccd 1.0' PACKAGE_BUGREPORT='danfis@danfis.cz' PACKAGE_URL='' ac_unique_file="src/ccd.c" # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS CCD_PRECISION CXXCPP CPP LT_SYS_LIBRARY_PATH OTOOL64 OTOOL LIPO NMEDIT DSYMUTIL MANIFEST_TOOL RANLIB ac_ct_AR AR DLLTOOL OBJDUMP LN_S NM ac_ct_DUMPBIN DUMPBIN LD FGREP EGREP GREP SED host_os host_vendor host_cpu host build_os build_vendor build_cpu build LIBTOOL am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE ac_ct_CC CFLAGS CC am__fastdepCXX_FALSE am__fastdepCXX_TRUE CXXDEPMODE am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__quote am__include DEPDIR OBJEXT EXEEXT ac_ct_CXX CPPFLAGS LDFLAGS CXXFLAGS CXX AM_BACKSLASH AM_DEFAULT_VERBOSITY AM_DEFAULT_V AM_V am__untar am__tar AMTAR am__leading_dot SET_MAKE AWK mkdir_p MKDIR_P INSTALL_STRIP_PROGRAM STRIP install_sh MAKEINFO AUTOHEADER AUTOMAKE AUTOCONF ACLOCAL VERSION PACKAGE CYGPATH_W am__isrc INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir runstatedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_silent_rules enable_dependency_tracking enable_shared enable_static with_pic enable_fast_install with_aix_soname with_gnu_ld with_sysroot enable_libtool_lock enable_double_precision ' ac_precious_vars='build_alias host_alias target_alias CXX CXXFLAGS LDFLAGS LIBS CPPFLAGS CCC CC CFLAGS LT_SYS_LIBRARY_PATH CPP CXXCPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -runstatedir | --runstatedir | --runstatedi | --runstated \ | --runstate | --runstat | --runsta | --runst | --runs \ | --run | --ru | --r) ac_prev=runstatedir ;; -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ | --run=* | --ru=* | --r=*) runstatedir=$ac_optarg ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures libccd 1.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/libccd] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of libccd 1.0:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-silent-rules less verbose build output (undo: "make V=1") --disable-silent-rules verbose build output (undo: "make V=0") --enable-dependency-tracking do not reject slow dependency extractors --disable-dependency-tracking speeds up one-time build --enable-shared[=PKGS] build shared libraries [default=no] --enable-static[=PKGS] build static libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) --enable-double-precision enable double precision computations instead of single precision Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use both] --with-aix-soname=aix|svr4|both shared library versioning (aka "SONAME") variant to provide on AIX, [default=aix]. --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-sysroot[=DIR] Search for dependent libraries within DIR (or the compiler's sysroot if not specified). Some influential environment variables: CXX C++ compiler command CXXFLAGS C++ compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CC C compiler command CFLAGS C compiler flags LT_SYS_LIBRARY_PATH User-defined run-time library search path. CPP C preprocessor CXXCPP C++ preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF libccd configure 1.0 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_cxx_try_compile LINENO # ---------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_compile # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func # ac_fn_cxx_try_cpp LINENO # ------------------------ # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_cpp # ac_fn_cxx_try_link LINENO # ------------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_link # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ( $as_echo "## ------------------------------- ## ## Report this to danfis@danfis.cz ## ## ------------------------------- ##" ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache # variable VAR accordingly. ac_fn_c_check_type () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof ($2)) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof (($2))) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else eval "$3=yes" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_type cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by libccd $as_me 1.0, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_config_headers="$ac_config_headers src/config.h" am__api_version='1.15' ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in #(( ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 $as_echo_n "checking whether build environment is sane... " >&6; } # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[\\\"\#\$\&\'\`$am_lf]*) as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; esac case $srcdir in *[\\\"\#\$\&\'\`$am_lf\ \ ]*) as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". as_fn_error $? "ls -t appears to fail. Make sure there is not a broken alias in your environment" "$LINENO" 5 fi if test "$2" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$2" = conftest.file ) then # Ok. : else as_fn_error $? "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi rm -f conftest.file test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s&\$&$program_suffix&;$program_transform_name" # Double any \ or $. # By default was `s,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` # Expand $ac_aux_dir to an absolute path. am_aux_dir=`cd "$ac_aux_dir" && pwd` if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 $as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if ${ac_cv_path_mkdir+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir (GNU coreutils) '* | \ 'mkdir (coreutils) '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS fi test -d ./--version && rmdir ./--version if test "${ac_cv_path_mkdir+set}" = set; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a # value for MKDIR_P within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. MKDIR_P="$ac_install_sh -d" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 $as_echo "$MKDIR_P" >&6; } for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=1;; esac am_make=${MAKE-make} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 $as_echo_n "checking whether $am_make supports nested variables... " >&6; } if ${am_cv_make_support_nested_variables+:} false; then : $as_echo_n "(cached) " >&6 else if $as_echo 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 $as_echo "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." am__isrc=' -I$(srcdir)' # test to see if srcdir already configured if test -f $srcdir/config.status; then as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE='libccd' VERSION='1.0' cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # mkdir_p='$(MKDIR_P)' # We need awk for the "check" target (and possibly the TAP driver). The # system "awk" is bad on some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar pax cpio none' am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 fi fi # Checks for programs. ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test -z "$CXX"; then if test -n "$CCC"; then CXX=$CCC else if test -n "$ac_tool_prefix"; then for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CXX=$ac_cv_prog_CXX if test -n "$CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 $as_echo "$CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CXX" && break done fi if test -z "$CXX"; then ac_ct_CXX=$CXX for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CXX"; then ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CXX="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CXX=$ac_cv_prog_ac_ct_CXX if test -n "$ac_ct_CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 $as_echo "$ac_ct_CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CXX" && break done if test "x$ac_ct_CXX" = x; then CXX="g++" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CXX=$ac_ct_CXX fi fi fi fi # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C++ compiler works" >&5 $as_echo_n "checking whether the C++ compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C++ compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler default output file name" >&5 $as_echo_n "checking for C++ compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C++ compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 $as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } if ${ac_cv_cxx_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 $as_echo "$ac_cv_cxx_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GXX=yes else GXX= fi ac_test_CXXFLAGS=${CXXFLAGS+set} ac_save_CXXFLAGS=$CXXFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 $as_echo_n "checking whether $CXX accepts -g... " >&6; } if ${ac_cv_prog_cxx_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_cxx_werror_flag=$ac_cxx_werror_flag ac_cxx_werror_flag=yes ac_cv_prog_cxx_g=no CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes else CXXFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : else ac_cxx_werror_flag=$ac_save_cxx_werror_flag CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cxx_werror_flag=$ac_save_cxx_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 $as_echo "$ac_cv_prog_cxx_g" >&6; } if test "$ac_test_CXXFLAGS" = set; then CXXFLAGS=$ac_save_CXXFLAGS elif test $ac_cv_prog_cxx_g = yes; then if test "$GXX" = yes; then CXXFLAGS="-g -O2" else CXXFLAGS="-g" fi else if test "$GXX" = yes; then CXXFLAGS="-O2" else CXXFLAGS= fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 $as_echo_n "checking for style of include used by $am_make... " >&6; } am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 $as_echo "$_am_result" >&6; } rm -f confinc confmf # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then : enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi depcc="$CXX" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CXX_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CXX_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CXX_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CXX_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5 $as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; } CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then am__fastdepCXX_TRUE= am__fastdepCXX_FALSE='#' else am__fastdepCXX_TRUE='#' am__fastdepCXX_FALSE= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 $as_echo_n "checking whether $CC understands -c and -o together... " >&6; } if ${am_cv_prog_cc_c_o+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 $as_echo "$am_cv_prog_cc_c_o" >&6; } if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then : enableval=$enable_shared; p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS=$lt_save_ifs ;; esac else enable_shared=no fi case `pwd` in *\ * | *\ *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 $as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; esac macro_version='2.4.6' macro_revision='2.4.6' ltmain=$ac_aux_dir/ltmain.sh # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac # Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\(["`$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 $as_echo_n "checking how to print strings... " >&6; } # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "" } case $ECHO in printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 $as_echo "printf" >&6; } ;; print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 $as_echo "print -r" >&6; } ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 $as_echo "cat" >&6; } ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 $as_echo_n "checking for a sed that does not truncate output... " >&6; } if ${ac_cv_path_SED+:} false; then : $as_echo_n "(cached) " >&6 else ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for ac_i in 1 2 3 4 5 6 7; do ac_script="$ac_script$as_nl$ac_script" done echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed { ac_script=; unset ac_script;} if test -z "$SED"; then ac_path_SED_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_SED" || continue # Check for GNU ac_path_SED and select it if it is found. # Check for GNU $ac_path_SED case `"$ac_path_SED" --version 2>&1` in *GNU*) ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo '' >> "conftest.nl" "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_SED_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_SED="$ac_path_SED" ac_path_SED_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_SED_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_SED"; then as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 fi else ac_cv_path_SED=$SED fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 $as_echo "$ac_cv_path_SED" >&6; } SED="$ac_cv_path_SED" rm -f conftest.sed test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 $as_echo_n "checking for fgrep... " >&6; } if ${ac_cv_path_FGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 then ac_cv_path_FGREP="$GREP -F" else if test -z "$FGREP"; then ac_path_FGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in fgrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_FGREP" || continue # Check for GNU ac_path_FGREP and select it if it is found. # Check for GNU $ac_path_FGREP case `"$ac_path_FGREP" --version 2>&1` in *GNU*) ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'FGREP' >> "conftest.nl" "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_FGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_FGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_FGREP"; then as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_FGREP=$FGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 $as_echo "$ac_cv_path_FGREP" >&6; } FGREP="$ac_cv_path_FGREP" test -z "$GREP" && GREP=grep # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test yes = "$with_gnu_ld"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if ${lt_cv_prog_gnu_ld+:} false; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 $as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } if ${lt_cv_path_NM+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM=$NM else lt_nm_to_check=${ac_tool_prefix}nm if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. tmp_nm=$ac_dir/$lt_tmp_nm if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then # Check to see if the nm accepts a BSD-compat flag. # Adding the 'sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty case $build_os in mingw*) lt_bad_file=conftest.nm/nofile ;; *) lt_bad_file=/dev/null ;; esac case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in *$lt_bad_file* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break 2 ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break 2 ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS=$lt_save_ifs done : ${lt_cv_path_NM=no} fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 $as_echo "$lt_cv_path_NM" >&6; } if test no != "$lt_cv_path_NM"; then NM=$lt_cv_path_NM else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else if test -n "$ac_tool_prefix"; then for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DUMPBIN"; then ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DUMPBIN=$ac_cv_prog_DUMPBIN if test -n "$DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 $as_echo "$DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$DUMPBIN" && break done fi if test -z "$DUMPBIN"; then ac_ct_DUMPBIN=$DUMPBIN for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DUMPBIN"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN if test -n "$ac_ct_DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 $as_echo "$ac_ct_DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_DUMPBIN" && break done if test "x$ac_ct_DUMPBIN" = x; then DUMPBIN=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DUMPBIN=$ac_ct_DUMPBIN fi fi case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols -headers" ;; *) DUMPBIN=: ;; esac fi if test : != "$DUMPBIN"; then NM=$DUMPBIN fi fi test -z "$NM" && NM=nm { $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 $as_echo_n "checking the name lister ($NM) interface... " >&6; } if ${lt_cv_nm_interface+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 $as_echo "$lt_cv_nm_interface" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } fi # find the maximum length of command line arguments { $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 $as_echo_n "checking the maximum length of command line arguments... " >&6; } if ${lt_cv_sys_max_cmd_len+:} false; then : $as_echo_n "(cached) " >&6 else i=0 teststring=ABCD case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test X`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test 17 != "$i" # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac fi if test -n "$lt_cv_sys_max_cmd_len"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 $as_echo "$lt_cv_sys_max_cmd_len" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } fi max_cmd_len=$lt_cv_sys_max_cmd_len : ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 $as_echo_n "checking how to convert $build file names to $host format... " >&6; } if ${lt_cv_to_host_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac fi to_host_file_cmd=$lt_cv_to_host_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 $as_echo "$lt_cv_to_host_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 $as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } if ${lt_cv_to_tool_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else #assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac fi to_tool_file_cmd=$lt_cv_to_tool_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 $as_echo "$lt_cv_to_tool_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 $as_echo_n "checking for $LD option to reload object files... " >&6; } if ${lt_cv_ld_reload_flag+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_reload_flag='-r' fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 $as_echo "$lt_cv_ld_reload_flag" >&6; } reload_flag=$lt_cv_ld_reload_flag case $reload_flag in "" | " "*) ;; *) reload_flag=" $reload_flag" ;; esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in cygwin* | mingw* | pw32* | cegcc*) if test yes != "$GCC"; then reload_cmds=false fi ;; darwin*) if test yes = "$GCC"; then reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs' else reload_cmds='$LD$reload_flag -o $output$reload_objs' fi ;; esac if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OBJDUMP"; then ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OBJDUMP=$ac_cv_prog_OBJDUMP if test -n "$OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 $as_echo "$OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OBJDUMP"; then ac_ct_OBJDUMP=$OBJDUMP # Extract the first word of "objdump", so it can be a program name with args. set dummy objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OBJDUMP"; then ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OBJDUMP="objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP if test -n "$ac_ct_OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 $as_echo "$ac_ct_OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OBJDUMP" = x; then OBJDUMP="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OBJDUMP=$ac_ct_OBJDUMP fi else OBJDUMP="$ac_cv_prog_OBJDUMP" fi test -z "$OBJDUMP" && OBJDUMP=objdump { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 $as_echo_n "checking how to recognize dependent libraries... " >&6; } if ${lt_cv_deplibs_check_method+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # 'unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # that responds to the $file_magic_cmd with a given extended regex. # If you have 'file' or equivalent on your system and you're not sure # whether 'pass_all' will *always* work, you probably want this one. case $host_os in aix[4-9]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[45]*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. if ( file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[3-9]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd* | bitrig*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; os2*) lt_cv_deplibs_check_method=pass_all ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 $as_echo "$lt_cv_deplibs_check_method" >&6; } file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. set dummy ${ac_tool_prefix}dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DLLTOOL"; then ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DLLTOOL=$ac_cv_prog_DLLTOOL if test -n "$DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 $as_echo "$DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DLLTOOL"; then ac_ct_DLLTOOL=$DLLTOOL # Extract the first word of "dlltool", so it can be a program name with args. set dummy dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DLLTOOL"; then ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DLLTOOL="dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL if test -n "$ac_ct_DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 $as_echo "$ac_ct_DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DLLTOOL" = x; then DLLTOOL="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DLLTOOL=$ac_ct_DLLTOOL fi else DLLTOOL="$ac_cv_prog_DLLTOOL" fi test -z "$DLLTOOL" && DLLTOOL=dlltool { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 $as_echo_n "checking how to associate runtime and link libraries... " >&6; } if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh; # decide which one to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd=$ECHO ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 $as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO if test -n "$ac_tool_prefix"; then for ac_prog in ar do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AR" && break done fi if test -z "$AR"; then ac_ct_AR=$AR for ac_prog in ar do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 $as_echo "$ac_ct_AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_AR" && break done if test "x$ac_ct_AR" = x; then AR="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi fi : ${AR=ar} : ${AR_FLAGS=cru} { $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 $as_echo_n "checking for archiver @FILE support... " >&6; } if ${lt_cv_ar_at_file+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ar_at_file=no cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test 0 -eq "$ac_status"; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test 0 -ne "$ac_status"; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 $as_echo "$lt_cv_ar_at_file" >&6; } if test no = "$lt_cv_ar_at_file"; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi test -z "$STRIP" && STRIP=: if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi test -z "$RANLIB" && RANLIB=: # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in bitrig* | openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Check for command to grab the raw symbol name followed by C symbol from nm. { $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 $as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } if ${lt_cv_sys_global_symbol_pipe+:} false; then : $as_echo_n "(cached) " >&6 else # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[BCDEGRST]' # Regexp to match symbols that can be accessed directly from C. sympat='\([_A-Za-z][_A-Za-z0-9]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[BCDT]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[ABCDGISTW]' ;; hpux*) if test ia64 = "$host_cpu"; then symcode='[ABCDEGRST]' fi ;; irix* | nonstopux*) symcode='[BCDEGRST]' ;; osf*) symcode='[BCDEGQRST]' ;; solaris*) symcode='[BDRT]' ;; sco3.2v5*) symcode='[DT]' ;; sysv4.2uw2*) symcode='[DT]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[ABDT]' ;; sysv4) symcode='[DFNSTU]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[ABCDGIRSTW]' ;; esac if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Gets list of data symbols to import. lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" # Adjust the below global symbol transforms to fixup imported variables. lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" lt_c_name_lib_hook="\ -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" else # Disable hooks by default. lt_cv_sys_global_symbol_to_import= lt_cdecl_hook= lt_c_name_hook= lt_c_name_lib_hook= fi # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n"\ $lt_cdecl_hook\ " -e 's/^T .* \(.*\)$/extern int \1();/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ $lt_c_name_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" # Transform an extracted symbol line into symbol name with lib prefix and # symbol address. lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ $lt_c_name_lib_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function, # D for any global variable and I for any imported variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK '"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ " /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ " /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ " {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ " s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Now try to grab the symbols. nlist=conftest.nm if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE /* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS=conftstm.$ac_objext CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest$ac_exeext; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&5 fi else echo "cannot find nm_test_var in $nlist" >&5 fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 fi else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test yes = "$pipe_works"; then break else lt_cv_sys_global_symbol_pipe= fi done fi if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 $as_echo "failed" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then nm_file_list_spec='@' fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 $as_echo_n "checking for sysroot... " >&6; } # Check whether --with-sysroot was given. if test "${with_sysroot+set}" = set; then : withval=$with_sysroot; else with_sysroot=no fi lt_sysroot= case $with_sysroot in #( yes) if test yes = "$GCC"; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5 $as_echo "$with_sysroot" >&6; } as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 $as_echo "${lt_sysroot:-no}" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5 $as_echo_n "checking for a working dd... " >&6; } if ${ac_cv_path_lt_DD+:} false; then : $as_echo_n "(cached) " >&6 else printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i : ${lt_DD:=$DD} if test -z "$lt_DD"; then ac_path_lt_DD_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in dd; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_lt_DD="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_lt_DD" || continue if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: fi $ac_path_lt_DD_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_lt_DD"; then : fi else ac_cv_path_lt_DD=$lt_DD fi rm -f conftest.i conftest2.i conftest.out fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5 $as_echo "$ac_cv_path_lt_DD" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5 $as_echo_n "checking how to truncate binary pipes... " >&6; } if ${lt_cv_truncate_bin+:} false; then : $as_echo_n "(cached) " >&6 else printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i lt_cv_truncate_bin= if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" fi rm -f conftest.i conftest2.i conftest.out test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5 $as_echo "$lt_cv_truncate_bin" >&6; } # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in $*""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } # Check whether --enable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then : enableval=$enable_libtool_lock; fi test no = "$enable_libtool_lock" || enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out what ABI is being produced by ac_compile, and set mode # options accordingly. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE=32 ;; *ELF-64*) HPUX_IA64_MODE=64 ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then if test yes = "$lt_cv_prog_gnu_ld"; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; mips64*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then emul=elf case `/usr/bin/file conftest.$ac_objext` in *32-bit*) emul="${emul}32" ;; *64-bit*) emul="${emul}64" ;; esac case `/usr/bin/file conftest.$ac_objext` in *MSB*) emul="${emul}btsmip" ;; *LSB*) emul="${emul}ltsmip" ;; esac case `/usr/bin/file conftest.$ac_objext` in *N32*) emul="${emul}n32" ;; esac LD="${LD-ld} -m $emul" fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. Note that the listed cases only cover the # situations where additional linker options are needed (such as when # doing 32-bit compilation for a host where ld defaults to 64-bit, or # vice versa); the common cases where no linker options are needed do # not appear in the list. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `/usr/bin/file conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*linux*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*linux*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -belf" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 $as_echo_n "checking whether the C compiler needs -belf... " >&6; } if ${lt_cv_cc_needs_belf+:} false; then : $as_echo_n "(cached) " >&6 else ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_cc_needs_belf=yes else lt_cv_cc_needs_belf=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 $as_echo "$lt_cv_cc_needs_belf" >&6; } if test yes != "$lt_cv_cc_needs_belf"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS=$SAVE_CFLAGS fi ;; *-*solaris*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*|x86_64-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD=${LD-ld}_sol2 fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks=$enable_libtool_lock if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. set dummy ${ac_tool_prefix}mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$MANIFEST_TOOL"; then ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL if test -n "$MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 $as_echo "$MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_MANIFEST_TOOL"; then ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL # Extract the first word of "mt", so it can be a program name with args. set dummy mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_MANIFEST_TOOL"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL if test -n "$ac_ct_MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 $as_echo "$ac_ct_MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_MANIFEST_TOOL" = x; then MANIFEST_TOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL fi else MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" fi test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 $as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } if ${lt_cv_path_mainfest_tool+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&5 if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 $as_echo "$lt_cv_path_mainfest_tool" >&6; } if test yes != "$lt_cv_path_mainfest_tool"; then MANIFEST_TOOL=: fi case $host_os in rhapsody* | darwin*) if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DSYMUTIL"; then ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DSYMUTIL=$ac_cv_prog_DSYMUTIL if test -n "$DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 $as_echo "$DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DSYMUTIL"; then ac_ct_DSYMUTIL=$DSYMUTIL # Extract the first word of "dsymutil", so it can be a program name with args. set dummy dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DSYMUTIL"; then ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL if test -n "$ac_ct_DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 $as_echo "$ac_ct_DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DSYMUTIL" = x; then DSYMUTIL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DSYMUTIL=$ac_ct_DSYMUTIL fi else DSYMUTIL="$ac_cv_prog_DSYMUTIL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. set dummy ${ac_tool_prefix}nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NMEDIT"; then ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi NMEDIT=$ac_cv_prog_NMEDIT if test -n "$NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 $as_echo "$NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_NMEDIT"; then ac_ct_NMEDIT=$NMEDIT # Extract the first word of "nmedit", so it can be a program name with args. set dummy nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_NMEDIT"; then ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_NMEDIT="nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT if test -n "$ac_ct_NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 $as_echo "$ac_ct_NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_NMEDIT" = x; then NMEDIT=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac NMEDIT=$ac_ct_NMEDIT fi else NMEDIT="$ac_cv_prog_NMEDIT" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. set dummy ${ac_tool_prefix}lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$LIPO"; then ac_cv_prog_LIPO="$LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_LIPO="${ac_tool_prefix}lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi LIPO=$ac_cv_prog_LIPO if test -n "$LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 $as_echo "$LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_LIPO"; then ac_ct_LIPO=$LIPO # Extract the first word of "lipo", so it can be a program name with args. set dummy lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_LIPO"; then ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_LIPO="lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO if test -n "$ac_ct_LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 $as_echo "$ac_ct_LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_LIPO" = x; then LIPO=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac LIPO=$ac_ct_LIPO fi else LIPO="$ac_cv_prog_LIPO" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. set dummy ${ac_tool_prefix}otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL"; then ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL="${ac_tool_prefix}otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL=$ac_cv_prog_OTOOL if test -n "$OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 $as_echo "$OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL"; then ac_ct_OTOOL=$OTOOL # Extract the first word of "otool", so it can be a program name with args. set dummy otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL"; then ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL="otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL if test -n "$ac_ct_OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 $as_echo "$ac_ct_OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL" = x; then OTOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL=$ac_ct_OTOOL fi else OTOOL="$ac_cv_prog_OTOOL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. set dummy ${ac_tool_prefix}otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL64"; then ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL64=$ac_cv_prog_OTOOL64 if test -n "$OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 $as_echo "$OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL64"; then ac_ct_OTOOL64=$OTOOL64 # Extract the first word of "otool64", so it can be a program name with args. set dummy otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL64"; then ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL64="otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 if test -n "$ac_ct_OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 $as_echo "$ac_ct_OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL64" = x; then OTOOL64=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL64=$ac_ct_OTOOL64 fi else OTOOL64="$ac_cv_prog_OTOOL64" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 $as_echo_n "checking for -single_module linker flag... " >&6; } if ${lt_cv_apple_cc_single_mod+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_apple_cc_single_mod=no if test -z "$LT_MULTI_MODULE"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&5 $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&5 # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test 0 = "$_lt_result"; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&5 fi rm -rf libconftest.dylib* rm -f conftest.* fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 $as_echo "$lt_cv_apple_cc_single_mod" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 $as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } if ${lt_cv_ld_exported_symbols_list+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_ld_exported_symbols_list=yes else lt_cv_ld_exported_symbols_list=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 $as_echo "$lt_cv_ld_exported_symbols_list" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 $as_echo_n "checking for -force_load linker flag... " >&6; } if ${lt_cv_ld_force_load+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 echo "$AR cru libconftest.a conftest.o" >&5 $AR cru libconftest.a conftest.o 2>&5 echo "$RANLIB libconftest.a" >&5 $RANLIB libconftest.a 2>&5 cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&5 elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then lt_cv_ld_force_load=yes else cat conftest.err >&5 fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 $as_echo "$lt_cv_ld_force_load" >&6; } case $host_os in rhapsody* | darwin1.[012]) _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[91]*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; 10.[012][,.]*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test yes = "$lt_cv_apple_cc_single_mod"; then _lt_dar_single_mod='$single_module' fi if test yes = "$lt_cv_ld_exported_symbols_list"; then _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' fi if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac # func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x$2 in x) ;; *:) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" ;; x:*) eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" ;; *::*) eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" ;; *) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" ;; esac } ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in dlfcn.h do : ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default " if test "x$ac_cv_header_dlfcn_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_DLFCN_H 1 _ACEOF fi done func_stripname_cnf () { case $2 in .*) func_stripname_result=`$ECHO "$3" | $SED "s%^$1%%; s%\\\\$2\$%%"`;; *) func_stripname_result=`$ECHO "$3" | $SED "s%^$1%%; s%$2\$%%"`;; esac } # func_stripname_cnf # Set options enable_dlopen=no enable_win32_dll=no # Check whether --enable-static was given. if test "${enable_static+set}" = set; then : enableval=$enable_static; p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS=$lt_save_ifs ;; esac else enable_static=yes fi # Check whether --with-pic was given. if test "${with_pic+set}" = set; then : withval=$with_pic; lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for lt_pkg in $withval; do IFS=$lt_save_ifs if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS=$lt_save_ifs ;; esac else pic_mode=default fi # Check whether --enable-fast-install was given. if test "${enable_fast_install+set}" = set; then : enableval=$enable_fast_install; p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS=$lt_save_ifs ;; esac else enable_fast_install=yes fi shared_archive_member_spec= case $host,$enable_shared in power*-*-aix[5-9]*,yes) { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5 $as_echo_n "checking which variant of shared library versioning to provide... " >&6; } # Check whether --with-aix-soname was given. if test "${with_aix_soname+set}" = set; then : withval=$with_aix_soname; case $withval in aix|svr4|both) ;; *) as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5 ;; esac lt_cv_with_aix_soname=$with_aix_soname else if ${lt_cv_with_aix_soname+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_with_aix_soname=aix fi with_aix_soname=$lt_cv_with_aix_soname fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5 $as_echo "$with_aix_soname" >&6; } if test aix != "$with_aix_soname"; then # For the AIX way of multilib, we name the shared archive member # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, # the AIX toolchain works better with OBJECT_MODE set (default 32). if test 64 = "${OBJECT_MODE-32}"; then shared_archive_member_spec=shr_64 else shared_archive_member_spec=shr fi fi ;; *) with_aix_soname=aix ;; esac # This can be used to rebuild libtool when needed LIBTOOL_DEPS=$ltmain # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' test -z "$LN_S" && LN_S="ln -s" if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 $as_echo_n "checking for objdir... " >&6; } if ${lt_cv_objdir+:} false; then : $as_echo_n "(cached) " >&6 else rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 $as_echo "$lt_cv_objdir" >&6; } objdir=$lt_cv_objdir cat >>confdefs.h <<_ACEOF #define LT_OBJDIR "$lt_cv_objdir/" _ACEOF case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a '.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld=$lt_cv_prog_gnu_ld old_CC=$CC old_CFLAGS=$CFLAGS # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o func_cc_basename $compiler cc_basename=$func_cc_basename_result # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 $as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD=$MAGIC_CMD lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/${ac_tool_prefix}file"; then lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS=$lt_save_ifs MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac fi MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 $as_echo_n "checking for file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD=$MAGIC_CMD lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/file"; then lt_cv_path_MAGIC_CMD=$ac_dir/"file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS=$lt_save_ifs MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac fi MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else MAGIC_CMD=: fi fi fi ;; esac # Use C for the default configuration in the libtool script lt_save_CC=$CC ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o objext=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* if test -n "$compiler"; then lt_prog_compiler_no_builtin_flag= if test yes = "$GCC"; then case $cc_basename in nvcc*) lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; *) lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 $as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 $as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" else : fi fi lt_prog_compiler_wl= lt_prog_compiler_pic= lt_prog_compiler_static= if test yes = "$GCC"; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi lt_prog_compiler_pic='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic='-DDLL_EXPORT' case $host_os in os2*) lt_prog_compiler_static='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. lt_prog_compiler_static= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) lt_prog_compiler_pic='-fPIC' ;; esac ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic=-Kconform_pic fi ;; *) lt_prog_compiler_pic='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 lt_prog_compiler_wl='-Xlinker ' if test -n "$lt_prog_compiler_pic"; then lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl='-Wl,' if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' fi ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' case $cc_basename in nagfor*) # NAG Fortran compiler lt_prog_compiler_wl='-Wl,-Wl,,' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; esac ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' case $host_os in os2*) lt_prog_compiler_static='$wl-static' ;; esac ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static='$wl-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64, which still supported -KPIC. ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; # Lahey Fortran 8.1. lf95*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='--shared' lt_prog_compiler_static='--static' ;; nagfor*) # NAG Fortran compiler lt_prog_compiler_wl='-Wl,-Wl,,' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; tcc*) # Fabrice Bellard et al's Tiny C Compiler lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; ccc*) lt_prog_compiler_wl='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-qpic' lt_prog_compiler_static='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='' ;; *Sun\ F* | *Sun*Fortran*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Wl,' ;; *Intel*\ [CF]*Compiler*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; *Portland\ Group*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; esac ;; esac ;; newsos6) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static='-non_shared' ;; rdos*) lt_prog_compiler_static='-non_shared' ;; solaris*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) lt_prog_compiler_wl='-Qoption ld ';; *) lt_prog_compiler_wl='-Wl,';; esac ;; sunos4*) lt_prog_compiler_wl='-Qoption ld ' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic='-Kconform_pic' lt_prog_compiler_static='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; unicos*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_can_build_shared=no ;; uts4*) lt_prog_compiler_pic='-pic' lt_prog_compiler_static='-Bstatic' ;; *) lt_prog_compiler_can_build_shared=no ;; esac fi case $host_os in # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; *) lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if ${lt_cv_prog_compiler_pic+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic=$lt_prog_compiler_pic fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 $as_echo "$lt_cv_prog_compiler_pic" >&6; } lt_prog_compiler_pic=$lt_cv_prog_compiler_pic # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } if ${lt_cv_prog_compiler_pic_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic -DPIC" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 $as_echo "$lt_cv_prog_compiler_pic_works" >&6; } if test yes = "$lt_cv_prog_compiler_pic_works"; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; esac else lt_prog_compiler_pic= lt_prog_compiler_can_build_shared=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if ${lt_cv_prog_compiler_static_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works=yes fi else lt_cv_prog_compiler_static_works=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 $as_echo "$lt_cv_prog_compiler_static_works" >&6; } if test yes = "$lt_cv_prog_compiler_static_works"; then : else lt_prog_compiler_static= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } hard_links=nottested if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test no = "$hard_links"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } runpath_var= allow_undefined_flag= always_export_symbols=no archive_cmds= archive_expsym_cmds= compiler_needs_object=no enable_shared_with_static_runtimes=no export_dynamic_flag_spec= export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' hardcode_automatic=no hardcode_direct=no hardcode_direct_absolute=no hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_minus_L=no hardcode_shlibpath_var=unsupported inherit_rpath=no link_all_deplibs=unknown module_cmds= module_expsym_cmds= old_archive_from_new_cmds= old_archive_from_expsyms_cmds= thread_safe_flag_spec= whole_archive_flag_spec= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ' (' and ')$', so one must not match beginning or # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', # as well as any symbol that contains 'd'. exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test yes != "$GCC"; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd* | bitrig*) with_gnu_ld=no ;; linux* | k*bsd*-gnu | gnu*) link_all_deplibs=no ;; esac ld_shlibs=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test yes = "$with_gnu_ld"; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; *\ \(GNU\ Binutils\)\ [3-9]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test yes = "$lt_use_gnu_ld_interface"; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='$wl' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' export_dynamic_flag_spec='$wl--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else whole_archive_flag_spec= fi supports_anon_versioning=no case `$LD -v | $SED -e 's/(^)\+)\s\+//' 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test ia64 != "$host_cpu"; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else ld_shlibs=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' export_dynamic_flag_spec='$wl--export-all-symbols' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs=no fi ;; haiku*) archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' link_all_deplibs=yes ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported shrext_cmds=.dll archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' enable_shared_with_static_runtimes=yes ;; interix[3-9]*) hardcode_direct=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='$wl-rpath,$libdir' export_dynamic_flag_spec='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test linux-dietlibc = "$host_os"; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test no = "$tmp_diet" then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 whole_archive_flag_spec= tmp_sharedflag='--shared' ;; nagfor*) # NAGFOR 5.3 tmp_sharedflag='-Wl,-shared' ;; xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi case $cc_basename in tcc*) export_dynamic_flag_spec='-rdynamic' ;; xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test yes = "$supports_anon_versioning"; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else ld_shlibs=no fi ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac ;; sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct=yes hardcode_shlibpath_var=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac if test no = "$ld_shlibs"; then runpath_var= hardcode_libdir_flag_spec= export_dynamic_flag_spec= whole_archive_flag_spec= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag=unsupported always_export_symbols=yes archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix[4-9]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then aix_use_runtimelinking=yes break fi done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds='' hardcode_direct=yes hardcode_direct_absolute=yes hardcode_libdir_separator=':' link_all_deplibs=yes file_list_spec='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # traditional, no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. hardcode_direct=no hardcode_direct_absolute=no ;; esac if test yes = "$GCC"; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag="$shared_flag "'$wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi export_dynamic_flag_spec='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an # empty executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=/usr/lib:/lib fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=/usr/lib:/lib fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag=' $wl-bernotok' allow_undefined_flag=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec='$convenience' fi archive_cmds_need_lc=yes archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols archive_expsym_cmds="$archive_expsym_cmds"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; bsdi[45]*) export_dynamic_flag_spec=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported always_export_symbols=yes file_list_spec='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, )='true' enable_shared_with_static_runtimes=yes exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib old_postinstall_cmds='chmod 644 $oldlib' postlink_cmds='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_from_new_cmds='true' # FIXME: Should let the user specify the lib program. old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' enable_shared_with_static_runtimes=yes ;; esac ;; darwin* | rhapsody*) archive_cmds_need_lc=no hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported if test yes = "$lt_cv_ld_force_load"; then whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec='' fi link_all_deplibs=yes allow_undefined_flag=$_lt_dar_allow_undefined case $cc_basename in ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" archive_expsym_cmds="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" module_expsym_cmds="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" else ld_shlibs=no fi ;; dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9*) if test yes = "$GCC"; then archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes export_dynamic_flag_spec='$wl-E' ;; hpux10*) if test yes,no = "$GCC,$with_gnu_ld"; then archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test no = "$with_gnu_ld"; then hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test yes,no = "$GCC,$with_gnu_ld"; then case $host_cpu in hppa*64*) archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 $as_echo_n "checking if $CC understands -b... " >&6; } if ${lt_cv_prog_compiler__b+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler__b=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -b" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler__b=yes fi else lt_cv_prog_compiler__b=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 $as_echo "$lt_cv_prog_compiler__b" >&6; } if test yes = "$lt_cv_prog_compiler__b"; then archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi ;; esac fi if test no = "$with_gnu_ld"; then hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_direct=no hardcode_shlibpath_var=no ;; *) hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test yes = "$GCC"; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 $as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } if ${lt_cv_irix_exported_symbol+:} false; then : $as_echo_n "(cached) " >&6 else save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int foo (void) { return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_irix_exported_symbol=yes else lt_cv_irix_exported_symbol=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 $as_echo "$lt_cv_irix_exported_symbol" >&6; } if test yes = "$lt_cv_irix_exported_symbol"; then archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' fi link_all_deplibs=no else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: inherit_rpath=yes link_all_deplibs=yes ;; linux*) case $cc_basename in tcc*) # Fabrice Bellard et al's Tiny C Compiler ld_shlibs=yes archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; *nto* | *qnx*) ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes hardcode_shlibpath_var=no hardcode_direct_absolute=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec='$wl-rpath,$libdir' export_dynamic_flag_spec='$wl-E' else archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='$wl-rpath,$libdir' fi else ld_shlibs=no fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported shrext_cmds=.dll archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' enable_shared_with_static_runtimes=yes ;; osf3*) if test yes = "$GCC"; then allow_undefined_flag=' $wl-expect_unresolved $wl\*' archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test yes = "$GCC"; then allow_undefined_flag=' $wl-expect_unresolved $wl\*' archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi archive_cmds_need_lc='no' hardcode_libdir_separator=: ;; solaris*) no_undefined_flag=' -z defs' if test yes = "$GCC"; then wlarc='$wl' archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='$wl' archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi hardcode_libdir_flag_spec='-R$libdir' hardcode_shlibpath_var=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. GCC discards it without '$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test yes = "$GCC"; then whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' else whole_archive_flag_spec='-z allextract$convenience -z defaultextract' fi ;; esac link_all_deplibs=yes ;; sunos4*) if test sequent = "$host_vendor"; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; sysv4) case $host_vendor in sni) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds='$CC -r -o $output$reload_objs' hardcode_direct=no ;; motorola) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; sysv4.3*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag='$wl-z,text' archive_cmds_need_lc=no hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag='$wl-z,text' allow_undefined_flag='$wl-z,nodefs' archive_cmds_need_lc=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='$wl-R,$libdir' hardcode_libdir_separator=':' link_all_deplibs=yes export_dynamic_flag_spec='$wl-Bexport' runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; *) ld_shlibs=no ;; esac if test sni = "$host_vendor"; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) export_dynamic_flag_spec='$wl-Blargedynsym' ;; esac fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 $as_echo "$ld_shlibs" >&6; } test no = "$ld_shlibs" && can_build_shared=no with_gnu_ld=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc" in x|xyes) # Assume -lc should be added archive_cmds_need_lc=yes if test yes,yes = "$GCC,$enable_shared"; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } if ${lt_cv_archive_cmds_need_lc+:} false; then : $as_echo_n "(cached) " >&6 else $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl pic_flag=$lt_prog_compiler_pic compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag allow_undefined_flag= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then lt_cv_archive_cmds_need_lc=no else lt_cv_archive_cmds_need_lc=yes fi allow_undefined_flag=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 $as_echo "$lt_cv_archive_cmds_need_lc" >&6; } archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc ;; esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } if test yes = "$GCC"; then case $host_os in darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; *) lt_awk_arg='/^libraries:/' ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;; *) lt_sed_strip_eq='s|=/|/|g' ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary... lt_tmp_lt_search_path_spec= lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` # ...but if some path component already ends with the multilib dir we assume # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). case "$lt_multi_os_dir; $lt_search_path_spec " in "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) lt_multi_os_dir= ;; esac for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" elif test -n "$lt_multi_os_dir"; then test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS = " "; FS = "/|\n";} { lt_foo = ""; lt_count = 0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo = "/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[lt_foo]++; } if (lt_freq[lt_foo] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's|/\([A-Za-z]:\)|\1|g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='$libname$release$shared_ext$major' ;; aix[4-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line '#! .'. This would cause the generated library to # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # Using Import Files as archive members, it is possible to support # filename-based versioning of shared library archives on AIX. While # this would work for both with and without runtime linking, it will # prevent static linking of such archives. So we do filename-based # shared library versioning with .so extension only, which is used # when both runtime linking and shared linking is enabled. # Unfortunately, runtime linking may impact performance, so we do # not want this to be the default eventually. Also, we use the # versioned .so libs for executables only if there is the -brtl # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. # To allow for filename-based versioning support, we need to create # libNAME.so.V as an archive file, containing: # *) an Import File, referring to the versioned filename of the # archive as well as the shared archive member, telling the # bitwidth (32 or 64) of that shared object, and providing the # list of exported symbols of that shared object, eventually # decorated with the 'weak' keyword # *) the shared object with the F_LOADONLY flag set, to really avoid # it being seen by the linker. # At run time we better use the real file rather than another symlink, # but for link time we create the symlink libNAME.so -> libNAME.so.V case $with_aix_soname,$aix_use_runtimelinking in # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. aix,yes) # traditional libtool dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; aix,no) # traditional AIX only dynamic_linker='AIX lib.a(lib.so.V)' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' ;; svr4,*) # full svr4 only dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,yes) # both, prefer svr4 dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # unpreferred sharedlib libNAME.a needs extra handling postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,no) # both, prefer aix dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' ;; esac shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' library_names_spec='$libname.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[23].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[3-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; linux*android*) version_type=none # Android doesn't support versioned libraries. need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext' soname_spec='$libname$release$shared_ext' finish_cmds= shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes dynamic_linker='Android linker' # Don't embed -rpath directories since the linker doesn't support them. hardcode_libdir_flag_spec='-L$libdir' ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH if ${lt_cv_shlibpath_overrides_runpath+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : lt_cv_shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir fi shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not # being certain /sbin/ldconfig is available, command # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, # even though it is searched at run-time. Try to do the best guess by # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd* | bitrig*) version_type=sunos sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then need_version=no else need_version=yes fi library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no # OS/2 can only load a DLL with a base name of 8 characters or less. soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; v=$($ECHO $release$versuffix | tr -d .-); n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); $ECHO $n$v`$shared_ext' library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' shlibpath_var=BEGINLIBPATH sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=sco need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi # remember unaugmented sys_lib_dlsearch_path content for libtool script decls... configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec # ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" # to be used as default LT_SYS_LIBRARY_PATH value in generated libtool configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action= if test -n "$hardcode_libdir_flag_spec" || test -n "$runpath_var" || test yes = "$hardcode_automatic"; then # We can hardcode non-existent directories. if test no != "$hardcode_direct" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" && test no != "$hardcode_minus_L"; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action=unsupported fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 $as_echo "$hardcode_action" >&6; } if test relink = "$hardcode_action" || test yes = "$inherit_rpath"; then # Fast installation is not supported enable_fast_install=no elif test yes = "$shlibpath_overrides_runpath" || test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi if test yes != "$enable_dlopen"; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen=load_add_on lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen=LoadLibrary lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen=dlopen lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl else lt_cv_dlopen=dyld lt_cv_dlopen_libs= lt_cv_dlopen_self=yes fi ;; tpf*) # Don't try to run any link tests for TPF. We know it's impossible # because TPF is a cross-compiler, and we know how we open DSOs. lt_cv_dlopen=dlopen lt_cv_dlopen_libs= lt_cv_dlopen_self=no ;; *) ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" if test "x$ac_cv_func_shl_load" = xyes; then : lt_cv_dlopen=shl_load else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } if ${ac_cv_lib_dld_shl_load+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_shl_load=yes else ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes; then : lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld else ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" if test "x$ac_cv_func_dlopen" = xyes; then : lt_cv_dlopen=dlopen else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 $as_echo_n "checking for dlopen in -lsvld... " >&6; } if ${ac_cv_lib_svld_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_svld_dlopen=yes else ac_cv_lib_svld_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 $as_echo "$ac_cv_lib_svld_dlopen" >&6; } if test "x$ac_cv_lib_svld_dlopen" = xyes; then : lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 $as_echo_n "checking for dld_link in -ldld... " >&6; } if ${ac_cv_lib_dld_dld_link+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dld_link (); int main () { return dld_link (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_dld_link=yes else ac_cv_lib_dld_dld_link=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 $as_echo "$ac_cv_lib_dld_dld_link" >&6; } if test "x$ac_cv_lib_dld_dld_link" = xyes; then : lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld fi fi fi fi fi fi ;; esac if test no = "$lt_cv_dlopen"; then enable_dlopen=no else enable_dlopen=yes fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS=$CPPFLAGS test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS=$LDFLAGS wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS=$LIBS LIBS="$lt_cv_dlopen_libs $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 $as_echo_n "checking whether a program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self+:} false; then : $as_echo_n "(cached) " >&6 else if test yes = "$cross_compiling"; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed lt_cv_dlopen_self=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 $as_echo "$lt_cv_dlopen_self" >&6; } if test yes = "$lt_cv_dlopen_self"; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 $as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self_static+:} false; then : $as_echo_n "(cached) " >&6 else if test yes = "$cross_compiling"; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed lt_cv_dlopen_self_static=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 $as_echo "$lt_cv_dlopen_self_static" >&6; } fi CPPFLAGS=$save_CPPFLAGS LDFLAGS=$save_LDFLAGS LIBS=$save_LIBS ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi striplib= old_striplib= { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 $as_echo_n "checking whether stripping libraries is possible... " >&6; } if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP"; then striplib="$STRIP -x" old_striplib="$STRIP -S" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac fi # Report what library types will actually be built { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 $as_echo_n "checking if libtool supports shared libraries... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 $as_echo "$can_build_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 $as_echo_n "checking whether to build shared libraries... " >&6; } test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[4-9]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 $as_echo "$enable_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 $as_echo_n "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 $as_echo "$enable_static" >&6; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC=$lt_save_CC if test -n "$CXX" && ( test no != "$CXX" && ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || (test g++ != "$CXX"))); then ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 $as_echo_n "checking how to run the C++ preprocessor... " >&6; } if test -z "$CXXCPP"; then if ${ac_cv_prog_CXXCPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CXXCPP needs to be expanded for CXXCPP in "$CXX -E" "/lib/cpp" do ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CXXCPP=$CXXCPP fi CXXCPP=$ac_cv_prog_CXXCPP else ac_cv_prog_CXXCPP=$CXXCPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 $as_echo "$CXXCPP" >&6; } ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu else _lt_caught_CXX_error=yes fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu archive_cmds_need_lc_CXX=no allow_undefined_flag_CXX= always_export_symbols_CXX=no archive_expsym_cmds_CXX= compiler_needs_object_CXX=no export_dynamic_flag_spec_CXX= hardcode_direct_CXX=no hardcode_direct_absolute_CXX=no hardcode_libdir_flag_spec_CXX= hardcode_libdir_separator_CXX= hardcode_minus_L_CXX=no hardcode_shlibpath_var_CXX=unsupported hardcode_automatic_CXX=no inherit_rpath_CXX=no module_cmds_CXX= module_expsym_cmds_CXX= link_all_deplibs_CXX=unknown old_archive_cmds_CXX=$old_archive_cmds reload_flag_CXX=$reload_flag reload_cmds_CXX=$reload_cmds no_undefined_flag_CXX= whole_archive_flag_spec_CXX= enable_shared_with_static_runtimes_CXX=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o objext_CXX=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_caught_CXX_error"; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} CFLAGS=$CXXFLAGS compiler=$CC compiler_CXX=$CC func_cc_basename $compiler cc_basename=$func_cc_basename_result if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test yes = "$GXX"; then lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin' else lt_prog_compiler_no_builtin_flag_CXX= fi if test yes = "$GXX"; then # Set up default GNU C++ configuration # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test yes = "$with_gnu_ld"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if ${lt_cv_prog_gnu_ld+:} false; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test yes = "$with_gnu_ld"; then archive_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='$wl' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec_CXX=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else whole_archive_flag_spec_CXX= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } ld_shlibs_CXX=yes case $host_os in aix3*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aix[4-9]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds_CXX='' hardcode_direct_CXX=yes hardcode_direct_absolute_CXX=yes hardcode_libdir_separator_CXX=':' link_all_deplibs_CXX=yes file_list_spec_CXX='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. hardcode_direct_CXX=no hardcode_direct_absolute_CXX=no ;; esac if test yes = "$GXX"; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct_CXX=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L_CXX=yes hardcode_libdir_flag_spec_CXX='-L$libdir' hardcode_libdir_separator_CXX= fi esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag=$shared_flag' $wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi export_dynamic_flag_spec_CXX='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. always_export_symbols_CXX=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. # The "-G" linker flag allows undefined symbols. no_undefined_flag_CXX='-bernotok' # Determine the default libpath from the value encoded in an empty # executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath__CXX+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX=/usr/lib:/lib fi fi aix_libpath=$lt_cv_aix_libpath__CXX fi hardcode_libdir_flag_spec_CXX='$wl-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then hardcode_libdir_flag_spec_CXX='$wl-R $libdir:/usr/lib:/lib' allow_undefined_flag_CXX="-z nodefs" archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath__CXX+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX=/usr/lib:/lib fi fi aix_libpath=$lt_cv_aix_libpath__CXX fi hardcode_libdir_flag_spec_CXX='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag_CXX=' $wl-bernotok' allow_undefined_flag_CXX=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. whole_archive_flag_spec_CXX='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec_CXX='$convenience' fi archive_cmds_need_lc_CXX=yes archive_expsym_cmds_CXX='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$RM -r $output_objdir/$realname.d' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag_CXX=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else ld_shlibs_CXX=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in ,cl* | no,cl*) # Native MSVC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec_CXX=' ' allow_undefined_flag_CXX=unsupported always_export_symbols_CXX=yes file_list_spec_CXX='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. archive_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' archive_expsym_cmds_CXX='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, CXX)='true' enable_shared_with_static_runtimes_CXX=yes # Don't use ranlib old_postinstall_cmds_CXX='chmod 644 $oldlib' postlink_cmds_CXX='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ func_to_tool_file "$lt_outputfile"~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec_CXX='-L$libdir' export_dynamic_flag_spec_CXX='$wl--export-all-symbols' allow_undefined_flag_CXX=unsupported always_export_symbols_CXX=no enable_shared_with_static_runtimes_CXX=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... archive_expsym_cmds_CXX='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs_CXX=no fi ;; esac ;; darwin* | rhapsody*) archive_cmds_need_lc_CXX=no hardcode_direct_CXX=no hardcode_automatic_CXX=yes hardcode_shlibpath_var_CXX=unsupported if test yes = "$lt_cv_ld_force_load"; then whole_archive_flag_spec_CXX='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec_CXX='' fi link_all_deplibs_CXX=yes allow_undefined_flag_CXX=$_lt_dar_allow_undefined case $cc_basename in ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" archive_expsym_cmds_CXX="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" module_expsym_cmds_CXX="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" if test yes != "$lt_cv_apple_cc_single_mod"; then archive_cmds_CXX="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" archive_expsym_cmds_CXX="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" fi else ld_shlibs_CXX=no fi ;; os2*) hardcode_libdir_flag_spec_CXX='-L$libdir' hardcode_minus_L_CXX=yes allow_undefined_flag_CXX=unsupported shrext_cmds=.dll archive_cmds_CXX='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' archive_expsym_cmds_CXX='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' old_archive_From_new_cmds_CXX='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' enable_shared_with_static_runtimes_CXX=yes ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF ld_shlibs_CXX=no ;; freebsd-elf*) archive_cmds_need_lc_CXX=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions ld_shlibs_CXX=yes ;; haiku*) archive_cmds_CXX='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' link_all_deplibs_CXX=yes ;; hpux9*) hardcode_libdir_flag_spec_CXX='$wl+b $wl$libdir' hardcode_libdir_separator_CXX=: export_dynamic_flag_spec_CXX='$wl-E' hardcode_direct_CXX=yes hardcode_minus_L_CXX=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aCC*) archive_cmds_CXX='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then archive_cmds_CXX='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; hpux10*|hpux11*) if test no = "$with_gnu_ld"; then hardcode_libdir_flag_spec_CXX='$wl+b $wl$libdir' hardcode_libdir_separator_CXX=: case $host_cpu in hppa*64*|ia64*) ;; *) export_dynamic_flag_spec_CXX='$wl-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) hardcode_direct_CXX=no hardcode_shlibpath_var_CXX=no ;; *) hardcode_direct_CXX=yes hardcode_direct_absolute_CXX=yes hardcode_minus_L_CXX=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aCC*) case $host_cpu in hppa*64*) archive_cmds_CXX='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) archive_cmds_CXX='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) archive_cmds_CXX='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then case $host_cpu in hppa*64*) archive_cmds_CXX='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) archive_cmds_CXX='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) archive_cmds_CXX='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; interix[3-9]*) hardcode_direct_CXX=no hardcode_shlibpath_var_CXX=no hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' export_dynamic_flag_spec_CXX='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds_CXX='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' fi fi link_all_deplibs_CXX=yes ;; esac hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' hardcode_libdir_separator_CXX=: inherit_rpath_CXX=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac archive_cmds_need_lc_CXX=no hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' whole_archive_flag_spec_CXX='$wl--whole-archive$convenience $wl--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [1-5].* | *pgcpp\ [1-5].*) prelink_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' old_archive_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' archive_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac hardcode_libdir_flag_spec_CXX='$wl--rpath $wl$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' whole_archive_flag_spec_CXX='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' ;; cxx*) # Compaq C++ archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec_CXX='-rpath $libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' archive_cmds_CXX='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then archive_expsym_cmds_CXX='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 no_undefined_flag_CXX=' -zdefs' archive_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' archive_expsym_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' hardcode_libdir_flag_spec_CXX='-R$libdir' whole_archive_flag_spec_CXX='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object_CXX=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; m88k*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= hardcode_libdir_flag_spec_CXX='-R$libdir' hardcode_direct_CXX=yes hardcode_shlibpath_var_CXX=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) ld_shlibs_CXX=yes ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then hardcode_direct_CXX=yes hardcode_shlibpath_var_CXX=no hardcode_direct_absolute_CXX=yes archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' export_dynamic_flag_spec_CXX='$wl-E' whole_archive_flag_spec_CXX=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else ld_shlibs_CXX=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' hardcode_libdir_separator_CXX=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; *) old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; cxx*) case $host in osf3*) allow_undefined_flag_CXX=' $wl-expect_unresolved $wl\*' archive_cmds_CXX='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' ;; *) allow_undefined_flag_CXX=' -expect_unresolved \*' archive_cmds_CXX='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ $RM $lib.exp' hardcode_libdir_flag_spec_CXX='-rpath $libdir' ;; esac hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes,no = "$GXX,$with_gnu_ld"; then allow_undefined_flag_CXX=' $wl-expect_unresolved $wl\*' case $host in osf3*) archive_cmds_CXX='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; *) archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; esac hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ archive_cmds_need_lc_CXX=yes no_undefined_flag_CXX=' -zdefs' archive_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' hardcode_libdir_flag_spec_CXX='-R$libdir' hardcode_shlibpath_var_CXX=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) whole_archive_flag_spec_CXX='-z allextract$convenience -z defaultextract' ;; esac link_all_deplibs_CXX=yes output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test yes,no = "$GXX,$with_gnu_ld"; then no_undefined_flag_CXX=' $wl-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # g++ 2.7 appears to require '-G' NOT '-shared' on this # platform. archive_cmds_CXX='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' fi hardcode_libdir_flag_spec_CXX='$wl-R $wl$libdir' case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) whole_archive_flag_spec_CXX='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag_CXX='$wl-z,text' archive_cmds_need_lc_CXX=no hardcode_shlibpath_var_CXX=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) archive_cmds_CXX='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds_CXX='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag_CXX='$wl-z,text' allow_undefined_flag_CXX='$wl-z,nodefs' archive_cmds_need_lc_CXX=no hardcode_shlibpath_var_CXX=no hardcode_libdir_flag_spec_CXX='$wl-R,$libdir' hardcode_libdir_separator_CXX=':' link_all_deplibs_CXX=yes export_dynamic_flag_spec_CXX='$wl-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) archive_cmds_CXX='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' old_archive_cmds_CXX='$CC -Tprelink_objects $oldobjs~ '"$old_archive_cmds_CXX" reload_cmds_CXX='$CC -Tprelink_objects $reload_objs~ '"$reload_cmds_CXX" ;; *) archive_cmds_CXX='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 $as_echo "$ld_shlibs_CXX" >&6; } test no = "$ld_shlibs_CXX" && can_build_shared=no GCC_CXX=$GXX LD_CXX=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... # Dependencies to place before and after the object being linked: predep_objects_CXX= postdep_objects_CXX= predeps_CXX= postdeps_CXX= compiler_lib_search_path_CXX= cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF _lt_libdeps_save_CFLAGS=$CFLAGS case "$CC $CFLAGS " in #( *\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; *\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; *\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; esac if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case $prev$p in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test x-L = "$p" || test x-R = "$p"; then prev=$p continue fi # Expand the sysroot to ease extracting the directories later. if test -z "$prev"; then case $p in -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; esac fi case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac if test no = "$pre_test_object_deps_done"; then case $prev in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$compiler_lib_search_path_CXX"; then compiler_lib_search_path_CXX=$prev$p else compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} $prev$p" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$postdeps_CXX"; then postdeps_CXX=$prev$p else postdeps_CXX="${postdeps_CXX} $prev$p" fi fi prev= ;; *.lto.$objext) ;; # Ignore GCC LTO objects *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test no = "$pre_test_object_deps_done"; then if test -z "$predep_objects_CXX"; then predep_objects_CXX=$p else predep_objects_CXX="$predep_objects_CXX $p" fi else if test -z "$postdep_objects_CXX"; then postdep_objects_CXX=$p else postdep_objects_CXX="$postdep_objects_CXX $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling CXX test program" fi $RM -f confest.$objext CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken case $host_os in interix[3-9]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. predep_objects_CXX= postdep_objects_CXX= postdeps_CXX= ;; esac case " $postdeps_CXX " in *" -lc "*) archive_cmds_need_lc_CXX=no ;; esac compiler_lib_search_dirs_CXX= if test -n "${compiler_lib_search_path_CXX}"; then compiler_lib_search_dirs_CXX=`echo " ${compiler_lib_search_path_CXX}" | $SED -e 's! -L! !g' -e 's!^ !!'` fi lt_prog_compiler_wl_CXX= lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX= # C++ specific cases for pic, static, wl, etc. if test yes = "$GXX"; then lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_CXX='-Bstatic' fi lt_prog_compiler_pic_CXX='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic_CXX='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic_CXX='-DDLL_EXPORT' case $host_os in os2*) lt_prog_compiler_static_CXX='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic_CXX='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all lt_prog_compiler_pic_CXX= ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. lt_prog_compiler_static_CXX= ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic_CXX=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) lt_prog_compiler_pic_CXX='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic_CXX='-fPIC -shared' ;; *) lt_prog_compiler_pic_CXX='-fPIC' ;; esac else case $host_os in aix[4-9]*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_CXX='-Bstatic' else lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic_CXX='-DDLL_EXPORT' ;; dgux*) case $cc_basename in ec++*) lt_prog_compiler_pic_CXX='-KPIC' ;; ghcx*) # Green Hills C++ Compiler lt_prog_compiler_pic_CXX='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='$wl-a ${wl}archive' if test ia64 != "$host_cpu"; then lt_prog_compiler_pic_CXX='+Z' fi ;; aCC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='$wl-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic_CXX='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # KAI C++ Compiler lt_prog_compiler_wl_CXX='--backend -Wl,' lt_prog_compiler_pic_CXX='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64, which still supported -KPIC. lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-fPIC' lt_prog_compiler_static_CXX='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-fpic' lt_prog_compiler_static_CXX='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX='-non_shared' ;; xlc* | xlC* | bgxl[cC]* | mpixl[cC]*) # IBM XL 8.0, 9.0 on PPC and BlueGene lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-qpic' lt_prog_compiler_static_CXX='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' lt_prog_compiler_wl_CXX='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) lt_prog_compiler_pic_CXX='-W c,exportall' ;; *) ;; esac ;; netbsd* | netbsdelf*-gnu) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic_CXX='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) lt_prog_compiler_wl_CXX='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 lt_prog_compiler_pic_CXX='-pic' ;; cxx*) # Digital/Compaq C++ lt_prog_compiler_wl_CXX='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' lt_prog_compiler_wl_CXX='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler lt_prog_compiler_pic_CXX='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x lt_prog_compiler_pic_CXX='-pic' lt_prog_compiler_static_CXX='-Bstatic' ;; lcc*) # Lucid lt_prog_compiler_pic_CXX='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 lt_prog_compiler_pic_CXX='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) lt_prog_compiler_can_build_shared_CXX=no ;; esac fi case $host_os in # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic_CXX= ;; *) lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if ${lt_cv_prog_compiler_pic_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_CXX=$lt_prog_compiler_pic_CXX fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_CXX" >&5 $as_echo "$lt_cv_prog_compiler_pic_CXX" >&6; } lt_prog_compiler_pic_CXX=$lt_cv_prog_compiler_pic_CXX # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic_CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... " >&6; } if ${lt_cv_prog_compiler_pic_works_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works_CXX=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works_CXX=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works_CXX" >&5 $as_echo "$lt_cv_prog_compiler_pic_works_CXX" >&6; } if test yes = "$lt_cv_prog_compiler_pic_works_CXX"; then case $lt_prog_compiler_pic_CXX in "" | " "*) ;; *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; esac else lt_prog_compiler_pic_CXX= lt_prog_compiler_can_build_shared_CXX=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if ${lt_cv_prog_compiler_static_works_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works_CXX=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works_CXX=yes fi else lt_cv_prog_compiler_static_works_CXX=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works_CXX" >&5 $as_echo "$lt_cv_prog_compiler_static_works_CXX" >&6; } if test yes = "$lt_cv_prog_compiler_static_works_CXX"; then : else lt_prog_compiler_static_CXX= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o_CXX=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o_CXX=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 $as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o_CXX=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o_CXX=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 $as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } hard_links=nottested if test no = "$lt_cv_prog_compiler_c_o_CXX" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test no = "$hard_links"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' case $host_os in aix[4-9]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else export_symbols_cmds_CXX='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi ;; pw32*) export_symbols_cmds_CXX=$ltdll_cmds ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl*) exclude_expsyms_CXX='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms_CXX='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' ;; esac ;; linux* | k*bsd*-gnu | gnu*) link_all_deplibs_CXX=no ;; *) export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 $as_echo "$ld_shlibs_CXX" >&6; } test no = "$ld_shlibs_CXX" && can_build_shared=no with_gnu_ld_CXX=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc_CXX" in x|xyes) # Assume -lc should be added archive_cmds_need_lc_CXX=yes if test yes,yes = "$GCC,$enable_shared"; then case $archive_cmds_CXX in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } if ${lt_cv_archive_cmds_need_lc_CXX+:} false; then : $as_echo_n "(cached) " >&6 else $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl_CXX pic_flag=$lt_prog_compiler_pic_CXX compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag_CXX allow_undefined_flag_CXX= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then lt_cv_archive_cmds_need_lc_CXX=no else lt_cv_archive_cmds_need_lc_CXX=yes fi allow_undefined_flag_CXX=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc_CXX" >&5 $as_echo "$lt_cv_archive_cmds_need_lc_CXX" >&6; } archive_cmds_need_lc_CXX=$lt_cv_archive_cmds_need_lc_CXX ;; esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='$libname$release$shared_ext$major' ;; aix[4-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line '#! .'. This would cause the generated library to # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # Using Import Files as archive members, it is possible to support # filename-based versioning of shared library archives on AIX. While # this would work for both with and without runtime linking, it will # prevent static linking of such archives. So we do filename-based # shared library versioning with .so extension only, which is used # when both runtime linking and shared linking is enabled. # Unfortunately, runtime linking may impact performance, so we do # not want this to be the default eventually. Also, we use the # versioned .so libs for executables only if there is the -brtl # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. # To allow for filename-based versioning support, we need to create # libNAME.so.V as an archive file, containing: # *) an Import File, referring to the versioned filename of the # archive as well as the shared archive member, telling the # bitwidth (32 or 64) of that shared object, and providing the # list of exported symbols of that shared object, eventually # decorated with the 'weak' keyword # *) the shared object with the F_LOADONLY flag set, to really avoid # it being seen by the linker. # At run time we better use the real file rather than another symlink, # but for link time we create the symlink libNAME.so -> libNAME.so.V case $with_aix_soname,$aix_use_runtimelinking in # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. aix,yes) # traditional libtool dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; aix,no) # traditional AIX only dynamic_linker='AIX lib.a(lib.so.V)' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' ;; svr4,*) # full svr4 only dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,yes) # both, prefer svr4 dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # unpreferred sharedlib libNAME.a needs extra handling postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,no) # both, prefer aix dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' ;; esac shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' library_names_spec='$libname.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[23].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[3-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; linux*android*) version_type=none # Android doesn't support versioned libraries. need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext' soname_spec='$libname$release$shared_ext' finish_cmds= shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes dynamic_linker='Android linker' # Don't embed -rpath directories since the linker doesn't support them. hardcode_libdir_flag_spec_CXX='-L$libdir' ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH if ${lt_cv_shlibpath_overrides_runpath+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl_CXX\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec_CXX\"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : lt_cv_shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir fi shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not # being certain /sbin/ldconfig is available, command # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, # even though it is searched at run-time. Try to do the best guess by # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd* | bitrig*) version_type=sunos sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then need_version=no else need_version=yes fi library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no # OS/2 can only load a DLL with a base name of 8 characters or less. soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; v=$($ECHO $release$versuffix | tr -d .-); n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); $ECHO $n$v`$shared_ext' library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' shlibpath_var=BEGINLIBPATH sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=sco need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi # remember unaugmented sys_lib_dlsearch_path content for libtool script decls... configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec # ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" # to be used as default LT_SYS_LIBRARY_PATH value in generated libtool configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action_CXX= if test -n "$hardcode_libdir_flag_spec_CXX" || test -n "$runpath_var_CXX" || test yes = "$hardcode_automatic_CXX"; then # We can hardcode non-existent directories. if test no != "$hardcode_direct_CXX" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, CXX)" && test no != "$hardcode_minus_L_CXX"; then # Linking always hardcodes the temporary library directory. hardcode_action_CXX=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action_CXX=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action_CXX=unsupported fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action_CXX" >&5 $as_echo "$hardcode_action_CXX" >&6; } if test relink = "$hardcode_action_CXX" || test yes = "$inherit_rpath_CXX"; then # Fast installation is not supported enable_fast_install=no elif test yes = "$shlibpath_overrides_runpath" || test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi fi # test -n "$compiler" CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test yes != "$_lt_caught_CXX_error" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_config_commands="$ac_config_commands libtool" # Only expand once: # Checks for libraries. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lm" >&5 $as_echo_n "checking for main in -lm... " >&6; } if ${ac_cv_lib_m_main+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lm $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_m_main=yes else ac_cv_lib_m_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_main" >&5 $as_echo "$ac_cv_lib_m_main" >&6; } if test "x$ac_cv_lib_m_main" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBM 1 _ACEOF LIBS="-lm $LIBS" fi # FIXME: Replace `main' with a function in `-lrt': { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lrt" >&5 $as_echo_n "checking for main in -lrt... " >&6; } if ${ac_cv_lib_rt_main+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lrt $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_rt_main=yes else ac_cv_lib_rt_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_main" >&5 $as_echo "$ac_cv_lib_rt_main" >&6; } if test "x$ac_cv_lib_rt_main" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBRT 1 _ACEOF LIBS="-lrt $LIBS" fi # Checks for header files. for ac_header in float.h stdlib.h string.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done # Checks for typedefs, structures, and compiler characteristics. ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" if test "x$ac_cv_type_size_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define size_t unsigned int _ACEOF fi # Checks for library functions. ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default" if test "x$ac_cv_type_pid_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define pid_t int _ACEOF fi for ac_header in vfork.h do : ac_fn_c_check_header_mongrel "$LINENO" "vfork.h" "ac_cv_header_vfork_h" "$ac_includes_default" if test "x$ac_cv_header_vfork_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_VFORK_H 1 _ACEOF fi done for ac_func in fork vfork do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done if test "x$ac_cv_func_fork" = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working fork" >&5 $as_echo_n "checking for working fork... " >&6; } if ${ac_cv_func_fork_works+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_fork_works=cross else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { /* By Ruediger Kuhlmann. */ return fork () < 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_fork_works=yes else ac_cv_func_fork_works=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_fork_works" >&5 $as_echo "$ac_cv_func_fork_works" >&6; } else ac_cv_func_fork_works=$ac_cv_func_fork fi if test "x$ac_cv_func_fork_works" = xcross; then case $host in *-*-amigaos* | *-*-msdosdjgpp*) # Override, as these systems have only a dummy fork() stub ac_cv_func_fork_works=no ;; *) ac_cv_func_fork_works=yes ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&5 $as_echo "$as_me: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&2;} fi ac_cv_func_vfork_works=$ac_cv_func_vfork if test "x$ac_cv_func_vfork" = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working vfork" >&5 $as_echo_n "checking for working vfork... " >&6; } if ${ac_cv_func_vfork_works+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_vfork_works=cross else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Thanks to Paul Eggert for this test. */ $ac_includes_default #include #ifdef HAVE_VFORK_H # include #endif /* On some sparc systems, changes by the child to local and incoming argument registers are propagated back to the parent. The compiler is told about this with #include , but some compilers (e.g. gcc -O) don't grok . Test for this by using a static variable whose address is put into a register that is clobbered by the vfork. */ static void #ifdef __cplusplus sparc_address_test (int arg) # else sparc_address_test (arg) int arg; #endif { static pid_t child; if (!child) { child = vfork (); if (child < 0) { perror ("vfork"); _exit(2); } if (!child) { arg = getpid(); write(-1, "", 0); _exit (arg); } } } int main () { pid_t parent = getpid (); pid_t child; sparc_address_test (0); child = vfork (); if (child == 0) { /* Here is another test for sparc vfork register problems. This test uses lots of local variables, at least as many local variables as main has allocated so far including compiler temporaries. 4 locals are enough for gcc 1.40.3 on a Solaris 4.1.3 sparc, but we use 8 to be safe. A buggy compiler should reuse the register of parent for one of the local variables, since it will think that parent can't possibly be used any more in this routine. Assigning to the local variable will thus munge parent in the parent process. */ pid_t p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(), p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid(); /* Convince the compiler that p..p7 are live; otherwise, it might use the same hardware register for all 8 local variables. */ if (p != p1 || p != p2 || p != p3 || p != p4 || p != p5 || p != p6 || p != p7) _exit(1); /* On some systems (e.g. IRIX 3.3), vfork doesn't separate parent from child file descriptors. If the child closes a descriptor before it execs or exits, this munges the parent's descriptor as well. Test for this by closing stdout in the child. */ _exit(close(fileno(stdout)) != 0); } else { int status; struct stat st; while (wait(&status) != child) ; return ( /* Was there some problem with vforking? */ child < 0 /* Did the child fail? (This shouldn't happen.) */ || status /* Did the vfork/compiler bug occur? */ || parent != getpid() /* Did the file descriptor bug occur? */ || fstat(fileno(stdout), &st) != 0 ); } } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_vfork_works=yes else ac_cv_func_vfork_works=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_vfork_works" >&5 $as_echo "$ac_cv_func_vfork_works" >&6; } fi; if test "x$ac_cv_func_fork_works" = xcross; then ac_cv_func_vfork_works=$ac_cv_func_vfork { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&5 $as_echo "$as_me: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&2;} fi if test "x$ac_cv_func_vfork_works" = xyes; then $as_echo "#define HAVE_WORKING_VFORK 1" >>confdefs.h else $as_echo "#define vfork fork" >>confdefs.h fi if test "x$ac_cv_func_fork_works" = xyes; then $as_echo "#define HAVE_WORKING_FORK 1" >>confdefs.h fi for ac_func in clock_gettime do : ac_fn_c_check_func "$LINENO" "clock_gettime" "ac_cv_func_clock_gettime" if test "x$ac_cv_func_clock_gettime" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_CLOCK_GETTIME 1 _ACEOF fi done use_double=no # Check whether --enable-double-precision was given. if test "${enable_double_precision+set}" = set; then : enableval=$enable_double_precision; use_double=$enableval fi if test x$use_double = xno then CCD_PRECISION=CCD_SINGLE else CCD_PRECISION=CCD_DOUBLE fi ac_config_files="$ac_config_files Makefile src/Makefile src/ccd/precision.h src/testsuites/Makefile src/testsuites/cu/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs { $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 $as_echo_n "checking that generated files are newer than configure... " >&6; } if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 $as_echo "done" >&6; } if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' else am__EXEEXT_TRUE='#' am__EXEEXT_FALSE= fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then as_fn_error $? "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCXX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by libccd $as_me 1.0, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ libccd config.status 1.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' MKDIR_P='$MKDIR_P' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`' SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`' nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`' objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`' configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`' hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' compiler_lib_search_dirs='`$ECHO "$compiler_lib_search_dirs" | $SED "$delay_single_quote_subst"`' predep_objects='`$ECHO "$predep_objects" | $SED "$delay_single_quote_subst"`' postdep_objects='`$ECHO "$postdep_objects" | $SED "$delay_single_quote_subst"`' predeps='`$ECHO "$predeps" | $SED "$delay_single_quote_subst"`' postdeps='`$ECHO "$postdeps" | $SED "$delay_single_quote_subst"`' compiler_lib_search_path='`$ECHO "$compiler_lib_search_path" | $SED "$delay_single_quote_subst"`' LD_CXX='`$ECHO "$LD_CXX" | $SED "$delay_single_quote_subst"`' reload_flag_CXX='`$ECHO "$reload_flag_CXX" | $SED "$delay_single_quote_subst"`' reload_cmds_CXX='`$ECHO "$reload_cmds_CXX" | $SED "$delay_single_quote_subst"`' old_archive_cmds_CXX='`$ECHO "$old_archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' compiler_CXX='`$ECHO "$compiler_CXX" | $SED "$delay_single_quote_subst"`' GCC_CXX='`$ECHO "$GCC_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag_CXX='`$ECHO "$lt_prog_compiler_no_builtin_flag_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_pic_CXX='`$ECHO "$lt_prog_compiler_pic_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_wl_CXX='`$ECHO "$lt_prog_compiler_wl_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_static_CXX='`$ECHO "$lt_prog_compiler_static_CXX" | $SED "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o_CXX='`$ECHO "$lt_cv_prog_compiler_c_o_CXX" | $SED "$delay_single_quote_subst"`' archive_cmds_need_lc_CXX='`$ECHO "$archive_cmds_need_lc_CXX" | $SED "$delay_single_quote_subst"`' enable_shared_with_static_runtimes_CXX='`$ECHO "$enable_shared_with_static_runtimes_CXX" | $SED "$delay_single_quote_subst"`' export_dynamic_flag_spec_CXX='`$ECHO "$export_dynamic_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' whole_archive_flag_spec_CXX='`$ECHO "$whole_archive_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' compiler_needs_object_CXX='`$ECHO "$compiler_needs_object_CXX" | $SED "$delay_single_quote_subst"`' old_archive_from_new_cmds_CXX='`$ECHO "$old_archive_from_new_cmds_CXX" | $SED "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds_CXX='`$ECHO "$old_archive_from_expsyms_cmds_CXX" | $SED "$delay_single_quote_subst"`' archive_cmds_CXX='`$ECHO "$archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' archive_expsym_cmds_CXX='`$ECHO "$archive_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' module_cmds_CXX='`$ECHO "$module_cmds_CXX" | $SED "$delay_single_quote_subst"`' module_expsym_cmds_CXX='`$ECHO "$module_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' with_gnu_ld_CXX='`$ECHO "$with_gnu_ld_CXX" | $SED "$delay_single_quote_subst"`' allow_undefined_flag_CXX='`$ECHO "$allow_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' no_undefined_flag_CXX='`$ECHO "$no_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec_CXX='`$ECHO "$hardcode_libdir_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' hardcode_libdir_separator_CXX='`$ECHO "$hardcode_libdir_separator_CXX" | $SED "$delay_single_quote_subst"`' hardcode_direct_CXX='`$ECHO "$hardcode_direct_CXX" | $SED "$delay_single_quote_subst"`' hardcode_direct_absolute_CXX='`$ECHO "$hardcode_direct_absolute_CXX" | $SED "$delay_single_quote_subst"`' hardcode_minus_L_CXX='`$ECHO "$hardcode_minus_L_CXX" | $SED "$delay_single_quote_subst"`' hardcode_shlibpath_var_CXX='`$ECHO "$hardcode_shlibpath_var_CXX" | $SED "$delay_single_quote_subst"`' hardcode_automatic_CXX='`$ECHO "$hardcode_automatic_CXX" | $SED "$delay_single_quote_subst"`' inherit_rpath_CXX='`$ECHO "$inherit_rpath_CXX" | $SED "$delay_single_quote_subst"`' link_all_deplibs_CXX='`$ECHO "$link_all_deplibs_CXX" | $SED "$delay_single_quote_subst"`' always_export_symbols_CXX='`$ECHO "$always_export_symbols_CXX" | $SED "$delay_single_quote_subst"`' export_symbols_cmds_CXX='`$ECHO "$export_symbols_cmds_CXX" | $SED "$delay_single_quote_subst"`' exclude_expsyms_CXX='`$ECHO "$exclude_expsyms_CXX" | $SED "$delay_single_quote_subst"`' include_expsyms_CXX='`$ECHO "$include_expsyms_CXX" | $SED "$delay_single_quote_subst"`' prelink_cmds_CXX='`$ECHO "$prelink_cmds_CXX" | $SED "$delay_single_quote_subst"`' postlink_cmds_CXX='`$ECHO "$postlink_cmds_CXX" | $SED "$delay_single_quote_subst"`' file_list_spec_CXX='`$ECHO "$file_list_spec_CXX" | $SED "$delay_single_quote_subst"`' hardcode_action_CXX='`$ECHO "$hardcode_action_CXX" | $SED "$delay_single_quote_subst"`' compiler_lib_search_dirs_CXX='`$ECHO "$compiler_lib_search_dirs_CXX" | $SED "$delay_single_quote_subst"`' predep_objects_CXX='`$ECHO "$predep_objects_CXX" | $SED "$delay_single_quote_subst"`' postdep_objects_CXX='`$ECHO "$postdep_objects_CXX" | $SED "$delay_single_quote_subst"`' predeps_CXX='`$ECHO "$predeps_CXX" | $SED "$delay_single_quote_subst"`' postdeps_CXX='`$ECHO "$postdeps_CXX" | $SED "$delay_single_quote_subst"`' compiler_lib_search_path_CXX='`$ECHO "$compiler_lib_search_path_CXX" | $SED "$delay_single_quote_subst"`' LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } # Quote evaled strings. for var in SHELL \ ECHO \ PATH_SEPARATOR \ SED \ GREP \ EGREP \ FGREP \ LD \ NM \ LN_S \ lt_SP2NL \ lt_NL2SP \ reload_flag \ OBJDUMP \ deplibs_check_method \ file_magic_cmd \ file_magic_glob \ want_nocaseglob \ DLLTOOL \ sharedlib_from_linklib_cmd \ AR \ AR_FLAGS \ archiver_list_spec \ STRIP \ RANLIB \ CC \ CFLAGS \ compiler \ lt_cv_sys_global_symbol_pipe \ lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_import \ lt_cv_sys_global_symbol_to_c_name_address \ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ lt_cv_nm_interface \ nm_file_list_spec \ lt_cv_truncate_bin \ lt_prog_compiler_no_builtin_flag \ lt_prog_compiler_pic \ lt_prog_compiler_wl \ lt_prog_compiler_static \ lt_cv_prog_compiler_c_o \ need_locks \ MANIFEST_TOOL \ DSYMUTIL \ NMEDIT \ LIPO \ OTOOL \ OTOOL64 \ shrext_cmds \ export_dynamic_flag_spec \ whole_archive_flag_spec \ compiler_needs_object \ with_gnu_ld \ allow_undefined_flag \ no_undefined_flag \ hardcode_libdir_flag_spec \ hardcode_libdir_separator \ exclude_expsyms \ include_expsyms \ file_list_spec \ variables_saved_for_relink \ libname_spec \ library_names_spec \ soname_spec \ install_override_mode \ finish_eval \ old_striplib \ striplib \ compiler_lib_search_dirs \ predep_objects \ postdep_objects \ predeps \ postdeps \ compiler_lib_search_path \ LD_CXX \ reload_flag_CXX \ compiler_CXX \ lt_prog_compiler_no_builtin_flag_CXX \ lt_prog_compiler_pic_CXX \ lt_prog_compiler_wl_CXX \ lt_prog_compiler_static_CXX \ lt_cv_prog_compiler_c_o_CXX \ export_dynamic_flag_spec_CXX \ whole_archive_flag_spec_CXX \ compiler_needs_object_CXX \ with_gnu_ld_CXX \ allow_undefined_flag_CXX \ no_undefined_flag_CXX \ hardcode_libdir_flag_spec_CXX \ hardcode_libdir_separator_CXX \ exclude_expsyms_CXX \ include_expsyms_CXX \ file_list_spec_CXX \ compiler_lib_search_dirs_CXX \ predep_objects_CXX \ postdep_objects_CXX \ predeps_CXX \ postdeps_CXX \ compiler_lib_search_path_CXX; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in reload_cmds \ old_postinstall_cmds \ old_postuninstall_cmds \ old_archive_cmds \ extract_expsyms_cmds \ old_archive_from_new_cmds \ old_archive_from_expsyms_cmds \ archive_cmds \ archive_expsym_cmds \ module_cmds \ module_expsym_cmds \ export_symbols_cmds \ prelink_cmds \ postlink_cmds \ postinstall_cmds \ postuninstall_cmds \ finish_cmds \ sys_lib_search_path_spec \ configure_time_dlsearch_path \ configure_time_lt_sys_library_path \ reload_cmds_CXX \ old_archive_cmds_CXX \ old_archive_from_new_cmds_CXX \ old_archive_from_expsyms_cmds_CXX \ archive_cmds_CXX \ archive_expsym_cmds_CXX \ module_cmds_CXX \ module_expsym_cmds_CXX \ export_symbols_cmds_CXX \ prelink_cmds_CXX \ postlink_cmds_CXX; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done ac_aux_dir='$ac_aux_dir' # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi PACKAGE='$PACKAGE' VERSION='$VERSION' RM='$RM' ofile='$ofile' _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "src/config.h") CONFIG_HEADERS="$CONFIG_HEADERS src/config.h" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; "src/ccd/precision.h") CONFIG_FILES="$CONFIG_FILES src/ccd/precision.h" ;; "src/testsuites/Makefile") CONFIG_FILES="$CONFIG_FILES src/testsuites/Makefile" ;; "src/testsuites/cu/Makefile") CONFIG_FILES="$CONFIG_FILES src/testsuites/cu/Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi # Compute "$ac_file"'s index in $config_headers. _am_arg="$ac_file" _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || $as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$_am_arg" : 'X\(//\)[^/]' \| \ X"$_am_arg" : 'X\(//\)$' \| \ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$_am_arg" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'`/stamp-h$_am_stamp_count ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || { # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`$as_dirname -- "$mf" || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "$am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`$as_dirname -- "$file" || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir=$dirpart/$fdir; as_fn_mkdir_p # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ;; "libtool":C) # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi cfgfile=${ofile}T trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # Generated automatically by $as_me ($PACKAGE) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # Provide generalized library-building support services. # Written by Gordon Matzigkeit, 1996 # Copyright (C) 2014 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program or library that is built # using GNU Libtool, you may include this file under the same # distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # The names of the tagged configurations supported by this script. available_tags='CXX ' # Configured defaults for sys_lib_dlsearch_path munging. : \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} # ### BEGIN LIBTOOL CONFIG # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Which release of libtool.m4 was used? macro_version=$macro_version macro_revision=$macro_revision # Whether or not to build static libraries. build_old_libs=$enable_static # What type of objects to build. pic_mode=$pic_mode # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # Shared archive member basename,for filename based shared library versioning on AIX. shared_archive_member_spec=$shared_archive_member_spec # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # An echo program that protects backslashes. ECHO=$lt_ECHO # The PATH separator for the build system. PATH_SEPARATOR=$lt_PATH_SEPARATOR # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # A sed program that does not truncate output. SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="\$SED -e 1s/^X//" # A grep program that handles long lines. GREP=$lt_GREP # An ERE matcher. EGREP=$lt_EGREP # A literal string matcher. FGREP=$lt_FGREP # A BSD- or MS-compatible name lister. NM=$lt_NM # Whether we need soft or hard links. LN_S=$lt_LN_S # What is the maximum length of a command? max_cmd_len=$max_cmd_len # Object file suffix (normally "o"). objext=$ac_objext # Executable file suffix (normally ""). exeext=$exeext # whether the shell understands "unset". lt_unset=$lt_unset # turn spaces into newlines. SP2NL=$lt_lt_SP2NL # turn newlines into spaces. NL2SP=$lt_lt_NL2SP # convert \$build file names to \$host format. to_host_file_cmd=$lt_cv_to_host_file_cmd # convert \$build files to toolchain format. to_tool_file_cmd=$lt_cv_to_tool_file_cmd # An object symbol dumper. OBJDUMP=$lt_OBJDUMP # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method = "file_magic". file_magic_cmd=$lt_file_magic_cmd # How to find potential files when deplibs_check_method = "file_magic". file_magic_glob=$lt_file_magic_glob # Find potential files using nocaseglob when deplibs_check_method = "file_magic". want_nocaseglob=$lt_want_nocaseglob # DLL creation program. DLLTOOL=$lt_DLLTOOL # Command to associate shared and link libraries. sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd # The archiver. AR=$lt_AR # Flags to create an archive. AR_FLAGS=$lt_AR_FLAGS # How to feed a file listing to the archiver. archiver_list_spec=$lt_archiver_list_spec # A symbol stripping program. STRIP=$lt_STRIP # Commands used to install an old-style archive. RANLIB=$lt_RANLIB old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Whether to use a lock for old archive extraction. lock_old_archive_extraction=$lock_old_archive_extraction # A C compiler. LTCC=$lt_CC # LTCC compiler flags. LTCFLAGS=$lt_CFLAGS # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration. global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm into a list of symbols to manually relocate. global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import # Transform the output of nm in a C name address pair. global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # Transform the output of nm in a C name address pair when lib prefix is needed. global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix # The name lister interface. nm_interface=$lt_lt_cv_nm_interface # Specify filename containing input files for \$NM. nm_file_list_spec=$lt_nm_file_list_spec # The root where to search for dependent libraries,and where our libraries should be installed. lt_sysroot=$lt_sysroot # Command to truncate a binary pipe. lt_truncate_bin=$lt_lt_cv_truncate_bin # The name of the directory that contains temporary libtool files. objdir=$objdir # Used to examine libraries when file_magic_cmd begins with "file". MAGIC_CMD=$MAGIC_CMD # Must we lock files when doing compilation? need_locks=$lt_need_locks # Manifest tool. MANIFEST_TOOL=$lt_MANIFEST_TOOL # Tool to manipulate archived DWARF debug symbol files on Mac OS X. DSYMUTIL=$lt_DSYMUTIL # Tool to change global to local symbols on Mac OS X. NMEDIT=$lt_NMEDIT # Tool to manipulate fat objects and archives on Mac OS X. LIPO=$lt_LIPO # ldd/readelf like tool for Mach-O binaries on Mac OS X. OTOOL=$lt_OTOOL # ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. OTOOL64=$lt_OTOOL64 # Old archive suffix (normally "a"). libext=$libext # Shared library suffix (normally ".so"). shrext_cmds=$lt_shrext_cmds # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Variables whose values should be saved in libtool wrapper scripts and # restored at link time. variables_saved_for_relink=$lt_variables_saved_for_relink # Do we need the "lib" prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Library versioning type. version_type=$version_type # Shared library runtime path variable. runpath_var=$runpath_var # Shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Permission mode override for installation of shared libraries. install_override_mode=$lt_install_override_mode # Command to use after installation of a shared archive. postinstall_cmds=$lt_postinstall_cmds # Command to use after uninstallation of a shared archive. postuninstall_cmds=$lt_postuninstall_cmds # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # As "finish_cmds", except a single script fragment to be evaled but # not shown. finish_eval=$lt_finish_eval # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Compile-time system search path for libraries. sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Detected run-time system search path for libraries. sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path # Explicit LT_SYS_LIBRARY_PATH set during ./configure time. configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # The linker used to build libraries. LD=$lt_LD # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds # A language specific compiler. CC=$lt_compiler # Is the compiler the GNU compiler? with_gcc=$GCC # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds archive_expsym_cmds=$lt_archive_expsym_cmds # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds module_expsym_cmds=$lt_module_expsym_cmds # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \$shlibpath_var if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms # Symbols that must always be exported. include_expsyms=$lt_include_expsyms # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds # Commands necessary for finishing linking programs. postlink_cmds=$lt_postlink_cmds # Specify filename containing input files. file_list_spec=$lt_file_list_spec # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action # The directories searched by this compiler when creating a shared library. compiler_lib_search_dirs=$lt_compiler_lib_search_dirs # Dependencies to place before and after the objects being linked to # create a shared library. predep_objects=$lt_predep_objects postdep_objects=$lt_postdep_objects predeps=$lt_predeps postdeps=$lt_postdeps # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path # ### END LIBTOOL CONFIG _LT_EOF cat <<'_LT_EOF' >> "$cfgfile" # ### BEGIN FUNCTIONS SHARED WITH CONFIGURE # func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x$2 in x) ;; *:) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" ;; x:*) eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" ;; *::*) eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" ;; *) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" ;; esac } # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in $*""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } # ### END FUNCTIONS SHARED WITH CONFIGURE _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac ltmain=$ac_aux_dir/ltmain.sh # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" cat <<_LT_EOF >> "$ofile" # ### BEGIN LIBTOOL TAG CONFIG: CXX # The linker used to build libraries. LD=$lt_LD_CXX # How to create reloadable object files. reload_flag=$lt_reload_flag_CXX reload_cmds=$lt_reload_cmds_CXX # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds_CXX # A language specific compiler. CC=$lt_compiler_CXX # Is the compiler the GNU compiler? with_gcc=$GCC_CXX # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic_CXX # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl_CXX # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static_CXX # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc_CXX # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object_CXX # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds_CXX archive_expsym_cmds=$lt_archive_expsym_cmds_CXX # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds_CXX module_expsym_cmds=$lt_module_expsym_cmds_CXX # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld_CXX # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag_CXX # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag_CXX # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct_CXX # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \$shlibpath_var if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute_CXX # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L_CXX # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic_CXX # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath_CXX # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs_CXX # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols_CXX # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds_CXX # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms_CXX # Symbols that must always be exported. include_expsyms=$lt_include_expsyms_CXX # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds_CXX # Commands necessary for finishing linking programs. postlink_cmds=$lt_postlink_cmds_CXX # Specify filename containing input files. file_list_spec=$lt_file_list_spec_CXX # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action_CXX # The directories searched by this compiler when creating a shared library. compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_CXX # Dependencies to place before and after the objects being linked to # create a shared library. predep_objects=$lt_predep_objects_CXX postdep_objects=$lt_postdep_objects_CXX predeps=$lt_predeps_CXX postdeps=$lt_postdeps_CXX # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path_CXX # ### END LIBTOOL TAG CONFIG: CXX _LT_EOF ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi ode-0.16/libccd/Makefile.am0000664000175200017520000000011313403272463012411 00000000000000SUBDIRS = src EXTRA_DIST = \ bootstrap \ BSD-LICENSE \ README ode-0.16/libccd/bootstrap0000775000175200017520000000033113403272463012322 00000000000000#!/bin/sh # on Mac libtoolize is called glibtoolize LIBTOOLIZE=libtoolize if [ `uname -s` = Darwin ]; then LIBTOOLIZE=glibtoolize fi $LIBTOOLIZE -c --automake aclocal autoheader autoconf automake -a --foreign -c ode-0.16/libccd/README0000664000175200017520000000444313403272463011247 00000000000000libccd is library for a collision detection between two convex shapes. libccd implements variation on Gilbert–Johnson–Keerthi algorithm plus Expand Polytope Algorithm (EPA) and also implements algorithm Minkowski Portal Refinement (MPR, a.k.a. XenoCollide) as described in Game Programming Gems 7. For more info see home of libccd: http://libccd.danfis.cz. Dependencies ------------- This library is currently based only on standard libraries. The only exception are testsuites that are built on top of CU (cu.danfis.cz) library licensed under LGPL, however only testing depends on it and libccd library itself can be distributed without it. License -------- libccd is licensed under OSI-approved 3-clause BSD License, text of license is distributed along with source code in BSD-LICENSE file. Each file should include license notice, the rest should be considered as licensed under 3-clause BSD License. Compile And Install -------------------- Simply type 'make' and 'make install' in src/ directory. Library libccd is by default compiled in double precision of floating point numbers - you can controll this by options USE_SINGLE/USE_DOUBLE, i.e.: $ make USE_SINGLE=yes will compile library in single precision. Installation directory can be changed by options PREFIX, INCLUDEDIR and LIBDIR. For more info type 'make help'. Compile And Install Using Autotools ------------------------------------ libccd also contains support for autotools: 1) Generate configure script etc.: $ ./bootstrap 2) Create new build/ directory: $ mkdir build && cd build 3) Run configure script: $ ../configure 4) Run make and make install: $ make && make install configure script can change the way libccd is compiled and installed, most significant option is --enable-double-precision which enables double precision (single is default in this case). Usage ------ See ccd.h for public API. In your application include , setup ccd_t structure and run some of functions (all functions are reentrant). Then link with libccd.a. Directories ------------ src/ - contains source files of libccd. src/testsuites - testsuites - libccd must be compiled before compiling this. src/testsuites/cu - CU unit testing framework src/testsuites/regressions - files ready for regression tests doc/ - some documentation. ode-0.16/libccd/Makefile.in0000664000175200017520000006101413403272666012436 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ $(am__configure_deps) $(am__DIST_COMMON) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/src/config.h CONFIG_CLEAN_FILES = src/ccd/precision.h CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ cscope distdir dist dist-all distcheck am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags CSCOPE = cscope DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/../compile \ $(top_srcdir)/../config.guess $(top_srcdir)/../config.sub \ $(top_srcdir)/../install-sh $(top_srcdir)/../ltmain.sh \ $(top_srcdir)/../missing $(top_srcdir)/src/ccd/precision.h.in \ README DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ if test -d "$(distdir)"; then \ find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -rf "$(distdir)" \ || { sleep 5 && rm -rf "$(distdir)"; }; \ else :; fi am__post_remove_distdir = $(am__remove_distdir) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best DIST_TARGETS = dist-gzip distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CCD_PRECISION = @CCD_PRECISION@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = src EXTRA_DIST = \ bootstrap \ BSD-LICENSE \ README all: all-recursive .SUFFIXES: am--refresh: Makefile @: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): src/ccd/precision.h: $(top_builddir)/config.status $(top_srcdir)/src/ccd/precision.h.in cd $(top_builddir) && $(SHELL) ./config.status $@ mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool config.lt # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscope: cscope.files test ! -s cscope.files \ || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) clean-cscope: -rm -f cscope.files cscope.files: clean-cscope cscopelist cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files distdir: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done -test -n "$(am__skip_mode_fix)" \ || find "$(distdir)" -type d ! -perm -755 \ -exec chmod u+rwx,go+rx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 $(am__post_remove_distdir) dist-lzip: distdir tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz $(am__post_remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__post_remove_distdir) dist-tarZ: distdir @echo WARNING: "Support for distribution archives compressed with" \ "legacy program 'compress' is deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir @echo WARNING: "Support for shar distribution archives is" \ "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__post_remove_distdir) dist dist-all: $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' $(am__post_remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ *.tar.xz*) \ xz -dc $(distdir).tar.xz | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ && $(am__cd) $(distdir)/_build/sub \ && ../../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ --srcdir=../.. --prefix="$$dc_install_base" \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ && cd "$$am__cwd" \ || exit 1 $(am__post_remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: @test -n '$(distuninstallcheck_dir)' || { \ echo 'ERROR: trying to run $@ with an empty' \ '$$(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ $(am__cd) '$(distuninstallcheck_dir)' || { \ echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f Makefile distclean-am: clean-am distclean-generic distclean-libtool \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ am--refresh check check-am clean clean-cscope clean-generic \ clean-libtool cscope cscopelist-am ctags ctags-am dist \ dist-all dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ \ dist-xz dist-zip distcheck distclean distclean-generic \ distclean-libtool distclean-tags distcleancheck distdir \ distuninstallcheck dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am tags tags-am uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ode-0.16/libccd/configure.ac0000664000175200017520000000243413403272463012653 00000000000000# -*- Autoconf -*- # Process this file with autoconf to produce a configure script. #AC_PREREQ([2.65]) AC_INIT([libccd], [1.0], [danfis@danfis.cz]) AC_CONFIG_SRCDIR([src/ccd.c]) AC_CONFIG_HEADERS([src/config.h]) AM_INIT_AUTOMAKE(foreign) # Checks for programs. AC_PROG_CXX AC_PROG_CC AC_PROG_INSTALL AC_DISABLE_SHARED LT_INIT # Checks for libraries. AC_CHECK_LIB([m], [main]) # FIXME: Replace `main' with a function in `-lrt': AC_CHECK_LIB([rt], [main]) # Checks for header files. AC_CHECK_HEADERS([float.h stdlib.h string.h unistd.h]) # Checks for typedefs, structures, and compiler characteristics. AC_TYPE_SIZE_T # Checks for library functions. AC_FUNC_FORK AC_CHECK_FUNCS([clock_gettime]) use_double=no AC_ARG_ENABLE(double-precision, AS_HELP_STRING([--enable-double-precision], [enable double precision computations instead of single precision]), [use_double=$enableval]) if test x$use_double = xno then CCD_PRECISION=CCD_SINGLE else CCD_PRECISION=CCD_DOUBLE fi AC_SUBST(CCD_PRECISION) AC_CONFIG_FILES([Makefile src/Makefile src/ccd/precision.h src/testsuites/Makefile src/testsuites/cu/Makefile]) AC_OUTPUT ode-0.16/config.h.cmake.in0000664000175200017520000000530313403272463012245 00000000000000#ifndef ODE_CONFIG_H #define ODE_CONFIG_H /* Define to 1 if you have and it should be used (not on Ultrix). */ #cmakedefine HAVE_ALLOCA_H 1 /* Use the Apple OpenGL framework. */ #cmakedefine HAVE_APPLE_OPENGL_FRAMEWORK 1 /* Define to 1 if you have the `gettimeofday' function. */ #cmakedefine HAVE_GETTIMEOFDAY 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_INTTYPES_H 1 /* Define to 1 if you have the `isnan' function. */ #cmakedefine HAVE_ISNAN 1 /* Define to 1 if you have the `isnanf' function. */ #cmakedefine HAVE_ISNANF 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_MALLOC_H 1 /* Define to 1 if you have the `pthread_attr_setstacklazy' function. */ #cmakedefine HAVE_PTHREAD_ATTR_SETSTACKLAZY 1 /* Define to 1 if you have the `pthread_condattr_setclock' function. */ #cmakedefine HAVE_PTHREAD_CONDATTR_SETCLOCK 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_TIME_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_TYPES_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_UNISTD_H 1 /* Define to 1 if you have the `_isnan' function. */ #cmakedefine HAVE__ISNAN 1 /* Define to 1 if you have the `_isnanf' function. */ #cmakedefine HAVE__ISNANF 1 /* Define to 1 if you have the `__isnan' function. */ #cmakedefine HAVE___ISNAN 1 /* Define to 1 if you have the `__isnanf' function. */ #cmakedefine HAVE___ISNANF 1 /* compiling for a pentium on a gcc-based platform? */ #cmakedefine PENTIUM 1 /* compiling for a X86_64 system on a gcc-based platform? */ #cmakedefine X86_64_SYSTEM 1 /* Try to identify the platform */ #if defined(_XENON) #define ODE_PLATFORM_XBOX360 #elif defined(SN_TARGET_PSP_HW) #define ODE_PLATFORM_PSP #elif defined(SN_TARGET_PS3) #define ODE_PLATFORM_PS3 #elif defined(_MSC_VER) || defined(__CYGWIN32__) || defined(__MINGW32__) #define ODE_PLATFORM_WINDOWS #elif defined(__linux__) #define ODE_PLATFORM_LINUX #elif defined(__APPLE__) && defined(__MACH__) #define ODE_PLATFORM_OSX #else #error "Need some help identifying the platform!" #endif /* Additional platform defines used in the code */ #if defined(ODE_PLATFORM_WINDOWS) && !defined(WIN32) #define WIN32 #endif #if defined(__CYGWIN32__) || defined(__MINGW32__) #define CYGWIN #endif #if defined(ODE_PLATFORM_OSX) #define macintosh #endif #ifdef HAVE_ALLOCA_H #include #endif #ifdef HAVE_MALLOC_H #include #endif #ifdef HAVE_STDINT_H #include #endif #ifdef HAVE_INTTYPES_H #include #endif #include "typedefs.h" #endif // ODE_CONFIG_H ode-0.16/aclocal.m40000664000175200017520000012251113403272661011004 00000000000000# generated automatically by aclocal 1.15 -*- Autoconf -*- # Copyright (C) 1996-2014 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, [m4_warning([this file was generated for autoconf 2.69. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) # Copyright (C) 2002-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.15' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.15], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.15])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to # '$srcdir', '$srcdir/..', or '$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is '.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl # Expand $ac_aux_dir to an absolute path. am_aux_dir=`cd "$ac_aux_dir" && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ([2.52])dnl m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl m4_define([_AM_COND_VALUE_$1], [$2])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], [$1], [CXX], [depcc="$CXX" am_compiler_list=], [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], [$1], [UPC], [depcc="$UPC" am_compiler_list=], [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES. AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE([dependency-tracking], [dnl AS_HELP_STRING( [--enable-dependency-tracking], [do not reject slow dependency extractors]) AS_HELP_STRING( [--disable-dependency-tracking], [speeds up one-time build])]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl AC_SUBST([am__nodep])dnl _AM_SUBST_NOTMAKE([am__nodep])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "$am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking # is enabled. FIXME. This creates each '.P' file that we will # need in order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC]) [_AM_PROG_CC_C_O ]) # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.65])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [AC_DIAGNOSE([obsolete], [$0: two- and three-arguments forms are deprecated.]) m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if( m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), [ok:ok],, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) AM_MISSING_PROG([AUTOCONF], [autoconf]) AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) AM_MISSING_PROG([AUTOHEADER], [autoheader]) AM_MISSING_PROG([MAKEINFO], [makeinfo]) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # AC_SUBST([mkdir_p], ['$(MKDIR_P)']) # We need awk for the "check" target (and possibly the TAP driver). The # system "awk" is bad on some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES([CC])], [m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES([CXX])], [m4_define([AC_PROG_CXX], m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES([OBJC])], [m4_define([AC_PROG_OBJC], m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], [_AM_DEPENDENCIES([OBJCXX])], [m4_define([AC_PROG_OBJCXX], m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl ]) AC_REQUIRE([AM_SILENT_RULES])dnl dnl The testsuite driver may need to know about EXEEXT, so add the dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) fi fi dnl The trailing newline in this macro's definition is deliberate, for dnl backward compatibility and to allow trailing 'dnl'-style comments dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. ]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi AC_SUBST([install_sh])]) # Copyright (C) 2003-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MAKE_INCLUDE() # ----------------- # Check to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it is modern enough. # If it is, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= AC_MSG_WARN(['missing' script is too old or missing]) fi ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # -------------------- # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), [1])]) # _AM_SET_OPTIONS(OPTIONS) # ------------------------ # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Copyright (C) 1999-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_CC_C_O # --------------- # Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC # to automatically call this. AC_DEFUN([_AM_PROG_CC_C_O], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([compile])dnl AC_LANG_PUSH([C])dnl AC_CACHE_CHECK( [whether $CC understands -c and -o together], [am_cv_prog_cc_c_o], [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i]) if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi AC_LANG_POP([C])]) # For backward compatibility. AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) # Copyright (C) 2001-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_RUN_LOG(COMMAND) # ------------------- # Run COMMAND, save the exit status in ac_status, and log it. # (This has been adapted from Autoconf's _AC_RUN_LOG macro.) AC_DEFUN([AM_RUN_LOG], [{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD (exit $ac_status); }]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[[\\\"\#\$\&\'\`$am_lf]]*) AC_MSG_ERROR([unsafe absolute working directory name]);; esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi if test "$[2]" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT([yes]) # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi AC_CONFIG_COMMANDS_PRE( [AC_MSG_CHECKING([that generated files are newer than configure]) if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi AC_MSG_RESULT([done])]) rm -f conftest.file ]) # Copyright (C) 2009-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SILENT_RULES([DEFAULT]) # -------------------------- # Enable less verbose build rules; with the default set to DEFAULT # ("yes" being less verbose, "no" or empty being verbose). AC_DEFUN([AM_SILENT_RULES], [AC_ARG_ENABLE([silent-rules], [dnl AS_HELP_STRING( [--enable-silent-rules], [less verbose build output (undo: "make V=1")]) AS_HELP_STRING( [--disable-silent-rules], [verbose build output (undo: "make V=0")])dnl ]) case $enable_silent_rules in @%:@ ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; esac dnl dnl A few 'make' implementations (e.g., NonStop OS and NextStep) dnl do not support nested variable expansions. dnl See automake bug#9928 and bug#10237. am_make=${MAKE-make} AC_CACHE_CHECK([whether $am_make supports nested variables], [am_cv_make_support_nested_variables], [if AS_ECHO([['TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi]) if test $am_cv_make_support_nested_variables = yes; then dnl Using '$V' instead of '$(V)' breaks IRIX make. AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AC_SUBST([AM_V])dnl AM_SUBST_NOTMAKE([AM_V])dnl AC_SUBST([AM_DEFAULT_V])dnl AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl AC_SUBST([AM_DEFAULT_VERBOSITY])dnl AM_BACKSLASH='\' AC_SUBST([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) # Copyright (C) 2001-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor 'install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in "make install-strip", and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) # -------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of 'v7', 'ustar', or 'pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar # AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' m4_if([$1], [v7], [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], [m4_case([$1], [ustar], [# The POSIX 1988 'ustar' format is defined with fixed-size fields. # There is notably a 21 bits limit for the UID and the GID. In fact, # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 # and bug#13588). am_max_uid=2097151 # 2^21 - 1 am_max_gid=$am_max_uid # The $UID and $GID variables are not portable, so we need to resort # to the POSIX-mandated id(1) utility. Errors in the 'id' calls # below are definitely unexpected, so allow the users to see them # (that is, avoid stderr redirection). am_uid=`id -u || echo unknown` am_gid=`id -g || echo unknown` AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) if test $am_uid -le $am_max_uid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) if test $am_gid -le $am_max_gid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi], [pax], [], [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Go ahead even if we have the value already cached. We do so because we # need to set the values for the 'am__tar' and 'am__untar' variables. _am_tools=${am_cv_prog_tar_$1-$_am_tools} for _am_tool in $_am_tools; do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works. rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR m4_include([m4/libtool.m4]) m4_include([m4/ltoptions.m4]) m4_include([m4/ltsugar.m4]) m4_include([m4/ltversion.m4]) m4_include([m4/lt~obsolete.m4]) m4_include([m4/pkg.m4]) ode-0.16/configure0000775000175200017520000241470313403272663011066 00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for ODE 0.16. # # Report bugs to . # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org and ode@ode.org about $0: your system, including any error possibly output before $0: this message. Then install a modern shell, or manually $0: run the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" SHELL=${CONFIG_SHELL-/bin/sh} test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='ODE' PACKAGE_TARNAME='ode' PACKAGE_VERSION='0.16' PACKAGE_STRING='ODE 0.16' PACKAGE_BUGREPORT='ode@ode.org' PACKAGE_URL='' ac_unique_file="ode/src/ode.cpp" # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" enable_option_checking=no ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBCCD_CONVEX_CONVEX_FALSE LIBCCD_CONVEX_CONVEX_TRUE LIBCCD_CONVEX_SPHERE_FALSE LIBCCD_CONVEX_SPHERE_TRUE LIBCCD_CONVEX_CYL_FALSE LIBCCD_CONVEX_CYL_TRUE LIBCCD_CONVEX_CAP_FALSE LIBCCD_CONVEX_CAP_TRUE LIBCCD_CONVEX_BOX_FALSE LIBCCD_CONVEX_BOX_TRUE LIBCCD_CAP_CYL_FALSE LIBCCD_CAP_CYL_TRUE LIBCCD_CYL_CYL_FALSE LIBCCD_CYL_CYL_TRUE LIBCCD_BOX_CYL_FALSE LIBCCD_BOX_CYL_TRUE LIBCCD_INTERNAL_FALSE LIBCCD_INTERNAL_TRUE LIBCCD_FALSE LIBCCD_TRUE CCD_LIBS CCD_CFLAGS ENABLE_OU_FALSE ENABLE_OU_TRUE subdirs ALLOCA LIBOBJS ENABLE_DEMOS_FALSE ENABLE_DEMOS_TRUE LIBSTDCXX ENABLE_DRAWSTUFF_FALSE ENABLE_DRAWSTUFF_TRUE OSX_FALSE OSX_TRUE X11_FALSE X11_TRUE WIN32_FALSE WIN32_TRUE GL_LIBS X11_LIBS X11_CFLAGS EXTRA_LIBTOOL_LDFLAGS ODE_PRECISION TRIMESH_FALSE TRIMESH_TRUE GIMPACT_FALSE GIMPACT_TRUE OPCODE_FALSE OPCODE_TRUE X86_64_SYSTEM_FALSE X86_64_SYSTEM_TRUE HAVE_DOXYGEN_FALSE HAVE_DOXYGEN_TRUE DOXYGEN PKG_CONFIG_LIBDIR PKG_CONFIG_PATH PKG_CONFIG ac_ct_WINDRES WINDRES CXXCPP LT_SYS_LIBRARY_PATH OTOOL64 OTOOL LIPO NMEDIT DSYMUTIL MANIFEST_TOOL RANLIB ac_ct_AR AR NM ac_ct_DUMPBIN DUMPBIN LD FGREP EGREP GREP SED LIBTOOL OBJDUMP DLLTOOL AS LN_S CPP am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE ac_ct_CC CFLAGS CC am__fastdepCXX_FALSE am__fastdepCXX_TRUE CXXDEPMODE am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__quote am__include DEPDIR OBJEXT EXEEXT ac_ct_CXX CPPFLAGS LDFLAGS CXXFLAGS CXX AM_BACKSLASH AM_DEFAULT_VERBOSITY AM_DEFAULT_V AM_V am__untar am__tar AMTAR am__leading_dot SET_MAKE AWK mkdir_p MKDIR_P INSTALL_STRIP_PROGRAM STRIP install_sh MAKEINFO AUTOHEADER AUTOMAKE AUTOCONF ACLOCAL VERSION PACKAGE CYGPATH_W am__isrc INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM host_os host_vendor host_cpu host build_os build_vendor build_cpu build ODE_VERSION_INFO ODE_VERSION target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir runstatedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_version_info enable_silent_rules enable_dependency_tracking enable_shared enable_static with_pic enable_fast_install with_aix_soname with_gnu_ld with_sysroot enable_libtool_lock with_trimesh enable_double_precision with_drawstuff enable_demos enable_old_trimesh enable_gprof enable_threading_intf enable_ou enable_builtin_threading_impl enable_libccd with_cylinder_cylinder with_box_cylinder with_capsule_cylinder with_convex_box with_convex_capsule with_convex_cylinder with_convex_sphere with_convex_convex with_libccd enable_asserts ' ac_precious_vars='build_alias host_alias target_alias CXX CXXFLAGS LDFLAGS LIBS CPPFLAGS CCC CC CFLAGS CPP LT_SYS_LIBRARY_PATH CXXCPP PKG_CONFIG PKG_CONFIG_PATH PKG_CONFIG_LIBDIR DOXYGEN X11_CFLAGS X11_LIBS CCD_CFLAGS CCD_LIBS' ac_subdirs_all='ou libccd' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -runstatedir | --runstatedir | --runstatedi | --runstated \ | --runstate | --runstat | --runsta | --runst | --runs \ | --run | --ru | --r) ac_prev=runstatedir ;; -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ | --run=* | --ru=* | --r=*) runstatedir=$ac_optarg ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures ODE 0.16 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/ode] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of ODE 0.16:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --disable-version-info don't encode version information in the generated library --enable-silent-rules less verbose build output (undo: "make V=1") --disable-silent-rules verbose build output (undo: "make V=0") --enable-dependency-tracking do not reject slow dependency extractors --disable-dependency-tracking speeds up one-time build --enable-shared[=PKGS] build shared libraries [default=no] --enable-static[=PKGS] build static libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) --enable-double-precision Configure ODE to work with double precision, if not specified, single precision is used [default=no] --disable-demos don't build demos --enable-old-trimesh enable use of the old trimesh collider --enable-gprof enable profiling with gprof --disable-threading-intf disable threading interface support (external implementations cannot be assigned) --enable-ou use TLS for global caches (allows threaded collision checks for isolated spaces) --disable-builtin-threading-impl disable built-in multithreaded threading implementation --enable-libccd enable all libccd colliders (except box-cylinder) --disable-asserts disables debug error checking Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use both] --with-aix-soname=aix|svr4|both shared library versioning (aka "SONAME") variant to provide on AIX, [default=aix]. --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-sysroot[=DIR] Search for dependent libraries within DIR (or the compiler's sysroot if not specified). --with-trimesh=[opcode|gimpact|none] use the specified system for trimesh support [default=opcode] --with-drawstuff=X11|Win32|OSX|none force a particular drawstuff implementation or disable it.[default=autodetect] --with-cylinder-cylinder=[none,libccd] use specific collider for cylinder-cylinder --with-box-cylinder=[default,libccd] use specific collider for box-cylinder --with-capsule-cylinder=[none,libccd] use specific collider for capsule-cylinder --with-convex-box=[none,libccd] use specific collider for convex-box --with-convex-capsule=[none,libccd] use specific collider for convex-capsule --with-convex-cylinder=[none,libccd] use specific collider for convex-cylinder --with-convex-sphere=[default,libccd] use specific collider for convex-sphere --with-convex-convex=[default,libccd] use specific collider for convex-convex --with-libccd=[internal|system] use the specified libccd [default=system] Some influential environment variables: CXX C++ compiler command CXXFLAGS C++ compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CC C compiler command CFLAGS C compiler flags CPP C preprocessor LT_SYS_LIBRARY_PATH User-defined run-time library search path. CXXCPP C++ preprocessor PKG_CONFIG path to pkg-config utility PKG_CONFIG_PATH directories to add to pkg-config's search path PKG_CONFIG_LIBDIR path overriding pkg-config's built-in search path DOXYGEN set to doxygen binary to generate doxygen docs X11_CFLAGS C compiler flags for X11, overriding pkg-config X11_LIBS linker flags for X11, overriding pkg-config CCD_CFLAGS C compiler flags for CCD, overriding pkg-config CCD_LIBS linker flags for CCD, overriding pkg-config Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF ODE configure 0.16 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_cxx_try_compile LINENO # ---------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_compile # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func # ac_fn_cxx_try_cpp LINENO # ------------------------ # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_cpp # ac_fn_cxx_try_link LINENO # ------------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_link # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ( $as_echo "## -------------------------- ## ## Report this to ode@ode.org ## ## -------------------------- ##" ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache # variable VAR accordingly. ac_fn_c_check_type () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof ($2)) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof (($2))) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else eval "$3=yes" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_type # ac_fn_c_find_intX_t LINENO BITS VAR # ----------------------------------- # Finds a signed integer type with width BITS, setting cache variable VAR # accordingly. ac_fn_c_find_intX_t () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for int$2_t" >&5 $as_echo_n "checking for int$2_t... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" # Order is important - never check a type that is potentially smaller # than half of the expected target width. for ac_type in int$2_t 'int' 'long int' \ 'long long int' 'short int' 'signed char'; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default enum { N = $2 / 2 - 1 }; int main () { static int test_array [1 - 2 * !(0 < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1))]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default enum { N = $2 / 2 - 1 }; int main () { static int test_array [1 - 2 * !(($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1) < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 2))]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else case $ac_type in #( int$2_t) : eval "$3=yes" ;; #( *) : eval "$3=\$ac_type" ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if eval test \"x\$"$3"\" = x"no"; then : else break fi done fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_find_intX_t # ac_fn_c_find_uintX_t LINENO BITS VAR # ------------------------------------ # Finds an unsigned integer type with width BITS, setting cache variable VAR # accordingly. ac_fn_c_find_uintX_t () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uint$2_t" >&5 $as_echo_n "checking for uint$2_t... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" # Order is important - never check a type that is potentially smaller # than half of the expected target width. for ac_type in uint$2_t 'unsigned int' 'unsigned long int' \ 'unsigned long long int' 'unsigned short int' 'unsigned char'; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !((($ac_type) -1 >> ($2 / 2 - 1)) >> ($2 / 2 - 1) == 3)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : case $ac_type in #( uint$2_t) : eval "$3=yes" ;; #( *) : eval "$3=\$ac_type" ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if eval test \"x\$"$3"\" = x"no"; then : else break fi done fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_find_uintX_t cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by ODE $as_me 0.16, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ODE_VERSION=0.16 # Those are instructions from the Libtool manual: # 1. Start with version information of `0:0:0' for each libtool library. # # 2. Update the version information only immediately before a public # release of your software. More frequent updates are unnecessary, # and only guarantee that the current interface number gets larger # faster. # # 3. If the library source code has changed at all since the last # update, then increment REVISION (`C:R:A' becomes `C:r+1:A'). # # 4. If any interfaces have been added, removed, or changed since the # last update, increment CURRENT, and set REVISION to 0. # # 5. If any interfaces have been added since the last public release, # then increment AGE. # # 6. If any interfaces have been removed since the last public release, # then set AGE to 0. CURRENT=8 REVISION=0 AGE=0 # Check whether --enable-version-info was given. if test "${enable_version_info+set}" = set; then : enableval=$enable_version_info; version_info=$enableval else version_info=yes fi if test x$version_info = xyes then ODE_VERSION_INFO="-version-info $CURRENT:$REVISION:$AGE" else ODE_VERSION_INFO="-avoid-version" fi ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac am__api_version='1.15' # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in #(( ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 $as_echo_n "checking whether build environment is sane... " >&6; } # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[\\\"\#\$\&\'\`$am_lf]*) as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; esac case $srcdir in *[\\\"\#\$\&\'\`$am_lf\ \ ]*) as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". as_fn_error $? "ls -t appears to fail. Make sure there is not a broken alias in your environment" "$LINENO" 5 fi if test "$2" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$2" = conftest.file ) then # Ok. : else as_fn_error $? "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi rm -f conftest.file test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s&\$&$program_suffix&;$program_transform_name" # Double any \ or $. # By default was `s,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` # Expand $ac_aux_dir to an absolute path. am_aux_dir=`cd "$ac_aux_dir" && pwd` if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 $as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if ${ac_cv_path_mkdir+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir (GNU coreutils) '* | \ 'mkdir (coreutils) '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS fi test -d ./--version && rmdir ./--version if test "${ac_cv_path_mkdir+set}" = set; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a # value for MKDIR_P within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. MKDIR_P="$ac_install_sh -d" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 $as_echo "$MKDIR_P" >&6; } for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=1;; esac am_make=${MAKE-make} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 $as_echo_n "checking whether $am_make supports nested variables... " >&6; } if ${am_cv_make_support_nested_variables+:} false; then : $as_echo_n "(cached) " >&6 else if $as_echo 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 $as_echo "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." am__isrc=' -I$(srcdir)' # test to see if srcdir already configured if test -f $srcdir/config.status; then as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE='ode' VERSION='0.16' cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # mkdir_p='$(MKDIR_P)' # We need awk for the "check" target (and possibly the TAP driver). The # system "awk" is bad on some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar pax cpio none' am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 fi fi ac_config_headers="$ac_config_headers ode/src/config.h" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test -z "$CXX"; then if test -n "$CCC"; then CXX=$CCC else if test -n "$ac_tool_prefix"; then for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CXX=$ac_cv_prog_CXX if test -n "$CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 $as_echo "$CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CXX" && break done fi if test -z "$CXX"; then ac_ct_CXX=$CXX for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CXX"; then ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CXX="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CXX=$ac_cv_prog_ac_ct_CXX if test -n "$ac_ct_CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 $as_echo "$ac_ct_CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CXX" && break done if test "x$ac_ct_CXX" = x; then CXX="g++" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CXX=$ac_ct_CXX fi fi fi fi # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C++ compiler works" >&5 $as_echo_n "checking whether the C++ compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C++ compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler default output file name" >&5 $as_echo_n "checking for C++ compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C++ compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 $as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } if ${ac_cv_cxx_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 $as_echo "$ac_cv_cxx_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GXX=yes else GXX= fi ac_test_CXXFLAGS=${CXXFLAGS+set} ac_save_CXXFLAGS=$CXXFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 $as_echo_n "checking whether $CXX accepts -g... " >&6; } if ${ac_cv_prog_cxx_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_cxx_werror_flag=$ac_cxx_werror_flag ac_cxx_werror_flag=yes ac_cv_prog_cxx_g=no CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes else CXXFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : else ac_cxx_werror_flag=$ac_save_cxx_werror_flag CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cxx_werror_flag=$ac_save_cxx_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 $as_echo "$ac_cv_prog_cxx_g" >&6; } if test "$ac_test_CXXFLAGS" = set; then CXXFLAGS=$ac_save_CXXFLAGS elif test $ac_cv_prog_cxx_g = yes; then if test "$GXX" = yes; then CXXFLAGS="-g -O2" else CXXFLAGS="-g" fi else if test "$GXX" = yes; then CXXFLAGS="-O2" else CXXFLAGS= fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 $as_echo_n "checking for style of include used by $am_make... " >&6; } am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 $as_echo "$_am_result" >&6; } rm -f confinc confmf # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then : enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi depcc="$CXX" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CXX_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CXX_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CXX_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CXX_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5 $as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; } CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then am__fastdepCXX_TRUE= am__fastdepCXX_FALSE='#' else am__fastdepCXX_TRUE='#' am__fastdepCXX_FALSE= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 $as_echo_n "checking whether $CC understands -c and -o together... " >&6; } if ${am_cv_prog_cc_c_o+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 $as_echo "$am_cv_prog_cc_c_o" >&6; } if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } fi case `pwd` in *\ * | *\ *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 $as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; esac macro_version='2.4.6' macro_revision='2.4.6' ltmain=$ac_aux_dir/ltmain.sh # Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\(["`$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 $as_echo_n "checking how to print strings... " >&6; } # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "" } case $ECHO in printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 $as_echo "printf" >&6; } ;; print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 $as_echo "print -r" >&6; } ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 $as_echo "cat" >&6; } ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 $as_echo_n "checking for a sed that does not truncate output... " >&6; } if ${ac_cv_path_SED+:} false; then : $as_echo_n "(cached) " >&6 else ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for ac_i in 1 2 3 4 5 6 7; do ac_script="$ac_script$as_nl$ac_script" done echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed { ac_script=; unset ac_script;} if test -z "$SED"; then ac_path_SED_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_SED" || continue # Check for GNU ac_path_SED and select it if it is found. # Check for GNU $ac_path_SED case `"$ac_path_SED" --version 2>&1` in *GNU*) ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo '' >> "conftest.nl" "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_SED_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_SED="$ac_path_SED" ac_path_SED_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_SED_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_SED"; then as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 fi else ac_cv_path_SED=$SED fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 $as_echo "$ac_cv_path_SED" >&6; } SED="$ac_cv_path_SED" rm -f conftest.sed test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 $as_echo_n "checking for fgrep... " >&6; } if ${ac_cv_path_FGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 then ac_cv_path_FGREP="$GREP -F" else if test -z "$FGREP"; then ac_path_FGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in fgrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_FGREP" || continue # Check for GNU ac_path_FGREP and select it if it is found. # Check for GNU $ac_path_FGREP case `"$ac_path_FGREP" --version 2>&1` in *GNU*) ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'FGREP' >> "conftest.nl" "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_FGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_FGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_FGREP"; then as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_FGREP=$FGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 $as_echo "$ac_cv_path_FGREP" >&6; } FGREP="$ac_cv_path_FGREP" test -z "$GREP" && GREP=grep # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test yes = "$with_gnu_ld"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if ${lt_cv_prog_gnu_ld+:} false; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 $as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } if ${lt_cv_path_NM+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM=$NM else lt_nm_to_check=${ac_tool_prefix}nm if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. tmp_nm=$ac_dir/$lt_tmp_nm if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then # Check to see if the nm accepts a BSD-compat flag. # Adding the 'sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty case $build_os in mingw*) lt_bad_file=conftest.nm/nofile ;; *) lt_bad_file=/dev/null ;; esac case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in *$lt_bad_file* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break 2 ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break 2 ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS=$lt_save_ifs done : ${lt_cv_path_NM=no} fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 $as_echo "$lt_cv_path_NM" >&6; } if test no != "$lt_cv_path_NM"; then NM=$lt_cv_path_NM else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else if test -n "$ac_tool_prefix"; then for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DUMPBIN"; then ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DUMPBIN=$ac_cv_prog_DUMPBIN if test -n "$DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 $as_echo "$DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$DUMPBIN" && break done fi if test -z "$DUMPBIN"; then ac_ct_DUMPBIN=$DUMPBIN for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DUMPBIN"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN if test -n "$ac_ct_DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 $as_echo "$ac_ct_DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_DUMPBIN" && break done if test "x$ac_ct_DUMPBIN" = x; then DUMPBIN=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DUMPBIN=$ac_ct_DUMPBIN fi fi case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols -headers" ;; *) DUMPBIN=: ;; esac fi if test : != "$DUMPBIN"; then NM=$DUMPBIN fi fi test -z "$NM" && NM=nm { $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 $as_echo_n "checking the name lister ($NM) interface... " >&6; } if ${lt_cv_nm_interface+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 $as_echo "$lt_cv_nm_interface" >&6; } # find the maximum length of command line arguments { $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 $as_echo_n "checking the maximum length of command line arguments... " >&6; } if ${lt_cv_sys_max_cmd_len+:} false; then : $as_echo_n "(cached) " >&6 else i=0 teststring=ABCD case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test X`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test 17 != "$i" # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac fi if test -n "$lt_cv_sys_max_cmd_len"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 $as_echo "$lt_cv_sys_max_cmd_len" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } fi max_cmd_len=$lt_cv_sys_max_cmd_len : ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 $as_echo_n "checking how to convert $build file names to $host format... " >&6; } if ${lt_cv_to_host_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac fi to_host_file_cmd=$lt_cv_to_host_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 $as_echo "$lt_cv_to_host_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 $as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } if ${lt_cv_to_tool_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else #assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac fi to_tool_file_cmd=$lt_cv_to_tool_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 $as_echo "$lt_cv_to_tool_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 $as_echo_n "checking for $LD option to reload object files... " >&6; } if ${lt_cv_ld_reload_flag+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_reload_flag='-r' fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 $as_echo "$lt_cv_ld_reload_flag" >&6; } reload_flag=$lt_cv_ld_reload_flag case $reload_flag in "" | " "*) ;; *) reload_flag=" $reload_flag" ;; esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in cygwin* | mingw* | pw32* | cegcc*) if test yes != "$GCC"; then reload_cmds=false fi ;; darwin*) if test yes = "$GCC"; then reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs' else reload_cmds='$LD$reload_flag -o $output$reload_objs' fi ;; esac if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OBJDUMP"; then ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OBJDUMP=$ac_cv_prog_OBJDUMP if test -n "$OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 $as_echo "$OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OBJDUMP"; then ac_ct_OBJDUMP=$OBJDUMP # Extract the first word of "objdump", so it can be a program name with args. set dummy objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OBJDUMP"; then ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OBJDUMP="objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP if test -n "$ac_ct_OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 $as_echo "$ac_ct_OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OBJDUMP" = x; then OBJDUMP="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OBJDUMP=$ac_ct_OBJDUMP fi else OBJDUMP="$ac_cv_prog_OBJDUMP" fi test -z "$OBJDUMP" && OBJDUMP=objdump { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 $as_echo_n "checking how to recognize dependent libraries... " >&6; } if ${lt_cv_deplibs_check_method+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # 'unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # that responds to the $file_magic_cmd with a given extended regex. # If you have 'file' or equivalent on your system and you're not sure # whether 'pass_all' will *always* work, you probably want this one. case $host_os in aix[4-9]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[45]*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. if ( file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[3-9]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd* | bitrig*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; os2*) lt_cv_deplibs_check_method=pass_all ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 $as_echo "$lt_cv_deplibs_check_method" >&6; } file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. set dummy ${ac_tool_prefix}dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DLLTOOL"; then ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DLLTOOL=$ac_cv_prog_DLLTOOL if test -n "$DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 $as_echo "$DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DLLTOOL"; then ac_ct_DLLTOOL=$DLLTOOL # Extract the first word of "dlltool", so it can be a program name with args. set dummy dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DLLTOOL"; then ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DLLTOOL="dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL if test -n "$ac_ct_DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 $as_echo "$ac_ct_DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DLLTOOL" = x; then DLLTOOL="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DLLTOOL=$ac_ct_DLLTOOL fi else DLLTOOL="$ac_cv_prog_DLLTOOL" fi test -z "$DLLTOOL" && DLLTOOL=dlltool { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 $as_echo_n "checking how to associate runtime and link libraries... " >&6; } if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh; # decide which one to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd=$ECHO ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 $as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO if test -n "$ac_tool_prefix"; then for ac_prog in ar do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AR" && break done fi if test -z "$AR"; then ac_ct_AR=$AR for ac_prog in ar do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 $as_echo "$ac_ct_AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_AR" && break done if test "x$ac_ct_AR" = x; then AR="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi fi : ${AR=ar} : ${AR_FLAGS=cru} { $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 $as_echo_n "checking for archiver @FILE support... " >&6; } if ${lt_cv_ar_at_file+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ar_at_file=no cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test 0 -eq "$ac_status"; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test 0 -ne "$ac_status"; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 $as_echo "$lt_cv_ar_at_file" >&6; } if test no = "$lt_cv_ar_at_file"; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi test -z "$STRIP" && STRIP=: if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi test -z "$RANLIB" && RANLIB=: # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in bitrig* | openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Check for command to grab the raw symbol name followed by C symbol from nm. { $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 $as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } if ${lt_cv_sys_global_symbol_pipe+:} false; then : $as_echo_n "(cached) " >&6 else # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[BCDEGRST]' # Regexp to match symbols that can be accessed directly from C. sympat='\([_A-Za-z][_A-Za-z0-9]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[BCDT]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[ABCDGISTW]' ;; hpux*) if test ia64 = "$host_cpu"; then symcode='[ABCDEGRST]' fi ;; irix* | nonstopux*) symcode='[BCDEGRST]' ;; osf*) symcode='[BCDEGQRST]' ;; solaris*) symcode='[BDRT]' ;; sco3.2v5*) symcode='[DT]' ;; sysv4.2uw2*) symcode='[DT]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[ABDT]' ;; sysv4) symcode='[DFNSTU]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[ABCDGIRSTW]' ;; esac if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Gets list of data symbols to import. lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" # Adjust the below global symbol transforms to fixup imported variables. lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" lt_c_name_lib_hook="\ -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" else # Disable hooks by default. lt_cv_sys_global_symbol_to_import= lt_cdecl_hook= lt_c_name_hook= lt_c_name_lib_hook= fi # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n"\ $lt_cdecl_hook\ " -e 's/^T .* \(.*\)$/extern int \1();/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ $lt_c_name_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" # Transform an extracted symbol line into symbol name with lib prefix and # symbol address. lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ $lt_c_name_lib_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function, # D for any global variable and I for any imported variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK '"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ " /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ " /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ " {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ " s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Now try to grab the symbols. nlist=conftest.nm if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE /* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS=conftstm.$ac_objext CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest$ac_exeext; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&5 fi else echo "cannot find nm_test_var in $nlist" >&5 fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 fi else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test yes = "$pipe_works"; then break else lt_cv_sys_global_symbol_pipe= fi done fi if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 $as_echo "failed" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then nm_file_list_spec='@' fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 $as_echo_n "checking for sysroot... " >&6; } # Check whether --with-sysroot was given. if test "${with_sysroot+set}" = set; then : withval=$with_sysroot; else with_sysroot=no fi lt_sysroot= case $with_sysroot in #( yes) if test yes = "$GCC"; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5 $as_echo "$with_sysroot" >&6; } as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 $as_echo "${lt_sysroot:-no}" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5 $as_echo_n "checking for a working dd... " >&6; } if ${ac_cv_path_lt_DD+:} false; then : $as_echo_n "(cached) " >&6 else printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i : ${lt_DD:=$DD} if test -z "$lt_DD"; then ac_path_lt_DD_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in dd; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_lt_DD="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_lt_DD" || continue if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: fi $ac_path_lt_DD_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_lt_DD"; then : fi else ac_cv_path_lt_DD=$lt_DD fi rm -f conftest.i conftest2.i conftest.out fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5 $as_echo "$ac_cv_path_lt_DD" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5 $as_echo_n "checking how to truncate binary pipes... " >&6; } if ${lt_cv_truncate_bin+:} false; then : $as_echo_n "(cached) " >&6 else printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i lt_cv_truncate_bin= if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" fi rm -f conftest.i conftest2.i conftest.out test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5 $as_echo "$lt_cv_truncate_bin" >&6; } # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in $*""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } # Check whether --enable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then : enableval=$enable_libtool_lock; fi test no = "$enable_libtool_lock" || enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out what ABI is being produced by ac_compile, and set mode # options accordingly. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE=32 ;; *ELF-64*) HPUX_IA64_MODE=64 ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then if test yes = "$lt_cv_prog_gnu_ld"; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; mips64*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then emul=elf case `/usr/bin/file conftest.$ac_objext` in *32-bit*) emul="${emul}32" ;; *64-bit*) emul="${emul}64" ;; esac case `/usr/bin/file conftest.$ac_objext` in *MSB*) emul="${emul}btsmip" ;; *LSB*) emul="${emul}ltsmip" ;; esac case `/usr/bin/file conftest.$ac_objext` in *N32*) emul="${emul}n32" ;; esac LD="${LD-ld} -m $emul" fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. Note that the listed cases only cover the # situations where additional linker options are needed (such as when # doing 32-bit compilation for a host where ld defaults to 64-bit, or # vice versa); the common cases where no linker options are needed do # not appear in the list. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `/usr/bin/file conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*linux*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*linux*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -belf" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 $as_echo_n "checking whether the C compiler needs -belf... " >&6; } if ${lt_cv_cc_needs_belf+:} false; then : $as_echo_n "(cached) " >&6 else ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_cc_needs_belf=yes else lt_cv_cc_needs_belf=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 $as_echo "$lt_cv_cc_needs_belf" >&6; } if test yes != "$lt_cv_cc_needs_belf"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS=$SAVE_CFLAGS fi ;; *-*solaris*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*|x86_64-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD=${LD-ld}_sol2 fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks=$enable_libtool_lock if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. set dummy ${ac_tool_prefix}mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$MANIFEST_TOOL"; then ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL if test -n "$MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 $as_echo "$MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_MANIFEST_TOOL"; then ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL # Extract the first word of "mt", so it can be a program name with args. set dummy mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_MANIFEST_TOOL"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL if test -n "$ac_ct_MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 $as_echo "$ac_ct_MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_MANIFEST_TOOL" = x; then MANIFEST_TOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL fi else MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" fi test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 $as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } if ${lt_cv_path_mainfest_tool+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&5 if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 $as_echo "$lt_cv_path_mainfest_tool" >&6; } if test yes != "$lt_cv_path_mainfest_tool"; then MANIFEST_TOOL=: fi case $host_os in rhapsody* | darwin*) if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DSYMUTIL"; then ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DSYMUTIL=$ac_cv_prog_DSYMUTIL if test -n "$DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 $as_echo "$DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DSYMUTIL"; then ac_ct_DSYMUTIL=$DSYMUTIL # Extract the first word of "dsymutil", so it can be a program name with args. set dummy dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DSYMUTIL"; then ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL if test -n "$ac_ct_DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 $as_echo "$ac_ct_DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DSYMUTIL" = x; then DSYMUTIL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DSYMUTIL=$ac_ct_DSYMUTIL fi else DSYMUTIL="$ac_cv_prog_DSYMUTIL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. set dummy ${ac_tool_prefix}nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NMEDIT"; then ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi NMEDIT=$ac_cv_prog_NMEDIT if test -n "$NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 $as_echo "$NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_NMEDIT"; then ac_ct_NMEDIT=$NMEDIT # Extract the first word of "nmedit", so it can be a program name with args. set dummy nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_NMEDIT"; then ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_NMEDIT="nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT if test -n "$ac_ct_NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 $as_echo "$ac_ct_NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_NMEDIT" = x; then NMEDIT=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac NMEDIT=$ac_ct_NMEDIT fi else NMEDIT="$ac_cv_prog_NMEDIT" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. set dummy ${ac_tool_prefix}lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$LIPO"; then ac_cv_prog_LIPO="$LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_LIPO="${ac_tool_prefix}lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi LIPO=$ac_cv_prog_LIPO if test -n "$LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 $as_echo "$LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_LIPO"; then ac_ct_LIPO=$LIPO # Extract the first word of "lipo", so it can be a program name with args. set dummy lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_LIPO"; then ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_LIPO="lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO if test -n "$ac_ct_LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 $as_echo "$ac_ct_LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_LIPO" = x; then LIPO=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac LIPO=$ac_ct_LIPO fi else LIPO="$ac_cv_prog_LIPO" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. set dummy ${ac_tool_prefix}otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL"; then ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL="${ac_tool_prefix}otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL=$ac_cv_prog_OTOOL if test -n "$OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 $as_echo "$OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL"; then ac_ct_OTOOL=$OTOOL # Extract the first word of "otool", so it can be a program name with args. set dummy otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL"; then ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL="otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL if test -n "$ac_ct_OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 $as_echo "$ac_ct_OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL" = x; then OTOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL=$ac_ct_OTOOL fi else OTOOL="$ac_cv_prog_OTOOL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. set dummy ${ac_tool_prefix}otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL64"; then ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL64=$ac_cv_prog_OTOOL64 if test -n "$OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 $as_echo "$OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL64"; then ac_ct_OTOOL64=$OTOOL64 # Extract the first word of "otool64", so it can be a program name with args. set dummy otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL64"; then ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL64="otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 if test -n "$ac_ct_OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 $as_echo "$ac_ct_OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL64" = x; then OTOOL64=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL64=$ac_ct_OTOOL64 fi else OTOOL64="$ac_cv_prog_OTOOL64" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 $as_echo_n "checking for -single_module linker flag... " >&6; } if ${lt_cv_apple_cc_single_mod+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_apple_cc_single_mod=no if test -z "$LT_MULTI_MODULE"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&5 $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&5 # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test 0 = "$_lt_result"; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&5 fi rm -rf libconftest.dylib* rm -f conftest.* fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 $as_echo "$lt_cv_apple_cc_single_mod" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 $as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } if ${lt_cv_ld_exported_symbols_list+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_ld_exported_symbols_list=yes else lt_cv_ld_exported_symbols_list=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 $as_echo "$lt_cv_ld_exported_symbols_list" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 $as_echo_n "checking for -force_load linker flag... " >&6; } if ${lt_cv_ld_force_load+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 echo "$AR cru libconftest.a conftest.o" >&5 $AR cru libconftest.a conftest.o 2>&5 echo "$RANLIB libconftest.a" >&5 $RANLIB libconftest.a 2>&5 cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&5 elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then lt_cv_ld_force_load=yes else cat conftest.err >&5 fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 $as_echo "$lt_cv_ld_force_load" >&6; } case $host_os in rhapsody* | darwin1.[012]) _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[91]*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; 10.[012][,.]*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test yes = "$lt_cv_apple_cc_single_mod"; then _lt_dar_single_mod='$single_module' fi if test yes = "$lt_cv_ld_exported_symbols_list"; then _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' fi if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac # func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x$2 in x) ;; *:) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" ;; x:*) eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" ;; *::*) eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" ;; *) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" ;; esac } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in dlfcn.h do : ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default " if test "x$ac_cv_header_dlfcn_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_DLFCN_H 1 _ACEOF fi done func_stripname_cnf () { case $2 in .*) func_stripname_result=`$ECHO "$3" | $SED "s%^$1%%; s%\\\\$2\$%%"`;; *) func_stripname_result=`$ECHO "$3" | $SED "s%^$1%%; s%$2\$%%"`;; esac } # func_stripname_cnf # Set options # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then : enableval=$enable_shared; p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS=$lt_save_ifs ;; esac else enable_shared=no fi enable_win32_dll=yes case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}as", so it can be a program name with args. set dummy ${ac_tool_prefix}as; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AS+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AS"; then ac_cv_prog_AS="$AS" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AS="${ac_tool_prefix}as" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AS=$ac_cv_prog_AS if test -n "$AS"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AS" >&5 $as_echo "$AS" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_AS"; then ac_ct_AS=$AS # Extract the first word of "as", so it can be a program name with args. set dummy as; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AS+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AS"; then ac_cv_prog_ac_ct_AS="$ac_ct_AS" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AS="as" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AS=$ac_cv_prog_ac_ct_AS if test -n "$ac_ct_AS"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AS" >&5 $as_echo "$ac_ct_AS" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_AS" = x; then AS="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AS=$ac_ct_AS fi else AS="$ac_cv_prog_AS" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. set dummy ${ac_tool_prefix}dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DLLTOOL"; then ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DLLTOOL=$ac_cv_prog_DLLTOOL if test -n "$DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 $as_echo "$DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DLLTOOL"; then ac_ct_DLLTOOL=$DLLTOOL # Extract the first word of "dlltool", so it can be a program name with args. set dummy dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DLLTOOL"; then ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DLLTOOL="dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL if test -n "$ac_ct_DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 $as_echo "$ac_ct_DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DLLTOOL" = x; then DLLTOOL="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DLLTOOL=$ac_ct_DLLTOOL fi else DLLTOOL="$ac_cv_prog_DLLTOOL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OBJDUMP"; then ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OBJDUMP=$ac_cv_prog_OBJDUMP if test -n "$OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 $as_echo "$OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OBJDUMP"; then ac_ct_OBJDUMP=$OBJDUMP # Extract the first word of "objdump", so it can be a program name with args. set dummy objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OBJDUMP"; then ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OBJDUMP="objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP if test -n "$ac_ct_OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 $as_echo "$ac_ct_OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OBJDUMP" = x; then OBJDUMP="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OBJDUMP=$ac_ct_OBJDUMP fi else OBJDUMP="$ac_cv_prog_OBJDUMP" fi ;; esac test -z "$AS" && AS=as test -z "$DLLTOOL" && DLLTOOL=dlltool test -z "$OBJDUMP" && OBJDUMP=objdump enable_dlopen=no # Check whether --enable-static was given. if test "${enable_static+set}" = set; then : enableval=$enable_static; p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS=$lt_save_ifs ;; esac else enable_static=yes fi # Check whether --with-pic was given. if test "${with_pic+set}" = set; then : withval=$with_pic; lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for lt_pkg in $withval; do IFS=$lt_save_ifs if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS=$lt_save_ifs ;; esac else pic_mode=default fi # Check whether --enable-fast-install was given. if test "${enable_fast_install+set}" = set; then : enableval=$enable_fast_install; p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS=$lt_save_ifs ;; esac else enable_fast_install=yes fi shared_archive_member_spec= case $host,$enable_shared in power*-*-aix[5-9]*,yes) { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5 $as_echo_n "checking which variant of shared library versioning to provide... " >&6; } # Check whether --with-aix-soname was given. if test "${with_aix_soname+set}" = set; then : withval=$with_aix_soname; case $withval in aix|svr4|both) ;; *) as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5 ;; esac lt_cv_with_aix_soname=$with_aix_soname else if ${lt_cv_with_aix_soname+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_with_aix_soname=aix fi with_aix_soname=$lt_cv_with_aix_soname fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5 $as_echo "$with_aix_soname" >&6; } if test aix != "$with_aix_soname"; then # For the AIX way of multilib, we name the shared archive member # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, # the AIX toolchain works better with OBJECT_MODE set (default 32). if test 64 = "${OBJECT_MODE-32}"; then shared_archive_member_spec=shr_64 else shared_archive_member_spec=shr fi fi ;; *) with_aix_soname=aix ;; esac # This can be used to rebuild libtool when needed LIBTOOL_DEPS=$ltmain # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' test -z "$LN_S" && LN_S="ln -s" if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 $as_echo_n "checking for objdir... " >&6; } if ${lt_cv_objdir+:} false; then : $as_echo_n "(cached) " >&6 else rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 $as_echo "$lt_cv_objdir" >&6; } objdir=$lt_cv_objdir cat >>confdefs.h <<_ACEOF #define LT_OBJDIR "$lt_cv_objdir/" _ACEOF case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a '.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld=$lt_cv_prog_gnu_ld old_CC=$CC old_CFLAGS=$CFLAGS # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o func_cc_basename $compiler cc_basename=$func_cc_basename_result # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 $as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD=$MAGIC_CMD lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/${ac_tool_prefix}file"; then lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS=$lt_save_ifs MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac fi MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 $as_echo_n "checking for file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD=$MAGIC_CMD lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/file"; then lt_cv_path_MAGIC_CMD=$ac_dir/"file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS=$lt_save_ifs MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac fi MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else MAGIC_CMD=: fi fi fi ;; esac # Use C for the default configuration in the libtool script lt_save_CC=$CC ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o objext=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then lt_prog_compiler_no_builtin_flag= if test yes = "$GCC"; then case $cc_basename in nvcc*) lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; *) lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 $as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 $as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" else : fi fi lt_prog_compiler_wl= lt_prog_compiler_pic= lt_prog_compiler_static= if test yes = "$GCC"; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi lt_prog_compiler_pic='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic='-DDLL_EXPORT' case $host_os in os2*) lt_prog_compiler_static='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. lt_prog_compiler_static= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) lt_prog_compiler_pic='-fPIC' ;; esac ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic=-Kconform_pic fi ;; *) lt_prog_compiler_pic='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 lt_prog_compiler_wl='-Xlinker ' if test -n "$lt_prog_compiler_pic"; then lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl='-Wl,' if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' fi ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' case $cc_basename in nagfor*) # NAG Fortran compiler lt_prog_compiler_wl='-Wl,-Wl,,' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; esac ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' case $host_os in os2*) lt_prog_compiler_static='$wl-static' ;; esac ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static='$wl-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64, which still supported -KPIC. ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; # Lahey Fortran 8.1. lf95*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='--shared' lt_prog_compiler_static='--static' ;; nagfor*) # NAG Fortran compiler lt_prog_compiler_wl='-Wl,-Wl,,' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; tcc*) # Fabrice Bellard et al's Tiny C Compiler lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; ccc*) lt_prog_compiler_wl='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-qpic' lt_prog_compiler_static='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='' ;; *Sun\ F* | *Sun*Fortran*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Wl,' ;; *Intel*\ [CF]*Compiler*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; *Portland\ Group*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; esac ;; esac ;; newsos6) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static='-non_shared' ;; rdos*) lt_prog_compiler_static='-non_shared' ;; solaris*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) lt_prog_compiler_wl='-Qoption ld ';; *) lt_prog_compiler_wl='-Wl,';; esac ;; sunos4*) lt_prog_compiler_wl='-Qoption ld ' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic='-Kconform_pic' lt_prog_compiler_static='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; unicos*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_can_build_shared=no ;; uts4*) lt_prog_compiler_pic='-pic' lt_prog_compiler_static='-Bstatic' ;; *) lt_prog_compiler_can_build_shared=no ;; esac fi case $host_os in # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; *) lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if ${lt_cv_prog_compiler_pic+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic=$lt_prog_compiler_pic fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 $as_echo "$lt_cv_prog_compiler_pic" >&6; } lt_prog_compiler_pic=$lt_cv_prog_compiler_pic # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } if ${lt_cv_prog_compiler_pic_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic -DPIC" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 $as_echo "$lt_cv_prog_compiler_pic_works" >&6; } if test yes = "$lt_cv_prog_compiler_pic_works"; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; esac else lt_prog_compiler_pic= lt_prog_compiler_can_build_shared=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if ${lt_cv_prog_compiler_static_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works=yes fi else lt_cv_prog_compiler_static_works=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 $as_echo "$lt_cv_prog_compiler_static_works" >&6; } if test yes = "$lt_cv_prog_compiler_static_works"; then : else lt_prog_compiler_static= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } hard_links=nottested if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test no = "$hard_links"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } runpath_var= allow_undefined_flag= always_export_symbols=no archive_cmds= archive_expsym_cmds= compiler_needs_object=no enable_shared_with_static_runtimes=no export_dynamic_flag_spec= export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' hardcode_automatic=no hardcode_direct=no hardcode_direct_absolute=no hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_minus_L=no hardcode_shlibpath_var=unsupported inherit_rpath=no link_all_deplibs=unknown module_cmds= module_expsym_cmds= old_archive_from_new_cmds= old_archive_from_expsyms_cmds= thread_safe_flag_spec= whole_archive_flag_spec= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ' (' and ')$', so one must not match beginning or # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', # as well as any symbol that contains 'd'. exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test yes != "$GCC"; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd* | bitrig*) with_gnu_ld=no ;; linux* | k*bsd*-gnu | gnu*) link_all_deplibs=no ;; esac ld_shlibs=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test yes = "$with_gnu_ld"; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; *\ \(GNU\ Binutils\)\ [3-9]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test yes = "$lt_use_gnu_ld_interface"; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='$wl' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' export_dynamic_flag_spec='$wl--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else whole_archive_flag_spec= fi supports_anon_versioning=no case `$LD -v | $SED -e 's/(^)\+)\s\+//' 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test ia64 != "$host_cpu"; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else ld_shlibs=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' export_dynamic_flag_spec='$wl--export-all-symbols' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs=no fi ;; haiku*) archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' link_all_deplibs=yes ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported shrext_cmds=.dll archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' enable_shared_with_static_runtimes=yes ;; interix[3-9]*) hardcode_direct=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='$wl-rpath,$libdir' export_dynamic_flag_spec='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test linux-dietlibc = "$host_os"; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test no = "$tmp_diet" then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 whole_archive_flag_spec= tmp_sharedflag='--shared' ;; nagfor*) # NAGFOR 5.3 tmp_sharedflag='-Wl,-shared' ;; xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi case $cc_basename in tcc*) export_dynamic_flag_spec='-rdynamic' ;; xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test yes = "$supports_anon_versioning"; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else ld_shlibs=no fi ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac ;; sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct=yes hardcode_shlibpath_var=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac if test no = "$ld_shlibs"; then runpath_var= hardcode_libdir_flag_spec= export_dynamic_flag_spec= whole_archive_flag_spec= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag=unsupported always_export_symbols=yes archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix[4-9]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then aix_use_runtimelinking=yes break fi done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds='' hardcode_direct=yes hardcode_direct_absolute=yes hardcode_libdir_separator=':' link_all_deplibs=yes file_list_spec='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # traditional, no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. hardcode_direct=no hardcode_direct_absolute=no ;; esac if test yes = "$GCC"; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag="$shared_flag "'$wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi export_dynamic_flag_spec='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an # empty executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=/usr/lib:/lib fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=/usr/lib:/lib fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag=' $wl-bernotok' allow_undefined_flag=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec='$convenience' fi archive_cmds_need_lc=yes archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols archive_expsym_cmds="$archive_expsym_cmds"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; bsdi[45]*) export_dynamic_flag_spec=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported always_export_symbols=yes file_list_spec='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, )='true' enable_shared_with_static_runtimes=yes exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib old_postinstall_cmds='chmod 644 $oldlib' postlink_cmds='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_from_new_cmds='true' # FIXME: Should let the user specify the lib program. old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' enable_shared_with_static_runtimes=yes ;; esac ;; darwin* | rhapsody*) archive_cmds_need_lc=no hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported if test yes = "$lt_cv_ld_force_load"; then whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec='' fi link_all_deplibs=yes allow_undefined_flag=$_lt_dar_allow_undefined case $cc_basename in ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" archive_expsym_cmds="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" module_expsym_cmds="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" else ld_shlibs=no fi ;; dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9*) if test yes = "$GCC"; then archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes export_dynamic_flag_spec='$wl-E' ;; hpux10*) if test yes,no = "$GCC,$with_gnu_ld"; then archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test no = "$with_gnu_ld"; then hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test yes,no = "$GCC,$with_gnu_ld"; then case $host_cpu in hppa*64*) archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 $as_echo_n "checking if $CC understands -b... " >&6; } if ${lt_cv_prog_compiler__b+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler__b=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -b" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler__b=yes fi else lt_cv_prog_compiler__b=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 $as_echo "$lt_cv_prog_compiler__b" >&6; } if test yes = "$lt_cv_prog_compiler__b"; then archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi ;; esac fi if test no = "$with_gnu_ld"; then hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_direct=no hardcode_shlibpath_var=no ;; *) hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test yes = "$GCC"; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 $as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } if ${lt_cv_irix_exported_symbol+:} false; then : $as_echo_n "(cached) " >&6 else save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int foo (void) { return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_irix_exported_symbol=yes else lt_cv_irix_exported_symbol=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 $as_echo "$lt_cv_irix_exported_symbol" >&6; } if test yes = "$lt_cv_irix_exported_symbol"; then archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' fi link_all_deplibs=no else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: inherit_rpath=yes link_all_deplibs=yes ;; linux*) case $cc_basename in tcc*) # Fabrice Bellard et al's Tiny C Compiler ld_shlibs=yes archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; *nto* | *qnx*) ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes hardcode_shlibpath_var=no hardcode_direct_absolute=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec='$wl-rpath,$libdir' export_dynamic_flag_spec='$wl-E' else archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='$wl-rpath,$libdir' fi else ld_shlibs=no fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported shrext_cmds=.dll archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' enable_shared_with_static_runtimes=yes ;; osf3*) if test yes = "$GCC"; then allow_undefined_flag=' $wl-expect_unresolved $wl\*' archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test yes = "$GCC"; then allow_undefined_flag=' $wl-expect_unresolved $wl\*' archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi archive_cmds_need_lc='no' hardcode_libdir_separator=: ;; solaris*) no_undefined_flag=' -z defs' if test yes = "$GCC"; then wlarc='$wl' archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='$wl' archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi hardcode_libdir_flag_spec='-R$libdir' hardcode_shlibpath_var=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. GCC discards it without '$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test yes = "$GCC"; then whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' else whole_archive_flag_spec='-z allextract$convenience -z defaultextract' fi ;; esac link_all_deplibs=yes ;; sunos4*) if test sequent = "$host_vendor"; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; sysv4) case $host_vendor in sni) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds='$CC -r -o $output$reload_objs' hardcode_direct=no ;; motorola) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; sysv4.3*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag='$wl-z,text' archive_cmds_need_lc=no hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag='$wl-z,text' allow_undefined_flag='$wl-z,nodefs' archive_cmds_need_lc=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='$wl-R,$libdir' hardcode_libdir_separator=':' link_all_deplibs=yes export_dynamic_flag_spec='$wl-Bexport' runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; *) ld_shlibs=no ;; esac if test sni = "$host_vendor"; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) export_dynamic_flag_spec='$wl-Blargedynsym' ;; esac fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 $as_echo "$ld_shlibs" >&6; } test no = "$ld_shlibs" && can_build_shared=no with_gnu_ld=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc" in x|xyes) # Assume -lc should be added archive_cmds_need_lc=yes if test yes,yes = "$GCC,$enable_shared"; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } if ${lt_cv_archive_cmds_need_lc+:} false; then : $as_echo_n "(cached) " >&6 else $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl pic_flag=$lt_prog_compiler_pic compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag allow_undefined_flag= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then lt_cv_archive_cmds_need_lc=no else lt_cv_archive_cmds_need_lc=yes fi allow_undefined_flag=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 $as_echo "$lt_cv_archive_cmds_need_lc" >&6; } archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc ;; esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } if test yes = "$GCC"; then case $host_os in darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; *) lt_awk_arg='/^libraries:/' ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;; *) lt_sed_strip_eq='s|=/|/|g' ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary... lt_tmp_lt_search_path_spec= lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` # ...but if some path component already ends with the multilib dir we assume # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). case "$lt_multi_os_dir; $lt_search_path_spec " in "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) lt_multi_os_dir= ;; esac for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" elif test -n "$lt_multi_os_dir"; then test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS = " "; FS = "/|\n";} { lt_foo = ""; lt_count = 0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo = "/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[lt_foo]++; } if (lt_freq[lt_foo] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's|/\([A-Za-z]:\)|\1|g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='$libname$release$shared_ext$major' ;; aix[4-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line '#! .'. This would cause the generated library to # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # Using Import Files as archive members, it is possible to support # filename-based versioning of shared library archives on AIX. While # this would work for both with and without runtime linking, it will # prevent static linking of such archives. So we do filename-based # shared library versioning with .so extension only, which is used # when both runtime linking and shared linking is enabled. # Unfortunately, runtime linking may impact performance, so we do # not want this to be the default eventually. Also, we use the # versioned .so libs for executables only if there is the -brtl # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. # To allow for filename-based versioning support, we need to create # libNAME.so.V as an archive file, containing: # *) an Import File, referring to the versioned filename of the # archive as well as the shared archive member, telling the # bitwidth (32 or 64) of that shared object, and providing the # list of exported symbols of that shared object, eventually # decorated with the 'weak' keyword # *) the shared object with the F_LOADONLY flag set, to really avoid # it being seen by the linker. # At run time we better use the real file rather than another symlink, # but for link time we create the symlink libNAME.so -> libNAME.so.V case $with_aix_soname,$aix_use_runtimelinking in # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. aix,yes) # traditional libtool dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; aix,no) # traditional AIX only dynamic_linker='AIX lib.a(lib.so.V)' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' ;; svr4,*) # full svr4 only dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,yes) # both, prefer svr4 dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # unpreferred sharedlib libNAME.a needs extra handling postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,no) # both, prefer aix dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' ;; esac shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' library_names_spec='$libname.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[23].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[3-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; linux*android*) version_type=none # Android doesn't support versioned libraries. need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext' soname_spec='$libname$release$shared_ext' finish_cmds= shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes dynamic_linker='Android linker' # Don't embed -rpath directories since the linker doesn't support them. hardcode_libdir_flag_spec='-L$libdir' ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH if ${lt_cv_shlibpath_overrides_runpath+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : lt_cv_shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir fi shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not # being certain /sbin/ldconfig is available, command # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, # even though it is searched at run-time. Try to do the best guess by # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd* | bitrig*) version_type=sunos sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then need_version=no else need_version=yes fi library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no # OS/2 can only load a DLL with a base name of 8 characters or less. soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; v=$($ECHO $release$versuffix | tr -d .-); n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); $ECHO $n$v`$shared_ext' library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' shlibpath_var=BEGINLIBPATH sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=sco need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi # remember unaugmented sys_lib_dlsearch_path content for libtool script decls... configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec # ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" # to be used as default LT_SYS_LIBRARY_PATH value in generated libtool configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action= if test -n "$hardcode_libdir_flag_spec" || test -n "$runpath_var" || test yes = "$hardcode_automatic"; then # We can hardcode non-existent directories. if test no != "$hardcode_direct" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" && test no != "$hardcode_minus_L"; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action=unsupported fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 $as_echo "$hardcode_action" >&6; } if test relink = "$hardcode_action" || test yes = "$inherit_rpath"; then # Fast installation is not supported enable_fast_install=no elif test yes = "$shlibpath_overrides_runpath" || test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi if test yes != "$enable_dlopen"; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen=load_add_on lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen=LoadLibrary lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen=dlopen lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl else lt_cv_dlopen=dyld lt_cv_dlopen_libs= lt_cv_dlopen_self=yes fi ;; tpf*) # Don't try to run any link tests for TPF. We know it's impossible # because TPF is a cross-compiler, and we know how we open DSOs. lt_cv_dlopen=dlopen lt_cv_dlopen_libs= lt_cv_dlopen_self=no ;; *) ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" if test "x$ac_cv_func_shl_load" = xyes; then : lt_cv_dlopen=shl_load else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } if ${ac_cv_lib_dld_shl_load+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_shl_load=yes else ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes; then : lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld else ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" if test "x$ac_cv_func_dlopen" = xyes; then : lt_cv_dlopen=dlopen else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 $as_echo_n "checking for dlopen in -lsvld... " >&6; } if ${ac_cv_lib_svld_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_svld_dlopen=yes else ac_cv_lib_svld_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 $as_echo "$ac_cv_lib_svld_dlopen" >&6; } if test "x$ac_cv_lib_svld_dlopen" = xyes; then : lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 $as_echo_n "checking for dld_link in -ldld... " >&6; } if ${ac_cv_lib_dld_dld_link+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dld_link (); int main () { return dld_link (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_dld_link=yes else ac_cv_lib_dld_dld_link=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 $as_echo "$ac_cv_lib_dld_dld_link" >&6; } if test "x$ac_cv_lib_dld_dld_link" = xyes; then : lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld fi fi fi fi fi fi ;; esac if test no = "$lt_cv_dlopen"; then enable_dlopen=no else enable_dlopen=yes fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS=$CPPFLAGS test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS=$LDFLAGS wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS=$LIBS LIBS="$lt_cv_dlopen_libs $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 $as_echo_n "checking whether a program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self+:} false; then : $as_echo_n "(cached) " >&6 else if test yes = "$cross_compiling"; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed lt_cv_dlopen_self=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 $as_echo "$lt_cv_dlopen_self" >&6; } if test yes = "$lt_cv_dlopen_self"; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 $as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self_static+:} false; then : $as_echo_n "(cached) " >&6 else if test yes = "$cross_compiling"; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed lt_cv_dlopen_self_static=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 $as_echo "$lt_cv_dlopen_self_static" >&6; } fi CPPFLAGS=$save_CPPFLAGS LDFLAGS=$save_LDFLAGS LIBS=$save_LIBS ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi striplib= old_striplib= { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 $as_echo_n "checking whether stripping libraries is possible... " >&6; } if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP"; then striplib="$STRIP -x" old_striplib="$STRIP -S" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac fi # Report what library types will actually be built { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 $as_echo_n "checking if libtool supports shared libraries... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 $as_echo "$can_build_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 $as_echo_n "checking whether to build shared libraries... " >&6; } test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[4-9]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 $as_echo "$enable_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 $as_echo_n "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 $as_echo "$enable_static" >&6; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC=$lt_save_CC if test -n "$CXX" && ( test no != "$CXX" && ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || (test g++ != "$CXX"))); then ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 $as_echo_n "checking how to run the C++ preprocessor... " >&6; } if test -z "$CXXCPP"; then if ${ac_cv_prog_CXXCPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CXXCPP needs to be expanded for CXXCPP in "$CXX -E" "/lib/cpp" do ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CXXCPP=$CXXCPP fi CXXCPP=$ac_cv_prog_CXXCPP else ac_cv_prog_CXXCPP=$CXXCPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 $as_echo "$CXXCPP" >&6; } ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu else _lt_caught_CXX_error=yes fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu archive_cmds_need_lc_CXX=no allow_undefined_flag_CXX= always_export_symbols_CXX=no archive_expsym_cmds_CXX= compiler_needs_object_CXX=no export_dynamic_flag_spec_CXX= hardcode_direct_CXX=no hardcode_direct_absolute_CXX=no hardcode_libdir_flag_spec_CXX= hardcode_libdir_separator_CXX= hardcode_minus_L_CXX=no hardcode_shlibpath_var_CXX=unsupported hardcode_automatic_CXX=no inherit_rpath_CXX=no module_cmds_CXX= module_expsym_cmds_CXX= link_all_deplibs_CXX=unknown old_archive_cmds_CXX=$old_archive_cmds reload_flag_CXX=$reload_flag reload_cmds_CXX=$reload_cmds no_undefined_flag_CXX= whole_archive_flag_spec_CXX= enable_shared_with_static_runtimes_CXX=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o objext_CXX=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_caught_CXX_error"; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} CFLAGS=$CXXFLAGS compiler=$CC compiler_CXX=$CC func_cc_basename $compiler cc_basename=$func_cc_basename_result if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test yes = "$GXX"; then lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin' else lt_prog_compiler_no_builtin_flag_CXX= fi if test yes = "$GXX"; then # Set up default GNU C++ configuration # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test yes = "$with_gnu_ld"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if ${lt_cv_prog_gnu_ld+:} false; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test yes = "$with_gnu_ld"; then archive_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='$wl' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec_CXX=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else whole_archive_flag_spec_CXX= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } ld_shlibs_CXX=yes case $host_os in aix3*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aix[4-9]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds_CXX='' hardcode_direct_CXX=yes hardcode_direct_absolute_CXX=yes hardcode_libdir_separator_CXX=':' link_all_deplibs_CXX=yes file_list_spec_CXX='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. hardcode_direct_CXX=no hardcode_direct_absolute_CXX=no ;; esac if test yes = "$GXX"; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct_CXX=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L_CXX=yes hardcode_libdir_flag_spec_CXX='-L$libdir' hardcode_libdir_separator_CXX= fi esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag=$shared_flag' $wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi export_dynamic_flag_spec_CXX='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. always_export_symbols_CXX=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. # The "-G" linker flag allows undefined symbols. no_undefined_flag_CXX='-bernotok' # Determine the default libpath from the value encoded in an empty # executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath__CXX+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX=/usr/lib:/lib fi fi aix_libpath=$lt_cv_aix_libpath__CXX fi hardcode_libdir_flag_spec_CXX='$wl-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then hardcode_libdir_flag_spec_CXX='$wl-R $libdir:/usr/lib:/lib' allow_undefined_flag_CXX="-z nodefs" archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath__CXX+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX=/usr/lib:/lib fi fi aix_libpath=$lt_cv_aix_libpath__CXX fi hardcode_libdir_flag_spec_CXX='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag_CXX=' $wl-bernotok' allow_undefined_flag_CXX=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. whole_archive_flag_spec_CXX='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec_CXX='$convenience' fi archive_cmds_need_lc_CXX=yes archive_expsym_cmds_CXX='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$RM -r $output_objdir/$realname.d' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag_CXX=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else ld_shlibs_CXX=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in ,cl* | no,cl*) # Native MSVC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec_CXX=' ' allow_undefined_flag_CXX=unsupported always_export_symbols_CXX=yes file_list_spec_CXX='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. archive_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' archive_expsym_cmds_CXX='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, CXX)='true' enable_shared_with_static_runtimes_CXX=yes # Don't use ranlib old_postinstall_cmds_CXX='chmod 644 $oldlib' postlink_cmds_CXX='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ func_to_tool_file "$lt_outputfile"~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec_CXX='-L$libdir' export_dynamic_flag_spec_CXX='$wl--export-all-symbols' allow_undefined_flag_CXX=unsupported always_export_symbols_CXX=no enable_shared_with_static_runtimes_CXX=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... archive_expsym_cmds_CXX='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs_CXX=no fi ;; esac ;; darwin* | rhapsody*) archive_cmds_need_lc_CXX=no hardcode_direct_CXX=no hardcode_automatic_CXX=yes hardcode_shlibpath_var_CXX=unsupported if test yes = "$lt_cv_ld_force_load"; then whole_archive_flag_spec_CXX='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec_CXX='' fi link_all_deplibs_CXX=yes allow_undefined_flag_CXX=$_lt_dar_allow_undefined case $cc_basename in ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" archive_expsym_cmds_CXX="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" module_expsym_cmds_CXX="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" if test yes != "$lt_cv_apple_cc_single_mod"; then archive_cmds_CXX="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" archive_expsym_cmds_CXX="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" fi else ld_shlibs_CXX=no fi ;; os2*) hardcode_libdir_flag_spec_CXX='-L$libdir' hardcode_minus_L_CXX=yes allow_undefined_flag_CXX=unsupported shrext_cmds=.dll archive_cmds_CXX='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' archive_expsym_cmds_CXX='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' old_archive_From_new_cmds_CXX='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' enable_shared_with_static_runtimes_CXX=yes ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF ld_shlibs_CXX=no ;; freebsd-elf*) archive_cmds_need_lc_CXX=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions ld_shlibs_CXX=yes ;; haiku*) archive_cmds_CXX='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' link_all_deplibs_CXX=yes ;; hpux9*) hardcode_libdir_flag_spec_CXX='$wl+b $wl$libdir' hardcode_libdir_separator_CXX=: export_dynamic_flag_spec_CXX='$wl-E' hardcode_direct_CXX=yes hardcode_minus_L_CXX=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aCC*) archive_cmds_CXX='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then archive_cmds_CXX='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; hpux10*|hpux11*) if test no = "$with_gnu_ld"; then hardcode_libdir_flag_spec_CXX='$wl+b $wl$libdir' hardcode_libdir_separator_CXX=: case $host_cpu in hppa*64*|ia64*) ;; *) export_dynamic_flag_spec_CXX='$wl-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) hardcode_direct_CXX=no hardcode_shlibpath_var_CXX=no ;; *) hardcode_direct_CXX=yes hardcode_direct_absolute_CXX=yes hardcode_minus_L_CXX=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aCC*) case $host_cpu in hppa*64*) archive_cmds_CXX='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) archive_cmds_CXX='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) archive_cmds_CXX='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then case $host_cpu in hppa*64*) archive_cmds_CXX='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) archive_cmds_CXX='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) archive_cmds_CXX='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; interix[3-9]*) hardcode_direct_CXX=no hardcode_shlibpath_var_CXX=no hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' export_dynamic_flag_spec_CXX='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds_CXX='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' fi fi link_all_deplibs_CXX=yes ;; esac hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' hardcode_libdir_separator_CXX=: inherit_rpath_CXX=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac archive_cmds_need_lc_CXX=no hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' whole_archive_flag_spec_CXX='$wl--whole-archive$convenience $wl--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [1-5].* | *pgcpp\ [1-5].*) prelink_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' old_archive_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' archive_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac hardcode_libdir_flag_spec_CXX='$wl--rpath $wl$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' whole_archive_flag_spec_CXX='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' ;; cxx*) # Compaq C++ archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec_CXX='-rpath $libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' archive_cmds_CXX='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then archive_expsym_cmds_CXX='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 no_undefined_flag_CXX=' -zdefs' archive_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' archive_expsym_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' hardcode_libdir_flag_spec_CXX='-R$libdir' whole_archive_flag_spec_CXX='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object_CXX=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; m88k*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= hardcode_libdir_flag_spec_CXX='-R$libdir' hardcode_direct_CXX=yes hardcode_shlibpath_var_CXX=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) ld_shlibs_CXX=yes ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then hardcode_direct_CXX=yes hardcode_shlibpath_var_CXX=no hardcode_direct_absolute_CXX=yes archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' export_dynamic_flag_spec_CXX='$wl-E' whole_archive_flag_spec_CXX=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else ld_shlibs_CXX=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' hardcode_libdir_separator_CXX=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; *) old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; cxx*) case $host in osf3*) allow_undefined_flag_CXX=' $wl-expect_unresolved $wl\*' archive_cmds_CXX='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' ;; *) allow_undefined_flag_CXX=' -expect_unresolved \*' archive_cmds_CXX='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ $RM $lib.exp' hardcode_libdir_flag_spec_CXX='-rpath $libdir' ;; esac hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes,no = "$GXX,$with_gnu_ld"; then allow_undefined_flag_CXX=' $wl-expect_unresolved $wl\*' case $host in osf3*) archive_cmds_CXX='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; *) archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; esac hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ archive_cmds_need_lc_CXX=yes no_undefined_flag_CXX=' -zdefs' archive_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' hardcode_libdir_flag_spec_CXX='-R$libdir' hardcode_shlibpath_var_CXX=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) whole_archive_flag_spec_CXX='-z allextract$convenience -z defaultextract' ;; esac link_all_deplibs_CXX=yes output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test yes,no = "$GXX,$with_gnu_ld"; then no_undefined_flag_CXX=' $wl-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # g++ 2.7 appears to require '-G' NOT '-shared' on this # platform. archive_cmds_CXX='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' fi hardcode_libdir_flag_spec_CXX='$wl-R $wl$libdir' case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) whole_archive_flag_spec_CXX='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag_CXX='$wl-z,text' archive_cmds_need_lc_CXX=no hardcode_shlibpath_var_CXX=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) archive_cmds_CXX='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds_CXX='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag_CXX='$wl-z,text' allow_undefined_flag_CXX='$wl-z,nodefs' archive_cmds_need_lc_CXX=no hardcode_shlibpath_var_CXX=no hardcode_libdir_flag_spec_CXX='$wl-R,$libdir' hardcode_libdir_separator_CXX=':' link_all_deplibs_CXX=yes export_dynamic_flag_spec_CXX='$wl-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) archive_cmds_CXX='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' old_archive_cmds_CXX='$CC -Tprelink_objects $oldobjs~ '"$old_archive_cmds_CXX" reload_cmds_CXX='$CC -Tprelink_objects $reload_objs~ '"$reload_cmds_CXX" ;; *) archive_cmds_CXX='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 $as_echo "$ld_shlibs_CXX" >&6; } test no = "$ld_shlibs_CXX" && can_build_shared=no GCC_CXX=$GXX LD_CXX=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... # Dependencies to place before and after the object being linked: predep_objects_CXX= postdep_objects_CXX= predeps_CXX= postdeps_CXX= compiler_lib_search_path_CXX= cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF _lt_libdeps_save_CFLAGS=$CFLAGS case "$CC $CFLAGS " in #( *\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; *\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; *\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; esac if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case $prev$p in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test x-L = "$p" || test x-R = "$p"; then prev=$p continue fi # Expand the sysroot to ease extracting the directories later. if test -z "$prev"; then case $p in -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; esac fi case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac if test no = "$pre_test_object_deps_done"; then case $prev in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$compiler_lib_search_path_CXX"; then compiler_lib_search_path_CXX=$prev$p else compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} $prev$p" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$postdeps_CXX"; then postdeps_CXX=$prev$p else postdeps_CXX="${postdeps_CXX} $prev$p" fi fi prev= ;; *.lto.$objext) ;; # Ignore GCC LTO objects *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test no = "$pre_test_object_deps_done"; then if test -z "$predep_objects_CXX"; then predep_objects_CXX=$p else predep_objects_CXX="$predep_objects_CXX $p" fi else if test -z "$postdep_objects_CXX"; then postdep_objects_CXX=$p else postdep_objects_CXX="$postdep_objects_CXX $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling CXX test program" fi $RM -f confest.$objext CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken case $host_os in interix[3-9]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. predep_objects_CXX= postdep_objects_CXX= postdeps_CXX= ;; esac case " $postdeps_CXX " in *" -lc "*) archive_cmds_need_lc_CXX=no ;; esac compiler_lib_search_dirs_CXX= if test -n "${compiler_lib_search_path_CXX}"; then compiler_lib_search_dirs_CXX=`echo " ${compiler_lib_search_path_CXX}" | $SED -e 's! -L! !g' -e 's!^ !!'` fi lt_prog_compiler_wl_CXX= lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX= # C++ specific cases for pic, static, wl, etc. if test yes = "$GXX"; then lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_CXX='-Bstatic' fi lt_prog_compiler_pic_CXX='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic_CXX='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic_CXX='-DDLL_EXPORT' case $host_os in os2*) lt_prog_compiler_static_CXX='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic_CXX='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all lt_prog_compiler_pic_CXX= ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. lt_prog_compiler_static_CXX= ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic_CXX=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) lt_prog_compiler_pic_CXX='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic_CXX='-fPIC -shared' ;; *) lt_prog_compiler_pic_CXX='-fPIC' ;; esac else case $host_os in aix[4-9]*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_CXX='-Bstatic' else lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic_CXX='-DDLL_EXPORT' ;; dgux*) case $cc_basename in ec++*) lt_prog_compiler_pic_CXX='-KPIC' ;; ghcx*) # Green Hills C++ Compiler lt_prog_compiler_pic_CXX='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='$wl-a ${wl}archive' if test ia64 != "$host_cpu"; then lt_prog_compiler_pic_CXX='+Z' fi ;; aCC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='$wl-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic_CXX='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # KAI C++ Compiler lt_prog_compiler_wl_CXX='--backend -Wl,' lt_prog_compiler_pic_CXX='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64, which still supported -KPIC. lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-fPIC' lt_prog_compiler_static_CXX='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-fpic' lt_prog_compiler_static_CXX='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX='-non_shared' ;; xlc* | xlC* | bgxl[cC]* | mpixl[cC]*) # IBM XL 8.0, 9.0 on PPC and BlueGene lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-qpic' lt_prog_compiler_static_CXX='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' lt_prog_compiler_wl_CXX='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) lt_prog_compiler_pic_CXX='-W c,exportall' ;; *) ;; esac ;; netbsd* | netbsdelf*-gnu) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic_CXX='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) lt_prog_compiler_wl_CXX='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 lt_prog_compiler_pic_CXX='-pic' ;; cxx*) # Digital/Compaq C++ lt_prog_compiler_wl_CXX='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' lt_prog_compiler_wl_CXX='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler lt_prog_compiler_pic_CXX='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x lt_prog_compiler_pic_CXX='-pic' lt_prog_compiler_static_CXX='-Bstatic' ;; lcc*) # Lucid lt_prog_compiler_pic_CXX='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 lt_prog_compiler_pic_CXX='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) lt_prog_compiler_can_build_shared_CXX=no ;; esac fi case $host_os in # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic_CXX= ;; *) lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if ${lt_cv_prog_compiler_pic_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_CXX=$lt_prog_compiler_pic_CXX fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_CXX" >&5 $as_echo "$lt_cv_prog_compiler_pic_CXX" >&6; } lt_prog_compiler_pic_CXX=$lt_cv_prog_compiler_pic_CXX # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic_CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... " >&6; } if ${lt_cv_prog_compiler_pic_works_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works_CXX=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works_CXX=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works_CXX" >&5 $as_echo "$lt_cv_prog_compiler_pic_works_CXX" >&6; } if test yes = "$lt_cv_prog_compiler_pic_works_CXX"; then case $lt_prog_compiler_pic_CXX in "" | " "*) ;; *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; esac else lt_prog_compiler_pic_CXX= lt_prog_compiler_can_build_shared_CXX=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if ${lt_cv_prog_compiler_static_works_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works_CXX=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works_CXX=yes fi else lt_cv_prog_compiler_static_works_CXX=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works_CXX" >&5 $as_echo "$lt_cv_prog_compiler_static_works_CXX" >&6; } if test yes = "$lt_cv_prog_compiler_static_works_CXX"; then : else lt_prog_compiler_static_CXX= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o_CXX=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o_CXX=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 $as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o_CXX=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o_CXX=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 $as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } hard_links=nottested if test no = "$lt_cv_prog_compiler_c_o_CXX" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test no = "$hard_links"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' case $host_os in aix[4-9]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else export_symbols_cmds_CXX='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi ;; pw32*) export_symbols_cmds_CXX=$ltdll_cmds ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl*) exclude_expsyms_CXX='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms_CXX='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' ;; esac ;; linux* | k*bsd*-gnu | gnu*) link_all_deplibs_CXX=no ;; *) export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 $as_echo "$ld_shlibs_CXX" >&6; } test no = "$ld_shlibs_CXX" && can_build_shared=no with_gnu_ld_CXX=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc_CXX" in x|xyes) # Assume -lc should be added archive_cmds_need_lc_CXX=yes if test yes,yes = "$GCC,$enable_shared"; then case $archive_cmds_CXX in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } if ${lt_cv_archive_cmds_need_lc_CXX+:} false; then : $as_echo_n "(cached) " >&6 else $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl_CXX pic_flag=$lt_prog_compiler_pic_CXX compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag_CXX allow_undefined_flag_CXX= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then lt_cv_archive_cmds_need_lc_CXX=no else lt_cv_archive_cmds_need_lc_CXX=yes fi allow_undefined_flag_CXX=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc_CXX" >&5 $as_echo "$lt_cv_archive_cmds_need_lc_CXX" >&6; } archive_cmds_need_lc_CXX=$lt_cv_archive_cmds_need_lc_CXX ;; esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='$libname$release$shared_ext$major' ;; aix[4-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line '#! .'. This would cause the generated library to # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # Using Import Files as archive members, it is possible to support # filename-based versioning of shared library archives on AIX. While # this would work for both with and without runtime linking, it will # prevent static linking of such archives. So we do filename-based # shared library versioning with .so extension only, which is used # when both runtime linking and shared linking is enabled. # Unfortunately, runtime linking may impact performance, so we do # not want this to be the default eventually. Also, we use the # versioned .so libs for executables only if there is the -brtl # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. # To allow for filename-based versioning support, we need to create # libNAME.so.V as an archive file, containing: # *) an Import File, referring to the versioned filename of the # archive as well as the shared archive member, telling the # bitwidth (32 or 64) of that shared object, and providing the # list of exported symbols of that shared object, eventually # decorated with the 'weak' keyword # *) the shared object with the F_LOADONLY flag set, to really avoid # it being seen by the linker. # At run time we better use the real file rather than another symlink, # but for link time we create the symlink libNAME.so -> libNAME.so.V case $with_aix_soname,$aix_use_runtimelinking in # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. aix,yes) # traditional libtool dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; aix,no) # traditional AIX only dynamic_linker='AIX lib.a(lib.so.V)' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' ;; svr4,*) # full svr4 only dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,yes) # both, prefer svr4 dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # unpreferred sharedlib libNAME.a needs extra handling postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,no) # both, prefer aix dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' ;; esac shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' library_names_spec='$libname.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[23].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[3-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; linux*android*) version_type=none # Android doesn't support versioned libraries. need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext' soname_spec='$libname$release$shared_ext' finish_cmds= shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes dynamic_linker='Android linker' # Don't embed -rpath directories since the linker doesn't support them. hardcode_libdir_flag_spec_CXX='-L$libdir' ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH if ${lt_cv_shlibpath_overrides_runpath+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl_CXX\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec_CXX\"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : lt_cv_shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir fi shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not # being certain /sbin/ldconfig is available, command # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, # even though it is searched at run-time. Try to do the best guess by # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd* | bitrig*) version_type=sunos sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then need_version=no else need_version=yes fi library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no # OS/2 can only load a DLL with a base name of 8 characters or less. soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; v=$($ECHO $release$versuffix | tr -d .-); n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); $ECHO $n$v`$shared_ext' library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' shlibpath_var=BEGINLIBPATH sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=sco need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi # remember unaugmented sys_lib_dlsearch_path content for libtool script decls... configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec # ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" # to be used as default LT_SYS_LIBRARY_PATH value in generated libtool configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action_CXX= if test -n "$hardcode_libdir_flag_spec_CXX" || test -n "$runpath_var_CXX" || test yes = "$hardcode_automatic_CXX"; then # We can hardcode non-existent directories. if test no != "$hardcode_direct_CXX" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, CXX)" && test no != "$hardcode_minus_L_CXX"; then # Linking always hardcodes the temporary library directory. hardcode_action_CXX=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action_CXX=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action_CXX=unsupported fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action_CXX" >&5 $as_echo "$hardcode_action_CXX" >&6; } if test relink = "$hardcode_action_CXX" || test yes = "$inherit_rpath_CXX"; then # Fast installation is not supported enable_fast_install=no elif test yes = "$shlibpath_overrides_runpath" || test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi fi # test -n "$compiler" CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test yes != "$_lt_caught_CXX_error" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_config_commands="$ac_config_commands libtool" # Only expand once: if test -n "$ac_tool_prefix"; then for ac_prog in windres do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_WINDRES+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$WINDRES"; then ac_cv_prog_WINDRES="$WINDRES" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_WINDRES="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi WINDRES=$ac_cv_prog_WINDRES if test -n "$WINDRES"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WINDRES" >&5 $as_echo "$WINDRES" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$WINDRES" && break done fi if test -z "$WINDRES"; then ac_ct_WINDRES=$WINDRES for ac_prog in windres do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_WINDRES+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_WINDRES"; then ac_cv_prog_ac_ct_WINDRES="$ac_ct_WINDRES" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_WINDRES="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_WINDRES=$ac_cv_prog_ac_ct_WINDRES if test -n "$ac_ct_WINDRES"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_WINDRES" >&5 $as_echo "$ac_ct_WINDRES" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_WINDRES" && break done if test "x$ac_ct_WINDRES" = x; then WINDRES="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac WINDRES=$ac_ct_WINDRES fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 $as_echo_n "checking whether byte ordering is bigendian... " >&6; } if ${ac_cv_c_bigendian+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_bigendian=unknown # See if we're dealing with a universal compiler. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __APPLE_CC__ not a universal capable compiler #endif typedef int dummy; _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # Check for potential -arch flags. It is not universal unless # there are at least two -arch flags with different values. ac_arch= ac_prev= for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do if test -n "$ac_prev"; then case $ac_word in i?86 | x86_64 | ppc | ppc64) if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then ac_arch=$ac_word else ac_cv_c_bigendian=universal break fi ;; esac ac_prev= elif test "x$ac_word" = "x-arch"; then ac_prev=arch fi done fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_c_bigendian = unknown; then # See if sys/param.h defines the BYTE_ORDER macro. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { #if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ && LITTLE_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # It does; now see whether it defined to BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { #if BYTE_ORDER != BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_bigendian=yes else ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { #if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # It does; now see whether it defined to _BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { #ifndef _BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_bigendian=yes else ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # Compile a test program. if test "$cross_compiling" = yes; then : # Try to guess by grepping values from an object file. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; int use_ascii (int i) { return ascii_mm[i] + ascii_ii[i]; } short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; int use_ebcdic (int i) { return ebcdic_mm[i] + ebcdic_ii[i]; } extern int foo; int main () { return use_ascii (foo) == use_ebcdic (foo); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then ac_cv_c_bigendian=yes fi if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then if test "$ac_cv_c_bigendian" = unknown; then ac_cv_c_bigendian=no else # finding both strings is unlikely to happen, but who knows? ac_cv_c_bigendian=unknown fi fi fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { /* Are we little or big endian? From Harbison&Steele. */ union { long int l; char c[sizeof (long int)]; } u; u.l = 1; return u.c[sizeof (long int) - 1] == 1; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_c_bigendian=no else ac_cv_c_bigendian=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 $as_echo "$ac_cv_c_bigendian" >&6; } case $ac_cv_c_bigendian in #( yes) $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h ;; #( no) ;; #( universal) $as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h ;; #( *) as_fn_error $? "unknown endianness presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 $as_echo_n "checking for inline... " >&6; } if ${ac_cv_c_inline+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __cplusplus typedef int foo_t; static $ac_kw foo_t static_foo () {return 0; } $ac_kw foo_t foo () {return 0; } #endif _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_inline=$ac_kw fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext test "$ac_cv_c_inline" != no && break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 $as_echo "$ac_cv_c_inline" >&6; } case $ac_cv_c_inline in inline | yes) ;; *) case $ac_cv_c_inline in no) ac_val=;; *) ac_val=$ac_cv_c_inline;; esac cat >>confdefs.h <<_ACEOF #ifndef __cplusplus #define inline $ac_val #endif _ACEOF ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working volatile" >&5 $as_echo_n "checking for working volatile... " >&6; } if ${ac_cv_c_volatile+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { volatile int x; int * volatile y = (int *) 0; return !x && !y; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_volatile=yes else ac_cv_c_volatile=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_volatile" >&5 $as_echo "$ac_cv_c_volatile" >&6; } if test $ac_cv_c_volatile = no; then $as_echo "#define volatile /**/" >>confdefs.h fi if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PKG_CONFIG=$ac_cv_path_PKG_CONFIG if test -n "$PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 $as_echo "$PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_path_PKG_CONFIG"; then ac_pt_PKG_CONFIG=$PKG_CONFIG # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $ac_pt_PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG if test -n "$ac_pt_PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 $as_echo "$ac_pt_PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_pt_PKG_CONFIG" = x; then PKG_CONFIG="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac PKG_CONFIG=$ac_pt_PKG_CONFIG fi else PKG_CONFIG="$ac_cv_path_PKG_CONFIG" fi fi if test -n "$PKG_CONFIG"; then _pkg_min_version=0.9.0 { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 $as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } PKG_CONFIG="" fi fi for ac_prog in doxygen do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DOXYGEN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DOXYGEN"; then ac_cv_prog_DOXYGEN="$DOXYGEN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DOXYGEN="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DOXYGEN=$ac_cv_prog_DOXYGEN if test -n "$DOXYGEN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DOXYGEN" >&5 $as_echo "$DOXYGEN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$DOXYGEN" && break done if test x$DOXYGEN = xdoxygen; then HAVE_DOXYGEN_TRUE= HAVE_DOXYGEN_FALSE='#' else HAVE_DOXYGEN_TRUE='#' HAVE_DOXYGEN_FALSE= fi pentium=no cpu64=no case "$host_cpu" in i586 | i686 | i786 ) pentium=yes $as_echo "#define PENTIUM 1" >>confdefs.h ;; x86_64* ) pentium=yes cpu64=yes $as_echo "#define X86_64_SYSTEM 1" >>confdefs.h ;; esac if test x$cpu64 = xyes; then X86_64_SYSTEM_TRUE= X86_64_SYSTEM_FALSE='#' else X86_64_SYSTEM_TRUE='#' X86_64_SYSTEM_FALSE= fi for ac_header in alloca.h stdio.h inttypes.h stdint.h stdlib.h math.h \ string.h stdarg.h malloc.h float.h time.h sys/time.h \ limits.h stddef.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done opcode=no gimpact=no # Check whether --with-trimesh was given. if test "${with_trimesh+set}" = set; then : withval=$with_trimesh; trimesh=$withval else trimesh=opcode fi if test "$trimesh" = opcode then opcode=yes fi if test "$trimesh" = gimpact then gimpact=yes fi if test $opcode = yes; then OPCODE_TRUE= OPCODE_FALSE='#' else OPCODE_TRUE='#' OPCODE_FALSE= fi if test $gimpact = yes; then GIMPACT_TRUE= GIMPACT_FALSE='#' else GIMPACT_TRUE='#' GIMPACT_FALSE= fi if test $opcode = yes -o $gimpact = yes; then TRIMESH_TRUE= TRIMESH_FALSE='#' else TRIMESH_TRUE='#' TRIMESH_FALSE= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if double precision is requested" >&5 $as_echo_n "checking if double precision is requested... " >&6; } # Check whether --enable-double-precision was given. if test "${enable_double_precision+set}" = set; then : enableval=$enable_double_precision; usedouble=$enableval else usedouble=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $usedouble" >&5 $as_echo "$usedouble" >&6; } if test "$usedouble" = yes; then ODE_PRECISION=dDOUBLE else ODE_PRECISION=dSINGLE fi # Check whether --with-drawstuff was given. if test "${with_drawstuff+set}" = set; then : withval=$with_drawstuff; drawstuff=$withval else drawstuff= fi EXTRA_LIBTOOL_LDFLAGS= case "$host_os" in cygwin* | mingw*) if test "x$drawstuff" = x then drawstuff="Win32" # if in a Windows enviroment fi EXTRA_LIBTOOL_LDFLAGS="-no-undefined" ;; *apple* | *darwin*) # For Mac OS X if test "x$drawstuff" = x then drawstuff="OSX" fi CC="$CXX" LINK="$CXXLINK" ;; *) if test "x$drawstuff" = x then drawstuff="X11" # if anything else default to X11 fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking which drawstuff lib to build" >&5 $as_echo_n "checking which drawstuff lib to build... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $drawstuff" >&5 $as_echo "$drawstuff" >&6; } if test "x$drawstuff" = "xX11" then # The built-in macro, X_PATH, causes too many problems, these days everyone uses Xorg, # so we can ask pkg-config to find it for us. pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for X11" >&5 $as_echo_n "checking for X11... " >&6; } if test -n "$X11_CFLAGS"; then pkg_cv_X11_CFLAGS="$X11_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"x11\""; } >&5 ($PKG_CONFIG --exists --print-errors "x11") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_X11_CFLAGS=`$PKG_CONFIG --cflags "x11" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$X11_LIBS"; then pkg_cv_X11_LIBS="$X11_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"x11\""; } >&5 ($PKG_CONFIG --exists --print-errors "x11") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_X11_LIBS=`$PKG_CONFIG --libs "x11" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then X11_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "x11" 2>&1` else X11_PKG_ERRORS=`$PKG_CONFIG --print-errors "x11" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$X11_PKG_ERRORS" >&5 drawstuff="none" elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } drawstuff="none" else X11_CFLAGS=$pkg_cv_X11_CFLAGS X11_LIBS=$pkg_cv_X11_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi fi if test "x$drawstuff" = "xOSX"; then $as_echo "#define HAVE_APPLE_OPENGL_FRAMEWORK 1" >>confdefs.h GL_LIBS="-framework OpenGL -framework GLUT" elif test "x$drawstuff" != "xnone"; then have_gl_headers=yes for ac_header in GL/gl.h GL/glu.h GL/glext.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "#ifdef WIN32 #include #endif #if HAVE_GL_GL_H #include #endif #if HAVE_GL_GLU_H #include #endif " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF else have_gl_headers=no fi done have_gl=no have_glu=no TEMP_LDFLAGS="$LDFLAGS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lGL" >&5 $as_echo_n "checking for main in -lGL... " >&6; } if ${ac_cv_lib_GL_main+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lGL $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_GL_main=yes else ac_cv_lib_GL_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_GL_main" >&5 $as_echo "$ac_cv_lib_GL_main" >&6; } if test "x$ac_cv_lib_GL_main" = xyes; then : GL_LIBS="-lGL"; have_gl=yes fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lGLU" >&5 $as_echo_n "checking for main in -lGLU... " >&6; } if ${ac_cv_lib_GLU_main+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lGLU -lGL $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_GLU_main=yes else ac_cv_lib_GLU_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_GLU_main" >&5 $as_echo "$ac_cv_lib_GLU_main" >&6; } if test "x$ac_cv_lib_GLU_main" = xyes; then : GL_LIBS="-lGLU $GL_LIBS"; have_glu=yes fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lopengl32" >&5 $as_echo_n "checking for main in -lopengl32... " >&6; } if ${ac_cv_lib_opengl32_main+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lopengl32 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_opengl32_main=yes else ac_cv_lib_opengl32_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_opengl32_main" >&5 $as_echo "$ac_cv_lib_opengl32_main" >&6; } if test "x$ac_cv_lib_opengl32_main" = xyes; then : GL_LIBS="-lopengl32"; have_gl=yes fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lglu32" >&5 $as_echo_n "checking for main in -lglu32... " >&6; } if ${ac_cv_lib_glu32_main+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lglu32 -lopengl32 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_glu32_main=yes else ac_cv_lib_glu32_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_glu32_main" >&5 $as_echo "$ac_cv_lib_glu32_main" >&6; } if test "x$ac_cv_lib_glu32_main" = xyes; then : GL_LIBS="-lglu32 $GL_LIBS"; have_glu=yes fi LDFLAGS="$TEMP_LDFLAGS" if test $have_gl = no -o $have_glu = no -o $have_gl_headers = no; then drawstuff="none" fi fi if test x$drawstuff = xWin32; then WIN32_TRUE= WIN32_FALSE='#' else WIN32_TRUE='#' WIN32_FALSE= fi if test x$drawstuff = xX11; then X11_TRUE= X11_FALSE='#' else X11_TRUE='#' X11_FALSE= fi if test x$drawstuff = xOSX; then OSX_TRUE= OSX_FALSE='#' else OSX_TRUE='#' OSX_FALSE= fi if test x$drawstuff != xnone; then ENABLE_DRAWSTUFF_TRUE= ENABLE_DRAWSTUFF_FALSE='#' else ENABLE_DRAWSTUFF_TRUE='#' ENABLE_DRAWSTUFF_FALSE= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if demos should be built" >&5 $as_echo_n "checking if demos should be built... " >&6; } # Check whether --enable-demos was given. if test "${enable_demos+set}" = set; then : enableval=$enable_demos; enable_demos=$enableval else enable_demos=yes fi if test x$drawstuff = xnone -a x$enable_demos = xyes ; then enable_demos=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_demos" >&5 $as_echo "$enable_demos" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Demos will not be built because OpenGL doesn't seem to work. See \`config.log' for details." >&5 $as_echo "$as_me: WARNING: Demos will not be built because OpenGL doesn't seem to work. See \`config.log' for details." >&2;} else { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_demos" >&5 $as_echo "$enable_demos" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lstdc++" >&5 $as_echo_n "checking for main in -lstdc++... " >&6; } if ${ac_cv_lib_stdcpp_main+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lstdc++ $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_stdcpp_main=yes else ac_cv_lib_stdcpp_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_stdcpp_main" >&5 $as_echo "$ac_cv_lib_stdcpp_main" >&6; } if test "x$ac_cv_lib_stdcpp_main" = xyes; then : LIBSTDCXX="-lstdc++" else LIBSTDCXX= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lpthread" >&5 $as_echo_n "checking for main in -lpthread... " >&6; } if ${ac_cv_lib_pthread_main+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthread $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pthread_main=yes else ac_cv_lib_pthread_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_main" >&5 $as_echo "$ac_cv_lib_pthread_main" >&6; } if test "x$ac_cv_lib_pthread_main" = xyes; then : LIBS="$LIBS -lpthread" fi if test x$enable_demos = xyes; then ENABLE_DEMOS_TRUE= ENABLE_DEMOS_FALSE='#' else ENABLE_DEMOS_TRUE='#' ENABLE_DEMOS_FALSE= fi old_trimesh=no # Check whether --enable-old-trimesh was given. if test "${enable_old_trimesh+set}" = set; then : enableval=$enable_old_trimesh; old_trimesh=$enableval fi if test x$old_trimesh = xyes -a $trimesh = opcode; then $as_echo "#define dTRIMESH_OPCODE_USE_OLD_TRIMESH_TRIMESH_COLLIDER 1" >>confdefs.h else old_trimesh=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gprof" >&5 $as_echo_n "checking for gprof... " >&6; } # Check whether --enable-gprof was given. if test "${enable_gprof+set}" = set; then : enableval=$enable_gprof; gprof=$enableval else gprof=no fi if test "$gprof" != no then CFLAGS="-pg $CFLAGS" CXXFLAGS="-pg $CXXFLAGS" { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled" >&5 $as_echo "enabled" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lgmon" >&5 $as_echo_n "checking for main in -lgmon... " >&6; } if ${ac_cv_lib_gmon_main+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lgmon $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_gmon_main=yes else ac_cv_lib_gmon_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gmon_main" >&5 $as_echo "$ac_cv_lib_gmon_main" >&6; } if test "x$ac_cv_lib_gmon_main" = xyes; then : LIBS="$LIBS -lgmon" fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Checks for typedefs, structures, and compiler characteristics. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdbool.h that conforms to C99" >&5 $as_echo_n "checking for stdbool.h that conforms to C99... " >&6; } if ${ac_cv_header_stdbool_h+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #ifndef bool "error: bool is not defined" #endif #ifndef false "error: false is not defined" #endif #if false "error: false is not 0" #endif #ifndef true "error: true is not defined" #endif #if true != 1 "error: true is not 1" #endif #ifndef __bool_true_false_are_defined "error: __bool_true_false_are_defined is not defined" #endif struct s { _Bool s: 1; _Bool t; } s; char a[true == 1 ? 1 : -1]; char b[false == 0 ? 1 : -1]; char c[__bool_true_false_are_defined == 1 ? 1 : -1]; char d[(bool) 0.5 == true ? 1 : -1]; /* See body of main program for 'e'. */ char f[(_Bool) 0.0 == false ? 1 : -1]; char g[true]; char h[sizeof (_Bool)]; char i[sizeof s.t]; enum { j = false, k = true, l = false * true, m = true * 256 }; /* The following fails for HP aC++/ANSI C B3910B A.05.55 [Dec 04 2003]. */ _Bool n[m]; char o[sizeof n == m * sizeof n[0] ? 1 : -1]; char p[-1 - (_Bool) 0 < 0 && -1 - (bool) 0 < 0 ? 1 : -1]; /* Catch a bug in an HP-UX C compiler. See http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html http://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html */ _Bool q = true; _Bool *pq = &q; int main () { bool e = &s; *pq |= q; *pq |= ! q; /* Refer to every declared value, to avoid compiler optimizations. */ return (!a + !b + !c + !d + !e + !f + !g + !h + !i + !!j + !k + !!l + !m + !n + !o + !p + !q + !pq); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdbool_h=yes else ac_cv_header_stdbool_h=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdbool_h" >&5 $as_echo "$ac_cv_header_stdbool_h" >&6; } ac_fn_c_check_type "$LINENO" "_Bool" "ac_cv_type__Bool" "$ac_includes_default" if test "x$ac_cv_type__Bool" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE__BOOL 1 _ACEOF fi if test $ac_cv_header_stdbool_h = yes; then $as_echo "#define HAVE_STDBOOL_H 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 $as_echo_n "checking for inline... " >&6; } if ${ac_cv_c_inline+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __cplusplus typedef int foo_t; static $ac_kw foo_t static_foo () {return 0; } $ac_kw foo_t foo () {return 0; } #endif _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_inline=$ac_kw fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext test "$ac_cv_c_inline" != no && break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 $as_echo "$ac_cv_c_inline" >&6; } case $ac_cv_c_inline in inline | yes) ;; *) case $ac_cv_c_inline in no) ac_val=;; *) ac_val=$ac_cv_c_inline;; esac cat >>confdefs.h <<_ACEOF #ifndef __cplusplus #define inline $ac_val #endif _ACEOF ;; esac ac_fn_c_find_intX_t "$LINENO" "32" "ac_cv_c_int32_t" case $ac_cv_c_int32_t in #( no|yes) ;; #( *) cat >>confdefs.h <<_ACEOF #define int32_t $ac_cv_c_int32_t _ACEOF ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for obstacks" >&5 $as_echo_n "checking for obstacks... " >&6; } if ${ac_cv_func_obstack+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default #include "obstack.h" int main () { struct obstack mem; #define obstack_chunk_alloc malloc #define obstack_chunk_free free obstack_init (&mem); obstack_free (&mem, 0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_func_obstack=yes else ac_cv_func_obstack=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_obstack" >&5 $as_echo "$ac_cv_func_obstack" >&6; } if test $ac_cv_func_obstack = yes; then $as_echo "#define HAVE_OBSTACK 1" >>confdefs.h else case " $LIBOBJS " in *" obstack.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS obstack.$ac_objext" ;; esac fi ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" if test "x$ac_cv_type_size_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define size_t unsigned int _ACEOF fi ac_fn_c_find_uintX_t "$LINENO" "32" "ac_cv_c_uint32_t" case $ac_cv_c_uint32_t in #( no|yes) ;; #( *) $as_echo "#define _UINT32_T 1" >>confdefs.h cat >>confdefs.h <<_ACEOF #define uint32_t $ac_cv_c_uint32_t _ACEOF ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lm" >&5 $as_echo_n "checking for main in -lm... " >&6; } if ${ac_cv_lib_m_main+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lm $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_m_main=yes else ac_cv_lib_m_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_main" >&5 $as_echo "$ac_cv_lib_m_main" >&6; } if test "x$ac_cv_lib_m_main" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBM 1 _ACEOF LIBS="-lm $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lsunmath" >&5 $as_echo_n "checking for main in -lsunmath... " >&6; } if ${ac_cv_lib_sunmath_main+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsunmath $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_sunmath_main=yes else ac_cv_lib_sunmath_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sunmath_main" >&5 $as_echo "$ac_cv_lib_sunmath_main" >&6; } if test "x$ac_cv_lib_sunmath_main" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBSUNMATH 1 _ACEOF LIBS="-lsunmath $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lrt" >&5 $as_echo_n "checking for main in -lrt... " >&6; } if ${ac_cv_lib_rt_main+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lrt $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_rt_main=yes else ac_cv_lib_rt_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_main" >&5 $as_echo "$ac_cv_lib_rt_main" >&6; } if test "x$ac_cv_lib_rt_main" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBRT 1 _ACEOF LIBS="-lrt $LIBS" fi for ac_func in atan2f clock_gettime copysign copysignf cosf fabsf floor fmodf gettimeofday isnan _isnan __isnan isnanf _isnanf __isnanf memmove memset pthread_attr_setstacklazy pthread_condattr_setclock sinf snprintf sqrt sqrtf strchr strstr vsnprintf do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done # The Ultrix 4.2 mips builtin alloca declared by alloca.h only works # for constant arguments. Useless! { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working alloca.h" >&5 $as_echo_n "checking for working alloca.h... " >&6; } if ${ac_cv_working_alloca_h+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { char *p = (char *) alloca (2 * sizeof (int)); if (p) return 0; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_working_alloca_h=yes else ac_cv_working_alloca_h=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_working_alloca_h" >&5 $as_echo "$ac_cv_working_alloca_h" >&6; } if test $ac_cv_working_alloca_h = yes; then $as_echo "#define HAVE_ALLOCA_H 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for alloca" >&5 $as_echo_n "checking for alloca... " >&6; } if ${ac_cv_func_alloca_works+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __GNUC__ # define alloca __builtin_alloca #else # ifdef _MSC_VER # include # define alloca _alloca # else # ifdef HAVE_ALLOCA_H # include # else # ifdef _AIX #pragma alloca # else # ifndef alloca /* predefined by HP cc +Olibcalls */ void *alloca (size_t); # endif # endif # endif # endif #endif int main () { char *p = (char *) alloca (1); if (p) return 0; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_func_alloca_works=yes else ac_cv_func_alloca_works=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_alloca_works" >&5 $as_echo "$ac_cv_func_alloca_works" >&6; } if test $ac_cv_func_alloca_works = yes; then $as_echo "#define HAVE_ALLOCA 1" >>confdefs.h else # The SVR3 libPW and SVR4 libucb both contain incompatible functions # that cause trouble. Some versions do not even contain alloca or # contain a buggy version. If you still want to use their alloca, # use ar to extract alloca.o from them instead of compiling alloca.c. ALLOCA=\${LIBOBJDIR}alloca.$ac_objext $as_echo "#define C_ALLOCA 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether \`alloca.c' needs Cray hooks" >&5 $as_echo_n "checking whether \`alloca.c' needs Cray hooks... " >&6; } if ${ac_cv_os_cray+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if defined CRAY && ! defined CRAY2 webecray #else wenotbecray #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "webecray" >/dev/null 2>&1; then : ac_cv_os_cray=yes else ac_cv_os_cray=no fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_os_cray" >&5 $as_echo "$ac_cv_os_cray" >&6; } if test $ac_cv_os_cray = yes; then for ac_func in _getb67 GETB67 getb67; do as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define CRAY_STACKSEG_END $ac_func _ACEOF break fi done fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking stack direction for C alloca" >&5 $as_echo_n "checking stack direction for C alloca... " >&6; } if ${ac_cv_c_stack_direction+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_c_stack_direction=0 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int find_stack_direction (int *addr, int depth) { int dir, dummy = 0; if (! addr) addr = &dummy; *addr = addr < &dummy ? 1 : addr == &dummy ? 0 : -1; dir = depth ? find_stack_direction (addr, depth - 1) : 0; return dir + dummy; } int main (int argc, char **argv) { return find_stack_direction (0, argc + !argv + 20) < 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_c_stack_direction=1 else ac_cv_c_stack_direction=-1 fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_stack_direction" >&5 $as_echo "$ac_cv_c_stack_direction" >&6; } cat >>confdefs.h <<_ACEOF #define STACK_DIRECTION $ac_cv_c_stack_direction _ACEOF fi # Check whether --enable-threading-intf was given. if test "${enable_threading_intf+set}" = set; then : enableval=$enable_threading_intf; threading_intf=$enableval else threading_intf=yes fi # Check whether --enable-ou was given. if test "${enable_ou+set}" = set; then : enableval=$enable_ou; use_ou_tls=$enableval else use_ou_tls=no fi use_ou="no" if test x$use_ou_tls = xyes -o x$threading_intf = xyes then use_ou="yes" fi OU_NAMESPACE=odeou $as_echo "#define _OU_NAMESPACE odeou" >>confdefs.h $as_echo "#define dOU_ENABLED 1" >>confdefs.h if test x$use_ou_tls = xyes then OU_FEATURE_SET=_OU_FEATURE_SET_TLS $as_echo "#define _OU_FEATURE_SET _OU_FEATURE_SET_TLS" >>confdefs.h elif test x$use_ou = xyes then OU_FEATURE_SET=_OU_FEATURE_SET_ATOMICS $as_echo "#define _OU_FEATURE_SET _OU_FEATURE_SET_ATOMICS" >>confdefs.h else OU_FEATURE_SET=_OU_FEATURE_SET_BASICS $as_echo "#define _OU_FEATURE_SET _OU_FEATURE_SET_BASICS" >>confdefs.h fi if test x$use_ou = xyes then $as_echo "#define dATOMICS_ENABLED 1" >>confdefs.h if test x$use_ou_tls = xyes then $as_echo "#define dTLS_ENABLED 1" >>confdefs.h fi fi case "$host_os" in cygwin* | mingw*) targetos=_OU_TARGET_OS_WINDOWS ;; *qnx*) targetos=_OU_TARGET_OS_QNX ;; *apple* | *darwin*) targetos=_OU_TARGET_OS_MAC ;; *sunos*) targetos=_OU_TARGET_OS_SUNOS ;; *aix*) targetos=_OU_TARGET_OS_AIX ;; *) targetos=_OU_TARGET_OS_GENUNIX ;; esac if test $targetos = _OU_TARGET_OS_MAC then MAC_OS_X_VERSION=1000 ac_fn_c_check_func "$LINENO" "OSAtomicAdd32Barrier" "ac_cv_func_OSAtomicAdd32Barrier" if test "x$ac_cv_func_OSAtomicAdd32Barrier" = xyes; then : MAC_OS_X_VERSION=1040 fi ac_fn_c_check_func "$LINENO" "OSAtomicAnd32OrigBarrier" "ac_cv_func_OSAtomicAnd32OrigBarrier" if test "x$ac_cv_func_OSAtomicAnd32OrigBarrier" = xyes; then : MAC_OS_X_VERSION=1050 fi cat >>confdefs.h <<_ACEOF #define MAC_OS_X_VERSION $MAC_OS_X_VERSION _ACEOF fi if test $targetos = _OU_TARGET_OS_SUNOS then ac_fn_c_check_func "$LINENO" "atomic_inc_32_nv" "ac_cv_func_atomic_inc_32_nv" if test "x$ac_cv_func_atomic_inc_32_nv" = xyes; then : else targetos=_OU_TARGET_OS_GENUNIX fi fi cat >>confdefs.h <<_ACEOF #define _OU_TARGET_OS $targetos _ACEOF subdirs="$subdirs ou" if true; then ENABLE_OU_TRUE= ENABLE_OU_FALSE='#' else ENABLE_OU_TRUE='#' ENABLE_OU_FALSE= fi if test x$threading_intf = xyes then # Check whether --enable-builtin-threading-impl was given. if test "${enable_builtin_threading_impl+set}" = set; then : enableval=$enable_builtin_threading_impl; use_builtin_threading_impl=$enableval else use_builtin_threading_impl=yes fi if test x$use_builtin_threading_impl = xyes then $as_echo "#define dBUILTIN_THREADING_IMPL_ENABLED 1" >>confdefs.h fi else $as_echo "#define dTHREADING_INTF_DISABLED 1" >>confdefs.h use_builtin_threading_impl=no fi col_cylinder_cylinder=none col_box_cylinder=default col_capsule_cylinder=none col_convex_box=none col_convex_capsule=none col_convex_cylinder=none col_convex_sphere=default col_convex_convex=default use_libccd=no libccd_all=no # Check whether --enable-libccd was given. if test "${enable_libccd+set}" = set; then : enableval=$enable_libccd; libccd_all=$enableval fi if test x$libccd_all = xyes then col_cylinder_cylinder=libccd col_capsule_cylinder=libccd col_convex_box=libccd col_convex_capsule=libccd col_convex_cylinder=libccd col_convex_sphere=libccd col_convex_convex=libccd use_libccd=yes fi # Check whether --with-cylinder-cylinder was given. if test "${with_cylinder_cylinder+set}" = set; then : withval=$with_cylinder_cylinder; col_cylinder_cylinder=$withval fi # Check whether --with-box-cylinder was given. if test "${with_box_cylinder+set}" = set; then : withval=$with_box_cylinder; col_box_cylinder=$withval fi # Check whether --with-capsule-cylinder was given. if test "${with_capsule_cylinder+set}" = set; then : withval=$with_capsule_cylinder; col_capsule_cylinder=$withval fi # Check whether --with-convex-box was given. if test "${with_convex_box+set}" = set; then : withval=$with_convex_box; col_convex_box=$withval fi # Check whether --with-convex-capsule was given. if test "${with_convex_capsule+set}" = set; then : withval=$with_convex_capsule; col_convex_capsule=$withval fi # Check whether --with-convex-cylinder was given. if test "${with_convex_cylinder+set}" = set; then : withval=$with_convex_cylinder; col_convex_cylinder=$withval fi # Check whether --with-convex-sphere was given. if test "${with_convex_sphere+set}" = set; then : withval=$with_convex_sphere; col_convex_sphere=$withval fi # Check whether --with-convex-convex was given. if test "${with_convex_convex+set}" = set; then : withval=$with_convex_convex; col_convex_convex=$withval fi if test x$col_cylinder_cylinder = xlibccd -o \ x$col_box_cylinder = xlibccd -o \ x$col_capsule_cylinder = xlibccd -o \ x$col_convex_box = xlibccd -o \ x$col_convex_capsule = libccd -o \ x$col_convex_cylinder = xlibccd -o \ x$col_convex_sphere = libccd -o \ x$col_convex_convex = libccd then use_libccd=yes fi libccd_source=internal # Check whether --with-libccd was given. if test "${with_libccd+set}" = set; then : withval=$with_libccd; libccd_source=$withval else libccd_source=system fi if test x$use_libccd = xyes then if test x$libccd_source = xsystem then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CCD" >&5 $as_echo_n "checking for CCD... " >&6; } if test -n "$CCD_CFLAGS"; then pkg_cv_CCD_CFLAGS="$CCD_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"ccd\""; } >&5 ($PKG_CONFIG --exists --print-errors "ccd") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_CCD_CFLAGS=`$PKG_CONFIG --cflags "ccd" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$CCD_LIBS"; then pkg_cv_CCD_LIBS="$CCD_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"ccd\""; } >&5 ($PKG_CONFIG --exists --print-errors "ccd") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_CCD_LIBS=`$PKG_CONFIG --libs "ccd" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then CCD_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "ccd" 2>&1` else CCD_PKG_ERRORS=`$PKG_CONFIG --print-errors "ccd" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$CCD_PKG_ERRORS" >&5 libccd_source=internal elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } libccd_source=internal else CCD_CFLAGS=$pkg_cv_CCD_CFLAGS CCD_LIBS=$pkg_cv_CCD_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi fi fi # Configure libccd unconditionally as that may be needed for special make targets subdirs="$subdirs libccd" if test x$use_libccd != xno; then LIBCCD_TRUE= LIBCCD_FALSE='#' else LIBCCD_TRUE='#' LIBCCD_FALSE= fi if test x$libccd_source = xinternal; then LIBCCD_INTERNAL_TRUE= LIBCCD_INTERNAL_FALSE='#' else LIBCCD_INTERNAL_TRUE='#' LIBCCD_INTERNAL_FALSE= fi if test x$col_box_cylinder = xlibccd; then LIBCCD_BOX_CYL_TRUE= LIBCCD_BOX_CYL_FALSE='#' else LIBCCD_BOX_CYL_TRUE='#' LIBCCD_BOX_CYL_FALSE= fi if test x$col_cylinder_cylinder = xlibccd; then LIBCCD_CYL_CYL_TRUE= LIBCCD_CYL_CYL_FALSE='#' else LIBCCD_CYL_CYL_TRUE='#' LIBCCD_CYL_CYL_FALSE= fi if test x$col_capsule_cylinder = xlibccd; then LIBCCD_CAP_CYL_TRUE= LIBCCD_CAP_CYL_FALSE='#' else LIBCCD_CAP_CYL_TRUE='#' LIBCCD_CAP_CYL_FALSE= fi if test x$col_convex_box = xlibccd; then LIBCCD_CONVEX_BOX_TRUE= LIBCCD_CONVEX_BOX_FALSE='#' else LIBCCD_CONVEX_BOX_TRUE='#' LIBCCD_CONVEX_BOX_FALSE= fi if test x$col_convex_capsule = xlibccd; then LIBCCD_CONVEX_CAP_TRUE= LIBCCD_CONVEX_CAP_FALSE='#' else LIBCCD_CONVEX_CAP_TRUE='#' LIBCCD_CONVEX_CAP_FALSE= fi if test x$col_convex_cylinder = xlibccd; then LIBCCD_CONVEX_CYL_TRUE= LIBCCD_CONVEX_CYL_FALSE='#' else LIBCCD_CONVEX_CYL_TRUE='#' LIBCCD_CONVEX_CYL_FALSE= fi if test x$col_convex_sphere = xlibccd; then LIBCCD_CONVEX_SPHERE_TRUE= LIBCCD_CONVEX_SPHERE_FALSE='#' else LIBCCD_CONVEX_SPHERE_TRUE='#' LIBCCD_CONVEX_SPHERE_FALSE= fi if test x$col_convex_convex = xlibccd; then LIBCCD_CONVEX_CONVEX_TRUE= LIBCCD_CONVEX_CONVEX_FALSE='#' else LIBCCD_CONVEX_CONVEX_TRUE='#' LIBCCD_CONVEX_CONVEX_FALSE= fi # Check whether --enable-asserts was given. if test "${enable_asserts+set}" = set; then : enableval=$enable_asserts; asserts=$enableval else asserts=yes fi if test x$asserts = xno then CPPFLAGS="$CPPFLAGS -DdNODEBUG -DNDEBUG" fi ac_config_files="$ac_config_files Makefile drawstuff/Makefile drawstuff/src/Makefile drawstuff/dstest/Makefile include/Makefile include/drawstuff/Makefile include/ode/Makefile include/ode/version.h include/ode/precision.h ode/Makefile ode/doc/Doxyfile ode/doc/Makefile ode/src/Makefile ode/src/joints/Makefile ode/demo/Makefile OPCODE/Makefile OPCODE/Ice/Makefile GIMPACT/Makefile GIMPACT/include/Makefile GIMPACT/include/GIMPACT/Makefile GIMPACT/src/Makefile tests/Makefile tests/joints/Makefile tests/UnitTest++/Makefile tests/UnitTest++/src/Makefile tests/UnitTest++/src/Posix/Makefile tests/UnitTest++/src/Win32/Makefile ode-config ode.pc" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs { $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 $as_echo_n "checking that generated files are newer than configure... " >&6; } if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 $as_echo "done" >&6; } if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' else am__EXEEXT_TRUE='#' am__EXEEXT_FALSE= fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then as_fn_error $? "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCXX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_DOXYGEN_TRUE}" && test -z "${HAVE_DOXYGEN_FALSE}"; then as_fn_error $? "conditional \"HAVE_DOXYGEN\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${X86_64_SYSTEM_TRUE}" && test -z "${X86_64_SYSTEM_FALSE}"; then as_fn_error $? "conditional \"X86_64_SYSTEM\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${OPCODE_TRUE}" && test -z "${OPCODE_FALSE}"; then as_fn_error $? "conditional \"OPCODE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${GIMPACT_TRUE}" && test -z "${GIMPACT_FALSE}"; then as_fn_error $? "conditional \"GIMPACT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${TRIMESH_TRUE}" && test -z "${TRIMESH_FALSE}"; then as_fn_error $? "conditional \"TRIMESH\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WIN32_TRUE}" && test -z "${WIN32_FALSE}"; then as_fn_error $? "conditional \"WIN32\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${X11_TRUE}" && test -z "${X11_FALSE}"; then as_fn_error $? "conditional \"X11\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${OSX_TRUE}" && test -z "${OSX_FALSE}"; then as_fn_error $? "conditional \"OSX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_DRAWSTUFF_TRUE}" && test -z "${ENABLE_DRAWSTUFF_FALSE}"; then as_fn_error $? "conditional \"ENABLE_DRAWSTUFF\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_DEMOS_TRUE}" && test -z "${ENABLE_DEMOS_FALSE}"; then as_fn_error $? "conditional \"ENABLE_DEMOS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_OU_TRUE}" && test -z "${ENABLE_OU_FALSE}"; then as_fn_error $? "conditional \"ENABLE_OU\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${LIBCCD_TRUE}" && test -z "${LIBCCD_FALSE}"; then as_fn_error $? "conditional \"LIBCCD\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${LIBCCD_INTERNAL_TRUE}" && test -z "${LIBCCD_INTERNAL_FALSE}"; then as_fn_error $? "conditional \"LIBCCD_INTERNAL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${LIBCCD_BOX_CYL_TRUE}" && test -z "${LIBCCD_BOX_CYL_FALSE}"; then as_fn_error $? "conditional \"LIBCCD_BOX_CYL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${LIBCCD_CYL_CYL_TRUE}" && test -z "${LIBCCD_CYL_CYL_FALSE}"; then as_fn_error $? "conditional \"LIBCCD_CYL_CYL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${LIBCCD_CAP_CYL_TRUE}" && test -z "${LIBCCD_CAP_CYL_FALSE}"; then as_fn_error $? "conditional \"LIBCCD_CAP_CYL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${LIBCCD_CONVEX_BOX_TRUE}" && test -z "${LIBCCD_CONVEX_BOX_FALSE}"; then as_fn_error $? "conditional \"LIBCCD_CONVEX_BOX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${LIBCCD_CONVEX_CAP_TRUE}" && test -z "${LIBCCD_CONVEX_CAP_FALSE}"; then as_fn_error $? "conditional \"LIBCCD_CONVEX_CAP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${LIBCCD_CONVEX_CYL_TRUE}" && test -z "${LIBCCD_CONVEX_CYL_FALSE}"; then as_fn_error $? "conditional \"LIBCCD_CONVEX_CYL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${LIBCCD_CONVEX_SPHERE_TRUE}" && test -z "${LIBCCD_CONVEX_SPHERE_FALSE}"; then as_fn_error $? "conditional \"LIBCCD_CONVEX_SPHERE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${LIBCCD_CONVEX_CONVEX_TRUE}" && test -z "${LIBCCD_CONVEX_CONVEX_FALSE}"; then as_fn_error $? "conditional \"LIBCCD_CONVEX_CONVEX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by ODE $as_me 0.16, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ ODE config.status 0.16 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' MKDIR_P='$MKDIR_P' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' AS='`$ECHO "$AS" | $SED "$delay_single_quote_subst"`' DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`' SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`' nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`' objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`' configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`' hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' compiler_lib_search_dirs='`$ECHO "$compiler_lib_search_dirs" | $SED "$delay_single_quote_subst"`' predep_objects='`$ECHO "$predep_objects" | $SED "$delay_single_quote_subst"`' postdep_objects='`$ECHO "$postdep_objects" | $SED "$delay_single_quote_subst"`' predeps='`$ECHO "$predeps" | $SED "$delay_single_quote_subst"`' postdeps='`$ECHO "$postdeps" | $SED "$delay_single_quote_subst"`' compiler_lib_search_path='`$ECHO "$compiler_lib_search_path" | $SED "$delay_single_quote_subst"`' LD_CXX='`$ECHO "$LD_CXX" | $SED "$delay_single_quote_subst"`' reload_flag_CXX='`$ECHO "$reload_flag_CXX" | $SED "$delay_single_quote_subst"`' reload_cmds_CXX='`$ECHO "$reload_cmds_CXX" | $SED "$delay_single_quote_subst"`' old_archive_cmds_CXX='`$ECHO "$old_archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' compiler_CXX='`$ECHO "$compiler_CXX" | $SED "$delay_single_quote_subst"`' GCC_CXX='`$ECHO "$GCC_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag_CXX='`$ECHO "$lt_prog_compiler_no_builtin_flag_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_pic_CXX='`$ECHO "$lt_prog_compiler_pic_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_wl_CXX='`$ECHO "$lt_prog_compiler_wl_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_static_CXX='`$ECHO "$lt_prog_compiler_static_CXX" | $SED "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o_CXX='`$ECHO "$lt_cv_prog_compiler_c_o_CXX" | $SED "$delay_single_quote_subst"`' archive_cmds_need_lc_CXX='`$ECHO "$archive_cmds_need_lc_CXX" | $SED "$delay_single_quote_subst"`' enable_shared_with_static_runtimes_CXX='`$ECHO "$enable_shared_with_static_runtimes_CXX" | $SED "$delay_single_quote_subst"`' export_dynamic_flag_spec_CXX='`$ECHO "$export_dynamic_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' whole_archive_flag_spec_CXX='`$ECHO "$whole_archive_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' compiler_needs_object_CXX='`$ECHO "$compiler_needs_object_CXX" | $SED "$delay_single_quote_subst"`' old_archive_from_new_cmds_CXX='`$ECHO "$old_archive_from_new_cmds_CXX" | $SED "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds_CXX='`$ECHO "$old_archive_from_expsyms_cmds_CXX" | $SED "$delay_single_quote_subst"`' archive_cmds_CXX='`$ECHO "$archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' archive_expsym_cmds_CXX='`$ECHO "$archive_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' module_cmds_CXX='`$ECHO "$module_cmds_CXX" | $SED "$delay_single_quote_subst"`' module_expsym_cmds_CXX='`$ECHO "$module_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' with_gnu_ld_CXX='`$ECHO "$with_gnu_ld_CXX" | $SED "$delay_single_quote_subst"`' allow_undefined_flag_CXX='`$ECHO "$allow_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' no_undefined_flag_CXX='`$ECHO "$no_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec_CXX='`$ECHO "$hardcode_libdir_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' hardcode_libdir_separator_CXX='`$ECHO "$hardcode_libdir_separator_CXX" | $SED "$delay_single_quote_subst"`' hardcode_direct_CXX='`$ECHO "$hardcode_direct_CXX" | $SED "$delay_single_quote_subst"`' hardcode_direct_absolute_CXX='`$ECHO "$hardcode_direct_absolute_CXX" | $SED "$delay_single_quote_subst"`' hardcode_minus_L_CXX='`$ECHO "$hardcode_minus_L_CXX" | $SED "$delay_single_quote_subst"`' hardcode_shlibpath_var_CXX='`$ECHO "$hardcode_shlibpath_var_CXX" | $SED "$delay_single_quote_subst"`' hardcode_automatic_CXX='`$ECHO "$hardcode_automatic_CXX" | $SED "$delay_single_quote_subst"`' inherit_rpath_CXX='`$ECHO "$inherit_rpath_CXX" | $SED "$delay_single_quote_subst"`' link_all_deplibs_CXX='`$ECHO "$link_all_deplibs_CXX" | $SED "$delay_single_quote_subst"`' always_export_symbols_CXX='`$ECHO "$always_export_symbols_CXX" | $SED "$delay_single_quote_subst"`' export_symbols_cmds_CXX='`$ECHO "$export_symbols_cmds_CXX" | $SED "$delay_single_quote_subst"`' exclude_expsyms_CXX='`$ECHO "$exclude_expsyms_CXX" | $SED "$delay_single_quote_subst"`' include_expsyms_CXX='`$ECHO "$include_expsyms_CXX" | $SED "$delay_single_quote_subst"`' prelink_cmds_CXX='`$ECHO "$prelink_cmds_CXX" | $SED "$delay_single_quote_subst"`' postlink_cmds_CXX='`$ECHO "$postlink_cmds_CXX" | $SED "$delay_single_quote_subst"`' file_list_spec_CXX='`$ECHO "$file_list_spec_CXX" | $SED "$delay_single_quote_subst"`' hardcode_action_CXX='`$ECHO "$hardcode_action_CXX" | $SED "$delay_single_quote_subst"`' compiler_lib_search_dirs_CXX='`$ECHO "$compiler_lib_search_dirs_CXX" | $SED "$delay_single_quote_subst"`' predep_objects_CXX='`$ECHO "$predep_objects_CXX" | $SED "$delay_single_quote_subst"`' postdep_objects_CXX='`$ECHO "$postdep_objects_CXX" | $SED "$delay_single_quote_subst"`' predeps_CXX='`$ECHO "$predeps_CXX" | $SED "$delay_single_quote_subst"`' postdeps_CXX='`$ECHO "$postdeps_CXX" | $SED "$delay_single_quote_subst"`' compiler_lib_search_path_CXX='`$ECHO "$compiler_lib_search_path_CXX" | $SED "$delay_single_quote_subst"`' LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } # Quote evaled strings. for var in AS \ DLLTOOL \ OBJDUMP \ SHELL \ ECHO \ PATH_SEPARATOR \ SED \ GREP \ EGREP \ FGREP \ LD \ NM \ LN_S \ lt_SP2NL \ lt_NL2SP \ reload_flag \ deplibs_check_method \ file_magic_cmd \ file_magic_glob \ want_nocaseglob \ sharedlib_from_linklib_cmd \ AR \ AR_FLAGS \ archiver_list_spec \ STRIP \ RANLIB \ CC \ CFLAGS \ compiler \ lt_cv_sys_global_symbol_pipe \ lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_import \ lt_cv_sys_global_symbol_to_c_name_address \ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ lt_cv_nm_interface \ nm_file_list_spec \ lt_cv_truncate_bin \ lt_prog_compiler_no_builtin_flag \ lt_prog_compiler_pic \ lt_prog_compiler_wl \ lt_prog_compiler_static \ lt_cv_prog_compiler_c_o \ need_locks \ MANIFEST_TOOL \ DSYMUTIL \ NMEDIT \ LIPO \ OTOOL \ OTOOL64 \ shrext_cmds \ export_dynamic_flag_spec \ whole_archive_flag_spec \ compiler_needs_object \ with_gnu_ld \ allow_undefined_flag \ no_undefined_flag \ hardcode_libdir_flag_spec \ hardcode_libdir_separator \ exclude_expsyms \ include_expsyms \ file_list_spec \ variables_saved_for_relink \ libname_spec \ library_names_spec \ soname_spec \ install_override_mode \ finish_eval \ old_striplib \ striplib \ compiler_lib_search_dirs \ predep_objects \ postdep_objects \ predeps \ postdeps \ compiler_lib_search_path \ LD_CXX \ reload_flag_CXX \ compiler_CXX \ lt_prog_compiler_no_builtin_flag_CXX \ lt_prog_compiler_pic_CXX \ lt_prog_compiler_wl_CXX \ lt_prog_compiler_static_CXX \ lt_cv_prog_compiler_c_o_CXX \ export_dynamic_flag_spec_CXX \ whole_archive_flag_spec_CXX \ compiler_needs_object_CXX \ with_gnu_ld_CXX \ allow_undefined_flag_CXX \ no_undefined_flag_CXX \ hardcode_libdir_flag_spec_CXX \ hardcode_libdir_separator_CXX \ exclude_expsyms_CXX \ include_expsyms_CXX \ file_list_spec_CXX \ compiler_lib_search_dirs_CXX \ predep_objects_CXX \ postdep_objects_CXX \ predeps_CXX \ postdeps_CXX \ compiler_lib_search_path_CXX; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in reload_cmds \ old_postinstall_cmds \ old_postuninstall_cmds \ old_archive_cmds \ extract_expsyms_cmds \ old_archive_from_new_cmds \ old_archive_from_expsyms_cmds \ archive_cmds \ archive_expsym_cmds \ module_cmds \ module_expsym_cmds \ export_symbols_cmds \ prelink_cmds \ postlink_cmds \ postinstall_cmds \ postuninstall_cmds \ finish_cmds \ sys_lib_search_path_spec \ configure_time_dlsearch_path \ configure_time_lt_sys_library_path \ reload_cmds_CXX \ old_archive_cmds_CXX \ old_archive_from_new_cmds_CXX \ old_archive_from_expsyms_cmds_CXX \ archive_cmds_CXX \ archive_expsym_cmds_CXX \ module_cmds_CXX \ module_expsym_cmds_CXX \ export_symbols_cmds_CXX \ prelink_cmds_CXX \ postlink_cmds_CXX; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done ac_aux_dir='$ac_aux_dir' # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi PACKAGE='$PACKAGE' VERSION='$VERSION' RM='$RM' ofile='$ofile' _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "ode/src/config.h") CONFIG_HEADERS="$CONFIG_HEADERS ode/src/config.h" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "drawstuff/Makefile") CONFIG_FILES="$CONFIG_FILES drawstuff/Makefile" ;; "drawstuff/src/Makefile") CONFIG_FILES="$CONFIG_FILES drawstuff/src/Makefile" ;; "drawstuff/dstest/Makefile") CONFIG_FILES="$CONFIG_FILES drawstuff/dstest/Makefile" ;; "include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile" ;; "include/drawstuff/Makefile") CONFIG_FILES="$CONFIG_FILES include/drawstuff/Makefile" ;; "include/ode/Makefile") CONFIG_FILES="$CONFIG_FILES include/ode/Makefile" ;; "include/ode/version.h") CONFIG_FILES="$CONFIG_FILES include/ode/version.h" ;; "include/ode/precision.h") CONFIG_FILES="$CONFIG_FILES include/ode/precision.h" ;; "ode/Makefile") CONFIG_FILES="$CONFIG_FILES ode/Makefile" ;; "ode/doc/Doxyfile") CONFIG_FILES="$CONFIG_FILES ode/doc/Doxyfile" ;; "ode/doc/Makefile") CONFIG_FILES="$CONFIG_FILES ode/doc/Makefile" ;; "ode/src/Makefile") CONFIG_FILES="$CONFIG_FILES ode/src/Makefile" ;; "ode/src/joints/Makefile") CONFIG_FILES="$CONFIG_FILES ode/src/joints/Makefile" ;; "ode/demo/Makefile") CONFIG_FILES="$CONFIG_FILES ode/demo/Makefile" ;; "OPCODE/Makefile") CONFIG_FILES="$CONFIG_FILES OPCODE/Makefile" ;; "OPCODE/Ice/Makefile") CONFIG_FILES="$CONFIG_FILES OPCODE/Ice/Makefile" ;; "GIMPACT/Makefile") CONFIG_FILES="$CONFIG_FILES GIMPACT/Makefile" ;; "GIMPACT/include/Makefile") CONFIG_FILES="$CONFIG_FILES GIMPACT/include/Makefile" ;; "GIMPACT/include/GIMPACT/Makefile") CONFIG_FILES="$CONFIG_FILES GIMPACT/include/GIMPACT/Makefile" ;; "GIMPACT/src/Makefile") CONFIG_FILES="$CONFIG_FILES GIMPACT/src/Makefile" ;; "tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;; "tests/joints/Makefile") CONFIG_FILES="$CONFIG_FILES tests/joints/Makefile" ;; "tests/UnitTest++/Makefile") CONFIG_FILES="$CONFIG_FILES tests/UnitTest++/Makefile" ;; "tests/UnitTest++/src/Makefile") CONFIG_FILES="$CONFIG_FILES tests/UnitTest++/src/Makefile" ;; "tests/UnitTest++/src/Posix/Makefile") CONFIG_FILES="$CONFIG_FILES tests/UnitTest++/src/Posix/Makefile" ;; "tests/UnitTest++/src/Win32/Makefile") CONFIG_FILES="$CONFIG_FILES tests/UnitTest++/src/Win32/Makefile" ;; "ode-config") CONFIG_FILES="$CONFIG_FILES ode-config" ;; "ode.pc") CONFIG_FILES="$CONFIG_FILES ode.pc" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi # Compute "$ac_file"'s index in $config_headers. _am_arg="$ac_file" _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || $as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$_am_arg" : 'X\(//\)[^/]' \| \ X"$_am_arg" : 'X\(//\)$' \| \ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$_am_arg" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'`/stamp-h$_am_stamp_count ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || { # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`$as_dirname -- "$mf" || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "$am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`$as_dirname -- "$file" || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir=$dirpart/$fdir; as_fn_mkdir_p # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ;; "libtool":C) # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi cfgfile=${ofile}T trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # Generated automatically by $as_me ($PACKAGE) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # Provide generalized library-building support services. # Written by Gordon Matzigkeit, 1996 # Copyright (C) 2014 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program or library that is built # using GNU Libtool, you may include this file under the same # distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # The names of the tagged configurations supported by this script. available_tags='CXX ' # Configured defaults for sys_lib_dlsearch_path munging. : \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} # ### BEGIN LIBTOOL CONFIG # Which release of libtool.m4 was used? macro_version=$macro_version macro_revision=$macro_revision # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Assembler program. AS=$lt_AS # DLL creation program. DLLTOOL=$lt_DLLTOOL # Object dumper program. OBJDUMP=$lt_OBJDUMP # Whether or not to build static libraries. build_old_libs=$enable_static # What type of objects to build. pic_mode=$pic_mode # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # Shared archive member basename,for filename based shared library versioning on AIX. shared_archive_member_spec=$shared_archive_member_spec # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # An echo program that protects backslashes. ECHO=$lt_ECHO # The PATH separator for the build system. PATH_SEPARATOR=$lt_PATH_SEPARATOR # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # A sed program that does not truncate output. SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="\$SED -e 1s/^X//" # A grep program that handles long lines. GREP=$lt_GREP # An ERE matcher. EGREP=$lt_EGREP # A literal string matcher. FGREP=$lt_FGREP # A BSD- or MS-compatible name lister. NM=$lt_NM # Whether we need soft or hard links. LN_S=$lt_LN_S # What is the maximum length of a command? max_cmd_len=$max_cmd_len # Object file suffix (normally "o"). objext=$ac_objext # Executable file suffix (normally ""). exeext=$exeext # whether the shell understands "unset". lt_unset=$lt_unset # turn spaces into newlines. SP2NL=$lt_lt_SP2NL # turn newlines into spaces. NL2SP=$lt_lt_NL2SP # convert \$build file names to \$host format. to_host_file_cmd=$lt_cv_to_host_file_cmd # convert \$build files to toolchain format. to_tool_file_cmd=$lt_cv_to_tool_file_cmd # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method = "file_magic". file_magic_cmd=$lt_file_magic_cmd # How to find potential files when deplibs_check_method = "file_magic". file_magic_glob=$lt_file_magic_glob # Find potential files using nocaseglob when deplibs_check_method = "file_magic". want_nocaseglob=$lt_want_nocaseglob # Command to associate shared and link libraries. sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd # The archiver. AR=$lt_AR # Flags to create an archive. AR_FLAGS=$lt_AR_FLAGS # How to feed a file listing to the archiver. archiver_list_spec=$lt_archiver_list_spec # A symbol stripping program. STRIP=$lt_STRIP # Commands used to install an old-style archive. RANLIB=$lt_RANLIB old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Whether to use a lock for old archive extraction. lock_old_archive_extraction=$lock_old_archive_extraction # A C compiler. LTCC=$lt_CC # LTCC compiler flags. LTCFLAGS=$lt_CFLAGS # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration. global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm into a list of symbols to manually relocate. global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import # Transform the output of nm in a C name address pair. global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # Transform the output of nm in a C name address pair when lib prefix is needed. global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix # The name lister interface. nm_interface=$lt_lt_cv_nm_interface # Specify filename containing input files for \$NM. nm_file_list_spec=$lt_nm_file_list_spec # The root where to search for dependent libraries,and where our libraries should be installed. lt_sysroot=$lt_sysroot # Command to truncate a binary pipe. lt_truncate_bin=$lt_lt_cv_truncate_bin # The name of the directory that contains temporary libtool files. objdir=$objdir # Used to examine libraries when file_magic_cmd begins with "file". MAGIC_CMD=$MAGIC_CMD # Must we lock files when doing compilation? need_locks=$lt_need_locks # Manifest tool. MANIFEST_TOOL=$lt_MANIFEST_TOOL # Tool to manipulate archived DWARF debug symbol files on Mac OS X. DSYMUTIL=$lt_DSYMUTIL # Tool to change global to local symbols on Mac OS X. NMEDIT=$lt_NMEDIT # Tool to manipulate fat objects and archives on Mac OS X. LIPO=$lt_LIPO # ldd/readelf like tool for Mach-O binaries on Mac OS X. OTOOL=$lt_OTOOL # ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. OTOOL64=$lt_OTOOL64 # Old archive suffix (normally "a"). libext=$libext # Shared library suffix (normally ".so"). shrext_cmds=$lt_shrext_cmds # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Variables whose values should be saved in libtool wrapper scripts and # restored at link time. variables_saved_for_relink=$lt_variables_saved_for_relink # Do we need the "lib" prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Library versioning type. version_type=$version_type # Shared library runtime path variable. runpath_var=$runpath_var # Shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Permission mode override for installation of shared libraries. install_override_mode=$lt_install_override_mode # Command to use after installation of a shared archive. postinstall_cmds=$lt_postinstall_cmds # Command to use after uninstallation of a shared archive. postuninstall_cmds=$lt_postuninstall_cmds # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # As "finish_cmds", except a single script fragment to be evaled but # not shown. finish_eval=$lt_finish_eval # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Compile-time system search path for libraries. sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Detected run-time system search path for libraries. sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path # Explicit LT_SYS_LIBRARY_PATH set during ./configure time. configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # The linker used to build libraries. LD=$lt_LD # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds # A language specific compiler. CC=$lt_compiler # Is the compiler the GNU compiler? with_gcc=$GCC # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds archive_expsym_cmds=$lt_archive_expsym_cmds # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds module_expsym_cmds=$lt_module_expsym_cmds # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \$shlibpath_var if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms # Symbols that must always be exported. include_expsyms=$lt_include_expsyms # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds # Commands necessary for finishing linking programs. postlink_cmds=$lt_postlink_cmds # Specify filename containing input files. file_list_spec=$lt_file_list_spec # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action # The directories searched by this compiler when creating a shared library. compiler_lib_search_dirs=$lt_compiler_lib_search_dirs # Dependencies to place before and after the objects being linked to # create a shared library. predep_objects=$lt_predep_objects postdep_objects=$lt_postdep_objects predeps=$lt_predeps postdeps=$lt_postdeps # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path # ### END LIBTOOL CONFIG _LT_EOF cat <<'_LT_EOF' >> "$cfgfile" # ### BEGIN FUNCTIONS SHARED WITH CONFIGURE # func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x$2 in x) ;; *:) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" ;; x:*) eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" ;; *::*) eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" ;; *) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" ;; esac } # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in $*""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } # ### END FUNCTIONS SHARED WITH CONFIGURE _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac ltmain=$ac_aux_dir/ltmain.sh # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" cat <<_LT_EOF >> "$ofile" # ### BEGIN LIBTOOL TAG CONFIG: CXX # The linker used to build libraries. LD=$lt_LD_CXX # How to create reloadable object files. reload_flag=$lt_reload_flag_CXX reload_cmds=$lt_reload_cmds_CXX # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds_CXX # A language specific compiler. CC=$lt_compiler_CXX # Is the compiler the GNU compiler? with_gcc=$GCC_CXX # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic_CXX # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl_CXX # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static_CXX # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc_CXX # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object_CXX # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds_CXX archive_expsym_cmds=$lt_archive_expsym_cmds_CXX # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds_CXX module_expsym_cmds=$lt_module_expsym_cmds_CXX # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld_CXX # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag_CXX # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag_CXX # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct_CXX # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \$shlibpath_var if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute_CXX # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L_CXX # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic_CXX # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath_CXX # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs_CXX # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols_CXX # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds_CXX # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms_CXX # Symbols that must always be exported. include_expsyms=$lt_include_expsyms_CXX # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds_CXX # Commands necessary for finishing linking programs. postlink_cmds=$lt_postlink_cmds_CXX # Specify filename containing input files. file_list_spec=$lt_file_list_spec_CXX # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action_CXX # The directories searched by this compiler when creating a shared library. compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_CXX # Dependencies to place before and after the objects being linked to # create a shared library. predep_objects=$lt_predep_objects_CXX postdep_objects=$lt_postdep_objects_CXX predeps=$lt_predeps_CXX postdeps=$lt_postdeps_CXX # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path_CXX # ### END LIBTOOL TAG CONFIG: CXX _LT_EOF ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 export OU_NAMESPACE=$OU_NAMESPACE export OU_FEATURE_SET=$OU_FEATURE_SET # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi # # CONFIG_SUBDIRS section. # if test "$no_recursion" != yes; then # Remove --cache-file, --srcdir, and --disable-option-checking arguments # so they do not pile up. ac_sub_configure_args= ac_prev= eval "set x $ac_configure_args" shift for ac_arg do if test -n "$ac_prev"; then ac_prev= continue fi case $ac_arg in -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* \ | --c=*) ;; --config-cache | -C) ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) ;; --disable-option-checking) ;; *) case $ac_arg in *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append ac_sub_configure_args " '$ac_arg'" ;; esac done # Always prepend --prefix to ensure using the same prefix # in subdir configurations. ac_arg="--prefix=$prefix" case $ac_arg in *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac ac_sub_configure_args="'$ac_arg' $ac_sub_configure_args" # Pass --silent if test "$silent" = yes; then ac_sub_configure_args="--silent $ac_sub_configure_args" fi # Always prepend --disable-option-checking to silence warnings, since # different subdirs can have different --enable and --with options. ac_sub_configure_args="--disable-option-checking $ac_sub_configure_args" ac_popdir=`pwd` for ac_dir in : $subdirs; do test "x$ac_dir" = x: && continue # Do not complain, so a configure script can configure whichever # parts of a large source tree are present. test -d "$srcdir/$ac_dir" || continue ac_msg="=== configuring in $ac_dir (`pwd`/$ac_dir)" $as_echo "$as_me:${as_lineno-$LINENO}: $ac_msg" >&5 $as_echo "$ac_msg" >&6 as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" # Check for guested configure; otherwise get Cygnus style configure. if test -f "$ac_srcdir/configure.gnu"; then ac_sub_configure=$ac_srcdir/configure.gnu elif test -f "$ac_srcdir/configure"; then ac_sub_configure=$ac_srcdir/configure elif test -f "$ac_srcdir/configure.in"; then # This should be Cygnus configure. ac_sub_configure=$ac_aux_dir/configure else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: no configuration information is in $ac_dir" >&5 $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2;} ac_sub_configure= fi # The recursion is here. if test -n "$ac_sub_configure"; then # Make the cache file name correct relative to the subdirectory. case $cache_file in [\\/]* | ?:[\\/]* ) ac_sub_cache_file=$cache_file ;; *) # Relative name. ac_sub_cache_file=$ac_top_build_prefix$cache_file ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&5 $as_echo "$as_me: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&6;} # The eval makes quoting arguments work. eval "\$SHELL \"\$ac_sub_configure\" $ac_sub_configure_args \ --cache-file=\"\$ac_sub_cache_file\" --srcdir=\"\$ac_srcdir\"" || as_fn_error $? "$ac_sub_configure failed for $ac_dir" "$LINENO" 5 fi cd "$ac_popdir" done fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi chmod +x ode-config BUILDDIR=`pwd` echo "Configuration:" echo " Build system type: $build" echo " Host system type: $host" echo " Use double precision: $usedouble" echo " Use drawstuff: $drawstuff" echo " Demos enabled: $enable_demos" echo " Use OPCODE: $opcode" echo " Use GIMPACT: $gimpact" echo " Use libccd: $use_libccd" if test x$use_libccd = xyes then echo " libccd source: $libccd_source" fi echo " Custom colliders:" echo " cylinder-cylinder: $col_cylinder_cylinder" echo " box-cylinder: $col_box_cylinder" echo " capsule-cylinder: $col_capsule_cylinder" echo " convex-box: $col_convex_box" echo " convex-capsule: $col_convex_capsule" echo " convex-cylinder: $col_convex_cylinder" echo " convex-sphere: $col_convex_sphere" echo " convex-convex: $col_convex_convex" echo " Is target a Pentium: $pentium" echo " Is target x86-64: $cpu64" echo " Use old opcode trimesh collider: $old_trimesh" echo " TLS for global caches: $use_ou_tls" echo " Threading intf enabled: $threading_intf" echo " Built-in threading included: $use_builtin_threading_impl" echo " Enable debug error check: $asserts" echo " Headers will be installed in $includedir/ode" echo " Libraries will be installed in $libdir" echo " Building in directory $BUILDDIR" ode-0.16/tools/0000775000175200017520000000000013403272463010362 500000000000000ode-0.16/tools/msw-release.bat0000664000175200017520000000672013403272463013223 00000000000000@echo off rem *********************************************************** rem * ODE Windows Binary Release Script rem * Originally written by Jason Perkins (starkos@gmail.com) rem * rem * See README.txt in this directory for complete release rem * instructions before running this script. rem * rem * Prerequisites: rem * Command-line svn installed on path rem * Command-line 7z (7zip) installed on path rem * Command-line doxygen installed on path rem * Run from Visual Studio 2003 command prompt rem *********************************************************** rem * Check arguments if "%1"=="" goto show_usage rem *********************************************************** rem * Pre-build checklist rem *********************************************************** echo. echo STARTING PREBUILD CHECKLIST, PRESS ^^C TO ABORT. echo. echo Are you running at the VS2003 command prompt? pause echo. echo Is the version number "%1" correct? pause echo. echo Does the release branch "%1" exist in SVN? pause echo. echo Are 'svn', '7z', and 'doxygen' on the path? pause echo. echo Okay, ready to build the Windows binary packages for version %1! pause rem *********************************************************** rem * Retrieve source code rem *********************************************************** echo. echo RETRIEVING SOURCE CODE FROM REPOSITORY... echo. svn export https://opende.svn.sourceforge.net/svnroot/opende/branches/%1 ode-%1 rem *********************************************************** rem * Prepare source code rem *********************************************************** echo. echo PREPARING SOURCE TREE... echo. cd ode-%1 copy build\config-default.h include\ode\config.h cd ode\doc doxygen cd ..\..\.. rem *********************************************************** rem * Build the binaries rem *********************************************************** echo. echo BUILDING RELEASE BINARIES (this will take a while)... echo. cd ode-%1\build\vs2003 devenv.exe ode.sln /build DebugLib /project ode devenv.exe ode.sln /build DebugDLL /project ode devenv.exe ode.sln /build ReleaseLib /project ode devenv.exe ode.sln /build ReleaseDLL /project ode rem *********************************************************** rem * Package things up rem *********************************************************** cd ..\.. move lib\ReleaseDLL\ode.lib lib\ReleaseDLL\ode-imports.lib cd .. 7z a -tzip ode-win32-%1.zip ode-%1\*.txt ode-%1\include\ode\*.h ode-%1\lib\* ode-%1\docs\* rem *********************************************************** rem * Clean up rem *********************************************************** echo. echo CLEANING UP... echo. rmdir /s /q ode-%1 rem *********************************************************** rem * Upload to SF.net rem *********************************************************** echo. echo Ready to upload package to SourceForce, press ^^C to abort. pause echo "anonymous" > ftp.txt echo "starkos" >> ftp.txt echo "cd incoming" >> ftp.txt echo "bin" >> ftp.txt echo "put ode-win32-%1.zip" >> ftp.txt echo "quit" >> ftp.txt ftp -s:ftp.txt upload.sourceforge.net erase ftp.txt goto done rem *********************************************************** rem * Error messages rem *********************************************************** :show_usage echo Usage: msw_release.bat version_number goto done :done ode-0.16/tools/README.txt0000664000175200017520000000506413403272463012005 00000000000000HOW TO MAKE A RELEASE Originally by Jason Perkins (starkos@industriousone.com) PREREQUISITES In order to build an OpenDE release you'll need: * A Windows system * A Posix-like system (Linux, Mac OS X, Cygwin) * Visual Studio 2003 or later (for C++ release) * Visual Studio 2005 or later (for .NET release) * Subversion (command line version) * 7zip (command line version) * Doxygen All command line binaries (svn, 7z, doxygen) must be available on the system search path. INSTRUCTIONS * Update the version numbers in configure.in AC_INIT(ODE,0.9.0-rc1,ode@ode.org) ODE_CURRENT=0 ODE_REVISION=9 ODE_AGE=0-rc1 * Create a release branch in Subversion. Using TortoiseSVN: Update working copy Right-click working copy folder and choose Branch/Tag To https://opende.svn.sourceforge.net/svnroot/branches/0.9.0-rc1 Enter log message "Branching for 0.9.0-rc1 release" OK Using the command line: $ cd ode $ svn update $ svn copy . -m "Branching for..." https://opende.... (see above) * Run msw-release.bat from a Visual Studio command prompt to create the Windows binary package. I've used VS2003 for all releases since 0.5, but am thinking about switching up to VS2005. The format of this command is: > msw-release.bat 0.9.0-rc1 The version argument supplied to the script must match the name of the release branch in Subversion. * Run dotnet-release.bat to create the .NET bindings package. This script must be run from a Visual Studio 2005 (or later) command prompt. The format of the command is: > dotnet-release.bat 0.9.0-rc1 The version argument supplied to the script must match the name of the release branch in Subversion. * Run src-release.sh to create the source package. This script must be run from a Posix-like environment in order to prepare the configure script. I've tried it under Linux, Mac OS X, and Windows with Cygwin. $ ./src-release.sh 0.9.0-rc1 The version argument supplied to the script must match the name of the release branch in Subversion. * Visit the project site on SourceForge (http://sf.net/projects/opende) and create a new file release including all of the files. SANITY CHECKING A few optional, but recommeded, checks to make sure that everything worked properly. The binaries exist in lib/ include/ode/config.h exists configure script exists (if not, make sure autotools is installed) docs exist in docs/ (if not, make sure doxygen is on the path) ode-0.16/tools/src-release.sh0000664000175200017520000000536113403272463013050 00000000000000#!/bin/sh ################################################################### # ODE Source Code Release Script # Originally written by Jason Perkins (starkos@gmail.com) # # See README.txt in this directory for complete release # instructions before running this script. # # Prerequisites: # Command-line svn installed on path # Command-line zip installed on path # Command-line doxygen installed on path # Autotools support installed # Run from a Posix-like shell (Linux, OS X, Cygwin) ################################################################### # Check arguments if [ $# -ne 1 ]; then echo 1>&2 "Usage: $0 version_number" exit 1 fi ################################################################### # Pre-build checklist ################################################################### echo "" echo "STARTING PREBUILD CHECKLIST, PRESS ^C TO ABORT." echo "" echo "Is the version number '$1' correct?" read line echo "" echo "Have you created a release branch named '$1' in SVN?" read line echo "" echo Are 'svn', 'zip', and 'doxygen' on the path? read line echo "" echo "Okay, ready to build the source code package for version $1!" read line ################################################################### # Retrieve source code ################################################################### echo "" echo "RETRIEVING SOURCE CODE FROM REPOSITORY..." echo "" svn export https://opende.svn.sourceforge.net/svnroot/opende/branches/$1 ode-$1 ################################################################### # Prepare source code ################################################################### echo "" echo "PREPARING SOURCE TREE..." echo "" cd ode-$1 chmod 755 autogen.sh ./autogen.sh rm -rf autom4te.cache cp build/config-default.h include/ode/config.h cd ode/doc doxygen cd ../../.. ################################################################### # Package source code ################################################################### echo "" echo "PACKAGING SOURCE CODE..." echo "" zip -r9 ode-src-$1.zip ode-$1/* ################################################################### # Clean up ################################################################### echo "" echo "CLEANING UP..." echo "" rm -rf ode-$1 ##################################################################### # Send the files to SourceForge ##################################################################### echo "" echo "Upload packages to SourceForge?" read line if [ $line = "y" ]; then echo "Uploading to SourceForge..." echo "user anonymous starkos" > ftp.txt echo "cd incoming" >> ftp.txt echo "bin" >> ftp.txt echo "put ode-src-$1.zip" >> ftp.txt echo "quit" >> ftp.txt ftp -n upload.sourceforge.net < ftp.txt rm -f ftp.txt fi ode-0.16/tools/ode_convex_export.py0000664000175200017520000000356613403272463014420 00000000000000#!BPY """ Name: 'ODE Convex...' Blender: 244 Group: 'Export' Tooltip: 'Export to Open Dynamics.' """ __author__ = "Rodrigo Hernandez" __url__ = ("http://www.ode.org") __version__ = "0.1" __bpydoc__ = """\ ODE Convex Exporter This script Exports a Blender scene as a series of ODE Convex Geom data stored in a C header file. """ import Blender import bpy def WriteMesh(file,ob): mesh = ob.getData(mesh=1) # Write Point Count file.write("unsigned int %s_pointcount = %d;\n" % (ob.getName(),len(mesh.verts))) # Write Plane Count file.write("unsigned int %s_planecount = %d;\n" % (ob.getName(),len(mesh.faces))) # Write Points file.write("dReal %s_points[%d]={\n" % (ob.getName(),(len(mesh.verts)*3))) for vert in mesh.verts: if vert.index==(len(mesh.verts)-1): file.write("%f,%f,%f\n};\n" % (vert.co[0],vert.co[1],vert.co[2])) else: file.write("%f,%f,%f,\n" % (vert.co[0],vert.co[1],vert.co[2])) # Write Polygons file.write("unsigned int %s_polygons[]={\n" % ob.getName()) for face in mesh.faces: file.write("%d," % len(face.verts)) for vert in face.verts: file.write("%d," % vert.index) if face.index==(len(mesh.faces)-1): file.write("\n};\n"); else: file.write("\n"); # Write Planes file.write("dReal %s_planes[]={\n" % ob.getName()) for face in mesh.faces: # d calculated separatelly for code readability d = face.no[0]*face.verts[0].co[0]+face.no[1]*face.verts[0].co[1]+face.no[2]*face.verts[0].co[2] file.write("%f,%f,%f,%f,\n" % (face.no[0],face.no[1],face.no[2],d)) file.write("};\n"); # Entry Point sce = bpy.data.scenes.active in_editmode = Blender.Window.EditMode() if in_editmode: Blender.Window.EditMode(0) file = open("convex.h",mode='wt') for ob in sce.objects: if ob.getType()=='Mesh': WriteMesh(file,ob) file.close() if in_editmode: Blender.Window.EditMode(1) print "ODE Export Done"ode-0.16/Makefile.am0000664000175200017520000000160413403272610011171 00000000000000AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 --install if ENABLE_OU OU_DIR = ou endif if LIBCCD if LIBCCD_INTERNAL LIBCCD_DIR = libccd endif endif if ENABLE_DEMOS DRAWSTUFF_DIR = drawstuff endif if GIMPACT GIMPACT_DIR = GIMPACT endif if OPCODE OPCODE_DIR = OPCODE endif SUBDIRS = include \ $(DRAWSTUFF_DIR) \ $(GIMPACT_DIR) \ $(OPCODE_DIR) \ $(OU_DIR) \ $(LIBCCD_DIR) \ ode \ tests bin_SCRIPTS = ode-config # Utility rule for making a release release: dist-gzip dist-bzip2 @echo Created release packages for ${PACKAGE}-${VERSION}. EXTRA_DIST = bootstrap build tools \ CHANGELOG.txt COPYING INSTALL.txt CSR.txt README.md \ LICENSE.TXT LICENSE-BSD.TXT \ bindings \ CMakeLists.txt ode-config.cmake.in config.h.cmake.in cmake pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = ode.pc ode-0.16/bootstrap0000775000175200017520000000140613403272463011106 00000000000000#!/bin/sh echo "Please make sure that you use automake 1.11 or later" echo "Warnings about underquoted definitions are harmless" if [ `uname -s` = Darwin ]; then echo "On OSX, install latest libtool, as the OS provided glibtoolize will not work" fi echo "Running aclocal" aclocal -I m4 --install || exit 1 echo "Running libtoolize" libtoolize --copy --automake --install || exit 1 echo "Running autoheader" autoheader || exit 1 echo "Running automake" automake --foreign --add-missing --copy || exit 1 echo "Running autoconf" autoconf || exit 1 echo "Running bootstrap in ou directory" (cd ou && ./bootstrap) if [ -d libccd ]; then echo "Running bootstrap in libccd directory" (cd libccd && ./bootstrap) fi; echo "Now you are ready to run ./configure" ode-0.16/tests/0000775000175200017520000000000013403273061010357 500000000000000ode-0.16/tests/Makefile.am0000664000175200017520000000121613403272463012340 00000000000000SUBDIRS = joints UnitTest++ AM_CPPFLAGS = -I$(srcdir)/UnitTest++/src \ -I$(top_srcdir)/include \ -I$(top_builddir)/include \ -I$(top_srcdir)/ode/src if GIMPACT AM_CPPFLAGS += -DdTRIMESH_ENABLED -DdTRIMESH_GIMPACT endif if OPCODE AM_CPPFLAGS += -DdTRIMESH_ENABLED -DdTRIMESH_OPCODE endif check_PROGRAMS = tests TESTS = tests tests_SOURCES = \ collision.cpp \ friction.cpp \ joint.cpp \ main.cpp \ odemath.cpp tests_LDADD = \ $(top_builddir)/ode/src/libode.la \ joints/*.o \ UnitTest++/src/libunittestpp.la ode-0.16/tests/collision.cpp0000664000175200017520000001542613403272463013013 00000000000000#include #include #include "common.h" TEST(test_collision_trimesh_sphere_exact) { /* * This tests some extreme cases, where a sphere barely touches some triangles * with zero depth. */ #ifdef dTRIMESH_GIMPACT /* * Although GIMPACT is algorithmically able to handle this extreme case, * the numerical approximation used for the square root produces inexact results. */ return; #endif { const int VertexCount = 4; const int IndexCount = 2*3; // this is a square on the XY plane /* 3 2 +----+ | /| | / | | / | |/ | +----+ 0 1 */ float vertices[VertexCount * 3] = { -1,-1,0, 1,-1,0, 1,1,0, -1,1,0 }; dTriIndex indices[IndexCount] = { 0,1,2, 0,2,3 }; dTriMeshDataID data = dGeomTriMeshDataCreate(); dGeomTriMeshDataBuildSingle(data, vertices, 3 * sizeof(float), VertexCount, indices, IndexCount, 3 * sizeof(dTriIndex)); dGeomID trimesh = dCreateTriMesh(0, data, 0, 0, 0); const dReal radius = 4; dGeomID sphere = dCreateSphere(0, radius); dContactGeom cg[4]; int nc; dVector3 trinormal = { 0, 0, -1 }; // Test case: sphere touches the diagonal edge dGeomSetPosition(sphere, 0,0,radius); nc = dCollide(trimesh, sphere, 4, &cg[0], sizeof cg[0]); CHECK_EQUAL(2, nc); for (int i=0; i #include #include TEST(test_dNormalization3) { const dVector3 x = {1,0,0,0}; const dVector3 y = {0,1,0,0}; const dVector3 z = {0,0,1,0}; dVector3 v; // Check when value in first component (i.e. [0]) v[0] = REAL(1.0); v[1] = REAL(0.0); v[2] = REAL(0.0); dSafeNormalize3(v); CHECK_ARRAY_CLOSE(x, v, 3, 1e-6); CHECK_EQUAL(dCalcVectorLength3(v), REAL(1.0)); v[0] = REAL(0.1); v[1] = REAL(0.0); v[2] = REAL(0.0); dSafeNormalize3(v); CHECK_ARRAY_CLOSE(x, v, 3, 1e-6); CHECK_EQUAL(dCalcVectorLength3(v), REAL(1.0)); v[0] = REAL(1e-20); v[1] = REAL(0.0); v[2] = REAL(0.0); dSafeNormalize3(v); CHECK_ARRAY_CLOSE(x, v, 3, 1e-6); CHECK_EQUAL(dCalcVectorLength3(v), REAL(1.0)); // Check when value in first component (i.e. [0]) v[0] = REAL(0.0); v[1] = REAL(1.0); v[2] = REAL(0.0); dSafeNormalize3(v); CHECK_ARRAY_CLOSE(y, v, 3, 1e-6); CHECK_EQUAL(dCalcVectorLength3(v), REAL(1.0)); v[0] = REAL(0.0); v[1] = REAL(0.1); v[2] = REAL(0.0); dSafeNormalize3(v); CHECK_ARRAY_CLOSE(y, v, 3, 1e-6); CHECK_EQUAL(dCalcVectorLength3(v), REAL(1.0)); v[0] = REAL(0.0); v[1] = REAL(1e-20); v[2] = REAL(0.0); dSafeNormalize3(v); CHECK_ARRAY_CLOSE(y, v, 3, 1e-6); CHECK_EQUAL(dCalcVectorLength3(v), REAL(1.0)); // Check when value in first component (i.e. [0]) v[0] = REAL(0.0); v[1] = REAL(0.0); v[2] = REAL(1.0); dSafeNormalize3(v); CHECK_ARRAY_CLOSE(z, v, 3, 1e-6); CHECK_EQUAL(dCalcVectorLength3(v), REAL(1.0)); v[0] = REAL(0.0); v[1] = REAL(0.0); v[2] = REAL(0.1); dSafeNormalize3(v); CHECK_ARRAY_CLOSE(z, v, 3, 1e-6); CHECK_EQUAL(dCalcVectorLength3(v), REAL(1.0)); v[0] = REAL(0.0); v[1] = REAL(0.0); v[2] = REAL(1e-20); dSafeNormalize3(v); CHECK_ARRAY_CLOSE(z, v, 3, 1e-6); CHECK_EQUAL(dCalcVectorLength3(v), REAL(1.0)); // Check negative // Check when value in first component (i.e. [0]) v[0] = REAL(-1.0); v[1] = REAL(0.0); v[2] = REAL(0.0); dSafeNormalize3(v); CHECK_EQUAL(dCalcVectorLength3(v), REAL(1.0)); v[0] = REAL(-0.1); v[1] = REAL(0.0); v[2] = REAL(0.0); dSafeNormalize3(v); CHECK_EQUAL(dCalcVectorLength3(v), REAL(1.0)); v[0] = REAL(-1e-20); v[1] = REAL(0.0); v[2] = REAL(0.0); dSafeNormalize3(v); CHECK_EQUAL(dCalcVectorLength3(v), REAL(1.0)); // Check when value in first component (i.e. [0]) v[0] = REAL(0.0); v[1] = REAL(-1.0); v[2] = REAL(0.0); dSafeNormalize3(v); CHECK_EQUAL(dCalcVectorLength3(v), REAL(1.0)); v[0] = REAL(0.0); v[1] = REAL(-0.1); v[2] = REAL(0.0); dSafeNormalize3(v); CHECK_EQUAL(dCalcVectorLength3(v), REAL(1.0)); v[0] = REAL(0.0); v[1] = REAL(-1e-20); v[2] = REAL(0.0); dSafeNormalize3(v); CHECK_EQUAL(dCalcVectorLength3(v), REAL(1.0)); // Check when value in first component (i.e. [0]) v[0] = REAL(0.0); v[1] = REAL(0.0); v[2] = REAL(-1.0); dSafeNormalize3(v); CHECK_EQUAL(dCalcVectorLength3(v), REAL(1.0)); v[0] = REAL(0.0); v[1] = REAL(0.0); v[2] = REAL(-0.1); dSafeNormalize3(v); CHECK_EQUAL(dCalcVectorLength3(v), REAL(1.0)); v[0] = REAL(0.0); v[1] = REAL(0.0); v[2] = REAL(-1e-20); dSafeNormalize3(v); CHECK_EQUAL(dCalcVectorLength3(v), REAL(1.0)); v[0] = REAL(9999999999.0); v[1] = REAL(0.0); v[2] = REAL(1e-20); dSafeNormalize3(v); CHECK_EQUAL(dCalcVectorLength3(v), REAL(1.0)); v[0] = REAL(9999999999.0); v[1] = REAL(9999.0); v[2] = REAL(9.0); dSafeNormalize3(v); CHECK_CLOSE(dCalcVectorLength3(v), REAL(1.0),REAL(0.001)); } TEST(test_dOrthogonalizeR) { { dMatrix3 r1 = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0 }; dMatrix3 r2; memcpy(r2, r1, sizeof(dMatrix3)); dOrthogonalizeR(r2); CHECK_ARRAY_EQUAL(r1, r2, 12); } { dMatrix3 r1 = { 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0 }; dMatrix3 r2; memcpy(r2, r1, sizeof(dMatrix3)); dOrthogonalizeR(r2); CHECK_ARRAY_EQUAL(r1, r2, 12); } { dMatrix3 r1 = { 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0 }; dMatrix3 r2; memcpy(r2, r1, sizeof(dMatrix3)); dOrthogonalizeR(r2); CHECK_ARRAY_EQUAL(r1, r2, 12); } { dMatrix3 r1 = { -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1, 0 }; dMatrix3 r2; memcpy(r2, r1, sizeof(dMatrix3)); dOrthogonalizeR(r2); CHECK_ARRAY_EQUAL(r1, r2, 12); } { dMatrix3 r1 = { 0, -1, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0 }; dMatrix3 r2; memcpy(r2, r1, sizeof(dMatrix3)); dOrthogonalizeR(r2); CHECK_ARRAY_EQUAL(r1, r2, 12); } { dMatrix3 r1 = { 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0 }; dMatrix3 r2; memcpy(r2, r1, sizeof(dMatrix3)); dOrthogonalizeR(r2); CHECK_ARRAY_EQUAL(r1, r2, 12); } } ode-0.16/tests/main.cpp0000664000175200017520000000036713403272463011742 00000000000000// openode_UnitTest++.cpp : Defines the entry point for the console application. // #include #include int main() { dInitODE(); int res = UnitTest::RunAllTests(); dCloseODE(); return res; } ode-0.16/tests/joints/0000775000175200017520000000000013403273061011665 500000000000000ode-0.16/tests/joints/piston.cpp0000664000175200017520000013307213403272463013640 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ //234567890123456789012345678901234567890123456789012345678901234567890123456789 // 1 2 3 4 5 6 7 //////////////////////////////////////////////////////////////////////////////// // This file create unit test for some of the functions found in: // ode/src/joinst/piston.cpp // // //////////////////////////////////////////////////////////////////////////////// #include #include #include "../../ode/src/config.h" #include "../../ode/src/joints/piston.h" SUITE (TestdxJointPiston) { // The 2 bodies are positionned at (0, 0, 0), with no rotation // The joint is a Piston Joint // Axis is along the X axis // Anchor at (0, 0, 0) struct Fixture_dxJointPiston_B1_and_B2_At_Zero_Axis_Along_X { Fixture_dxJointPiston_B1_and_B2_At_Zero_Axis_Along_X() { wId = dWorldCreate(); bId1 = dBodyCreate (wId); dBodySetPosition (bId1, 0, 0, 0); bId2 = dBodyCreate (wId); dBodySetPosition (bId2, 0, 0, 0); jId = dJointCreatePiston (wId, 0); joint = (dxJointPiston*) jId; dJointAttach (jId, bId1, bId2); dJointSetPistonAxis (jId, axis[0], axis[1], axis[2]); } ~Fixture_dxJointPiston_B1_and_B2_At_Zero_Axis_Along_X() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId1; dBodyID bId2; dJointID jId; dxJointPiston* joint; static const dVector3 axis; static const dReal offset; }; const dVector3 Fixture_dxJointPiston_B1_and_B2_At_Zero_Axis_Along_X::axis = { 1, 0, 0 }; const dReal Fixture_dxJointPiston_B1_and_B2_At_Zero_Axis_Along_X::offset = REAL (3.1); // Move 1st body offset unit in the X direction // // X-------> X---------> Axis --> // B1 => B1 // B2 B2 // // Start with a Offset of offset unit // // X-------> X---------> Axis --> // B1 => B1 // B2 B2 TEST_FIXTURE (Fixture_dxJointPiston_B1_and_B2_At_Zero_Axis_Along_X, test_dJointSetPistonAxisOffset_B1_3Unit) { dJointSetPistonAnchor (jId, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); dBodySetPosition (bId1, offset, 0, 0); CHECK_CLOSE (offset, dJointGetPistonPosition (jId), 1e-4); dJointSetPistonAnchorOffset (jId, 0, 0, 0, offset*axis[0],offset*axis[1],offset*axis[2]); CHECK_CLOSE (offset, dJointGetPistonPosition (jId), 1e-4); dBodySetPosition (bId1, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); // Only here to test a deprecated warning #if 0 // the deprecated warning is not a functional part of the API, no need to test it. dJointSetPistonAxisDelta (jId, 1, 0, 0, 0, 0, 0); #endif } // Move 1st body offset unit in the opposite X direction // // X-------> X---------> Axis --> // B1 => B1 // B2 B2 // // Start with a Offset of -offset unit // // X-------> X---------> Axis --> // B1 => B1 // B2 B2 TEST_FIXTURE (Fixture_dxJointPiston_B1_and_B2_At_Zero_Axis_Along_X, test_dJointSetPistonAxisOffset_B1_Minus_3Unit) { dJointSetPistonAnchor (jId, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); dBodySetPosition (bId1, -offset, 0, 0); CHECK_CLOSE (-offset, dJointGetPistonPosition (jId), 1e-4); dJointSetPistonAnchorOffset (jId, 0, 0, 0, -offset*axis[0],-offset*axis[1],-offset*axis[2]); CHECK_CLOSE (-offset, dJointGetPistonPosition (jId), 1e-4); dBodySetPosition (bId1, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); } // Move 2nd body offset unit in the X direction // // X-------> X---------> Axis --> // B1 => B1 // B2 B2 // // Start with a Offset of offset unit // // X-------> X---------> Axis --> // B1 => B1 // B2 B2 TEST_FIXTURE (Fixture_dxJointPiston_B1_and_B2_At_Zero_Axis_Along_X, test_dJointSetPistonAxisOffset_B2_3Unit) { dJointSetPistonAnchor (jId, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); dBodySetPosition (bId2, offset, 0, 0); CHECK_CLOSE (-offset, dJointGetPistonPosition (jId), 1e-4); dJointSetPistonAnchorOffset (jId, 0, 0, 0, -offset*axis[0],-offset*axis[1],-offset*axis[2]); CHECK_CLOSE (-offset, dJointGetPistonPosition (jId), 1e-4); dBodySetPosition (bId2, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); } // Move 2nd body offset unit in the opposite X direction // // X-------> X---------> Axis --> // B1 => B1 // B2 B2 // // Start with a Offset of -offset unit // // X-------> X---------> Axis --> // B1 => B1 // B2 B2 TEST_FIXTURE (Fixture_dxJointPiston_B1_and_B2_At_Zero_Axis_Along_X, test_dJointSetPistonAxisOffset_B2_Minus_3Unit) { dJointSetPistonAnchor (jId, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); dBodySetPosition (bId2, -offset, 0, 0); CHECK_CLOSE (offset, dJointGetPistonPosition (jId), 1e-4); dJointSetPistonAnchorOffset (jId, 0, 0, 0, offset*axis[0],offset*axis[1],offset*axis[2]); CHECK_CLOSE (offset, dJointGetPistonPosition (jId), 1e-4); dBodySetPosition (bId2, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); } // The 2 bodies are positionned at (0, 0, 0), with no rotation // The joint is a Piston Joint // Axis is the opposite of the X axis // Anchor at (0, 0, 0) struct Fixture_dxJointPiston_B1_and_B2_At_Zero_Axis_Inverse_of_X { Fixture_dxJointPiston_B1_and_B2_At_Zero_Axis_Inverse_of_X() { wId = dWorldCreate(); bId1 = dBodyCreate (wId); dBodySetPosition (bId1, 0, 0, 0); bId2 = dBodyCreate (wId); dBodySetPosition (bId2, 0, 0, 0); jId = dJointCreatePiston (wId, 0); joint = (dxJointPiston*) jId; dJointAttach (jId, bId1, bId2); dJointSetPistonAxis (jId, axis[0], axis[1], axis[2]); } ~Fixture_dxJointPiston_B1_and_B2_At_Zero_Axis_Inverse_of_X() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId1; dBodyID bId2; dJointID jId; dxJointPiston* joint; static const dVector3 axis; static const dReal offset; }; const dVector3 Fixture_dxJointPiston_B1_and_B2_At_Zero_Axis_Inverse_of_X::axis = { -1, 0, 0 }; const dReal Fixture_dxJointPiston_B1_and_B2_At_Zero_Axis_Inverse_of_X::offset = REAL (3.1); // Move 1st body offset unit in the X direction // // X-------> X---------> <-- Axis // B1 => B1 // B2 B2 // // Start with a Offset of offset unit // // X-------> X---------> <-- Axis // B1 => B1 // B2 B2 TEST_FIXTURE (Fixture_dxJointPiston_B1_and_B2_At_Zero_Axis_Inverse_of_X, test_dJointSetPistonAxisOffset_B1_3Unit) { dJointSetPistonAnchor (jId, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); dBodySetPosition (bId1, offset, 0, 0); CHECK_CLOSE (-offset, dJointGetPistonPosition (jId), 1e-4); dJointSetPistonAnchorOffset (jId, 0, 0, 0, -offset*axis[0],-offset*axis[1],-offset*axis[2]); CHECK_CLOSE (-offset, dJointGetPistonPosition (jId), 1e-4); dBodySetPosition (bId1, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); } // Move 1st body offset unit in the opposite X direction // // X-------> X---------> <-- Axis // B1 => B1 // B2 B2 // // Start with a Offset of offset unit // // X-------> X---------> <-- Axis // B1 => B1 // B2 B2 TEST_FIXTURE (Fixture_dxJointPiston_B1_and_B2_At_Zero_Axis_Inverse_of_X, test_dJointSetPistonAxisOffset_B1_Minus_3Unit) { dJointSetPistonAnchor (jId, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); dBodySetPosition (bId1, -offset, 0, 0); CHECK_CLOSE (offset, dJointGetPistonPosition (jId), 1e-4); dJointSetPistonAnchorOffset (jId, 0, 0, 0, offset*axis[0],offset*axis[1],offset*axis[2]); CHECK_CLOSE (offset, dJointGetPistonPosition (jId), 1e-4); dBodySetPosition (bId1, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); } // Move 2nd body offset unit in the X direction // // X-------> X---------> <-- Axis // B1 => B1 // B2 B2 // // Start with a Offset of offset unit // // X-------> X---------> <-- Axis // B1 => B1 // B2 B2 TEST_FIXTURE (Fixture_dxJointPiston_B1_and_B2_At_Zero_Axis_Inverse_of_X, test_dJointSetPistonAxisOffset_B2_3Unit) { dJointSetPistonAnchor (jId, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); dBodySetPosition (bId2, offset, 0, 0); CHECK_CLOSE (offset, dJointGetPistonPosition (jId), 1e-4); dJointSetPistonAnchorOffset (jId, 0, 0, 0, offset*axis[0],offset*axis[1],offset*axis[2]); CHECK_CLOSE (offset, dJointGetPistonPosition (jId), 1e-4); dBodySetPosition (bId2, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); } // Move 2nd body offset unit in the opposite X direction // // X-------> X---------> <-- Axis // B1 => B1 // B2 B2 // // Start with a Offset of -offset unit // // X-------> X---------> <-- Axis // B1 => B1 // B2 B2 TEST_FIXTURE (Fixture_dxJointPiston_B1_and_B2_At_Zero_Axis_Inverse_of_X, test_dJointSetPistonAxisOffset_B2_Minus_3Unit) { dJointSetPistonAnchor (jId, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); dBodySetPosition (bId2, -offset, 0, 0); CHECK_CLOSE (-offset, dJointGetPistonPosition (jId), 1e-4); dJointSetPistonAnchorOffset (jId, 0, 0, 0, -offset*axis[0],-offset*axis[1],-offset*axis[2]); CHECK_CLOSE (-offset, dJointGetPistonPosition (jId), 1e-4); dBodySetPosition (bId2, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); } // Only body 1 // The body are positionned at (0, 0, 0), with no rotation // The joint is a Piston Joint // Axis is along the X axis // Anchor at (0, 0, 0) struct Fixture_dxJointPiston_B1_At_Zero_Axis_Along_X { Fixture_dxJointPiston_B1_At_Zero_Axis_Along_X() { wId = dWorldCreate(); bId1 = dBodyCreate (wId); dBodySetPosition (bId1, 0, 0, 0); jId = dJointCreatePiston (wId, 0); joint = (dxJointPiston*) jId; dJointAttach (jId, bId1, NULL); dJointSetPistonAxis (jId, axis[0], axis[1], axis[2]); } ~Fixture_dxJointPiston_B1_At_Zero_Axis_Along_X() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId1; dJointID jId; dxJointPiston* joint; static const dVector3 axis; static const dReal offset; }; const dVector3 Fixture_dxJointPiston_B1_At_Zero_Axis_Along_X::axis = { 1, 0, 0 }; const dReal Fixture_dxJointPiston_B1_At_Zero_Axis_Along_X::offset = REAL (3.1); // Move 1st body offset unit in the X direction // // X-------> X---------> Axis --> // B1 => B1 // // Start with a Offset of offset unit // // X-------> X---------> Axis --> // B1 => B1 TEST_FIXTURE (Fixture_dxJointPiston_B1_At_Zero_Axis_Along_X, test_dJointSetPistonAxisOffset_B1_OffsetUnit) { dJointSetPistonAnchor (jId, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); dBodySetPosition (bId1, offset, 0, 0); CHECK_CLOSE (offset, dJointGetPistonPosition (jId), 1e-4); dJointSetPistonAnchorOffset (jId, 0, 0, 0, offset*axis[0],offset*axis[1],offset*axis[2]); CHECK_CLOSE (offset, dJointGetPistonPosition (jId), 1e-4); dBodySetPosition (bId1, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); } // Move 1st body offset unit in the opposite X direction // // X-------> X---------> Axis --> // B1 => B1 // // Start with a Offset of -offset unit // // X-------> X---------> Axis --> // B1 => B1 TEST_FIXTURE (Fixture_dxJointPiston_B1_At_Zero_Axis_Along_X, test_dJointSetPistonAxisOffset_B1_Minus_OffsetUnit) { dJointSetPistonAnchor (jId, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); dBodySetPosition (bId1, -offset, 0, 0); CHECK_CLOSE (-offset, dJointGetPistonPosition (jId), 1e-4); dJointSetPistonAnchorOffset (jId, 0, 0, 0, -offset*axis[0],-offset*axis[1],-offset*axis[2]); CHECK_CLOSE (-offset, dJointGetPistonPosition (jId), 1e-4); dBodySetPosition (bId1, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); } // Only body 1 // The body are positionned at (0, 0, 0), with no rotation // The joint is a Piston Joint // Axis is in the oppsite X axis // Anchor at (0, 0, 0) struct Fixture_dxJointPiston_B1_At_Zero_Axis_Inverse_of_X { Fixture_dxJointPiston_B1_At_Zero_Axis_Inverse_of_X() { wId = dWorldCreate(); bId1 = dBodyCreate (wId); dBodySetPosition (bId1, 0, 0, 0); jId = dJointCreatePiston (wId, 0); joint = (dxJointPiston*) jId; dJointAttach (jId, bId1, NULL); dJointSetPistonAxis (jId, axis[0], axis[1], axis[2]); } ~Fixture_dxJointPiston_B1_At_Zero_Axis_Inverse_of_X() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId1; dJointID jId; dxJointPiston* joint; static const dVector3 axis; static const dReal offset; }; const dVector3 Fixture_dxJointPiston_B1_At_Zero_Axis_Inverse_of_X::axis = { -1, 0, 0 }; const dReal Fixture_dxJointPiston_B1_At_Zero_Axis_Inverse_of_X::offset = REAL (3.1); // Move 1st body offset unit in the X direction // // X-------> X---------> <--- Axis // B1 => B1 // // Start with a Offset of offset unit // // X-------> X---------> <--- Axis // B1 => B1 TEST_FIXTURE (Fixture_dxJointPiston_B1_At_Zero_Axis_Inverse_of_X, test_dJointSetPistonAxisOffset_B1_OffsetUnit) { dJointSetPistonAnchor (jId, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); dBodySetPosition (bId1, offset, 0, 0); CHECK_CLOSE (-offset, dJointGetPistonPosition (jId), 1e-4); dJointSetPistonAnchorOffset (jId, 0, 0, 0, -offset*axis[0],-offset*axis[1],-offset*axis[2]); CHECK_CLOSE (-offset, dJointGetPistonPosition (jId), 1e-4); dBodySetPosition (bId1, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); } // Move 1st body offset unit in the opposite X direction // // X-------> X---------> <--- Axis // B1 => B1 // // Start with a Offset of -offset unit // // X-------> X---------> <--- Axis // B1 => B1 TEST_FIXTURE (Fixture_dxJointPiston_B1_At_Zero_Axis_Inverse_of_X, test_dJointSetPistonAxisOffset_B1_Minus_OffsetUnit) { dJointSetPistonAnchor (jId, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); dBodySetPosition (bId1, -offset, 0, 0); CHECK_CLOSE (offset, dJointGetPistonPosition (jId), 1e-4); dJointSetPistonAnchorOffset (jId, 0, 0, 0, offset*axis[0],offset*axis[1],offset*axis[2]); CHECK_CLOSE (offset, dJointGetPistonPosition (jId), 1e-4); dBodySetPosition (bId1, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); } // Only body 2 // The body are positionned at (0, 0, 0), with no rotation // The joint is a Piston Joint // Axis is along the X axis // Anchor at (0, 0, 0) struct Fixture_dxJointPiston_B2_At_Zero_Axis_Along_X { Fixture_dxJointPiston_B2_At_Zero_Axis_Along_X() { wId = dWorldCreate(); bId2 = dBodyCreate (wId); dBodySetPosition (bId2, 0, 0, 0); jId = dJointCreatePiston (wId, 0); joint = (dxJointPiston*) jId; dJointAttach (jId, NULL, bId2); dJointSetPistonAxis (jId, axis[0], axis[1], axis[2]); } ~Fixture_dxJointPiston_B2_At_Zero_Axis_Along_X() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId2; dJointID jId; dxJointPiston* joint; static const dVector3 axis; static const dReal offset; }; const dVector3 Fixture_dxJointPiston_B2_At_Zero_Axis_Along_X::axis = { 1, 0, 0 }; const dReal Fixture_dxJointPiston_B2_At_Zero_Axis_Along_X::offset = REAL (3.1); // Move 2nd body offset unit in the X direction // // X-------> X---------> Axis --> // B2 => B2 // // Start with a Offset of offset unit // // X-------> X---------> Axis --> // B2 => B2 TEST_FIXTURE (Fixture_dxJointPiston_B2_At_Zero_Axis_Along_X, test_dJointSetPistonAxisOffset_B2_OffsetUnit) { dJointSetPistonAnchor (jId, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); dBodySetPosition (bId2, offset, 0, 0); CHECK_CLOSE (-offset, dJointGetPistonPosition (jId), 1e-4); dJointSetPistonAnchorOffset (jId, 0, 0, 0, -offset*axis[0],-offset*axis[1],-offset*axis[2]); CHECK_CLOSE (-offset, dJointGetPistonPosition (jId), 1e-4); dBodySetPosition (bId2, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); } // Move 2nd body offset unit in the opposite X direction // // X-------> X---------> Axis --> // B2 => B2 // // Start with a Offset of -offset unit // // X-------> X---------> Axis --> // B2 => B2 TEST_FIXTURE (Fixture_dxJointPiston_B2_At_Zero_Axis_Along_X, test_dJointSetPistonAxisOffset_B2_Minus_OffsetUnit) { dJointSetPistonAnchor (jId, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); dBodySetPosition (bId2, -offset, 0, 0); CHECK_CLOSE (offset, dJointGetPistonPosition (jId), 1e-4); dJointSetPistonAnchorOffset (jId, 0, 0, 0, offset*axis[0],offset*axis[1],offset*axis[2]); CHECK_CLOSE (offset, dJointGetPistonPosition (jId), 1e-4); dBodySetPosition (bId2, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); } // Only body 2 // The body are positionned at (0, 0, 0), with no rotation // The joint is a Piston Joint // Axis is in the opposite X axis // Anchor at (0, 0, 0) struct Fixture_dxJointPiston_B2_At_Zero_Axis_Inverse_of_X { Fixture_dxJointPiston_B2_At_Zero_Axis_Inverse_of_X() { wId = dWorldCreate(); bId2 = dBodyCreate (wId); dBodySetPosition (bId2, 0, 0, 0); jId = dJointCreatePiston (wId, 0); joint = (dxJointPiston*) jId; dJointAttach (jId, NULL, bId2); dJointSetPistonAxis (jId, axis[0], axis[1], axis[2]); } ~Fixture_dxJointPiston_B2_At_Zero_Axis_Inverse_of_X() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId2; dJointID jId; dxJointPiston* joint; static const dVector3 axis; static const dReal offset; }; const dVector3 Fixture_dxJointPiston_B2_At_Zero_Axis_Inverse_of_X::axis = { -1, 0, 0 }; const dReal Fixture_dxJointPiston_B2_At_Zero_Axis_Inverse_of_X::offset = REAL (3.1); // Move 2nd body offset unit in the X direction // // X-------> X---------> <--- Axis // B2 => B2 // // Start with a Offset of offset unit // // X-------> X---------> <--- Axis // B2 => B2 TEST_FIXTURE (Fixture_dxJointPiston_B2_At_Zero_Axis_Inverse_of_X, test_dJointSetPistonAxisOffset_B2_OffsetUnit) { dJointSetPistonAnchor (jId, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); dBodySetPosition (bId2, offset, 0, 0); CHECK_CLOSE (offset, dJointGetPistonPosition (jId), 1e-4); dJointSetPistonAnchorOffset (jId, 0, 0, 0, offset*axis[0],offset*axis[1],offset*axis[2]); CHECK_CLOSE (offset, dJointGetPistonPosition (jId), 1e-4); dBodySetPosition (bId2, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); #if 0 // another deprecated warning test? dJointSetPistonAxisDelta (jId, 1, 0, 0, 0, 0, 0); #endif } // Move 1st body offset unit in the opposite X direction // // X-------> X---------> <--- Axis // B2 => B2 // // Start with a Offset of -offset unit // // X-------> X---------> <--- Axis // B2 => B2 TEST_FIXTURE (Fixture_dxJointPiston_B2_At_Zero_Axis_Inverse_of_X, test_dJointSetPistonAxisOffset_B2_Minus_OffsetUnit) { dJointSetPistonAnchor (jId, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); dBodySetPosition (bId2, -offset, 0, 0); CHECK_CLOSE (-offset, dJointGetPistonPosition (jId), 1e-4); dJointSetPistonAnchorOffset (jId, 0, 0, 0, -offset*axis[0],-offset*axis[1],-offset*axis[2]); CHECK_CLOSE (-offset, dJointGetPistonPosition (jId), 1e-4); dBodySetPosition (bId2, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); } // ========================================================================== // Test Position Rate // ========================================================================== // Apply force on 1st body in the X direction also the Axis direction // // X-------> X---------> Axis --> // B1 F-> => B1 // B2 B2 TEST_FIXTURE (Fixture_dxJointPiston_B1_and_B2_At_Zero_Axis_Along_X, test_dJointSetPistonPositionRate_Force_Along_Axis_on_B1) { CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); CHECK_CLOSE (0.0, dJointGetPistonPositionRate (jId), 1e-4); dBodyAddForce (bId1, 1.0, 0, 0); dWorldQuickStep (wId, 1.0); CHECK_CLOSE (1, dJointGetPistonPositionRate (jId), 1e-4); } // Apply force on 1st body in the inverse X direction // // X-------> X---------> Axis --> // B1 <-F => B1 // B2 B2 TEST_FIXTURE (Fixture_dxJointPiston_B1_and_B2_At_Zero_Axis_Along_X, test_dJointSetPistonPositionRate_Force_Inverse_of_Axis_on_B1) { CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); CHECK_CLOSE (0.0, dJointGetPistonPositionRate (jId), 1e-4); dBodyAddForce (bId1, -1.0, 0, 0); dWorldQuickStep (wId, 1.0); CHECK_CLOSE (-1, dJointGetPistonPositionRate (jId), 1e-4); } // Apply force on 1st body in the X direction also the Axis direction // // X-------> X---------> <-- Axis // B1 F-> => B1 // B2 B2 TEST_FIXTURE (Fixture_dxJointPiston_B1_and_B2_At_Zero_Axis_Inverse_of_X, test_dJointSetPistonPositionRate_Force_Inverse_Axis_on_B1) { CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); CHECK_CLOSE (0.0, dJointGetPistonPositionRate (jId), 1e-4); dBodyAddForce (bId1, 1.0, 0, 0); dWorldQuickStep (wId, 1.0); CHECK_CLOSE (-1, dJointGetPistonPositionRate (jId), 1e-4); } // Apply force on 1st body in the inverse X direction // // X-------> X---------> <-- Axis // B1 <-F => B1 // B2 B2 TEST_FIXTURE (Fixture_dxJointPiston_B1_and_B2_At_Zero_Axis_Inverse_of_X, test_dJointSetPistonPositionRate_Force_Along_of_Axis_on_B1) { CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); CHECK_CLOSE (0.0, dJointGetPistonPositionRate (jId), 1e-4); dBodyAddForce (bId1, -1.0, 0, 0); dWorldQuickStep (wId, 1.0); CHECK_CLOSE (1, dJointGetPistonPositionRate (jId), 1e-4); } // Apply force on 1st body in the X direction also the Axis direction // // X-------> X---------> Axis --> // B1 => B1 // B2 F-> B2 TEST_FIXTURE (Fixture_dxJointPiston_B1_and_B2_At_Zero_Axis_Along_X, test_dJointSetPistonPositionRate_Force_Along_Axis_on_B2) { CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); CHECK_CLOSE (0.0, dJointGetPistonPositionRate (jId), 1e-4); dBodyAddForce (bId2, 1.0, 0, 0); dWorldQuickStep (wId, 1.0); CHECK_CLOSE (-1, dJointGetPistonPositionRate (jId), 1e-4); } // Apply force on 1st body in the inverse X direction // // X-------> X---------> Axis --> // B1 => B1 // B2 <-F B2 TEST_FIXTURE (Fixture_dxJointPiston_B1_and_B2_At_Zero_Axis_Along_X, test_dJointSetPistonPositionRate_Force_Inverse_of_Axis_on_B2) { CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); CHECK_CLOSE (0.0, dJointGetPistonPositionRate (jId), 1e-4); dBodyAddForce (bId2, -1.0, 0, 0); dWorldQuickStep (wId, 1.0); CHECK_CLOSE (1, dJointGetPistonPositionRate (jId), 1e-4); } // Apply force on 1st body in the X direction also the Axis direction // // X-------> X---------> <-- Axis // B1 => B1 // B2 F-> B2 TEST_FIXTURE (Fixture_dxJointPiston_B1_and_B2_At_Zero_Axis_Inverse_of_X, test_dJointSetPistonPositionRate_Force_Inverse_Axis_on_B2) { CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); CHECK_CLOSE (0.0, dJointGetPistonPositionRate (jId), 1e-4); dBodyAddForce (bId2, 1.0, 0, 0); dWorldQuickStep (wId, 1.0); CHECK_CLOSE (1, dJointGetPistonPositionRate (jId), 1e-4); } // Apply force on 1st body in the inverse X direction // // X-------> X---------> <-- Axis // B1 => B1 // B2 <-F B2 TEST_FIXTURE (Fixture_dxJointPiston_B1_and_B2_At_Zero_Axis_Inverse_of_X, test_dJointSetPistonPositionRate_Force_Along_of_Axis_on_B2) { CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); CHECK_CLOSE (0.0, dJointGetPistonPositionRate (jId), 1e-4); dBodyAddForce (bId2, -1.0, 0, 0); dWorldQuickStep (wId, 1.0); CHECK_CLOSE (-1, dJointGetPistonPositionRate (jId), 1e-4); } // Apply force on 1st body in the X direction also the Axis direction // // X-------> X---------> Axis --> // B1 F-> => B1 TEST_FIXTURE (Fixture_dxJointPiston_B1_At_Zero_Axis_Along_X, test_dJointSetPistonPositionRate_Force_Along_Axis_on_B1) { CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); CHECK_CLOSE (0.0, dJointGetPistonPositionRate (jId), 1e-4); dBodyAddForce (bId1, 1.0, 0, 0); dWorldQuickStep (wId, 1.0); CHECK_CLOSE (1, dJointGetPistonPositionRate (jId), 1e-4); } // Apply force on 1st body in the inverse X direction // // X-------> X---------> Axis --> // B1 <-F => B1 TEST_FIXTURE (Fixture_dxJointPiston_B1_At_Zero_Axis_Along_X, test_dJointSetPistonPositionRate_Force_Inverse_of_Axis_on_B1) { CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); CHECK_CLOSE (0.0, dJointGetPistonPositionRate (jId), 1e-4); dBodyAddForce (bId1, -1.0, 0, 0); dWorldQuickStep (wId, 1.0); CHECK_CLOSE (-1, dJointGetPistonPositionRate (jId), 1e-4); } // Apply force on 1st body in the X direction also the Axis direction // // X-------> X---------> <-- Axis // B1 F-> => B1 TEST_FIXTURE (Fixture_dxJointPiston_B1_At_Zero_Axis_Inverse_of_X, test_dJointSetPistonPositionRate_Force_Inverse_Axis_on_B1) { CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); CHECK_CLOSE (0.0, dJointGetPistonPositionRate (jId), 1e-4); dBodyAddForce (bId1, 1.0, 0, 0); dWorldQuickStep (wId, 1.0); CHECK_CLOSE (-1, dJointGetPistonPositionRate (jId), 1e-4); } // Apply force on 1st body in the inverse X direction // // X-------> X---------> <-- Axis // B1 <-F => B1 TEST_FIXTURE (Fixture_dxJointPiston_B1_At_Zero_Axis_Inverse_of_X, test_dJointSetPistonPositionRate_Force_Along_of_Axis_on_B1) { CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); CHECK_CLOSE (0.0, dJointGetPistonPositionRate (jId), 1e-4); dBodyAddForce (bId1, -1.0, 0, 0); dWorldQuickStep (wId, 1.0); CHECK_CLOSE (1, dJointGetPistonPositionRate (jId), 1e-4); } // Apply force on body 2 in the X direction also the Axis direction // // X-------> X---------> Axis --> // B2 F-> B2 TEST_FIXTURE (Fixture_dxJointPiston_B2_At_Zero_Axis_Along_X, test_dJointSetPistonPositionRate_Force_Along_Axis_on_B2) { CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); CHECK_CLOSE (0.0, dJointGetPistonPositionRate (jId), 1e-4); dBodyAddForce (bId2, 1.0, 0, 0); dWorldQuickStep (wId, 1.0); CHECK_CLOSE (-1, dJointGetPistonPositionRate (jId), 1e-4); } // Apply force on body 2 in the inverse X direction // // X-------> X---------> Axis --> // B2 <-F B2 TEST_FIXTURE (Fixture_dxJointPiston_B2_At_Zero_Axis_Along_X, test_dJointSetPistonPositionRate_Force_Inverse_of_Axis_on_B2) { CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); CHECK_CLOSE (0.0, dJointGetPistonPositionRate (jId), 1e-4); dBodyAddForce (bId2, -1.0, 0, 0); dWorldQuickStep (wId, 1.0); CHECK_CLOSE (1, dJointGetPistonPositionRate (jId), 1e-4); } // Apply force on body 2 in the X direction also the Axis direction // // X-------> X---------> <-- Axis // B2 F-> B2 TEST_FIXTURE (Fixture_dxJointPiston_B2_At_Zero_Axis_Inverse_of_X, test_dJointSetPistonPositionRate_Force_Inverse_Axis_on_B2) { CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); CHECK_CLOSE (0.0, dJointGetPistonPositionRate (jId), 1e-4); dBodyAddForce (bId2, 1.0, 0, 0); dWorldQuickStep (wId, 1.0); CHECK_CLOSE (1, dJointGetPistonPositionRate (jId), 1e-4); } // Apply force on body 2 in the inverse X direction // // X-------> X---------> <-- Axis // B2 <-F B2 TEST_FIXTURE (Fixture_dxJointPiston_B2_At_Zero_Axis_Inverse_of_X, test_dJointSetPistonPositionRate_Force_Along_of_Axis_on_B2) { CHECK_CLOSE (0.0, dJointGetPistonPosition (jId), 1e-4); CHECK_CLOSE (0.0, dJointGetPistonPositionRate (jId), 1e-4); dBodyAddForce (bId2, -1.0, 0, 0); dWorldQuickStep (wId, 1.0); CHECK_CLOSE (-1, dJointGetPistonPositionRate (jId), 1e-4); } // Create 2 bodies attached by a Piston joint // Axis is along the X axis (Default value // Anchor at (0, 0, 0) (Default value) // // ^Y // | // * Body2 // | // | // Body1 | // * Z--------> struct dxJointPiston_Test_Initialization { dxJointPiston_Test_Initialization() { wId = dWorldCreate(); // Remove gravity to have the only force be the force of the joint dWorldSetGravity(wId, 0,0,0); for (int j=0; j<2; ++j) { bId[j][0] = dBodyCreate (wId); dBodySetPosition (bId[j][0], -1, -2, -3); bId[j][1] = dBodyCreate (wId); dBodySetPosition (bId[j][1], 11, 22, 33); dMatrix3 R; dVector3 axis; // Random axis axis[0] = REAL(0.53); axis[1] = -REAL(0.71); axis[2] = REAL(0.43); dNormalize3(axis); dRFromAxisAndAngle (R, axis[0], axis[1], axis[2], REAL(0.47123)); // 27deg dBodySetRotation (bId[j][0], R); axis[0] = REAL(1.2); axis[1] = REAL(0.87); axis[2] = -REAL(0.33); dNormalize3(axis); dRFromAxisAndAngle (R, axis[0], axis[1], axis[2], REAL(0.47123)); // 27deg dBodySetRotation (bId[j][1], R); jId[j] = dJointCreatePiston (wId, 0); dJointAttach (jId[j], bId[j][0], bId[j][1]); } } ~dxJointPiston_Test_Initialization() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId[2][2]; dJointID jId[2]; }; // Test if setting a Piston with its default values // will behave the same as a default Piston joint TEST_FIXTURE (dxJointPiston_Test_Initialization, test_Piston_Initialization) { using namespace std; dVector3 axis; dJointGetPistonAxis(jId[1], axis); dJointSetPistonAxis(jId[1], axis[0], axis[1], axis[2]); dVector3 anchor; dJointGetPistonAnchor(jId[1], anchor); dJointSetPistonAnchor(jId[1], anchor[0], anchor[1], anchor[2]); for (int b=0; b<2; ++b) { // Compare body b of the first joint with its equivalent on the // second joint const dReal *qA = dBodyGetQuaternion(bId[0][b]); const dReal *qB = dBodyGetQuaternion(bId[1][b]); CHECK_CLOSE (qA[0], qB[0], 1e-6); CHECK_CLOSE (qA[1], qB[1], 1e-6); CHECK_CLOSE (qA[2], qB[2], 1e-6); CHECK_CLOSE (qA[3], qB[3], 1e-6); } dWorldStep (wId,0.5); dWorldStep (wId,0.5); dWorldStep (wId,0.5); dWorldStep (wId,0.5); for (int b=0; b<2; ++b) { // Compare body b of the first joint with its equivalent on the // second joint const dReal *qA = dBodyGetQuaternion(bId[0][b]); const dReal *qB = dBodyGetQuaternion(bId[1][b]); CHECK_CLOSE (qA[0], qB[0], 1e-6); CHECK_CLOSE (qA[1], qB[1], 1e-6); CHECK_CLOSE (qA[2], qB[2], 1e-6); CHECK_CLOSE (qA[3], qB[3], 1e-6); const dReal *posA = dBodyGetPosition(bId[0][b]); const dReal *posB = dBodyGetPosition(bId[1][b]); CHECK_CLOSE (posA[0], posB[0], 1e-6); CHECK_CLOSE (posA[1], posB[1], 1e-6); CHECK_CLOSE (posA[2], posB[2], 1e-6); CHECK_CLOSE (posA[3], posB[3], 1e-6); } } // Compare only one body to 2 bodies with one fixed. // // The body are positionned at (0, 0, 0), with no rotation // The joint is a Piston Joint // Axis is along the X axis // Anchor at (0, 0, 0) struct Fixture_dxJointPiston_Compare_Body_At_Zero_Axis_Along_X { Fixture_dxJointPiston_Compare_Body_At_Zero_Axis_Along_X() { wId = dWorldCreate(); bId1_12 = dBodyCreate (wId); dBodySetPosition (bId1_12, 0, 0, 0); bId2_12 = dBodyCreate (wId); dBodySetPosition (bId2_12, 0, 0, 0); // The force will be added in the function since it is not // always on the same body jId_12 = dJointCreatePiston (wId, 0); dJointAttach(jId_12, bId1_12, bId2_12); fixed = dJointCreateFixed (wId, 0); bId = dBodyCreate (wId); dBodySetPosition (bId, 0, 0, 0); dBodyAddForce (bId, 4, 0, 0); jId = dJointCreatePiston (wId, 0); } ~Fixture_dxJointPiston_Compare_Body_At_Zero_Axis_Along_X() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId1_12; dBodyID bId2_12; dJointID jId_12; // Joint with 2 bodies dJointID fixed; dBodyID bId; dJointID jId; // Joint with one body }; // This test compare the result of a slider with 2 bodies where body body 2 is // fixed to the world to a slider with only one body at position 1. // // Test the limits [-1, 0.25] when only one body at is attached to the joint // using dJointAttache(jId, bId, 0); // TEST_FIXTURE(Fixture_dxJointPiston_Compare_Body_At_Zero_Axis_Along_X, test_Limit_minus1_025_One_Body_on_left) { dBodyAddForce (bId1_12, 4, 0, 0); dJointAttach(jId_12, bId1_12, bId2_12); dJointSetPistonParam(jId_12, dParamLoStop, -1); dJointSetPistonParam(jId_12, dParamHiStop, 0.25); dJointAttach(fixed, 0, bId2_12); dJointSetFixed(fixed); dJointAttach(jId, bId, 0); dJointSetPistonParam(jId, dParamLoStop, -1); dJointSetPistonParam(jId, dParamHiStop, 0.25); for (int i=0; i<50; ++i) dWorldStep(wId, 1.0); const dReal *pos1_12 = dBodyGetPosition(bId1_12); const dReal *pos = dBodyGetPosition(bId); CHECK_CLOSE (pos1_12[0], pos[0], 1e-2); CHECK_CLOSE (pos1_12[1], pos[1], 1e-2); CHECK_CLOSE (pos1_12[2], pos[2], 1e-2); const dReal *q1_12 = dBodyGetQuaternion(bId1_12); const dReal *q = dBodyGetQuaternion(bId); CHECK_CLOSE (q1_12[0], q[0], 1e-4); CHECK_CLOSE (q1_12[1], q[1], 1e-4); CHECK_CLOSE (q1_12[2], q[2], 1e-4); CHECK_CLOSE (q1_12[3], q[3], 1e-4); } // This test compare the result of a slider with 2 bodies where body body 1 is // fixed to the world to a slider with only one body at position 2. // // Test the limits [-1, 0.25] when only one body at is attached to the joint // using dJointAttache(jId, 0, bId); // TEST_FIXTURE(Fixture_dxJointPiston_Compare_Body_At_Zero_Axis_Along_X, test_Limit_minus1_025_One_Body_on_right) { dBodyAddForce (bId2_12, 4, 0, 0); dJointAttach(jId_12, bId1_12, bId2_12); dJointSetPistonParam(jId_12, dParamLoStop, -1); dJointSetPistonParam(jId_12, dParamHiStop, 0.25); dJointAttach(fixed, bId1_12, 0); dJointSetFixed(fixed); dJointAttach(jId, 0, bId); dJointSetPistonParam(jId, dParamLoStop, -1); dJointSetPistonParam(jId, dParamHiStop, 0.25); for (int i=0; i<50; ++i) dWorldStep(wId, 1.0); const dReal *pos2_12 = dBodyGetPosition(bId2_12); const dReal *pos = dBodyGetPosition(bId); CHECK_CLOSE (pos2_12[0], pos[0], 1e-2); CHECK_CLOSE (pos2_12[1], pos[1], 1e-2); CHECK_CLOSE (pos2_12[2], pos[2], 1e-2); const dReal *q2_12 = dBodyGetQuaternion(bId2_12); const dReal *q = dBodyGetQuaternion(bId); CHECK_CLOSE (q2_12[0], q[0], 1e-4); CHECK_CLOSE (q2_12[1], q[1], 1e-4); CHECK_CLOSE (q2_12[2], q[2], 1e-4); CHECK_CLOSE (q2_12[3], q[3], 1e-4); } // This test compare the result of a slider with 2 bodies where body body 2 is // fixed to the world to a slider with only one body at position 1. // // Test the limits [0, 0] when only one body at is attached to the joint // using dJointAttache(jId, bId, 0); // // The body should not move since their is no room between the two limits // TEST_FIXTURE(Fixture_dxJointPiston_Compare_Body_At_Zero_Axis_Along_X, test_Limit_0_0_One_Body_on_left) { dBodyAddForce (bId1_12, 4, 0, 0); dJointAttach(jId_12, bId1_12, bId2_12); dJointSetPistonParam(jId_12, dParamLoStop, 0); dJointSetPistonParam(jId_12, dParamHiStop, 0); dJointAttach(fixed, 0, bId2_12); dJointSetFixed(fixed); dJointAttach(jId, bId, 0); dJointSetPistonParam(jId, dParamLoStop, 0); dJointSetPistonParam(jId, dParamHiStop, 0); for (int i=0; i<500; ++i) dWorldStep(wId, 1.0); const dReal *pos1_12 = dBodyGetPosition(bId1_12); const dReal *pos = dBodyGetPosition(bId); CHECK_CLOSE (pos1_12[0], pos[0], 1e-4); CHECK_CLOSE (pos1_12[1], pos[1], 1e-4); CHECK_CLOSE (pos1_12[2], pos[2], 1e-4); CHECK_CLOSE (0, pos[0], 1e-4); CHECK_CLOSE (0, pos[1], 1e-4); CHECK_CLOSE (0, pos[2], 1e-4); const dReal *q1_12 = dBodyGetQuaternion(bId1_12); const dReal *q = dBodyGetQuaternion(bId); CHECK_CLOSE (q1_12[0], q[0], 1e-4); CHECK_CLOSE (q1_12[1], q[1], 1e-4); CHECK_CLOSE (q1_12[2], q[2], 1e-4); CHECK_CLOSE (q1_12[3], q[3], 1e-4); } // This test compare the result of a slider with 2 bodies where body body 1 is // fixed to the world to a slider with only one body at position 2. // // Test the limits [0, 0] when only one body at is attached to the joint // using dJointAttache(jId, 0, bId); // // The body should not move since their is no room between the two limits // TEST_FIXTURE(Fixture_dxJointPiston_Compare_Body_At_Zero_Axis_Along_X, test_Limit_0_0_One_Body_on_right) { dBodyAddForce (bId2_12, 4, 0, 0); dJointAttach(jId_12, bId1_12, bId2_12); dJointSetPistonParam(jId_12, dParamLoStop, 0); dJointSetPistonParam(jId_12, dParamHiStop, 0); dJointAttach(fixed, bId1_12, 0); dJointSetFixed(fixed); dJointAttach(jId, 0, bId); dJointSetPistonParam(jId, dParamLoStop, 0); dJointSetPistonParam(jId, dParamHiStop, 0); for (int i=0; i<500; ++i) dWorldStep(wId, 1.0); const dReal *pos2_12 = dBodyGetPosition(bId2_12); const dReal *pos = dBodyGetPosition(bId); CHECK_CLOSE (pos2_12[0], pos[0], 1e-4); CHECK_CLOSE (pos2_12[1], pos[1], 1e-4); CHECK_CLOSE (pos2_12[2], pos[2], 1e-4); CHECK_CLOSE (0, pos[0], 1e-4); CHECK_CLOSE (0, pos[1], 1e-4); CHECK_CLOSE (0, pos[2], 1e-4); const dReal *q2_12 = dBodyGetQuaternion(bId2_12); const dReal *q = dBodyGetQuaternion(bId); CHECK_CLOSE (q2_12[0], q[0], 1e-4); CHECK_CLOSE (q2_12[1], q[1], 1e-4); CHECK_CLOSE (q2_12[2], q[2], 1e-4); CHECK_CLOSE (q2_12[3], q[3], 1e-4); } } // End of SUITE TestdxJointPiston ode-0.16/tests/joints/Makefile.am0000664000175200017520000000066113403272463013651 00000000000000AM_CPPFLAGS = -I$(srcdir)/../UnitTest++/src \ -I$(top_srcdir)/include \ -I$(top_builddir)/include \ -I$(top_srcdir)/ode/src check_LTLIBRARIES = libjoints.la libjoints_la_LDFLAGS = -static libjoints_la_SOURCES = \ amotor.cpp \ ball.cpp \ dball.cpp \ fixed.cpp \ hinge.cpp \ hinge2.cpp \ piston.cpp \ pr.cpp \ pu.cpp \ slider.cpp \ universal.cpp ode-0.16/tests/joints/ball.cpp0000664000175200017520000001247613403272463013242 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ //234567890123456789012345678901234567890123456789012345678901234567890123456789 // 1 2 3 4 5 6 7 //////////////////////////////////////////////////////////////////////////////// // This file create unit test for some of the functions found in: // ode/src/joinst/ball.cpp // // //////////////////////////////////////////////////////////////////////////////// #include #include #include "../../ode/src/config.h" #include "../../ode/src/joints/ball.h" using namespace std; SUITE (TestdxJointBall) { // The 2 bodies are positionned at (-1, -2, -3), and (11, 22, 33) // The bodis have rotation of 27deg around some axis. // The joint is a Ball Joint // Axis is along the X axis // Anchor at (0, 0, 0) struct dxJointBall_Fixture_B1_and_B2_At_Zero_Axis_Along_X { dxJointBall_Fixture_B1_and_B2_At_Zero_Axis_Along_X() { wId = dWorldCreate(); for (int j=0; j<2; ++j) { bId[j][0] = dBodyCreate (wId); dBodySetPosition (bId[j][0], -1, -2, -3); bId[j][1] = dBodyCreate (wId); dBodySetPosition (bId[j][1], 11, 22, 33); dMatrix3 R; dVector3 axis; // Random axis axis[0] = REAL(0.53); axis[1] = -REAL(0.71); axis[2] = REAL(0.43); dNormalize3(axis); dRFromAxisAndAngle (R, axis[0], axis[1], axis[2], REAL(0.47123)); // 27deg dBodySetRotation (bId[j][0], R); axis[0] = REAL(1.2); axis[1] = REAL(0.87); axis[2] = -REAL(0.33); dNormalize3(axis); dRFromAxisAndAngle (R, axis[0], axis[1], axis[2], REAL(0.47123)); // 27deg dBodySetRotation (bId[j][1], R); jId[j] = dJointCreateBall (wId, 0); dJointAttach (jId[j], bId[j][0], bId[j][1]); } } ~dxJointBall_Fixture_B1_and_B2_At_Zero_Axis_Along_X() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId[2][2]; dJointID jId[2]; }; // Rotate 2nd body 90deg around X then back to original position // // ^ ^ ^ // | | => | <--- // | | | // B1 B2 B1 B2 // // Start with a Delta of 90deg // ^ ^ ^ // | <--- => | | // | | | // B1 B2 B1 B2 TEST_FIXTURE (dxJointBall_Fixture_B1_and_B2_At_Zero_Axis_Along_X, test_dJointSetBallAxisOffset_B2_90deg) { dVector3 anchor; dJointGetBallAnchor(jId[1], anchor); dJointSetBallAnchor(jId[1], anchor[0], anchor[1], anchor[2]); for (int b=0; b<2; ++b) { // Compare body b of the first joint with its equivalent on the // second joint const dReal *qA = dBodyGetQuaternion(bId[0][b]); const dReal *qB = dBodyGetQuaternion(bId[1][b]); CHECK_CLOSE (qA[0], qB[0], 1e-4); CHECK_CLOSE (qA[1], qB[1], 1e-4); CHECK_CLOSE (qA[2], qB[2], 1e-4); CHECK_CLOSE (qA[3], qB[3], 1e-4); } dWorldStep (wId,0.5); dWorldStep (wId,0.5); dWorldStep (wId,0.5); dWorldStep (wId,0.5); for (int b=0; b<2; ++b) { // Compare body b of the first joint with its equivalent on the // second joint const dReal *qA = dBodyGetQuaternion(bId[0][b]); const dReal *qB = dBodyGetQuaternion(bId[1][b]); CHECK_CLOSE (qA[0], qB[0], 1e-4); CHECK_CLOSE (qA[1], qB[1], 1e-4); CHECK_CLOSE (qA[2], qB[2], 1e-4); CHECK_CLOSE (qA[3], qB[3], 1e-4); const dReal *posA = dBodyGetPosition(bId[0][b]); const dReal *posB = dBodyGetPosition(bId[1][b]); CHECK_CLOSE (posA[0], posB[0], 1e-4); CHECK_CLOSE (posA[1], posB[1], 1e-4); CHECK_CLOSE (posA[2], posB[2], 1e-4); CHECK_CLOSE (posA[3], posB[3], 1e-4); } } } // End of SUITE TestdxJointBall ode-0.16/tests/joints/universal.cpp0000664000175200017520000020255013403272463014332 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ //////////////////////////////////////////////////////////////////////////////// // This file create unit test for some of the functions found in: // ode/src/joinst/universal.cpp // // //////////////////////////////////////////////////////////////////////////////// #include #include #include #include "../../ode/src/config.h" #include "../../ode/src/joints/universal.h" dReal d2r(dReal degree) { return degree * (dReal)(M_PI / 180.0); } dReal r2d(dReal degree) { return degree * (dReal)(180.0/M_PI); } SUITE (TestdxJointUniversal) { // The 2 bodies are positionned at (0, 0, 0) // The bodis have no rotation. // The joint is a Universal Joint // Axis1 is along the X axis // Axis2 is along the Y axis // Anchor at (0, 0, 0) struct Fixture_dxJointUniversal_B1_and_B2_At_Zero_Axis1_Along_X_Axis2_Along_Y { Fixture_dxJointUniversal_B1_and_B2_At_Zero_Axis1_Along_X_Axis2_Along_Y() { wId = dWorldCreate(); bId1 = dBodyCreate (wId); dBodySetPosition (bId1, 0, 0, 0); bId2 = dBodyCreate (wId); dBodySetPosition (bId2, 0, 0, 0); jId = dJointCreateUniversal (wId, 0); joint = (dxJointUniversal*) jId; dJointAttach (jId, bId1, bId2); } ~Fixture_dxJointUniversal_B1_and_B2_At_Zero_Axis1_Along_X_Axis2_Along_Y() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId1; dBodyID bId2; dJointID jId; dxJointUniversal* joint; }; // The 2 bodies are positionned at (-1, -2, -3), and (11, 22, 33) // The bodis have rotation of 27deg around some axis. // The joint is a Universal Joint // Axis is along the X axis // Anchor at (0, 0, 0) struct Fixture_dxJointUniversal_B1_and_B2_At_Random_Axis_Along_X { Fixture_dxJointUniversal_B1_and_B2_At_Random_Axis_Along_X() { wId = dWorldCreate(); bId1 = dBodyCreate (wId); dBodySetPosition (bId1, -1, -2, -3); bId2 = dBodyCreate (wId); dBodySetPosition (bId2, 11, 22, 33); dMatrix3 R; dVector3 axis; axis[0] = REAL(0.53); axis[1] = -REAL(0.71); axis[2] = REAL(0.43); dNormalize3(axis); dRFromAxisAndAngle (R, axis[0], axis[1], axis[2], REAL(0.47123)); // 27deg dBodySetRotation (bId1, R); axis[0] = REAL(1.2); axis[1] = REAL(0.87); axis[2] = -REAL(0.33); dNormalize3(axis); dRFromAxisAndAngle (R, axis[0], axis[1], axis[2], REAL(0.47123)); // 27deg dBodySetRotation (bId2, R); jId = dJointCreateUniversal (wId, 0); joint = (dxJointUniversal*) jId; dJointAttach (jId, bId1, bId2); } ~Fixture_dxJointUniversal_B1_and_B2_At_Random_Axis_Along_X() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId1; dBodyID bId2; dJointID jId; dxJointUniversal* joint; }; // Only one body body1 at (0,0,0) // The joint is an Universal Joint. // Axis1 is along the X axis // Axis2 is along the Y axis // Anchor at (0, 0, 0) // // ^Y // | // | // | // | // | // Z <-- X struct Fixture_dxJointUniversal_B1_At_Zero_Default_Axes { Fixture_dxJointUniversal_B1_At_Zero_Default_Axes() { wId = dWorldCreate(); bId1 = dBodyCreate (wId); dBodySetPosition (bId1, 0, 0, 0); jId = dJointCreateUniversal (wId, 0); dJointAttach (jId, bId1, NULL); dJointSetUniversalAnchor (jId, 0, 0, 0); } ~Fixture_dxJointUniversal_B1_At_Zero_Default_Axes() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId1; dJointID jId; }; // Only one body body2 at (0,0,0) // The joint is an Universal Joint. // Axis1 is along the X axis. // Axis2 is along the Y axis. // Anchor at (0, 0, 0) // // ^Y // | // | // | // | // | // Z <-- X struct Fixture_dxJointUniversal_B2_At_Zero_Default_Axes { Fixture_dxJointUniversal_B2_At_Zero_Default_Axes() { wId = dWorldCreate(); bId2 = dBodyCreate (wId); dBodySetPosition (bId2, 0, 0, 0); jId = dJointCreateUniversal (wId, 0); dJointAttach (jId, NULL, bId2); dJointSetUniversalAnchor (jId, 0, 0, 0); } ~Fixture_dxJointUniversal_B2_At_Zero_Default_Axes() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId2; dJointID jId; }; // Test is dJointGetUniversalAngles versus // dJointGetUniversalAngle1 and dJointGetUniversalAngle2 dJointGetUniversalAxis TEST_FIXTURE (Fixture_dxJointUniversal_B1_and_B2_At_Zero_Axis1_Along_X_Axis2_Along_Y, test_dJointSetGetUniversalAngles_Versus_Angle1_and_Angle2) { CHECK_CLOSE (0, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (0, dJointGetUniversalAngle2 (jId), 1e-4); dReal angle1, angle2; dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (0, angle1, 1e-4); CHECK_CLOSE (0, angle2, 1e-4); dMatrix3 R; dReal ang1, ang2; dVector3 axis1; dJointGetUniversalAxis1 (jId, axis1); dVector3 axis2; dJointGetUniversalAxis2 (jId, axis2); ang1 = d2r(REAL(23.0)); dRFromAxisAndAngle (R, axis1[0], axis1[1], axis1[2], ang1); dBodySetRotation (bId1, R); ang2 = d2r(REAL(17.0)); dRFromAxisAndAngle (R, axis2[0], axis2[1], axis2[2], ang2); dBodySetRotation (bId2, R); CHECK_CLOSE (ang1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (-ang2, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (ang1, angle1, 1e-4); CHECK_CLOSE (-ang2, angle2, 1e-4); // ax1 and ax2 are pseudo-random axis. N.B. They are NOT the axis of the joints. dVector3 ax1; ax1[0] = REAL(0.2); ax1[1] = -REAL(0.67); ax1[2] = -REAL(0.81); dNormalize3(ax1); dVector3 ax2; ax2[0] = REAL(0.62); ax2[1] = REAL(0.31); ax2[2] = REAL(0.43); dNormalize3(ax2); ang1 = d2r(REAL(23.0)); dRFromAxisAndAngle (R, ax1[0], ax1[1], ax1[2], ang1); dBodySetRotation (bId1, R); ang2 = d2r(REAL(0.0)); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (angle1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (angle2, dJointGetUniversalAngle2 (jId), 1e-4); ang1 = d2r(REAL(0.0)); ang2 = d2r(REAL(23.0)); dRFromAxisAndAngle (R, ax2[0], ax2[1], ax2[2], ang2); dBodySetRotation (bId1, R); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (angle1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (angle2, dJointGetUniversalAngle2 (jId), 1e-4); ang1 = d2r(REAL(38.0)); dRFromAxisAndAngle (R, ax1[0], ax1[1], ax1[2], ang2); dBodySetRotation (bId1, R); ang2 = d2r(REAL(-43.0)); dRFromAxisAndAngle (R, ax2[0], ax2[1], ax2[2], ang2); dBodySetRotation (bId1, R); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (angle1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (angle2, dJointGetUniversalAngle2 (jId), 1e-4); // Try with random axis for the axis of the joints dRSetIdentity(R); dBodySetRotation (bId1, R); dBodySetRotation (bId1, R); axis1[0] = REAL(0.32); axis1[1] = -REAL(0.57); axis1[2] = REAL(0.71); dNormalize3(axis1); axis2[0] = -REAL(0.26); axis2[1] = -REAL(0.31); axis2[2] = REAL(0.69); dNormalize3(axis2); dVector3 cross; dCalcVectorCross3(cross, axis1, axis2); dJointSetUniversalAxis1(jId, axis1[0], axis1[1], axis1[2]); dJointSetUniversalAxis2(jId, cross[0], cross[1], cross[2]); ang1 = d2r(REAL(23.0)); dRFromAxisAndAngle (R, ax1[0], ax1[1], ax1[2], ang1); dBodySetRotation (bId1, R); ang2 = d2r(REAL(0.0)); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (angle1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (angle2, dJointGetUniversalAngle2 (jId), 1e-4); ang1 = d2r(REAL(0.0)); ang2 = d2r(REAL(23.0)); dRFromAxisAndAngle (R, ax2[0], ax2[1], ax2[2], ang2); dBodySetRotation (bId1, R); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (angle1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (angle2, dJointGetUniversalAngle2 (jId), 1e-4); ang1 = d2r(REAL(38.0)); dRFromAxisAndAngle (R, ax1[0], ax1[1], ax1[2], ang2); dBodySetRotation (bId1, R); ang2 = d2r(REAL(-43.0)); dRFromAxisAndAngle (R, ax2[0], ax2[1], ax2[2], ang2); dBodySetRotation (bId1, R); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (angle1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (angle2, dJointGetUniversalAngle2 (jId), 1e-4); } // ========================================================================= // Test ONE BODY behavior // ========================================================================= // Test when there is only one body at position one on the joint TEST_FIXTURE (Fixture_dxJointUniversal_B1_At_Zero_Default_Axes, test_dJointGetUniversalAngle1_1Body_B1) { CHECK_CLOSE (0, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (0, dJointGetUniversalAngle2 (jId), 1e-4); dReal angle1, angle2; dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (0, angle1, 1e-4); CHECK_CLOSE (0, angle2, 1e-4); dVector3 axis1; dJointGetUniversalAxis1 (jId, axis1); dVector3 axis2; dJointGetUniversalAxis2 (jId, axis2); dMatrix3 R; dReal ang1 = REAL(0.23); dRFromAxisAndAngle (R, axis1[0], axis1[1], axis1[2], ang1); dBodySetRotation (bId1, R); dReal ang2 = REAL(0.0); CHECK_CLOSE (ang1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (-ang2, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (ang1, angle1, 1e-4); CHECK_CLOSE (-ang2, angle2, 1e-4); dMatrix3 I; dRSetIdentity(I); // Set the rotation of the body to be the Identity (i.e. zero) dBodySetRotation (bId1, I); CHECK_CLOSE (0, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (0, dJointGetUniversalAngle2 (jId), 1e-4); // Test the same rotation, when axis1 is inverted dJointSetUniversalAxis1 (jId, -axis1[0], -axis1[1], -axis1[2]); dBodySetRotation (bId1, R); CHECK_CLOSE (-ang1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (-ang2, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (-ang1, angle1, 1e-4); CHECK_CLOSE (-ang2, angle2, 1e-4); // Test the same rotation, when axis1 is default and axis2 is inverted dBodySetRotation (bId1, I); dJointSetUniversalAxis1 (jId, axis1[0], axis1[1], axis1[2]); dJointSetUniversalAxis2 (jId, -axis2[0], -axis2[1], -axis2[2]); dBodySetRotation (bId1, R); CHECK_CLOSE (ang1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (ang2, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (ang1, angle1, 1e-4); CHECK_CLOSE (ang2, angle2, 1e-4); } // Test when there is only one body at position two on the joint TEST_FIXTURE (Fixture_dxJointUniversal_B2_At_Zero_Default_Axes, test_dJointGetUniversalAngle1_1Body_B2) { CHECK_CLOSE (0, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (0, dJointGetUniversalAngle2 (jId), 1e-4); dReal angle1, angle2; dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (0, angle1, 1e-4); CHECK_CLOSE (0, angle2, 1e-4); dVector3 axis1; dJointGetUniversalAxis1 (jId, axis1); dVector3 axis2; dJointGetUniversalAxis2 (jId, axis2); dMatrix3 R; dReal ang1 = REAL(0.0); dReal ang2 = REAL(0.23); dRFromAxisAndAngle (R, axis2[0], axis2[1], axis2[2], ang2); dBodySetRotation (bId2, R); CHECK_CLOSE (ang1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (-ang2, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (ang1, angle1, 1e-4); CHECK_CLOSE (-ang2, angle2, 1e-4); dMatrix3 I; dRSetIdentity(I); // Set the rotation of the body to be the Identity (i.e. zero) dBodySetRotation (bId2, I); CHECK_CLOSE (0, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (0, dJointGetUniversalAngle2 (jId), 1e-4); dJointSetUniversalAxis2 (jId, -axis2[0], -axis2[1], -axis2[2]); dBodySetRotation (bId2, R); CHECK_CLOSE (-ang1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (ang2, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (-ang1, angle1, 1e-4); CHECK_CLOSE (ang2, angle2, 1e-4); // Test the same rotation, when axis1 is inverted and axis2 is default dBodySetRotation (bId2, I); dJointSetUniversalAxis1 (jId, -axis1[0], -axis1[1], -axis1[2]); dJointSetUniversalAxis2 (jId, axis2[0], axis2[1], axis2[2]); dBodySetRotation (bId2, R); CHECK_CLOSE (ang1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (-ang2, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (ang1, angle1, 1e-4); CHECK_CLOSE (-ang2, angle2, 1e-4); } // ========================================================================= // // ========================================================================= // Test is dJointSetUniversalAxis and dJointGetUniversalAxis return same value TEST_FIXTURE (Fixture_dxJointUniversal_B1_and_B2_At_Random_Axis_Along_X, test_dJointSetGetUniversalAxis) { dVector3 axisOrig, axis; dJointGetUniversalAxis1 (jId, axisOrig); dJointGetUniversalAxis1 (jId, axis); dJointSetUniversalAxis1 (jId, axis[0], axis[1], axis[2]); dJointGetUniversalAxis1 (jId, axis); CHECK_CLOSE (axis[0], axisOrig[0] , 1e-4); CHECK_CLOSE (axis[1], axisOrig[1] , 1e-4); CHECK_CLOSE (axis[2], axisOrig[2] , 1e-4); dJointGetUniversalAxis2 (jId, axisOrig); dJointGetUniversalAxis2(jId, axis); dJointSetUniversalAxis2 (jId, axis[0], axis[1], axis[2]); dJointGetUniversalAxis2 (jId, axis); CHECK_CLOSE (axis[0], axisOrig[0] , 1e-4); CHECK_CLOSE (axis[1], axisOrig[1] , 1e-4); CHECK_CLOSE (axis[2], axisOrig[2] , 1e-4); dVector3 anchor1, anchor2, anchorOrig1, anchorOrig2; dJointGetUniversalAnchor (jId, anchorOrig1); dJointGetUniversalAnchor (jId, anchor1); dJointGetUniversalAnchor2 (jId, anchorOrig2); dJointGetUniversalAnchor2 (jId, anchor2); dJointSetUniversalAnchor (jId, anchor1[0], anchor1[1], anchor1[2]); dJointGetUniversalAnchor (jId, anchor1); dJointGetUniversalAnchor2 (jId, anchor2); CHECK_CLOSE (anchor1[0], anchorOrig1[0] , 1e-4); CHECK_CLOSE (anchor1[1], anchorOrig1[1] , 1e-4); CHECK_CLOSE (anchor1[2], anchorOrig1[2] , 1e-4); CHECK_CLOSE (anchor2[0], anchorOrig2[0] , 1e-4); CHECK_CLOSE (anchor2[1], anchorOrig2[1] , 1e-4); CHECK_CLOSE (anchor2[2], anchorOrig2[2] , 1e-4); } // Create 2 bodies attached by a Universal joint // Axis is along the X axis (Default value // Anchor at (0, 0, 0) (Default value) // // ^Y // | // * Body2 // | // | // Body1 | // * Z--------> struct dxJointUniversal_Test_Initialization { dxJointUniversal_Test_Initialization() { wId = dWorldCreate(); // Remove gravity to have the only force be the force of the joint dWorldSetGravity(wId, 0,0,0); for (int j=0; j<2; ++j) { bId[j][0] = dBodyCreate (wId); dBodySetPosition (bId[j][0], -1, -2, -3); bId[j][1] = dBodyCreate (wId); dBodySetPosition (bId[j][1], 11, 22, 33); dMatrix3 R; dVector3 axis; // Random axis axis[0] = REAL(0.53); axis[1] = -REAL(0.71); axis[2] = REAL(0.43); dNormalize3(axis); dRFromAxisAndAngle (R, axis[0], axis[1], axis[2], REAL(0.47123)); // 27deg dBodySetRotation (bId[j][0], R); axis[0] = REAL(1.2); axis[1] = REAL(0.87); axis[2] = -REAL(0.33); dNormalize3(axis); dRFromAxisAndAngle (R, axis[0], axis[1], axis[2], REAL(0.47123)); // 27deg dBodySetRotation (bId[j][1], R); jId[j] = dJointCreateUniversal (wId, 0); dJointAttach (jId[j], bId[j][0], bId[j][1]); dJointSetUniversalParam(jId[j], dParamLoStop, 1); dJointSetUniversalParam(jId[j], dParamHiStop, 2); dJointSetUniversalParam(jId[j], dParamFMax, 200); } } ~dxJointUniversal_Test_Initialization() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId[2][2]; dJointID jId[2]; }; // Test if setting a Universal with its default values // will behave the same as a default Universal joint TEST_FIXTURE (dxJointUniversal_Test_Initialization, test_Universal_Initialization) { using namespace std; dVector3 axis; dJointGetUniversalAxis1(jId[1], axis); dJointSetUniversalAxis1(jId[1], axis[0], axis[1], axis[2]); dJointGetUniversalAxis2(jId[1], axis); dJointSetUniversalAxis2(jId[1], axis[0], axis[1], axis[2]); dVector3 anchor; dJointGetUniversalAnchor(jId[1], anchor); dJointSetUniversalAnchor(jId[1], anchor[0], anchor[1], anchor[2]); for (int b=0; b<2; ++b) { // Compare body b of the first joint with its equivalent on the // second joint const dReal *qA = dBodyGetQuaternion(bId[0][b]); const dReal *qB = dBodyGetQuaternion(bId[1][b]); CHECK_CLOSE (qA[0], qB[0], 1e-4); CHECK_CLOSE (qA[1], qB[1], 1e-4); CHECK_CLOSE (qA[2], qB[2], 1e-4); CHECK_CLOSE (qA[3], qB[3], 1e-4); } dWorldStep (wId,0.5); dWorldStep (wId,0.5); dWorldStep (wId,0.5); dWorldStep (wId,0.5); for (int b=0; b<2; ++b) { // Compare body b of the first joint with its equivalent on the // second joint const dReal *qA = dBodyGetQuaternion(bId[0][b]); const dReal *qB = dBodyGetQuaternion(bId[1][b]); CHECK_CLOSE (qA[0], qB[0], 1e-4); CHECK_CLOSE (qA[1], qB[1], 1e-4); CHECK_CLOSE (qA[2], qB[2], 1e-4); CHECK_CLOSE (qA[3], qB[3], 1e-4); const dReal *posA = dBodyGetPosition(bId[0][b]); const dReal *posB = dBodyGetPosition(bId[1][b]); CHECK_CLOSE (posA[0], posB[0], 1e-4); CHECK_CLOSE (posA[1], posB[1], 1e-4); CHECK_CLOSE (posA[2], posB[2], 1e-4); CHECK_CLOSE (posA[3], posB[3], 1e-4); } } // ========================================================================== // Testing the offset // TODO: // - Test Axis1Offset(...., 0, ang2); // ========================================================================== // Rotate first body 90deg around X (Axis1) then back to original position // // ^ ^ ^ Z ^ // | | => <--- | | // | | | | // B1 B2 B1 B2 .----->Y // / // / // v X (N.B. X is going out of the screen) // // Set Axis1 with an Offset of 90deg // ^ ^ ^ // <--- | => | | // | | | // B1 B2 B1 B2 TEST_FIXTURE (Fixture_dxJointUniversal_B1_and_B2_At_Zero_Axis1_Along_X_Axis2_Along_Y, test_dJointSetUniversalAxis1Offset_B1_90deg) { dMatrix3 R; CHECK_CLOSE (0, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (0, dJointGetUniversalAngle2 (jId), 1e-4); dReal angle1, angle2; dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (0, angle1, 1e-4); CHECK_CLOSE (0, angle2, 1e-4); dVector3 axis; dJointGetUniversalAxis1 (jId, axis); dReal ang1 = d2r(REAL(90.0)); dReal ang2 = d2r(REAL(0.0)); dRFromAxisAndAngle (R, axis[0], axis[1], axis[2], ang1); dBodySetRotation (bId1, R); CHECK_CLOSE (ang1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (ang2, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (ang1, angle1, 1e-4); CHECK_CLOSE (ang2, angle2, 1e-4); dJointSetUniversalAxis1Offset (jId, axis[0], axis[1], axis[2], ang1, ang2); CHECK_CLOSE (ang1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (ang2, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (ang1, angle1, 1e-4); CHECK_CLOSE (ang2, angle2, 1e-4); dRSetIdentity(R); // Set the rotation of the body to be zero dBodySetRotation (bId1, R); CHECK_CLOSE (0, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (0, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (0, angle1, 1e-4); CHECK_CLOSE (0, angle2, 1e-4); } // Rotate 2nd body 90deg around (Axis2) then back to original position // Offset when setting axis1 // // ^ ^ ^ Z ^ // | | => <--- | | // | | | | // B1 B2 B1 B2 .----->Y // / // / // v X (N.B. X is going out of the screen) // // Set Axis1 with an Offset of 90deg // ^ ^ ^ // <--- | => | | // | | | // B1 B2 B1 B2 TEST_FIXTURE (Fixture_dxJointUniversal_B1_and_B2_At_Zero_Axis1_Along_X_Axis2_Along_Y, test_dJointSetUniversalAxis1Offset_B2_90deg) { dMatrix3 R; CHECK_CLOSE (0, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (0, dJointGetUniversalAngle2 (jId), 1e-4); dReal angle1, angle2; dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (0, angle1, 1e-4); CHECK_CLOSE (0, angle2, 1e-4); dVector3 ax1, ax2; dJointGetUniversalAxis1 (jId, ax1); dJointGetUniversalAxis2 (jId, ax2); dReal ang1 = d2r(REAL(0.0)); dReal ang2 = d2r(REAL(90.0)); dRFromAxisAndAngle (R, ax2[0], ax2[1], ax2[2], ang2); dBodySetRotation (bId2, R); CHECK_CLOSE (ang1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (-ang2, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (ang1, angle1, 1e-4); CHECK_CLOSE (-ang2, angle2, 1e-4); dJointSetUniversalAxis1Offset (jId, ax1[0], ax1[1], ax1[2], ang1, -ang2); CHECK_CLOSE (ang1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (-ang2, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (ang1, angle1, 1e-4); CHECK_CLOSE (-ang2, angle2, 1e-4); dRSetIdentity(R); // Set the rotation of the body to be zero dBodySetRotation (bId1, R); dBodySetRotation (bId2, R); CHECK_CLOSE (0, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (0, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (0, angle1, 1e-4); CHECK_CLOSE (0, angle2, 1e-4); } // Rotate second body 90deg around Y (Axis2) then back to original position // // ^ ^ ^ Z ^ // | | => | . | // | | | | // B1 B2 B1 B2 .----->Y // / // / // v X (N.B. X is going out of the screen) // // Set Axis2 with an Offset of 90deg // ^ ^ ^ // | . => | | // | | | // B1 B2 B1 B2 TEST_FIXTURE (Fixture_dxJointUniversal_B1_and_B2_At_Zero_Axis1_Along_X_Axis2_Along_Y, test_dJointSetUniversalAxisOffset_B2_90deg) { CHECK_CLOSE (0, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (0, dJointGetUniversalAngle2 (jId), 1e-4); dReal angle1, angle2; dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (0, angle1, 1e-4); CHECK_CLOSE (0, angle2, 1e-4); dVector3 axis; dJointGetUniversalAxis2 (jId, axis); dReal ang1 = d2r(REAL(0.0)); dReal ang2 = d2r(REAL(90.0)); dMatrix3 R; dRFromAxisAndAngle (R, axis[0], axis[1], axis[2], ang2); dBodySetRotation (bId2, R); CHECK_CLOSE (ang1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (-ang2, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (ang1, angle1, 1e-4); CHECK_CLOSE (-ang2, angle2, 1e-4); dJointSetUniversalAxis2Offset (jId, axis[0], axis[1], axis[2], ang1, -ang2); CHECK_CLOSE (ang1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (-ang2, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (ang1, angle1, 1e-4); CHECK_CLOSE (-ang2, angle2, 1e-4); dRSetIdentity(R); // Set the rotation of the body to be zero dBodySetRotation (bId2, R); CHECK_CLOSE (0, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (0, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (0, angle1, 1e-4); CHECK_CLOSE (0, angle2, 1e-4); } // Rotate 2nd body -90deg around Y (Axis2) then back to original position // // ^ ^ ^ Z ^ // | | => | x | // | | | | // B1 B2 B1 B2 X .----> Y // N.B. X is going out of the screen // Start with a Delta of 90deg // ^ ^ ^ // | x => | | // | | | // B1 B2 B1 B2 TEST_FIXTURE (Fixture_dxJointUniversal_B1_and_B2_At_Zero_Axis1_Along_X_Axis2_Along_Y, test_dJointSetUniversalAxisOffset_B2_Minus90deg) { CHECK_CLOSE (dJointGetUniversalAngle1 (jId), 0, 1e-4); CHECK_CLOSE (dJointGetUniversalAngle2 (jId), 0, 1e-4); dReal angle1, angle2; dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (0, angle1, 1e-4); CHECK_CLOSE (0, angle2, 1e-4); dVector3 axis; dJointGetUniversalAxis2 (jId, axis); dReal ang1 = d2r(REAL(0.0)); dReal ang2 = d2r(REAL(90.0)); dMatrix3 R; dRFromAxisAndAngle (R, axis[0], axis[1], axis[2], -ang2); dBodySetRotation (bId2, R); CHECK_CLOSE (ang1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (ang2, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (ang1, angle1, 1e-4); CHECK_CLOSE (ang2, angle2, 1e-4); dJointSetUniversalAxis2Offset (jId, axis[0], axis[1], axis[2], ang1, ang2); CHECK_CLOSE (ang1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (ang2, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (ang1, angle1, 1e-4); CHECK_CLOSE (ang2, angle2, 1e-4); dRFromAxisAndAngle (R, axis[0], axis[1], axis[2], 0); dBodySetRotation (bId2, R); CHECK_CLOSE (0, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (0, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (0, angle1, 1e-4); CHECK_CLOSE (0, angle2, 1e-4); } // Rotate 1st body 0.23rad around X (Axis1) then back to original position // // ^ ^ ^ ^ Z ^ // | | => \ | | // | | \ | | // B1 B2 B1 B2 .-------> Y // / // / // v X (N.B. X is going out of the screen) // // Start with a Delta of 0.23rad // ^ ^ ^ ^ // \ | => | | // \ | | | // B1 B2 B1 B2 TEST_FIXTURE (Fixture_dxJointUniversal_B1_and_B2_At_Zero_Axis1_Along_X_Axis2_Along_Y, test_dJointSetUniversalAxis1Offset_B1_0_23rad) { CHECK_CLOSE (0, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (0, dJointGetUniversalAngle2 (jId), 1e-4); dReal angle1, angle2; dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (0, angle1, 1e-4); CHECK_CLOSE (0, angle2, 1e-4); dVector3 axis; dJointGetUniversalAxis1 (jId, axis); dReal ang1 = REAL(0.23); dReal ang2 = REAL(0.0); dMatrix3 R; dRFromAxisAndAngle (R, axis[0], axis[1], axis[2], ang1); dBodySetRotation (bId1, R); CHECK_CLOSE (ang1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (ang2, dJointGetUniversalAngle2 (jId), 1e-4); dJointSetUniversalAxis1Offset (jId, axis[0], axis[1], axis[2], ang1, ang2); CHECK_CLOSE (ang1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (ang2, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (ang1, angle1, 1e-4); CHECK_CLOSE (ang2, angle2, 1e-4); dRSetIdentity(R); // Set the rotation of the body to be zero dBodySetRotation (bId1, R); CHECK_CLOSE (0, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (0, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (0, angle1, 1e-4); CHECK_CLOSE (0, angle2, 1e-4); } // Rotate 2nd body 0.23rad around Y (Axis2) then back to original position // // ^ ^ ^ ^ Z ^ ^ Y (N.B. Y is going in the screen) // | | => | / | / // | | | / | / // B1 B2 B1 B2 .-------> X // // Start with a Delta of 0.23rad // ^ ^ ^ ^ // | / => | | // | / | | // B1 B2 B1 B2 TEST_FIXTURE (Fixture_dxJointUniversal_B1_and_B2_At_Zero_Axis1_Along_X_Axis2_Along_Y, test_dJointSetUniversalAxisOffset_B2_0_23rad) { CHECK_CLOSE (0, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (0, dJointGetUniversalAngle2 (jId), 1e-4); dReal angle1, angle2; dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (0, angle1, 1e-4); CHECK_CLOSE (0, angle2, 1e-4); dVector3 axis; dJointGetUniversalAxis2 (jId, axis); dReal ang1 = REAL(0.0); dReal ang2 = REAL(0.23); dMatrix3 R; dRFromAxisAndAngle (R, axis[0], axis[1], axis[2], ang2); dBodySetRotation (bId2, R); CHECK_CLOSE (ang1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (-ang2, dJointGetUniversalAngle2 (jId), 1e-4); dJointSetUniversalAxis2Offset (jId, axis[0], axis[1], axis[2], ang1, -ang2); CHECK_CLOSE (ang1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (-ang2, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (ang1, angle1, 1e-4); CHECK_CLOSE (-ang2, angle2, 1e-4); dRSetIdentity(R); // Set the rotation of the body to be zero dBodySetRotation (bId2, R); CHECK_CLOSE (0, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (0, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (0, angle1, 1e-4); CHECK_CLOSE (0, angle2, 1e-4); } // Rotate 1st body 0.23rad around X axis and 2nd body 0.37rad around Y (Axis2) // then back to their original position. // The Axis offset are set one at a time // // ^ ^ ^ ^ Z ^ ^ Y (N.B. Y is going in the screen) // | | => \ / | / // | | \ / | / // B1 B2 B1 B2 .-------> X // // Start with a Delta of 0.23rad // ^ ^ ^ ^ // \ / => | | // \ / | | // B1 B2 B1 B2 TEST_FIXTURE (Fixture_dxJointUniversal_B1_and_B2_At_Zero_Axis1_Along_X_Axis2_Along_Y, test_dJointSetUniversalAxisOffset_B1_0_23rad_B2_0_37rad_One_by_One) { CHECK_CLOSE (0, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (0, dJointGetUniversalAngle2 (jId), 1e-4); dReal angle1, angle2; dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (0, angle1, 1e-4); CHECK_CLOSE (0, angle2, 1e-4); dVector3 axis1; dJointGetUniversalAxis1 (jId, axis1); dVector3 axis2; dJointGetUniversalAxis2 (jId, axis2); dMatrix3 R; dReal ang1 = REAL(0.23); dRFromAxisAndAngle (R, axis1[0], axis1[1], axis1[2], ang1); dBodySetRotation (bId1, R); dReal ang2 = REAL(0.37); dRFromAxisAndAngle (R, axis2[0], axis2[1], axis2[2], ang2); dBodySetRotation (bId2, R); CHECK_CLOSE (ang1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (-ang2, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (ang1, angle1, 1e-4); CHECK_CLOSE (-ang2, angle2, 1e-4); dJointSetUniversalAxis1Offset (jId, axis1[0], axis1[1], axis1[2], ang1, -ang2 ); CHECK_CLOSE (ang1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (-ang2, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (ang1, angle1, 1e-4); CHECK_CLOSE (-ang2, angle2, 1e-4); dJointGetUniversalAxis1 (jId, axis1); dJointGetUniversalAxis2 (jId, axis2); dRFromAxisAndAngle (R, axis2[0], axis2[1], axis2[2], ang2); dBodySetRotation (bId2, R); dJointSetUniversalAxis2Offset (jId, axis2[0], axis2[1], axis2[2], ang1, -ang2); CHECK_CLOSE (ang1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (-ang2, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (ang1, angle1, 1e-4); CHECK_CLOSE (-ang2, angle2, 1e-4); dRSetIdentity(R); // Set the rotation of the body to be zero dBodySetRotation (bId1, R); dBodySetRotation (bId2, R); CHECK_CLOSE (0, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (0, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (0, angle1, 1e-4); CHECK_CLOSE (0, angle2, 1e-4); } // The 2 bodies are positionned at (0, 0, 0), with no rotation // The joint is an Universal Joint. // Axis in the inverse direction of the X axis // Anchor at (0, 0, 0) // ^Y // | // | // | // | // | // Z <---- x (X going out of the page) struct Fixture_dxJointUniversal_B1_and_B2_At_Zero_Axis1_Inverse_of_X { Fixture_dxJointUniversal_B1_and_B2_At_Zero_Axis1_Inverse_of_X() { wId = dWorldCreate(); bId1 = dBodyCreate (wId); dBodySetPosition (bId1, 0, 0, 0); bId2 = dBodyCreate (wId); dBodySetPosition (bId2, 0, 0, 0); jId = dJointCreateUniversal (wId, 0); joint = (dxJointUniversal*) jId; dJointAttach (jId, bId1, bId2); dJointSetUniversalAnchor (jId, 0, 0, 0); axis[0] = -1; axis[1] = 0; axis[2] = 0; dJointSetUniversalAxis1(jId, axis[0], axis[1], axis[2]); } ~Fixture_dxJointUniversal_B1_and_B2_At_Zero_Axis1_Inverse_of_X() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId1; dBodyID bId2; dJointID jId; dxJointUniversal* joint; dVector3 axis; }; // No offset when setting the Axis1 offset // x is a Symbol for lines pointing into the screen // . is a Symbol for lines pointing out of the screen // // In 2D In 3D // ^ ^ ^ ^ Z ^ ^ Y // | | => | | | / // | | | | | / // B1 B2 B1 B2 .-------> X <-- Axis1 // // Start with a Delta of 90deg // ^ ^ ^ ^ // | | => | | // | | | | // B1 B2 B1 B2 TEST_FIXTURE (Fixture_dxJointUniversal_B1_and_B2_At_Zero_Axis1_Inverse_of_X, test_dJointSetUniversalAxis1Offset_No_Offset_Axis1_Inverse_of_X) { CHECK_CLOSE (dJointGetUniversalAngle1 (jId), 0, 1e-4); CHECK_CLOSE (dJointGetUniversalAngle2 (jId), 0, 1e-4); dReal angle1, angle2; dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (0, angle1, 1e-4); CHECK_CLOSE (0, angle2, 1e-4); dVector3 axis; dJointGetUniversalAxis1 (jId, axis); dReal ang1 = REAL(0.0); dReal ang2 = REAL(0.0); dMatrix3 R; dRFromAxisAndAngle (R, axis[0], axis[1], axis[2], ang1); dBodySetRotation (bId1, R); CHECK_CLOSE (ang1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (ang2, dJointGetUniversalAngle2 (jId), 1e-4); dJointSetUniversalAxis1Offset (jId, axis[0], axis[1], axis[2], ang1, ang2); CHECK_CLOSE (ang1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (ang2, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (ang1, angle1, 1e-4); CHECK_CLOSE (ang2, angle2, 1e-4); dRSetIdentity(R); // Set the rotation of the body to be zero dBodySetRotation (bId1, R); CHECK_CLOSE (0, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (0, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (0, angle1, 1e-4); CHECK_CLOSE (0, angle2, 1e-4); } // Rotate 1st body 90deg around axis1 then back to original position // x is a Symbol for lines pointing into the screen // . is a Symbol for lines pointing out of the screen // // In 2D In 3D // ^ ^ ^ Z ^ ^ Y // | | => x | | / // | | | | / // B1 B2 B1 B2 .-------> X <-- Axis1 // // Start with a Delta of 90deg // ^ ^ ^ // x | => | | // | | | // B1 B2 B1 B2 TEST_FIXTURE (Fixture_dxJointUniversal_B1_and_B2_At_Zero_Axis1_Inverse_of_X, test_dJointSetUniversalAxis1Offset_B1_90Deg_Axis1_Inverse_of_X) { CHECK_CLOSE (dJointGetUniversalAngle1 (jId), 0, 1e-4); CHECK_CLOSE (dJointGetUniversalAngle2 (jId), 0, 1e-4); dReal angle1, angle2; dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (0, angle1, 1e-4); CHECK_CLOSE (0, angle2, 1e-4); dVector3 axis; dJointGetUniversalAxis1 (jId, axis); dReal ang1 = d2r(90); dReal ang2 = REAL(0.0); dMatrix3 R; dRFromAxisAndAngle (R, axis[0], axis[1], axis[2], ang1); dBodySetRotation (bId1, R); CHECK_CLOSE (ang1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (ang2, dJointGetUniversalAngle2 (jId), 1e-4); dJointSetUniversalAxis1Offset (jId, axis[0], axis[1], axis[2], ang1, ang2); CHECK_CLOSE (ang1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (ang2, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (ang1, angle1, 1e-4); CHECK_CLOSE (ang2, angle2, 1e-4); dRSetIdentity(R); // Set the rotation of the body to be zero dBodySetRotation (bId1, R); CHECK_CLOSE (0, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (0, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (0, angle1, 1e-4); CHECK_CLOSE (0, angle2, 1e-4); } // No offset when setting the Axis 2 offset // x is a Symbol for lines pointing into the screen // . is a Symbol for lines pointing out of the screen // // In 2D In 3D // ^ ^ ^ ^ Z ^ ^ Y ^ Axis2 // | | => | | | / / // | | | | | / / // B1 B2 B1 B2 . -------> <-- Axis1 // // Start with a Delta of 90deg // ^ ^ ^ ^ // | | => | | // | | | | // B1 B2 B1 B2 TEST_FIXTURE (Fixture_dxJointUniversal_B1_and_B2_At_Zero_Axis1_Inverse_of_X, test_dJointSetUniversalAxis2Offset_No_Offset_Axis2_Inverse_of_X) { CHECK_CLOSE (dJointGetUniversalAngle1 (jId), 0, 1e-4); CHECK_CLOSE (dJointGetUniversalAngle2 (jId), 0, 1e-4); dReal angle1, angle2; dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (0, angle1, 1e-4); CHECK_CLOSE (0, angle2, 1e-4); dVector3 axis; dJointGetUniversalAxis2 (jId, axis); dReal ang1 = d2r(REAL(0.0)); dReal ang2 = d2r(REAL(0.0)); dMatrix3 R; dRFromAxisAndAngle (R, axis[0], axis[1], axis[2], ang2); dBodySetRotation (bId2, R); CHECK_CLOSE (ang1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (-ang2, dJointGetUniversalAngle2 (jId), 1e-4); dJointSetUniversalAxis2Offset (jId, axis[0], axis[1], axis[2], ang1, -ang2); CHECK_CLOSE (ang1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (-ang2, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (ang1, angle1, 1e-4); CHECK_CLOSE (-ang2, angle2, 1e-4); dRSetIdentity(R); // Set the rotation of the body to be zero dBodySetRotation (bId2, R); CHECK_CLOSE (0, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (0, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (0, angle1, 1e-4); CHECK_CLOSE (0, angle2, 1e-4); } // Rotate 2nd body 90deg around axis2 then back to original position // // In 2D In 3D // ^ ^ ^ Z ^ ^ Y ^ Axis2 // | | => | --> | / / // | | | | / / // B1 B2 B1 B2 . -------> <-- Axis1 // // Start with a Delta of 90deg // ^ ^ ^ // | <--- => | | // | | | // B1 B2 B1 B2 TEST_FIXTURE (Fixture_dxJointUniversal_B1_and_B2_At_Zero_Axis1_Inverse_of_X, test_dJointSetUniversalAxisOffset_B2_90Deg) { CHECK_CLOSE (dJointGetUniversalAngle1 (jId), 0, 1e-4); CHECK_CLOSE (dJointGetUniversalAngle2 (jId), 0, 1e-4); dReal angle1, angle2; dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (0, angle1, 1e-4); CHECK_CLOSE (0, angle2, 1e-4); dVector3 axis; dJointGetUniversalAxis2 (jId, axis); dReal ang1 = d2r(REAL(0.0)); dReal ang2 = d2r(REAL(90.0)); dMatrix3 R; dRFromAxisAndAngle (R, axis[0], axis[1], axis[2], ang2); dBodySetRotation (bId2, R); CHECK_CLOSE (0, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (-ang2, dJointGetUniversalAngle2 (jId), 1e-4); dJointSetUniversalAxis2Offset (jId, axis[0], axis[1], axis[2], ang1, -ang2); CHECK_CLOSE (ang1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (-ang2, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (ang1, angle1, 1e-4); CHECK_CLOSE (-ang2, angle2, 1e-4); dRSetIdentity(R); // Set the rotation of the body to be zero dBodySetRotation (bId2, R); CHECK_CLOSE (0, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (0, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (0, angle1, 1e-4); CHECK_CLOSE (0, angle2, 1e-4); } // Rotate 2nd body -90deg around axis2 then back to original position // // ^ ^ ^ // | | => | ---> // | | | // B1 B2 B1 B2 // // Start with a Delta of 90deg // ^ ^ ^ // | ---> => | | // | | | // B1 B2 B1 B2 TEST_FIXTURE (Fixture_dxJointUniversal_B1_and_B2_At_Zero_Axis1_Inverse_of_X, test_dJointSetUniversalAxis1Offset_B2_Minus90Deg) { CHECK_CLOSE (dJointGetUniversalAngle1 (jId), 0, 1e-4); CHECK_CLOSE (dJointGetUniversalAngle2 (jId), 0, 1e-4); dReal angle1, angle2; dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (0, angle1, 1e-4); CHECK_CLOSE (0, angle2, 1e-4); dVector3 axis; dJointGetUniversalAxis2 (jId, axis); dReal ang1 = d2r(0.0); dReal ang2 = d2r(REAL(-90.0)); dMatrix3 R; dRFromAxisAndAngle (R, axis[0], axis[1], axis[2], ang2); dBodySetRotation (bId2, R); CHECK_CLOSE (ang1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (-ang2, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (ang1, angle1, 1e-4); CHECK_CLOSE (-ang2, angle2, 1e-4); dJointGetUniversalAxis1 (jId, axis); dJointSetUniversalAxis1Offset (jId, axis[0], axis[1], axis[2], ang1, -ang2); CHECK_CLOSE (ang1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (-ang2, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (ang1, angle1, 1e-4); CHECK_CLOSE (-ang2, angle2, 1e-4); dRSetIdentity(R); // Set the rotation of the body to be zero dBodySetRotation (bId2, R); CHECK_CLOSE (0, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (0, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (0, angle1, 1e-4); CHECK_CLOSE (0, angle2, 1e-4); } // Rotate 1st body 0.23rad around X then back to original position // // ^ ^ ^ ^ // | | => \ | // | | \ | // B1 B2 B1 B2 // // Start with a Delta of 0.23rad // ^ ^ ^ ^ // \ | => | | // \ | | | // B1 B2 B1 B2 TEST_FIXTURE (Fixture_dxJointUniversal_B1_and_B2_At_Zero_Axis1_Inverse_of_X, test_dJointSetUniversalAxis1Offset_B1_0_23rad) { CHECK_CLOSE (0, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (0, dJointGetUniversalAngle2 (jId), 1e-4); dReal angle1, angle2; dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (0, angle1, 1e-4); CHECK_CLOSE (0, angle2, 1e-4); dVector3 axis; dJointGetUniversalAxis1 (jId, axis); dReal ang1 = REAL(0.23); dReal ang2 = REAL(0.0); dMatrix3 R; dRFromAxisAndAngle (R, axis[0], axis[1], axis[2], ang1); dBodySetRotation (bId1, R); CHECK_CLOSE (ang1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (-ang2, dJointGetUniversalAngle2 (jId), 1e-4); dJointSetUniversalAxis1Offset (jId, axis[0], axis[1], axis[2], ang1, ang2); CHECK_CLOSE (ang1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (-ang2, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (ang1, angle1, 1e-4); CHECK_CLOSE (-ang2, angle2, 1e-4); dRSetIdentity(R); // Set the rotation of the body to be zero dBodySetRotation (bId1, R); CHECK_CLOSE (0, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (0, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (0, angle1, 1e-4); CHECK_CLOSE (0, angle2, 1e-4); } // Rotate 2nd body -0.23rad around Z then back to original position // // ^ ^ ^ ^ // | | => / | // | | / | // B1 B2 B1 B2 // // Start with a Delta of 0.23rad // ^ ^ ^ ^ // / | => | | // / | | | // B1 B2 B1 B2 TEST_FIXTURE (Fixture_dxJointUniversal_B1_and_B2_At_Zero_Axis1_Inverse_of_X, test_dJointSetUniversalAxisOffset_B1_Minus0_23rad) { CHECK_CLOSE (dJointGetUniversalAngle1 (jId), 0, 1e-4); dMatrix3 R; dRFromAxisAndAngle (R, 1, 0, 0, -REAL(0.23)); dBodySetRotation (bId1, R); CHECK_CLOSE (REAL(0.23), dJointGetUniversalAngle1 (jId), 1e-4); dVector3 axis; dJointGetUniversalAxis1 (jId, axis); dJointSetUniversalAxis1Offset (jId, axis[0], axis[1], axis[2], REAL(0.23), 0); CHECK_CLOSE (REAL(0.23), dJointGetUniversalAngle1 (jId), 1e-4); dRFromAxisAndAngle (R, 1, 0, 0, 0); dBodySetRotation (bId1, R); CHECK_CLOSE (0, dJointGetUniversalAngle1 (jId), 1e-4); } // Rotate the body by 90deg around X then back to original position. // The body is attached at the second position of the joint: // dJointAttache(jId, 0, bId); // // ^ // | => <--- // | // B1 B1 // // Start with a Delta of 90deg // ^ // <--- => | // | // B1 B1 TEST_FIXTURE (Fixture_dxJointUniversal_B1_At_Zero_Default_Axes, test_dJointSetUniversalAxisOffset_1Body_B1_90Deg) { CHECK_CLOSE (dJointGetUniversalAngle1 (jId), 0, 1e-4); dMatrix3 R; dRFromAxisAndAngle (R, 1, 0, 0, M_PI/2.0); dBodySetRotation (bId1, R); CHECK_CLOSE (M_PI/2.0, dJointGetUniversalAngle1 (jId), 1e-4); dVector3 axis; dJointGetUniversalAxis1 (jId, axis); dJointSetUniversalAxis1Offset (jId, axis[0], axis[1], axis[2], M_PI/2.0, 0); CHECK_CLOSE (M_PI/2.0, dJointGetUniversalAngle1 (jId), 1e-4); dRFromAxisAndAngle (R, 1, 0, 0, 0); dBodySetRotation (bId1, R); CHECK_CLOSE (0, dJointGetUniversalAngle1 (jId), 1e-4); } // Rotate the body by -0.23rad around X then back to original position. // The body is attached at the second position of the joint: // dJointAttache(jId, 0, bId); // // ^ ^ // | => / // | / // B1 B1 // // Start with a Delta of -0.23rad // ^ ^ // / => | // / | // B1 B1 TEST_FIXTURE (Fixture_dxJointUniversal_B1_At_Zero_Default_Axes, test_dJointSetUniversalAxisOffset_1Body_B1_Minus0_23rad) { CHECK_CLOSE (dJointGetUniversalAngle1 (jId), 0, 1e-4); dMatrix3 R; dRFromAxisAndAngle (R, 1, 0, 0, -REAL(0.23)); dBodySetRotation (bId1, R); CHECK_CLOSE (-REAL(0.23), dJointGetUniversalAngle1 (jId), 1e-4); dVector3 axis; dJointGetUniversalAxis1 (jId, axis); dJointSetUniversalAxis1Offset (jId, axis[0], axis[1], axis[2], -REAL(0.23), 0); CHECK_CLOSE (-REAL(0.23), dJointGetUniversalAngle1 (jId), 1e-4); dRFromAxisAndAngle (R, 1, 0, 0, 0); dBodySetRotation (bId1, R); CHECK_CLOSE (0, dJointGetUniversalAngle1 (jId), 1e-4); } // Only one body body1 at (0,0,0) // The joint is an Universal Joint. // Axis the inverse of the X axis // Anchor at (0, 0, 0) // // ^Y // | // | // | // | // | // Z <-- X struct Fixture_dxJointUniversal_B1_At_Zero_Axis_Inverse_of_X { Fixture_dxJointUniversal_B1_At_Zero_Axis_Inverse_of_X() { wId = dWorldCreate(); bId1 = dBodyCreate (wId); dBodySetPosition (bId1, 0, 0, 0); jId = dJointCreateUniversal (wId, 0); joint = (dxJointUniversal*) jId; dJointAttach (jId, bId1, NULL); dJointSetUniversalAnchor (jId, 0, 0, 0); axis[0] = -1; axis[1] = 0; axis[2] = 0; dJointSetUniversalAxis1(jId, axis[0], axis[1], axis[2]); } ~Fixture_dxJointUniversal_B1_At_Zero_Axis_Inverse_of_X() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId1; dJointID jId; dxJointUniversal* joint; dVector3 axis; }; // Rotate B1 by 90deg around X then back to original position // // ^ // | => <--- // | // B1 B1 // // Start with a Delta of 90deg // ^ // <--- => | // | // B1 B1 TEST_FIXTURE (Fixture_dxJointUniversal_B1_At_Zero_Axis_Inverse_of_X, test_dJointSetUniversalAxisOffset_1Body_B1_90Deg) { CHECK_CLOSE (0, dJointGetUniversalAngle1 (jId), 1e-4); dVector3 axis; dJointGetUniversalAxis1(jId, axis); dReal ang1 = d2r(REAL(90.0)); dMatrix3 R; dRFromAxisAndAngle (R, axis[0], axis[1], axis[2], ang1); dBodySetRotation (bId1, R); CHECK_CLOSE (ang1, dJointGetUniversalAngle1 (jId), 1e-4); dJointSetUniversalAxis1Offset (jId, axis[0], axis[1], axis[2], ang1, 0); CHECK_CLOSE (ang1, dJointGetUniversalAngle1 (jId), 1e-4); dRSetIdentity(R); // Set the rotation of the body to be zero dBodySetRotation (bId1, R); CHECK_CLOSE (0, dJointGetUniversalAngle1 (jId), 1e-4); } // Rotate B1 by -0.23rad around X then back to original position // // ^ ^ // | => / // | / // B1 B1 // // Start with a Delta of -0.23rad // ^ ^ // / => | // / | // B1 B1 TEST_FIXTURE (Fixture_dxJointUniversal_B1_At_Zero_Axis_Inverse_of_X, test_dJointSetUniversalAxisOffset_1Body_B1_Minus0_23rad) { CHECK_CLOSE (dJointGetUniversalAngle1 (jId), 0, 1e-4); dMatrix3 R; dRFromAxisAndAngle (R, 1, 0, 0, -REAL(0.23)); dBodySetRotation (bId1, R); CHECK_CLOSE (REAL(0.23), dJointGetUniversalAngle1 (jId), 1e-4); dVector3 axis; dJointGetUniversalAxis1 (jId, axis); dJointSetUniversalAxis1Offset (jId, axis[0], axis[1], axis[2], REAL(0.23), 0); CHECK_CLOSE (REAL(0.23), dJointGetUniversalAngle1 (jId), 1e-4); dRFromAxisAndAngle (R, 1, 0, 0, 0); dBodySetRotation (bId1, R); CHECK_CLOSE (0, dJointGetUniversalAngle1 (jId), 1e-4); } // Rotate B2 by 90deg around X then back to original position // // ^ // | => <--- // | // B2 B2 // // Start with a Delta of 90deg // ^ // <--- => | // | // B2 B2 TEST_FIXTURE (Fixture_dxJointUniversal_B2_At_Zero_Default_Axes, test_dJointSetUniversalAxisOffset_1Body_B2_90Deg) { CHECK_CLOSE (0, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (0, dJointGetUniversalAngle2 (jId), 1e-4); dVector3 axis; dJointGetUniversalAxis2 (jId, axis); dReal ang2 = d2r(REAL(90.0)); dMatrix3 R; dRFromAxisAndAngle (R, axis[0], axis[1], axis[2], ang2); dBodySetRotation (bId2, R); CHECK_CLOSE (-ang2, dJointGetUniversalAngle2 (jId), 1e-4); dJointSetUniversalAxis2Offset (jId, axis[0], axis[1], axis[2], 0, -ang2); CHECK_CLOSE (0, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (-ang2, dJointGetUniversalAngle2 (jId), 1e-4); dRSetIdentity(R); // Set the rotation of the body to be zero dBodySetRotation (bId2, R); CHECK_CLOSE (0, dJointGetUniversalAngle2 (jId), 1e-4); } // Rotate B2 by -0.23rad around Y then back to original position // // ^ ^ // | => / // | / // B2 B2 // // Start with an offset of -0.23rad // ^ ^ // / => | // / | // B2 B2 TEST_FIXTURE (Fixture_dxJointUniversal_B2_At_Zero_Default_Axes, test_dJointSetUniversalAxis2Offset_1Body_B2_Minus0_23rad) { CHECK_CLOSE (0, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (0, dJointGetUniversalAngle2 (jId), 1e-4); dReal angle1, angle2; dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (0, angle1, 1e-4); CHECK_CLOSE (0, angle2, 1e-4); dVector3 axis; dJointGetUniversalAxis2 (jId, axis); dReal ang1 = 0; dReal ang2 = REAL(-0.23); dMatrix3 R; dRFromAxisAndAngle (R, axis[0], axis[1], axis[2], ang2); dBodySetRotation (bId2, R); CHECK_CLOSE (ang1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (-ang2, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (ang1, angle1, 1e-4); CHECK_CLOSE (-ang2, angle2, 1e-4); dJointSetUniversalAxis2Offset (jId, axis[0], axis[1], axis[2], ang1, -ang2); CHECK_CLOSE (ang1, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (-ang2, dJointGetUniversalAngle2 (jId), 1e-4); dRSetIdentity(R); // Set the rotation of the body to be zero dBodySetRotation (bId2, R); CHECK_CLOSE (0, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (0, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (0, angle1, 1e-4); CHECK_CLOSE (0, angle2, 1e-4); } // The 2 bodies are positionned at (0,0,0), and (0,0,0) // The bodis have no rotation. // The joint is a Universal Joint // The axis of the joint are at random (Still at 90deg w.r.t each other) // Anchor at (0, 0, 0) struct Fixture_dxJointUniversal_B1_and_B2_Axis_Random { Fixture_dxJointUniversal_B1_and_B2_Axis_Random() { wId = dWorldCreate(); bId1 = dBodyCreate (wId); dBodySetPosition (bId1, -1, -2, -3); bId2 = dBodyCreate (wId); dBodySetPosition (bId2, 11, 22, 33); jId = dJointCreateUniversal (wId, 0); dJointAttach (jId, bId1, bId2); dVector3 axis1; axis1[0] = REAL(0.53); axis1[1] = -REAL(0.71); axis1[2] = REAL(0.43); dNormalize3(axis1); dVector3 axis; axis[0] = REAL(1.2); axis[1] = REAL(0.87); axis[2] = -REAL(0.33); dVector3 axis2; dCalcVectorCross3(axis2, axis1, axis); dJointSetUniversalAxis1(jId, axis1[0], axis1[1], axis1[2]); dJointSetUniversalAxis2(jId, axis2[0], axis2[1], axis2[2]); } ~Fixture_dxJointUniversal_B1_and_B2_Axis_Random() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId1; dBodyID bId2; dJointID jId; }; // Rotate first body 90deg around Axis1 then back to original position // // ^ ^ ^ Z ^ // | | => <--- | | // | | | | // B1 B2 B1 B2 X .----->Y // N.B. X is going out of the screen // Set Axis1 with an Offset of 90deg // ^ ^ ^ // <--- | => | | // | | | // B1 B2 B1 B2 TEST_FIXTURE (Fixture_dxJointUniversal_B1_and_B2_Axis_Random, test_dJointSetUniversalAxisOffset_B1_90deg_Axis_Random) { CHECK_CLOSE (0, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (0, dJointGetUniversalAngle2 (jId), 1e-4); dReal angle1, angle2; dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (0, angle1, 1e-4); CHECK_CLOSE (0, angle2, 1e-4); dVector3 axis; dJointGetUniversalAxis1 (jId, axis); dReal angle = d2r(90); dMatrix3 R; dRFromAxisAndAngle (R, axis[0], axis[1], axis[2], angle); dBodySetRotation (bId1, R); CHECK_CLOSE (angle, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (0, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (angle, angle1, 1e-4); CHECK_CLOSE (0, angle2, 1e-4); dJointSetUniversalAxis1Offset (jId, axis[0], axis[1], axis[2], angle, 0); CHECK_CLOSE (angle, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (0, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (angle, angle1, 1e-4); CHECK_CLOSE (0, angle2, 1e-4); dRFromAxisAndAngle (R, axis[0], axis[1], axis[2], 0); dBodySetRotation (bId1, R); CHECK_CLOSE (0, dJointGetUniversalAngle1 (jId), 1e-4); CHECK_CLOSE (0, dJointGetUniversalAngle2 (jId), 1e-4); dJointGetUniversalAngles(jId, &angle1, &angle2); CHECK_CLOSE (0, angle1, 1e-4); CHECK_CLOSE (0, angle2, 1e-4); } } // End of SUITE TestdxJointUniversal ode-0.16/tests/joints/dball.cpp0000664000175200017520000000632013403272463013375 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ //234567890123456789012345678901234567890123456789012345678901234567890123456789 // 1 2 3 4 5 6 7 //////////////////////////////////////////////////////////////////////////////// // This file create unit test for some of the functions found in: // ode/src/joinst/dball.cpp // // //////////////////////////////////////////////////////////////////////////////// #include #include #include "../../ode/src/config.h" using namespace std; SUITE (TestdxJointDBall) { struct SimpleFixture { dWorldID w; dBodyID b1, b2; dJointID j; SimpleFixture() : w(dWorldCreate()), b1(dBodyCreate(w)), b2(dBodyCreate(w)), j(dJointCreateDBall(w, 0)) { dJointAttach(j, b1, b2); } ~SimpleFixture() { dJointDestroy(j); dBodyDestroy(b1); dBodyDestroy(b2); dWorldDestroy(w); } }; TEST_FIXTURE(SimpleFixture, testTargetDistance) { dBodySetPosition(b1, -1, -2, -3); dBodySetPosition(b2, 3, 5, 7); dJointAttach(j, b1, b2); // this recomputes the deduced target distance CHECK_CLOSE(dJointGetDBallDistance(j), dSqrt(REAL(165.0)), 1e-4); // moving body should not change target distance dBodySetPosition(b1, 2,3,4); CHECK_CLOSE(dJointGetDBallDistance(j), dSqrt(REAL(165.0)), 1e-4); // setting target distance manually should override the deduced one dJointSetDBallDistance(j, REAL(6.0)); CHECK_EQUAL(dJointGetDBallDistance(j), REAL(6.0)); } } ode-0.16/tests/joints/pr.cpp0000664000175200017520000010530713403272463012745 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ //234567890123456789012345678901234567890123456789012345678901234567890123456789 // 1 2 3 4 5 6 7 //////////////////////////////////////////////////////////////////////////////// // This file create unit test for some of the functions found in: // ode/src/joinst/pr.cpp // // //////////////////////////////////////////////////////////////////////////////// #include #include #include "../../ode/src/config.h" #include "../../ode/src/joints/pr.h" SUITE (TestdxJointPR) { // The 2 bodies are positionned at (0, 0, 0), with no rotation // The joint is a PR Joint // Axis is along the X axis // Anchor at (0, 0, 0) struct Fixture_dxJointPR_B1_and_B2_At_Zero_Axis_Along_X { Fixture_dxJointPR_B1_and_B2_At_Zero_Axis_Along_X() { wId = dWorldCreate(); bId1 = dBodyCreate (wId); dBodySetPosition (bId1, 0, 0, 0); bId2 = dBodyCreate (wId); dBodySetPosition (bId2, 0, 0, 0); jId = dJointCreatePR (wId, 0); joint = (dxJointPR*) jId; dJointAttach (jId, bId1, bId2); dJointSetPRAxis1 (jId, axis[0], axis[1], axis[2]); } ~Fixture_dxJointPR_B1_and_B2_At_Zero_Axis_Along_X() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId1; dBodyID bId2; dJointID jId; dxJointPR* joint; static const dVector3 axis; static const dReal offset; }; const dVector3 Fixture_dxJointPR_B1_and_B2_At_Zero_Axis_Along_X::axis = { 1, 0, 0 }; const dReal Fixture_dxJointPR_B1_and_B2_At_Zero_Axis_Along_X::offset = REAL (3.1); // Move 1st body offset unit in the X direction // // X-------> X---------> Axis --> // B1 => B1 // B2 B2 // // Start with a Offset of offset unit // // X-------> X---------> Axis --> // B1 => B1 // B2 B2 TEST_FIXTURE (Fixture_dxJointPR_B1_and_B2_At_Zero_Axis_Along_X, test_dJointSetPRAxisOffset_B1_3Unit) { dJointSetPRAnchor (jId, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPRPosition (jId), 1e-4); dBodySetPosition (bId1, offset, 0, 0); CHECK_CLOSE (offset, dJointGetPRPosition (jId), 1e-4); // dJointSetPRAnchorOffset (jId, 0, 0, 0, // offset*axis[0],offset*axis[1],offset*axis[2]); // CHECK_CLOSE (offset, dJointGetPRPosition (jId), 1e-4); // dBodySetPosition (bId1, 0, 0, 0); // CHECK_CLOSE (0.0, dJointGetPRPosition (jId), 1e-4); // // Only here to test a deprecated warning // dJointSetPRAxisDelta (jId, 1, 0, 0, 0, 0, 0); } // Move 1st body offset unit in the opposite X direction // // X-------> X---------> Axis --> // B1 => B1 // B2 B2 // // Start with a Offset of -offset unit // // X-------> X---------> Axis --> // B1 => B1 // B2 B2 TEST_FIXTURE (Fixture_dxJointPR_B1_and_B2_At_Zero_Axis_Along_X, test_dJointSetPRAxisOffset_B1_Minus_3Unit) { dJointSetPRAnchor (jId, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPRPosition (jId), 1e-4); dBodySetPosition (bId1, -offset, 0, 0); CHECK_CLOSE (-offset, dJointGetPRPosition (jId), 1e-4); // dJointSetPRAnchorOffset (jId, 0, 0, 0, // -offset*axis[0],-offset*axis[1],-offset*axis[2]); // CHECK_CLOSE (-offset, dJointGetPRPosition (jId), 1e-4); // dBodySetPosition (bId1, 0, 0, 0); // CHECK_CLOSE (0.0, dJointGetPRPosition (jId), 1e-4); } // Move 2nd body offset unit in the X direction // // X-------> X---------> Axis --> // B1 => B1 // B2 B2 // // Start with a Offset of offset unit // // X-------> X---------> Axis --> // B1 => B1 // B2 B2 TEST_FIXTURE (Fixture_dxJointPR_B1_and_B2_At_Zero_Axis_Along_X, test_dJointSetPRAxisOffset_B2_3Unit) { dJointSetPRAnchor (jId, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPRPosition (jId), 1e-4); dBodySetPosition (bId2, offset, 0, 0); CHECK_CLOSE (-offset, dJointGetPRPosition (jId), 1e-4); // dJointSetPRAnchorOffset (jId, 0, 0, 0, // -offset*axis[0],-offset*axis[1],-offset*axis[2]); // CHECK_CLOSE (-offset, dJointGetPRPosition (jId), 1e-4); // dBodySetPosition (bId2, 0, 0, 0); // CHECK_CLOSE (0.0, dJointGetPRPosition (jId), 1e-4); } // Move 2nd body offset unit in the opposite X direction // // X-------> X---------> Axis --> // B1 => B1 // B2 B2 // // Start with a Offset of -offset unit // // X-------> X---------> Axis --> // B1 => B1 // B2 B2 TEST_FIXTURE (Fixture_dxJointPR_B1_and_B2_At_Zero_Axis_Along_X, test_dJointSetPRAxisOffset_B2_Minus_3Unit) { dJointSetPRAnchor (jId, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPRPosition (jId), 1e-4); dBodySetPosition (bId2, -offset, 0, 0); CHECK_CLOSE (offset, dJointGetPRPosition (jId), 1e-4); // dJointSetPRAnchorOffset (jId, 0, 0, 0, // offset*axis[0],offset*axis[1],offset*axis[2]); // CHECK_CLOSE (offset, dJointGetPRPosition (jId), 1e-4); // dBodySetPosition (bId2, 0, 0, 0); // CHECK_CLOSE (0.0, dJointGetPRPosition (jId), 1e-4); } // Only body 1 // The body are positionned at (0, 0, 0), with no rotation // The joint is a PR Joint // Axis is along the X axis // Anchor at (0, 0, 0) struct Fixture_dxJointPR_B1_At_Zero_Axis_Along_X { Fixture_dxJointPR_B1_At_Zero_Axis_Along_X() { wId = dWorldCreate(); bId1 = dBodyCreate (wId); dBodySetPosition (bId1, 0, 0, 0); jId = dJointCreatePR (wId, 0); joint = (dxJointPR*) jId; dJointAttach (jId, bId1, NULL); dJointSetPRAxis1 (jId, axis[0], axis[1], axis[2]); } ~Fixture_dxJointPR_B1_At_Zero_Axis_Along_X() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId1; dJointID jId; dxJointPR* joint; static const dVector3 axis; static const dReal offset; }; const dVector3 Fixture_dxJointPR_B1_At_Zero_Axis_Along_X::axis = { 1, 0, 0 }; const dReal Fixture_dxJointPR_B1_At_Zero_Axis_Along_X::offset = REAL (3.1); // Move 1st body offset unit in the X direction // // X-------> X---------> Axis --> // B1 => B1 // // Start with a Offset of offset unit // // X-------> X---------> Axis --> // B1 => B1 TEST_FIXTURE (Fixture_dxJointPR_B1_At_Zero_Axis_Along_X, test_dJointSetPRAxisOffset_B1_OffsetUnit) { dJointSetPRAnchor (jId, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPRPosition (jId), 1e-4); dBodySetPosition (bId1, offset, 0, 0); CHECK_CLOSE (offset, dJointGetPRPosition (jId), 1e-4); // dJointSetPRAnchorOffset (jId, 0, 0, 0, // offset*axis[0],offset*axis[1],offset*axis[2]); // CHECK_CLOSE (offset, dJointGetPRPosition (jId), 1e-4); // dBodySetPosition (bId1, 0, 0, 0); // CHECK_CLOSE (0.0, dJointGetPRPosition (jId), 1e-4); } // Move 1st body offset unit in the opposite X direction // // X-------> X---------> Axis --> // B1 => B1 // // Start with a Offset of -offset unit // // X-------> X---------> Axis --> // B1 => B1 TEST_FIXTURE (Fixture_dxJointPR_B1_At_Zero_Axis_Along_X, test_dJointSetPRAxisOffset_B1_Minus_OffsetUnit) { dJointSetPRAnchor (jId, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPRPosition (jId), 1e-4); dBodySetPosition (bId1, -offset, 0, 0); CHECK_CLOSE (-offset, dJointGetPRPosition (jId), 1e-4); // dJointSetPRAnchorOffset (jId, 0, 0, 0, // -offset*axis[0],-offset*axis[1],-offset*axis[2]); // CHECK_CLOSE (-offset, dJointGetPRPosition (jId), 1e-4); // dBodySetPosition (bId1, 0, 0, 0); // CHECK_CLOSE (0.0, dJointGetPRPosition (jId), 1e-4); } // Only body 1 // The body are positionned at (0, 0, 0), with no rotation // The joint is a PR Joint // Axis is in the oppsite X axis // Anchor at (0, 0, 0) struct Fixture_dxJointPR_B1_At_Zero_Axis_Inverse_of_X { Fixture_dxJointPR_B1_At_Zero_Axis_Inverse_of_X() { wId = dWorldCreate(); bId1 = dBodyCreate (wId); dBodySetPosition (bId1, 0, 0, 0); jId = dJointCreatePR (wId, 0); joint = (dxJointPR*) jId; dJointAttach (jId, bId1, NULL); dJointSetPRAxis1 (jId, axis[0], axis[1], axis[2]); } ~Fixture_dxJointPR_B1_At_Zero_Axis_Inverse_of_X() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId1; dJointID jId; dxJointPR* joint; static const dVector3 axis; static const dReal offset; }; const dVector3 Fixture_dxJointPR_B1_At_Zero_Axis_Inverse_of_X::axis = { -1, 0, 0 }; const dReal Fixture_dxJointPR_B1_At_Zero_Axis_Inverse_of_X::offset = REAL (3.1); // Move 1st body offset unit in the X direction // // X-------> X---------> <--- Axis // B1 => B1 // // Start with a Offset of offset unit // // X-------> X---------> <--- Axis // B1 => B1 TEST_FIXTURE (Fixture_dxJointPR_B1_At_Zero_Axis_Inverse_of_X, test_dJointSetPRAxisOffset_B1_OffsetUnit) { dJointSetPRAnchor (jId, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPRPosition (jId), 1e-4); dBodySetPosition (bId1, offset, 0, 0); CHECK_CLOSE (-offset, dJointGetPRPosition (jId), 1e-4); // dJointSetPRAnchorOffset (jId, 0, 0, 0, // -offset*axis[0],-offset*axis[1],-offset*axis[2]); // CHECK_CLOSE (-offset, dJointGetPRPosition (jId), 1e-4); // dBodySetPosition (bId1, 0, 0, 0); // CHECK_CLOSE (0.0, dJointGetPRPosition (jId), 1e-4); } // Move 1st body offset unit in the opposite X direction // // X-------> X---------> <--- Axis // B1 => B1 // // Start with a Offset of -offset unit // // X-------> X---------> <--- Axis // B1 => B1 TEST_FIXTURE (Fixture_dxJointPR_B1_At_Zero_Axis_Inverse_of_X, test_dJointSetPRAxisOffset_B1_Minus_OffsetUnit) { dJointSetPRAnchor (jId, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPRPosition (jId), 1e-4); dBodySetPosition (bId1, -offset, 0, 0); CHECK_CLOSE (offset, dJointGetPRPosition (jId), 1e-4); // dJointSetPRAnchorOffset (jId, 0, 0, 0, // offset*axis[0],offset*axis[1],offset*axis[2]); // CHECK_CLOSE (offset, dJointGetPRPosition (jId), 1e-4); // dBodySetPosition (bId1, 0, 0, 0); // CHECK_CLOSE (0.0, dJointGetPRPosition (jId), 1e-4); } // Compare only one body to 2 bodies with one fixed. // // The body are positionned at (0, 0, 0), with no rotation // The joint is a PR Joint // Axis is along the X axis // Anchor at (0, 0, 0) struct Fixture_dxJointPR_Compare_Body_At_Zero_AxisP_Along_Y { Fixture_dxJointPR_Compare_Body_At_Zero_AxisP_Along_Y() { wId = dWorldCreate(); bId1_12 = dBodyCreate (wId); dBodySetPosition (bId1_12, 0, 0, 0); bId2_12 = dBodyCreate (wId); dBodySetPosition (bId2_12, 0, 0, 0); // The force will be added in the function since it is not // always on the same body jId_12 = dJointCreatePR (wId, 0); dJointAttach(jId_12, bId1_12, bId2_12); fixed = dJointCreateFixed (wId, 0); jId = dJointCreatePR (wId, 0); bId = dBodyCreate (wId); dBodySetPosition (bId, 0, 0, 0); // Linear velocity along the prismatic axis; dVector3 axis; dJointGetPRAxis1(jId_12, axis); dJointSetPRAxis1(jId, axis[0], axis[1], axis[2]); dBodySetLinearVel (bId, 4*axis[0], 4*axis[1], 4*axis[2]); } ~Fixture_dxJointPR_Compare_Body_At_Zero_AxisP_Along_Y() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId1_12; dBodyID bId2_12; dJointID jId_12; // Joint with 2 bodies dJointID fixed; dBodyID bId; dJointID jId; // Joint with one body }; TEST_FIXTURE (Fixture_dxJointPR_Compare_Body_At_Zero_AxisP_Along_Y, test_dJointSetPRPositionRate_Only_B1) { // Linear velocity along the prismatic axis; dVector3 axis; dJointGetPRAxis1(jId_12, axis); dBodySetLinearVel (bId1_12, 4*axis[0], 4*axis[1], 4*axis[2]); dJointAttach(jId_12, bId1_12, bId2_12); dJointAttach(fixed, 0, bId2_12); dJointSetFixed(fixed); dJointAttach(jId, bId, 0); CHECK_CLOSE(dJointGetPRPositionRate(jId_12), dJointGetPRPositionRate(jId), 1e-2); CHECK_CLOSE(dJointGetPRAngleRate(jId_12), dJointGetPRAngleRate(jId), 1e-2); } TEST_FIXTURE (Fixture_dxJointPR_Compare_Body_At_Zero_AxisP_Along_Y, test_dJointSetPRPositionRate_Only_B2) { // Linear velocity along the prismatic axis; dVector3 axis; dJointGetPRAxis1(jId_12, axis); dBodySetLinearVel (bId2_12, 4*axis[0], 4*axis[1], 4*axis[2]); dJointAttach(jId_12, bId1_12, bId2_12); dJointAttach(fixed, bId1_12, 0); dJointSetFixed(fixed); dJointAttach(jId, 0, bId); CHECK_CLOSE(dJointGetPRPositionRate(jId_12), dJointGetPRPositionRate(jId), 1e-2); CHECK_CLOSE(dJointGetPRAngleRate(jId_12), dJointGetPRAngleRate(jId), 1e-2); } // Only body 2 // The body are positionned at (0, 0, 0), with no rotation // The joint is a PR Joint // Axis is along the X axis // Anchor at (0, 0, 0) struct Fixture_dxJointPR_B2_At_Zero_Axis_Along_X { Fixture_dxJointPR_B2_At_Zero_Axis_Along_X() { wId = dWorldCreate(); bId2 = dBodyCreate (wId); dBodySetPosition (bId2, 0, 0, 0); jId = dJointCreatePR (wId, 0); joint = (dxJointPR*) jId; dJointAttach (jId, NULL, bId2); dJointSetPRAxis1 (jId, axis[0], axis[1], axis[2]); } ~Fixture_dxJointPR_B2_At_Zero_Axis_Along_X() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId2; dJointID jId; dxJointPR* joint; static const dVector3 axis; static const dReal offset; }; const dVector3 Fixture_dxJointPR_B2_At_Zero_Axis_Along_X::axis = { 1, 0, 0 }; const dReal Fixture_dxJointPR_B2_At_Zero_Axis_Along_X::offset = REAL (3.1); // Move 2nd body offset unit in the X direction // // X-------> X---------> Axis --> // B2 => B2 // // Start with a Offset of offset unit // // X-------> X---------> Axis --> // B2 => B2 TEST_FIXTURE (Fixture_dxJointPR_B2_At_Zero_Axis_Along_X, test_dJointSetPRAxisOffset_B2_OffsetUnit) { dJointSetPRAnchor (jId, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPRPosition (jId), 1e-4); dBodySetPosition (bId2, offset, 0, 0); CHECK_CLOSE (-offset, dJointGetPRPosition (jId), 1e-4); // dJointSetPRAnchorOffset (jId, 0, 0, 0, // -offset*axis[0],-offset*axis[1],-offset*axis[2]); // CHECK_CLOSE (-offset, dJointGetPRPosition (jId), 1e-4); // dBodySetPosition (bId2, 0, 0, 0); // CHECK_CLOSE (0.0, dJointGetPRPosition (jId), 1e-4); } // Move 2nd body offset unit in the opposite X direction // // X-------> X---------> Axis --> // B2 => B2 // // Start with a Offset of -offset unit // // X-------> X---------> Axis --> // B2 => B2 TEST_FIXTURE (Fixture_dxJointPR_B2_At_Zero_Axis_Along_X, test_dJointSetPRAxisOffset_B2_Minus_OffsetUnit) { dJointSetPRAnchor (jId, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPRPosition (jId), 1e-4); dBodySetPosition (bId2, -offset, 0, 0); CHECK_CLOSE (offset, dJointGetPRPosition (jId), 1e-4); // dJointSetPRAnchorOffset (jId, 0, 0, 0, // offset*axis[0],offset*axis[1],offset*axis[2]); // CHECK_CLOSE (offset, dJointGetPRPosition (jId), 1e-4); // dBodySetPosition (bId2, 0, 0, 0); // CHECK_CLOSE (0.0, dJointGetPRPosition (jId), 1e-4); } // Only body 2 // The body are positionned at (0, 0, 0), with no rotation // The joint is a PR Joint // Axis is in the opposite X axis // Anchor at (0, 0, 0) struct Fixture_dxJointPR_B2_At_Zero_Axis_Inverse_of_X { Fixture_dxJointPR_B2_At_Zero_Axis_Inverse_of_X() { wId = dWorldCreate(); bId2 = dBodyCreate (wId); dBodySetPosition (bId2, 0, 0, 0); jId = dJointCreatePR (wId, 0); joint = (dxJointPR*) jId; dJointAttach (jId, NULL, bId2); dJointSetPRAxis1 (jId, axis[0], axis[1], axis[2]); } ~Fixture_dxJointPR_B2_At_Zero_Axis_Inverse_of_X() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId2; dJointID jId; dxJointPR* joint; static const dVector3 axis; static const dReal offset; }; const dVector3 Fixture_dxJointPR_B2_At_Zero_Axis_Inverse_of_X::axis = { -1, 0, 0 }; const dReal Fixture_dxJointPR_B2_At_Zero_Axis_Inverse_of_X::offset = REAL (3.1); // Move 2nd body offset unit in the X direction // // X-------> X---------> <--- Axis // B2 => B2 // // Start with a Offset of offset unit // // X-------> X---------> <--- Axis // B2 => B2 TEST_FIXTURE (Fixture_dxJointPR_B2_At_Zero_Axis_Inverse_of_X, test_dJointSetPRAxisOffset_B2_OffsetUnit) { dJointSetPRAnchor (jId, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPRPosition (jId), 1e-4); dBodySetPosition (bId2, offset, 0, 0); CHECK_CLOSE (offset, dJointGetPRPosition (jId), 1e-4); // dJointSetPRAnchorOffset (jId, 0, 0, 0, // offset*axis[0],offset*axis[1],offset*axis[2]); // CHECK_CLOSE (offset, dJointGetPRPosition (jId), 1e-4); // dBodySetPosition (bId2, 0, 0, 0); // CHECK_CLOSE (0.0, dJointGetPRPosition (jId), 1e-4); // dJointSetPRAxisDelta (jId, 1, 0, 0, 0, 0, 0); } // Move 1st body offset unit in the opposite X direction // // X-------> X---------> <--- Axis // B2 => B2 // // Start with a Offset of -offset unit // // X-------> X---------> <--- Axis // B2 => B2 TEST_FIXTURE (Fixture_dxJointPR_B2_At_Zero_Axis_Inverse_of_X, test_dJointSetPRAxisOffset_B2_Minus_OffsetUnit) { dJointSetPRAnchor (jId, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPRPosition (jId), 1e-4); dBodySetPosition (bId2, -offset, 0, 0); CHECK_CLOSE (-offset, dJointGetPRPosition (jId), 1e-4); // dJointSetPRAnchorOffset (jId, 0, 0, 0, // -offset*axis[0],-offset*axis[1],-offset*axis[2]); // CHECK_CLOSE (-offset, dJointGetPRPosition (jId), 1e-4); // dBodySetPosition (bId2, 0, 0, 0); // CHECK_CLOSE (0.0, dJointGetPRPosition (jId), 1e-4); } // The 2 bodies are positionned at (0, 0, 0), and (0, 0, 0) // The bodis have rotation of 27deg around some axis. // The joint is a PR Joint // Axis is along the X axis // Anchor at (0, 0, 0) struct Fixture_dxJointPR_B1_and_B2_Random_Orientation_At_Zero_Axis_Along_X { Fixture_dxJointPR_B1_and_B2_Random_Orientation_At_Zero_Axis_Along_X() { wId = dWorldCreate(); bId1 = dBodyCreate (wId); dBodySetPosition (bId1, 0, 0, 0); bId2 = dBodyCreate (wId); dBodySetPosition (bId2, 0, 0, 0); dMatrix3 R; dVector3 axis; // Random axis axis[0] = REAL(0.53); axis[1] = -REAL(0.71); axis[2] = REAL(0.43); dNormalize3(axis); dRFromAxisAndAngle (R, axis[0], axis[1], axis[2], REAL(0.47123)); // 27deg dBodySetRotation (bId1, R); axis[0] = REAL(1.2); axis[1] = REAL(0.87); axis[2] = -REAL(0.33); dNormalize3(axis); dRFromAxisAndAngle (R, axis[0], axis[1], axis[2], REAL(0.47123)); // 27deg dBodySetRotation (bId2, R); jId = dJointCreatePR (wId, 0); joint = (dxJointPR*) jId; dJointAttach (jId, bId1, bId2); } ~Fixture_dxJointPR_B1_and_B2_Random_Orientation_At_Zero_Axis_Along_X() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId1; dBodyID bId2; dJointID jId; dxJointPR* joint; }; // Test is dJointSetPRAxis and dJointGetPRAxis return same value TEST_FIXTURE (Fixture_dxJointPR_B1_and_B2_Random_Orientation_At_Zero_Axis_Along_X, test_dJointSetGetPRAxis) { dVector3 axisOrig, axis; dJointGetPRAxis1 (jId, axisOrig); dJointGetPRAxis1 (jId, axis); dJointSetPRAxis1 (jId, axis[0], axis[1], axis[2]); dJointGetPRAxis1 (jId, axis); CHECK_CLOSE (axis[0], axisOrig[0] , 1e-4); CHECK_CLOSE (axis[1], axisOrig[1] , 1e-4); CHECK_CLOSE (axis[2], axisOrig[2] , 1e-4); dJointGetPRAxis2 (jId, axisOrig); dJointGetPRAxis2(jId, axis); dJointSetPRAxis2 (jId, axis[0], axis[1], axis[2]); dJointGetPRAxis2 (jId, axis); CHECK_CLOSE (axis[0], axisOrig[0] , 1e-4); CHECK_CLOSE (axis[1], axisOrig[1] , 1e-4); CHECK_CLOSE (axis[2], axisOrig[2] , 1e-4); } // Create 2 bodies attached by a PR joint // Axis is along the X axis (Default value // Anchor at (0, 0, 0) (Default value) // // ^Y // | // * Body2 // | // | // Body1 | // * Z--------> struct dxJointPR_Test_Initialization { dxJointPR_Test_Initialization() { wId = dWorldCreate(); // Remove gravity to have the only force be the force of the joint dWorldSetGravity(wId, 0,0,0); for (int j=0; j<2; ++j) { bId[j][0] = dBodyCreate (wId); dBodySetPosition (bId[j][0], -1, -2, -3); bId[j][1] = dBodyCreate (wId); dBodySetPosition (bId[j][1], 11, 22, 33); dMatrix3 R; dVector3 axis; // Random axis axis[0] = REAL(0.53); axis[1] = -REAL(0.71); axis[2] = REAL(0.43); dNormalize3(axis); dRFromAxisAndAngle (R, axis[0], axis[1], axis[2], REAL(0.47123)); // 27deg dBodySetRotation (bId[j][0], R); axis[0] = REAL(1.2); axis[1] = REAL(0.87); axis[2] = -REAL(0.33); dNormalize3(axis); dRFromAxisAndAngle (R, axis[0], axis[1], axis[2], REAL(0.47123)); // 27deg dBodySetRotation (bId[j][1], R); jId[j] = dJointCreatePR (wId, 0); dJointAttach (jId[j], bId[j][0], bId[j][1]); } } ~dxJointPR_Test_Initialization() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId[2][2]; dJointID jId[2]; }; // Test if setting a PR with its default values // will behave the same as a default PR joint TEST_FIXTURE (dxJointPR_Test_Initialization, test_PR_Initialization) { using namespace std; dVector3 axis; dJointGetPRAxis1(jId[1], axis); dJointSetPRAxis1(jId[1], axis[0], axis[1], axis[2]); dJointGetPRAxis2(jId[1], axis); dJointSetPRAxis2(jId[1], axis[0], axis[1], axis[2]); dVector3 anchor; dJointGetPRAnchor(jId[1], anchor); dJointSetPRAnchor(jId[1], anchor[0], anchor[1], anchor[2]); for (int b=0; b<2; ++b) { // Compare body b of the first joint with its equivalent on the // second joint const dReal *qA = dBodyGetQuaternion(bId[0][b]); const dReal *qB = dBodyGetQuaternion(bId[1][b]); CHECK_CLOSE (qA[0], qB[0], 1e-4); CHECK_CLOSE (qA[1], qB[1], 1e-4); CHECK_CLOSE (qA[2], qB[2], 1e-4); CHECK_CLOSE (qA[3], qB[3], 1e-4); } dWorldStep (wId,0.5); dWorldStep (wId,0.5); dWorldStep (wId,0.5); dWorldStep (wId,0.5); for (int b=0; b<2; ++b) { // Compare body b of the first joint with its equivalent on the // second joint const dReal *qA = dBodyGetQuaternion(bId[0][b]); const dReal *qB = dBodyGetQuaternion(bId[1][b]); CHECK_CLOSE (qA[0], qB[0], 1e-4); CHECK_CLOSE (qA[1], qB[1], 1e-4); CHECK_CLOSE (qA[2], qB[2], 1e-4); CHECK_CLOSE (qA[3], qB[3], 1e-4); const dReal *posA = dBodyGetPosition(bId[0][b]); const dReal *posB = dBodyGetPosition(bId[1][b]); CHECK_CLOSE (posA[0], posB[0], 1e-4); CHECK_CLOSE (posA[1], posB[1], 1e-4); CHECK_CLOSE (posA[2], posB[2], 1e-4); CHECK_CLOSE (posA[3], posB[3], 1e-4); } } // This test compare the result of a slider with 2 bodies where body body 2 is // fixed to the world to a slider with only one body at position 1. // // Test the limits [-1, 0.25] when only one body at is attached to the joint // using dJointAttache(jId, bId, 0); // TEST_FIXTURE(Fixture_dxJointPR_Compare_Body_At_Zero_AxisP_Along_Y, test_Limit_minus1_025_One_Body_on_left) { // Linear velocity along the prismatic axis; dVector3 axis; dJointGetPRAxis1(jId_12, axis); dBodySetLinearVel (bId1_12, 4*axis[0], 4*axis[1], 4*axis[2]); dJointAttach(jId_12, bId1_12, bId2_12); dJointSetPRParam(jId_12, dParamLoStop, -1); dJointSetPRParam(jId_12, dParamHiStop, 0.25); dJointAttach(fixed, 0, bId2_12); dJointSetFixed(fixed); dJointAttach(jId, bId, 0); dJointSetPRParam(jId, dParamLoStop, -1); dJointSetPRParam(jId, dParamHiStop, 0.25); for (int i=0; i<50; ++i) dWorldStep(wId, 1.0); const dReal *pos1_12 = dBodyGetPosition(bId1_12); const dReal *pos = dBodyGetPosition(bId); CHECK_CLOSE (pos1_12[0], pos[0], 1e-2); CHECK_CLOSE (pos1_12[1], pos[1], 1e-2); CHECK_CLOSE (pos1_12[2], pos[2], 1e-2); const dReal *q1_12 = dBodyGetQuaternion(bId1_12); const dReal *q = dBodyGetQuaternion(bId); CHECK_CLOSE (q1_12[0], q[0], 1e-4); CHECK_CLOSE (q1_12[1], q[1], 1e-4); CHECK_CLOSE (q1_12[2], q[2], 1e-4); CHECK_CLOSE (q1_12[3], q[3], 1e-4); } // This test compare the result of a slider with 2 bodies where body body 1 is // fixed to the world to a slider with only one body at position 2. // // Test the limits [-1, 0.25] when only one body at is attached to the joint // using dJointAttache(jId, 0, bId); // TEST_FIXTURE(Fixture_dxJointPR_Compare_Body_At_Zero_AxisP_Along_Y, test_Limit_minus1_025_One_Body_on_right) { // Linear velocity along the prismatic axis; dVector3 axis; dJointGetPRAxis1(jId_12, axis); dBodySetLinearVel (bId2_12, 4*axis[0], 4*axis[1], 4*axis[2]); dJointAttach(jId_12, bId1_12, bId2_12); dJointSetPRParam(jId_12, dParamLoStop, -1); dJointSetPRParam(jId_12, dParamHiStop, 0.25); dJointAttach(fixed, bId1_12, 0); dJointSetFixed(fixed); dJointAttach(jId, 0, bId); dJointSetPRParam(jId, dParamLoStop, -1); dJointSetPRParam(jId, dParamHiStop, 0.25); for (int i=0; i<50; ++i) dWorldStep(wId, 1.0); const dReal *pos2_12 = dBodyGetPosition(bId2_12); const dReal *pos = dBodyGetPosition(bId); CHECK_CLOSE (pos2_12[0], pos[0], 1e-2); CHECK_CLOSE (pos2_12[1], pos[1], 1e-2); CHECK_CLOSE (pos2_12[2], pos[2], 1e-2); const dReal *q2_12 = dBodyGetQuaternion(bId2_12); const dReal *q = dBodyGetQuaternion(bId); CHECK_CLOSE (q2_12[0], q[0], 1e-4); CHECK_CLOSE (q2_12[1], q[1], 1e-4); CHECK_CLOSE (q2_12[2], q[2], 1e-4); CHECK_CLOSE (q2_12[3], q[3], 1e-4); } // This test compare the result of a slider with 2 bodies where body body 2 is // fixed to the world to a slider with only one body at position 1. // // Test the limits [0, 0] when only one body at is attached to the joint // using dJointAttache(jId, bId, 0); // // The body should not move since their is no room between the two limits // TEST_FIXTURE(Fixture_dxJointPR_Compare_Body_At_Zero_AxisP_Along_Y, test_Limit_0_0_One_Body_on_left) { // Linear velocity along the prismatic axis; dVector3 axis; dJointGetPRAxis1(jId_12, axis); dBodySetLinearVel (bId1_12, 4*axis[0], 4*axis[1], 4*axis[2]); dJointAttach(jId_12, bId1_12, bId2_12); dJointSetPRParam(jId_12, dParamLoStop, 0); dJointSetPRParam(jId_12, dParamHiStop, 0); dJointAttach(fixed, 0, bId2_12); dJointSetFixed(fixed); dJointAttach(jId, bId, 0); dJointSetPRParam(jId, dParamLoStop, 0); dJointSetPRParam(jId, dParamHiStop, 0); for (int i=0; i<50; ++i) dWorldStep(wId, 1.0); const dReal *pos1_12 = dBodyGetPosition(bId1_12); const dReal *pos = dBodyGetPosition(bId); CHECK_CLOSE (pos1_12[0], pos[0], 1e-4); CHECK_CLOSE (pos1_12[1], pos[1], 1e-4); CHECK_CLOSE (pos1_12[2], pos[2], 1e-4); CHECK_CLOSE (0, pos[0], 1e-4); CHECK_CLOSE (0, pos[1], 1e-4); CHECK_CLOSE (0, pos[2], 1e-4); const dReal *q1_12 = dBodyGetQuaternion(bId1_12); const dReal *q = dBodyGetQuaternion(bId); CHECK_CLOSE (q1_12[0], q[0], 1e-4); CHECK_CLOSE (q1_12[1], q[1], 1e-4); CHECK_CLOSE (q1_12[2], q[2], 1e-4); CHECK_CLOSE (q1_12[3], q[3], 1e-4); } // This test compare the result of a slider with 2 bodies where body body 1 is // fixed to the world to a slider with only one body at position 2. // // Test the limits [0, 0] when only one body at is attached to the joint // using dJointAttache(jId, 0, bId); // // The body should not move since their is no room between the two limits // TEST_FIXTURE(Fixture_dxJointPR_Compare_Body_At_Zero_AxisP_Along_Y, test_Limit_0_0_One_Body_on_right) { // Linear velocity along the prismatic axis; dVector3 axis; dJointGetPRAxis1(jId_12, axis); dBodySetLinearVel (bId2_12, 4*axis[0], 4*axis[1], 4*axis[2]); dJointAttach(jId_12, bId1_12, bId2_12); dJointSetPRParam(jId_12, dParamLoStop, 0); dJointSetPRParam(jId_12, dParamHiStop, 0); dJointAttach(fixed, bId1_12, 0); dJointSetFixed(fixed); dJointAttach(jId, 0, bId); dJointSetPRParam(jId, dParamLoStop, 0); dJointSetPRParam(jId, dParamHiStop, 0); for (int i=0; i<50; ++i) { dWorldStep(wId, 1.0); } const dReal *pos2_12 = dBodyGetPosition(bId2_12); const dReal *pos = dBodyGetPosition(bId); CHECK_CLOSE (pos2_12[0], pos[0], 1e-4); CHECK_CLOSE (pos2_12[1], pos[1], 1e-4); CHECK_CLOSE (pos2_12[2], pos[2], 1e-4); CHECK_CLOSE (0, pos[0], 1e-4); CHECK_CLOSE (0, pos[1], 1e-4); CHECK_CLOSE (0, pos[2], 1e-4); const dReal *q2_12 = dBodyGetQuaternion(bId2_12); const dReal *q = dBodyGetQuaternion(bId); CHECK_CLOSE (q2_12[0], q[0], 1e-4); CHECK_CLOSE (q2_12[1], q[1], 1e-4); CHECK_CLOSE (q2_12[2], q[2], 1e-4); CHECK_CLOSE (q2_12[3], q[3], 1e-4); } } // End of SUITE TestdxJointPR ode-0.16/tests/joints/hinge2.cpp0000664000175200017520000001312213403272463013471 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ //234567890123456789012345678901234567890123456789012345678901234567890123456789 // 1 2 3 4 5 6 7 //////////////////////////////////////////////////////////////////////////////// // This file create unit test for some of the functions found in: // ode/src/joinst/hinge2.cpp // // //////////////////////////////////////////////////////////////////////////////// #include #include #include "../../ode/src/config.h" #include "../../ode/src/joints/hinge2.h" using namespace std; SUITE (TestdxJointHinge2) { // The 2 bodies are positionned at (-1, -2, -3), and (11, 22, 33) // The bodis have rotation of 27deg around some axis. // The joint is a Hinge2 Joint // Axis is along the X axis // Anchor at (0, 0, 0) struct dxJointHinge2_Fixture_B1_and_B2_At_Zero_Axis_Along_X { dxJointHinge2_Fixture_B1_and_B2_At_Zero_Axis_Along_X() { wId = dWorldCreate(); for (int j=0; j<2; ++j) { bId[j][0] = dBodyCreate (wId); dBodySetPosition (bId[j][0], -1, -2, -3); bId[j][1] = dBodyCreate (wId); dBodySetPosition (bId[j][1], 11, 22, 33); dMatrix3 R; dVector3 axis; // Random axis axis[0] = REAL(0.53); axis[1] = -REAL(0.71); axis[2] = REAL(0.43); dNormalize3(axis); dRFromAxisAndAngle (R, axis[0], axis[1], axis[2], REAL(0.47123)); // 27deg dBodySetRotation (bId[j][0], R); axis[0] = REAL(1.2); axis[1] = REAL(0.87); axis[2] = -REAL(0.33); dNormalize3(axis); dRFromAxisAndAngle (R, axis[0], axis[1], axis[2], REAL(0.47123)); // 27deg dBodySetRotation (bId[j][1], R); jId[j] = dJointCreateHinge2 (wId, 0); dJointAttach (jId[j], bId[j][0], bId[j][1]); } } ~dxJointHinge2_Fixture_B1_and_B2_At_Zero_Axis_Along_X() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId[2][2]; dJointID jId[2]; }; // Rotate 2nd body 90deg around X then back to original position // // ^ ^ ^ // | | => | <--- // | | | // B1 B2 B1 B2 // // Start with a Delta of 90deg // ^ ^ ^ // | <--- => | | // | | | // B1 B2 B1 B2 TEST_FIXTURE (dxJointHinge2_Fixture_B1_and_B2_At_Zero_Axis_Along_X, test_dJointSetHinge2AxisOffset_B2_90deg) { dVector3 anchor; dJointGetHinge2Anchor(jId[1], anchor); dJointSetHinge2Anchor(jId[1], anchor[0], anchor[1], anchor[2]); dVector3 axis1, axis2; dJointGetHinge2Axis1(jId[1], axis1); dJointGetHinge2Axis2(jId[1], axis2); dJointSetHinge2Axes(jId[1], axis1, axis2); dJointSetHinge2Axes(jId[1], axis1, NULL); dJointSetHinge2Axes(jId[1], NULL, axis2); for (int b=0; b<2; ++b) { // Compare body b of the first joint with its equivalent on the // second joint const dReal *qA = dBodyGetQuaternion(bId[0][b]); const dReal *qB = dBodyGetQuaternion(bId[1][b]); CHECK_CLOSE (qA[0], qB[0], 1e-4); CHECK_CLOSE (qA[1], qB[1], 1e-4); CHECK_CLOSE (qA[2], qB[2], 1e-4); CHECK_CLOSE (qA[3], qB[3], 1e-4); } dWorldStep (wId,0.5); dWorldStep (wId,0.5); dWorldStep (wId,0.5); dWorldStep (wId,0.5); for (int b=0; b<2; ++b) { // Compare body b of the first joint with its equivalent on the // second joint const dReal *qA = dBodyGetQuaternion(bId[0][b]); const dReal *qB = dBodyGetQuaternion(bId[1][b]); CHECK_CLOSE (qA[0], qB[0], 1e-4); CHECK_CLOSE (qA[1], qB[1], 1e-4); CHECK_CLOSE (qA[2], qB[2], 1e-4); CHECK_CLOSE (qA[3], qB[3], 1e-4); const dReal *posA = dBodyGetPosition(bId[0][b]); const dReal *posB = dBodyGetPosition(bId[1][b]); CHECK_CLOSE (posA[0], posB[0], 1e-4); CHECK_CLOSE (posA[1], posB[1], 1e-4); CHECK_CLOSE (posA[2], posB[2], 1e-4); CHECK_CLOSE (posA[3], posB[3], 1e-4); } } } // End of SUITE TestdxJointHinge2 ode-0.16/tests/joints/slider.cpp0000664000175200017520000012131013403272463013576 00000000000000 /************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ //234567890123456789012345678901234567890123456789012345678901234567890123456789 // 1 2 3 4 5 6 7 //////////////////////////////////////////////////////////////////////////////// // This file create unit test for some of the functions found in: // ode/src/joinst/slider.cpp // // //////////////////////////////////////////////////////////////////////////////// #include #include #include "../../ode/src/config.h" #include "../../ode/src/joints/slider.h" SUITE (TestdxJointSlider) { struct dxJointSlider_Fixture_1 { dxJointSlider_Fixture_1() { wId = dWorldCreate(); bId1 = dBodyCreate (wId); dBodySetPosition (bId1, 0, -1, 0); bId2 = dBodyCreate (wId); dBodySetPosition (bId2, 0, 1, 0); jId = dJointCreateSlider (wId, 0); joint = (dxJointSlider*) jId; dJointAttach (jId, bId1, bId2); } ~dxJointSlider_Fixture_1() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId1; dBodyID bId2; dJointID jId; dxJointSlider* joint; }; TEST_FIXTURE (dxJointSlider_Fixture_1, test_dJointSetSlider) { // the 2 bodies are align dJointSetSliderAxis (jId, 1, 0, 0); CHECK_CLOSE (joint->qrel[0], 1.0, 1e-4); CHECK_CLOSE (joint->qrel[1], 0.0, 1e-4); CHECK_CLOSE (joint->qrel[2], 0.0, 1e-4); CHECK_CLOSE (joint->qrel[3], 0.0, 1e-4); dMatrix3 R; // Rotate 2nd body 90deg around X dBodySetPosition (bId2, 0, 0, 1); dRFromAxisAndAngle (R, 1, 0, 0, M_PI/2.0); dBodySetRotation (bId2, R); dJointSetSliderAxis (jId, 1, 0 ,0); CHECK_CLOSE (joint->qrel[0], 0.70710678118654757, 1e-4); CHECK_CLOSE (joint->qrel[1], 0.70710678118654757, 1e-4); CHECK_CLOSE (joint->qrel[2], 0.0, 1e-4); CHECK_CLOSE (joint->qrel[3], 0.0, 1e-4); // Rotate 2nd body -90deg around X dBodySetPosition (bId2, 0, 0, -1); dRFromAxisAndAngle (R, 1, 0, 0, -M_PI/2.0); dBodySetRotation (bId2, R); dJointSetSliderAxis (jId, 1, 0 ,0); CHECK_CLOSE (joint->qrel[0], 0.70710678118654757, 1e-4); CHECK_CLOSE (joint->qrel[1], -0.70710678118654757, 1e-4); CHECK_CLOSE (joint->qrel[2], 0.0, 1e-4); CHECK_CLOSE (joint->qrel[3], 0.0, 1e-4); // Rotate 2nd body 90deg around Z dBodySetPosition (bId2, 0, 1, 0); dRFromAxisAndAngle (R, 0, 0, 1, M_PI/2.0); dBodySetRotation (bId2, R); dJointSetSliderAxis (jId, 1, 0 ,0); CHECK_CLOSE (joint->qrel[0], 0.70710678118654757, 1e-4); CHECK_CLOSE (joint->qrel[1], 0.0, 1e-4); CHECK_CLOSE (joint->qrel[2], 0.0, 1e-4); CHECK_CLOSE (joint->qrel[3], 0.70710678118654757, 1e-4); // Rotate 2nd body 45deg around Y dBodySetPosition (bId2, 0, 1, 0); dRFromAxisAndAngle (R, 0, 1, 0, M_PI/4.0); dBodySetRotation (bId2, R); dJointSetSliderAxis (jId, 1, 0 ,0); CHECK_CLOSE (joint->qrel[0], 0.92387953251128674, 1e-4); CHECK_CLOSE (joint->qrel[1], 0.0, 1e-4); CHECK_CLOSE (joint->qrel[2], 0.38268343236508984, 1e-4); CHECK_CLOSE (joint->qrel[3], 0.0, 1e-4); // Rotate in a strange manner // Both bodies at origin dRFromEulerAngles (R, REAL(0.23), REAL(3.1), REAL(-0.73)); dBodySetPosition (bId1, 0, 0, 0); dBodySetRotation (bId1, R); dRFromEulerAngles (R, REAL(-0.57), REAL(1.49), REAL(0.81)); dBodySetPosition (bId2, 0, 0, 0); dBodySetRotation (bId2, R); dJointSetSliderAxis (jId, 1, 0 ,0); CHECK_CLOSE (joint->qrel[0], -0.25526036263124319, 1e-4); CHECK_CLOSE (joint->qrel[1], 0.28434861188441968, 1e-4); CHECK_CLOSE (joint->qrel[2], -0.65308047160141625, 1e-4); CHECK_CLOSE (joint->qrel[3], 0.65381489108282143, 1e-4); } // The 2 bodies are positionned at (0, 0, 0), with no rotation // The joint is a Slider Joint // Axis is along the X axis // Anchor at (0, 0, 0) struct Fixture_dxJointSlider_B1_and_B2_At_Zero_Axis_Along_X { Fixture_dxJointSlider_B1_and_B2_At_Zero_Axis_Along_X() { wId = dWorldCreate(); bId1 = dBodyCreate (wId); dBodySetPosition (bId1, 0, 0, 0); bId2 = dBodyCreate (wId); dBodySetPosition (bId2, 0, 0, 0); jId = dJointCreateSlider (wId, 0); joint = (dxJointSlider*) jId; dJointAttach (jId, bId1, bId2); dJointSetSliderAxis(jId, axis[0], axis[1], axis[2]); } ~Fixture_dxJointSlider_B1_and_B2_At_Zero_Axis_Along_X() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId1; dBodyID bId2; dJointID jId; dxJointSlider* joint; static const dVector3 axis; static const dReal offset; }; const dVector3 Fixture_dxJointSlider_B1_and_B2_At_Zero_Axis_Along_X::axis = {1, 0, 0}; const dReal Fixture_dxJointSlider_B1_and_B2_At_Zero_Axis_Along_X::offset = REAL(3.1); // Move 1st body offset unit in the X direction // // X-------> X---------> Axis --> // B1 => B1 // B2 B2 // // Start with a Offset of offset unit // // X-------> X---------> Axis --> // B1 => B1 // B2 B2 TEST_FIXTURE (Fixture_dxJointSlider_B1_and_B2_At_Zero_Axis_Along_X, test_dJointSetSliderAxisOffset_B1_3Unit) { CHECK_CLOSE (0.0, dJointGetSliderPosition(jId), 1e-4); dBodySetPosition(bId1, offset, 0, 0); CHECK_CLOSE (offset, dJointGetSliderPosition(jId), 1e-4); } // Move 1st body offset unit in the opposite X direction // // X-------> X---------> Axis --> // B1 => B1 // B2 B2 // // Start with a Offset of -offset unit // // X-------> X---------> Axis --> // B1 => B1 // B2 B2 TEST_FIXTURE (Fixture_dxJointSlider_B1_and_B2_At_Zero_Axis_Along_X, test_dJointSetSliderAxisOffset_B1_Minus_3Unit) { CHECK_CLOSE (0.0, dJointGetSliderPosition(jId), 1e-4); dBodySetPosition(bId1, -offset, 0, 0); CHECK_CLOSE (-offset, dJointGetSliderPosition(jId), 1e-4); } // Move 2nd body offset unit in the X direction // // X-------> X---------> Axis --> // B1 => B1 // B2 B2 // // Start with a Offset of offset unit // // X-------> X---------> Axis --> // B1 => B1 // B2 B2 TEST_FIXTURE (Fixture_dxJointSlider_B1_and_B2_At_Zero_Axis_Along_X, test_dJointSetSliderAxisOffset_B2_3Unit) { CHECK_CLOSE (0.0, dJointGetSliderPosition(jId), 1e-4); dBodySetPosition(bId2, offset, 0, 0); CHECK_CLOSE (-offset, dJointGetSliderPosition(jId), 1e-4); } // Move 2nd body offset unit in the opposite X direction // // X-------> X---------> Axis --> // B1 => B1 // B2 B2 // // Start with a Offset of -offset unit // // X-------> X---------> Axis --> // B1 => B1 // B2 B2 TEST_FIXTURE (Fixture_dxJointSlider_B1_and_B2_At_Zero_Axis_Along_X, test_dJointSetSliderAxisOffset_B2_Minus_3Unit) { CHECK_CLOSE (0.0, dJointGetSliderPosition(jId), 1e-4); dBodySetPosition(bId2, -offset, 0, 0); CHECK_CLOSE (offset, dJointGetSliderPosition(jId), 1e-4); } // The 2 bodies are positionned at (0, 0, 0), with no rotation // The joint is a Slider Joint // Axis is the opposite of the X axis // Anchor at (0, 0, 0) struct Fixture_dxJointSlider_B1_and_B2_At_Zero_Axis_Inverse_of_X { Fixture_dxJointSlider_B1_and_B2_At_Zero_Axis_Inverse_of_X() { wId = dWorldCreate(); bId1 = dBodyCreate (wId); dBodySetPosition (bId1, 0, 0, 0); bId2 = dBodyCreate (wId); dBodySetPosition (bId2, 0, 0, 0); jId = dJointCreateSlider (wId, 0); joint = (dxJointSlider*) jId; dJointAttach (jId, bId1, bId2); dJointSetSliderAxis(jId, axis[0], axis[1], axis[2]); } ~Fixture_dxJointSlider_B1_and_B2_At_Zero_Axis_Inverse_of_X() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId1; dBodyID bId2; dJointID jId; dxJointSlider* joint; static const dVector3 axis; static const dReal offset; }; const dVector3 Fixture_dxJointSlider_B1_and_B2_At_Zero_Axis_Inverse_of_X::axis = {-1, 0, 0}; const dReal Fixture_dxJointSlider_B1_and_B2_At_Zero_Axis_Inverse_of_X::offset = REAL(3.1); // Move 1st body offset unit in the X direction // // X-------> X---------> <-- Axis // B1 => B1 // B2 B2 // // Start with a Offset of offset unit // // X-------> X---------> <-- Axis // B1 => B1 // B2 B2 TEST_FIXTURE (Fixture_dxJointSlider_B1_and_B2_At_Zero_Axis_Inverse_of_X, test_dJointSetSliderAxisOffset_B1_3Unit) { CHECK_CLOSE (0.0, dJointGetSliderPosition(jId), 1e-4); dBodySetPosition(bId1, offset, 0, 0); CHECK_CLOSE (-offset, dJointGetSliderPosition(jId), 1e-4); } // Move 1st body offset unit in the opposite X direction // // X-------> X---------> <-- Axis // B1 => B1 // B2 B2 // // Start with a Offset of offset unit // // X-------> X---------> <-- Axis // B1 => B1 // B2 B2 TEST_FIXTURE (Fixture_dxJointSlider_B1_and_B2_At_Zero_Axis_Inverse_of_X, test_dJointSetSliderAxisOffset_B1_Minus_3Unit) { CHECK_CLOSE (0.0, dJointGetSliderPosition(jId), 1e-4); dBodySetPosition(bId1, -offset, 0, 0); CHECK_CLOSE (offset, dJointGetSliderPosition(jId), 1e-4); } // Move 2nd body offset unit in the X direction // // X-------> X---------> <-- Axis // B1 => B1 // B2 B2 // // Start with a Offset of offset unit // // X-------> X---------> <-- Axis // B1 => B1 // B2 B2 TEST_FIXTURE (Fixture_dxJointSlider_B1_and_B2_At_Zero_Axis_Inverse_of_X, test_dJointSetSliderAxisOffset_B2_3Unit) { CHECK_CLOSE (0.0, dJointGetSliderPosition(jId), 1e-4); dBodySetPosition(bId2, offset, 0, 0); CHECK_CLOSE (offset, dJointGetSliderPosition(jId), 1e-4); } // Move 2nd body offset unit in the opposite X direction // // X-------> X---------> <-- Axis // B1 => B1 // B2 B2 // // Start with a Offset of -offset unit // // X-------> X---------> <-- Axis // B1 => B1 // B2 B2 TEST_FIXTURE (Fixture_dxJointSlider_B1_and_B2_At_Zero_Axis_Inverse_of_X, test_dJointSetSliderAxisOffset_B2_Minus_3Unit) { CHECK_CLOSE (0.0, dJointGetSliderPosition(jId), 1e-4); dBodySetPosition(bId2, -offset, 0, 0); CHECK_CLOSE (-offset, dJointGetSliderPosition(jId), 1e-4); } // Only body 1 // The body are positionned at (0, 0, 0), with no rotation // The joint is a Slider Joint // Axis is along the X axis // Anchor at (0, 0, 0) struct Fixture_dxJointSlider_B1_At_Zero_Axis_Along_X { Fixture_dxJointSlider_B1_At_Zero_Axis_Along_X() { wId = dWorldCreate(); bId1 = dBodyCreate (wId); dBodySetPosition (bId1, 0, 0, 0); jId = dJointCreateSlider (wId, 0); joint = (dxJointSlider*) jId; dJointAttach (jId, bId1, NULL); dJointSetSliderAxis(jId, axis[0], axis[1], axis[2]); } ~Fixture_dxJointSlider_B1_At_Zero_Axis_Along_X() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId1; dJointID jId; dxJointSlider* joint; static const dVector3 axis; static const dReal offset; }; const dVector3 Fixture_dxJointSlider_B1_At_Zero_Axis_Along_X::axis = {1, 0, 0}; const dReal Fixture_dxJointSlider_B1_At_Zero_Axis_Along_X::offset = REAL(3.1); // Move 1st body offset unit in the X direction // // X-------> X---------> Axis --> // B1 => B1 // TEST_FIXTURE (Fixture_dxJointSlider_B1_At_Zero_Axis_Along_X, test_dJointSetSliderAxisOffset_B1_OffsetUnit) { CHECK_CLOSE (0.0, dJointGetSliderPosition(jId), 1e-4); dBodySetPosition(bId1, offset, 0, 0); CHECK_CLOSE (offset, dJointGetSliderPosition(jId), 1e-4); } // Move 1st body offset unit in the opposite X direction // // X-------> X---------> Axis --> // B1 => B1 // TEST_FIXTURE (Fixture_dxJointSlider_B1_At_Zero_Axis_Along_X, test_dJointSetSliderAxisOffset_B1_Minus_OffsetUnit) { CHECK_CLOSE (0.0, dJointGetSliderPosition(jId), 1e-4); dBodySetPosition(bId1, -offset, 0, 0); CHECK_CLOSE (-offset, dJointGetSliderPosition(jId), 1e-4); } // Only body 1 // The body are positionned at (0, 0, 0), with no rotation // The joint is a Slider Joint // Axis is in the oppsite X axis // Anchor at (0, 0, 0) struct Fixture_dxJointSlider_B1_At_Zero_Axis_Inverse_of_X { Fixture_dxJointSlider_B1_At_Zero_Axis_Inverse_of_X() { wId = dWorldCreate(); bId1 = dBodyCreate (wId); dBodySetPosition (bId1, 0, 0, 0); jId = dJointCreateSlider (wId, 0); joint = (dxJointSlider*) jId; dJointAttach (jId, bId1, NULL); dJointSetSliderAxis(jId, axis[0], axis[1], axis[2]); } ~Fixture_dxJointSlider_B1_At_Zero_Axis_Inverse_of_X() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId1; dJointID jId; dxJointSlider* joint; static const dVector3 axis; static const dReal offset; }; const dVector3 Fixture_dxJointSlider_B1_At_Zero_Axis_Inverse_of_X::axis = {-1, 0, 0}; const dReal Fixture_dxJointSlider_B1_At_Zero_Axis_Inverse_of_X::offset = REAL(3.1); // Move 1st body offset unit in the X direction // // X-------> X---------> <--- Axis // B1 => B1 // TEST_FIXTURE (Fixture_dxJointSlider_B1_At_Zero_Axis_Inverse_of_X, test_dJointSetSliderAxisOffset_B1_OffsetUnit) { CHECK_CLOSE (0.0, dJointGetSliderPosition(jId), 1e-4); dBodySetPosition(bId1, offset, 0, 0); CHECK_CLOSE (-offset, dJointGetSliderPosition(jId), 1e-4); } // Move 1st body offset unit in the opposite X direction // // X-------> X---------> <--- Axis // B1 => B1 // TEST_FIXTURE (Fixture_dxJointSlider_B1_At_Zero_Axis_Inverse_of_X, test_dJointSetSliderAxisOffset_B1_Minus_OffsetUnit) { CHECK_CLOSE (0.0, dJointGetSliderPosition(jId), 1e-4); dBodySetPosition(bId1, -offset, 0, 0); CHECK_CLOSE (offset, dJointGetSliderPosition(jId), 1e-4); } // Only body 2 // The body are positionned at (0, 0, 0), with no rotation // The joint is a Slider Joint // Axis is along the X axis // Anchor at (0, 0, 0) struct Fixture_dxJointSlider_B2_At_Zero_Axis_Along_X { Fixture_dxJointSlider_B2_At_Zero_Axis_Along_X() { wId = dWorldCreate(); bId2 = dBodyCreate (wId); dBodySetPosition (bId2, 0, 0, 0); jId = dJointCreateSlider (wId, 0); joint = (dxJointSlider*) jId; dJointAttach (jId, NULL, bId2); dJointSetSliderAxis(jId, axis[0], axis[1], axis[2]); } ~Fixture_dxJointSlider_B2_At_Zero_Axis_Along_X() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId2; dJointID jId; dxJointSlider* joint; static const dVector3 axis; static const dReal offset; }; const dVector3 Fixture_dxJointSlider_B2_At_Zero_Axis_Along_X::axis = {1, 0, 0}; const dReal Fixture_dxJointSlider_B2_At_Zero_Axis_Along_X::offset = REAL(3.1); // Move 2nd body offset unit in the X direction // // X-------> X---------> Axis --> // B2 => B2 // TEST_FIXTURE (Fixture_dxJointSlider_B2_At_Zero_Axis_Along_X, test_dJointSetSliderAxisOffset_B2_OffsetUnit) { CHECK_CLOSE (0.0, dJointGetSliderPosition(jId), 1e-4); dBodySetPosition(bId2, offset, 0, 0); CHECK_CLOSE (-offset, dJointGetSliderPosition(jId), 1e-4); } // Move 2nd body offset unit in the opposite X direction // // X-------> X---------> Axis --> // B2 => B2 // TEST_FIXTURE (Fixture_dxJointSlider_B2_At_Zero_Axis_Along_X, test_dJointSetSliderAxisOffset_B2_Minus_OffsetUnit) { CHECK_CLOSE (0.0, dJointGetSliderPosition(jId), 1e-4); dBodySetPosition(bId2, -offset, 0, 0); CHECK_CLOSE (offset, dJointGetSliderPosition(jId), 1e-4); } // Only body 2 // The body are positionned at (0, 0, 0), with no rotation // The joint is a Slider Joint // Axis is in the oppsite X axis // Anchor at (0, 0, 0) struct Fixture_dxJointSlider_B2_At_Zero_Axis_Inverse_of_X { Fixture_dxJointSlider_B2_At_Zero_Axis_Inverse_of_X() { wId = dWorldCreate(); bId2 = dBodyCreate (wId); dBodySetPosition (bId2, 0, 0, 0); jId = dJointCreateSlider (wId, 0); joint = (dxJointSlider*) jId; dJointAttach (jId, NULL, bId2); dJointSetSliderAxis(jId, axis[0], axis[1], axis[2]); } ~Fixture_dxJointSlider_B2_At_Zero_Axis_Inverse_of_X() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId2; dJointID jId; dxJointSlider* joint; static const dVector3 axis; static const dReal offset; }; const dVector3 Fixture_dxJointSlider_B2_At_Zero_Axis_Inverse_of_X::axis = {-1, 0, 0}; const dReal Fixture_dxJointSlider_B2_At_Zero_Axis_Inverse_of_X::offset = REAL(3.1); // Move 2nd body offset unit in the X direction // // X-------> X---------> <--- Axis // B2 => B2 // TEST_FIXTURE (Fixture_dxJointSlider_B2_At_Zero_Axis_Inverse_of_X, test_dJointSetSliderAxisOffset_B2_OffsetUnit) { CHECK_CLOSE (0.0, dJointGetSliderPosition(jId), 1e-4); dBodySetPosition(bId2, offset, 0, 0); CHECK_CLOSE (offset, dJointGetSliderPosition(jId), 1e-4); } // Move 2nd body offset unit in the opposite X direction // // X-------> X---------> <--- Axis // B2 => B2 // TEST_FIXTURE (Fixture_dxJointSlider_B2_At_Zero_Axis_Inverse_of_X, test_dJointSetSliderAxisOffset_B2_Minus_OffsetUnit) { CHECK_CLOSE (0.0, dJointGetSliderPosition(jId), 1e-4); dBodySetPosition(bId2, -offset, 0, 0); CHECK_CLOSE (-offset, dJointGetSliderPosition(jId), 1e-4); } // ========================================================================== // Test Position Rate // ========================================================================== // Apply force on 1st body in the X direction also the Axis direction // // X-------> X---------> Axis --> // B1 F-> => B1 // B2 B2 TEST_FIXTURE (Fixture_dxJointSlider_B1_and_B2_At_Zero_Axis_Along_X, test_dJointSetSliderPositionRate_Force_Along_Axis_on_B1) { CHECK_CLOSE (0.0, dJointGetSliderPosition(jId), 1e-4); CHECK_CLOSE (0.0, dJointGetSliderPositionRate(jId), 1e-4); dBodyAddForce(bId1, 1.0, 0, 0); dWorldQuickStep (wId, 1.0); CHECK_CLOSE (1, dJointGetSliderPositionRate(jId), 1e-4); } // Apply force on 1st body in the inverse X direction // // X-------> X---------> Axis --> // B1 <-F => B1 // B2 B2 TEST_FIXTURE (Fixture_dxJointSlider_B1_and_B2_At_Zero_Axis_Along_X, test_dJointSetSliderPositionRate_Force_Inverse_of_Axis_on_B1) { CHECK_CLOSE (0.0, dJointGetSliderPosition(jId), 1e-4); CHECK_CLOSE (0.0, dJointGetSliderPositionRate(jId), 1e-4); dBodyAddForce(bId1, -1.0, 0, 0); dWorldQuickStep (wId, 1.0); CHECK_CLOSE (-1, dJointGetSliderPositionRate(jId), 1e-4); } // Apply force on 1st body in the X direction also the Axis direction // // X-------> X---------> <-- Axis // B1 F-> => B1 // B2 B2 TEST_FIXTURE (Fixture_dxJointSlider_B1_and_B2_At_Zero_Axis_Inverse_of_X, test_dJointSetSliderPositionRate_Force_Inverse_Axis_on_B1) { CHECK_CLOSE (0.0, dJointGetSliderPosition(jId), 1e-4); CHECK_CLOSE (0.0, dJointGetSliderPositionRate(jId), 1e-4); dBodyAddForce(bId1, 1.0, 0, 0); dWorldQuickStep (wId, 1.0); CHECK_CLOSE (-1, dJointGetSliderPositionRate(jId), 1e-4); } // Apply force on 1st body in the inverse X direction // // X-------> X---------> <-- Axis // B1 <-F => B1 // B2 B2 TEST_FIXTURE (Fixture_dxJointSlider_B1_and_B2_At_Zero_Axis_Inverse_of_X, test_dJointSetSliderPositionRate_Force_Along_of_Axis_on_B1) { CHECK_CLOSE (0.0, dJointGetSliderPosition(jId), 1e-4); CHECK_CLOSE (0.0, dJointGetSliderPositionRate(jId), 1e-4); dBodyAddForce(bId1, -1.0, 0, 0); dWorldQuickStep (wId, 1.0); CHECK_CLOSE (1, dJointGetSliderPositionRate(jId), 1e-4); } // Apply force on 1st body in the X direction also the Axis direction // // X-------> X---------> Axis --> // B1 => B1 // B2 F-> B2 TEST_FIXTURE (Fixture_dxJointSlider_B1_and_B2_At_Zero_Axis_Along_X, test_dJointSetSliderPositionRate_Force_Along_Axis_on_B2) { CHECK_CLOSE (0.0, dJointGetSliderPosition(jId), 1e-4); CHECK_CLOSE (0.0, dJointGetSliderPositionRate(jId), 1e-4); dBodyAddForce(bId2, 1.0, 0, 0); dWorldQuickStep (wId, 1.0); CHECK_CLOSE (-1, dJointGetSliderPositionRate(jId), 1e-4); } // Apply force on 1st body in the inverse X direction // // X-------> X---------> Axis --> // B1 => B1 // B2 <-F B2 TEST_FIXTURE (Fixture_dxJointSlider_B1_and_B2_At_Zero_Axis_Along_X, test_dJointSetSliderPositionRate_Force_Inverse_of_Axis_on_B2) { CHECK_CLOSE (0.0, dJointGetSliderPosition(jId), 1e-4); CHECK_CLOSE (0.0, dJointGetSliderPositionRate(jId), 1e-4); dBodyAddForce(bId2, -1.0, 0, 0); dWorldQuickStep (wId, 1.0); CHECK_CLOSE (1, dJointGetSliderPositionRate(jId), 1e-4); } // Apply force on 1st body in the X direction also the Axis direction // // X-------> X---------> <-- Axis // B1 => B1 // B2 F-> B2 TEST_FIXTURE (Fixture_dxJointSlider_B1_and_B2_At_Zero_Axis_Inverse_of_X, test_dJointSetSliderPositionRate_Force_Inverse_Axis_on_B2) { CHECK_CLOSE (0.0, dJointGetSliderPosition(jId), 1e-4); CHECK_CLOSE (0.0, dJointGetSliderPositionRate(jId), 1e-4); dBodyAddForce(bId2, 1.0, 0, 0); dWorldQuickStep (wId, 1.0); CHECK_CLOSE (1, dJointGetSliderPositionRate(jId), 1e-4); } // Apply force on 1st body in the inverse X direction // // X-------> X---------> <-- Axis // B1 => B1 // B2 <-F B2 TEST_FIXTURE (Fixture_dxJointSlider_B1_and_B2_At_Zero_Axis_Inverse_of_X, test_dJointSetSliderPositionRate_Force_Along_of_Axis_on_B2) { CHECK_CLOSE (0.0, dJointGetSliderPosition(jId), 1e-4); CHECK_CLOSE (0.0, dJointGetSliderPositionRate(jId), 1e-4); dBodyAddForce(bId2, -1.0, 0, 0); dWorldQuickStep (wId, 1.0); CHECK_CLOSE (-1, dJointGetSliderPositionRate(jId), 1e-4); } // Apply force on 1st body in the X direction also the Axis direction // // X-------> X---------> Axis --> // B1 F-> => B1 TEST_FIXTURE (Fixture_dxJointSlider_B1_At_Zero_Axis_Along_X, test_dJointSetSliderPositionRate_Force_Along_Axis_on_B1) { CHECK_CLOSE (0.0, dJointGetSliderPosition(jId), 1e-4); CHECK_CLOSE (0.0, dJointGetSliderPositionRate(jId), 1e-4); dBodyAddForce(bId1, 1.0, 0, 0); dWorldQuickStep (wId, 1.0); CHECK_CLOSE (1, dJointGetSliderPositionRate(jId), 1e-4); } // Apply force on 1st body in the inverse X direction // // X-------> X---------> Axis --> // B1 <-F => B1 TEST_FIXTURE (Fixture_dxJointSlider_B1_At_Zero_Axis_Along_X, test_dJointSetSliderPositionRate_Force_Inverse_of_Axis_on_B1) { CHECK_CLOSE (0.0, dJointGetSliderPosition(jId), 1e-4); CHECK_CLOSE (0.0, dJointGetSliderPositionRate(jId), 1e-4); dBodyAddForce(bId1, -1.0, 0, 0); dWorldQuickStep (wId, 1.0); CHECK_CLOSE (-1, dJointGetSliderPositionRate(jId), 1e-4); } // Apply force on 1st body in the X direction also the Axis direction // // X-------> X---------> <-- Axis // B1 F-> => B1 TEST_FIXTURE (Fixture_dxJointSlider_B1_At_Zero_Axis_Inverse_of_X, test_dJointSetSliderPositionRate_Force_Inverse_Axis_on_B1) { CHECK_CLOSE (0.0, dJointGetSliderPosition(jId), 1e-4); CHECK_CLOSE (0.0, dJointGetSliderPositionRate(jId), 1e-4); dBodyAddForce(bId1, 1.0, 0, 0); dWorldQuickStep (wId, 1.0); CHECK_CLOSE (-1, dJointGetSliderPositionRate(jId), 1e-4); } // Apply force on 1st body in the inverse X direction // // X-------> X---------> <-- Axis // B1 <-F => B1 TEST_FIXTURE (Fixture_dxJointSlider_B1_At_Zero_Axis_Inverse_of_X, test_dJointSetSliderPositionRate_Force_Along_of_Axis_on_B1) { CHECK_CLOSE (0.0, dJointGetSliderPosition(jId), 1e-4); CHECK_CLOSE (0.0, dJointGetSliderPositionRate(jId), 1e-4); dBodyAddForce(bId1, -1.0, 0, 0); dWorldQuickStep (wId, 1.0); CHECK_CLOSE (1, dJointGetSliderPositionRate(jId), 1e-4); } // Apply force on body 2 in the X direction also the Axis direction // // X-------> X---------> Axis --> // B2 F-> B2 TEST_FIXTURE (Fixture_dxJointSlider_B2_At_Zero_Axis_Along_X, test_dJointSetSliderPositionRate_Force_Along_Axis_on_B2) { CHECK_CLOSE (0.0, dJointGetSliderPosition(jId), 1e-4); CHECK_CLOSE (0.0, dJointGetSliderPositionRate(jId), 1e-4); dBodyAddForce(bId2, 1.0, 0, 0); dWorldQuickStep (wId, 1.0); CHECK_CLOSE (-1, dJointGetSliderPositionRate(jId), 1e-4); } // Apply force on body 2 in the inverse X direction // // X-------> X---------> Axis --> // B2 <-F B2 TEST_FIXTURE (Fixture_dxJointSlider_B2_At_Zero_Axis_Along_X, test_dJointSetSliderPositionRate_Force_Inverse_of_Axis_on_B2) { CHECK_CLOSE (0.0, dJointGetSliderPosition(jId), 1e-4); CHECK_CLOSE (0.0, dJointGetSliderPositionRate(jId), 1e-4); dBodyAddForce(bId2, -1.0, 0, 0); dWorldQuickStep (wId, 1.0); CHECK_CLOSE (1, dJointGetSliderPositionRate(jId), 1e-4); } // Apply force on body 2 in the X direction also the Axis direction // // X-------> X---------> <-- Axis // B2 F-> B2 TEST_FIXTURE (Fixture_dxJointSlider_B2_At_Zero_Axis_Inverse_of_X, test_dJointSetSliderPositionRate_Force_Inverse_Axis_on_B2) { CHECK_CLOSE (0.0, dJointGetSliderPosition(jId), 1e-4); CHECK_CLOSE (0.0, dJointGetSliderPositionRate(jId), 1e-4); dBodyAddForce(bId2, 1.0, 0, 0); dWorldQuickStep (wId, 1.0); CHECK_CLOSE (1, dJointGetSliderPositionRate(jId), 1e-4); } // Apply force on body 2 in the inverse X direction // // X-------> X---------> <-- Axis // B2 <-F B2 TEST_FIXTURE (Fixture_dxJointSlider_B2_At_Zero_Axis_Inverse_of_X, test_dJointSetSliderPositionRate_Force_Along_of_Axis_on_B2) { CHECK_CLOSE (0.0, dJointGetSliderPosition(jId), 1e-4); CHECK_CLOSE (0.0, dJointGetSliderPositionRate(jId), 1e-4); dBodyAddForce(bId2, -1.0, 0, 0); dWorldQuickStep (wId, 1.0); CHECK_CLOSE (-1, dJointGetSliderPositionRate(jId), 1e-4); } // Create 2 bodies attached by a Slider joint // Axis is along the X axis (Default value // Anchor at (0, 0, 0) (Default value) // // ^Y // | // | // | // | // Body1 | Body2 // * Z-----*->x struct dxJointSlider_Test_Initialization { dxJointSlider_Test_Initialization() { wId = dWorldCreate(); // Remove gravity to have the only force be the force of the joint dWorldSetGravity(wId, 0,0,0); for (int j=0; j<2; ++j) { bId[j][0] = dBodyCreate (wId); dBodySetPosition (bId[j][0], -1, -2, -3); bId[j][1] = dBodyCreate (wId); dBodySetPosition (bId[j][1], 11, 22, 33); dMatrix3 R; dVector3 axis; // Random axis axis[0] = REAL(0.53); axis[1] = -REAL(0.71); axis[2] = REAL(0.43); dNormalize3(axis); dRFromAxisAndAngle (R, axis[0], axis[1], axis[2], REAL(0.47123)); // 27deg dBodySetRotation (bId[j][0], R); axis[0] = REAL(1.2); axis[1] = REAL(0.87); axis[2] = -REAL(0.33); dNormalize3(axis); dRFromAxisAndAngle (R, axis[0], axis[1], axis[2], REAL(0.47123)); // 27deg dBodySetRotation (bId[j][1], R); jId[j] = dJointCreateSlider (wId, 0); dJointAttach (jId[j], bId[j][0], bId[j][1]); } } ~dxJointSlider_Test_Initialization() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId[2][2]; dJointID jId[2]; }; // Test if setting a Slider joint with its default values // will behave the same as a default Slider joint TEST_FIXTURE (dxJointSlider_Test_Initialization, test_Slider_Initialization) { using namespace std; dVector3 axis; dJointGetSliderAxis(jId[1], axis); dJointSetSliderAxis(jId[1], axis[0], axis[1], axis[2]); CHECK_CLOSE (dJointGetSliderPosition(jId[0]), dJointGetSliderPosition(jId[1]), 1e-6); for (int b=0; b<2; ++b) { // Compare body b of the first joint with its equivalent on the // second joint const dReal *qA = dBodyGetQuaternion(bId[0][b]); const dReal *qB = dBodyGetQuaternion(bId[1][b]); CHECK_CLOSE (qA[0], qB[0], 1e-6); CHECK_CLOSE (qA[1], qB[1], 1e-6); CHECK_CLOSE (qA[2], qB[2], 1e-6); CHECK_CLOSE (qA[3], qB[3], 1e-6); } dWorldStep (wId,0.5); dWorldStep (wId,0.5); dWorldStep (wId,0.5); dWorldStep (wId,0.5); for (int b=0; b<2; ++b) { // Compare body b of the first joint with its equivalent on the // second joint const dReal *qA = dBodyGetQuaternion(bId[0][b]); const dReal *qB = dBodyGetQuaternion(bId[1][b]); CHECK_CLOSE (qA[0], qB[0], 1e-6); CHECK_CLOSE (qA[1], qB[1], 1e-6); CHECK_CLOSE (qA[2], qB[2], 1e-6); CHECK_CLOSE (qA[3], qB[3], 1e-6); const dReal *posA = dBodyGetPosition(bId[0][b]); const dReal *posB = dBodyGetPosition(bId[1][b]); CHECK_CLOSE (posA[0], posB[0], 1e-6); CHECK_CLOSE (posA[1], posB[1], 1e-6); CHECK_CLOSE (posA[2], posB[2], 1e-6); CHECK_CLOSE (posA[3], posB[3], 1e-6); } } // Compare Only body 1 to 2 bodies with one fixed. // // The body are positionned at (0, 0, 0), with no rotation // The joint is a Slider Joint // Axis is along the X axis // Anchor at (0, 0, 0) struct Fixture_dxJointSlider_Compare_Body_At_Zero_Axis_Along_X { Fixture_dxJointSlider_Compare_Body_At_Zero_Axis_Along_X() { wId = dWorldCreate(); bId1_12 = dBodyCreate (wId); dBodySetPosition (bId1_12, 0, 0, 0); bId2_12 = dBodyCreate (wId); dBodySetPosition (bId2_12, 0, 0, 0); // The force will be added in the function since it is not // always on the same body jId_12 = dJointCreateSlider (wId, 0); dJointAttach(jId_12, bId1_12, bId2_12); fixed = dJointCreateFixed (wId, 0); bId = dBodyCreate (wId); dBodySetPosition (bId, 0, 0, 0); dBodyAddForce (bId, 4, 0, 0); jId = dJointCreateSlider (wId, 0); } ~Fixture_dxJointSlider_Compare_Body_At_Zero_Axis_Along_X() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId1_12; dBodyID bId2_12; dJointID jId_12; // Joint with 2 bodies dJointID fixed; dBodyID bId; dJointID jId; // Joint with one body }; // This test compare the result of a slider with 2 bodies where body body 2 is // fixed to the world to a slider with only one body at position 1. // // Test the limits [-1, 0.25] when only one body at is attached to the joint // using dJointAttache(jId, bId, 0); // TEST_FIXTURE(Fixture_dxJointSlider_Compare_Body_At_Zero_Axis_Along_X, test_Limit_minus1_025_One_Body_on_left) { dBodyAddForce (bId1_12, 4, 0, 0); dJointAttach(jId_12, bId1_12, bId2_12); dJointSetSliderParam(jId_12, dParamLoStop, -1); dJointSetSliderParam(jId_12, dParamHiStop, 0.25); dJointAttach(fixed, 0, bId2_12); dJointSetFixed(fixed); dJointAttach(jId, bId, 0); dJointSetSliderParam(jId, dParamLoStop, -1); dJointSetSliderParam(jId, dParamHiStop, 0.25); for (int i=0; i<50; ++i) dWorldStep(wId, 1.0); const dReal *pos1_12 = dBodyGetPosition(bId1_12); const dReal *pos = dBodyGetPosition(bId); CHECK_CLOSE (pos[0], pos1_12[0], 1e-2); CHECK_CLOSE (pos[1], pos1_12[1], 1e-2); CHECK_CLOSE (pos[2], pos1_12[2], 1e-2); } // This test compare the result of a slider with 2 bodies where body body 1 is // fixed to the world to a slider with only one body at position 2. // // Test the limits [-1, 0.25] when only one body at is attached to the joint // using dJointAttache(jId, 0, bId); // TEST_FIXTURE(Fixture_dxJointSlider_Compare_Body_At_Zero_Axis_Along_X, test_Limit_minus1_025_One_Body_on_right) { dBodyAddForce (bId2_12, 4, 0, 0); dJointAttach(jId_12, bId1_12, bId2_12); dJointSetSliderParam(jId_12, dParamLoStop, -1); dJointSetSliderParam(jId_12, dParamHiStop, 0.25); dJointAttach(fixed, bId1_12, 0); dJointSetFixed(fixed); dJointAttach(jId, 0, bId); dJointSetSliderParam(jId, dParamLoStop, -1); dJointSetSliderParam(jId, dParamHiStop, 0.25); for (int i=0; i<50; ++i) { dWorldStep(wId, 1.0); } const dReal *pos2_12 = dBodyGetPosition(bId2_12); const dReal *pos = dBodyGetPosition(bId); CHECK_CLOSE (pos[0], pos2_12[0], 1e-2); CHECK_CLOSE (pos[1], pos2_12[1], 1e-2); CHECK_CLOSE (pos[2], pos2_12[2], 1e-2); } // This test compare the result of a slider with 2 bodies where body body 2 is // fixed to the world to a slider with only one body at position 1. // // Test the limits [0, 0] when only one body at is attached to the joint // using dJointAttache(jId, bId, 0); // // The body should not move since their is no room between the two limits // TEST_FIXTURE(Fixture_dxJointSlider_Compare_Body_At_Zero_Axis_Along_X, test_Limit_0_0_One_Body_on_left) { dBodyAddForce (bId1_12, 4, 0, 0); dJointAttach(jId_12, bId1_12, bId2_12); dJointSetSliderParam(jId_12, dParamLoStop, 0); dJointSetSliderParam(jId_12, dParamHiStop, 0); dJointAttach(fixed, 0, bId2_12); dJointSetFixed(fixed); dJointAttach(jId, bId, 0); dJointSetSliderParam(jId, dParamLoStop, 0); dJointSetSliderParam(jId, dParamHiStop, 0); for (int i=0; i<500; ++i) dWorldStep(wId, 1.0); const dReal *pos1_12 = dBodyGetPosition(bId1_12); const dReal *pos = dBodyGetPosition(bId); CHECK_CLOSE (pos[0], pos1_12[0], 1e-4); CHECK_CLOSE (pos[1], pos1_12[1], 1e-4); CHECK_CLOSE (pos[2], pos1_12[2], 1e-4); CHECK_CLOSE (pos[0], 0, 1e-4); CHECK_CLOSE (pos[1], 0, 1e-4); CHECK_CLOSE (pos[2], 0, 1e-4); } // This test compare the result of a slider with 2 bodies where body body 1 is // fixed to the world to a slider with only one body at position 2. // // Test the limits [0, 0] when only one body at is attached to the joint // using dJointAttache(jId, 0, bId); // // The body should not move since their is no room between the two limits // TEST_FIXTURE(Fixture_dxJointSlider_Compare_Body_At_Zero_Axis_Along_X, test_Limit_0_0_One_Body_on_right) { dBodyAddForce (bId2_12, 4, 0, 0); dJointAttach(jId_12, bId1_12, bId2_12); dJointSetSliderParam(jId_12, dParamLoStop, 0); dJointSetSliderParam(jId_12, dParamHiStop, 0); dJointAttach(fixed, bId1_12, 0); dJointSetFixed(fixed); dJointAttach(jId, 0, bId); dJointSetSliderParam(jId, dParamLoStop, 0); dJointSetSliderParam(jId, dParamHiStop, 0); for (int i=0; i<500; ++i) dWorldStep(wId, 1.0); const dReal *pos2_12 = dBodyGetPosition(bId2_12); const dReal *pos = dBodyGetPosition(bId); CHECK_CLOSE (pos[0], pos2_12[0], 1e-4); CHECK_CLOSE (pos[1], pos2_12[1], 1e-4); CHECK_CLOSE (pos[2], pos2_12[2], 1e-4); CHECK_CLOSE (pos[0], 0, 1e-4); CHECK_CLOSE (pos[1], 0, 1e-4); CHECK_CLOSE (pos[2], 0, 1e-4); } } // End of SUITE TestdxJointSlider ode-0.16/tests/joints/amotor.cpp0000664000175200017520000002656013403272463013630 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ //234567890123456789012345678901234567890123456789012345678901234567890123456789 // 1 2 3 4 5 6 7 //////////////////////////////////////////////////////////////////////////////// // This file create unit test for some of the functions found in: // ode/src/joinst/fixed.cpp // // //////////////////////////////////////////////////////////////////////////////// #include #include #include "config.h" #include "../../ode/src/joints/amotor.h" const dReal tol = 1e-5; SUITE (TestdxJointAMotor) { struct FixtureBase { dWorldID world; dBodyID body; dJointID joint; FixtureBase() { world = dWorldCreate(); body = dBodyCreate(world); joint = dJointCreateAMotor(world, 0); } ~FixtureBase() { dJointDestroy(joint); dBodyDestroy(body); dWorldDestroy(world); } }; struct FixtureXUser: FixtureBase { FixtureXUser() { // body only allowed to rotate around X axis dBodySetFiniteRotationMode(body, 1); dBodySetFiniteRotationAxis(body, 1, 0, 0); dJointAttach(joint, body, 0); dJointSetAMotorNumAxes(joint, 2); dJointSetAMotorAxis(joint, 0, 2, 0, 1, 0); dJointSetAMotorAxis(joint, 1, 2, 0, 0, 1); dJointSetAMotorParam(joint, dParamVel, 0); dJointSetAMotorParam(joint, dParamFMax, dInfinity); dJointSetAMotorParam(joint, dParamVel2, 0); dJointSetAMotorParam(joint, dParamFMax2, dInfinity); } }; TEST_FIXTURE(FixtureXUser, rotate_x) { const dReal h = 1; const dReal v = 1; dMatrix3 identity = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0}; dBodySetRotation(body, identity); dBodySetAngularVel(body, v, 0, 0); dWorldQuickStep(world, h); const dReal* rot = dBodyGetRotation(body); CHECK_CLOSE(1, rot[0], tol); CHECK_CLOSE(0, rot[4], tol); CHECK_CLOSE(0, rot[8], tol); CHECK_CLOSE(0, rot[1], tol); CHECK_CLOSE(dCos(v*h), rot[5], tol); CHECK_CLOSE(dSin(v*h), rot[9], tol); CHECK_CLOSE(0, rot[2], tol); CHECK_CLOSE(-dSin(v*h), rot[6], tol); CHECK_CLOSE( dCos(v*h), rot[10], tol); } TEST_FIXTURE(FixtureXUser, rotate_yz) { const dReal h = 1; const dReal v = 1; dMatrix3 identity = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0}; dBodySetRotation(body, identity); dVector3 axis_y; dJointGetAMotorAxis(joint, 0, axis_y); CHECK_CLOSE(0, axis_y[0], tol); CHECK_CLOSE(1, axis_y[1], tol); CHECK_CLOSE(0, axis_y[2], tol); dVector3 axis_z; dJointGetAMotorAxis(joint, 1, axis_z); CHECK_CLOSE(0, axis_z[0], tol); CHECK_CLOSE(0, axis_z[1], tol); CHECK_CLOSE(1, axis_z[2], tol); dBodySetAngularVel(body, 0, v, v); dWorldStep(world, h); const dReal* rot = dBodyGetRotation(body); CHECK_CLOSE(1, rot[0], tol); CHECK_CLOSE(0, rot[4], tol); CHECK_CLOSE(0, rot[8], tol); CHECK_CLOSE(0, rot[1], tol); CHECK_CLOSE(1, rot[5], tol); CHECK_CLOSE(0, rot[9], tol); CHECK_CLOSE(0, rot[2], tol); CHECK_CLOSE(0, rot[6], tol); CHECK_CLOSE(1, rot[10], tol); } TEST_FIXTURE(FixtureBase, sanity_check) { dMatrix3 R; dRFromAxisAndAngle(R, 1, 1, 1, 10*M_PI/180); dBodySetRotation(body, R); dVector3 res; dJointAttach(joint, body, 0); dJointSetAMotorNumAxes(joint, 3); CHECK_EQUAL(3, dJointGetAMotorNumAxes(joint)); // axes relative to world dJointSetAMotorAxis(joint, 0, 0, 1, 0, 0); dJointGetAMotorAxis(joint, 0, res); CHECK_EQUAL(0, dJointGetAMotorAxisRel(joint, 0)); CHECK_CLOSE(1, res[0], tol); CHECK_CLOSE(0, res[1], tol); CHECK_CLOSE(0, res[2], tol); dJointSetAMotorAxis(joint, 1, 0, 0, 1, 0); dJointGetAMotorAxis(joint, 1, res); CHECK_EQUAL(0, dJointGetAMotorAxisRel(joint, 1)); CHECK_CLOSE(0, res[0], tol); CHECK_CLOSE(1, res[1], tol); CHECK_CLOSE(0, res[2], tol); dJointSetAMotorAxis(joint, 2, 0, 0, 0, 1); dJointGetAMotorAxis(joint, 2, res); CHECK_EQUAL(0, dJointGetAMotorAxisRel(joint, 2)); CHECK_CLOSE(0, res[0], tol); CHECK_CLOSE(0, res[1], tol); CHECK_CLOSE(1, res[2], tol); // axes relative to body1 dJointSetAMotorAxis(joint, 0, 1, 1, 0, 0); dJointGetAMotorAxis(joint, 0, res); CHECK_EQUAL(1, dJointGetAMotorAxisRel(joint, 0)); CHECK_CLOSE(1, res[0], tol); CHECK_CLOSE(0, res[1], tol); CHECK_CLOSE(0, res[2], tol); dJointSetAMotorAxis(joint, 1, 1, 0, 1, 0); dJointGetAMotorAxis(joint, 1, res); CHECK_EQUAL(1, dJointGetAMotorAxisRel(joint, 1)); CHECK_CLOSE(0, res[0], tol); CHECK_CLOSE(1, res[1], tol); CHECK_CLOSE(0, res[2], tol); dJointSetAMotorAxis(joint, 2, 1, 0, 0, 1); dJointGetAMotorAxis(joint, 2, res); CHECK_EQUAL(1, dJointGetAMotorAxisRel(joint, 2)); CHECK_CLOSE(0, res[0], tol); CHECK_CLOSE(0, res[1], tol); CHECK_CLOSE(1, res[2], tol); // axes relative to body2 dJointSetAMotorAxis(joint, 0, 2, 1, 0, 0); dJointGetAMotorAxis(joint, 0, res); CHECK_EQUAL(2, dJointGetAMotorAxisRel(joint, 0)); CHECK_CLOSE(1, res[0], tol); CHECK_CLOSE(0, res[1], tol); CHECK_CLOSE(0, res[2], tol); dJointSetAMotorAxis(joint, 1, 2, 0, 1, 0); dJointGetAMotorAxis(joint, 1, res); CHECK_EQUAL(2, dJointGetAMotorAxisRel(joint, 1)); CHECK_CLOSE(0, res[0], tol); CHECK_CLOSE(1, res[1], tol); CHECK_CLOSE(0, res[2], tol); dJointSetAMotorAxis(joint, 2, 2, 0, 0, 1); dJointGetAMotorAxis(joint, 2, res); CHECK_EQUAL(2, dJointGetAMotorAxisRel(joint, 2)); CHECK_CLOSE(0, res[0], tol); CHECK_CLOSE(0, res[1], tol); CHECK_CLOSE(1, res[2], tol); // reverse attachment to force internal reversal dJointAttach(joint, 0, body); // axes relative to world dJointSetAMotorAxis(joint, 0, 0, 1, 0, 0); dJointGetAMotorAxis(joint, 0, res); CHECK_EQUAL(0, dJointGetAMotorAxisRel(joint, 0)); CHECK_CLOSE(1, res[0], tol); CHECK_CLOSE(0, res[1], tol); CHECK_CLOSE(0, res[2], tol); dJointSetAMotorAxis(joint, 1, 0, 0, 1, 0); dJointGetAMotorAxis(joint, 1, res); CHECK_EQUAL(0, dJointGetAMotorAxisRel(joint, 1)); CHECK_CLOSE(0, res[0], tol); CHECK_CLOSE(1, res[1], tol); CHECK_CLOSE(0, res[2], tol); dJointSetAMotorAxis(joint, 2, 0, 0, 0, 1); dJointGetAMotorAxis(joint, 2, res); CHECK_EQUAL(0, dJointGetAMotorAxisRel(joint, 2)); CHECK_CLOSE(0, res[0], tol); CHECK_CLOSE(0, res[1], tol); CHECK_CLOSE(1, res[2], tol); // axes relative to body1 dJointSetAMotorAxis(joint, 0, 1, 1, 0, 0); dJointGetAMotorAxis(joint, 0, res); CHECK_EQUAL(1, dJointGetAMotorAxisRel(joint, 0)); CHECK_CLOSE(1, res[0], tol); CHECK_CLOSE(0, res[1], tol); CHECK_CLOSE(0, res[2], tol); dJointSetAMotorAxis(joint, 1, 1, 0, 1, 0); dJointGetAMotorAxis(joint, 1, res); CHECK_EQUAL(1, dJointGetAMotorAxisRel(joint, 1)); CHECK_CLOSE(0, res[0], tol); CHECK_CLOSE(1, res[1], tol); CHECK_CLOSE(0, res[2], tol); dJointSetAMotorAxis(joint, 2, 1, 0, 0, 1); dJointGetAMotorAxis(joint, 2, res); CHECK_EQUAL(1, dJointGetAMotorAxisRel(joint, 2)); CHECK_CLOSE(0, res[0], tol); CHECK_CLOSE(0, res[1], tol); CHECK_CLOSE(1, res[2], tol); // axes relative to body2 dJointSetAMotorAxis(joint, 0, 2, 1, 0, 0); dJointGetAMotorAxis(joint, 0, res); CHECK_EQUAL(2, dJointGetAMotorAxisRel(joint, 0)); CHECK_CLOSE(1, res[0], tol); CHECK_CLOSE(0, res[1], tol); CHECK_CLOSE(0, res[2], tol); dJointSetAMotorAxis(joint, 1, 2, 0, 1, 0); dJointGetAMotorAxis(joint, 1, res); CHECK_EQUAL(2, dJointGetAMotorAxisRel(joint, 1)); CHECK_CLOSE(0, res[0], tol); CHECK_CLOSE(1, res[1], tol); CHECK_CLOSE(0, res[2], tol); dJointSetAMotorAxis(joint, 2, 2, 0, 0, 1); dJointGetAMotorAxis(joint, 2, res); CHECK_EQUAL(2, dJointGetAMotorAxisRel(joint, 2)); CHECK_CLOSE(0, res[0], tol); CHECK_CLOSE(0, res[1], tol); CHECK_CLOSE(1, res[2], tol); } struct FixtureXEuler : FixtureBase { FixtureXEuler() { // body only allowed to rotate around X axis dJointAttach(joint, 0, body); dJointSetAMotorMode(joint, dAMotorEuler); dJointSetAMotorAxis(joint, 0, 0, 1, 0, 0); dJointSetAMotorAxis(joint, 2, 0, 0, 0, 1); } }; TEST_FIXTURE(FixtureXEuler, check_axes) { // test patch #181 bug fix dVector3 axis_x; dJointGetAMotorAxis(joint, 0, axis_x); CHECK_CLOSE(1, axis_x[0], tol); CHECK_CLOSE(0, axis_x[1], tol); CHECK_CLOSE(0, axis_x[2], tol); dVector3 axis_y; dJointGetAMotorAxis(joint, 1, axis_y); CHECK_CLOSE(0, axis_y[0], tol); CHECK_CLOSE(1, axis_y[1], tol); CHECK_CLOSE(0, axis_y[2], tol); dVector3 axis_z; dJointGetAMotorAxis(joint, 2, axis_z); CHECK_CLOSE(0, axis_z[0], tol); CHECK_CLOSE(0, axis_z[1], tol); CHECK_CLOSE(1, axis_z[2], tol); } } // End of SUITE TestdxJointAMotor ode-0.16/tests/joints/pu.cpp0000664000175200017520000007040413403272463012747 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ //234567890123456789012345678901234567890123456789012345678901234567890123456789 // 1 2 3 4 5 6 7 //////////////////////////////////////////////////////////////////////////////// // This file create unit test for some of the functions found in: // ode/src/joinst/pu.cpp // // //////////////////////////////////////////////////////////////////////////////// #include #include #include "../../ode/src/config.h" #include "../../ode/src/joints/pu.h" SUITE (TestdxJointPU) { // The 2 bodies are positionned at (0, 0, 0), and (0, 0, 0) // The second body has a rotation of 27deg around X axis. // The joint is a PU Joint // Axis is along the X axis // Anchor at (0, 0, 0) struct Fixture_dxJointPU_B1_and_B2_At_Zero_Axis_Along_X { Fixture_dxJointPU_B1_and_B2_At_Zero_Axis_Along_X() { wId = dWorldCreate(); bId1 = dBodyCreate (wId); dBodySetPosition (bId1, 0, 0, 0); bId2 = dBodyCreate (wId); dBodySetPosition (bId2, 0, 0, 0); dMatrix3 R; dRFromAxisAndAngle (R, 1, 0, 0, REAL(0.47123)); // 27deg dBodySetRotation (bId2, R); jId = dJointCreatePU (wId, 0); joint = (dxJointPU*) jId; dJointAttach (jId, bId1, bId2); } ~Fixture_dxJointPU_B1_and_B2_At_Zero_Axis_Along_X() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId1; dBodyID bId2; dJointID jId; dxJointPU* joint; }; // Test is dJointSetPUAxis and dJointGetPUAxis return same value TEST_FIXTURE (Fixture_dxJointPU_B1_and_B2_At_Zero_Axis_Along_X, test_dJointSetGetPUAxis) { dVector3 axisOrig, axis; dJointGetPUAxis1 (jId, axisOrig); dJointGetPUAxis1 (jId, axis); dJointSetPUAxis1 (jId, axis[0], axis[1], axis[2]); dJointGetPUAxis1 (jId, axis); CHECK_CLOSE (axis[0], axisOrig[0] , 1e-4); CHECK_CLOSE (axis[1], axisOrig[1] , 1e-4); CHECK_CLOSE (axis[2], axisOrig[2] , 1e-4); dJointGetPUAxis2 (jId, axisOrig); dJointGetPUAxis2(jId, axis); dJointSetPUAxis2 (jId, axis[0], axis[1], axis[2]); dJointGetPUAxis2 (jId, axis); CHECK_CLOSE (axis[0], axisOrig[0] , 1e-4); CHECK_CLOSE (axis[1], axisOrig[1] , 1e-4); CHECK_CLOSE (axis[2], axisOrig[2] , 1e-4); dJointGetPUAxis3 (jId, axisOrig); dJointGetPUAxis3(jId, axis); dJointSetPUAxis3 (jId, axis[0], axis[1], axis[2]); dJointGetPUAxis3 (jId, axis); CHECK_CLOSE (axis[0], axisOrig[0] , 1e-4); CHECK_CLOSE (axis[1], axisOrig[1] , 1e-4); CHECK_CLOSE (axis[2], axisOrig[2] , 1e-4); } // The joint is a PU Joint // Default joint value // The two bodies at at (0, 0, 0) struct Fixture_dxJointPU_B1_and_B2_At_Zero { Fixture_dxJointPU_B1_and_B2_At_Zero() { wId = dWorldCreate(); bId1 = dBodyCreate (wId); dBodySetPosition (bId1, 0, 0, 0); bId2 = dBodyCreate (wId); dBodySetPosition (bId2, 0, 0, 0); jId = dJointCreatePU (wId, 0); joint = (dxJointPU*) jId; dJointAttach (jId, bId1, bId2); } ~Fixture_dxJointPU_B1_and_B2_At_Zero() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId1; dBodyID bId2; dJointID jId; dxJointPU* joint; static const dReal offset; }; const dReal Fixture_dxJointPU_B1_and_B2_At_Zero::offset = REAL (3.1); // Move 1st body offset unit in the X direction // // X-------> X---------> Axis --> // B1 => B1 // B2 B2 // // Start with a Offset of offset unit // // X-------> X---------> Axis --> // B1 => B1 // B2 B2 TEST_FIXTURE (Fixture_dxJointPU_B1_and_B2_At_Zero, test_dJointSetPUAxisOffset_B1_3Unit) { CHECK_CLOSE (0.0, dJointGetPUPosition (jId), 1e-4); dBodySetPosition (bId1, offset, 0, 0); CHECK_CLOSE (offset, dJointGetPUPosition (jId), 1e-4); dVector3 axis; dJointGetPUAxisP (jId, axis); dJointSetPUAnchorOffset (jId, 0, 0, 0, offset*axis[0],offset*axis[1],offset*axis[2]); CHECK_CLOSE (offset, dJointGetPUPosition (jId), 1e-4); dBodySetPosition (bId1, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPUPosition (jId), 1e-4); } // Move 1st body offset unit in the opposite X direction // // X-------> X---------> Axis --> // B1 => B1 // B2 B2 // // Start with a Offset of -offset unit // // X-------> X---------> Axis --> // B1 => B1 // B2 B2 TEST_FIXTURE (Fixture_dxJointPU_B1_and_B2_At_Zero, test_dJointSetPUAxisOffset_B1_Minus_3Unit) { CHECK_CLOSE (0.0, dJointGetPUPosition (jId), 1e-4); dBodySetPosition (bId1, -offset, 0, 0); CHECK_CLOSE (-offset, dJointGetPUPosition (jId), 1e-4); dVector3 axis; dJointGetPUAxisP (jId, axis); dJointSetPUAnchorOffset (jId, 0, 0, 0, -offset*axis[0],-offset*axis[1],-offset*axis[2]); CHECK_CLOSE (-offset, dJointGetPUPosition (jId), 1e-4); dBodySetPosition (bId1, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPUPosition (jId), 1e-4); } // Move 2nd body offset unit in the X direction // // X-------> X---------> Axis --> // B1 => B1 // B2 B2 // // Start with a Offset of offset unit // // X-------> X---------> Axis --> // B1 => B1 // B2 B2 TEST_FIXTURE (Fixture_dxJointPU_B1_and_B2_At_Zero, test_dJointSetPUAxisOffset_B2_3Unit) { CHECK_CLOSE (0.0, dJointGetPUPosition (jId), 1e-4); dBodySetPosition (bId2, offset, 0, 0); CHECK_CLOSE (-offset, dJointGetPUPosition (jId), 1e-4); dVector3 axis; dJointGetPUAxisP (jId, axis); dJointSetPUAnchorOffset (jId, 0, 0, 0, -offset*axis[0],-offset*axis[1],-offset*axis[2]); CHECK_CLOSE (-offset, dJointGetPUPosition (jId), 1e-4); dBodySetPosition (bId2, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPUPosition (jId), 1e-4); } // Move 2nd body offset unit in the opposite X direction // // X-------> X---------> Axis --> // B1 => B1 // B2 B2 // // Start with a Offset of -offset unit // // X-------> X---------> Axis --> // B1 => B1 // B2 B2 TEST_FIXTURE (Fixture_dxJointPU_B1_and_B2_At_Zero, test_dJointSetPUAxisOffset_B2_Minus_3Unit) { CHECK_CLOSE (0.0, dJointGetPUPosition (jId), 1e-4); dBodySetPosition (bId2, -offset, 0, 0); CHECK_CLOSE (offset, dJointGetPUPosition (jId), 1e-4); dVector3 axis; dJointGetPUAxisP (jId, axis); dJointSetPUAnchorOffset (jId, 0, 0, 0, offset*axis[0],offset*axis[1],offset*axis[2]); CHECK_CLOSE (offset, dJointGetPUPosition (jId), 1e-4); dBodySetPosition (bId2, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPUPosition (jId), 1e-4); } // Attach only one body at position 1 to the joint dJointAttach (jId, bId, 0) // Move 1st body offset unit in the X direction // // X-------> X---------> Axis --> // B1 => B1 // // Start with a Offset of offset unit // // X-------> X---------> Axis --> // B1 => B1 TEST_FIXTURE (Fixture_dxJointPU_B1_and_B2_At_Zero, test_dJointSetPUAxisOffset_B1_OffsetUnit) { dJointAttach (jId, bId1, 0); CHECK_CLOSE (0.0, dJointGetPUPosition (jId), 1e-4); dBodySetPosition (bId1, offset, 0, 0); CHECK_CLOSE (offset, dJointGetPUPosition (jId), 1e-4); dVector3 axis; dJointGetPUAxisP (jId, axis); dJointSetPUAnchorOffset (jId, 0, 0, 0, offset*axis[0],offset*axis[1],offset*axis[2]); CHECK_CLOSE (offset, dJointGetPUPosition (jId), 1e-4); dBodySetPosition (bId1, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPUPosition (jId), 1e-4); } // Attache only one body at position 1 to the joint dJointAttach (jId, bId, 0) // Move 1st body offset unit in the opposite X direction // // X-------> X---------> Axis --> // B1 => B1 // // Start with a Offset of -offset unit // // X-------> X---------> Axis --> // B1 => B1 TEST_FIXTURE (Fixture_dxJointPU_B1_and_B2_At_Zero, test_dJointSetPUAxisOffset_B1_Minus_OffsetUnit) { dJointAttach (jId, bId1, 0); CHECK_CLOSE (0.0, dJointGetPUPosition (jId), 1e-4); dBodySetPosition (bId1, -offset, 0, 0); CHECK_CLOSE (-offset, dJointGetPUPosition (jId), 1e-4); dVector3 axis; dJointGetPUAxisP (jId, axis); dJointSetPUAnchorOffset (jId, 0, 0, 0, -offset*axis[0],-offset*axis[1],-offset*axis[2]); CHECK_CLOSE (-offset, dJointGetPUPosition (jId), 1e-4); dBodySetPosition (bId1, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPUPosition (jId), 1e-4); } // Attache only one body at position 2 to the joint dJointAttach (jId, 0, bId) // Move 1st body offset unit in the X direction // // X-------> X---------> Axis --> // B2 => B2 // // Start with a Offset of offset unit // // X-------> X---------> Axis --> // B2 => B2 TEST_FIXTURE (Fixture_dxJointPU_B1_and_B2_At_Zero, test_dJointSetPUAxisOffset_B2_OffsetUnit) { dJointAttach (jId, 0, bId2); CHECK_CLOSE (0.0, dJointGetPUPosition (jId), 1e-4); dBodySetPosition (bId2, offset, 0, 0); CHECK_CLOSE (-offset, dJointGetPUPosition (jId), 1e-4); dVector3 axis; dJointGetPUAxisP (jId, axis); dJointSetPUAnchorOffset (jId, 0, 0, 0, -offset*axis[0], -offset*axis[1], -offset*axis[2]); CHECK_CLOSE (-offset, dJointGetPUPosition (jId), 1e-4); dBodySetPosition (bId2, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPUPosition (jId), 1e-4); } // Attache only one body at position 2 to the joint dJointAttach (jId, 0, bId) // Move 1st body offset unit in the opposite X direction // // X-------> X---------> Axis --> // B2 => B2 // // Start with a Offset of -offset unit // // X-------> X---------> Axis --> // B2 => B2 TEST_FIXTURE (Fixture_dxJointPU_B1_and_B2_At_Zero, test_dJointSetPUAxisOffset_B2_Minus_OffsetUnit) { dJointAttach (jId, 0, bId2); CHECK_CLOSE (0.0, dJointGetPUPosition (jId), 1e-4); dBodySetPosition (bId2, -offset, 0, 0); CHECK_CLOSE (offset, dJointGetPUPosition (jId), 1e-4); dVector3 axis; dJointGetPUAxisP (jId, axis); dJointSetPUAnchorOffset (jId, 0, 0, 0, offset*axis[0], offset*axis[1], offset*axis[2]); CHECK_CLOSE (offset, dJointGetPUPosition (jId), 1e-4); dBodySetPosition (bId2, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPUPosition (jId), 1e-4); } // Only one body // The body are positionned at (0, 0, 0), with no rotation // The joint is a PU Joint // Axis is in the oppsite X axis // Anchor at (0, 0, 0) // N.B. By default the body is attached at position 1 on the joint // dJointAttach (jId, bId, 0); struct Fixture_dxJointPU_One_Body_At_Zero_Axis_Inverse_of_X { Fixture_dxJointPU_One_Body_At_Zero_Axis_Inverse_of_X() { wId = dWorldCreate(); bId = dBodyCreate (wId); dBodySetPosition (bId, 0, 0, 0); jId = dJointCreatePU (wId, 0); joint = (dxJointPU*) jId; dJointAttach (jId, bId, NULL); dJointSetPUAxisP (jId, axis[0], axis[1], axis[2]); } ~Fixture_dxJointPU_One_Body_At_Zero_Axis_Inverse_of_X() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId; dJointID jId; dxJointPU* joint; static const dVector3 axis; static const dReal offset; }; const dVector3 Fixture_dxJointPU_One_Body_At_Zero_Axis_Inverse_of_X::axis = { -1, 0, 0 }; const dReal Fixture_dxJointPU_One_Body_At_Zero_Axis_Inverse_of_X::offset = REAL (3.1); // Move 1st body offset unit in the X direction // // X-------> X---------> <--- Axis // B1 => B1 // // Start with a Offset of offset unit // // X-------> X---------> <--- Axis // B1 => B1 TEST_FIXTURE (Fixture_dxJointPU_One_Body_At_Zero_Axis_Inverse_of_X, test_dJointSetPUAxisOffset_B1_At_Position_1_OffsetUnit) { CHECK_CLOSE (0.0, dJointGetPUPosition (jId), 1e-4); dBodySetPosition (bId, offset, 0, 0); CHECK_CLOSE (-offset, dJointGetPUPosition (jId), 1e-4); dJointSetPUAnchorOffset (jId, 0, 0, 0, -offset*axis[0],-offset*axis[1],-offset*axis[2]); CHECK_CLOSE (-offset, dJointGetPUPosition (jId), 1e-4); dBodySetPosition (bId, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPUPosition (jId), 1e-4); } // Move 1st body offset unit in the opposite X direction // // X-------> X---------> <--- Axis // B1 => B1 // // Start with a Offset of -offset unit // // X-------> X---------> <--- Axis // B1 => B1 TEST_FIXTURE (Fixture_dxJointPU_One_Body_At_Zero_Axis_Inverse_of_X, test_dJointSetPUAxisOffset_B1_Minus_OffsetUnit) { CHECK_CLOSE (0.0, dJointGetPUPosition (jId), 1e-4); dBodySetPosition (bId, -offset, 0, 0); CHECK_CLOSE (offset, dJointGetPUPosition (jId), 1e-4); dJointSetPUAnchorOffset (jId, 0, 0, 0, offset*axis[0],offset*axis[1],offset*axis[2]); CHECK_CLOSE (offset, dJointGetPUPosition (jId), 1e-4); dBodySetPosition (bId, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPUPosition (jId), 1e-4); } // Move 1st body offset unit in the X direction // // X-------> X---------> <--- Axis // B2 => B2 // // Start with a Offset of offset unit // // X-------> X---------> <--- Axis // B2 => B2 TEST_FIXTURE (Fixture_dxJointPU_One_Body_At_Zero_Axis_Inverse_of_X, test_dJointSetPUAxisOffset_B2_OffsetUnit) { // By default it is attached to position 1 // Now attach the body at positiojn 2 dJointAttach(jId, 0, bId); CHECK_CLOSE (0.0, dJointGetPUPosition (jId), 1e-4); dBodySetPosition (bId, offset, 0, 0); CHECK_CLOSE (offset, dJointGetPUPosition (jId), 1e-4); dJointSetPUAnchorOffset (jId, 0, 0, 0, offset*axis[0], offset*axis[1], offset*axis[2]); CHECK_CLOSE (offset, dJointGetPUPosition (jId), 1e-4); dBodySetPosition (bId, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPUPosition (jId), 1e-4); } // Move 1st body offset unit in the opposite X direction // // X-------> X---------> <--- Axis // B2 => B2 // // Start with a Offset of -offset unit // // X-------> X---------> <--- Axis // B2 => B2 TEST_FIXTURE (Fixture_dxJointPU_One_Body_At_Zero_Axis_Inverse_of_X, test_dJointSetPUAxisOffset_B2_Minus_OffsetUnit) { // By default it is attached to position 1 // Now attach the body at positiojn 2 dJointAttach(jId, 0, bId); CHECK_CLOSE (0.0, dJointGetPUPosition (jId), 1e-4); dBodySetPosition (bId, -offset, 0, 0); CHECK_CLOSE (-offset, dJointGetPUPosition (jId), 1e-4); dJointSetPUAnchorOffset (jId, 0, 0, 0, -offset*axis[0], -offset*axis[1], -offset*axis[2]); CHECK_CLOSE (-offset, dJointGetPUPosition (jId), 1e-4); dBodySetPosition (bId, 0, 0, 0); CHECK_CLOSE (0.0, dJointGetPUPosition (jId), 1e-4); } // Compare only one body to 2 bodies with one fixed. // // The body are positionned at (0, 0, 0), with no rotation // The joint is a PU Joint with default values struct Fixture_dxJointPU_Compare_One_Body_To_Two_Bodies_At_Zero { Fixture_dxJointPU_Compare_One_Body_To_Two_Bodies_At_Zero() { wId = dWorldCreate(); bId1_12 = dBodyCreate (wId); dBodySetPosition (bId1_12, 0, 0, 0); bId2_12 = dBodyCreate (wId); dBodySetPosition (bId2_12, 0, 0, 0); // The force will be added in the function since it is not // always on the same body jId_12 = dJointCreatePU (wId, 0); dJointAttach(jId_12, bId1_12, bId2_12); fixed = dJointCreateFixed (wId, 0); jId = dJointCreatePU (wId, 0); bId = dBodyCreate (wId); dBodySetPosition (bId, 0, 0, 0); // Linear velocity along the prismatic axis; dVector3 axis; dJointGetPUAxisP(jId_12, axis); dJointSetPUAxisP(jId, axis[0], axis[1], axis[2]); dBodySetLinearVel (bId, magnitude*axis[0], magnitude*axis[1], magnitude*axis[2]); } ~Fixture_dxJointPU_Compare_One_Body_To_Two_Bodies_At_Zero() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId1_12; dBodyID bId2_12; dJointID jId_12; // Joint with 2 bodies dJointID fixed; dBodyID bId; dJointID jId; // Joint with one body static const dReal magnitude; }; const dReal Fixture_dxJointPU_Compare_One_Body_To_Two_Bodies_At_Zero::magnitude = REAL (4.27); TEST_FIXTURE (Fixture_dxJointPU_Compare_One_Body_To_Two_Bodies_At_Zero, test_dJointSetPUPositionRate_Only_B1) { // Linear velocity along the prismatic axis; dVector3 axis; dJointGetPUAxisP(jId_12, axis); dBodySetLinearVel (bId1_12, magnitude*axis[0], magnitude*axis[1], magnitude*axis[2]); dJointAttach(jId_12, bId1_12, bId2_12); dJointAttach(fixed, 0, bId2_12); dJointSetFixed(fixed); dJointAttach(jId, bId, 0); CHECK_CLOSE(dJointGetPUPositionRate(jId_12), dJointGetPUPositionRate(jId), 1e-2); } TEST_FIXTURE (Fixture_dxJointPU_Compare_One_Body_To_Two_Bodies_At_Zero, test_dJointSetPUPositionRate_Only_B2) { // Linear velocity along the prismatic axis; dVector3 axis; dJointGetPUAxisP(jId_12, axis); dBodySetLinearVel (bId2_12, magnitude*axis[0], magnitude*axis[1], magnitude*axis[2]); dJointAttach(jId_12, bId1_12, bId2_12); dJointAttach(fixed, bId1_12, 0); dJointSetFixed(fixed); dJointAttach(jId, 0, bId); CHECK_CLOSE(dJointGetPUPositionRate(jId_12), dJointGetPUPositionRate(jId), 1e-2); } // This test compare the result of a pu joint with 2 bodies where body body 2 is // fixed to the world to a pu joint with only one body at position 1. // // Test the limits [-1, 0.25] when only one body at is attached to the joint // using dJointAttache(jId, bId, 0); // TEST_FIXTURE(Fixture_dxJointPU_Compare_One_Body_To_Two_Bodies_At_Zero, test_Limit_minus1_025_One_Body_on_left) { dVector3 axis; dJointGetPUAxisP(jId_12, axis); dJointSetPUAxisP(jId, axis[0], axis[1], axis[2]); dBodySetLinearVel (bId1_12, magnitude*axis[0], magnitude*axis[1], magnitude*axis[2]); dJointAttach(jId_12, bId1_12, bId2_12); dJointSetPUParam(jId_12, dParamLoStop3, -1); dJointSetPUParam(jId_12, dParamHiStop3, 0.25); dJointAttach(fixed, 0, bId2_12); dJointSetFixed(fixed); dJointAttach(jId, bId, 0); dJointSetPUParam(jId, dParamLoStop3, -1); dJointSetPUParam(jId, dParamHiStop3, 0.25); for (int i=0; i<50; ++i) dWorldStep(wId, 1.0); const dReal *pos1_12 = dBodyGetPosition(bId1_12); const dReal *pos = dBodyGetPosition(bId); CHECK_CLOSE (pos1_12[0], pos[0], 1e-2); CHECK_CLOSE (pos1_12[1], pos[1], 1e-2); CHECK_CLOSE (pos1_12[2], pos[2], 1e-2); const dReal *q1_12 = dBodyGetQuaternion(bId1_12); const dReal *q = dBodyGetQuaternion(bId); CHECK_CLOSE (q1_12[0], q[0], 1e-4); CHECK_CLOSE (q1_12[1], q[1], 1e-4); CHECK_CLOSE (q1_12[2], q[2], 1e-4); CHECK_CLOSE (q1_12[3], q[3], 1e-4); // Should be different than zero CHECK( dJointGetPUPosition(jId_12) ); CHECK( dJointGetPUPosition(jId) ); CHECK( dJointGetPUPositionRate(jId_12) ); CHECK( dJointGetPUPositionRate(jId) ); } // This test compare the result of a pu joint with 2 bodies where body body 1 is // fixed to the world to a pu joint with only one body at position 2. // // Test the limits [-1, 0.25] when only one body at is attached to the joint // using dJointAttache(jId, 0, bId); // TEST_FIXTURE(Fixture_dxJointPU_Compare_One_Body_To_Two_Bodies_At_Zero, test_Limit_minus1_025_One_Body_on_right) { dVector3 axis; dJointGetPUAxisP(jId_12, axis); dJointSetPUAxisP(jId, axis[0], axis[1], axis[2]); dBodySetLinearVel (bId2_12, magnitude*axis[0], magnitude*axis[1], magnitude*axis[2]); dJointAttach(jId_12, bId1_12, bId2_12); dJointSetPUParam(jId_12, dParamLoStop3, -1); dJointSetPUParam(jId_12, dParamHiStop3, 0.25); dJointAttach(fixed, bId1_12, 0); dJointSetFixed(fixed); dJointAttach(jId, 0, bId); dJointSetPUParam(jId, dParamLoStop3, -1); dJointSetPUParam(jId, dParamHiStop3, 0.25); for (int i=0; i<50; ++i) dWorldStep(wId, 1.0); const dReal *pos2_12 = dBodyGetPosition(bId2_12); const dReal *pos = dBodyGetPosition(bId); CHECK_CLOSE (pos2_12[0], pos[0], 1e-2); CHECK_CLOSE (pos2_12[1], pos[1], 1e-2); CHECK_CLOSE (pos2_12[2], pos[2], 1e-2); const dReal *q2_12 = dBodyGetQuaternion(bId2_12); const dReal *q = dBodyGetQuaternion(bId); CHECK_CLOSE (q2_12[0], q[0], 1e-4); CHECK_CLOSE (q2_12[1], q[1], 1e-4); CHECK_CLOSE (q2_12[2], q[2], 1e-4); CHECK_CLOSE (q2_12[3], q[3], 1e-4); // Should be different than zero CHECK( dJointGetPUPosition(jId_12) ); CHECK( dJointGetPUPosition(jId) ); CHECK( dJointGetPUPositionRate(jId_12) ); CHECK( dJointGetPUPositionRate(jId) ); } // This test compare the result of a pu joint with 2 bodies where body 2 is // fixed to the world to a pu joint with only one body at position 1. // // Test the limits [0, 0] when only one body at is attached to the joint // using dJointAttache(jId, bId, 0); // // The body should not move since their is no room between the two limits // TEST_FIXTURE(Fixture_dxJointPU_Compare_One_Body_To_Two_Bodies_At_Zero, test_Limit_0_0_One_Body_on_left) { dVector3 axis; dJointGetPUAxisP(jId_12, axis); dJointSetPUAxisP(jId, axis[0], axis[1], axis[2]); dBodySetLinearVel (bId1_12, magnitude*axis[0], magnitude*axis[1], magnitude*axis[2]); dJointAttach(jId_12, bId1_12, bId2_12); dJointSetPUParam(jId_12, dParamLoStop3, 0); dJointSetPUParam(jId_12, dParamHiStop3, 0); dJointAttach(fixed, 0, bId2_12); dJointSetFixed(fixed); dJointAttach(jId, bId, 0); dJointSetPUParam(jId, dParamLoStop3, 0); dJointSetPUParam(jId, dParamHiStop3, 0); for (int i=0; i<500; ++i) dWorldStep(wId, 1.0); const dReal *pos1_12 = dBodyGetPosition(bId1_12); const dReal *pos = dBodyGetPosition(bId); CHECK_CLOSE (pos1_12[0], pos[0], 1e-4); CHECK_CLOSE (pos1_12[1], pos[1], 1e-4); CHECK_CLOSE (pos1_12[2], pos[2], 1e-4); CHECK_CLOSE (0, pos[0], 1e-4); CHECK_CLOSE (0, pos[1], 1e-4); CHECK_CLOSE (0, pos[2], 1e-4); const dReal *q1_12 = dBodyGetQuaternion(bId1_12); const dReal *q = dBodyGetQuaternion(bId); CHECK_CLOSE (q1_12[0], q[0], 1e-4); CHECK_CLOSE (q1_12[1], q[1], 1e-4); CHECK_CLOSE (q1_12[2], q[2], 1e-4); CHECK_CLOSE (q1_12[3], q[3], 1e-4); } // This test compare the result of a pu joint with 2 bodies where body body 1 is // fixed to the world to a pu joint with only one body at position 2. // // Test the limits [0, 0] when only one body at is attached to the joint // using dJointAttache(jId, 0, bId); // // The body should not move since their is no room between the two limits // TEST_FIXTURE(Fixture_dxJointPU_Compare_One_Body_To_Two_Bodies_At_Zero, test_Limit_0_0_One_Body_on_right) { dVector3 axis; dJointGetPUAxisP(jId_12, axis); dJointSetPUAxisP(jId, axis[0], axis[1], axis[2]); dBodySetLinearVel (bId2_12, magnitude*axis[0], magnitude*axis[1], magnitude*axis[2]); dJointAttach(jId_12, bId1_12, bId2_12); dJointSetPUParam(jId_12, dParamLoStop3, 0); dJointSetPUParam(jId_12, dParamHiStop3, 0); dJointAttach(fixed, bId1_12, 0); dJointSetFixed(fixed); dJointAttach(jId, 0, bId); dJointSetPUParam(jId, dParamLoStop3, 0); dJointSetPUParam(jId, dParamHiStop3, 0); for (int i=0; i<500; ++i) dWorldStep(wId, 1.0); const dReal *pos2_12 = dBodyGetPosition(bId2_12); const dReal *pos = dBodyGetPosition(bId); CHECK_CLOSE (pos2_12[0], pos[0], 1e-4); CHECK_CLOSE (pos2_12[1], pos[1], 1e-4); CHECK_CLOSE (pos2_12[2], pos[2], 1e-4); CHECK_CLOSE (0, pos[0], 1e-4); CHECK_CLOSE (0, pos[1], 1e-4); CHECK_CLOSE (0, pos[2], 1e-4); const dReal *q2_12 = dBodyGetQuaternion(bId2_12); const dReal *q = dBodyGetQuaternion(bId); CHECK_CLOSE (q2_12[0], q[0], 1e-4); CHECK_CLOSE (q2_12[1], q[1], 1e-4); CHECK_CLOSE (q2_12[2], q[2], 1e-4); CHECK_CLOSE (q2_12[3], q[3], 1e-4); } } // End of SUITE TestdxJointPU ode-0.16/tests/joints/fixed.cpp0000664000175200017520000001273213403272463013422 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ //234567890123456789012345678901234567890123456789012345678901234567890123456789 // 1 2 3 4 5 6 7 //////////////////////////////////////////////////////////////////////////////// // This file create unit test for some of the functions found in: // ode/src/joinst/fixed.cpp // // //////////////////////////////////////////////////////////////////////////////// #include #include #include "../../ode/src/config.h" #include "../../ode/src/joints/fixed.h" SUITE (TestdxJointFixed) { struct dxJointFixed_Fixture_1 { dxJointFixed_Fixture_1() { wId = dWorldCreate(); bId1 = dBodyCreate (wId); dBodySetPosition (bId1, 0, -1, 0); bId2 = dBodyCreate (wId); dBodySetPosition (bId2, 0, 1, 0); jId = dJointCreateFixed (wId, 0); joint = (dxJointFixed*) jId; dJointAttach (jId, bId1, bId2); } ~dxJointFixed_Fixture_1() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId1; dBodyID bId2; dJointID jId; dxJointFixed* joint; }; TEST_FIXTURE (dxJointFixed_Fixture_1, test_dJointSetFixed) { // the 2 bodies are align dJointSetFixed (jId); CHECK_CLOSE (joint->qrel[0], 1.0, 1e-4); CHECK_CLOSE (joint->qrel[1], 0.0, 1e-4); CHECK_CLOSE (joint->qrel[2], 0.0, 1e-4); CHECK_CLOSE (joint->qrel[3], 0.0, 1e-4); dMatrix3 R; // Rotate 2nd body 90deg around X dBodySetPosition (bId2, 0, 0, 1); dRFromAxisAndAngle (R, 1, 0, 0, M_PI/2.0); dBodySetRotation (bId2, R); dJointSetFixed (jId); CHECK_CLOSE (joint->qrel[0], 0.70710678118654757, 1e-4); CHECK_CLOSE (joint->qrel[1], 0.70710678118654757, 1e-4); CHECK_CLOSE (joint->qrel[2], 0.0, 1e-4); CHECK_CLOSE (joint->qrel[3], 0.0, 1e-4); // Rotate 2nd body -90deg around X dBodySetPosition (bId2, 0, 0, -1); dRFromAxisAndAngle (R, 1, 0, 0, -M_PI/2.0); dBodySetRotation (bId2, R); dJointSetFixed (jId); CHECK_CLOSE (joint->qrel[0], 0.70710678118654757, 1e-4); CHECK_CLOSE (joint->qrel[1], -0.70710678118654757, 1e-4); CHECK_CLOSE (joint->qrel[2], 0.0, 1e-4); CHECK_CLOSE (joint->qrel[3], 0.0, 1e-4); // Rotate 2nd body 90deg around Z dBodySetPosition (bId2, 0, 1, 0); dRFromAxisAndAngle (R, 0, 0, 1, M_PI/2.0); dBodySetRotation (bId2, R); dJointSetFixed (jId); CHECK_CLOSE (joint->qrel[0], 0.70710678118654757, 1e-4); CHECK_CLOSE (joint->qrel[1], 0.0, 1e-4); CHECK_CLOSE (joint->qrel[2], 0.0, 1e-4); CHECK_CLOSE (joint->qrel[3], 0.70710678118654757, 1e-4); // Rotate 2nd body 45deg around Y dBodySetPosition (bId2, 0, 1, 0); dRFromAxisAndAngle (R, 0, 1, 0, M_PI/4.0); dBodySetRotation (bId2, R); dJointSetFixed (jId); CHECK_CLOSE (joint->qrel[0], 0.92387953251128674, 1e-4); CHECK_CLOSE (joint->qrel[1], 0.0, 1e-4); CHECK_CLOSE (joint->qrel[2], 0.38268343236508984, 1e-4); CHECK_CLOSE (joint->qrel[3], 0.0, 1e-4); // Rotate in a strange manner // Both bodies at origin dRFromEulerAngles (R, REAL(0.23), REAL(3.1), REAL(-0.73)); dBodySetPosition (bId1, 0, 0, 0); dBodySetRotation (bId1, R); dRFromEulerAngles (R, REAL(-0.57), REAL(1.49), REAL(0.81)); dBodySetPosition (bId2, 0, 0, 0); dBodySetRotation (bId2, R); dJointSetFixed (jId); CHECK_CLOSE (joint->qrel[0], -0.25526036263124319, 1e-4); CHECK_CLOSE (joint->qrel[1], 0.28434861188441968, 1e-4); CHECK_CLOSE (joint->qrel[2], -0.65308047160141625, 1e-4); CHECK_CLOSE (joint->qrel[3], 0.65381489108282143, 1e-4); } } // End of SUITE TestdxJointFixed ode-0.16/tests/joints/hinge.cpp0000664000175200017520000006006313403272463013415 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ //234567890123456789012345678901234567890123456789012345678901234567890123456789 // 1 2 3 4 5 6 7 //////////////////////////////////////////////////////////////////////////////// // This file create unit test for some of the functions found in: // ode/src/joinst/hinge.cpp // // //////////////////////////////////////////////////////////////////////////////// #include #include #include "../../ode/src/config.h" #include "../../ode/src/joints/hinge.h" SUITE (TestdxJointHinge) { // The 2 bodies are positionned at (0, 0, 0), with no rotation // The joint is an Hinge Joint // Axis is along the X axis // Anchor at (0, 0, 0) // ^Y // | // | // | // | // | // Z <---- . (X going out of the page) struct dxJointHinge_Fixture_B1_and_B2_At_Zero_Axis_Along_X { dxJointHinge_Fixture_B1_and_B2_At_Zero_Axis_Along_X() { wId = dWorldCreate(); bId1 = dBodyCreate (wId); dBodySetPosition (bId1, 0, 0, 0); bId2 = dBodyCreate (wId); dBodySetPosition (bId2, 0, 0, 0); jId = dJointCreateHinge (wId, 0); joint = (dxJointHinge*) jId; dJointAttach (jId, bId1, bId2); dJointSetHingeAnchor (jId, 0, 0, 0); axis[0] = 1; axis[1] = 0; axis[2] = 0; } ~dxJointHinge_Fixture_B1_and_B2_At_Zero_Axis_Along_X() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId1; dBodyID bId2; dJointID jId; dxJointHinge* joint; dVector3 axis; }; // Rotate 2nd body 90deg around X then back to original position // // ^ ^ ^ // | | => | <--- // | | | // B1 B2 B1 B2 // // Start with a Delta of 90deg // ^ ^ ^ // | <--- => | | // | | | // B1 B2 B1 B2 TEST_FIXTURE (dxJointHinge_Fixture_B1_and_B2_At_Zero_Axis_Along_X, test_dJointSetHingeAxisOffset_B2_90deg) { dMatrix3 R; CHECK_CLOSE (dJointGetHingeAngle (jId), 0.0, 1e-4); dRFromAxisAndAngle (R, 1, 0, 0, M_PI/2.0); dBodySetRotation (bId2, R); CHECK_CLOSE (-M_PI/2.0, dJointGetHingeAngle (jId), 1e-4); dJointSetHingeAxisOffset (jId, axis[0], axis[1], axis[2], -M_PI/2.0); CHECK_CLOSE (-M_PI/2.0, dJointGetHingeAngle (jId), 1e-4); dRFromAxisAndAngle (R, 1, 0, 0, 0); dBodySetRotation (bId2, R); CHECK_CLOSE (0.0, dJointGetHingeAngle (jId), 1e-4); } // Rotate 2nd body -90deg around X then back to original position // // ^ ^ ^ // | | => | ---> // | | | // B1 B2 B1 B2 // // Start with a Delta of 90deg // ^ ^ ^ // | ---> => | | // | | | // B1 B2 B1 B2 TEST_FIXTURE (dxJointHinge_Fixture_B1_and_B2_At_Zero_Axis_Along_X, test_dJointSetHingeAxisOffset_B2_Minus90deg) { dMatrix3 R; dJointSetHingeAxis (jId, axis[0], axis[1], axis[2]); CHECK_CLOSE (dJointGetHingeAngle (jId), 0.0, 1e-4); dRFromAxisAndAngle (R, 1, 0, 0, -M_PI/2.0); dBodySetRotation (bId2, R); CHECK_CLOSE (M_PI/2.0, dJointGetHingeAngle (jId), 1e-4); dJointSetHingeAxisOffset (jId, axis[0], axis[1], axis[2], M_PI/2.0); CHECK_CLOSE (M_PI/2.0, dJointGetHingeAngle (jId), 1e-4); dRFromAxisAndAngle (R, 1, 0, 0, 0); dBodySetRotation (bId2, R); CHECK_CLOSE (0.0, dJointGetHingeAngle (jId), 1e-4); } // Rotate 1st body 0.23rad around X then back to original position // // ^ ^ ^ ^ // | | => \ | // | | \ | // B1 B2 B1 B2 // // Start with a Delta of 0.23rad // ^ ^ ^ ^ // \ | => | | // \ | | | // B1 B2 B1 B2 TEST_FIXTURE (dxJointHinge_Fixture_B1_and_B2_At_Zero_Axis_Along_X, test_dJointSetHingeAxisOffset_B1_0_23rad) { dMatrix3 R; dJointSetHingeAxis (jId, axis[0], axis[1], axis[2]); CHECK_CLOSE (dJointGetHingeAngle (jId), 0.0, 1e-4); dRFromAxisAndAngle (R, 1, 0, 0, REAL(0.23) ); dBodySetRotation (bId1, R); CHECK_CLOSE (REAL(0.23), dJointGetHingeAngle (jId), 1e-4); dJointSetHingeAxisOffset (jId, axis[0], axis[1], axis[2], REAL(0.23)); CHECK_CLOSE (REAL(0.23), dJointGetHingeAngle (jId), 1e-4); dRFromAxisAndAngle (R, 1, 0, 0, 0); dBodySetRotation (bId1, R); CHECK_CLOSE (0.0, dJointGetHingeAngle (jId), 1e-4); } // Rotate 1st body -0.23rad around Z then back to original position // // ^ ^ ^ ^ // | | => / | // | | / | // B1 B2 B1 B2 // // Start with a Delta of 0.23rad // ^ ^ ^ ^ // / | => | | // / | | | // B1 B2 B1 B2 TEST_FIXTURE (dxJointHinge_Fixture_B1_and_B2_At_Zero_Axis_Along_X, test_dJointSetHingeAxisOffset_B1_Minus0_23rad) { dMatrix3 R; dJointSetHingeAxis (jId, axis[0], axis[1], axis[2]); CHECK_CLOSE (dJointGetHingeAngle (jId), 0.0, 1e-4); dRFromAxisAndAngle (R, 1, 0, 0, -REAL(0.23)); dBodySetRotation (bId1, R); CHECK_CLOSE (-REAL(0.23), dJointGetHingeAngle (jId), 1e-4); dJointSetHingeAxisOffset (jId, axis[0], axis[1], axis[2], -REAL(0.23)); CHECK_CLOSE (-REAL(0.23), dJointGetHingeAngle (jId), 1e-4); dRFromAxisAndAngle (R, 1, 0, 0, 0); dBodySetRotation (bId1, R); CHECK_CLOSE (0.0, dJointGetHingeAngle (jId), 1e-4); } // The 2 bodies are positionned at (0, 0, 0), with no rotation // The joint is an Hinge Joint. // Axis in the inverse direction of the X axis // Anchor at (0, 0, 0) // ^Y // | // | // | // | // | // Z <---- x (X going out of the page) struct dxJointHinge_Fixture_B1_and_B2_At_Zero_Axis_Inverse_of_X { dxJointHinge_Fixture_B1_and_B2_At_Zero_Axis_Inverse_of_X() { wId = dWorldCreate(); bId1 = dBodyCreate (wId); dBodySetPosition (bId1, 0, -1, 0); bId2 = dBodyCreate (wId); dBodySetPosition (bId2, 0, 1, 0); jId = dJointCreateHinge (wId, 0); joint = (dxJointHinge*) jId; dJointAttach (jId, bId1, bId2); dJointSetHingeAnchor (jId, 0, 0, 0); axis[0] = -1; axis[1] = 0; axis[2] = 0; } ~dxJointHinge_Fixture_B1_and_B2_At_Zero_Axis_Inverse_of_X() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId1; dBodyID bId2; dJointID jId; dxJointHinge* joint; dVector3 axis; }; // Rotate 2nd body 90deg around X then back to original position // // ^ ^ ^ // | | => | <--- // | | | // B1 B2 B1 B2 // // Start with a Delta of 90deg // ^ ^ ^ // | <--- => | | // | | | // B1 B2 B1 B2 TEST_FIXTURE (dxJointHinge_Fixture_B1_and_B2_At_Zero_Axis_Inverse_of_X, test_dJointSetHingeAxisOffset_B2_90Deg) { dMatrix3 R; dJointSetHingeAxis (jId, axis[0], axis[1], axis[2]); CHECK_CLOSE (dJointGetHingeAngle (jId), 0.0, 1e-4); dRFromAxisAndAngle (R, 1, 0, 0, M_PI/2.0); dBodySetRotation (bId2, R); CHECK_CLOSE (M_PI/2.0, dJointGetHingeAngle (jId), 1e-4); dJointSetHingeAxisOffset (jId, axis[0], axis[1], axis[2], M_PI/2.0); CHECK_CLOSE (M_PI/2.0, dJointGetHingeAngle (jId), 1e-4); dRFromAxisAndAngle (R, 1, 0, 0, 0); dBodySetRotation (bId2, R); CHECK_CLOSE (0.0, dJointGetHingeAngle (jId), 1e-4); } // Rotate 2nd body -90deg around X then back to original position // // ^ ^ ^ // | | => | ---> // | | | // B1 B2 B1 B2 // // Start with a Delta of 90deg // ^ ^ ^ // | ---> => | | // | | | // B1 B2 B1 B2 TEST_FIXTURE (dxJointHinge_Fixture_B1_and_B2_At_Zero_Axis_Inverse_of_X, test_dJointSetHingeAxisOffset_B2_Minus90Deg) { dMatrix3 R; dJointSetHingeAxis (jId, axis[0], axis[1], axis[2]); CHECK_CLOSE (dJointGetHingeAngle (jId), 0.0, 1e-4); dRFromAxisAndAngle (R, 1, 0, 0, -M_PI/2.0); dBodySetRotation (bId2, R); CHECK_CLOSE (-M_PI/2.0, dJointGetHingeAngle (jId), 1e-4); dJointSetHingeAxisOffset (jId, axis[0], axis[1], axis[2], -M_PI/2.0); CHECK_CLOSE (-M_PI/2.0, dJointGetHingeAngle (jId), 1e-4); dRFromAxisAndAngle (R, 1, 0, 0, 0); dBodySetRotation (bId2, R); CHECK_CLOSE (0.0, dJointGetHingeAngle (jId), 1e-4); } // Rotate 1st body 0.23rad around X then back to original position // // ^ ^ ^ ^ // | | => \ | // | | \ | // B1 B2 B1 B2 // // Start with a Delta of 0.23rad // ^ ^ ^ ^ // \ | => | | // \ | | | // B1 B2 B1 B2 TEST_FIXTURE (dxJointHinge_Fixture_B1_and_B2_At_Zero_Axis_Inverse_of_X, test_dJointSetHingeAxisOffset_B1_0_23rad) { dMatrix3 R; dJointSetHingeAxis (jId, axis[0], axis[1], axis[2]); CHECK_CLOSE (dJointGetHingeAngle (jId), 0.0, 1e-4); dRFromAxisAndAngle (R, 1, 0, 0, REAL(0.23)); dBodySetRotation (bId1, R); CHECK_CLOSE (-REAL(0.23), dJointGetHingeAngle (jId), 1e-4); dJointSetHingeAxisOffset (jId, axis[0], axis[1], axis[2], -REAL(0.23)); CHECK_CLOSE (-REAL(0.23), dJointGetHingeAngle (jId), 1e-4); dRFromAxisAndAngle (R, 1, 0, 0, 0); dBodySetRotation (bId1, R); CHECK_CLOSE (0.0, dJointGetHingeAngle (jId), 1e-4); } // Rotate 2nd body -0.23rad around Z then back to original position // // ^ ^ ^ ^ // | | => / | // | | / | // B1 B2 B1 B2 // // Start with a Delta of 0.23rad // ^ ^ ^ ^ // / | => | | // / | | | // B1 B2 B1 B2 TEST_FIXTURE (dxJointHinge_Fixture_B1_and_B2_At_Zero_Axis_Inverse_of_X, test_dJointSetHingeAxisOffset_B1_Minus0_23rad) { dMatrix3 R; dJointSetHingeAxis (jId, axis[0], axis[1], axis[2]); CHECK_CLOSE (dJointGetHingeAngle (jId), 0.0, 1e-4); dRFromAxisAndAngle (R, 1, 0, 0, -REAL(0.23)); dBodySetRotation (bId1, R); CHECK_CLOSE (REAL(0.23), dJointGetHingeAngle (jId), 1e-4); dJointSetHingeAxisOffset (jId, axis[0], axis[1], axis[2], REAL(0.23)); CHECK_CLOSE (REAL(0.23), dJointGetHingeAngle (jId), 1e-4); dRFromAxisAndAngle (R, 1, 0, 0, 0); dBodySetRotation (bId1, R); CHECK_CLOSE (0.0, dJointGetHingeAngle (jId), 1e-4); } // Only one body body1 at (0,0,0) // The joint is an Hinge Joint. // Axis is along the X axis // Anchor at (0, 0, 0) // // ^Y // | // | // | // | // | // Z <-- X struct dxJointHinge_Fixture_B1_At_Zero_Axis_Along_X { dxJointHinge_Fixture_B1_At_Zero_Axis_Along_X() { wId = dWorldCreate(); bId1 = dBodyCreate (wId); dBodySetPosition (bId1, 0, 0, 0); jId = dJointCreateHinge (wId, 0); joint = (dxJointHinge*) jId; dJointAttach (jId, bId1, NULL); dJointSetHingeAnchor (jId, 0, 0, 0); axis[0] = 1; axis[1] = 0; axis[2] = 0; } ~dxJointHinge_Fixture_B1_At_Zero_Axis_Along_X() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId1; dJointID jId; dxJointHinge* joint; dVector3 axis; }; // Rotate B1 by 90deg around X then back to original position // // ^ // | => <--- // | // B1 B1 // // Start with a Delta of 90deg // ^ // <--- => | // | // B1 B1 TEST_FIXTURE (dxJointHinge_Fixture_B1_At_Zero_Axis_Along_X, test_dJointSetHingeAxisOffset_1Body_B1_90Deg) { dMatrix3 R; dJointSetHingeAxis (jId, axis[0], axis[1], axis[2]); CHECK_CLOSE (dJointGetHingeAngle (jId), 0.0, 1e-4); dRFromAxisAndAngle (R, 1, 0, 0, M_PI/2.0); dBodySetRotation (bId1, R); CHECK_CLOSE (M_PI/2.0, dJointGetHingeAngle (jId), 1e-4); dJointSetHingeAxisOffset (jId, axis[0], axis[1], axis[2], M_PI/2.0); CHECK_CLOSE (M_PI/2.0, dJointGetHingeAngle (jId), 1e-4); dRFromAxisAndAngle (R, 1, 0, 0, 0); dBodySetRotation (bId1, R); CHECK_CLOSE (0, dJointGetHingeAngle (jId), 1e-4); } // Rotate B1 by -0.23rad around X then back to original position // // ^ ^ // | => / // | / // B1 B1 // // Start with a Delta of -0.23rad // ^ ^ // / => | // / | // B1 B1 TEST_FIXTURE (dxJointHinge_Fixture_B1_At_Zero_Axis_Along_X, test_dJointSetHingeAxisOffset_1Body_B1_Minus0_23rad) { dMatrix3 R; dJointSetHingeAxis (jId, axis[0], axis[1], axis[2]); CHECK_CLOSE (dJointGetHingeAngle (jId), 0.0, 1e-4); dRFromAxisAndAngle (R, 1, 0, 0, -REAL(0.23)); dBodySetRotation (bId1, R); CHECK_CLOSE (-REAL(0.23), dJointGetHingeAngle (jId), 1e-4); dJointSetHingeAxisOffset (jId, axis[0], axis[1], axis[2], -REAL(0.23)); CHECK_CLOSE (-REAL(0.23), dJointGetHingeAngle (jId), 1e-4); dRFromAxisAndAngle (R, 1, 0, 0, 0); dBodySetRotation (bId1, R); CHECK_CLOSE (0, dJointGetHingeAngle (jId), 1e-4); } // Only one body body1 at (0,0,0) // The joint is an Hinge Joint. // Axis the inverse of the X axis // Anchor at (0, 0, 0) // // ^Y // | // | // | // | // | // Z <-- X struct dxJointHinge_Fixture_B1_At_Zero_Axis_Inverse_of_X { dxJointHinge_Fixture_B1_At_Zero_Axis_Inverse_of_X() { wId = dWorldCreate(); bId1 = dBodyCreate (wId); dBodySetPosition (bId1, 0, 0, 0); jId = dJointCreateHinge (wId, 0); joint = (dxJointHinge*) jId; dJointAttach (jId, bId1, NULL); dJointSetHingeAnchor (jId, 0, 0, 0); axis[0] = -1; axis[1] = 0; axis[2] = 0; } ~dxJointHinge_Fixture_B1_At_Zero_Axis_Inverse_of_X() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId1; dJointID jId; dxJointHinge* joint; dVector3 axis; }; // Rotate B1 by 90deg around X then back to original position // // ^ // | => <--- // | // B1 B1 // // Start with a Delta of 90deg // ^ // <--- => | // | // B1 B1 TEST_FIXTURE (dxJointHinge_Fixture_B1_At_Zero_Axis_Inverse_of_X, test_dJointSetHingeAxisOffset_1Body_B1_90Deg) { dMatrix3 R; dJointSetHingeAxis (jId, axis[0], axis[1], axis[2]); CHECK_CLOSE (dJointGetHingeAngle (jId), 0.0, 1e-4); dRFromAxisAndAngle (R, 1, 0, 0, M_PI/2.0); dBodySetRotation (bId1, R); CHECK_CLOSE (-M_PI/2.0, dJointGetHingeAngle (jId), 1e-4); dJointSetHingeAxisOffset (jId, axis[0], axis[1], axis[2], -M_PI/2.0); CHECK_CLOSE (-M_PI/2.0, dJointGetHingeAngle (jId), 1e-4); dRFromAxisAndAngle (R, 1, 0, 0, 0); dBodySetRotation (bId1, R); CHECK_CLOSE (0, dJointGetHingeAngle (jId), 1e-4); } // Rotate B1 by -0.23rad around X then back to original position // // ^ ^ // | => / // | / // B1 B1 // // Start with a Delta of -0.23rad // ^ ^ // / => | // / | // B1 B1 TEST_FIXTURE (dxJointHinge_Fixture_B1_At_Zero_Axis_Inverse_of_X, test_dJointSetHingeAxisOffset_1Body_B1_Minus0_23rad) { dMatrix3 R; dJointSetHingeAxis (jId, axis[0], axis[1], axis[2]); CHECK_CLOSE (dJointGetHingeAngle (jId), 0.0, 1e-4); dRFromAxisAndAngle (R, 1, 0, 0, -REAL(0.23)); dBodySetRotation (bId1, R); CHECK_CLOSE (REAL(0.23), dJointGetHingeAngle (jId), 1e-4); dJointSetHingeAxisOffset (jId, axis[0], axis[1], axis[2], REAL(0.23)); CHECK_CLOSE (REAL(0.23), dJointGetHingeAngle (jId), 1e-4); dRFromAxisAndAngle (R, 1, 0, 0, 0); dBodySetRotation (bId1, R); CHECK_CLOSE (0, dJointGetHingeAngle (jId), 1e-4); } // Only one body body2 at (0,0,0) // The joint is an Hinge Joint. // Axis is along the X axis // Anchor at (0, 0, 0) // // ^Y // | // | // | // | // | // Z <-- X struct dxJointHinge_Fixture_B2_At_Zero_Axis_Along_X { dxJointHinge_Fixture_B2_At_Zero_Axis_Along_X() { wId = dWorldCreate(); bId2 = dBodyCreate (wId); dBodySetPosition (bId2, 0, 0, 0); jId = dJointCreateHinge (wId, 0); joint = (dxJointHinge*) jId; dJointAttach (jId, NULL, bId2); dJointSetHingeAnchor (jId, 0, 0, 0); axis[0] = 1; axis[1] = 0; axis[2] = 0; } ~dxJointHinge_Fixture_B2_At_Zero_Axis_Along_X() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId2; dJointID jId; dxJointHinge* joint; dVector3 axis; }; // Rotate B2 by 90deg around X then back to original position // // ^ // | => <--- // | // B2 B2 // // Start with a Delta of 90deg // ^ // <--- => | // | // B2 B2 TEST_FIXTURE (dxJointHinge_Fixture_B2_At_Zero_Axis_Along_X, test_dJointSetHingeAxisOffset_1Body_B2_90Deg) { dMatrix3 R; dJointSetHingeAxis (jId, axis[0], axis[1], axis[2]); CHECK_CLOSE (dJointGetHingeAngle (jId), 0.0, 1e-4); dRFromAxisAndAngle (R, 1, 0, 0, M_PI/2.0); dBodySetRotation (bId2, R); CHECK_CLOSE (-M_PI/2.0, dJointGetHingeAngle (jId), 1e-4); dJointSetHingeAxisOffset (jId, axis[0], axis[1], axis[2], -M_PI/2.0); CHECK_CLOSE (-M_PI/2.0, dJointGetHingeAngle (jId), 1e-4); dRFromAxisAndAngle (R, 1, 0, 0, 0); dBodySetRotation (bId2, R); CHECK_CLOSE (0, dJointGetHingeAngle (jId), 1e-4); } // Rotate B2 by -0.23rad around X then back to original position // // ^ ^ // | => / // | / // B2 B2 // // Start with a Delta of -0.23rad // ^ ^ // / => | // / | // B2 B2 TEST_FIXTURE (dxJointHinge_Fixture_B2_At_Zero_Axis_Along_X, test_dJointSetHingeAxisOffset_1Body_B2_Minus0_23rad) { dMatrix3 R; dJointSetHingeAxis (jId, axis[0], axis[1], axis[2]); CHECK_CLOSE (dJointGetHingeAngle (jId), 0.0, 1e-4); dRFromAxisAndAngle (R, 1, 0, 0, -REAL(0.23)); dBodySetRotation (bId2, R); CHECK_CLOSE (REAL(0.23), dJointGetHingeAngle (jId), 1e-4); dJointSetHingeAxisOffset (jId, axis[0], axis[1], axis[2], REAL(0.23)); CHECK_CLOSE (REAL(0.23), dJointGetHingeAngle (jId), 1e-4); dRFromAxisAndAngle (R, 1, 0, 0, 0); dBodySetRotation (bId2, R); CHECK_CLOSE (0, dJointGetHingeAngle (jId), 1e-4); } // Create 2 bodies attached by a Hinge joint // Axis is along the X axis (Default value // Anchor at (0, 0, 0) (Default value) // // ^Y // | // * Body2 // | // | // Body1 | // * Z--------> struct dxJointHinge_Test_Initialization { dxJointHinge_Test_Initialization() { wId = dWorldCreate(); // Remove gravity to have the only force be the force of the joint dWorldSetGravity(wId, 0,0,0); for (int j=0; j<2; ++j) { bId[j][0] = dBodyCreate (wId); dBodySetPosition (bId[j][0], -1, -2, -3); bId[j][1] = dBodyCreate (wId); dBodySetPosition (bId[j][1], 11, 22, 33); dMatrix3 R; dVector3 axis; // Random axis axis[0] = REAL(0.53); axis[1] = -REAL(0.71); axis[2] = REAL(0.43); dNormalize3(axis); dRFromAxisAndAngle (R, axis[0], axis[1], axis[2], REAL(0.47123)); // 27deg dBodySetRotation (bId[j][0], R); axis[0] = REAL(1.2); axis[1] = REAL(0.87); axis[2] = -REAL(0.33); dNormalize3(axis); dRFromAxisAndAngle (R, axis[0], axis[1], axis[2], REAL(0.47123)); // 27deg dBodySetRotation (bId[j][1], R); jId[j] = dJointCreateHinge (wId, 0); dJointAttach (jId[j], bId[j][0], bId[j][1]); // dJointSetHingeParam(jId[j], dParamLoStop, 1); // dJointSetHingeParam(jId[j], dParamHiStop, 2); // dJointSetHingeParam(jId[j], dParamFMax, 200); } } ~dxJointHinge_Test_Initialization() { dWorldDestroy (wId); } dWorldID wId; dBodyID bId[2][2]; dJointID jId[2]; }; // Test if setting a Hinge with its default values // will behave the same as a default Hinge joint TEST_FIXTURE (dxJointHinge_Test_Initialization, test_Hinge_Initialization) { using namespace std; dVector3 axis; dJointGetHingeAxis(jId[1], axis); dJointSetHingeAxis(jId[1], axis[0], axis[1], axis[2]); dVector3 anchor; dJointGetHingeAnchor(jId[1], anchor); dJointSetHingeAnchor(jId[1], anchor[0], anchor[1], anchor[2]); for (int b=0; b<2; ++b) { // Compare body b of the first joint with its equivalent on the // second joint const dReal *qA = dBodyGetQuaternion(bId[0][b]); const dReal *qB = dBodyGetQuaternion(bId[1][b]); CHECK_CLOSE (qA[0], qB[0], 1e-6); CHECK_CLOSE (qA[1], qB[1], 1e-6); CHECK_CLOSE (qA[2], qB[2], 1e-6); CHECK_CLOSE (qA[3], qB[3], 1e-6); } dWorldStep (wId,0.5); dWorldStep (wId,0.5); dWorldStep (wId,0.5); dWorldStep (wId,0.5); for (int b=0; b<2; ++b) { // Compare body b of the first joint with its equivalent on the // second joint const dReal *qA = dBodyGetQuaternion(bId[0][b]); const dReal *qB = dBodyGetQuaternion(bId[1][b]); CHECK_CLOSE (qA[0], qB[0], 1e-6); CHECK_CLOSE (qA[1], qB[1], 1e-6); CHECK_CLOSE (qA[2], qB[2], 1e-6); CHECK_CLOSE (qA[3], qB[3], 1e-6); const dReal *posA = dBodyGetPosition(bId[0][b]); const dReal *posB = dBodyGetPosition(bId[1][b]); CHECK_CLOSE (posA[0], posB[0], 1e-6); CHECK_CLOSE (posA[1], posB[1], 1e-6); CHECK_CLOSE (posA[2], posB[2], 1e-6); CHECK_CLOSE (posA[3], posB[3], 1e-6); } } TEST_FIXTURE(dxJointHinge_Fixture_B1_and_B2_At_Zero_Axis_Along_X, test_Hinge_dParamVel) { const dReal targetvel = 100; const dReal tolerance = targetvel * #ifdef dSINGLE 1e-2 #else 1e-6 #endif ; dJointSetHingeParam(jId, dParamFMax, dInfinity); dJointSetHingeParam(jId, dParamVel, targetvel); dWorldStep(wId, 0.001); const dReal *v1 = dBodyGetAngularVel(bId1); const dReal *v2 = dBodyGetAngularVel(bId2); dVector3 rvel = { v1[0]-v2[0], v1[1]-v2[1], v1[2]-v2[2] }; CHECK_CLOSE(rvel[0], targetvel, tolerance); CHECK_CLOSE(rvel[1], 0, tolerance); CHECK_CLOSE(rvel[2], 0, tolerance); } } // End of SUITE TestdxJointHinge ode-0.16/tests/joints/Makefile.in0000664000175200017520000004610713403272663013671 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = tests/joints ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/ode/src/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = libjoints_la_LIBADD = am_libjoints_la_OBJECTS = amotor.lo ball.lo dball.lo fixed.lo hinge.lo \ hinge2.lo piston.lo pr.lo pu.lo slider.lo universal.lo libjoints_la_OBJECTS = $(am_libjoints_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libjoints_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(libjoints_la_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/ode/src depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) AM_V_CXX = $(am__v_CXX_@AM_V@) am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = SOURCES = $(libjoints_la_SOURCES) DIST_SOURCES = $(libjoints_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CCD_CFLAGS = @CCD_CFLAGS@ CCD_LIBS = @CCD_LIBS@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXTRA_LIBTOOL_LDFLAGS = @EXTRA_LIBTOOL_LDFLAGS@ FGREP = @FGREP@ GL_LIBS = @GL_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSTDCXX = @LIBSTDCXX@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ ODE_PRECISION = @ODE_PRECISION@ ODE_VERSION = @ODE_VERSION@ ODE_VERSION_INFO = @ODE_VERSION_INFO@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ WINDRES = @WINDRES@ X11_CFLAGS = @X11_CFLAGS@ X11_LIBS = @X11_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_WINDRES = @ac_ct_WINDRES@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(srcdir)/../UnitTest++/src \ -I$(top_srcdir)/include \ -I$(top_builddir)/include \ -I$(top_srcdir)/ode/src check_LTLIBRARIES = libjoints.la libjoints_la_LDFLAGS = -static libjoints_la_SOURCES = \ amotor.cpp \ ball.cpp \ dball.cpp \ fixed.cpp \ hinge.cpp \ hinge2.cpp \ piston.cpp \ pr.cpp \ pu.cpp \ slider.cpp \ universal.cpp all: all-am .SUFFIXES: .SUFFIXES: .cpp .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/joints/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tests/joints/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-checkLTLIBRARIES: -test -z "$(check_LTLIBRARIES)" || rm -f $(check_LTLIBRARIES) @list='$(check_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libjoints.la: $(libjoints_la_OBJECTS) $(libjoints_la_DEPENDENCIES) $(EXTRA_libjoints_la_DEPENDENCIES) $(AM_V_CXXLD)$(libjoints_la_LINK) $(libjoints_la_OBJECTS) $(libjoints_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amotor.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ball.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dball.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fixed.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hinge.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hinge2.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/piston.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pu.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/slider.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/universal.Plo@am__quote@ .cpp.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cpp.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cpp.lo: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_LTLIBRARIES) check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-checkLTLIBRARIES clean-generic clean-libtool \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ clean-checkLTLIBRARIES clean-generic clean-libtool \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ode-0.16/tests/UnitTest++/0000775000175200017520000000000013403273061012264 500000000000000ode-0.16/tests/UnitTest++/src/0000775000175200017520000000000013403273061013053 500000000000000ode-0.16/tests/UnitTest++/src/Config.h0000664000175200017520000000152313403272463014357 00000000000000#ifndef UNITTEST_CONFIG_H #define UNITTEST_CONFIG_H // Standard defines documented here: http://predef.sourceforge.net #if defined _MSC_VER #pragma warning(disable:4127) // conditional expression is constant #pragma warning(disable:4702) // unreachable code #pragma warning(disable:4722) // destructor never returns, potential memory leak #endif #if defined(unix) || defined(__unix__) || defined(__unix) || defined(linux) || \ defined(__APPLE__) || defined (__NetBSD__) || defined (__OpenBSD__) || defined (__FreeBSD__) #define UNITTEST_POSIX #endif #if defined (__MINGW32__) #define UNITTEST_MINGW #endif // by default, MemoryOutStream is implemented in terms of std::ostringstream. // uncomment this line to use the custom MemoryOutStream (no deps on std::ostringstream). //#define UNITTEST_USE_CUSTOM_STREAMS #endif ode-0.16/tests/UnitTest++/src/MemoryOutStream.cpp0000664000175200017520000000503213403272463016620 00000000000000#include "MemoryOutStream.h" #ifndef UNITTEST_USE_CUSTOM_STREAMS namespace UnitTest { char const* MemoryOutStream::GetText() const { m_text = this->str(); return m_text.c_str(); } } #else #include #include namespace UnitTest { namespace { template void FormatToStream(MemoryOutStream& stream, char const* format, ValueType const& value) { char txt[32]; std::sprintf(txt, format, value); stream << txt; } int RoundUpToMultipleOfPow2Number (int n, int pow2Number) { return (n + (pow2Number - 1)) & ~(pow2Number - 1); } } MemoryOutStream::MemoryOutStream(int const size) : m_capacity (0) , m_buffer (0) { GrowBuffer(size); } MemoryOutStream::~MemoryOutStream() { delete [] m_buffer; } char const* MemoryOutStream::GetText() const { return m_buffer; } MemoryOutStream& MemoryOutStream::operator << (char const* txt) { int const bytesLeft = m_capacity - (int)std::strlen(m_buffer); int const bytesRequired = (int)std::strlen(txt) + 1; if (bytesRequired > bytesLeft) { int const requiredCapacity = bytesRequired + m_capacity - bytesLeft; GrowBuffer(requiredCapacity); } std::strcat(m_buffer, txt); return *this; } MemoryOutStream& MemoryOutStream::operator << (int const n) { FormatToStream(*this, "%i", n); return *this; } MemoryOutStream& MemoryOutStream::operator << (long const n) { FormatToStream(*this, "%li", n); return *this; } MemoryOutStream& MemoryOutStream::operator << (unsigned long const n) { FormatToStream(*this, "%lu", n); return *this; } MemoryOutStream& MemoryOutStream::operator << (float const f) { FormatToStream(*this, "%ff", f); return *this; } MemoryOutStream& MemoryOutStream::operator << (void const* p) { FormatToStream(*this, "%p", p); return *this; } MemoryOutStream& MemoryOutStream::operator << (unsigned int const s) { FormatToStream(*this, "%u", s); return *this; } MemoryOutStream& MemoryOutStream::operator <<(double const d) { FormatToStream(*this, "%f", d); return *this; } int MemoryOutStream::GetCapacity() const { return m_capacity; } void MemoryOutStream::GrowBuffer(int const desiredCapacity) { int const newCapacity = RoundUpToMultipleOfPow2Number(desiredCapacity, GROW_CHUNK_SIZE); char* buffer = new char[newCapacity]; if (m_buffer) std::strcpy(buffer, m_buffer); else std::strcpy(buffer, ""); delete [] m_buffer; m_buffer = buffer; m_capacity = newCapacity; } } #endif ode-0.16/tests/UnitTest++/src/TestReporter.h0000664000175200017520000000101713403272463015612 00000000000000#ifndef UNITTEST_TESTREPORTER_H #define UNITTEST_TESTREPORTER_H namespace UnitTest { class TestDetails; class TestReporter { public: virtual ~TestReporter(); virtual void ReportTestStart(TestDetails const& test) = 0; virtual void ReportFailure(TestDetails const& test, char const* failure) = 0; virtual void ReportTestFinish(TestDetails const& test, float secondsElapsed) = 0; virtual void ReportSummary(int totalTestCount, int failedTestCount, int failureCount, float secondsElapsed) = 0; }; } #endif ode-0.16/tests/UnitTest++/src/UnitTest++.h0000664000175200017520000000042713403272463015061 00000000000000#ifndef UNITTESTCPP_H #define UNITTESTCPP_H #include "Config.h" #include "Test.h" #include "TestList.h" #include "TestSuite.h" #include "TestResults.h" #include #include "TestMacros.h" #include "CheckMacros.h" #include "TestRunner.h" #include "TimeConstraint.h" #endif ode-0.16/tests/UnitTest++/src/Makefile.am0000664000175200017520000000275013403272463015040 00000000000000if WIN32 SUBDIRS = Win32 else SUBDIRS = Posix endif check_LTLIBRARIES = libunittestpp.la libunittestpp_la_SOURCES = AssertException.cpp AssertException.h \ CheckMacros.h Checks.cpp \ Checks.h Config.h \ DeferredTestReporter.cpp DeferredTestReporter.h \ DeferredTestResult.cpp DeferredTestResult.h \ MemoryOutStream.cpp MemoryOutStream.h \ ReportAssert.cpp ReportAssert.h \ Test.cpp TestDetails.cpp \ TestDetails.h Test.h \ TestList.cpp TestList.h \ TestMacros.h TestReporter.cpp \ TestReporter.h TestReporterStdout.cpp \ TestReporterStdout.h TestResults.cpp \ TestResults.h TestRunner.cpp \ TestRunner.h TestSuite.h \ TimeConstraint.cpp TimeConstraint.h \ TimeHelpers.h UnitTest++.h \ XmlTestReporter.cpp XmlTestReporter.h if WIN32 libunittestpp_la_LIBADD = $(builddir)/Win32/libhelper.la else libunittestpp_la_LIBADD = $(builddir)/Posix/libhelper.la endif ode-0.16/tests/UnitTest++/src/TimeConstraint.h0000664000175200017520000000134313403272463016115 00000000000000#ifndef UNITTEST_TIMECONSTRAINT_H #define UNITTEST_TIMECONSTRAINT_H #include "TimeHelpers.h" namespace UnitTest { class TestResults; class TestDetails; class TimeConstraint { public: TimeConstraint(int ms, TestResults& result, TestDetails const& details); ~TimeConstraint(); private: void operator=(TimeConstraint const&); TimeConstraint(TimeConstraint const&); Timer m_timer; TestResults& m_result; TestDetails const& m_details; int const m_maxMs; }; #define UNITTEST_TIME_CONSTRAINT(ms) \ UnitTest::TimeConstraint unitTest__timeConstraint__(ms, testResults_, UnitTest::TestDetails(m_details, __LINE__)) #define UNITTEST_TIME_CONSTRAINT_EXEMPT() do { m_timeConstraintExempt = true; } while (0) } #endif ode-0.16/tests/UnitTest++/src/Test.h0000664000175200017520000000114313403272463014067 00000000000000#ifndef UNITTEST_TEST_H #define UNITTEST_TEST_H #include "TestDetails.h" namespace UnitTest { class TestResults; class TestList; class Test { public: Test(char const* testName, char const* suiteName = "DefaultSuite", char const* filename = "", int lineNumber = 0); virtual ~Test(); void Run(TestResults& testResults) const; TestDetails const m_details; Test* next; mutable bool m_timeConstraintExempt; static TestList& GetTestList(); private: virtual void RunImpl(TestResults& testResults_) const; Test(Test const&); Test& operator =(Test const&); }; } #endif ode-0.16/tests/UnitTest++/src/TestList.cpp0000664000175200017520000000076113403272463015263 00000000000000#include "TestList.h" #include "Test.h" #include namespace UnitTest { TestList::TestList() : m_head(0) , m_tail(0) { } void TestList::Add(Test* test) { if (m_tail == 0) { assert(m_head == 0); m_head = test; m_tail = test; } else { m_tail->next = test; m_tail = test; } } const Test* TestList::GetHead() const { return m_head; } ListAdder::ListAdder(TestList& list, Test* test) { list.Add(test); } } ode-0.16/tests/UnitTest++/src/Test.cpp0000664000175200017520000000233413403272463014425 00000000000000#include "Config.h" #include "Test.h" #include "TestList.h" #include "TestResults.h" #include "AssertException.h" #include "MemoryOutStream.h" #ifdef UNITTEST_POSIX #include "Posix/SignalTranslator.h" #endif namespace UnitTest { TestList& Test::GetTestList() { static TestList s_list; return s_list; } Test::Test(char const* testName, char const* suiteName, char const* filename, int const lineNumber) : m_details(testName, suiteName, filename, lineNumber) , next(0) , m_timeConstraintExempt(false) { } Test::~Test() { } void Test::Run(TestResults& testResults) const { try { #ifdef UNITTEST_POSIX UNITTEST_THROW_SIGNALS #endif RunImpl(testResults); } catch (AssertException const& e) { testResults.OnTestFailure( TestDetails(m_details.testName, m_details.suiteName, e.Filename(), e.LineNumber()), e.what()); } catch (std::exception const& e) { MemoryOutStream stream; stream << "Unhandled exception: " << e.what(); testResults.OnTestFailure(m_details, stream.GetText()); } catch (...) { testResults.OnTestFailure(m_details, "Unhandled exception: Crash!"); } } void Test::RunImpl(TestResults&) const { } } ode-0.16/tests/UnitTest++/src/DeferredTestResult.h0000664000175200017520000000104313403272463016726 00000000000000#ifndef UNITTEST_DEFERREDTESTRESULT_H #define UNITTEST_DEFERREDTESTRESULT_H #include #include namespace UnitTest { struct DeferredTestResult { DeferredTestResult(); DeferredTestResult(char const* suite, char const* test); std::string suiteName; std::string testName; std::string failureFile; typedef std::pair< int, std::string > Failure; typedef std::vector< Failure > FailureVec; FailureVec failures; float timeElapsed; bool failed; }; } #endif //UNITTEST_DEFERREDTESTRESULT_H ode-0.16/tests/UnitTest++/src/TestDetails.h0000664000175200017520000000107613403272463015402 00000000000000#ifndef UNITTEST_TESTDETAILS_H #define UNITTEST_TESTDETAILS_H namespace UnitTest { class TestDetails { public: TestDetails(char const* testName, char const* suiteName, char const* filename, int lineNumber); TestDetails(const TestDetails& details, int lineNumber); char const* const suiteName; char const* const testName; char const* const filename; int const lineNumber; TestDetails(TestDetails const&); // Why is it public? --> http://gcc.gnu.org/bugs.html#cxx_rvalbind private: TestDetails& operator=(TestDetails const&); }; } #endif ode-0.16/tests/UnitTest++/src/MemoryOutStream.h0000664000175200017520000000230213403272463016262 00000000000000#ifndef UNITTEST_MEMORYOUTSTREAM_H #define UNITTEST_MEMORYOUTSTREAM_H #include "Config.h" #ifndef UNITTEST_USE_CUSTOM_STREAMS #include namespace UnitTest { class MemoryOutStream : public std::ostringstream { public: MemoryOutStream() {} char const* GetText() const; private: MemoryOutStream(MemoryOutStream const&); void operator =(MemoryOutStream const&); mutable std::string m_text; }; } #else #include namespace UnitTest { class MemoryOutStream { public: explicit MemoryOutStream(int const size = 256); ~MemoryOutStream(); char const* GetText() const; MemoryOutStream& operator << (char const* txt); MemoryOutStream& operator << (int n); MemoryOutStream& operator << (long n); MemoryOutStream& operator << (unsigned long n); MemoryOutStream& operator << (float f); MemoryOutStream& operator << (double d); MemoryOutStream& operator << (void const* p); MemoryOutStream& operator << (unsigned int s); enum { GROW_CHUNK_SIZE = 32 }; int GetCapacity() const; private: void operator= (MemoryOutStream const&); void GrowBuffer(int capacity); int m_capacity; char* m_buffer; }; } #endif #endif ode-0.16/tests/UnitTest++/src/TimeHelpers.h0000664000175200017520000000020313403272463015365 00000000000000#include "Config.h" #if defined UNITTEST_POSIX #include "Posix/TimeHelpers.h" #else #include "Win32/TimeHelpers.h" #endif ode-0.16/tests/UnitTest++/src/TestRunner.h0000664000175200017520000000041013403272463015255 00000000000000#ifndef UNITTEST_TESTRUNNER_H #define UNITTEST_TESTRUNNER_H namespace UnitTest { class TestReporter; class TestList; int RunAllTests(); int RunAllTests(TestReporter& reporter, TestList const& list, char const* suiteName, int maxTestTimeInMs = 0); } #endif ode-0.16/tests/UnitTest++/src/TestReporterStdout.cpp0000664000175200017520000000210713403272463017351 00000000000000#include "TestReporterStdout.h" #include #include "TestDetails.h" namespace UnitTest { void TestReporterStdout::ReportFailure(TestDetails const& details, char const* failure) { #ifdef __APPLE__ char const* const errorFormat = "%s:%d: error: Failure in %s: %s\n"; #else char const* const errorFormat = "%s(%d): error: Failure in %s: %s\n"; #endif std::printf(errorFormat, details.filename, details.lineNumber, details.testName, failure); } void TestReporterStdout::ReportTestStart(TestDetails const& /*test*/) { } void TestReporterStdout::ReportTestFinish(TestDetails const& /*test*/, float) { } void TestReporterStdout::ReportSummary(int const totalTestCount, int const failedTestCount, int const failureCount, float secondsElapsed) { if (failureCount > 0) std::printf("FAILURE: %d out of %d tests failed (%d failures).\n", failedTestCount, totalTestCount, failureCount); else std::printf("Success: %d tests passed.\n", totalTestCount); std::printf("Test time: %.2f seconds.\n", secondsElapsed); } } ode-0.16/tests/UnitTest++/src/TestReporterStdout.h0000664000175200017520000000102313403272463017012 00000000000000#ifndef UNITTEST_TESTREPORTERSTDOUT_H #define UNITTEST_TESTREPORTERSTDOUT_H #include "TestReporter.h" namespace UnitTest { class TestReporterStdout : public TestReporter { private: virtual void ReportTestStart(TestDetails const& test); virtual void ReportFailure(TestDetails const& test, char const* failure); virtual void ReportTestFinish(TestDetails const& test, float secondsElapsed); virtual void ReportSummary(int totalTestCount, int failedTestCount, int failureCount, float secondsElapsed); }; } #endif ode-0.16/tests/UnitTest++/src/ReportAssert.h0000664000175200017520000000025413403272463015607 00000000000000#ifndef UNITTEST_ASSERT_H #define UNITTEST_ASSERT_H namespace UnitTest { void ReportAssert(char const* description, char const* filename, int lineNumber); } #endif ode-0.16/tests/UnitTest++/src/TestDetails.cpp0000664000175200017520000000074413403272463015736 00000000000000#include "TestDetails.h" namespace UnitTest { TestDetails::TestDetails(char const* testName_, char const* suiteName_, char const* filename_, int lineNumber_) : suiteName(suiteName_) , testName(testName_) , filename(filename_) , lineNumber(lineNumber_) { } TestDetails::TestDetails(const TestDetails& details, int lineNumber_) : suiteName(details.suiteName) , testName(details.testName) , filename(details.filename) , lineNumber(lineNumber_) { } } ode-0.16/tests/UnitTest++/src/DeferredTestReporter.cpp0000664000175200017520000000145713403272463017616 00000000000000#include "DeferredTestReporter.h" #include "TestDetails.h" using namespace UnitTest; void DeferredTestReporter::ReportTestStart(TestDetails const& details) { m_results.push_back(DeferredTestResult(details.suiteName, details.testName)); } void DeferredTestReporter::ReportFailure(TestDetails const& details, char const* failure) { DeferredTestResult& r = m_results.back(); r.failed = true; r.failures.push_back(DeferredTestResult::Failure(details.lineNumber, failure)); r.failureFile = details.filename; } void DeferredTestReporter::ReportTestFinish(TestDetails const&, float const secondsElapsed) { DeferredTestResult& r = m_results.back(); r.timeElapsed = secondsElapsed; } DeferredTestReporter::DeferredTestResultList& DeferredTestReporter::GetResults() { return m_results; } ode-0.16/tests/UnitTest++/src/TestRunner.cpp0000664000175200017520000000327013403272463015617 00000000000000#include "TestRunner.h" #include "TestResults.h" #include "Test.h" #include "TestList.h" #include "TestReporter.h" #include "TestReporterStdout.h" #include "TimeHelpers.h" #include "MemoryOutStream.h" #include namespace UnitTest { int RunAllTests(TestReporter& reporter, TestList const& list, char const* suiteName, int const maxTestTimeInMs ) { TestResults result(&reporter); Timer overallTimer; overallTimer.Start(); Test const* curTest = list.GetHead(); while (curTest != 0) { if (suiteName == 0 || !std::strcmp(curTest->m_details.suiteName, suiteName)) { Timer testTimer; testTimer.Start(); result.OnTestStart(curTest->m_details); curTest->Run(result); int const testTimeInMs = testTimer.GetTimeInMs(); if (maxTestTimeInMs > 0 && testTimeInMs > maxTestTimeInMs && !curTest->m_timeConstraintExempt) { MemoryOutStream stream; stream << "Global time constraint failed. Expected under " << maxTestTimeInMs << "ms but took " << testTimeInMs << "ms."; result.OnTestFailure(curTest->m_details, stream.GetText()); } result.OnTestFinish(curTest->m_details, testTimeInMs/1000.0f); } curTest = curTest->next; } float const secondsElapsed = overallTimer.GetTimeInMs() / 1000.0f; reporter.ReportSummary(result.GetTotalTestCount(), result.GetFailedTestCount(), result.GetFailureCount(), secondsElapsed); return result.GetFailureCount(); } int RunAllTests() { TestReporterStdout reporter; return RunAllTests(reporter, Test::GetTestList(), 0); } } ode-0.16/tests/UnitTest++/src/DeferredTestReporter.h0000664000175200017520000000120313403272463017250 00000000000000#ifndef UNITTEST_DEFERREDTESTREPORTER_H #define UNITTEST_DEFERREDTESTREPORTER_H #include "TestReporter.h" #include "DeferredTestResult.h" #include namespace UnitTest { class DeferredTestReporter : public TestReporter { public: virtual void ReportTestStart(TestDetails const& details); virtual void ReportFailure(TestDetails const& details, char const* failure); virtual void ReportTestFinish(TestDetails const& details, float secondsElapsed); typedef std::vector< DeferredTestResult > DeferredTestResultList; DeferredTestResultList& GetResults(); private: DeferredTestResultList m_results; }; } #endif ode-0.16/tests/UnitTest++/src/AssertException.h0000664000175200017520000000077313403272463016300 00000000000000#ifndef UNITTEST_ASSERTEXCEPTION_H #define UNITTEST_ASSERTEXCEPTION_H #include namespace UnitTest { class AssertException : public std::exception { public: AssertException(char const* description, char const* filename, int lineNumber); virtual ~AssertException() throw(); virtual char const* what() const throw(); char const* Filename() const; int LineNumber() const; private: char m_description[512]; char m_filename[256]; int m_lineNumber; }; } #endif ode-0.16/tests/UnitTest++/src/Checks.h0000664000175200017520000001101413403272463014346 00000000000000#ifndef UNITTEST_CHECKS_H #define UNITTEST_CHECKS_H #include "Config.h" #include "TestResults.h" #include "MemoryOutStream.h" namespace UnitTest { template< typename Value > bool Check(Value const value) { return !!value; // doing double negative to avoid silly VS warnings } template< typename Expected, typename Actual > void CheckEqual(TestResults& results, Expected const expected, Actual const actual, TestDetails const& details) { if (!(expected == actual)) { UnitTest::MemoryOutStream stream; stream << "Expected " << expected << " but was " << actual; results.OnTestFailure(details, stream.GetText()); } } void CheckEqual(TestResults& results, char const* expected, char const* actual, TestDetails const& details); void CheckEqual(TestResults& results, char* expected, char* actual, TestDetails const& details); void CheckEqual(TestResults& results, char* expected, char const* actual, TestDetails const& details); void CheckEqual(TestResults& results, char const* expected, char* actual, TestDetails const& details); template< typename Expected, typename Actual, typename Tolerance > bool AreClose(Expected const expected, Actual const actual, Tolerance const tolerance) { return (actual >= (expected - tolerance)) && (actual <= (expected + tolerance)); } template< typename Expected, typename Actual, typename Tolerance > void CheckClose(TestResults& results, Expected const expected, Actual const actual, Tolerance const tolerance, TestDetails const& details) { if (!AreClose(expected, actual, tolerance)) { UnitTest::MemoryOutStream stream; stream << "Expected " << expected << " +/- " << tolerance << " but was " << actual; results.OnTestFailure(details, stream.GetText()); } } template< typename Expected, typename Actual > void CheckArrayEqual(TestResults& results, Expected const expected, Actual const actual, int const count, TestDetails const& details) { bool equal = true; for (int i = 0; i < count; ++i) equal &= (expected[i] == actual[i]); if (!equal) { UnitTest::MemoryOutStream stream; stream << "Expected [ "; for (int i = 0; i < count; ++i) stream << expected[i] << " "; stream << "] but was [ "; for (int i = 0; i < count; ++i) stream << actual[i] << " "; stream << "]"; results.OnTestFailure(details, stream.GetText()); } } template< typename Expected, typename Actual, typename Tolerance > bool ArrayAreClose(Expected const expected, Actual const actual, int const count, Tolerance const tolerance) { bool equal = true; for (int i = 0; i < count; ++i) equal &= AreClose(expected[i], actual[i], tolerance); return equal; } template< typename Expected, typename Actual, typename Tolerance > void CheckArrayClose(TestResults& results, Expected const expected, Actual const actual, int const count, Tolerance const tolerance, TestDetails const& details) { bool equal = ArrayAreClose(expected, actual, count, tolerance); if (!equal) { UnitTest::MemoryOutStream stream; stream << "Expected [ "; for (int i = 0; i < count; ++i) stream << expected[i] << " "; stream << "] +/- " << tolerance << " but was [ "; for (int i = 0; i < count; ++i) stream << actual[i] << " "; stream << "]"; results.OnTestFailure(details, stream.GetText()); } } template< typename Expected, typename Actual, typename Tolerance > void CheckArray2DClose(TestResults& results, Expected const expected, Actual const actual, int const rows, int const columns, Tolerance const tolerance, TestDetails const& details) { bool equal = true; for (int i = 0; i < rows; ++i) equal &= ArrayAreClose(expected[i], actual[i], columns, tolerance); if (!equal) { UnitTest::MemoryOutStream stream; stream << "Expected [ "; for (int i = 0; i < rows; ++i) { stream << "[ "; for (int j = 0; j < columns; ++j) stream << expected[i][j] << " "; stream << "] "; } stream << "] +/- " << tolerance << " but was [ "; for (int i = 0; i < rows; ++i) { stream << "[ "; for (int j = 0; j < columns; ++j) stream << actual[i][j] << " "; stream << "] "; } stream << "]"; results.OnTestFailure(details, stream.GetText()); } } } #endif ode-0.16/tests/UnitTest++/src/TestReporter.cpp0000664000175200017520000000012713403272463016146 00000000000000#include "TestReporter.h" namespace UnitTest { TestReporter::~TestReporter() { } } ode-0.16/tests/UnitTest++/src/XmlTestReporter.h0000664000175200017520000000171413403272463016277 00000000000000#ifndef UNITTEST_XMLTESTREPORTER_H #define UNITTEST_XMLTESTREPORTER_H #include "DeferredTestReporter.h" #include namespace UnitTest { class XmlTestReporter : public DeferredTestReporter { public: explicit XmlTestReporter(std::ostream& ostream); virtual void ReportSummary(int totalTestCount, int failedTestCount, int failureCount, float secondsElapsed); private: XmlTestReporter(XmlTestReporter const&); XmlTestReporter& operator=(XmlTestReporter const&); void AddXmlElement(std::ostream& os, char const* encoding); void BeginResults(std::ostream& os, int totalTestCount, int failedTestCount, int failureCount, float secondsElapsed); void EndResults(std::ostream& os); void BeginTest(std::ostream& os, DeferredTestResult const& result); void AddFailure(std::ostream& os, DeferredTestResult const& result); void EndTest(std::ostream& os, DeferredTestResult const& result); std::ostream& m_ostream; }; } #endif ode-0.16/tests/UnitTest++/src/Win32/0000775000175200017520000000000013403273061013755 500000000000000ode-0.16/tests/UnitTest++/src/Win32/Makefile.am0000664000175200017520000000013013403272463015730 00000000000000check_LTLIBRARIES = libhelper.la libhelper_la_SOURCES = TimeHelpers.cpp TimeHelpers.h ode-0.16/tests/UnitTest++/src/Win32/TimeHelpers.h0000664000175200017520000000110313403272463016267 00000000000000#ifndef UNITTEST_TIMEHELPERS_H #define UNITTEST_TIMEHELPERS_H #include "../Config.h" #ifdef UNITTEST_MINGW #ifndef __int64 #define __int64 long long #endif #endif namespace UnitTest { class Timer { public: Timer(); void Start(); int GetTimeInMs() const; private: __int64 GetTime() const; void* m_threadId; #if defined(_WIN64) unsigned __int64 m_processAffinityMask; #else unsigned long m_processAffinityMask; #endif __int64 m_startTime; __int64 m_frequency; }; namespace TimeHelpers { void SleepMs (int ms); } } #endif ode-0.16/tests/UnitTest++/src/Win32/TimeHelpers.cpp0000664000175200017520000000175313403272463016635 00000000000000#include "TimeHelpers.h" #include namespace UnitTest { Timer::Timer() : m_startTime(0) { m_threadId = ::GetCurrentThread(); DWORD_PTR systemMask; ::GetProcessAffinityMask(GetCurrentProcess(), &m_processAffinityMask, &systemMask); ::SetThreadAffinityMask(m_threadId, 1); ::QueryPerformanceFrequency(reinterpret_cast< LARGE_INTEGER* >(&m_frequency)); ::SetThreadAffinityMask(m_threadId, m_processAffinityMask); } void Timer::Start() { m_startTime = GetTime(); } int Timer::GetTimeInMs() const { __int64 const elapsedTime = GetTime() - m_startTime; double const seconds = double(elapsedTime) / double(m_frequency); return int(seconds * 1000.0f); } __int64 Timer::GetTime() const { LARGE_INTEGER curTime; ::SetThreadAffinityMask(m_threadId, 1); ::QueryPerformanceCounter(&curTime); ::SetThreadAffinityMask(m_threadId, m_processAffinityMask); return curTime.QuadPart; } void TimeHelpers::SleepMs(int const ms) { ::Sleep(ms); } } ode-0.16/tests/UnitTest++/src/Win32/Makefile.in0000664000175200017520000004503113403272663015754 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = tests/UnitTest++/src/Win32 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/ode/src/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = libhelper_la_LIBADD = am_libhelper_la_OBJECTS = TimeHelpers.lo libhelper_la_OBJECTS = $(am_libhelper_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/ode/src depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) AM_V_CXX = $(am__v_CXX_@AM_V@) am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libhelper_la_SOURCES) DIST_SOURCES = $(libhelper_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CCD_CFLAGS = @CCD_CFLAGS@ CCD_LIBS = @CCD_LIBS@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXTRA_LIBTOOL_LDFLAGS = @EXTRA_LIBTOOL_LDFLAGS@ FGREP = @FGREP@ GL_LIBS = @GL_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSTDCXX = @LIBSTDCXX@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ ODE_PRECISION = @ODE_PRECISION@ ODE_VERSION = @ODE_VERSION@ ODE_VERSION_INFO = @ODE_VERSION_INFO@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ WINDRES = @WINDRES@ X11_CFLAGS = @X11_CFLAGS@ X11_LIBS = @X11_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_WINDRES = @ac_ct_WINDRES@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ check_LTLIBRARIES = libhelper.la libhelper_la_SOURCES = TimeHelpers.cpp TimeHelpers.h all: all-am .SUFFIXES: .SUFFIXES: .cpp .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/UnitTest++/src/Win32/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tests/UnitTest++/src/Win32/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-checkLTLIBRARIES: -test -z "$(check_LTLIBRARIES)" || rm -f $(check_LTLIBRARIES) @list='$(check_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libhelper.la: $(libhelper_la_OBJECTS) $(libhelper_la_DEPENDENCIES) $(EXTRA_libhelper_la_DEPENDENCIES) $(AM_V_CXXLD)$(CXXLINK) $(libhelper_la_OBJECTS) $(libhelper_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TimeHelpers.Plo@am__quote@ .cpp.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cpp.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cpp.lo: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_LTLIBRARIES) check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-checkLTLIBRARIES clean-generic clean-libtool \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ clean-checkLTLIBRARIES clean-generic clean-libtool \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ode-0.16/tests/UnitTest++/src/TestResults.h0000664000175200017520000000136113403272463015453 00000000000000#ifndef UNITTEST_TESTRESULTS_H #define UNITTEST_TESTRESULTS_H namespace UnitTest { class TestReporter; class TestDetails; class TestResults { public: explicit TestResults(TestReporter* reporter = 0); void OnTestStart(TestDetails const& test); void OnTestFailure(TestDetails const& test, char const* failure); void OnTestFinish(TestDetails const& test, float secondsElapsed); int GetTotalTestCount() const; int GetFailedTestCount() const; int GetFailureCount() const; private: TestReporter* m_testReporter; int m_totalTestCount; int m_failedTestCount; int m_failureCount; bool m_currentTestFailed; TestResults(TestResults const&); TestResults& operator =(TestResults const&); }; } #endif ode-0.16/tests/UnitTest++/src/TimeConstraint.cpp0000664000175200017520000000122513403272463016447 00000000000000#include "TimeConstraint.h" #include "TestResults.h" #include "MemoryOutStream.h" namespace UnitTest { TimeConstraint::TimeConstraint(int ms, TestResults& result, TestDetails const& details) : m_result(result) , m_details(details) , m_maxMs(ms) { m_timer.Start(); } TimeConstraint::~TimeConstraint() { int const totalTimeInMs = m_timer.GetTimeInMs(); if (totalTimeInMs > m_maxMs) { MemoryOutStream stream; stream << "Time constraint failed. Expected to run test under " << m_maxMs << "ms but took " << totalTimeInMs << "ms."; m_result.OnTestFailure(m_details, stream.GetText()); } } } ode-0.16/tests/UnitTest++/src/DeferredTestResult.cpp0000664000175200017520000000060513403272463017264 00000000000000#include "DeferredTestResult.h" #include namespace UnitTest { DeferredTestResult::DeferredTestResult() : suiteName("") , testName("") , failureFile("") , timeElapsed(0.0f) , failed(false) { } DeferredTestResult::DeferredTestResult(char const* suite, char const* test) : suiteName(suite) , testName(test) , failureFile("") , timeElapsed(0.0f) , failed(false) { } } ode-0.16/tests/UnitTest++/src/TestSuite.h0000664000175200017520000000026413403272463015104 00000000000000#ifndef UNITTEST_TESTSUITE_H #define UNITTEST_TESTSUITE_H namespace UnitTestSuite { inline char const* GetSuiteName () { return "DefaultSuite"; } } #endif ode-0.16/tests/UnitTest++/src/Makefile.in0000664000175200017520000006322313403272663015055 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = tests/UnitTest++/src ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/ode/src/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = @WIN32_FALSE@libunittestpp_la_DEPENDENCIES = \ @WIN32_FALSE@ $(builddir)/Posix/libhelper.la @WIN32_TRUE@libunittestpp_la_DEPENDENCIES = \ @WIN32_TRUE@ $(builddir)/Win32/libhelper.la am_libunittestpp_la_OBJECTS = AssertException.lo Checks.lo \ DeferredTestReporter.lo DeferredTestResult.lo \ MemoryOutStream.lo ReportAssert.lo Test.lo TestDetails.lo \ TestList.lo TestReporter.lo TestReporterStdout.lo \ TestResults.lo TestRunner.lo TimeConstraint.lo \ XmlTestReporter.lo libunittestpp_la_OBJECTS = $(am_libunittestpp_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/ode/src depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) AM_V_CXX = $(am__v_CXX_@AM_V@) am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libunittestpp_la_SOURCES) DIST_SOURCES = $(libunittestpp_la_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = Posix Win32 am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CCD_CFLAGS = @CCD_CFLAGS@ CCD_LIBS = @CCD_LIBS@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXTRA_LIBTOOL_LDFLAGS = @EXTRA_LIBTOOL_LDFLAGS@ FGREP = @FGREP@ GL_LIBS = @GL_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSTDCXX = @LIBSTDCXX@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ ODE_PRECISION = @ODE_PRECISION@ ODE_VERSION = @ODE_VERSION@ ODE_VERSION_INFO = @ODE_VERSION_INFO@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ WINDRES = @WINDRES@ X11_CFLAGS = @X11_CFLAGS@ X11_LIBS = @X11_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_WINDRES = @ac_ct_WINDRES@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ @WIN32_FALSE@SUBDIRS = Posix @WIN32_TRUE@SUBDIRS = Win32 check_LTLIBRARIES = libunittestpp.la libunittestpp_la_SOURCES = AssertException.cpp AssertException.h \ CheckMacros.h Checks.cpp \ Checks.h Config.h \ DeferredTestReporter.cpp DeferredTestReporter.h \ DeferredTestResult.cpp DeferredTestResult.h \ MemoryOutStream.cpp MemoryOutStream.h \ ReportAssert.cpp ReportAssert.h \ Test.cpp TestDetails.cpp \ TestDetails.h Test.h \ TestList.cpp TestList.h \ TestMacros.h TestReporter.cpp \ TestReporter.h TestReporterStdout.cpp \ TestReporterStdout.h TestResults.cpp \ TestResults.h TestRunner.cpp \ TestRunner.h TestSuite.h \ TimeConstraint.cpp TimeConstraint.h \ TimeHelpers.h UnitTest++.h \ XmlTestReporter.cpp XmlTestReporter.h @WIN32_FALSE@libunittestpp_la_LIBADD = $(builddir)/Posix/libhelper.la @WIN32_TRUE@libunittestpp_la_LIBADD = $(builddir)/Win32/libhelper.la all: all-recursive .SUFFIXES: .SUFFIXES: .cpp .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/UnitTest++/src/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tests/UnitTest++/src/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-checkLTLIBRARIES: -test -z "$(check_LTLIBRARIES)" || rm -f $(check_LTLIBRARIES) @list='$(check_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libunittestpp.la: $(libunittestpp_la_OBJECTS) $(libunittestpp_la_DEPENDENCIES) $(EXTRA_libunittestpp_la_DEPENDENCIES) $(AM_V_CXXLD)$(CXXLINK) $(libunittestpp_la_OBJECTS) $(libunittestpp_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AssertException.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Checks.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DeferredTestReporter.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DeferredTestResult.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MemoryOutStream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ReportAssert.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Test.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TestDetails.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TestList.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TestReporter.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TestReporterStdout.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TestResults.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TestRunner.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TimeConstraint.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XmlTestReporter.Plo@am__quote@ .cpp.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cpp.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cpp.lo: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_LTLIBRARIES) check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-checkLTLIBRARIES clean-generic clean-libtool \ mostlyclean-am distclean: distclean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(am__recursive_targets) check-am install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-checkLTLIBRARIES clean-generic \ clean-libtool cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ode-0.16/tests/UnitTest++/src/TestList.h0000664000175200017520000000051213403272463014722 00000000000000#ifndef UNITTEST_TESTLIST_H #define UNITTEST_TESTLIST_H namespace UnitTest { class Test; class TestList { public: TestList(); void Add (Test* test); const Test* GetHead() const; private: Test* m_head; Test* m_tail; }; class ListAdder { public: ListAdder(TestList& list, Test* test); }; } #endif ode-0.16/tests/UnitTest++/src/TestResults.cpp0000664000175200017520000000224113403272463016004 00000000000000#include "TestResults.h" #include "TestReporter.h" #include "TestDetails.h" namespace UnitTest { TestResults::TestResults(TestReporter* testReporter) : m_testReporter(testReporter) , m_totalTestCount(0) , m_failedTestCount(0) , m_failureCount(0) , m_currentTestFailed(false) { } void TestResults::OnTestStart(TestDetails const& test) { ++m_totalTestCount; m_currentTestFailed = false; if (m_testReporter) m_testReporter->ReportTestStart(test); } void TestResults::OnTestFailure(TestDetails const& test, char const* failure) { ++m_failureCount; if (!m_currentTestFailed) { ++m_failedTestCount; m_currentTestFailed = true; } if (m_testReporter) m_testReporter->ReportFailure(test, failure); } void TestResults::OnTestFinish(TestDetails const& test, float secondsElapsed) { if (m_testReporter) m_testReporter->ReportTestFinish(test, secondsElapsed); } int TestResults::GetTotalTestCount() const { return m_totalTestCount; } int TestResults::GetFailedTestCount() const { return m_failedTestCount; } int TestResults::GetFailureCount() const { return m_failureCount; } } ode-0.16/tests/UnitTest++/src/Checks.cpp0000664000175200017520000000222613403272463014706 00000000000000#include "Checks.h" #include namespace UnitTest { namespace { void CheckStringsEqual(TestResults& results, char const* expected, char const* actual, TestDetails const& details) { if (std::strcmp(expected, actual)) { UnitTest::MemoryOutStream stream; stream << "Expected " << expected << " but was " << actual; results.OnTestFailure(details, stream.GetText()); } } } void CheckEqual(TestResults& results, char const* expected, char const* actual, TestDetails const& details) { CheckStringsEqual(results, expected, actual, details); } void CheckEqual(TestResults& results, char* expected, char* actual, TestDetails const& details) { CheckStringsEqual(results, expected, actual, details); } void CheckEqual(TestResults& results, char* expected, char const* actual, TestDetails const& details) { CheckStringsEqual(results, expected, actual, details); } void CheckEqual(TestResults& results, char const* expected, char* actual, TestDetails const& details) { CheckStringsEqual(results, expected, actual, details); } } ode-0.16/tests/UnitTest++/src/TestMacros.h0000664000175200017520000001176013403272463015242 00000000000000#ifndef UNITTEST_TESTMACROS_H #define UNITTEST_TESTMACROS_H #include "Config.h" #ifndef UNITTEST_POSIX #define UNITTEST_THROW_SIGNALS #else #include "Posix/SignalTranslator.h" #endif #ifdef TEST #error UnitTest++ redefines TEST #endif #define SUITE(Name) \ namespace Name { \ namespace UnitTestSuite { \ inline char const* GetSuiteName () { \ return #Name ; \ } \ } \ } \ namespace Name #define TEST_EX(Name, List) \ class Test##Name : public UnitTest::Test \ { \ public: \ Test##Name() : Test(#Name, UnitTestSuite::GetSuiteName(), __FILE__, __LINE__) {} \ private: \ virtual void RunImpl(UnitTest::TestResults& testResults_) const; \ } test##Name##Instance; \ \ UnitTest::ListAdder adder##Name (List, &test##Name##Instance); \ \ void Test##Name::RunImpl(UnitTest::TestResults& testResults_) const #define TEST(Name) TEST_EX(Name, UnitTest::Test::GetTestList()) #define TEST_FIXTURE_EX(Fixture, Name, List) \ class Fixture##Name##Helper : public Fixture \ { \ public: \ Fixture##Name##Helper(UnitTest::TestDetails const& details) : m_details(details) {} \ void RunTest(UnitTest::TestResults& testResults_); \ UnitTest::TestDetails const& m_details; \ private: \ Fixture##Name##Helper(Fixture##Name##Helper const&); \ Fixture##Name##Helper& operator =(Fixture##Name##Helper const&); \ }; \ \ class Test##Fixture##Name : public UnitTest::Test \ { \ public: \ Test##Fixture##Name() : Test(#Name, UnitTestSuite::GetSuiteName(), __FILE__, __LINE__) {} \ private: \ virtual void RunImpl(UnitTest::TestResults& testResults_) const; \ } test##Fixture##Name##Instance; \ \ UnitTest::ListAdder adder##Fixture##Name (List, &test##Fixture##Name##Instance); \ \ void Test##Fixture##Name::RunImpl(UnitTest::TestResults& testResults_) const \ { \ bool ctorOk = false; \ try { \ Fixture##Name##Helper fixtureHelper(m_details); \ ctorOk = true; \ try { \ UNITTEST_THROW_SIGNALS; \ fixtureHelper.RunTest(testResults_); \ } catch (UnitTest::AssertException const& e) { \ testResults_.OnTestFailure(UnitTest::TestDetails(m_details.testName, m_details.suiteName, e.Filename(), e.LineNumber()), e.what()); \ } catch (std::exception const& e) { \ UnitTest::MemoryOutStream stream; \ stream << "Unhandled exception: " << e.what(); \ testResults_.OnTestFailure(m_details, stream.GetText()); \ } catch (...) { testResults_.OnTestFailure(m_details, "Unhandled exception: Crash!"); } \ } \ catch (...) { \ if (ctorOk) \ { \ testResults_.OnTestFailure(UnitTest::TestDetails(m_details, __LINE__), \ "Unhandled exception while destroying fixture " #Fixture); \ } \ else \ { \ testResults_.OnTestFailure(UnitTest::TestDetails(m_details, __LINE__), \ "Unhandled exception while constructing fixture " #Fixture); \ } \ } \ } \ void Fixture##Name##Helper::RunTest(UnitTest::TestResults& testResults_) #define TEST_FIXTURE(Fixture,Name) TEST_FIXTURE_EX(Fixture, Name, UnitTest::Test::GetTestList()) #endif ode-0.16/tests/UnitTest++/src/XmlTestReporter.cpp0000664000175200017520000000635313403272463016636 00000000000000#include "XmlTestReporter.h" #include #include #include using std::string; using std::ostringstream; using std::ostream; namespace { void ReplaceChar(string& str, char const c, string const& replacement) { for (size_t pos = str.find(c); pos != string::npos; pos = str.find(c, pos + 1)) str.replace(pos, 1, replacement); } string XmlEscape(string const& value) { string escaped = value; ReplaceChar(escaped, '&', "&"); ReplaceChar(escaped, '<', "<"); ReplaceChar(escaped, '>', ">"); ReplaceChar(escaped, '\'', "'"); ReplaceChar(escaped, '\"', """); return escaped; } string BuildFailureMessage(string const& file, int const line, string const& message) { ostringstream failureMessage; failureMessage << file << "(" << line << ") : " << message; return failureMessage.str(); } } namespace UnitTest { XmlTestReporter::XmlTestReporter(ostream& ostream) : m_ostream(ostream) { } void XmlTestReporter::ReportSummary(int const totalTestCount, int const failedTestCount, int const failureCount, float const secondsElapsed) { AddXmlElement(m_ostream, NULL); BeginResults(m_ostream, totalTestCount, failedTestCount, failureCount, secondsElapsed); DeferredTestResultList const& results = GetResults(); for (DeferredTestResultList::const_iterator i = results.begin(); i != results.end(); ++i) { BeginTest(m_ostream, *i); if (i->failed) AddFailure(m_ostream, *i); EndTest(m_ostream, *i); } EndResults(m_ostream); } void XmlTestReporter::AddXmlElement(ostream& os, char const* encoding) { os << ""; } void XmlTestReporter::BeginResults(std::ostream& os, int const totalTestCount, int const failedTestCount, int const failureCount, float const secondsElapsed) { os << ""; } void XmlTestReporter::EndResults(std::ostream& os) { os << ""; } void XmlTestReporter::BeginTest(std::ostream& os, DeferredTestResult const& result) { os << ""; else os << "/>"; } void XmlTestReporter::AddFailure(std::ostream& os, DeferredTestResult const& result) { os << ">"; // close element for (DeferredTestResult::FailureVec::const_iterator it = result.failures.begin(); it != result.failures.end(); ++it) { string const escapedMessage = XmlEscape(it->second); string const message = BuildFailureMessage(result.failureFile, it->first, escapedMessage); os << ""; } } } ode-0.16/tests/UnitTest++/src/CheckMacros.h0000664000175200017520000000660513403272463015342 00000000000000#ifndef UNITTEST_CHECKMACROS_H #define UNITTEST_CHECKMACROS_H #include "Checks.h" #include "AssertException.h" #include "MemoryOutStream.h" #include "TestDetails.h" #ifdef CHECK #error UnitTest++ redefines CHECK #endif #define CHECK(value) \ do \ { \ try { \ if (!UnitTest::Check(value)) \ testResults_.OnTestFailure( UnitTest::TestDetails(m_details, __LINE__), #value); \ } \ catch (...) { \ testResults_.OnTestFailure(UnitTest::TestDetails(m_details, __LINE__), \ "Unhandled exception in CHECK(" #value ")"); \ } \ } while (0) #define CHECK_EQUAL(expected, actual) \ do \ { \ try { \ UnitTest::CheckEqual(testResults_, expected, actual, UnitTest::TestDetails(m_details, __LINE__)); \ } \ catch (...) { \ testResults_.OnTestFailure(UnitTest::TestDetails(m_details, __LINE__), \ "Unhandled exception in CHECK_EQUAL(" #expected ", " #actual ")"); \ } \ } while (0) #define CHECK_CLOSE(expected, actual, tolerance) \ do \ { \ try { \ UnitTest::CheckClose(testResults_, expected, actual, tolerance, UnitTest::TestDetails(m_details, __LINE__)); \ } \ catch (...) { \ testResults_.OnTestFailure(UnitTest::TestDetails(m_details, __LINE__), \ "Unhandled exception in CHECK_CLOSE(" #expected ", " #actual ")"); \ } \ } while (0) #define CHECK_ARRAY_EQUAL(expected, actual, count) \ do \ { \ try { \ UnitTest::CheckArrayEqual(testResults_, expected, actual, count, UnitTest::TestDetails(m_details, __LINE__)); \ } \ catch (...) { \ testResults_.OnTestFailure(UnitTest::TestDetails(m_details, __LINE__), \ "Unhandled exception in CHECK_ARRAY_EQUAL(" #expected ", " #actual ")"); \ } \ } while (0) #define CHECK_ARRAY_CLOSE(expected, actual, count, tolerance) \ do \ { \ try { \ UnitTest::CheckArrayClose(testResults_, expected, actual, count, tolerance, UnitTest::TestDetails(m_details, __LINE__)); \ } \ catch (...) { \ testResults_.OnTestFailure(UnitTest::TestDetails(m_details, __LINE__), \ "Unhandled exception in CHECK_ARRAY_CLOSE(" #expected ", " #actual ")"); \ } \ } while (0) #define CHECK_ARRAY2D_CLOSE(expected, actual, rows, columns, tolerance) \ do \ { \ try { \ UnitTest::CheckArray2DClose(testResults_, expected, actual, rows, columns, tolerance, UnitTest::TestDetails(m_details, __LINE__)); \ } \ catch (...) { \ testResults_.OnTestFailure(UnitTest::TestDetails(m_details, __LINE__), \ "Unhandled exception in CHECK_ARRAY_CLOSE(" #expected ", " #actual ")"); \ } \ } while (0) #define CHECK_THROW(expression, ExpectedExceptionType) \ do \ { \ bool caught_ = false; \ try { expression; } \ catch (ExpectedExceptionType const&) { caught_ = true; } \ catch (...) {} \ if (!caught_) \ testResults_.OnTestFailure(UnitTest::TestDetails(m_details, __LINE__), "Expected exception: \"" #ExpectedExceptionType "\" not thrown"); \ } while(0) #define CHECK_ASSERT(expression) \ CHECK_THROW(expression, UnitTest::AssertException); #endif ode-0.16/tests/UnitTest++/src/AssertException.cpp0000664000175200017520000000107113403272463016623 00000000000000#include "AssertException.h" #include namespace UnitTest { AssertException::AssertException(char const* description, char const* filename, int const lineNumber) : m_lineNumber(lineNumber) { std::strcpy(m_description, description); std::strcpy(m_filename, filename); } AssertException::~AssertException() throw() { } char const* AssertException::what() const throw() { return m_description; } char const* AssertException::Filename() const { return m_filename; } int AssertException::LineNumber() const { return m_lineNumber; } } ode-0.16/tests/UnitTest++/src/Posix/0000775000175200017520000000000013403273061014155 500000000000000ode-0.16/tests/UnitTest++/src/Posix/Makefile.am0000664000175200017520000000023213403272463016133 00000000000000check_LTLIBRARIES = libhelper.la libhelper_la_SOURCES = SignalTranslator.cpp SignalTranslator.h \ TimeHelpers.cpp TimeHelpers.h ode-0.16/tests/UnitTest++/src/Posix/SignalTranslator.cpp0000664000175200017520000000210413403272463020072 00000000000000#include "SignalTranslator.h" namespace UnitTest { sigjmp_buf* SignalTranslator::s_jumpTarget = 0; namespace { void SignalHandler (int sig) { siglongjmp(*SignalTranslator::s_jumpTarget, sig ); } } SignalTranslator::SignalTranslator () { m_oldJumpTarget = s_jumpTarget; s_jumpTarget = &m_currentJumpTarget; struct sigaction action; action.sa_flags = 0; action.sa_handler = SignalHandler; sigemptyset( &action.sa_mask ); sigaction( SIGSEGV, &action, &m_old_SIGSEGV_action ); sigaction( SIGFPE , &action, &m_old_SIGFPE_action ); sigaction( SIGTRAP, &action, &m_old_SIGTRAP_action ); sigaction( SIGBUS , &action, &m_old_SIGBUS_action ); sigaction( SIGILL , &action, &m_old_SIGBUS_action ); } SignalTranslator::~SignalTranslator() { sigaction( SIGILL , &m_old_SIGBUS_action , 0 ); sigaction( SIGBUS , &m_old_SIGBUS_action , 0 ); sigaction( SIGTRAP, &m_old_SIGTRAP_action, 0 ); sigaction( SIGFPE , &m_old_SIGFPE_action , 0 ); sigaction( SIGSEGV, &m_old_SIGSEGV_action, 0 ); s_jumpTarget = m_oldJumpTarget; } } ode-0.16/tests/UnitTest++/src/Posix/TimeHelpers.h0000664000175200017520000000046213403272463016476 00000000000000#ifndef UNITTEST_TIMEHELPERS_H #define UNITTEST_TIMEHELPERS_H #include namespace UnitTest { class Timer { public: Timer(); void Start(); int GetTimeInMs() const; private: struct timeval m_startTime; }; namespace TimeHelpers { void SleepMs (int ms); } } #endif ode-0.16/tests/UnitTest++/src/Posix/TimeHelpers.cpp0000664000175200017520000000102713403272463017027 00000000000000#include "TimeHelpers.h" #include namespace UnitTest { Timer::Timer() { m_startTime.tv_sec = 0; m_startTime.tv_usec = 0; } void Timer::Start() { gettimeofday(&m_startTime, 0); } int Timer::GetTimeInMs() const { struct timeval currentTime; gettimeofday(¤tTime, 0); int const dsecs = currentTime.tv_sec - m_startTime.tv_sec; int const dus = currentTime.tv_usec - m_startTime.tv_usec; return dsecs*1000 + dus/1000; } void TimeHelpers::SleepMs (int ms) { usleep(ms * 1000); } } ode-0.16/tests/UnitTest++/src/Posix/SignalTranslator.h0000664000175200017520000000162313403272463017544 00000000000000#ifndef UNITTEST_SIGNALTRANSLATOR_H #define UNITTEST_SIGNALTRANSLATOR_H #include #include namespace UnitTest { class SignalTranslator { public: SignalTranslator(); ~SignalTranslator(); static sigjmp_buf* s_jumpTarget; private: sigjmp_buf m_currentJumpTarget; sigjmp_buf* m_oldJumpTarget; struct sigaction m_old_SIGFPE_action; struct sigaction m_old_SIGTRAP_action; struct sigaction m_old_SIGSEGV_action; struct sigaction m_old_SIGBUS_action; struct sigaction m_old_SIGABRT_action; struct sigaction m_old_SIGALRM_action; }; #ifdef SOLARIS #define UNITTEST_EXTENSION #else #define UNITTEST_EXTENSION __extension__ #endif #define UNITTEST_THROW_SIGNALS \ UnitTest::SignalTranslator sig; \ if (UNITTEST_EXTENSION sigsetjmp(*UnitTest::SignalTranslator::s_jumpTarget, 1) != 0) \ throw ("Unhandled system exception"); } #endif ode-0.16/tests/UnitTest++/src/Posix/Makefile.in0000664000175200017520000004530113403272663016154 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = tests/UnitTest++/src/Posix ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/ode/src/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = libhelper_la_LIBADD = am_libhelper_la_OBJECTS = SignalTranslator.lo TimeHelpers.lo libhelper_la_OBJECTS = $(am_libhelper_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/ode/src depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) AM_V_CXX = $(am__v_CXX_@AM_V@) am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libhelper_la_SOURCES) DIST_SOURCES = $(libhelper_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CCD_CFLAGS = @CCD_CFLAGS@ CCD_LIBS = @CCD_LIBS@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXTRA_LIBTOOL_LDFLAGS = @EXTRA_LIBTOOL_LDFLAGS@ FGREP = @FGREP@ GL_LIBS = @GL_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSTDCXX = @LIBSTDCXX@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ ODE_PRECISION = @ODE_PRECISION@ ODE_VERSION = @ODE_VERSION@ ODE_VERSION_INFO = @ODE_VERSION_INFO@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ WINDRES = @WINDRES@ X11_CFLAGS = @X11_CFLAGS@ X11_LIBS = @X11_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_WINDRES = @ac_ct_WINDRES@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ check_LTLIBRARIES = libhelper.la libhelper_la_SOURCES = SignalTranslator.cpp SignalTranslator.h \ TimeHelpers.cpp TimeHelpers.h all: all-am .SUFFIXES: .SUFFIXES: .cpp .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/UnitTest++/src/Posix/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tests/UnitTest++/src/Posix/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-checkLTLIBRARIES: -test -z "$(check_LTLIBRARIES)" || rm -f $(check_LTLIBRARIES) @list='$(check_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libhelper.la: $(libhelper_la_OBJECTS) $(libhelper_la_DEPENDENCIES) $(EXTRA_libhelper_la_DEPENDENCIES) $(AM_V_CXXLD)$(CXXLINK) $(libhelper_la_OBJECTS) $(libhelper_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SignalTranslator.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TimeHelpers.Plo@am__quote@ .cpp.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cpp.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cpp.lo: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_LTLIBRARIES) check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-checkLTLIBRARIES clean-generic clean-libtool \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ clean-checkLTLIBRARIES clean-generic clean-libtool \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ode-0.16/tests/UnitTest++/src/ReportAssert.cpp0000664000175200017520000000032013403272463016134 00000000000000#include "AssertException.h" namespace UnitTest { void ReportAssert(char const* description, char const* filename, int const lineNumber) { throw AssertException(description, filename, lineNumber); } } ode-0.16/tests/UnitTest++/Makefile.am0000664000175200017520000000010013403272463014234 00000000000000# Makefile.am for UnitTest++ SUBDIRS = src EXTRA_DIST = docs ode-0.16/tests/UnitTest++/docs/0000775000175200017520000000000013403272463013221 500000000000000ode-0.16/tests/UnitTest++/docs/UnitTest++.html0000664000175200017520000003011113403272463015730 00000000000000 UnitTest++ in brief

UnitTest++ in brief

Introduction

This little document serves as bare-bones documentation for UnitTest++.

For background, goals and license details, see:

The documentation, while sparse, aims to be practical, so it should give you enough info to get started using UnitTest++ as fast as possible.

Building UnitTest++

Building UnitTest++ will be specific to each platform and build environment, but it should be straightforward.

Building with Visual Studio

If you are using Visual Studio, go for either of the provided .sln files, depending on version. There are no prefabricated solutions for versions earlier than VS.NET 2003, but we have had reports of people building UnitTest++ with at least VS.NET 2002.

Building with Make

The bundled makefile is written to build with g++. It also needs sed installed in the path, and to be able to use the mv and rm shell commands. The makefile should be usable on most Posix-like platforms.

Do "make all" to generate a library and test executable. A final build step runs all unit tests to make sure that the result works as expected.

Packaging

You'll probably want to keep the generated library in a shared space in source control, so you can reuse it for multiple test projects. A redistributable package of UnitTest++ would consist of the generated library file, and all of the header files in UnitTest++/src/ and its per-platform subfolders. The tests directory only contains the unit tests for the library, and need not be included.

Using UnitTest++

The source code for UnitTest++ comes with a full test suite written using UnitTest++. This is a great place to learn techniques for testing. There is one sample .cpp file: UnitTest++/src/tests/TestUnitTest++.cpp. It covers most of UnitTest++'s features in an easy-to-grasp context, so start there if you want a quick overview of typical usage.

Getting started

Listed below is a minimal C++ program to run a failing test through UnitTest++.

  // test.cpp
  #include <UnitTest++.h>

  TEST(FailSpectacularly)
  {
    CHECK(false);
  }

  int main()
  {
    return UnitTest::RunAllTests();
  }

UnitTest++.h is a facade header for UnitTest++, so including that should get you all features of the library. All classes and free functions are placed in namespace UnitTest, so you need to either qualify their full names (as with RunAllTests() in the example) or add a using namespace UnitTest; statement in your .cpp files. Note that any mention of UnitTest++ functions and classes in this document assume that the UnitTest namespace has been opened.

Compiling and linking this program with UnitTest++'s static library into an executable, and running it, will produce the following output (details may vary):

  .\test.cpp(5): error: Failure in FailSpectacularly: false
  FAILED: 1 out of 1 tests failed (1 failures).
  Test time: 0.00 seconds.

UnitTest++ attempts to report every failure in an IDE-friendly format, depending on platform (e.g. you can double-click it in Visual Studio's error list.) The exit code will be the number of failed tests, so that a failed test run always returns a non-zero exit code.

Test macros

To add a test, simply put the following code in a .cpp file of your choice:

  TEST(YourTestName)
  {
  }

The TEST macro contains enough machinery to turn this slightly odd-looking syntax into legal C++, and automatically register the test in a global list. This test list forms the basis of what is executed by RunAllTests().

If you want to re-use a set of test data for more than one test, or provide setup/teardown for tests, you can use the TEST_FIXTURE macro instead. The macro requires that you pass it a class name that it will instantiate, so any setup and teardown code should be in its constructor and destructor.

  struct SomeFixture
  {
    SomeFixture() { /* some setup */ }
    ~SomeFixture() { /* some teardown */ }

    int testData;
  };
 
  TEST_FIXTURE(SomeFixture, YourTestName)
  {
    int temp = testData;
  }

Note how members of the fixture are used as if they are a part of the test, since the macro-generated test class derives from the provided fixture class.

Suite macros

Tests can be grouped into suites, using the SUITE macro. A suite serves as a namespace for test names, so that the same test name can be used in two difference contexts.

  SUITE(YourSuiteName)
  {
    TEST(YourTestName)
    {
    }

    TEST(YourOtherTestName)
    {
    }
  }

This will place the tests into a C++ namespace called YourSuiteName, and make the suite name available to UnitTest++. RunAllTests() can be called for a specific suite name, so you can use this to build named groups of tests to be run together.

Simple check macros

In test cases, we want to check the results of our system under test. UnitTest++ provides a number of check macros that handle comparison and proper failure reporting.

The most basic variety is the boolean CHECK macro:

  CHECK(false); // fails

It will fail if the boolean expression evaluates to false.

For equality checks, it's generally better to use CHECK_EQUAL:

  CHECK_EQUAL(10, 20); // fails
  CHECK_EQUAL("foo", "bar"); // fails

Note how CHECK_EQUAL is overloaded for C strings, so you don't have to resort to strcmp or similar. There is no facility for case-insensitive comparison or string searches, so you may have to drop down to a plain boolean CHECK with help from the CRT:

  CHECK(std::strstr("zaza", "az") != 0); // succeeds

For floating-point comparison, equality isn't necessarily well-defined, so you should prefer the CHECK_CLOSE macro:

  CHECK_CLOSE(3.14, 3.1415, 0.01); // succeeds

All of the macros are tailored to avoid unintended side-effects, for example:

  TEST(CheckMacrosHaveNoSideEffects)
  {
    int i = 4;
    CHECK_EQUAL(5, ++i); // succeeds
    CHECK_EQUAL(5, i); // succeeds
  }

The check macros guarantee that the ++i expression isn't repeated internally, as demonstrated above.

Array check macros

There is a set of check macros for array comparison as well:

  const float oned[2] = { 10, 20 };
  CHECK_ARRAY_EQUAL(oned, oned, 2); // succeeds
  CHECK_ARRAY_CLOSE(oned, oned, 2, 0.00); // succeeds

  const float twod[2][3] = { {0, 1, 2}, {2, 3, 4} };
  CHECK_ARRAY2D_CLOSE(twod, twod, 2, 3, 0.00); // succeeds

The array equal macro compares elements using operator==, so CHECK_ARRAY_EQUAL won't work for an array of C strings, for example.

The array close macros are similar to the regular CHECK_CLOSE macro, and are really only useful for scalar types, that can be compared in terms of a difference between two array elements.

Note that the one-dimensional array macros work for std::vector as well, as it can be indexed just as a C array.

Exception check macros

Finally, there's a CHECK_THROW macro, which asserts that its enclosed expression throws the specified type:

  struct TestException {};
  CHECK_THROW(throw TestException(), TestException); // succeeds

UnitTest++ natively catches exceptions if your test code doesn't. So if your code under test throws any exception UnitTest++ will fail the test and report either using the what() method for std::exception derivatives or just a plain message for unknown exception types.

Should your test or code raise an irrecoverable error (an Access Violation on Win32, for example, or a signal on Linux), UnitTest++ will attempt to map them to an exception and fail the test, just as for other unhandled exceptions.

Time constraints

UnitTest++ can fail a test if it takes too long to complete, using so-called time constraints.

They come in two flavors; local and global time constraints.

Local time constraints are limited to the current scope, like so:

  TEST(YourTimedTest)
  {
     // Lengthy setup...

     {
        UNITTEST_TIME_CONSTRAINT(50);

        // Do time-critical stuff
     }

     // Lengthy teardown...
  }

The test will fail if the "Do time-critical stuff" block takes longer than 50 ms to complete. The time-consuming setup and teardown are not measured, since the time constraint is scope-bound. It's perfectly valid to have multiple local time constraints in the same test, as long as there is only one per block.

A global time constraint, on the other hand, requires that all of the tests in a test run are faster than a specified amount of time. This allows you, when you run a suite of tests, to ask UnitTest++ to fail it entirely if any test exceeds the global constraint. The max time is passed as a parameter to an overload of RunAllTests().

If you want to use a global time constraint, but have one test that is notoriously slow, you can exempt it from inspection by using the UNITTEST_TIME_CONSTRAINT_EXEMPT macro anywhere inside the test body.

  TEST(NotoriouslySlowTest)
  {
     UNITTEST_TIME_CONSTRAINT_EXEMPT();

     // Oh boy, this is going to take a while
     ...
  }

Test runners

The RunAllTests() function has an overload that lets you customize the behavior of the runner, such as global time constraints, custom reporters, which suite to run, etc.

  int RunAllTests(TestReporter& reporter, TestList const& list, char const* suiteName, int const maxTestTimeInMs);

If you attempt to pass custom parameters to RunAllTests(), note that the list parameter should have the value Test::GetTestList().

The parameterless RunAllTests() is a simple wrapper for this one, with sensible defaults.

Example setup

How to create a new test project varies depending on your environment, but here are some directions on common file structure and usage.

The general idea is that you keep one Main.cpp file with the entry-point which calls RunAllTests().

Then you can simply compile and link new .cpp files at will, typically one per test suite.

   + ShaverTests/
   |
   +- Main.cpp
   |
   +- TestBrush.cpp   
   +- TestEngine.cpp
   +- TestRazor.cpp   

Each of the Test*.cpp files will contain one or more TEST macro incantations with the associated test code. There are no source-level dependencies between Main.cpp and Test*.cpp, as the TEST macro handles the registration and setup necessary for RunAllTests() to find all tests compiled into the same final executable.

UnitTest++ does not require this structure, even if this is how the library itself does it. As long as your test project contains one or more TESTs and calls RunAllTests() at one point or another, it will be handled by UnitTest++.

It's common to make the generated executable start as a post-build step, so that merely building your test project will run the tests as well. Since the exit code is the count of failures, a failed test will generally break the build, as most build engines will fail a build if any step returns a non-zero exit code.

ode-0.16/tests/UnitTest++/COPYING0000664000175200017520000000206513403272463013247 00000000000000Copyright (c) 2006 Noel Llopis and Charles Nicholson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ode-0.16/tests/UnitTest++/README0000664000175200017520000000375313403272463013101 00000000000000UnitTest++ README Version: v1.3 Last update: 2007-4-22 UnitTest++ is free software. You may copy, distribute, and modify it under the terms of the License contained in the file COPYING distributed with this package. This license is the same as the MIT/X Consortium license. See src/tests/TestUnitTest++.cpp for usage. Authors: Noel Llopis (llopis@convexhull.com) Charles Nicholson (cn@cnicholson.net) Contributors: Jim Tilander (jim.tilander@gmail.com) Kim Grasman (kim@mvps.org) Jonathan Jansson (lilliemarck@users.sourceforge.net) Dirck Blaskey (listtarget2@danbala.com) Rory Driscoll (rorydriscoll@gmail.com) Dan Lind (podcat@gmail.com) Matt Kimmel (mattkimmel@gmail.com) -- Submitted with permission from Blue Fang Games Anthony Moralez (anthony.moralez@gmail.com) Jeff Dixon Release notes -------------- Version 1.3 (2007-4-22) - Removed dynamic memory allocations (other than streams) - MinGW support - Consistent (native) line endings - Minor bug fixing Version 1.2 (2006-10-29) - First pass at documentation. - More detailed error crash catching in fixtures. - Standard streams used for printing objects under check. This should allow the use of standard class types such as std::string or other custom classes with stream operators to ostream. - Standard streams can be optionally compiled off by defining UNITTEST_USE_CUSTOM_STREAMS in Config.h - Added named test suites - Added CHECK_ARRAY2D_CLOSE - Posix library name is libUnitTest++.a now - Floating point numbers are postfixed with f in the failure reports Version 1.1 (2006-04-18) - CHECK macros do not have side effects even if one of the parameters changes state - Removed CHECK_ARRAY_EQUAL (too similar to CHECK_ARRAY_CLOSE) - Added local and global time constraints - Removed dependencies on strstream - Improved Posix signal to exception translator - Failing tests are added to Visual Studio's error list - Fixed Visual Studio projects to work with spaces in directories Version 1.0 (2006-03-15) - Initial release ode-0.16/tests/UnitTest++/Makefile.in0000664000175200017520000004515113403272663014266 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Makefile.am for UnitTest++ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = tests/UnitTest++ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/ode/src/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in COPYING README DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CCD_CFLAGS = @CCD_CFLAGS@ CCD_LIBS = @CCD_LIBS@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXTRA_LIBTOOL_LDFLAGS = @EXTRA_LIBTOOL_LDFLAGS@ FGREP = @FGREP@ GL_LIBS = @GL_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSTDCXX = @LIBSTDCXX@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ ODE_PRECISION = @ODE_PRECISION@ ODE_VERSION = @ODE_VERSION@ ODE_VERSION_INFO = @ODE_VERSION_INFO@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ WINDRES = @WINDRES@ X11_CFLAGS = @X11_CFLAGS@ X11_LIBS = @X11_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_WINDRES = @ac_ct_WINDRES@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = src EXTRA_DIST = docs all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/UnitTest++/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tests/UnitTest++/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am tags tags-am uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ode-0.16/tests/Makefile.in0000664000175200017520000011042113403272663012352 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @GIMPACT_TRUE@am__append_1 = -DdTRIMESH_ENABLED -DdTRIMESH_GIMPACT @OPCODE_TRUE@am__append_2 = -DdTRIMESH_ENABLED -DdTRIMESH_OPCODE check_PROGRAMS = tests$(EXEEXT) TESTS = tests$(EXEEXT) subdir = tests ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/ode/src/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am_tests_OBJECTS = collision.$(OBJEXT) friction.$(OBJEXT) \ joint.$(OBJEXT) main.$(OBJEXT) odemath.$(OBJEXT) tests_OBJECTS = $(am_tests_OBJECTS) tests_DEPENDENCIES = $(top_builddir)/ode/src/libode.la joints/*.o \ UnitTest++/src/libunittestpp.la AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/ode/src depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) AM_V_CXX = $(am__v_CXX_@AM_V@) am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = SOURCES = $(tests_SOURCES) DIST_SOURCES = $(tests_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ check recheck distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp \ $(top_srcdir)/test-driver DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CCD_CFLAGS = @CCD_CFLAGS@ CCD_LIBS = @CCD_LIBS@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXTRA_LIBTOOL_LDFLAGS = @EXTRA_LIBTOOL_LDFLAGS@ FGREP = @FGREP@ GL_LIBS = @GL_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSTDCXX = @LIBSTDCXX@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ ODE_PRECISION = @ODE_PRECISION@ ODE_VERSION = @ODE_VERSION@ ODE_VERSION_INFO = @ODE_VERSION_INFO@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ WINDRES = @WINDRES@ X11_CFLAGS = @X11_CFLAGS@ X11_LIBS = @X11_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_WINDRES = @ac_ct_WINDRES@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = joints UnitTest++ AM_CPPFLAGS = -I$(srcdir)/UnitTest++/src -I$(top_srcdir)/include \ -I$(top_builddir)/include -I$(top_srcdir)/ode/src \ $(am__append_1) $(am__append_2) tests_SOURCES = \ collision.cpp \ friction.cpp \ joint.cpp \ main.cpp \ odemath.cpp tests_LDADD = \ $(top_builddir)/ode/src/libode.la \ joints/*.o \ UnitTest++/src/libunittestpp.la all: all-recursive .SUFFIXES: .SUFFIXES: .cpp .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tests/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list tests$(EXEEXT): $(tests_OBJECTS) $(tests_DEPENDENCIES) $(EXTRA_tests_DEPENDENCIES) @rm -f tests$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(tests_OBJECTS) $(tests_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collision.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/friction.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/joint.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/odemath.Po@am__quote@ .cpp.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cpp.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cpp.lo: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ elif test -n "$$redo_logs"; then \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? tests.log: tests$(EXEEXT) @p='tests$(EXEEXT)'; \ b='tests'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-checkPROGRAMS clean-generic clean-libtool \ mostlyclean-am distclean: distclean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(am__recursive_targets) check-am install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-TESTS check-am clean clean-checkPROGRAMS clean-generic \ clean-libtool cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am recheck tags tags-am \ uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ode-0.16/tests/joint.cpp0000664000175200017520000030205113403272463012134 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ //234567890123456789012345678901234567890123456789012345678901234567890123456789 // 1 2 3 4 5 6 7 //////////////////////////////////////////////////////////////////////////////// // This file create unit test for some of the functions found in: // ode/src/joint.cpp // // //////////////////////////////////////////////////////////////////////////////// #include #include #include "../ode/src/config.h" #include "../ode/src/joints/joints.h" //////////////////////////////////////////////////////////////////////////////// // Testing the Hinge2 Joint // SUITE(JointHinge2) { struct Hinge2GetInfo1_Fixture_1 { Hinge2GetInfo1_Fixture_1() { wId = dWorldCreate(); bId1 = dBodyCreate(wId); dBodySetPosition(bId1, 0, -1, 0); bId2 = dBodyCreate(wId); dBodySetPosition(bId2, 0, 1, 0); jId = dJointCreateHinge2(wId, 0); joint = (dxJointHinge2*)jId; dJointAttach(jId, bId1, bId2); dJointSetHinge2Anchor (jId, REAL(0.0), REAL(0.0), REAL(0.0)); } ~Hinge2GetInfo1_Fixture_1() { dWorldDestroy(wId); } dJointID jId; dxJointHinge2* joint; dWorldID wId; dBodyID bId1; dBodyID bId2; dxJoint::Info1 info; }; TEST_FIXTURE(Hinge2GetInfo1_Fixture_1, test_hinge2GetInfo1) { /* // ^Y // |---| HiStop // | | ^Y / // |B_2| | / // |---| | / // | ----- | / // Z <-- * Z<--|B_2|--* // / | \ ----- | \ // /|---|\ |---| \ // / | | \ | | \ // / |B_1| \ |B_1| \ // / |---| \ |---| \ //LoStop HiStop LoStop // // // // */ dMatrix3 R; dJointSetHinge2Param(jId, dParamLoStop, -M_PI/4.0); dJointSetHinge2Param(jId, dParamHiStop, M_PI/4.0); dxJoint::Info1 info; dxJointHinge2* joint = (dxJointHinge2*)jId; // Original position inside the limits joint->getInfo1(&info); CHECK_EQUAL(0, joint->limot1.limit); CHECK_EQUAL(4, info.m); // Move the body outside the Lo limits dBodySetPosition (bId2, 0, 0, 1); dRFromAxisAndAngle (R, 1, 0, 0, M_PI/2.0); dBodySetRotation (bId2, R); joint->getInfo1(&info); CHECK_EQUAL(1, joint->limot1.limit); CHECK_EQUAL(5, info.m); // Return to original position // Keep the limits dBodySetPosition (bId2, 0, 1, 0); dRFromAxisAndAngle (R, 1, REAL(0.0), REAL(0.0), REAL(0.0)); dBodySetRotation (bId2, R); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limot1.limit); CHECK_EQUAL(4, info.m); // Move the body outside the Lo limits dBodySetPosition (bId2, 0, 0, 1); dRFromAxisAndAngle (R, 1, 0, 0, M_PI/2.0); dBodySetRotation (bId2, R); joint->getInfo1(&info); CHECK_EQUAL(1, joint->limot1.limit); CHECK_EQUAL(5, info.m); // Return to original position // and remove the limits dBodySetPosition (bId2, 0, 1, 0); dRFromAxisAndAngle (R, 1, REAL(0.0), REAL(0.0), REAL(0.0)); dBodySetRotation (bId2, R); dJointSetHinge2Param(jId, dParamLoStop, -2*M_PI); dJointSetHinge2Param(jId, dParamHiStop, 2*M_PI); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limot1.limit); CHECK_EQUAL(4, info.m); // Set the limits // Move pass the Hi limits dJointSetHinge2Param(jId, dParamLoStop, -M_PI/4.0); dJointSetHinge2Param(jId, dParamHiStop, M_PI/4.0); dBodySetPosition (bId2, 0, 0, 1); dRFromAxisAndAngle (R, 1, 0, 0, -M_PI/2.0); dBodySetRotation (bId2, R); joint->getInfo1(&info); CHECK_EQUAL(2, joint->limot1.limit); CHECK_EQUAL(5, info.m); // Return to original position // Keep the limits dBodySetPosition (bId2, 0, 1, 0); dRFromAxisAndAngle (R, 1, REAL(0.0), REAL(0.0), REAL(0.0)); dBodySetRotation (bId2, R); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limot1.limit); CHECK_EQUAL(4, info.m); // Move the pass the Hi limit dBodySetPosition (bId2, 0, 0, 1); dRFromAxisAndAngle (R, 1, 0, 0, -M_PI/2.0); dBodySetRotation (bId2, R); joint->getInfo1(&info); CHECK_EQUAL(2, joint->limot1.limit); CHECK_EQUAL(5, info.m); // Return to original position // and remove the limits dBodySetPosition (bId2, 0, 1, 0); dRFromAxisAndAngle (R, 1, 0, 0, -M_PI/2.0); dBodySetRotation (bId2, R); dJointSetHinge2Param(jId, dParamLoStop, -2*M_PI); dJointSetHinge2Param(jId, dParamHiStop, 2*M_PI); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limot1.limit); CHECK_EQUAL(4, info.m); /// Motorize the first joint angle dJointSetHinge2Param(jId, dParamFMax, 2); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limot1.limit); CHECK_EQUAL(5, info.m); /// Motorize the second joint angle dJointSetHinge2Param(jId, dParamFMax2, 2); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limot1.limit); CHECK_EQUAL(6, info.m); /// Unmotorize the first joint angle dJointSetHinge2Param(jId, dParamFMax, 0); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limot1.limit); CHECK_EQUAL(5, info.m); } } // End of SUITE(JointHinge2) //////////////////////////////////////////////////////////////////////////////// // Testing the Universal Joint // SUITE(JointUniversal) { struct UniversalGetInfo1_Fixture_1 { UniversalGetInfo1_Fixture_1() { wId = dWorldCreate(); bId1 = dBodyCreate(wId); dBodySetPosition(bId1, 0, -1, 0); bId2 = dBodyCreate(wId); dBodySetPosition(bId2, 0, 1, 0); jId = dJointCreateUniversal(wId, 0); joint = (dxJointUniversal*)jId; dJointAttach(jId, bId1, bId2); dJointSetUniversalAnchor (jId, REAL(0.0), REAL(0.0), REAL(0.0)); } ~UniversalGetInfo1_Fixture_1() { dWorldDestroy(wId); } dJointID jId; dxJointUniversal* joint; dWorldID wId; dBodyID bId1; dBodyID bId2; dxJoint::Info1 info; }; TEST_FIXTURE(UniversalGetInfo1_Fixture_1, test_hinge2GetInfo1_RotAroundX) { /* // ^Y // |---| HiStop // | | ^Y / // |B_2| | / // |---| | / // | ----- | / // Z <-- * Z<--|B_2|--* // / | \ ----- | \ // /|---|\ |---| \ // / | | \ | | \ // / |B_1| \ |B_1| \ // / |---| \ |---| \ //LoStop HiStop LoStop // // // // */ dMatrix3 R; dJointSetUniversalParam(jId, dParamLoStop, -M_PI/4.0); dJointSetUniversalParam(jId, dParamHiStop, M_PI/4.0); dJointSetUniversalParam(jId, dParamLoStop2, -M_PI/4.0); dJointSetUniversalParam(jId, dParamHiStop2, M_PI/4.0); dxJoint::Info1 info; dxJointUniversal* joint = (dxJointUniversal*)jId; // Original position inside the limits joint->getInfo1(&info); CHECK_EQUAL(0, joint->limot1.limit); CHECK_EQUAL(4, info.m); // Move the body outside the Lo limits dBodySetPosition (bId2, 0, 0, 1); dRFromAxisAndAngle (R, 1, 0, 0, M_PI/2.0); dBodySetRotation (bId2, R); joint->getInfo1(&info); CHECK_EQUAL(1, joint->limot1.limit); CHECK_EQUAL(5, info.m); // Return to original position // Keep the limits dBodySetPosition (bId2, 0, 1, 0); dRFromAxisAndAngle (R, 1, REAL(0.0), REAL(0.0), REAL(0.0)); dBodySetRotation (bId2, R); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limot1.limit); CHECK_EQUAL(4, info.m); // Move the body outside the Lo limits dBodySetPosition (bId2, 0, 0, 1); dRFromAxisAndAngle (R, 1, 0, 0, M_PI/2.0); dBodySetRotation (bId2, R); joint->getInfo1(&info); CHECK_EQUAL(1, joint->limot1.limit); CHECK_EQUAL(5, info.m); // Return to original position // and remove the limits dBodySetPosition (bId2, 0, 1, 0); dRFromAxisAndAngle (R, 1, REAL(0.0), REAL(0.0), REAL(0.0)); dBodySetRotation (bId2, R); dJointSetUniversalParam(jId, dParamLoStop, -2*M_PI); dJointSetUniversalParam(jId, dParamHiStop, 2*M_PI); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limot1.limit); CHECK_EQUAL(4, info.m); // Set the limits // Move pass the Hi limits dJointSetUniversalParam(jId, dParamLoStop, -M_PI/4.0); dJointSetUniversalParam(jId, dParamHiStop, M_PI/4.0); dBodySetPosition (bId2, 0, 0, 1); dRFromAxisAndAngle (R, 1, 0, 0, -M_PI/2.0); dBodySetRotation (bId2, R); joint->getInfo1(&info); CHECK_EQUAL(2, joint->limot1.limit); CHECK_EQUAL(5, info.m); // Return to original position // Keep the limits dBodySetPosition (bId2, 0, 1, 0); dRFromAxisAndAngle (R, 1, REAL(0.0), REAL(0.0), REAL(0.0)); dBodySetRotation (bId2, R); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limot1.limit); CHECK_EQUAL(4, info.m); // Move the pass the Hi limit dBodySetPosition (bId2, 0, 0, 1); dRFromAxisAndAngle (R, 1, 0, 0, -M_PI/2.0); dBodySetRotation (bId2, R); joint->getInfo1(&info); CHECK_EQUAL(2, joint->limot1.limit); CHECK_EQUAL(5, info.m); // Return to original position // and remove the limits dBodySetPosition (bId2, 0, 1, 0); dRFromAxisAndAngle (R, 1, 0, 0, -M_PI/2.0); dBodySetRotation (bId2, R); dJointSetUniversalParam(jId, dParamLoStop, -2*M_PI); dJointSetUniversalParam(jId, dParamHiStop, 2*M_PI); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limot1.limit); CHECK_EQUAL(4, info.m); /// Motorize the first joint angle dJointSetUniversalParam(jId, dParamFMax, 2); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limot1.limit); CHECK_EQUAL(5, info.m); /// Motorize the second joint angle dJointSetUniversalParam(jId, dParamFMax2, 2); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limot1.limit); CHECK_EQUAL(6, info.m); /// Unmotorize the first joint angle dJointSetUniversalParam(jId, dParamFMax, 0); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limot1.limit); CHECK_EQUAL(5, info.m); } TEST_FIXTURE(UniversalGetInfo1_Fixture_1, test_hinge2GetInfo1_RotAroundY) { /* // ^Y // |---| HiStop // | | ^Y / // |B_2| | / // |---| | / // | ----- | / // Z <-- * Z<--|B_2|--* // / | \ ----- | \ // /|---|\ |---| \ // / | | \ | | \ // / |B_1| \ |B_1| \ // / |---| \ |---| \ //LoStop HiStop LoStop // // // // */ dMatrix3 R; dJointSetUniversalParam(jId, dParamLoStop, -M_PI/4.0); dJointSetUniversalParam(jId, dParamHiStop, M_PI/4.0); dJointSetUniversalParam(jId, dParamLoStop2, -M_PI/4.0); dJointSetUniversalParam(jId, dParamHiStop2, M_PI/4.0); dxJoint::Info1 info; dxJointUniversal* joint = (dxJointUniversal*)jId; // Original position inside the limits joint->getInfo1(&info); CHECK_EQUAL(0, joint->limot1.limit); CHECK_EQUAL(4, info.m); // Move the body outside the Lo limits dBodySetPosition (bId2, 0, 0, 1); dRFromAxisAndAngle (R, 0, 1, 0, M_PI/2.0); dBodySetRotation (bId2, R); joint->getInfo1(&info); CHECK_EQUAL(1, joint->limot2.limit); CHECK_EQUAL(5, info.m); // Return to original position // Keep the limits dBodySetPosition (bId2, 0, 1, 0); dRFromAxisAndAngle (R, 0, 1, 0, 0); dBodySetRotation (bId2, R); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limot2.limit); CHECK_EQUAL(4, info.m); // Move the body outside the Lo limits dBodySetPosition (bId2, 0, 0, 1); dRFromAxisAndAngle (R, 0, 1, 0, M_PI/2.0); dBodySetRotation (bId2, R); joint->getInfo1(&info); CHECK_EQUAL(1, joint->limot2.limit); CHECK_EQUAL(5, info.m); // Return to original position // and remove the limits dBodySetPosition (bId2, 0, 1, 0); dRFromAxisAndAngle (R, 0, 1, 0, 0); dBodySetRotation (bId2, R); dJointSetUniversalParam(jId, dParamLoStop2, -2*M_PI); dJointSetUniversalParam(jId, dParamHiStop2, 2*M_PI); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limot2.limit); CHECK_EQUAL(4, info.m); // Set the limits // Move pass the Hi limits dJointSetUniversalParam(jId, dParamLoStop2, -M_PI/4.0); dJointSetUniversalParam(jId, dParamHiStop2, M_PI/4.0); dBodySetPosition (bId2, 0, 0, 1); dRFromAxisAndAngle (R, 0, 1, 0, -M_PI/2.0); dBodySetRotation (bId2, R); joint->getInfo1(&info); CHECK_EQUAL(2, joint->limot2.limit); CHECK_EQUAL(5, info.m); // Return to original position // Keep the limits dBodySetPosition (bId2, 0, 1, 0); dRFromAxisAndAngle (R, 0, 1, 0, 0); dBodySetRotation (bId2, R); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limot2.limit); CHECK_EQUAL(4, info.m); // Move the pass the Hi limit dBodySetPosition (bId2, 0, 0, 1); dRFromAxisAndAngle (R, 0, 1, 0, -M_PI/2.0); dBodySetRotation (bId2, R); joint->getInfo1(&info); CHECK_EQUAL(2, joint->limot2.limit); CHECK_EQUAL(5, info.m); // Return to original position // and remove the limits dBodySetPosition (bId2, 0, 1, 0); dRFromAxisAndAngle (R, 0, 1, 0, -M_PI/2.0); dBodySetRotation (bId2, R); dJointSetUniversalParam(jId, dParamLoStop2, -2*M_PI); dJointSetUniversalParam(jId, dParamHiStop2, 2*M_PI); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limot2.limit); CHECK_EQUAL(4, info.m); /// Motorize the first joint angle dJointSetUniversalParam(jId, dParamFMax, 2); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limot2.limit); CHECK_EQUAL(5, info.m); /// Motorize the second joint angle dJointSetUniversalParam(jId, dParamFMax2, 2); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limot2.limit); CHECK_EQUAL(6, info.m); /// Unmotorize the first joint angle dJointSetUniversalParam(jId, dParamFMax, 0); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limot2.limit); CHECK_EQUAL(5, info.m); } } // End of SUITE(JointUniversal) // // // // Testing the PR Joint // SUITE(JointPR) { struct PRGetInfo1_Fixture_1 { PRGetInfo1_Fixture_1() { wId = dWorldCreate(); bId1 = dBodyCreate(wId); dBodySetPosition(bId1, 0, -1, 0); bId2 = dBodyCreate(wId); dBodySetPosition(bId2, 0, 1, 0); jId = dJointCreatePR(wId, 0); joint = (dxJointPR*)jId; dJointAttach(jId, bId1, bId2); dJointSetPRAnchor (jId, REAL(0.0), REAL(0.0), REAL(0.0)); } ~PRGetInfo1_Fixture_1() { dWorldDestroy(wId); } dJointID jId; dxJointPR* joint; dWorldID wId; dBodyID bId1; dBodyID bId2; dxJoint::Info1 info; }; //////////////////////////////////////////////////////////////////////////////// // Test when there is no limits. // The 2 bodies stay aligned. // // Default value for axisR1 = 1,0,0 // Default value for axisP1 = 0,1,0 //////////////////////////////////////////////////////////////////////////////// TEST_FIXTURE(PRGetInfo1_Fixture_1, test1_PRGetInfo1_) { dJointSetPRParam(jId, dParamLoStop, -dInfinity); dJointSetPRParam(jId, dParamHiStop, dInfinity); dJointSetPRParam(jId, dParamLoStop2, -M_PI); dJointSetPRParam(jId, dParamHiStop2, M_PI); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limotP.limit); CHECK_EQUAL(0, joint->limotR.limit); CHECK_EQUAL(4, info.m); } //////////////////////////////////////////////////////////////////////////////// // Test when there is limits for the prismatic at -10 and 10 // The Body 2 is moved -100 unit then at 100 // // Default value for axisR1 = 1,0,0 // Default value for axisP1 = 0,1,0 //////////////////////////////////////////////////////////////////////////////// TEST_FIXTURE(PRGetInfo1_Fixture_1, test2_PRGetInfo1) { dJointSetPRParam(jId, dParamLoStop, -10); dJointSetPRParam(jId, dParamHiStop, 10); dJointSetPRParam(jId, dParamLoStop2, -M_PI); dJointSetPRParam(jId, dParamHiStop2, M_PI); dBodySetPosition(bId2, 0, -100, 0); joint->getInfo1(&info); CHECK_EQUAL(2, joint->limotP.limit); CHECK_EQUAL(0, joint->limotR.limit); CHECK_EQUAL(5, info.m); dBodySetPosition(bId2, 0, 100, 0); joint->getInfo1(&info); CHECK_EQUAL(1, joint->limotP.limit); CHECK_EQUAL(0, joint->limotR.limit); CHECK_EQUAL(5, info.m); // Reset Position and test dBodySetPosition(bId2, 0, 1, 0); dMatrix3 R_final = { 1,0,0,0, 0,1,0,0, 0,0,1,0 }; dBodySetRotation (bId2, R_final); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limotP.limit); CHECK_EQUAL(0, joint->limotR.limit); CHECK_EQUAL(4, info.m); } //////////////////////////////////////////////////////////////////////////////// // Test when there is limits for the prismatic at -10 and 10 // and for the rotoide at -45deg and 45deg. // The Body 2 is only rotated by 90deg since the rotoide limits are not // used this should not change the limit value. // // Default value for axisR1 = 1,0,0 // Default value for axisP1 = 0,1,0 // //////////////////////////////////////////////////////////////////////////////// TEST_FIXTURE(PRGetInfo1_Fixture_1, test3_PRGetInfo1) { dJointSetPRParam(jId, dParamLoStop, -10); dJointSetPRParam(jId, dParamHiStop, 10); dJointSetPRParam(jId, dParamLoStop2, -M_PI/4.0); dJointSetPRParam(jId, dParamHiStop2, M_PI/4.0); dMatrix3 R; dBodySetPosition (bId2, 0, 0, 1); dRFromAxisAndAngle (R, 1, 0, 0, M_PI/2.0); dBodySetRotation (bId2, R); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limotP.limit); CHECK_EQUAL(1, joint->limotR.limit); CHECK_EQUAL(5, info.m); // Reset Position and test dBodySetPosition(bId2, 0, 1, 0); dMatrix3 R_final = { 1,0,0,0, 0,1,0,0, 0,0,1,0 }; dBodySetRotation (bId2, R_final); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limotP.limit); CHECK_EQUAL(0, joint->limotR.limit); CHECK_EQUAL(4, info.m); } // The joint is now powered. (i.e. info->fmax > 0 struct PRGetInfo1_Fixture_2 { PRGetInfo1_Fixture_2() { wId = dWorldCreate(); bId1 = dBodyCreate(wId); dBodySetPosition(bId1, 0, -1, 0); bId2 = dBodyCreate(wId); dBodySetPosition(bId2, 0, 1, 0); jId = dJointCreatePR(wId, 0); joint = (dxJointPR*)jId; dJointAttach(jId, bId1, bId2); dJointSetPRAnchor (jId, REAL(0.0), REAL(0.0), REAL(0.0)); joint->limotP.fmax = 1; } ~PRGetInfo1_Fixture_2() { dWorldDestroy(wId); } dJointID jId; dxJointPR* joint; dWorldID wId; dBodyID bId1; dBodyID bId2; dxJoint::Info1 info; }; //////////////////////////////////////////////////////////////////////////////// // Test when there is no limits. // The 2 bodies stay align. // // Default value for axisR1 = 1,0,0 // Default value for axisP1 = 0,1,0 // //////////////////////////////////////////////////////////////////////////////// TEST_FIXTURE(PRGetInfo1_Fixture_2, test1_PRGetInfo1) { dJointSetPRParam(jId, dParamLoStop, -dInfinity); dJointSetPRParam(jId, dParamHiStop, dInfinity); dJointSetPRParam(jId, dParamLoStop2, -M_PI); dJointSetPRParam(jId, dParamHiStop2, M_PI); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limotP.limit); CHECK_EQUAL(0, joint->limotR.limit); CHECK_EQUAL(5, info.m); } //////////////////////////////////////////////////////////////////////////////// // Test when there is limits for the prismatic at -10 and 10 // The Body 2 is moved -100 unit then at 100 // // Default value for axisR1 = 1,0,0 // Default value for axisP1 = 0,1,0 // //////////////////////////////////////////////////////////////////////////////// TEST_FIXTURE(PRGetInfo1_Fixture_2, test2_PRGetInfo1) { dJointSetPRParam(jId, dParamLoStop, -10); dJointSetPRParam(jId, dParamHiStop, 10); dJointSetPRParam(jId, dParamLoStop2, -M_PI); dJointSetPRParam(jId, dParamHiStop2, M_PI); dBodySetPosition(bId2, 0, -100, 0); joint->getInfo1(&info); CHECK_EQUAL(2, joint->limotP.limit); CHECK_EQUAL(0, joint->limotR.limit); CHECK_EQUAL(5, info.m); dBodySetPosition(bId2, 0, 100, 0); joint->getInfo1(&info); CHECK_EQUAL(1, joint->limotP.limit); CHECK_EQUAL(0, joint->limotR.limit); CHECK_EQUAL(5, info.m); // Reset Position and test dBodySetPosition(bId2, 0, 1, 0); dMatrix3 R_final = { 1,0,0,0, 0,1,0,0, 0,0,1,0 }; dBodySetRotation (bId2, R_final); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limotP.limit); CHECK_EQUAL(0, joint->limotR.limit); CHECK_EQUAL(5, info.m); } //////////////////////////////////////////////////////////////////////////////// // Test when there is limits for the prismatic at -10 and 10 // and for the rotoide at -45deg and 45deg // The Body 2 is only rotated by 90deg since the rotoide limits are not // used this should not change the limit value. // // Default value for axisR1 = 1,0,0 // Default value for axisP1 = 0,1,0 // //////////////////////////////////////////////////////////////////////////////// TEST_FIXTURE(PRGetInfo1_Fixture_2, test3_PRGetInfo1) { dJointSetPRParam(jId, dParamLoStop, -10); dJointSetPRParam(jId, dParamHiStop, 10); dJointSetPRParam(jId, dParamLoStop2, -M_PI/4.0); dJointSetPRParam(jId, dParamHiStop2, M_PI/4.0); dMatrix3 R; dBodySetPosition (bId2, 0, 0, 100); dRFromAxisAndAngle (R, 1, 0, 0, M_PI/2.0); dBodySetRotation (bId2, R); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limotP.limit); CHECK_EQUAL(1, joint->limotR.limit); CHECK_EQUAL(6, info.m); // Reset Position and test dBodySetPosition(bId2, 0, 1, 0); dMatrix3 R_final = { 1,0,0,0, 0,1,0,0, 0,0,1,0 }; dBodySetRotation (bId2, R_final); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limotP.limit); CHECK_EQUAL(0, joint->limotR.limit); CHECK_EQUAL(5, info.m); } //////////////////////////////////////////////////////////////////////////////// // Test the setting and getting of parameters //////////////////////////////////////////////////////////////////////////////// TEST_FIXTURE(PRGetInfo1_Fixture_1, test_SetPRParam) { dJointSetPRParam(jId, dParamHiStop, REAL(5.0) ); CHECK_EQUAL(REAL(5.0), joint->limotP.histop); dJointSetPRParam(jId, dParamVel, REAL(7.0) ); CHECK_EQUAL(REAL(7.0), joint->limotP.vel); #ifdef dParamFudgeFactor1 dJointSetPRParam(jId, dParamFudgeFactor1, REAL(5.5) ); CHECK_EQUAL(REAL(5.5), joint->limotP.dParamFudgeFactor); #endif dJointSetPRParam(jId, dParamCFM2, REAL(9.0) ); CHECK_EQUAL(REAL(9.0), joint->limotR.normal_cfm); dJointSetPRParam(jId, dParamStopERP2, REAL(11.0) ); CHECK_EQUAL(REAL(11.0), joint->limotR.stop_erp); } TEST_FIXTURE(PRGetInfo1_Fixture_1, test_GetPRParam) { joint->limotP.histop = REAL(5.0); CHECK_EQUAL(joint->limotP.histop, dJointGetPRParam(jId, dParamHiStop) ); joint->limotP.vel = REAL(7.0); CHECK_EQUAL(joint->limotP.vel, dJointGetPRParam(jId, dParamVel) ); #ifdef dParamFudgeFactor1 joint->limotP.dParamFudgeFactor = REAL(5.5); CHECK_EQUAL(joint->limotP.dParamFudgeFactor, dJointGetPRParam(jId, dParamFudgeFactor1) ); #endif joint->limotR.normal_cfm = REAL(9.0); CHECK_EQUAL(joint->limotR.normal_cfm, dJointGetPRParam(jId, dParamCFM2) ); joint->limotR.stop_erp = REAL(11.0); CHECK_EQUAL(joint->limotR.stop_erp, dJointGetPRParam(jId, dParamStopERP2) ); } //////////////////////////////////////////////////////////////////////////////// // Fixture for testing the PositionRate // // Default Position // ^Z // | // | // // Body2 R Body1 // +---------+ _ - +-----------+ // | |--------(_)----|-----| | ----->Y // +---------+ - +-----------+ // // N.B. X is comming out of the page //////////////////////////////////////////////////////////////////////////////// struct PRGetInfo1_Fixture_3 { PRGetInfo1_Fixture_3() { wId = dWorldCreate(); bId1 = dBodyCreate(wId); dBodySetPosition(bId1, 0, 1, 0); bId2 = dBodyCreate(wId); dBodySetPosition(bId2, 0, -1, 0); jId = dJointCreatePR(wId, 0); joint = (dxJointPR*)jId; dJointAttach(jId, bId1, bId2); dJointSetPRAnchor (jId, REAL(0.0), REAL(0.0), REAL(0.0)); dBodySetLinearVel (bId1, REAL(0.0), REAL(0.0), REAL(0.0)); dBodySetAngularVel(bId1, REAL(0.0), REAL(0.0), REAL(0.0)); dBodySetLinearVel (bId2, REAL(0.0), REAL(0.0), REAL(0.0)); dBodySetAngularVel(bId1, REAL(0.0), REAL(0.0), REAL(0.0)); } ~PRGetInfo1_Fixture_3() { dWorldDestroy(wId); } dJointID jId; dxJointPR* joint; dWorldID wId; dBodyID bId1; dBodyID bId2; dxJoint::Info1 info; }; //////////////////////////////////////////////////////////////////////////////// // Position Body1 [0, 1, 0] // Position Body2 [0, -1, 0] // Axis of the prismatic [0, 1, 0] // Axis of the rotoide [1, 0, ]0 // // Move at the same speed //////////////////////////////////////////////////////////////////////////////// TEST_FIXTURE(PRGetInfo1_Fixture_3, test_GetPRPositionRate_1) { // They move with the same linear speed // Angular speed == 0 dBodySetLinearVel(bId1, REAL(0.0), REAL(3.33), REAL(0.0)); dBodySetLinearVel(bId2, REAL(0.0), REAL(3.33), REAL(0.0)); CHECK_EQUAL(REAL(0.0), dJointGetPRPositionRate (jId) ); dBodySetLinearVel(bId1, REAL(1.11), REAL(3.33), REAL(0.0)); dBodySetLinearVel(bId2, REAL(1.11), REAL(3.33), REAL(0.0)); CHECK_EQUAL(REAL(0.0), dJointGetPRPositionRate (jId) ); dBodySetLinearVel(bId1, REAL(1.11), REAL(3.33), REAL(2.22)); dBodySetLinearVel(bId2, REAL(1.11), REAL(3.33), REAL(2.22)); CHECK_EQUAL(REAL(0.0), dJointGetPRPositionRate (jId) ); // Reset for the next set of test. dBodySetLinearVel(bId1, REAL(0.0), REAL(0.0), REAL(0.0)); dBodySetAngularVel(bId1, REAL(0.0), REAL(0.0), REAL(0.0)); dBodySetLinearVel(bId2, REAL(0.0), REAL(0.0), REAL(0.0)); dBodySetAngularVel(bId1, REAL(0.0), REAL(0.0), REAL(0.0)); // They move with the same angular speed // linear speed == 0 dBodySetAngularVel(bId1, REAL(1.22), REAL(0.0), REAL(0.0)); dBodySetAngularVel(bId2, REAL(1.22), REAL(0.0), REAL(0.0)); CHECK_EQUAL(REAL(0.0), dJointGetPRPositionRate (jId) ); dBodySetAngularVel(bId1, REAL(1.22), REAL(2.33), REAL(0.0)); dBodySetAngularVel(bId2, REAL(1.22), REAL(2.33), REAL(0.0)); CHECK_EQUAL(REAL(0.0), dJointGetPRPositionRate (jId) ); dBodySetAngularVel(bId1, REAL(1.22), REAL(2.33), REAL(3.44)); dBodySetAngularVel(bId2, REAL(1.22), REAL(2.33), REAL(3.44)); CHECK_EQUAL(REAL(0.0), dJointGetPRPositionRate (jId) ); } //////////////////////////////////////////////////////////////////////////////// // Position Body1 [0, 1, 0] // Position Body2 [0, -1, 0] // Axis of the prismatic [0, 1, 0] // Axis of the rotoide [1, 0, ]0 // // Only the first body moves //////////////////////////////////////////////////////////////////////////////// TEST_FIXTURE(PRGetInfo1_Fixture_3, GetPRPositionRate_Bodies_in_line_B1_moves) { dBodySetLinearVel(bId1, REAL(3.33), REAL(0.0), REAL(0.0)); // This is impossible but ... CHECK_EQUAL(REAL(0.0), dJointGetPRPositionRate (jId) ); dBodySetLinearVel(bId1, REAL(0.0), REAL(3.33), REAL(0.0)); CHECK_EQUAL(REAL(3.33), dJointGetPRPositionRate (jId) ); dBodySetLinearVel(bId1, REAL(0.0), REAL(0.0), REAL(3.33)); // This is impossible but ... CHECK_EQUAL(REAL(0.0), dJointGetPRPositionRate (jId) ); // Only the first body as angular velocity dBodySetAngularVel(bId1, REAL(1.22), REAL(0.0), REAL(0.0)); CHECK_EQUAL(REAL(0.0), dJointGetPRPositionRate (jId) ); dBodySetAngularVel(bId1, REAL(0.0), REAL(2.33), REAL(0.0)); CHECK_EQUAL(REAL(0.0), dJointGetPRPositionRate (jId) ); dBodySetAngularVel(bId1, REAL(0.0), REAL(0.0), REAL(5.55)); CHECK_EQUAL(REAL(0.0), dJointGetPRPositionRate (jId) ); } //////////////////////////////////////////////////////////////////////////////// // Position Body1 [0, 1, 0] // Position Body2 [0, -1, 0] // Axis of the prismatic [0, 1, 0] // Axis of the rotoide [1, 0, ]0 // // Only the second body moves //////////////////////////////////////////////////////////////////////////////// TEST_FIXTURE(PRGetInfo1_Fixture_3, GetPRPositionRate_Bodies_in_line_B2_moves) { dBodySetLinearVel(bId2, REAL(3.33), REAL(0.0), REAL(0.0)); // This is impossible but ... CHECK_EQUAL(REAL(0.0), dJointGetPRPositionRate (jId) ); // The length was at zero and this will give an negative length dBodySetLinearVel(bId2, REAL(0.0), REAL(3.33), REAL(0.0)); CHECK_EQUAL(REAL(-3.33), dJointGetPRPositionRate (jId) ); dBodySetLinearVel(bId2, REAL(0.0), REAL(0.0), REAL(3.33)); // This is impossible but ... CHECK_EQUAL(REAL(0.0), dJointGetPRPositionRate (jId) ); // Only angular velocity dBodySetAngularVel(bId2, REAL(1.22), REAL(0.0), REAL(0.0)); CHECK_EQUAL(REAL(0.0), dJointGetPRPositionRate (jId) ); dBodySetAngularVel(bId2, REAL(0.0), REAL(2.33), REAL(0.0)); CHECK_EQUAL(REAL(0.0), dJointGetPRPositionRate (jId) ); dBodySetAngularVel(bId2, REAL(0.0), REAL(0.0), REAL(5.55)); CHECK_EQUAL(REAL(0.0), dJointGetPRPositionRate (jId) ); } //////////////////////////////////////////////////////////////////////////////// // Fixture for testing the PositionRate // // The second body is at 90deg w.r.t. the first body // // // Default Position // ^Z // | // | // // +---+ // | |Body2 // | | // | | // +---+ // | // | // | // | Body1 // R _ - +-----------+ // (_)----|-----| | ----->Y // - +-----------+ // // N.B. X is comming out of the page //////////////////////////////////////////////////////////////////////////////// struct PRGetInfo1_Fixture_4 { PRGetInfo1_Fixture_4() { wId = dWorldCreate(); bId1 = dBodyCreate(wId); dBodySetPosition(bId1, 0, 1, 0); bId2 = dBodyCreate(wId); dBodySetPosition(bId2, 0, 0, 1); dMatrix3 R; dRFromAxisAndAngle (R, 1, 0, 0, -M_PI/2.0); dBodySetRotation (bId2, R); jId = dJointCreatePR(wId, 0); joint = (dxJointPR*)jId; dJointAttach(jId, bId1, bId2); dJointSetPRAnchor (jId, REAL(0.0), REAL(0.0), REAL(0.0)); dBodySetLinearVel(bId1, REAL(0.0), REAL(0.0), REAL(0.0)); dBodySetAngularVel(bId1, REAL(0.0), REAL(0.0), REAL(0.0)); dBodySetLinearVel(bId2, REAL(0.0), REAL(0.0), REAL(0.0)); dBodySetAngularVel(bId1, REAL(0.0), REAL(0.0), REAL(0.0)); } ~PRGetInfo1_Fixture_4() { dWorldDestroy(wId); } dJointID jId; dxJointPR* joint; dWorldID wId; dBodyID bId1; dBodyID bId2; dxJoint::Info1 info; }; //////////////////////////////////////////////////////////////////////////////// // Position Body1 [0, 1, 0] // Position Body2 [0, 0, 1] // Axis of the prismatic [0, 1, 0] // Axis of the rotoide [1, 0, 0] // // Only the first body moves //////////////////////////////////////////////////////////////////////////////// TEST_FIXTURE(PRGetInfo1_Fixture_4, GetPRPositionRate_Bodies_at90deg_B1_moves) { dBodySetLinearVel(bId1, REAL(3.33), REAL(0.0), REAL(0.0)); // This is impossible but ... CHECK_EQUAL(REAL(0.0), dJointGetPRPositionRate (jId) ); // The length was at zero and this will give an negative length dBodySetLinearVel(bId1, REAL(0.0), REAL(3.33), REAL(0.0)); CHECK_EQUAL(REAL(3.33), dJointGetPRPositionRate (jId) ); dBodySetLinearVel(bId1, REAL(0.0), REAL(0.0), REAL(3.33)); // This is impossible but ... CHECK_EQUAL(REAL(0.0), dJointGetPRPositionRate (jId) ); // Only angular velocity dBodySetAngularVel(bId1, REAL(1.22), REAL(0.0), REAL(0.0)); CHECK_EQUAL(REAL(0.0), dJointGetPRPositionRate (jId) ); dBodySetAngularVel(bId1, REAL(0.0), REAL(2.33), REAL(0.0)); CHECK_EQUAL(REAL(0.0), dJointGetPRPositionRate (jId) ); dBodySetAngularVel(bId1, REAL(0.0), REAL(0.0), REAL(5.55)); CHECK_EQUAL(REAL(0.0), dJointGetPRPositionRate (jId) ); } //////////////////////////////////////////////////////////////////////////////// // Position Body1 [0, 1, 0] // Position Body2 [0, 0, 1] // Axis of the prismatic [0, 1, 0] // Axis of the rotoide [1, 0, 0] // // Only the second body moves //////////////////////////////////////////////////////////////////////////////// TEST_FIXTURE(PRGetInfo1_Fixture_4, GetPRPositionRate_Bodies_at90deg_B2_moves) { dBodySetLinearVel(bId2, REAL(3.33), REAL(0.0), REAL(0.0)); // This is impossible but ... CHECK_EQUAL(REAL(0.0), dJointGetPRPositionRate (jId) ); dBodySetLinearVel(bId2, REAL(0.0), REAL(3.33), REAL(0.0)); CHECK_EQUAL(REAL(-3.33), dJointGetPRPositionRate (jId) ); dBodySetLinearVel(bId2, REAL(0.0), REAL(0.0), REAL(3.33)); // This is impossible but ... CHECK_EQUAL(REAL(0.0), dJointGetPRPositionRate (jId) ); // Only angular velocity dBodySetAngularVel(bId2, REAL(1.22), REAL(0.0), REAL(0.0)); CHECK_EQUAL(REAL(-1.0*1.22), dJointGetPRPositionRate (jId) ); dBodySetAngularVel(bId2, REAL(0.0), REAL(2.33), REAL(0.0)); CHECK_EQUAL(REAL(0.0), dJointGetPRPositionRate (jId) ); dBodySetAngularVel(bId2, REAL(0.0), REAL(0.0), REAL(5.55)); CHECK_EQUAL(REAL(0.0), dJointGetPRPositionRate (jId) ); } } // End of SUITE(JointPR) // // // // Testing the PU Joint // // // //////////////////////////////////////////////////////////////////////////////// // Default Position: // Position Body1 (3, 0, 0) // Position Body2 (1, 0, 0) // Angchor (2, 0, 0) // Axis1 (0, 1, 0) // Axis2 (0, 0, 1) // AxisP1 (1, 0, 0) // // Y ^ Axis2 // ^ | // / | ^ Axis1 // Z^ / | / // | / Body 2 | / Body 1 // | / +---------+ | / +-----------+ // | / / /| | / / /| // | / / / + _/ - / / + // | / / /-/--------(_)----|--- /-----------/-------> AxisP // | / +---------+ / - +-----------+ / // | / | |/ | |/ // | / +---------+ +-----------+ // |/ // .-----------------------------------------> X // |-----------------> // Anchor2 <--------------| // Anchor1 // //////////////////////////////////////////////////////////////////////////////// SUITE(JointPU) { struct PUGetInfo1_Fixture_1 { PUGetInfo1_Fixture_1() { wId = dWorldCreate(); bId1 = dBodyCreate(wId); dBodySetPosition(bId1, 3, 0, 0); bId2 = dBodyCreate(wId); dBodySetPosition(bId2, 1, 0, 0); jId = dJointCreatePU(wId, 0); joint = (dxJointPU*)jId; dJointAttach(jId, bId1, bId2); dJointSetPUAnchor (jId, 2, 0, 0); } ~PUGetInfo1_Fixture_1() { dWorldDestroy(wId); } dJointID jId; dxJointPU* joint; dWorldID wId; dBodyID bId1; dBodyID bId2; dxJoint::Info1 info; }; //////////////////////////////////////////////////////////////////////////////// // Test when there is no limits. // The 2 bodies stay aligned. // //////////////////////////////////////////////////////////////////////////////// TEST_FIXTURE(PUGetInfo1_Fixture_1, test1_SetPUParam) { dJointSetPUParam(jId, dParamLoStop1, -M_PI); dJointSetPUParam(jId, dParamHiStop1 , M_PI); dJointSetPUParam(jId, dParamLoStop2, -M_PI); dJointSetPUParam(jId, dParamHiStop2, M_PI); dJointSetPUParam(jId, dParamLoStop3, -dInfinity); dJointSetPUParam(jId, dParamHiStop3, dInfinity); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limot1.limit); CHECK_EQUAL(0, joint->limot2.limit); CHECK_EQUAL(0, joint->limotP.limit); CHECK_EQUAL(3, info.m); } //////////////////////////////////////////////////////////////////////////////// // Test when there is limits for the prismatic at -10 and 10 // The Body 2 is moved -100 unit then at 100 // // Default value for axisR1 = 1,0,0 // Default value for axisP1 = 0,1,0 //////////////////////////////////////////////////////////////////////////////// TEST_FIXTURE(PUGetInfo1_Fixture_1, test1_GetPUParam) { dJointSetPUParam(jId, dParamLoStop3, -10); dJointSetPUParam(jId, dParamHiStop3, 10); dBodySetPosition(bId2, REAL(-100.0), REAL(0.0), REAL(0.0)); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limot1.limit); CHECK_EQUAL(0, joint->limot2.limit); CHECK_EQUAL(2, joint->limotP.limit); CHECK_EQUAL(4, info.m); dBodySetPosition(bId2, REAL(100.0), REAL(0.0), REAL(0.0)); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limot1.limit); CHECK_EQUAL(0, joint->limot2.limit); CHECK_EQUAL(1, joint->limotP.limit); CHECK_EQUAL(4, info.m); // Reset Position and test dBodySetPosition(bId2, 1, 0, 0); dMatrix3 R_final = { 1,0,0,0, 0,1,0,0, 0,0,1,0 }; dBodySetRotation (bId2, R_final); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limot1.limit); CHECK_EQUAL(0, joint->limot2.limit); CHECK_EQUAL(0, joint->limotP.limit); CHECK_EQUAL(3, info.m); } //////////////////////////////////////////////////////////////////////////////// // Test when there is limits for the prismatic at -10 and 10 // and for Axis1 and Axis2 at -45deg and 45deg. // The Body 2 is rotated by 90deg around Axis1 // // //////////////////////////////////////////////////////////////////////////////// TEST_FIXTURE(PUGetInfo1_Fixture_1, test2_PUGetInfo1) { dJointSetPUParam(jId, dParamLoStop1, -M_PI/4.0); dJointSetPUParam(jId, dParamHiStop1, M_PI/4.0); dJointSetPUParam(jId, dParamLoStop2, -M_PI/4.0); dJointSetPUParam(jId, dParamHiStop2, M_PI/4.0); dJointSetPUParam(jId, dParamLoStop3, -10); dJointSetPUParam(jId, dParamHiStop3, 10); dMatrix3 R; dBodySetPosition (bId2, 0, 0, 1); dRFromAxisAndAngle (R, 0, 1, 0, M_PI/2.0); dBodySetRotation (bId2, R); joint->getInfo1(&info); CHECK_EQUAL(1, joint->limot1.limit); CHECK_EQUAL(0, joint->limot2.limit); CHECK_EQUAL(0, joint->limotP.limit); CHECK_EQUAL(4, info.m); // Reset Position and test dBodySetPosition(bId2, 1, 0, 0); dMatrix3 R_final = { 1,0,0,0, 0,1,0,0, 0,0,1,0 }; dBodySetRotation (bId2, R_final); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limot1.limit); CHECK_EQUAL(0, joint->limot2.limit); CHECK_EQUAL(0, joint->limotP.limit); CHECK_EQUAL(3, info.m); } //////////////////////////////////////////////////////////////////////////////// // Test when there is limits for the prismatic at -10 and 10 // and for Axis1 and Axis2 at -45deg and 45deg. // The Body 2 is rotated by 90deg around Axis1 and // Body1 is moved at X=100 // // //////////////////////////////////////////////////////////////////////////////// TEST_FIXTURE(PUGetInfo1_Fixture_1, test3_PUGetInfo1) { dJointSetPUParam(jId, dParamLoStop1, -M_PI/4.0); dJointSetPUParam(jId, dParamHiStop1, M_PI/4.0); dJointSetPUParam(jId, dParamLoStop2, -M_PI/4.0); dJointSetPUParam(jId, dParamHiStop2, M_PI/4.0); dJointSetPUParam(jId, dParamLoStop3, -10); dJointSetPUParam(jId, dParamHiStop3, 10); dBodySetPosition (bId1, REAL(100.0), REAL(0.0), REAL(0.0)); dMatrix3 R; dBodySetPosition (bId2, 0, 0, 1); dRFromAxisAndAngle (R, 0, 1, 0, M_PI/2.0); dBodySetRotation (bId2, R); joint->getInfo1(&info); CHECK_EQUAL(1, joint->limot1.limit); CHECK_EQUAL(0, joint->limot2.limit); CHECK_EQUAL(2, joint->limotP.limit); CHECK_EQUAL(5, info.m); // Reset Position and test dBodySetPosition(bId1, 3, 0, 0); dBodySetPosition(bId2, 1, 0, 0); dMatrix3 R_final = { 1,0,0,0, 0,1,0,0, 0,0,1,0 }; dBodySetRotation (bId2, R_final); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limot1.limit); CHECK_EQUAL(0, joint->limot2.limit); CHECK_EQUAL(0, joint->limotP.limit); CHECK_EQUAL(3, info.m); } //////////////////////////////////////////////////////////////////////////////// // Default Position: // Position Body1 (3, 0, 0) // Position Body2 (1, 0, 0) // Angchor (2, 0, 0) // Axis1 (0, 1, 0) // Axis2 (0, 0, 1) // AxisP1 (1, 0, 0) // // The motor on axis1 is now powered. (i.e. joint->limot1->fmax > 0 // // Y ^ Axis2 // ^ | // / | ^ Axis1 // Z^ / | / // | / Body 2 | / Body 1 // | / +---------+ | / +-----------+ // | / / /| | / / /| // | / / / + _/ - / / + // | / / /-/--------(_)----|--- /-----------/-------> AxisP // | / +---------+ / - +-----------+ / // | / | |/ | |/ // | / +---------+ +-----------+ // |/ // .-----------------------------------------> X // |-----------------> // Anchor2 <--------------| // Anchor1 // //////////////////////////////////////////////////////////////////////////////// struct PUGetInfo1_Fixture_2 { PUGetInfo1_Fixture_2() { wId = dWorldCreate(); bId1 = dBodyCreate(wId); dBodySetPosition(bId1, 3, 0, 0); bId2 = dBodyCreate(wId); dBodySetPosition(bId2, 1, 0, 0); jId = dJointCreatePU(wId, 0); joint = (dxJointPU*)jId; dJointAttach(jId, bId1, bId2); dJointSetPUAnchor (jId, 2, 0, 0); joint->limot1.fmax = 1; } ~PUGetInfo1_Fixture_2() { dWorldDestroy(wId); } dJointID jId; dxJointPU* joint; dWorldID wId; dBodyID bId1; dBodyID bId2; dxJoint::Info1 info; }; //////////////////////////////////////////////////////////////////////////////// // Test when there is no limits. // The 2 bodies stay aligned. // //////////////////////////////////////////////////////////////////////////////// TEST_FIXTURE(PUGetInfo1_Fixture_2, test0_PUGetInfo1) { dJointSetPUParam(jId, dParamLoStop1, -M_PI); dJointSetPUParam(jId, dParamHiStop1 , M_PI); dJointSetPUParam(jId, dParamLoStop2, -M_PI); dJointSetPUParam(jId, dParamHiStop2, M_PI); dJointSetPUParam(jId, dParamLoStop3, -dInfinity); dJointSetPUParam(jId, dParamHiStop3, dInfinity); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limot1.limit); CHECK_EQUAL(0, joint->limot2.limit); CHECK_EQUAL(0, joint->limotP.limit); CHECK_EQUAL(4, info.m); } //////////////////////////////////////////////////////////////////////////////// // Test when there is limits for the prismatic at -10 and 10 // The Body 2 is moved -100 unit then at 100 // // Default value for axisR1 = 1,0,0 // Default value for axisP1 = 0,1,0 //////////////////////////////////////////////////////////////////////////////// TEST_FIXTURE(PUGetInfo1_Fixture_2, test1_PUGetInfo1) { dJointSetPUParam(jId, dParamLoStop3, -10); dJointSetPUParam(jId, dParamHiStop3, 10); dBodySetPosition(bId2, REAL(-100.0), REAL(0.0), REAL(0.0)); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limot1.limit); CHECK_EQUAL(0, joint->limot2.limit); CHECK_EQUAL(2, joint->limotP.limit); CHECK_EQUAL(5, info.m); dBodySetPosition(bId2, REAL(100.0), REAL(0.0), REAL(0.0)); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limot1.limit); CHECK_EQUAL(0, joint->limot2.limit); CHECK_EQUAL(1, joint->limotP.limit); CHECK_EQUAL(5, info.m); // Reset Position and test dBodySetPosition(bId2, 1, 0, 0); dMatrix3 R_final = { 1,0,0,0, 0,1,0,0, 0,0,1,0 }; dBodySetRotation (bId2, R_final); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limot1.limit); CHECK_EQUAL(0, joint->limot2.limit); CHECK_EQUAL(0, joint->limotP.limit); CHECK_EQUAL(4, info.m); } //////////////////////////////////////////////////////////////////////////////// // Test when there is limits for the prismatic at -10 and 10 // and for Axis1 and Axis2 at -45deg and 45deg. // The Body 2 is rotated by 90deg around Axis1 // // //////////////////////////////////////////////////////////////////////////////// TEST_FIXTURE(PUGetInfo1_Fixture_2, test2_PUGetInfo1) { dJointSetPUParam(jId, dParamLoStop1, -M_PI/4.0); dJointSetPUParam(jId, dParamHiStop1, M_PI/4.0); dJointSetPUParam(jId, dParamLoStop2, -M_PI/4.0); dJointSetPUParam(jId, dParamHiStop2, M_PI/4.0); dJointSetPUParam(jId, dParamLoStop3, -10); dJointSetPUParam(jId, dParamHiStop3, 10); dMatrix3 R; dBodySetPosition (bId2, 0, 0, 1); dRFromAxisAndAngle (R, 0, 1, 0, M_PI/2.0); dBodySetRotation (bId2, R); joint->getInfo1(&info); CHECK_EQUAL(1, joint->limot1.limit); CHECK_EQUAL(0, joint->limot2.limit); CHECK_EQUAL(0, joint->limotP.limit); CHECK_EQUAL(4, info.m); // Reset Position and test dBodySetPosition(bId2, 1, 0, 0); dMatrix3 R_final = { 1,0,0,0, 0,1,0,0, 0,0,1,0 }; dBodySetRotation (bId2, R_final); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limot1.limit); CHECK_EQUAL(0, joint->limot2.limit); CHECK_EQUAL(0, joint->limotP.limit); CHECK_EQUAL(4, info.m); } //////////////////////////////////////////////////////////////////////////////// // Test when there is limits for the prismatic at -10 and 10 // and for Axis1 and Axis2 at -45deg and 45deg. // The Body 2 is rotated by 90deg around Axis1 and // Body1 is moved at X=100 // // //////////////////////////////////////////////////////////////////////////////// TEST_FIXTURE(PUGetInfo1_Fixture_2, test3_PUGetInfo1) { dJointSetPUParam(jId, dParamLoStop1, -M_PI/4.0); dJointSetPUParam(jId, dParamHiStop1, M_PI/4.0); dJointSetPUParam(jId, dParamLoStop2, -M_PI/4.0); dJointSetPUParam(jId, dParamHiStop2, M_PI/4.0); dJointSetPUParam(jId, dParamLoStop3, -10); dJointSetPUParam(jId, dParamHiStop3, 10); dBodySetPosition (bId1, REAL(100.0), REAL(0.0), REAL(0.0)); dMatrix3 R; dBodySetPosition (bId2, 0, 0, 1); dRFromAxisAndAngle (R, 0, 1, 0, M_PI/2.0); dBodySetRotation (bId2, R); joint->getInfo1(&info); CHECK_EQUAL(1, joint->limot1.limit); CHECK_EQUAL(0, joint->limot2.limit); CHECK_EQUAL(2, joint->limotP.limit); CHECK_EQUAL(5, info.m); // Reset Position and test dBodySetPosition(bId1, 3, 0, 0); dBodySetPosition(bId2, 1, 0, 0); dMatrix3 R_final = { 1,0,0,0, 0,1,0,0, 0,0,1,0 }; dBodySetRotation (bId2, R_final); joint->getInfo1(&info); CHECK_EQUAL(0, joint->limot1.limit); CHECK_EQUAL(0, joint->limot2.limit); CHECK_EQUAL(0, joint->limotP.limit); CHECK_EQUAL(4, info.m); } TEST_FIXTURE(PUGetInfo1_Fixture_2, test_SetPUParam) { dJointSetPUParam(jId, dParamHiStop, REAL(5.0) ); CHECK_EQUAL(REAL(5.0), joint->limot1.histop); dJointSetPUParam(jId, dParamVel, REAL(7.0) ); CHECK_EQUAL(REAL(7.0), joint->limot1.vel); #ifdef dParamFudgeFactor1 dJointSetPUParam(jId, dParamFudgeFactor1, REAL(5.5) ); CHECK_EQUAL(REAL(5.5), joint->limot1.dParamFudgeFactor); #endif dJointSetPUParam(jId, dParamCFM2, REAL(9.0) ); CHECK_EQUAL(REAL(9.0), joint->limot2.normal_cfm); dJointSetPUParam(jId, dParamStopERP2, REAL(11.0) ); CHECK_EQUAL(REAL(11.0), joint->limot2.stop_erp); dJointSetPUParam(jId, dParamBounce3, REAL(13.0) ); CHECK_EQUAL(REAL(13.0), joint->limotP.bounce); } TEST_FIXTURE(PUGetInfo1_Fixture_1, test_GetPUParam) { joint->limotP.histop = REAL(5.0); CHECK_EQUAL(joint->limot1.histop, dJointGetPUParam(jId, dParamHiStop) ); joint->limotP.vel = REAL(7.0); CHECK_EQUAL(joint->limot1.vel, dJointGetPUParam(jId, dParamVel) ); #ifdef dParamFudgeFactor1 joint->limotP.dParamFudgeFactor = REAL(5.5); CHECK_EQUAL(joint->limot1.dParamFudgeFactor, dJointGetPUParam(jId, dParamFudgeFactor1) ); #endif joint->limot2.normal_cfm = REAL(9.0); CHECK_EQUAL(joint->limot2.normal_cfm, dJointGetPUParam(jId, dParamCFM2) ); joint->limot2.stop_erp = REAL(11.0); CHECK_EQUAL(joint->limot2.stop_erp, dJointGetPUParam(jId, dParamStopERP2) ); joint->limotP.bounce = REAL(13.0); CHECK_EQUAL(joint->limotP.bounce, dJointGetPUParam(jId, dParamBounce3) ); } //////////////////////////////////////////////////////////////////////////////// // Texture for testing the PositionRate // // Default Position: // Position Body1 (3, 0, 0) // Position Body2 (1, 0, 0) // Angchor (2, 0, 0) // Axis1 (0, 1, 0) // Axis2 (0, 0, 1) // AxisP1 (1, 0, 0) // // Default velocity: // Body 1 lvel=( 0, 0, 0) avel=( 0, 0, 0) // Body 2 lvel=( 0, 0, 0) avel=( 0, 0, 0) // // // Y ^ Axis2 // ^ | // / | ^ Axis1 // Z^ / | / // | / Body 2 | / Body 1 // | / +---------+ | / +-----------+ // | / / /| | / / /| // | / / / + _/ - / / + // | / / /-/--------(_)----|--- /-----------/-------> AxisP // | / +---------+ / - +-----------+ / // | / | |/ | |/ // | / +---------+ +-----------+ // |/ // .-----------------------------------------> X // |-----------------> // Anchor2 <--------------| // Anchor1 // //////////////////////////////////////////////////////////////////////////////// struct PUGetInfo1_Fixture_3 { PUGetInfo1_Fixture_3() { wId = dWorldCreate(); bId1 = dBodyCreate(wId); dBodySetPosition(bId1, 3, 0, 0); bId2 = dBodyCreate(wId); dBodySetPosition(bId2, 1, 0, 0); jId = dJointCreatePU(wId, 0); joint = (dxJointPU*)jId; dJointAttach(jId, bId1, bId2); dJointSetPUAnchor (jId, 2, 0, 0); dBodySetLinearVel (bId1, REAL(0.0), REAL(0.0), REAL(0.0)); dBodySetAngularVel(bId1, REAL(0.0), REAL(0.0), REAL(0.0)); dBodySetLinearVel (bId2, REAL(0.0), REAL(0.0), REAL(0.0)); dBodySetAngularVel(bId1, REAL(0.0), REAL(0.0), REAL(0.0)); } ~PUGetInfo1_Fixture_3() { dWorldDestroy(wId); } dJointID jId; dxJointPU* joint; dWorldID wId; dBodyID bId1; dBodyID bId2; dxJoint::Info1 info; }; //////////////////////////////////////////////////////////////////////////////// // Position Body1 [3, 0, 0] // Position Body2 [1, 0, 0] // Axis of the prismatic [1, 0, 0] // Axis1 [0, 1, 0] // Axis2 [0, 0, 1] // // Move at the same speed //////////////////////////////////////////////////////////////////////////////// TEST_FIXTURE(PUGetInfo1_Fixture_3, test1_GetPUPositionRate) { // They move with the same linear speed // Angular speed == 0 dBodySetLinearVel(bId1, REAL(0.0), REAL(3.33), REAL(0.0)); dBodySetLinearVel(bId2, REAL(0.0), REAL(3.33), REAL(0.0)); CHECK_EQUAL(REAL(0.0), dJointGetPUPositionRate (jId) ); dBodySetLinearVel(bId1, REAL(1.11), REAL(3.33), REAL(0.0)); dBodySetLinearVel(bId2, REAL(1.11), REAL(3.33), REAL(0.0)); CHECK_EQUAL(REAL(0.0), dJointGetPUPositionRate (jId) ); dBodySetLinearVel(bId1, REAL(1.11), REAL(3.33), REAL(2.22)); dBodySetLinearVel(bId2, REAL(1.11), REAL(3.33), REAL(2.22)); CHECK_EQUAL(REAL(0.0), dJointGetPUPositionRate (jId) ); // Reset for the next set of test. dBodySetLinearVel(bId1, REAL(0.0), REAL(0.0), REAL(0.0)); dBodySetAngularVel(bId1, REAL(0.0), REAL(0.0), REAL(0.0)); dBodySetLinearVel(bId2, REAL(0.0), REAL(0.0), REAL(0.0)); dBodySetAngularVel(bId1, REAL(0.0), REAL(0.0), REAL(0.0)); // They move with the same angular speed // linear speed == 0 dBodySetAngularVel(bId1, REAL(1.22), REAL(0.0), REAL(0.0)); dBodySetAngularVel(bId2, REAL(1.22), REAL(0.0), REAL(0.0)); CHECK_EQUAL(REAL(0.0), dJointGetPUPositionRate (jId) ); dBodySetAngularVel(bId1, REAL(1.22), REAL(2.33), REAL(0.0)); dBodySetAngularVel(bId2, REAL(1.22), REAL(2.33), REAL(0.0)); CHECK_EQUAL(REAL(0.0), dJointGetPUPositionRate (jId) ); dBodySetAngularVel(bId1, REAL(1.22), REAL(2.33), REAL(3.44)); dBodySetAngularVel(bId2, REAL(1.22), REAL(2.33), REAL(3.44)); CHECK_EQUAL(REAL(0.0), dJointGetPUPositionRate (jId) ); } //////////////////////////////////////////////////////////////////////////////// // Position Body1 [3, 0, 0] // Position Body2 [1, 0, 0] // Axis of the prismatic [1, 0, 0] // Axis1 [0, 1, 0] // Axis2 [0, 0, 1] // // Only the first body moves //////////////////////////////////////////////////////////////////////////////// TEST_FIXTURE(PUGetInfo1_Fixture_3, GetPUPositionRate_Bodies_in_line_B1_moves) { dBodySetLinearVel(bId1, REAL(3.33), REAL(0.0), REAL(0.0)); // This is impossible but ... CHECK_EQUAL(REAL(3.33), dJointGetPUPositionRate (jId) ); dBodySetLinearVel(bId1, REAL(0.0), REAL(3.33), REAL(0.0)); CHECK_EQUAL(REAL(0.0), dJointGetPUPositionRate (jId) ); dBodySetLinearVel(bId1, REAL(0.0), REAL(0.0), REAL(3.33)); // This is impossible but ... CHECK_EQUAL(REAL(0.0), dJointGetPUPositionRate (jId) ); // Only the first body as angular velocity dBodySetAngularVel(bId1, REAL(1.22), REAL(0.0), REAL(0.0)); CHECK_EQUAL(REAL(0.0), dJointGetPUPositionRate (jId) ); dBodySetAngularVel(bId1, REAL(0.0), REAL(2.33), REAL(0.0)); CHECK_EQUAL(REAL(0.0), dJointGetPUPositionRate (jId) ); dBodySetAngularVel(bId1, REAL(0.0), REAL(0.0), REAL(5.55)); CHECK_EQUAL(REAL(0.0), dJointGetPUPositionRate (jId) ); } //////////////////////////////////////////////////////////////////////////////// // Position Body1 [3, 0, 0] // Position Body2 [1, 0, 0] // Axis of the prismatic [1, 0, 0] // Axis1 [0, 1, 0] // Axis2 [0, 0, 1] // // Only the second body moves //////////////////////////////////////////////////////////////////////////////// TEST_FIXTURE(PUGetInfo1_Fixture_3, GetPUPositionRate_Bodies_in_line_B2_moves) { // The length was at zero and this will give an negative length dBodySetLinearVel(bId2, REAL(3.33), REAL(0.0), REAL(0.0)); CHECK_EQUAL(REAL(-3.33), dJointGetPUPositionRate (jId) ); dBodySetLinearVel(bId2, REAL(0.0), REAL(3.33), REAL(0.0)); // This is impossible but ... CHECK_EQUAL(REAL(0.0), dJointGetPUPositionRate (jId) ); dBodySetLinearVel(bId2, REAL(0.0), REAL(0.0), REAL(3.33)); // This is impossible but ... CHECK_EQUAL(REAL(0.0), dJointGetPUPositionRate (jId) ); // Only angular velocity dBodySetAngularVel(bId2, REAL(1.22), REAL(0.0), REAL(0.0)); CHECK_EQUAL(REAL(0.0), dJointGetPUPositionRate (jId) ); dBodySetAngularVel(bId2, REAL(0.0), REAL(2.33), REAL(0.0)); CHECK_EQUAL(REAL(0.0), dJointGetPUPositionRate (jId) ); dBodySetAngularVel(bId2, REAL(0.0), REAL(0.0), REAL(5.55)); CHECK_EQUAL(REAL(0.0), dJointGetPUPositionRate (jId) ); } //////////////////////////////////////////////////////////////////////////////// // Fixture for testing the PositionRate // // Default Position: // Position Body1 (3, 0, 0) // Position Body2 (0, 0, 1) // Angchor (2, 0, 0) // Axis1 (0, 1, 0) // Axis2 (1, 0, 0) // AxisP (1, 0, 0) // // The second body is at 90deg w.r.t. the first body // // // Default Position // ^Z // | // | // // +---+ // | |Body2 // | | // | | // +---+ // | ^ Axis1 // | / // | / // | / Body1 // R _ - +-----------+ // (_)----|-----| | ----->X AxisP, Axis2 // - +-----------+ // // N.B. Y is going into the page //////////////////////////////////////////////////////////////////////////////// struct PUGetInfo1_Fixture_4 { PUGetInfo1_Fixture_4() { wId = dWorldCreate(); bId1 = dBodyCreate(wId); dBodySetPosition(bId1, 3, 0, 0); bId2 = dBodyCreate(wId); dBodySetPosition(bId2, 0, 0, 1); dMatrix3 R; dRFromAxisAndAngle (R, 1, 0, 0, -M_PI/2.0); dBodySetRotation (bId2, R); jId = dJointCreatePU(wId, 0); joint = (dxJointPU*)jId; dJointAttach(jId, bId1, bId2); dJointSetPUAnchor (jId, 2, 0, 0); dJointSetPUAxis1 (jId, 0, 1, 0); dJointSetPUAxis2 (jId, 1, 0, 0); dJointSetPUAxisP (jId, 1, 0, 0); dBodySetLinearVel(bId1, REAL(0.0), REAL(0.0), REAL(0.0)); dBodySetAngularVel(bId1, REAL(0.0), REAL(0.0), REAL(0.0)); dBodySetLinearVel(bId2, REAL(0.0), REAL(0.0), REAL(0.0)); dBodySetAngularVel(bId1, REAL(0.0), REAL(0.0), REAL(0.0)); } ~PUGetInfo1_Fixture_4() { dWorldDestroy(wId); } dJointID jId; dxJointPU* joint; dWorldID wId; dBodyID bId1; dBodyID bId2; dxJoint::Info1 info; }; //////////////////////////////////////////////////////////////////////////////// // Position Body1 (3, 0, 0) // Position Body2 (1, 0, 0) // Angchor (2, 0, 0) // Axis1 (0, 1, 0) // Axis2 (0, 0, 1) // AxisP1 (1, 0, 0) // // Only the first body moves //////////////////////////////////////////////////////////////////////////////// TEST_FIXTURE(PUGetInfo1_Fixture_4, GetPUPositionRate_Bodies_at90deg_B1_moves) { dBodySetLinearVel(bId1, REAL(3.33), REAL(0.0), REAL(0.0)); // This is impossible but ... CHECK_EQUAL(REAL(3.33), dJointGetPUPositionRate (jId) ); dBodySetLinearVel(bId1, REAL(0.0), REAL(3.33), REAL(0.0)); CHECK_EQUAL(REAL(0.0), dJointGetPUPositionRate (jId) ); dBodySetLinearVel(bId1, REAL(0.0), REAL(0.0), REAL(3.33)); // This is impossible but ... CHECK_EQUAL(REAL(0.0), dJointGetPUPositionRate (jId) ); // Only angular velocity dBodySetAngularVel(bId1, REAL(1.22), REAL(0.0), REAL(0.0)); CHECK_EQUAL(REAL(0.0), dJointGetPUPositionRate (jId) ); dBodySetAngularVel(bId1, REAL(0.0), REAL(2.33), REAL(0.0)); CHECK_EQUAL(REAL(0.0), dJointGetPUPositionRate (jId) ); dBodySetAngularVel(bId1, REAL(0.0), REAL(0.0), REAL(5.55)); CHECK_EQUAL(REAL(0.0), dJointGetPUPositionRate (jId) ); } //////////////////////////////////////////////////////////////////////////////// // Position Body1 (3, 0, 0) // Position Body2 (1, 0, 0) // Angchor (2, 0, 0) // Axis1 (0, 1, 0) // Axis2 (0, 0, 1) // AxisP1 (1, 0, 0) // // Only the second body moves //////////////////////////////////////////////////////////////////////////////// TEST_FIXTURE(PUGetInfo1_Fixture_4, GetPUPositionRate_Bodies_at90deg_B2_moves) { // The length was at zero and this will give an negative length dBodySetLinearVel(bId2, REAL(3.33), REAL(0.0), REAL(0.0)); CHECK_EQUAL(REAL(-3.33), dJointGetPUPositionRate (jId) ); dBodySetLinearVel(bId2, REAL(0.0), REAL(3.33), REAL(0.0)); // This is impossible but ... CHECK_EQUAL(REAL(0.0), dJointGetPUPositionRate (jId) ); dBodySetLinearVel(bId2, REAL(0.0), REAL(0.0), REAL(3.33)); // This is impossible but ... CHECK_EQUAL(REAL(0.0), dJointGetPUPositionRate (jId) ); // Only angular velocity dBodySetAngularVel(bId2, REAL(1.22), REAL(0.0), REAL(0.0)); CHECK_EQUAL(REAL(0.0), dJointGetPUPositionRate (jId) ); dBodySetAngularVel(bId2, REAL(0.0), REAL(2.33), REAL(0.0)); CHECK_EQUAL(REAL(-1.0*2.330), dJointGetPUPositionRate (jId) ); dBodySetAngularVel(bId2, REAL(0.0), REAL(0.0), REAL(5.55)); CHECK_EQUAL(REAL(0.0), dJointGetPUPositionRate (jId) ); } } // End of SUITE(JointPU) // ============================================================================= // ============================================================================= // // Testing the Piston Joint // // ============================================================================= // ============================================================================= //////////////////////////////////////////////////////////////////////////////// // Default Position: // Position Body1 (1, 0, 0) // Position Body2 (3, 0, 0) // Angchor (2, 0, 0) // AxisR (0, 1, 0) // Axis2 (0, 0, 1) // AxisP1 (1, 0, 0) // ///
///^Z                             |- Anchor point
/// |     Body_1                  |                       Body_2
/// |     +---------------+       V                       +------------------+
/// |    /               /|                             /                  /|
/// |   /               / +       |--      ______      /                  / +
/// .- /      x        /./........x.......(_____()..../         x        /.......> axis
///   +---------------+ /         |--                +------------------+ /        X
///   |               |/                             |                  |/
///   +---------------+                              +------------------+
///          |                                                 |
///          |                                                 |
///          |------------------> <----------------------------|
///              anchor1                  anchor2
///
///
/// Axis Y is going into the page
////////////////////////////////////////////////////////////////////////////////
SUITE(JointPiston)
{
    struct PistonGetInfo1_Fixture_1
    {
        PistonGetInfo1_Fixture_1()
        {
            wId = dWorldCreate();

            bId1 = dBodyCreate(wId);
            dBodySetPosition(bId1, 1, 0, 0);

            bId2 = dBodyCreate(wId);
            dBodySetPosition(bId2, 3, 0, 0);


            jId = dJointCreatePiston(wId, 0);
            joint = (dxJointPiston*)jId;

            dJointAttach(jId, bId1, bId2);

            dJointSetPistonAnchor (jId, 2, 0, 0);
        }

        ~PistonGetInfo1_Fixture_1()
        {
            dWorldDestroy(wId);
        }

        dJointID jId;
        dxJointPiston* joint;

        dWorldID wId;

        dBodyID bId1;
        dBodyID bId2;

        dxJoint::Info1 info;
    };


////////////////////////////////////////////////////////////////////////////////
// Test when there is no limits.
// The 2 bodies stay aligned.
//
////////////////////////////////////////////////////////////////////////////////
    TEST_FIXTURE(PistonGetInfo1_Fixture_1, test1_SetPistonParam)
    {
        dJointSetPistonParam(jId, dParamLoStop1, -dInfinity);
        dJointSetPistonParam(jId, dParamHiStop1,  dInfinity);
        dJointSetPistonParam(jId, dParamLoStop2, -M_PI);
        dJointSetPistonParam(jId, dParamHiStop2 , M_PI);

        joint->getInfo1(&info);

        CHECK_EQUAL(0, joint->limotP.limit);
        CHECK_EQUAL(0, joint->limotR.limit);
        CHECK_EQUAL(4, info.m);
    }


////////////////////////////////////////////////////////////////////////////////
// Test when there is limits for the prismatic at -10 and 10
// The Body 2 is moved -100 unit then at 100
//
// Default value for axisR1 = 1,0,0
// Default value for axisP1 = 0,1,0
////////////////////////////////////////////////////////////////////////////////
    TEST_FIXTURE(PistonGetInfo1_Fixture_1, test1_GetPistonParam)
    {
        dJointSetPistonParam(jId, dParamLoStop1, -10);
        dJointSetPistonParam(jId, dParamHiStop1,  10);

        dBodySetPosition(bId2, REAL(-100.0), REAL(0.0), REAL(0.0));

        joint->getInfo1(&info);

        CHECK_EQUAL(2, joint->limotP.limit);
        CHECK_EQUAL(0, joint->limotR.limit);
        CHECK_EQUAL(5, info.m);


        dBodySetPosition(bId2, REAL(100.0), REAL(0.0), REAL(0.0));

        joint->getInfo1(&info);

        CHECK_EQUAL(0, joint->limotR.limit);
        CHECK_EQUAL(1, joint->limotP.limit);
        CHECK_EQUAL(5, info.m);

        // Reset Position and test
        dBodySetPosition(bId2, 1, 0, 0);
        dMatrix3 R_final = { 1,0,0,0,
                             0,1,0,0,
                             0,0,1,0
                           };
        dBodySetRotation (bId2, R_final);

        joint->getInfo1(&info);


        CHECK_EQUAL(0, joint->limotR.limit);
        CHECK_EQUAL(0, joint->limotP.limit);
        CHECK_EQUAL(4, info.m);
    }

////////////////////////////////////////////////////////////////////////////////
// Test when there is limits for the prismatic at -10 and 10
// and the rotoide at -45deg and 45deg.
// The Body 2 is rotated by 90deg around the axis
//
//
////////////////////////////////////////////////////////////////////////////////
    TEST_FIXTURE(PistonGetInfo1_Fixture_1, test2_PistonGetInfo1)
    {
        dJointSetPistonParam(jId, dParamLoStop1, -10);
        dJointSetPistonParam(jId, dParamHiStop1,  10);
        dJointSetPistonParam(jId, dParamLoStop2, -M_PI/4.0);
        dJointSetPistonParam(jId, dParamHiStop2, M_PI/4.0);

        dMatrix3 R;
        dRFromAxisAndAngle (R, 1, 0, 0, M_PI/2.0);
        dBodySetRotation (bId2, R);

        joint->getInfo1(&info);

        CHECK_EQUAL(1, joint->limotR.limit);
        CHECK_EQUAL(0, joint->limotP.limit);
        CHECK_EQUAL(5, info.m);

        // Reset Position and test
        dMatrix3 R_final = { 1,0,0,0,
                             0,1,0,0,
                             0,0,1,0
                           };
        dBodySetRotation (bId2, R_final);

        joint->getInfo1(&info);

        CHECK_EQUAL(0, joint->limotR.limit);
        CHECK_EQUAL(0, joint->limotP.limit);
        CHECK_EQUAL(4, info.m);
    }

////////////////////////////////////////////////////////////////////////////////
// Test when there is limits for the prismatic at -10 and 10
// and for rotoide at -45deg and 45deg.
// The Body 2 is rotated by 90deg around the axis
// Body1 is moved at X=100
//
//
////////////////////////////////////////////////////////////////////////////////
    TEST_FIXTURE(PistonGetInfo1_Fixture_1, test3_PistonGetInfo1)
    {
        dJointSetPistonParam(jId, dParamLoStop1, -10);
        dJointSetPistonParam(jId, dParamHiStop1,  10);
        dJointSetPistonParam(jId, dParamLoStop2, -M_PI/4.0);
        dJointSetPistonParam(jId, dParamHiStop2, M_PI/4.0);


        dBodySetPosition (bId1, REAL(100.0), REAL(0.0), REAL(0.0));

        dMatrix3 R;
        dRFromAxisAndAngle (R, 1, 0, 0, M_PI/2.0);
        dBodySetRotation (bId2, R);

        joint->getInfo1(&info);

        CHECK_EQUAL(2, joint->limotP.limit);
        CHECK_EQUAL(1, joint->limotR.limit);

        CHECK_EQUAL(6, info.m);

        // Reset Position and test
        dBodySetPosition(bId1, 1, 0, 0);

        dMatrix3 R_final = { 1,0,0,0,
                             0,1,0,0,
                             0,0,1,0
                           };
        dBodySetRotation (bId2, R_final);

        joint->getInfo1(&info);

        CHECK_EQUAL(0, joint->limotP.limit);
        CHECK_EQUAL(0, joint->limotR.limit);
        CHECK_EQUAL(4, info.m);
    }


////////////////////////////////////////////////////////////////////////////////
// Default Position:
// Position Body1 (1, 0, 0)
// Position Body2 (3, 0, 0)
// Angchor        (2, 0, 0)
// AxisR          (0, 1, 0)
// Axis2          (0, 0, 1)
// AxisP1         (1, 0, 0)
//
// The motor on axis1 is now powered. (i.e. joint->limot1->fmax > 0
//
/// 
///^Z                             |- Anchor point
/// |     Body_1                  |                       Body_2
/// |     +---------------+       V                       +------------------+
/// |    /               /|                             /                  /|
/// |   /               / +       |--      ______      /                  / +
/// .- /      x        /./........x.......(_____()..../         x        /.......> axis
///   +---------------+ /         |--                +------------------+ /        X
///   |               |/                             |                  |/
///   +---------------+                              +------------------+
///          |                                                 |
///          |                                                 |
///          |------------------> <----------------------------|
///              anchor1                  anchor2
///
///
/// Axis Y is going into the page
////////////////////////////////////////////////////////////////////////////////
    struct PistonGetInfo1_Fixture_2
    {
        PistonGetInfo1_Fixture_2()
        {
            wId = dWorldCreate();

            bId1 = dBodyCreate(wId);
            dBodySetPosition(bId1, 1, 0, 0);

            bId2 = dBodyCreate(wId);
            dBodySetPosition(bId2, 3, 0, 0);


            jId = dJointCreatePiston(wId, 0);
            joint = (dxJointPiston*)jId;

            dJointAttach(jId, bId1, bId2);

            dJointSetPistonAnchor (jId, 2, 0, 0);

            joint->limotP.fmax = 1;
        }

        ~PistonGetInfo1_Fixture_2()
        {
            dWorldDestroy(wId);
        }

        dJointID jId;
        dxJointPiston* joint;

        dWorldID wId;

        dBodyID bId1;
        dBodyID bId2;

        dxJoint::Info1 info;
    };



////////////////////////////////////////////////////////////////////////////////
// Test when there is no limits.
// The 2 bodies stay aligned.
//
////////////////////////////////////////////////////////////////////////////////
    TEST_FIXTURE(PistonGetInfo1_Fixture_2,  test0_PistonGetInfo1)
    {
        dJointSetPistonParam(jId, dParamLoStop1, -dInfinity);
        dJointSetPistonParam(jId, dParamHiStop1,  dInfinity);
        dJointSetPistonParam(jId, dParamLoStop2, -M_PI);
        dJointSetPistonParam(jId, dParamHiStop2,  M_PI);


        joint->getInfo1(&info);

        CHECK_EQUAL(0, joint->limotP.limit);
        CHECK_EQUAL(0, joint->limotR.limit);
        CHECK_EQUAL(5, info.m);
    }


////////////////////////////////////////////////////////////////////////////////
// Test when there is limits for the prismatic at -10 and 10
// The Body 2 is moved -100 unit then at 100
//
// Default value for axis = 1,0,0
////////////////////////////////////////////////////////////////////////////////
    TEST_FIXTURE(PistonGetInfo1_Fixture_2, test1_PistonGetInfo1)
    {
        dJointSetPistonParam(jId, dParamLoStop1, -10);
        dJointSetPistonParam(jId, dParamHiStop1,  10);

        dBodySetPosition(bId2, REAL(-100.0), REAL(0.0), REAL(0.0));

        joint->getInfo1(&info);

        CHECK_EQUAL(2, joint->limotP.limit);
        CHECK_EQUAL(0, joint->limotR.limit);
        CHECK_EQUAL(5, info.m);


        dBodySetPosition(bId2, REAL(100.0), REAL(0.0), REAL(0.0));

        joint->getInfo1(&info);

        CHECK_EQUAL(1, joint->limotP.limit);
        CHECK_EQUAL(0, joint->limotR.limit);
        CHECK_EQUAL(5, info.m);

        // Reset Position and test
        dBodySetPosition(bId2, 3, 0, 0);
        dMatrix3 R_final = { 1,0,0,0,
                             0,1,0,0,
                             0,0,1,0
                           };
        dBodySetRotation (bId2, R_final);

        joint->getInfo1(&info);

        CHECK_EQUAL(0, joint->limotP.limit);
        CHECK_EQUAL(0, joint->limotR.limit);
        CHECK_EQUAL(5, info.m);
    }

////////////////////////////////////////////////////////////////////////////////
// Test when there is limits for the prismatic at -10 and 10
// and for the rotoide at -45deg and 45deg.
// The Body 2 is rotated by 90deg around the axis
//
//
////////////////////////////////////////////////////////////////////////////////
    TEST_FIXTURE(PistonGetInfo1_Fixture_2, test2_PistonGetInfo1)
    {
        dJointSetPistonParam(jId, dParamLoStop1, -10);
        dJointSetPistonParam(jId, dParamHiStop1,  10);
        dJointSetPistonParam(jId, dParamLoStop2, -M_PI/4.0);
        dJointSetPistonParam(jId, dParamHiStop2, M_PI/4.0);

        dMatrix3 R;
        dRFromAxisAndAngle (R, 1, 0, 0, M_PI/2.0);
        dBodySetRotation (bId2, R);

        joint->getInfo1(&info);

        CHECK_EQUAL(0, joint->limotP.limit);
        CHECK_EQUAL(1, joint->limotR.limit);
        CHECK_EQUAL(6, info.m);

        // Reset Position and test
        dMatrix3 R_final = { 1,0,0,0,
                             0,1,0,0,
                             0,0,1,0
                           };
        dBodySetRotation (bId2, R_final);

        joint->getInfo1(&info);

        CHECK_EQUAL(0, joint->limotP.limit);
        CHECK_EQUAL(0, joint->limotR.limit);
        CHECK_EQUAL(5, info.m);
    }

////////////////////////////////////////////////////////////////////////////////
// Test when there is limits for the prismatic at -10 and 10
// and for the rotoide axuis at -45deg and 45deg.
// The Body 2 is rotated by 90deg around the axis and
// Body1 is moved at X=100
//
//
////////////////////////////////////////////////////////////////////////////////
    TEST_FIXTURE(PistonGetInfo1_Fixture_2, test3_PistonGetInfo1)
    {
        dJointSetPistonParam(jId, dParamLoStop1, -10);
        dJointSetPistonParam(jId, dParamHiStop1,  10);
        dJointSetPistonParam(jId, dParamLoStop2, -M_PI/4.0);
        dJointSetPistonParam(jId, dParamHiStop2, M_PI/4.0);



        dBodySetPosition (bId1, REAL(100.0), REAL(0.0), REAL(0.0));

        dMatrix3 R;
        dRFromAxisAndAngle (R, 1, 0, 0, M_PI/2.0);
        dBodySetRotation (bId2, R);

        joint->getInfo1(&info);

        CHECK_EQUAL(2, joint->limotP.limit);
        CHECK_EQUAL(1, joint->limotR.limit);
        CHECK_EQUAL(6, info.m);

        // Reset Position and test
        dBodySetPosition(bId1, 1, 0, 0);

        dBodySetPosition(bId2, 3, 0, 0);
        dMatrix3 R_final = { 1,0,0,0,
                             0,1,0,0,
                             0,0,1,0
                           };
        dBodySetRotation (bId2, R_final);

        joint->getInfo1(&info);

        CHECK_EQUAL(0, joint->limotP.limit);
        CHECK_EQUAL(0, joint->limotR.limit);
        CHECK_EQUAL(5, info.m);
    }



    TEST_FIXTURE(PistonGetInfo1_Fixture_2, test_SetPistonParam)
    {
        dJointSetPistonParam(jId, dParamHiStop, REAL(5.0) );
        CHECK_EQUAL(REAL(5.0), joint->limotP.histop);

        dJointSetPistonParam(jId, dParamVel, REAL(7.0) );
        CHECK_EQUAL(REAL(7.0), joint->limotP.vel);

#ifdef dParamFudgeFactor1
        dJointSetPistonParam(jId, dParamFudgeFactor1, REAL(5.5) );
        CHECK_EQUAL(REAL(5.5), joint->limotP.dParamFudgeFactor);
#endif

        dJointSetPistonParam(jId, dParamCFM2, REAL(9.0) );
        CHECK_EQUAL(REAL(9.0), joint->limotR.normal_cfm);

        dJointSetPistonParam(jId, dParamStopERP2, REAL(11.0) );
        CHECK_EQUAL(REAL(11.0), joint->limotR.stop_erp);
    }



    TEST_FIXTURE(PistonGetInfo1_Fixture_1, test_GetPistonParam)
    {
        joint->limotP.histop = REAL(5.0);
        CHECK_EQUAL(joint->limotP.histop,
                    dJointGetPistonParam(jId, dParamHiStop) );

        joint->limotP.vel = REAL(7.0);

        CHECK_EQUAL(joint->limotP.vel,
                    dJointGetPistonParam(jId, dParamVel) );

#ifdef dParamFudgeFactor1
        joint->limotP.dParamFudgeFactor =  REAL(5.5);

        CHECK_EQUAL(joint->limotP.dParamFudgeFactor,
                    dJointGetPistonParam(jId, dParamFudgeFactor1) );
#endif

        joint->limotR.normal_cfm = REAL(9.0);
        CHECK_EQUAL(joint->limotR.normal_cfm,
                    dJointGetPistonParam(jId, dParamCFM2) );

        joint->limotR.stop_erp = REAL(11.0);
        CHECK_EQUAL(joint->limotR.stop_erp,
                    dJointGetPistonParam(jId, dParamStopERP2) );
    }



////////////////////////////////////////////////////////////////////////////////
// Texture for testing the PositionRate
//
// Default Position:
//   Position Body1 (3, 0, 0)
//   Position Body2 (1, 0, 0)
//   Angchor        (2, 0, 0)
//   Axis1          (0, 1, 0)
//   Axis2          (0, 0, 1)
//   AxisP1         (1, 0, 0)
//
// Default velocity:
//   Body 1 lvel=( 0, 0, 0)    avel=( 0, 0, 0)
//   Body 2 lvel=( 0, 0, 0)    avel=( 0, 0, 0)
//
//
//               Y                ^ Axis2
//              ^                 |
//             /                  |     ^ Axis1
// Z^         /                   |    /
//  |        / Body 2             |   /         Body 1
//  |       /  +---------+        |  /          +-----------+
//  |      /  /         /|        | /          /           /|
//  |     /  /         / +        _/     -    /           / +
//  |    /  /         /-/--------(_)----|--- /-----------/-------> AxisP
//  |   /  +---------+ /                 -  +-----------+ /
//  |  /   |         |/                     |           |/
//  | /    +---------+                      +-----------+
//  |/
//  .-----------------------------------------> X
//             |----------------->
//             Anchor2           <--------------|
//                               Anchor1
//
////////////////////////////////////////////////////////////////////////////////
    struct PistonGetInfo1_Fixture_3
    {
        PistonGetInfo1_Fixture_3()
        {
            wId = dWorldCreate();

            bId1 = dBodyCreate(wId);
            dBodySetPosition(bId1, 3, 0, 0);

            bId2 = dBodyCreate(wId);
            dBodySetPosition(bId2, 1, 0, 0);


            jId = dJointCreatePiston(wId, 0);
            joint = (dxJointPiston*)jId;

            dJointAttach(jId, bId1, bId2);
            dJointSetPistonAnchor (jId, 2, 0, 0);

            dBodySetLinearVel (bId1, REAL(0.0), REAL(0.0), REAL(0.0));
            dBodySetAngularVel(bId1, REAL(0.0), REAL(0.0), REAL(0.0));

            dBodySetLinearVel (bId2, REAL(0.0), REAL(0.0), REAL(0.0));
            dBodySetAngularVel(bId1, REAL(0.0), REAL(0.0), REAL(0.0));

        }

        ~PistonGetInfo1_Fixture_3()
        {
            dWorldDestroy(wId);
        }

        dJointID jId;
        dxJointPiston* joint;

        dWorldID wId;

        dBodyID bId1;
        dBodyID bId2;

        dxJoint::Info1 info;
    };

////////////////////////////////////////////////////////////////////////////////
// Position Body1 [3, 0, 0]
// Position Body2 [1, 0, 0]
// Axis of the prismatic [1, 0, 0]
// Axis1                 [0, 1, 0]
// Axis2                 [0, 0, 1]
//
// Move at the same speed
////////////////////////////////////////////////////////////////////////////////
    TEST_FIXTURE(PistonGetInfo1_Fixture_3, test1_GetPistonPositionRate)
    {
        // They move with the same linear speed
        // Angular speed == 0
        dBodySetLinearVel(bId1, 0, REAL(3.33), 0);
        dBodySetLinearVel(bId2, 0, REAL(3.33), 0);
        CHECK_EQUAL(REAL(0.0), dJointGetPistonPositionRate (jId) );

        dBodySetLinearVel(bId1, REAL(1.11), REAL(3.33), 0);
        dBodySetLinearVel(bId2, REAL(1.11), REAL(3.33), 0);
        CHECK_EQUAL(REAL(0.0), dJointGetPistonPositionRate (jId) );

        dBodySetLinearVel(bId1, REAL(1.11), REAL(3.33), REAL(2.22));
        dBodySetLinearVel(bId2, REAL(1.11), REAL(3.33), REAL(2.22));
        CHECK_EQUAL(REAL(0.0), dJointGetPistonPositionRate (jId) );


        // Reset for the next set of test.
        dBodySetLinearVel(bId1, REAL(0.0), REAL(0.0), REAL(0.0));
        dBodySetAngularVel(bId1, REAL(0.0), REAL(0.0), REAL(0.0));

        dBodySetLinearVel(bId2, REAL(0.0), REAL(0.0), REAL(0.0));
        dBodySetAngularVel(bId1, REAL(0.0), REAL(0.0), REAL(0.0));


        // They move with the same angular speed
        // linear speed == 0

        dBodySetAngularVel(bId1, REAL(1.22), 0.0, 0.0);
        dBodySetAngularVel(bId2, REAL(1.22), 0.0, 0.0);
        CHECK_EQUAL(REAL(0.0), dJointGetPistonPositionRate (jId) );

        dBodySetAngularVel(bId1, REAL(1.22), REAL(2.33), 0.0);
        dBodySetAngularVel(bId2, REAL(1.22), REAL(2.33), 0.0);
        CHECK_EQUAL(REAL(0.0), dJointGetPistonPositionRate (jId) );

        dBodySetAngularVel(bId1, REAL(1.22), REAL(2.33), REAL(3.44));
        dBodySetAngularVel(bId2, REAL(1.22), REAL(2.33), REAL(3.44));
        CHECK_EQUAL(REAL(0.0), dJointGetPistonPositionRate (jId) );
    }


////////////////////////////////////////////////////////////////////////////////
// Position Body1 [3, 0, 0]
// Position Body2 [1, 0, 0]
// Axis of the prismatic [1, 0, 0]
// Axis1                 [0, 1, 0]
// Axis2                 [0, 0, 1]
//
// Only the first body moves
////////////////////////////////////////////////////////////////////////////////
    TEST_FIXTURE(PistonGetInfo1_Fixture_3, GetPistonPositionRate_Bodies_in_line_B1_moves)
    {
        dBodySetLinearVel(bId1, REAL(3.33), 0.0, 0.0); // This is impossible but ...
        CHECK_EQUAL(REAL(3.33), dJointGetPistonPositionRate (jId) );

        dBodySetLinearVel(bId1, 0, REAL(3.33), 0);
        CHECK_EQUAL(REAL(0.0), dJointGetPistonPositionRate (jId) );

        dBodySetLinearVel(bId1, 0, 0, REAL(3.33));     // This is impossible but ...
        CHECK_EQUAL(REAL(0.0), dJointGetPistonPositionRate (jId) );


        // Only the first body as angular velocity
        dBodySetAngularVel(bId1, REAL(1.22), 0.0, 0.0);
        CHECK_EQUAL(REAL(0.0), dJointGetPistonPositionRate (jId) );

        dBodySetAngularVel(bId1, 0.0, REAL(2.33), 0.0);
        CHECK_EQUAL(REAL(0.0), dJointGetPistonPositionRate (jId) );

        dBodySetAngularVel(bId1, 0.0, 0.0, REAL(5.55));
        CHECK_EQUAL(REAL(0.0), dJointGetPistonPositionRate (jId) );
    }

////////////////////////////////////////////////////////////////////////////////
// Position Body1 [3, 0, 0]
// Position Body2 [1, 0, 0]
// Axis of the prismatic [1, 0, 0]
// Axis1                 [0, 1, 0]
// Axis2                 [0, 0, 1]
//
// Only the second body moves
////////////////////////////////////////////////////////////////////////////////
    TEST_FIXTURE(PistonGetInfo1_Fixture_3, GetPistonPositionRate_Bodies_in_line_B2_moves)
    {
        // The length was at zero and this will give an negative length
        dBodySetLinearVel(bId2, REAL(3.33), 0.0, 0.0);
        CHECK_EQUAL(REAL(-3.33), dJointGetPistonPositionRate (jId) );

        dBodySetLinearVel(bId2, 0, REAL(3.33), 0);      // This is impossible but ...
        CHECK_EQUAL(REAL(0.0), dJointGetPistonPositionRate (jId) );

        dBodySetLinearVel(bId2, 0, 0, REAL(3.33));     // This is impossible but ...
        CHECK_EQUAL(REAL(0.0), dJointGetPistonPositionRate (jId) );


        // Only angular velocity
        dBodySetAngularVel(bId2, REAL(1.22), 0.0, 0.0);
        CHECK_EQUAL(REAL(0.0), dJointGetPistonPositionRate (jId) );

        dBodySetAngularVel(bId2, 0.0, REAL(2.33), 0.0);
        CHECK_EQUAL(REAL(0.0), dJointGetPistonPositionRate (jId) );

        dBodySetAngularVel(bId2, 0.0, 0.0, REAL(5.55));
        CHECK_EQUAL(REAL(0.0), dJointGetPistonPositionRate (jId) );
    }


////////////////////////////////////////////////////////////////////////////////
// Fixture for testing the PositionRate
//
// Default Position:
// Position Body1 (3, 0, 0)
// Position Body2 (0, 0, 1)
// Angchor        (2, 0, 0)
// Axis1          (0, 1, 0)
// Axis2          (1, 0, 0)
// AxisP          (1, 0, 0)
//
// The second body is at 90deg w.r.t. the first body
// From
//
//               Y                ^ Axis2
//              ^                 |
//             /                  |     ^ Axis1
// Z^         /                   |    /
//  |        / Body 2             |   /         Body 1
//  |       /  +---------+        |  /          +-----------+
//  |      /  /         /|        | /          /           /|
//  |     /  /         / +        _/     -    /           / +
//  |    /  /         /-/--------(_)----|--- /-----------/-------> AxisP
//  |   /  +---------+ /                 -  +-----------+ /
//  |  /   |         |/                     |           |/
//  | /    +---------+                      +-----------+
//  |/
//  .-----------------------------------------> X
//             |----------------->
//             Anchor2           <--------------|
//                               Anchor1
// To
//
//               Y                ^ Axis2
//              ^                 |
//             /  Body 2          |     ^ Axis1
// Z^          +----------+       |    /
//  |        //          /|       |   /         Body 1
//  |       /+----------+ |       |  /          +-----------+
//  |      / |          | |       | /          /           /|
//  |     /  |          | |       _/     -    /           / +
//  |    /   |          |-|------(_)----|--- /-----------/-------> AxisP
//  |   /    |          | |              -  +-----------+ /
//  |  /     |          | |                 |           |/
//  | /      |          | +                 +-----------+
//  |/       |          |/
//  .--------+----------+--------------------> X
//             |---------------->
//             Anchor2           <--------------|
//                               Anchor1
// Default Position
//
// N.B. Y is going into the page
////////////////////////////////////////////////////////////////////////////////
    struct PistonGetInfo1_Fixture_4
    {
        PistonGetInfo1_Fixture_4()
        {
            wId = dWorldCreate();

            bId1 = dBodyCreate(wId);
            dBodySetPosition(bId1, 3, 0, 0);

            bId2 = dBodyCreate(wId);
            dBodySetPosition(bId2, 0, 0, 1);

            dMatrix3 R;
            dRFromAxisAndAngle (R, 1, 0, 0, -M_PI/2.0);
            dBodySetRotation (bId2, R);


            jId = dJointCreatePiston(wId, 0);
            joint = (dxJointPiston*)jId;

            dJointAttach(jId, bId1, bId2);
            dJointSetPistonAnchor (jId, 2, 0, 0);


            dBodySetLinearVel(bId1, REAL(0.0), REAL(0.0), REAL(0.0));
            dBodySetAngularVel(bId1, REAL(0.0), REAL(0.0), REAL(0.0));

            dBodySetLinearVel(bId2, REAL(0.0), REAL(0.0), REAL(0.0));
            dBodySetAngularVel(bId1, REAL(0.0), REAL(0.0), REAL(0.0));

        }

        ~PistonGetInfo1_Fixture_4()
        {
            dWorldDestroy(wId);
        }

        dJointID jId;
        dxJointPiston* joint;

        dWorldID wId;

        dBodyID bId1;
        dBodyID bId2;

        dxJoint::Info1 info;
    };


////////////////////////////////////////////////////////////////////////////////
// Position Body1 (3, 0, 0)
// Position Body2 (1, 0, 0)
// Angchor        (2, 0, 0)
// Axis1          (0, 1, 0)
// Axis2          (0, 0, 1)
// AxisP1         (1, 0, 0)
//
// Only the first body moves
////////////////////////////////////////////////////////////////////////////////
    TEST_FIXTURE(PistonGetInfo1_Fixture_4, GetPistonPositionRate_Bodies_at90deg_B1_moves)
    {
        dBodySetLinearVel(bId1, REAL(3.33), 0.0, 0.0); // This is impossible but ...
        CHECK_EQUAL(REAL(3.33), dJointGetPistonPositionRate (jId) );

        dBodySetLinearVel(bId1, 0, REAL(3.33), 0);
        CHECK_EQUAL(REAL(0.0), dJointGetPistonPositionRate (jId) );

        dBodySetLinearVel(bId1, 0, 0, REAL(3.33));     // This is impossible but ...
        CHECK_EQUAL(REAL(0.0), dJointGetPistonPositionRate (jId) );


        // Only angular velocity
        dBodySetAngularVel(bId1, REAL(1.22), 0.0, 0.0);
        CHECK_EQUAL(REAL(0.0), dJointGetPistonPositionRate (jId) );

        dBodySetAngularVel(bId1, 0.0, REAL(2.33), 0.0);
        CHECK_EQUAL(REAL(0.0), dJointGetPistonPositionRate (jId) );

        dBodySetAngularVel(bId1, 0.0, 0.0, REAL(5.55));
        CHECK_EQUAL(REAL(0.0), dJointGetPistonPositionRate (jId) );
    }

////////////////////////////////////////////////////////////////////////////////
// Position Body1 (3, 0, 0)
// Position Body2 (1, 0, 0)
// Angchor        (2, 0, 0)
// Axis1          (0, 1, 0)
// Axis2          (0, 0, 1)
// AxisP1         (1, 0, 0)
//
// Only the second body moves
////////////////////////////////////////////////////////////////////////////////
    TEST_FIXTURE(PistonGetInfo1_Fixture_4,  GetPistonPositionRate_Bodies_at90deg_B2_moves)
    {
        // The length was at zero and this will give an negative length
        dBodySetLinearVel(bId2, REAL(3.33), 0.0, 0.0);
        CHECK_EQUAL(REAL(-3.33), dJointGetPistonPositionRate (jId) );

        dBodySetLinearVel(bId2, 0, REAL(3.33), 0);     // This is impossible but ...
        CHECK_EQUAL(REAL(0.0), dJointGetPistonPositionRate (jId) );

        dBodySetLinearVel(bId2, 0, 0, REAL(3.33));     // This is impossible but ...
        CHECK_EQUAL(REAL(0.0), dJointGetPistonPositionRate (jId) );


        // Only angular velocity
        dBodySetAngularVel(bId2, REAL(1.22), 0.0, 0.0);
        CHECK_EQUAL(REAL(0.0), dJointGetPistonPositionRate (jId) );

        dBodySetAngularVel(bId2, 0.0, REAL(2.33), 0.0);
        CHECK_EQUAL(REAL(0.0), dJointGetPistonPositionRate (jId) );

        dBodySetAngularVel(bId2, 0.0, 0.0, REAL(5.55));
        CHECK_EQUAL(REAL(0.0), dJointGetPistonPositionRate (jId) );
    }



    struct Fixture_Simple_Hinge
    {
        Fixture_Simple_Hinge ()
        {
            wId = dWorldCreate();

            bId1 = dBodyCreate(wId);
            dBodySetPosition(bId1, 0, -1, 0);

            bId2 = dBodyCreate(wId);
            dBodySetPosition(bId2, 0, 1, 0);


            jId = dJointCreateHinge(wId, 0);

            dJointAttach(jId, bId1, bId2);
        }

        ~Fixture_Simple_Hinge()
        {
            dWorldDestroy(wId);
        }

        dJointID jId;

        dWorldID wId;

        dBodyID bId1;
        dBodyID bId2;
    };

    // Test that it is possible to have joint without a body
    TEST_FIXTURE(Fixture_Simple_Hinge, test_dJointAttach)
    {
        bool only_body1_OK = true;
        try {
            dJointAttach(jId, bId1, 0);
            dWorldStep (wId, 1);
        }
        catch (...) {
            only_body1_OK = false;
        }
        CHECK_EQUAL(true, only_body1_OK);

        bool only_body2_OK = true;
        try {
            dJointAttach(jId, 0, bId2);
            dWorldStep (wId, 1);
        }
        catch (...) {
            only_body2_OK = false;
        }
        CHECK_EQUAL(true, only_body2_OK);

        bool no_body_OK = true;
        try {
            dJointAttach(jId, 0, 0);
            dWorldStep (wId, 1);
        }
        catch (...) {
            no_body_OK = false;
        }
        CHECK_EQUAL(true, no_body_OK);
    }



} // End of SUITE(JointPiston)
ode-0.16/tests/friction.cpp0000664000175200017520000001503313403272463012627 00000000000000/*************************************************************************
  *                                                                       *
  * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
  * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
  *                                                                       *
  * This library is free software; you can redistribute it and/or         *
  * modify it under the terms of EITHER:                                  *
  *   (1) The GNU Lesser General Public License as published by the Free  *
  *       Software Foundation; either version 2.1 of the License, or (at  *
  *       your option) any later version. The text of the GNU Lesser      *
  *       General Public License is included with this library in the     *
  *       file LICENSE.TXT.                                               *
  *   (2) The BSD-style license that is included with this library in     *
  *       the file LICENSE-BSD.TXT.                                       *
  *                                                                       *
  * This library is distributed in the hope that it will be useful,       *
  * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
  * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
  *                                                                       *
  *************************************************************************/
//234567890123456789012345678901234567890123456789012345678901234567890123456789
//        1         2         3         4         5         6         7

////////////////////////////////////////////////////////////////////////////////
// This file create unit test for some of the functions found in:
// ode/src/joint.cpp
//
//
////////////////////////////////////////////////////////////////////////////////
#include 
#include 
#include 
#include "../ode/src/config.h"
#include "../ode/src/joints/joints.h"


/*
 * Tests for contact friction
 */

SUITE(JointContact)
{
    struct ContactSetup
    {
        dWorldID world;
        dBodyID body1;
        dBodyID body2;
        dJointID joint;

        ContactSetup()
        {
            world = dWorldCreate();
            body1 = dBodyCreate(world);
            body2 = dBodyCreate(world);

            dBodySetPosition(body1, -1, 0, 0);
            dBodySetPosition(body2,  1, 0, 0);
        }

        ~ContactSetup()
        {
            dBodyDestroy(body1);
            dBodyDestroy(body2);
            dWorldDestroy(world);
        }
    };
    
    TEST_FIXTURE(ContactSetup,
                 test_ZeroMu)
    {
        dxJoint::Info1 info1;
        dReal dummy_J[3][16] = {{0}};
        int dummy_findex[3];

        dReal info2_fps = 100;
        dReal info2_erp = 0;
        dReal *J1 = dummy_J[0];
        dReal *J2 = dummy_J[0] + 8;
        dReal *rhscfm = dummy_J[0] + 6;
        dReal *lohi = dummy_J[0] + 14;
        unsigned rowskip = 16;
        int *findex = dummy_findex;

#define ZERO_ALL do {                                           \
            memset(dummy_J, 0, sizeof dummy_J);                 \
            std::fill(dummy_findex, dummy_findex+3, -1);        \
        }                                                       \
        while (0)

        dContact contact;
        contact.surface.mode = dContactMu2 | dContactFDir1 | dContactApprox1;

        contact.geom.pos[0] = 0;
        contact.geom.pos[1] = 0;
        contact.geom.pos[2] = 0;

        // normal points into body1
        contact.geom.normal[0] = -1;
        contact.geom.normal[1] = 0;
        contact.geom.normal[2] = 0;

        contact.geom.depth = 0;

        contact.geom.g1 = 0;
        contact.geom.g2 = 0;

        // we ask for fdir1 = +Y, so fdir2 = normal x fdir1 = -Z
        contact.fdir1[0] = 0;
        contact.fdir1[1] = 1;
        contact.fdir1[2] = 0;

        /*
         * First, test with mu = 0, mu2 = 1
         * Because there is no friction on the first direction (+Y) the body
         * is allowed to translate in the Y axis and rotate around the Z axis.
         *
         * That is, the only constraint will be for the second dir (-Z):
         * so J[1] = [  0  0 -1    0  1  0    0  0  1    0  1  0 ]
         */        
        contact.surface.mu = 0;
        contact.surface.mu2 = 1;
        joint = dJointCreateContact(world, 0, &contact);
        dJointAttach(joint, body1, body2);
        joint->getInfo1(&info1);
        CHECK_EQUAL(2, (int)info1.m);
        ZERO_ALL;
        joint->getInfo2(info2_fps, info2_erp, rowskip, J1, J2,
            rowskip, rhscfm, lohi, findex);
        CHECK_CLOSE(0, dummy_J[1][0], 1e-6);
        CHECK_CLOSE(0, dummy_J[1][1], 1e-6);
        CHECK_CLOSE(-1, dummy_J[1][2], 1e-6);
        CHECK_CLOSE(0, dummy_J[1][3], 1e-6);
        CHECK_CLOSE(1, dummy_J[1][4], 1e-6);
        CHECK_CLOSE(0, dummy_J[1][5], 1e-6);
        CHECK_CLOSE(0, dummy_J[1][8], 1e-6);
        CHECK_CLOSE(0, dummy_J[1][9], 1e-6);
        CHECK_CLOSE(1, dummy_J[1][10], 1e-6);
        CHECK_CLOSE(0, dummy_J[1][11], 1e-6);
        CHECK_CLOSE(1, dummy_J[1][12], 1e-6);
        CHECK_CLOSE(0, dummy_J[1][13], 1e-6);
        CHECK_EQUAL(0, dummy_findex[1]); // because of dContactApprox1
        dJointDestroy(joint);


        /*
         * Now try with no frictino in the second direction. The Jacobian should look like:
         * J[1] = [  0  1  0    0  0  1    0 -1  0    0  0  1 ]
         */
        // try again, with zero mu2
        contact.surface.mu = 1;
        contact.surface.mu2 = 0;
        joint = dJointCreateContact(world, 0, &contact);
        dJointAttach(joint, body1, body2);
        joint->getInfo1(&info1);
        CHECK_EQUAL(2, (int)info1.m);
        ZERO_ALL;
        joint->getInfo2(info2_fps, info2_erp, rowskip, J1, J2,
            rowskip, rhscfm, lohi, findex);
        CHECK_CLOSE(0, dummy_J[1][0], 1e-6);
        CHECK_CLOSE(1, dummy_J[1][1], 1e-6);
        CHECK_CLOSE(0, dummy_J[1][2], 1e-6);
        CHECK_CLOSE(0, dummy_J[1][3], 1e-6);
        CHECK_CLOSE(0, dummy_J[1][4], 1e-6);
        CHECK_CLOSE(1, dummy_J[1][5], 1e-6);
        CHECK_CLOSE(0, dummy_J[1][8], 1e-6);
        CHECK_CLOSE(-1, dummy_J[1][9], 1e-6);
        CHECK_CLOSE(0, dummy_J[1][10], 1e-6);
        CHECK_CLOSE(0, dummy_J[1][11], 1e-6);
        CHECK_CLOSE(0, dummy_J[1][12], 1e-6);
        CHECK_CLOSE(1, dummy_J[1][13], 1e-6);
        CHECK_EQUAL(0, dummy_findex[1]);  // because of dContactApprox1
        dJointDestroy(joint);
    }

}
ode-0.16/drawstuff/0000775000175200017520000000000013403273060011221 500000000000000ode-0.16/drawstuff/src/0000775000175200017520000000000013403273060012010 500000000000000ode-0.16/drawstuff/src/resource.h0000664000175200017520000000173313403272463013742 00000000000000//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by resources.rc
//
#define IDD_MSGDLG                      101
#define IDR_MENU1                       102
#define IDD_ABOUT                       103
#define IDR_ACCELERATOR1                104
#define IDC_LIST1                       1000
#define IDM_EXIT                        40001
#define IDM_ABOUT                       40002
#define IDM_PAUSE                       40003
#define IDM_PERF_MONITOR                40004
#define IDM_SHADOWS                     40005
#define IDM_TEXTURES                    40006
#define IDM_SAVE_SETTINGS               40007
#define IDM_SINGLE_STEP                 40008

// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        108
#define _APS_NEXT_COMMAND_VALUE         40009
#define _APS_NEXT_CONTROL_VALUE         1001
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif
ode-0.16/drawstuff/src/drawstuff.cpp0000664000175200017520000012333313403272463014454 00000000000000/*************************************************************************
 *                                                                       *
 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
 * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
 *                                                                       *
 * This library is free software; you can redistribute it and/or         *
 * modify it under the terms of EITHER:                                  *
 *   (1) The GNU Lesser General Public License as published by the Free  *
 *       Software Foundation; either version 2.1 of the License, or (at  *
 *       your option) any later version. The text of the GNU Lesser      *
 *       General Public License is included with this library in the     *
 *       file LICENSE.TXT.                                               *
 *   (2) The BSD-style license that is included with this library in     *
 *       the file LICENSE-BSD.TXT.                                       *
 *                                                                       *
 * This library is distributed in the hope that it will be useful,       *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
 * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
 *                                                                       *
 *************************************************************************/

/*

simple graphics.

the following command line flags can be used (typically under unix)
  -notex              Do not use any textures
  -noshadow[s]        Do not draw any shadows
  -pause              Start the simulation paused
  -texturepath  Inform an alternative textures path

TODO
----

manage openGL state changes better

*/

#ifdef WIN32
#include 
#endif

#include 
#include "config.h"

#ifdef HAVE_APPLE_OPENGL_FRAMEWORK
#include 
#include 
#else
#include 
#include 
#endif

#include "drawstuff/drawstuff.h"
#include "internal.h"

//***************************************************************************
// misc

#ifndef DEFAULT_PATH_TO_TEXTURES
#if 0
#define DEFAULT_PATH_TO_TEXTURES "..\\textures\\"
#else
#define DEFAULT_PATH_TO_TEXTURES "../textures/"
#endif
#endif

#ifndef M_PI
#define M_PI (3.14159265358979323846)
#endif

// constants to convert degrees to radians and the reverse
#define RAD_TO_DEG (180.0/M_PI)
#define DEG_TO_RAD (M_PI/180.0)

// light vector. LIGHTZ is implicitly 1
#define LIGHTX (1.0f)
#define LIGHTY (0.4f)

// ground and sky
#define SHADOW_INTENSITY (0.65f)
#define GROUND_R (0.5f) 	// ground color for when there's no texture
#define GROUND_G (0.5f)
#define GROUND_B (0.3f)

const float ground_scale = 1.0f/1.0f;	// ground texture scale (1/size)
const float ground_ofsx = 0.5;		// offset of ground texture
const float ground_ofsy = 0.5;
const float sky_scale = 1.0f/4.0f;	// sky texture scale (1/size)
const float sky_height = 1.0f;		// sky height above viewpoint

//***************************************************************************
// misc mathematics stuff

static void normalizeVector3 (float v[3])
{
  float len = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
  if (len <= 0.0f) {
    v[0] = 1;
    v[1] = 0;
    v[2] = 0;
  }
  else {
    len = 1.0f / (float)sqrt(len);
    v[0] *= len;
    v[1] *= len;
    v[2] *= len;
  }
}

static void crossProduct3(float res[3], const float a[3], const float b[3])
{
  float res_0 = a[1]*b[2] - a[2]*b[1];
  float res_1 = a[2]*b[0] - a[0]*b[2];
  float res_2 = a[0]*b[1] - a[1]*b[0];
  // Only assign after all the calculations are over to avoid incurring memory aliasing
  res[0] = res_0;
  res[1] = res_1;
  res[2] = res_2;
}

//***************************************************************************
// PPM image object

typedef unsigned char byte;

class Image {
  int image_width,image_height;
  byte *image_data;
public:
  Image (char *filename);
  // load from PPM file
  ~Image();
  int width() { return image_width; }
  int height() { return image_height; }
  byte *data() { return image_data; }
};


// skip over whitespace and comments in a stream.

static void skipWhiteSpace (char *filename, FILE *f)
{
  int c,d;
  for(;;) {
    c = fgetc(f);
    if (c==EOF) dsError ("unexpected end of file in \"%s\"",filename);

    // skip comments
    if (c == '#') {
      do {
	d = fgetc(f);
	if (d==EOF) dsError ("unexpected end of file in \"%s\"",filename);
      } while (d != '\n');
      continue;
    }

    if (c > ' ') {
      ungetc (c,f);
      return;
    }
  }
}


// read a number from a stream, this return 0 if there is none (that's okay
// because 0 is a bad value for all PPM numbers anyway).

static int readNumber (char *filename, FILE *f)
{
  int c,n=0;
  for(;;) {
    c = fgetc(f);
    if (c==EOF) dsError ("unexpected end of file in \"%s\"",filename);
    if (c >= '0' && c <= '9') n = n*10 + (c - '0');
    else {
      ungetc (c,f);
      return n;
    }
  }
}


Image::Image (char *filename)
{
  FILE *f = fopen (filename,"rb");
  if (!f) dsError ("Can't open image file `%s'",filename);

  // read in header
  if (fgetc(f) != 'P' || fgetc(f) != '6')
    dsError ("image file \"%s\" is not a binary PPM (no P6 header)",filename);
  skipWhiteSpace (filename,f);

  // read in image parameters
  image_width = readNumber (filename,f);
  skipWhiteSpace (filename,f);
  image_height = readNumber (filename,f);
  skipWhiteSpace (filename,f);
  int max_value = readNumber (filename,f);

  // check values
  if (image_width < 1 || image_height < 1)
    dsError ("bad image file \"%s\"",filename);
  if (max_value != 255)
    dsError ("image file \"%s\" must have color range of 255",filename);

  // read either nothing, LF (10), or CR,LF (13,10)
  int c = fgetc(f);
  if (c == 10) {
    // LF
  }
  else if (c == 13) {
    // CR
    c = fgetc(f);
    if (c != 10) ungetc (c,f);
  }
  else ungetc (c,f);

  // read in rest of data
  image_data = new byte [image_width*image_height*3];
  if (fread (image_data,image_width*image_height*3,1,f) != 1)
    dsError ("Can not read data from image file `%s'",filename);
  fclose (f);
}


Image::~Image()
{
  delete[] image_data;
}

//***************************************************************************
// Texture object.

class Texture {
  Image *image;
  GLuint name;
public:
  Texture (char *filename);
  ~Texture();
  void bind (int modulate);
};


Texture::Texture (char *filename)
{
  image = new Image (filename);
  glGenTextures (1,&name);
  glBindTexture (GL_TEXTURE_2D,name);

  // set pixel unpacking mode
  glPixelStorei (GL_UNPACK_SWAP_BYTES, 0);
  glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
  glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
  glPixelStorei (GL_UNPACK_SKIP_ROWS, 0);
  glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);

  // glTexImage2D (GL_TEXTURE_2D, 0, 3, image->width(), image->height(), 0,
  //		   GL_RGB, GL_UNSIGNED_BYTE, image->data());
  gluBuild2DMipmaps (GL_TEXTURE_2D, 3, image->width(), image->height(),
		     GL_RGB, GL_UNSIGNED_BYTE, image->data());

  // set texture parameters - will these also be bound to the texture???
  glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

  glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
		   GL_LINEAR_MIPMAP_LINEAR);

  glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
}


Texture::~Texture()
{
  delete image;
  glDeleteTextures (1,&name);
}


void Texture::bind (int modulate)
{
  glBindTexture (GL_TEXTURE_2D,name);
  glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,
	     modulate ? GL_MODULATE : GL_DECAL);
}

//***************************************************************************
// the current drawing state (for when the user's step function is drawing)

static float color[4] = {0,0,0,0};	// current r,g,b,alpha color
static int tnum = 0;			// current texture number

//***************************************************************************
// OpenGL utility stuff

static void setCamera (float x, float y, float z, float h, float p, float r)
{
  glMatrixMode (GL_MODELVIEW);
  glLoadIdentity();
  glRotatef (90, 0,0,1);
  glRotatef (90, 0,1,0);
  glRotatef (r, 1,0,0);
  glRotatef (p, 0,1,0);
  glRotatef (-h, 0,0,1);
  glTranslatef (-x,-y,-z);
}


// sets the material color, not the light color

static void setColor (float r, float g, float b, float alpha)
{
  GLfloat light_ambient[4],light_diffuse[4],light_specular[4];
  light_ambient[0] = r*0.3f;
  light_ambient[1] = g*0.3f;
  light_ambient[2] = b*0.3f;
  light_ambient[3] = alpha;
  light_diffuse[0] = r*0.7f;
  light_diffuse[1] = g*0.7f;
  light_diffuse[2] = b*0.7f;
  light_diffuse[3] = alpha;
  light_specular[0] = r*0.2f;
  light_specular[1] = g*0.2f;
  light_specular[2] = b*0.2f;
  light_specular[3] = alpha;
  glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, light_ambient);
  glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, light_diffuse);
  glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, light_specular);
  glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, 5.0f);
}


static void setTransform (const float pos[3], const float R[12])
{
  GLfloat matrix[16];
  matrix[0]=R[0];
  matrix[1]=R[4];
  matrix[2]=R[8];
  matrix[3]=0;
  matrix[4]=R[1];
  matrix[5]=R[5];
  matrix[6]=R[9];
  matrix[7]=0;
  matrix[8]=R[2];
  matrix[9]=R[6];
  matrix[10]=R[10];
  matrix[11]=0;
  matrix[12]=pos[0];
  matrix[13]=pos[1];
  matrix[14]=pos[2];
  matrix[15]=1;
  glPushMatrix();
  glMultMatrixf (matrix);
}
static void setTransformD (const double pos[3], const double R[12])
{
  GLdouble matrix[16];
  matrix[0]=R[0];
  matrix[1]=R[4];
  matrix[2]=R[8];
  matrix[3]=0;
  matrix[4]=R[1];
  matrix[5]=R[5];
  matrix[6]=R[9];
  matrix[7]=0;
  matrix[8]=R[2];
  matrix[9]=R[6];
  matrix[10]=R[10];
  matrix[11]=0;
  matrix[12]=pos[0];
  matrix[13]=pos[1];
  matrix[14]=pos[2];
  matrix[15]=1;
  glPushMatrix();
  glMultMatrixd (matrix);
}


// set shadow projection transform

static void setShadowTransform()
{
  GLfloat matrix[16];
  for (int i=0; i<16; i++) matrix[i] = 0;
  matrix[0]=1;
  matrix[5]=1;
  matrix[8]=-LIGHTX;
  matrix[9]=-LIGHTY;
  matrix[15]=1;
  glPushMatrix();
  glMultMatrixf (matrix);
}

static void drawConvex (const float *_planes, unsigned int _planecount,
			const float *_points, unsigned int /*_pointcount*/,
			const unsigned int *_polygons)
{
  unsigned int polyindex=0;
  for(unsigned int i=0;i<_planecount;++i)
    {
      unsigned int pointcount=_polygons[polyindex];
      polyindex++;
      glBegin (GL_POLYGON);      
       glNormal3f(_planes[(i*4)+0],
		  _planes[(i*4)+1],
		  _planes[(i*4)+2]);
      for(unsigned int j=0;j 0) {
    float q1[3],q2[3],q3[3];		 // sub-vertices
    for (i=0; i<3; i++) {
      q1[i] = 0.5f*(p1[i]+p2[i]);
      q2[i] = 0.5f*(p2[i]+p3[i]);
      q3[i] = 0.5f*(p3[i]+p1[i]);
    }
    float length1 = (float)(1.0/sqrt(q1[0]*q1[0]+q1[1]*q1[1]+q1[2]*q1[2]));
    float length2 = (float)(1.0/sqrt(q2[0]*q2[0]+q2[1]*q2[1]+q2[2]*q2[2]));
    float length3 = (float)(1.0/sqrt(q3[0]*q3[0]+q3[1]*q3[1]+q3[2]*q3[2]));
    for (i=0; i<3; i++) {
      q1[i] *= length1;
      q2[i] *= length2;
      q3[i] *= length3;
    }
    drawPatch (p1,q1,q3,level-1);
    drawPatch (q1,p2,q2,level-1);
    drawPatch (q1,q2,q3,level-1);
    drawPatch (q3,q2,p3,level-1);
  }
  else {
    glNormal3f (p1[0],p1[1],p1[2]);
    glVertex3f (p1[0],p1[1],p1[2]);
    glNormal3f (p2[0],p2[1],p2[2]);
    glVertex3f (p2[0],p2[1],p2[2]);
    glNormal3f (p3[0],p3[1],p3[2]);
    glVertex3f (p3[0],p3[1],p3[2]);
  }
}


// draw a sphere of radius 1

static int sphere_quality = 1;

static void drawSphere()
{
  // icosahedron data for an icosahedron of radius 1.0
# define ICX 0.525731112119133606f
# define ICZ 0.850650808352039932f
  static GLfloat idata[12][3] = {
    {-ICX, 0, ICZ},
    {ICX, 0, ICZ},
    {-ICX, 0, -ICZ},
    {ICX, 0, -ICZ},
    {0, ICZ, ICX},
    {0, ICZ, -ICX},
    {0, -ICZ, ICX},
    {0, -ICZ, -ICX},
    {ICZ, ICX, 0},
    {-ICZ, ICX, 0},
    {ICZ, -ICX, 0},
    {-ICZ, -ICX, 0}
  };

  static int index[20][3] = {
    {0, 4, 1},	  {0, 9, 4},
    {9, 5, 4},	  {4, 5, 8},
    {4, 8, 1},	  {8, 10, 1},
    {8, 3, 10},   {5, 3, 8},
    {5, 2, 3},	  {2, 7, 3},
    {7, 10, 3},   {7, 6, 10},
    {7, 11, 6},   {11, 0, 6},
    {0, 1, 6},	  {6, 1, 10},
    {9, 0, 11},   {9, 11, 2},
    {9, 2, 5},	  {7, 2, 11},
  };

  static GLuint listnum = 0;
  if (listnum==0) {
    listnum = glGenLists (1);
    glNewList (listnum,GL_COMPILE);
    glBegin (GL_TRIANGLES);
    for (int i=0; i<20; i++) {
      drawPatch (&idata[index[i][2]][0],&idata[index[i][1]][0],
		 &idata[index[i][0]][0],sphere_quality);
    }
    glEnd();
    glEndList();
  }
  glCallList (listnum);
}


static void drawSphereShadow (float px, float py, float pz, float radius)
{
  // calculate shadow constants based on light vector
  static int init=0;
  static float len2,len1,scale;
  if (!init) {
    len2 = LIGHTX*LIGHTX + LIGHTY*LIGHTY;
    len1 = 1.0f/(float)sqrt(len2);
    scale = (float) sqrt(len2 + 1);
    init = 1;
  }

  // map sphere center to ground plane based on light vector
  px -= LIGHTX*pz;
  py -= LIGHTY*pz;

  const float kx = 0.96592582628907f;
  const float ky = 0.25881904510252f;
  float x=radius, y=0;

  glBegin (GL_TRIANGLE_FAN);
  for (int i=0; i<24; i++) {
    // for all points on circle, scale to elongated rotated shadow and draw
    float x2 = (LIGHTX*x*scale - LIGHTY*y)*len1 + px;
    float y2 = (LIGHTY*x*scale + LIGHTX*y)*len1 + py;
    glTexCoord2f (x2*ground_scale+ground_ofsx,y2*ground_scale+ground_ofsy);
    glVertex3f (x2,y2,0);

    // rotate [x,y] vector
    float xtmp = kx*x - ky*y;
    y = ky*x + kx*y;
    x = xtmp;
  }
  glEnd();
}


static void drawTriangle (const float *v0, const float *v1, const float *v2, int solid)
{
  float u[3],v[3],normal[3];
  u[0] = v1[0] - v0[0];
  u[1] = v1[1] - v0[1];
  u[2] = v1[2] - v0[2];
  v[0] = v2[0] - v0[0];
  v[1] = v2[1] - v0[1];
  v[2] = v2[2] - v0[2];
  crossProduct3(normal,u,v);
  normalizeVector3 (normal);

  glBegin(solid ? GL_TRIANGLES : GL_LINE_STRIP);
  glNormal3fv (normal);
  glVertex3fv (v0);
  glVertex3fv (v1);
  glVertex3fv (v2);
  glEnd();
}

static void drawTriangleD (const double *v0, const double *v1, const double *v2, int solid)
{
  float u[3],v[3],normal[3];
  u[0] = float( v1[0] - v0[0] );
  u[1] = float( v1[1] - v0[1] );
  u[2] = float( v1[2] - v0[2] );
  v[0] = float( v2[0] - v0[0] );
  v[1] = float( v2[1] - v0[1] );
  v[2] = float( v2[2] - v0[2] );
  crossProduct3(normal,u,v);
  normalizeVector3 (normal);

  glBegin(solid ? GL_TRIANGLES : GL_LINE_STRIP);
  glNormal3fv (normal);
  glVertex3dv (v0);
  glVertex3dv (v1);
  glVertex3dv (v2);
  glEnd();
}


// draw a capped cylinder of length l and radius r, aligned along the x axis

static int capped_cylinder_quality = 3;

static void drawCapsule (float l, float r)
{
  int i,j;
  float tmp,nx,ny,nz,start_nx,start_ny,a,ca,sa;
  // number of sides to the cylinder (divisible by 4):
  const int n = capped_cylinder_quality*4;

  l *= 0.5;
  a = float(M_PI*2.0)/float(n);
  sa = (float) sin(a);
  ca = (float) cos(a);

  // draw cylinder body
  ny=1; nz=0;		  // normal vector = (0,ny,nz)
  glBegin (GL_TRIANGLE_STRIP);
  for (i=0; i<=n; i++) {
    glNormal3d (ny,nz,0);
    glVertex3d (ny*r,nz*r,l);
    glNormal3d (ny,nz,0);
    glVertex3d (ny*r,nz*r,-l);
    // rotate ny,nz
    tmp = ca*ny - sa*nz;
    nz = sa*ny + ca*nz;
    ny = tmp;
  }
  glEnd();

  // draw first cylinder cap
  start_nx = 0;
  start_ny = 1;
  for (j=0; j<(n/4); j++) {
    // get start_n2 = rotated start_n
    float start_nx2 =  ca*start_nx + sa*start_ny;
    float start_ny2 = -sa*start_nx + ca*start_ny;
    // get n=start_n and n2=start_n2
    nx = start_nx; ny = start_ny; nz = 0;
    float nx2 = start_nx2, ny2 = start_ny2, nz2 = 0;
    glBegin (GL_TRIANGLE_STRIP);
    for (i=0; i<=n; i++) {
      glNormal3d (ny2,nz2,nx2);
      glVertex3d (ny2*r,nz2*r,l+nx2*r);
      glNormal3d (ny,nz,nx);
      glVertex3d (ny*r,nz*r,l+nx*r);
      // rotate n,n2
      tmp = ca*ny - sa*nz;
      nz = sa*ny + ca*nz;
      ny = tmp;
      tmp = ca*ny2- sa*nz2;
      nz2 = sa*ny2 + ca*nz2;
      ny2 = tmp;
    }
    glEnd();
    start_nx = start_nx2;
    start_ny = start_ny2;
  }

  // draw second cylinder cap
  start_nx = 0;
  start_ny = 1;
  for (j=0; j<(n/4); j++) {
    // get start_n2 = rotated start_n
    float start_nx2 = ca*start_nx - sa*start_ny;
    float start_ny2 = sa*start_nx + ca*start_ny;
    // get n=start_n and n2=start_n2
    nx = start_nx; ny = start_ny; nz = 0;
    float nx2 = start_nx2, ny2 = start_ny2, nz2 = 0;
    glBegin (GL_TRIANGLE_STRIP);
    for (i=0; i<=n; i++) {
      glNormal3d (ny,nz,nx);
      glVertex3d (ny*r,nz*r,-l+nx*r);
      glNormal3d (ny2,nz2,nx2);
      glVertex3d (ny2*r,nz2*r,-l+nx2*r);
      // rotate n,n2
      tmp = ca*ny - sa*nz;
      nz = sa*ny + ca*nz;
      ny = tmp;
      tmp = ca*ny2- sa*nz2;
      nz2 = sa*ny2 + ca*nz2;
      ny2 = tmp;
    }
    glEnd();
    start_nx = start_nx2;
    start_ny = start_ny2;
  }
}


// draw a cylinder of length l and radius r, aligned along the z axis

static void drawCylinder (float l, float r, float zoffset)
{
  int i;
  float tmp,ny,nz,a,ca,sa;
  const int n = 24;	// number of sides to the cylinder (divisible by 4)

  l *= 0.5;
  a = float(M_PI*2.0)/float(n);
  sa = (float) sin(a);
  ca = (float) cos(a);

  // draw cylinder body
  ny=1; nz=0;		  // normal vector = (0,ny,nz)
  glBegin (GL_TRIANGLE_STRIP);
  for (i=0; i<=n; i++) {
    glNormal3d (ny,nz,0);
    glVertex3d (ny*r,nz*r,l+zoffset);
    glNormal3d (ny,nz,0);
    glVertex3d (ny*r,nz*r,-l+zoffset);
    // rotate ny,nz
    tmp = ca*ny - sa*nz;
    nz = sa*ny + ca*nz;
    ny = tmp;
  }
  glEnd();

  // draw top cap
  glShadeModel (GL_FLAT);
  ny=1; nz=0;		  // normal vector = (0,ny,nz)
  glBegin (GL_TRIANGLE_FAN);
  glNormal3d (0,0,1);
  glVertex3d (0,0,l+zoffset);
  for (i=0; i<=n; i++) {
    if (i==1 || i==n/2+1)
      setColor (color[0]*0.75f,color[1]*0.75f,color[2]*0.75f,color[3]);
    glNormal3d (0,0,1);
    glVertex3d (ny*r,nz*r,l+zoffset);
    if (i==1 || i==n/2+1)
      setColor (color[0],color[1],color[2],color[3]);

    // rotate ny,nz
    tmp = ca*ny - sa*nz;
    nz = sa*ny + ca*nz;
    ny = tmp;
  }
  glEnd();

  // draw bottom cap
  ny=1; nz=0;		  // normal vector = (0,ny,nz)
  glBegin (GL_TRIANGLE_FAN);
  glNormal3d (0,0,-1);
  glVertex3d (0,0,-l+zoffset);
  for (i=0; i<=n; i++) {
    if (i==1 || i==n/2+1)
      setColor (color[0]*0.75f,color[1]*0.75f,color[2]*0.75f,color[3]);
    glNormal3d (0,0,-1);
    glVertex3d (ny*r,nz*r,-l+zoffset);
    if (i==1 || i==n/2+1)
      setColor (color[0],color[1],color[2],color[3]);

    // rotate ny,nz
    tmp = ca*ny + sa*nz;
    nz = -sa*ny + ca*nz;
    ny = tmp;
  }
  glEnd();
}

//***************************************************************************
// motion model

// current camera position and orientation
static float view_xyz[3];	// position x,y,z
static float view_hpr[3];	// heading, pitch, roll (degrees)


// initialize the above variables

static void initMotionModel()
{
  view_xyz[0] = 2;
  view_xyz[1] = 0;
  view_xyz[2] = 1;
  view_hpr[0] = 180;
  view_hpr[1] = 0;
  view_hpr[2] = 0;
}


static void wrapCameraAngles()
{
  for (int i=0; i<3; i++) {
    while (view_hpr[i] > 180) view_hpr[i] -= 360;
    while (view_hpr[i] < -180) view_hpr[i] += 360;
  }
}


// call this to update the current camera position. the bits in `mode' say
// if the left (1), middle (2) or right (4) mouse button is pressed, and
// (deltax,deltay) is the amount by which the mouse pointer has moved.

void dsMotion (int mode, int deltax, int deltay)
{
  float side = 0.01f * float(deltax);
  float fwd = (mode==4) ? (0.01f * float(deltay)) : 0.0f;
  float s = (float) sin (view_hpr[0]*DEG_TO_RAD);
  float c = (float) cos (view_hpr[0]*DEG_TO_RAD);

  if (mode==1) {
    view_hpr[0] += float (deltax) * 0.5f;
    view_hpr[1] += float (deltay) * 0.5f;
  }
  else {
    view_xyz[0] += -s*side + c*fwd;
    view_xyz[1] += c*side + s*fwd;
    if (mode==2 || mode==5) view_xyz[2] += 0.01f * float(deltay);
  }
  wrapCameraAngles();
}

//***************************************************************************
// drawing loop stuff

// the current state:
//    0 = uninitialized
//    1 = dsSimulationLoop() called
//    2 = dsDrawFrame() called
static int current_state = 0;

// textures and shadows
static int use_textures=1;		// 1 if textures to be drawn
static int use_shadows=1;		// 1 if shadows to be drawn
static Texture *sky_texture = 0;
static Texture *ground_texture = 0;
static Texture *wood_texture = 0;
static Texture *checkered_texture = 0;

static Texture *texture[4+1]; // +1 since index 0 is not used



#if !defined(macintosh) || defined(ODE_PLATFORM_OSX)

void dsStartGraphics (int /*width*/, int /*height*/, dsFunctions *fn)
{

  const char *prefix = DEFAULT_PATH_TO_TEXTURES;
  if (fn->version >= 2 && fn->path_to_textures) prefix = fn->path_to_textures;
  char *s = (char*) alloca (strlen(prefix) + 20);

  strcpy (s,prefix);
  strcat (s,"/sky.ppm");
  texture[DS_SKY] = sky_texture = new Texture (s);

  strcpy (s,prefix);
  strcat (s,"/ground.ppm");
  texture[DS_GROUND] = ground_texture = new Texture (s);

  strcpy (s,prefix);
  strcat (s,"/wood.ppm");
  texture[DS_WOOD] = wood_texture = new Texture (s);

  strcpy (s,prefix);
  strcat (s,"/checkered.ppm");
  texture[DS_CHECKERED] = checkered_texture = new Texture (s);
}

#else // macintosh

void dsStartGraphics (int width, int height, dsFunctions *fn)
{

   // All examples build into the same dir
   char *prefix = "::::drawstuff:textures";
   char *s = (char*) alloca (strlen(prefix) + 20);

   strcpy (s,prefix);
   strcat (s,":sky.ppm");
   sky_texture = new Texture (s);

   strcpy (s,prefix);
   strcat (s,":ground.ppm");
   ground_texture = new Texture (s);

   strcpy (s,prefix);
   strcat (s,":wood.ppm");
   wood_texture = new Texture (s);
}

#endif


void dsStopGraphics()
{
  delete sky_texture;
  delete ground_texture;
  delete wood_texture;
  sky_texture = 0;
  ground_texture = 0;
  wood_texture = 0;
}


static void drawSky (float view_xyz[3])
{
  glDisable (GL_LIGHTING);
  if (use_textures) {
    glEnable (GL_TEXTURE_2D);
    sky_texture->bind (0);
  }
  else {
    glDisable (GL_TEXTURE_2D);
    glColor3f (0,0.5,1.0);
  }

  // make sure sky depth is as far back as possible
  glShadeModel (GL_FLAT);
  glEnable (GL_DEPTH_TEST);
  glDepthFunc (GL_LEQUAL);
  glDepthRange (1,1);

  const float ssize = 1000.0f;
  static float offset = 0.0f;

  float x = ssize*sky_scale;
  float z = view_xyz[2] + sky_height;

  glBegin (GL_QUADS);
  glNormal3f (0,0,-1);
  glTexCoord2f (-x+offset,-x+offset);
  glVertex3f (-ssize+view_xyz[0],-ssize+view_xyz[1],z);
  glTexCoord2f (-x+offset,x+offset);
  glVertex3f (-ssize+view_xyz[0],ssize+view_xyz[1],z);
  glTexCoord2f (x+offset,x+offset);
  glVertex3f (ssize+view_xyz[0],ssize+view_xyz[1],z);
  glTexCoord2f (x+offset,-x+offset);
  glVertex3f (ssize+view_xyz[0],-ssize+view_xyz[1],z);
  glEnd();

  offset = offset + 0.002f;
  if (offset > 1) offset -= 1;

  glDepthFunc (GL_LESS);
  glDepthRange (0,1);
}


static void drawGround()
{
  glDisable (GL_LIGHTING);
  glShadeModel (GL_FLAT);
  glEnable (GL_DEPTH_TEST);
  glDepthFunc (GL_LESS);
  // glDepthRange (1,1);

  if (use_textures) {
    glEnable (GL_TEXTURE_2D);
    ground_texture->bind (0);
  }
  else {
    glDisable (GL_TEXTURE_2D);
    glColor3f (GROUND_R,GROUND_G,GROUND_B);
  }

  // ground fog seems to cause problems with TNT2 under windows
  /*
  GLfloat fogColor[4] = {0.5, 0.5, 0.5, 1};
  glEnable (GL_FOG);
  glFogi (GL_FOG_MODE, GL_EXP2);
  glFogfv (GL_FOG_COLOR, fogColor);
  glFogf (GL_FOG_DENSITY, 0.05f);
  glHint (GL_FOG_HINT, GL_NICEST); // GL_DONT_CARE);
  glFogf (GL_FOG_START, 1.0);
  glFogf (GL_FOG_END, 5.0);
  */

  const float gsize = 100.0f;
  const float offset = 0; // -0.001f; ... polygon offsetting doesn't work well

  glBegin (GL_QUADS);
  glNormal3f (0,0,1);
  glTexCoord2f (-gsize*ground_scale + ground_ofsx,
		-gsize*ground_scale + ground_ofsy);
  glVertex3f (-gsize,-gsize,offset);
  glTexCoord2f (gsize*ground_scale + ground_ofsx,
		-gsize*ground_scale + ground_ofsy);
  glVertex3f (gsize,-gsize,offset);
  glTexCoord2f (gsize*ground_scale + ground_ofsx,
		gsize*ground_scale + ground_ofsy);
  glVertex3f (gsize,gsize,offset);
  glTexCoord2f (-gsize*ground_scale + ground_ofsx,
		gsize*ground_scale + ground_ofsy);
  glVertex3f (-gsize,gsize,offset);
  glEnd();

  glDisable (GL_FOG);
}


static void drawPyramidGrid()
{
  // setup stuff
  glEnable (GL_LIGHTING);
  glDisable (GL_TEXTURE_2D);
  glShadeModel (GL_FLAT);
  glEnable (GL_DEPTH_TEST);
  glDepthFunc (GL_LESS);

  // draw the pyramid grid
  for (int i=-1; i<=1; i++) {
    for (int j=-1; j<=1; j++) {
      glPushMatrix();
      glTranslatef ((float)i,(float)j,(float)0);
      if (i==1 && j==0) setColor (1,0,0,1);
      else if (i==0 && j==1) setColor (0,0,1,1);
      else setColor (1,1,0,1);
      const float k = 0.03f;
      glBegin (GL_TRIANGLE_FAN);
      glNormal3f (0,-1,1);
      glVertex3f (0,0,k);
      glVertex3f (-k,-k,0);
      glVertex3f ( k,-k,0);
      glNormal3f (1,0,1);
      glVertex3f ( k, k,0);
      glNormal3f (0,1,1);
      glVertex3f (-k, k,0);
      glNormal3f (-1,0,1);
      glVertex3f (-k,-k,0);
      glEnd();
      glPopMatrix();
    }
  }
}


void dsDrawFrame (int width, int height, dsFunctions *fn, int pause)
{
  if (current_state < 1) dsDebug ("internal error");
  current_state = 2;

  // setup stuff
  glEnable (GL_LIGHTING);
  glEnable (GL_LIGHT0);
  glDisable (GL_TEXTURE_2D);
  glDisable (GL_TEXTURE_GEN_S);
  glDisable (GL_TEXTURE_GEN_T);
  glShadeModel (GL_FLAT);
  glEnable (GL_DEPTH_TEST);
  glDepthFunc (GL_LESS);
  glEnable (GL_CULL_FACE);
  glCullFace (GL_BACK);
  glFrontFace (GL_CCW);

  // setup viewport
  glViewport (0,0,width,height);
  glMatrixMode (GL_PROJECTION);
  glLoadIdentity();
  const float vnear = 0.1f;
  const float vfar = 100.0f;
  const float k = 0.8f;     // view scale, 1 = +/- 45 degrees
  if (width >= height) {
    float k2 = float(height)/float(width);
    glFrustum (-vnear*k,vnear*k,-vnear*k*k2,vnear*k*k2,vnear,vfar);
  }
  else {
    float k2 = float(width)/float(height);
    glFrustum (-vnear*k*k2,vnear*k*k2,-vnear*k,vnear*k,vnear,vfar);
  }

  // setup lights. it makes a difference whether this is done in the
  // GL_PROJECTION matrix mode (lights are scene relative) or the
  // GL_MODELVIEW matrix mode (lights are camera relative, bad!).
  static GLfloat light_ambient[] = { 0.5, 0.5, 0.5, 1.0 };
  static GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
  static GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
  glLightfv (GL_LIGHT0, GL_AMBIENT, light_ambient);
  glLightfv (GL_LIGHT0, GL_DIFFUSE, light_diffuse);
  glLightfv (GL_LIGHT0, GL_SPECULAR, light_specular);
  glColor3f (1.0, 1.0, 1.0);

  // clear the window
  glClearColor (0.5,0.5,0.5,0);
  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  // snapshot camera position (in MS Windows it is changed by the GUI thread)
  float view2_xyz[3];
  float view2_hpr[3];
  memcpy (view2_xyz,view_xyz,sizeof(float)*3);
  memcpy (view2_hpr,view_hpr,sizeof(float)*3);

  // go to GL_MODELVIEW matrix mode and set the camera
  glMatrixMode (GL_MODELVIEW);
  glLoadIdentity();
  setCamera (view2_xyz[0],view2_xyz[1],view2_xyz[2],
	     view2_hpr[0],view2_hpr[1],view2_hpr[2]);

  // set the light position (for some reason we have to do this in model view.
  static GLfloat light_position[] = { LIGHTX, LIGHTY, 1.0, 0.0 };
  glLightfv (GL_LIGHT0, GL_POSITION, light_position);

  // draw the background (ground, sky etc)
  drawSky (view2_xyz);
  drawGround();

  // draw the little markers on the ground
  drawPyramidGrid();

  // leave openGL in a known state - flat shaded white, no textures
  glEnable (GL_LIGHTING);
  glDisable (GL_TEXTURE_2D);
  glShadeModel (GL_FLAT);
  glEnable (GL_DEPTH_TEST);
  glDepthFunc (GL_LESS);
  glColor3f (1,1,1);
  setColor (1,1,1,1);

  // draw the rest of the objects. set drawing state first.
  color[0] = 1;
  color[1] = 1;
  color[2] = 1;
  color[3] = 1;
  tnum = 0;
  if (fn->step) fn->step (pause);
}


int dsGetShadows()
{
  return use_shadows;
}


void dsSetShadows (int a)
{
  use_shadows = (a != 0);
}


int dsGetTextures()
{
  return use_textures;
}


void dsSetTextures (int a)
{
  use_textures = (a != 0);
}

//***************************************************************************
// C interface

// sets lighting and texture modes, sets current color
static void setupDrawingMode()
{
  glEnable (GL_LIGHTING);
  if (tnum) {
    if (use_textures) {
      glEnable (GL_TEXTURE_2D);
      texture[tnum]->bind (1);
      glEnable (GL_TEXTURE_GEN_S);
      glEnable (GL_TEXTURE_GEN_T);
      glTexGeni (GL_S,GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR);
      glTexGeni (GL_T,GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR);
      static GLfloat s_params[4] = {1.0f,1.0f,0.0f,1};
      static GLfloat t_params[4] = {0.817f,-0.817f,0.817f,1};
      glTexGenfv (GL_S,GL_OBJECT_PLANE,s_params);
      glTexGenfv (GL_T,GL_OBJECT_PLANE,t_params);
    }
    else {
      glDisable (GL_TEXTURE_2D);
    }
  }
  else {
    glDisable (GL_TEXTURE_2D);
  }
  setColor (color[0],color[1],color[2],color[3]);

  if (color[3] < 1) {
    glEnable (GL_BLEND);
    glBlendFunc (GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
  }
  else {
    glDisable (GL_BLEND);
  }
}


static void setShadowDrawingMode()
{
  glDisable (GL_LIGHTING);
  if (use_textures) {
    glEnable (GL_TEXTURE_2D);
    ground_texture->bind (1);
    glColor3f (SHADOW_INTENSITY,SHADOW_INTENSITY,SHADOW_INTENSITY);
    glEnable (GL_TEXTURE_2D);
    glEnable (GL_TEXTURE_GEN_S);
    glEnable (GL_TEXTURE_GEN_T);
    glTexGeni (GL_S,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR);
    glTexGeni (GL_T,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR);
    static GLfloat s_params[4] = {ground_scale,0,0,ground_ofsx};
    static GLfloat t_params[4] = {0,ground_scale,0,ground_ofsy};
    glTexGenfv (GL_S,GL_EYE_PLANE,s_params);
    glTexGenfv (GL_T,GL_EYE_PLANE,t_params);
  }
  else {
    glDisable (GL_TEXTURE_2D);
    glColor3f (GROUND_R*SHADOW_INTENSITY,GROUND_G*SHADOW_INTENSITY,
	       GROUND_B*SHADOW_INTENSITY);
  }
  glDepthRange (0,0.9999);
}


extern "C" void dsSimulationLoop (int argc, char **argv,
				  int window_width, int window_height,
				  dsFunctions *fn)
{
  if (current_state != 0) dsError ("dsSimulationLoop() called more than once");
  current_state = 1;

  // look for flags that apply to us
  int initial_pause = 0;
  for (int i=1; ipath_to_textures = argv[i];
  }

  if (fn->version > DS_VERSION)
    dsDebug ("bad version number in dsFunctions structure");

  initMotionModel();
  dsPlatformSimLoop (window_width,window_height,fn,initial_pause);

  current_state = 0;
}


extern "C" void dsSetViewpoint (float xyz[3], float hpr[3])
{
  if (current_state < 1) dsError ("dsSetViewpoint() called before simulation started");
  if (xyz) {
    view_xyz[0] = xyz[0];
    view_xyz[1] = xyz[1];
    view_xyz[2] = xyz[2];
  }
  if (hpr) {
    view_hpr[0] = hpr[0];
    view_hpr[1] = hpr[1];
    view_hpr[2] = hpr[2];
    wrapCameraAngles();
  }
}


extern "C" void dsGetViewpoint (float xyz[3], float hpr[3])
{
  if (current_state < 1) dsError ("dsGetViewpoint() called before simulation started");
  if (xyz) {
    xyz[0] = view_xyz[0];
    xyz[1] = view_xyz[1];
    xyz[2] = view_xyz[2];
  }
  if (hpr) {
    hpr[0] = view_hpr[0];
    hpr[1] = view_hpr[1];
    hpr[2] = view_hpr[2];
  }
}


extern "C" void dsSetTexture (int texture_number)
{
  if (current_state != 2) dsError ("drawing function called outside simulation loop");
  tnum = texture_number;
}


extern "C" void dsSetColor (float red, float green, float blue)
{
  if (current_state != 2) dsError ("drawing function called outside simulation loop");
  color[0] = red;
  color[1] = green;
  color[2] = blue;
  color[3] = 1;
}


extern "C" void dsSetColorAlpha (float red, float green, float blue,
				 float alpha)
{
  if (current_state != 2) dsError ("drawing function called outside simulation loop");
  color[0] = red;
  color[1] = green;
  color[2] = blue;
  color[3] = alpha;
}


extern "C" void dsDrawBox (const float pos[3], const float R[12],
			   const float sides[3])
{
  if (current_state != 2) dsError ("drawing function called outside simulation loop");
  setupDrawingMode();
  glShadeModel (GL_FLAT);
  setTransform (pos,R);
  drawBox (sides);
  glPopMatrix();

  if (use_shadows) {
    setShadowDrawingMode();
    setShadowTransform();
    setTransform (pos,R);
    drawBox (sides);
    glPopMatrix();
    glPopMatrix();
    glDepthRange (0,1);
  }
}

extern "C" void dsDrawConvex (const float pos[3], const float R[12],
			      const float *_planes,unsigned int _planecount,
			      const float *_points, unsigned int _pointcount,
			      const unsigned int *_polygons)
{
  if (current_state != 2) dsError ("drawing function called outside simulation loop");
  setupDrawingMode();
  glShadeModel (GL_FLAT);
  setTransform (pos,R);
  drawConvex(_planes,_planecount,_points,_pointcount,_polygons);
  glPopMatrix();
  if (use_shadows) {
    setShadowDrawingMode();
    setShadowTransform();
    setTransform (pos,R);
    drawConvex(_planes,_planecount,_points,_pointcount,_polygons);
    glPopMatrix();
    glPopMatrix();
    glDepthRange (0,1);
  }
}


extern "C" void dsDrawSphere (const float pos[3], const float R[12],
			      float radius)
{
  if (current_state != 2) dsError ("drawing function called outside simulation loop");
  setupDrawingMode();
  glEnable (GL_NORMALIZE);
  glShadeModel (GL_SMOOTH);
  setTransform (pos,R);
  glScaled (radius,radius,radius);
  drawSphere();
  glPopMatrix();
  glDisable (GL_NORMALIZE);

  // draw shadows
  if (use_shadows) {
    glDisable (GL_LIGHTING);
    if (use_textures) {
      ground_texture->bind (1);
      glEnable (GL_TEXTURE_2D);
      glDisable (GL_TEXTURE_GEN_S);
      glDisable (GL_TEXTURE_GEN_T);
      glColor3f (SHADOW_INTENSITY,SHADOW_INTENSITY,SHADOW_INTENSITY);
    }
    else {
      glDisable (GL_TEXTURE_2D);
      glColor3f (GROUND_R*SHADOW_INTENSITY,GROUND_G*SHADOW_INTENSITY,
		 GROUND_B*SHADOW_INTENSITY);
    }
    glShadeModel (GL_FLAT);
    glDepthRange (0,0.9999);
    drawSphereShadow (pos[0],pos[1],pos[2],radius);
    glDepthRange (0,1);
  }
}


extern "C" void dsDrawTriangle (const float pos[3], const float R[12],
				const float *v0, const float *v1,
				const float *v2, int solid)
{
  if (current_state != 2) dsError ("drawing function called outside simulation loop");
  setupDrawingMode();
  glShadeModel (GL_FLAT);
  setTransform (pos,R);
  drawTriangle (v0, v1, v2, solid);
  glPopMatrix();
}


extern "C" void dsDrawTriangles (const float pos[3], const float R[12],
				const float *v, int n, int solid)
{
  if (current_state != 2) dsError ("drawing function called outside simulation loop");
  setupDrawingMode();
  glShadeModel (GL_FLAT);
  setTransform (pos,R);
  int i;
  for (i = 0; i < n; ++i, v += 9)
      drawTriangle (v, v + 3, v + 6, solid);
  glPopMatrix();
}


extern "C" void dsDrawCylinder (const float pos[3], const float R[12],
				float length, float radius)
{
  if (current_state != 2) dsError ("drawing function called outside simulation loop");
  setupDrawingMode();
  glShadeModel (GL_SMOOTH);
  setTransform (pos,R);
  drawCylinder (length,radius,0);
  glPopMatrix();

  if (use_shadows) {
    setShadowDrawingMode();
    setShadowTransform();
    setTransform (pos,R);
    drawCylinder (length,radius,0);
    glPopMatrix();
    glPopMatrix();
    glDepthRange (0,1);
  }
}


extern "C" void dsDrawCapsule (const float pos[3], const float R[12],
				      float length, float radius)
{
  if (current_state != 2) dsError ("drawing function called outside simulation loop");
  setupDrawingMode();
  glShadeModel (GL_SMOOTH);
  setTransform (pos,R);
  drawCapsule (length,radius);
  glPopMatrix();

  if (use_shadows) {
    setShadowDrawingMode();
    setShadowTransform();
    setTransform (pos,R);
    drawCapsule (length,radius);
    glPopMatrix();
    glPopMatrix();
    glDepthRange (0,1);
  }
}


static void drawLine(const float pos1[3], const float pos2[3])
{
  glDisable (GL_LIGHTING);
  glLineWidth (2);
  glShadeModel (GL_FLAT);
  glBegin (GL_LINES);
  glVertex3f (pos1[0],pos1[1],pos1[2]);
  glVertex3f (pos2[0],pos2[1],pos2[2]);
  glEnd();
}


extern "C" void dsDrawLine (const float pos1[3], const float pos2[3])
{
  setupDrawingMode();
  glColor4f(color[0], color[1], color[2], color[3]);
  drawLine(pos1, pos2);

  if (use_shadows) {
    setShadowDrawingMode();
    setShadowTransform();

    drawLine(pos1, pos2);

    glPopMatrix();
    glDepthRange (0,1);
  }
}


extern "C" void dsDrawBoxD (const double pos[3], const double R[12],
                            const double sides[3])
{
  int i;
  float pos2[3],R2[12],fsides[3];
  for (i=0; i<3; i++) pos2[i]=(float)pos[i];
  for (i=0; i<12; i++) R2[i]=(float)R[i];
  for (i=0; i<3; i++) fsides[i]=(float)sides[i];
  dsDrawBox (pos2,R2,fsides);
}

extern "C" void dsDrawConvexD (const double pos[3], const double R[12],
			       const double *_planes, unsigned int _planecount,
			       const double *_points, unsigned int _pointcount,
			       const unsigned int *_polygons)
{
  if (current_state != 2) dsError ("drawing function called outside simulation loop");
  setupDrawingMode();
  glShadeModel (GL_FLAT);
  setTransformD (pos,R);
  drawConvexD(_planes,_planecount,_points,_pointcount,_polygons);
  glPopMatrix();
  if (use_shadows) {
    setShadowDrawingMode();
    setShadowTransform();
    setTransformD (pos,R);
    drawConvexD(_planes,_planecount,_points,_pointcount,_polygons);
    glPopMatrix();
    glPopMatrix();
    glDepthRange (0,1);
  }
}

void dsDrawSphereD (const double pos[3], const double R[12], float radius)
{
  int i;
  float pos2[3],R2[12];
  for (i=0; i<3; i++) pos2[i]=(float)pos[i];
  for (i=0; i<12; i++) R2[i]=(float)R[i];
  dsDrawSphere (pos2,R2,radius);
}


void dsDrawTriangleD (const double pos[3], const double R[12],
				 const double *v0, const double *v1,
				 const double *v2, int solid)
{
  int i;
  float pos2[3],R2[12];
  for (i=0; i<3; i++) pos2[i]=(float)pos[i];
  for (i=0; i<12; i++) R2[i]=(float)R[i];

  setupDrawingMode();
  glShadeModel (GL_FLAT);
  setTransform (pos2,R2);
  drawTriangleD (v0, v1, v2, solid);
  glPopMatrix();
}


extern "C" void dsDrawTrianglesD (const double pos[3], const double R[12],
				const double *v, int n, int solid)
{
  int i;
  float pos2[3],R2[12];
  for (i=0; i<3; i++) pos2[i]=(float)pos[i];
  for (i=0; i<12; i++) R2[i]=(float)R[i];

  if (current_state != 2) dsError ("drawing function called outside simulation loop");
  setupDrawingMode();
  glShadeModel (GL_FLAT);
  setTransform (pos2,R2);
  for (i = 0; i < n; ++i, v += 9)
      drawTriangleD (v, v + 3, v + 6, solid);
  glPopMatrix();
}


void dsDrawCylinderD (const double pos[3], const double R[12],
		      float length, float radius)
{
  int i;
  float pos2[3],R2[12];
  for (i=0; i<3; i++) pos2[i]=(float)pos[i];
  for (i=0; i<12; i++) R2[i]=(float)R[i];
  dsDrawCylinder (pos2,R2,length,radius);
}


void dsDrawCapsuleD (const double pos[3], const double R[12],
			    float length, float radius)
{
  int i;
  float pos2[3],R2[12];
  for (i=0; i<3; i++) pos2[i]=(float)pos[i];
  for (i=0; i<12; i++) R2[i]=(float)R[i];
  dsDrawCapsule (pos2,R2,length,radius);
}


void dsDrawLineD (const double _pos1[3], const double _pos2[3])
{
  int i;
  float pos1[3],pos2[3];
  for (i=0; i<3; i++) pos1[i]=(float)_pos1[i];
  for (i=0; i<3; i++) pos2[i]=(float)_pos2[i];
  dsDrawLine (pos1,pos2);
}


void dsSetSphereQuality (int n)
{
  sphere_quality = n;
}


void dsSetCapsuleQuality (int n)
{
  capped_cylinder_quality = n;
}

void dsSetDrawMode(int mode)
{
  switch(mode)
    {
    case DS_POLYFILL:
      glPolygonMode(GL_FRONT,GL_FILL);
      break;
    case DS_WIREFRAME:
      glPolygonMode(GL_FRONT,GL_LINE);
      break;
    }
}
ode-0.16/drawstuff/src/Makefile.am0000664000175200017520000000123713403272463013775 00000000000000# Drawstuff is meant as an aid for testing and not as a full
# rendering library.

noinst_LTLIBRARIES = libdrawstuff.la
libdrawstuff_la_SOURCES = drawstuff.cpp internal.h
AM_CPPFLAGS = -I$(top_srcdir)/include \
        -I$(top_builddir)/include \
        -I$(top_srcdir)/ode/src \
        -DDEFAULT_PATH_TO_TEXTURES='"$(top_srcdir)/drawstuff/textures/"' \
        $(X11_CFLAGS)

if WIN32
libdrawstuff_la_SOURCES+= windows.cpp resource.h resources.rc
libdrawstuff_la_LIBADD = -lwinmm -lgdi32
libdrawstuff_la_LDFLAGS = -no-undefined
endif

if X11
libdrawstuff_la_SOURCES+= x11.cpp
libdrawstuff_la_LIBADD = $(X11_LIBS)
endif

if OSX
libdrawstuff_la_SOURCES+= osx.cpp
endif

ode-0.16/drawstuff/src/internal.h0000664000175200017520000000424713403272463013732 00000000000000/*************************************************************************
 *                                                                       *
 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
 * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
 *                                                                       *
 * This library is free software; you can redistribute it and/or         *
 * modify it under the terms of EITHER:                                  *
 *   (1) The GNU Lesser General Public License as published by the Free  *
 *       Software Foundation; either version 2.1 of the License, or (at  *
 *       your option) any later version. The text of the GNU Lesser      *
 *       General Public License is included with this library in the     *
 *       file LICENSE.TXT.                                               *
 *   (2) The BSD-style license that is included with this library in     *
 *       the file LICENSE-BSD.TXT.                                       *
 *                                                                       *
 * This library is distributed in the hope that it will be useful,       *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
 * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
 *                                                                       *
 *************************************************************************/

/* functions supplied and used by the platform specific code */

#ifndef __DS_INTERNAL_H
#define __DS_INTERNAL_H

#include "drawstuff/drawstuff.h"


// supplied by platform specific code

void dsPlatformSimLoop (int window_width, int window_height,
			dsFunctions *fn, int initial_pause);


// used by platform specific code

void dsStartGraphics (int width, int height, dsFunctions *fn);
void dsDrawFrame (int width, int height, dsFunctions *fn, int pause);
void dsStopGraphics();
void dsMotion (int mode, int deltax, int deltay);

int dsGetShadows();
void dsSetShadows (int a);

int dsGetTextures();
void dsSetTextures (int a);

#endif
ode-0.16/drawstuff/src/osx.cpp0000664000175200017520000002412313403272463013255 00000000000000/*************************************************************************
 *                                                                       *
 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
 * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
 *                                                                       *
 * This library is free software; you can redistribute it and/or         *
 * modify it under the terms of EITHER:                                  *
 *   (1) The GNU Lesser General Public License as published by the Free  *
 *       Software Foundation; either version 2.1 of the License, or (at  *
 *       your option) any later version. The text of the GNU Lesser      *
 *       General Public License is included with this library in the     *
 *       file LICENSE.TXT.                                               *
 *   (2) The BSD-style license that is included with this library in     *
 *       the file LICENSE-BSD.TXT.                                       *
 *                                                                       *
 * This library is distributed in the hope that it will be useful,       *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
 * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
 *                                                                       *
 *************************************************************************/

// Platform-specific code for Mac OS X using Carbon+AGL
//
// Created using x11.cpp and the window-initialization -routines from GLFW
// as reference.
// Not thoroughly tested and is certain to contain deficiencies and bugs

#include 
#include 
#include 
#include 
#include "config.h"
#include "common.h"

#ifdef HAVE_SYS_TIME_H
#include 
#endif

#include 
#include 
#include "internal.h"

#include 
#include 

// Global variables

static bool paused = false;			// 1 if in `pause' mode
static bool singlestep = false;		// 1 if single step key pressed
static bool writeframes = false;	// 1 if frame files to be written

static int					   	windowWidth = -1;
static int					   	windowHeight = -1;
static int 						mouseButtonMode = 0;	
static bool						mouseWithOption = false;	// Set if dragging the mouse with alt pressed
static bool						mouseWithControl = false;	// Set if dragging the mouse with ctrl pressed

static dsFunctions*			   	functions = NULL;
static int                   	windowReference;
static int                      frame = 1;
static int                      prev_x = 0;
static int                      prev_y = 0;

//***************************************************************************
// error handling for unix

static void printMessage (const char *msg1, const char *msg2, va_list ap)
{
  fflush (stderr);
  fflush (stdout);
  fprintf (stderr,"\n%s: ",msg1);
  vfprintf (stderr,msg2,ap);
  fprintf (stderr,"\n");
  fflush (stderr);
}

extern "C" void dsError (const char *msg, ...)
{
  va_list ap;
  va_start (ap,msg);
  printMessage ("Error",msg,ap);
  va_end (ap);
  exit (1);
}


extern "C" void dsDebug (const char *msg, ...)
{
  va_list ap;
  va_start (ap,msg);
  printMessage ("INTERNAL ERROR",msg,ap);
  va_end (ap);
  // *((char *)0) = 0;	 ... commit SEGVicide ?
  abort();
}

extern "C" void dsPrint (const char *msg, ...)
{
  va_list ap;
  va_start (ap,msg);
  vprintf (msg,ap);
  va_end (ap);
}

static void captureFrame( int num ){

  	fprintf( stderr,"\rcapturing frame %04d", num );
	unsigned char buffer[windowWidth*windowHeight][3];
	glReadPixels( 0, 0, windowWidth, windowHeight, GL_RGB, GL_UNSIGNED_BYTE, &buffer );
	char s[100];
	sprintf (s,"frame%04d.ppm",num);
	FILE *f = fopen (s,"wb");
	if( !f ){
		dsError( "can't open \"%s\" for writing", s );
	}
	fprintf( f,"P6\n%d %d\n255\n", windowWidth, windowHeight );
	for( int y=windowHeight-1; y>-1; y-- ){
		fwrite( buffer[y*windowWidth], 3*windowWidth, 1, f );
	}
	fclose (f);	
}

extern "C" void dsStop()
{
}

extern "C" double dsElapsedTime()
{
#if HAVE_GETTIMEOFDAY
  static double prev=0.0;
  timeval tv ;

  gettimeofday(&tv, 0);
  double curr = tv.tv_sec + (double) tv.tv_usec / 1000000.0 ;
  if (!prev)
    prev=curr;
  double retval = curr-prev;
  prev=curr;
  if (retval>1.0) retval=1.0;
  if (retval= 'a' && key <= 'z')
        uppercase = key - ('a' - 'A');
    else
        uppercase = key;
    
    int modifierMask = osxGetModifierMask();    
    if (modifierMask == 0)
    {
        if( key >= ' ' && key <= 126 && functions -> command )
            functions -> command( key );
    }
    else if (modifierMask & GLUT_ACTIVE_CTRL)
    {
        // ctrl+key was pressed
        uppercase += 'A' - 1;
        switch(uppercase ){
            case 'T':
                dsSetTextures( !dsGetTextures() );
                break;
            case 'S':
                dsSetShadows( !dsGetShadows() );
                break;
            case 'X':
                exit(0);
                break;
            case 'P':
                paused = !paused;
                singlestep = false;
                break;
            case 'O':
                if( paused ){
                    singlestep = true;
                }
                break;
            case 'V': {
                float xyz[3],hpr[3];
                dsGetViewpoint( xyz,hpr );
                printf( "Viewpoint = (%.4f,%.4f,%.4f,%.4f,%.4f,%.4f)\n", xyz[0], xyz[1], xyz[2], hpr[0], hpr[1], hpr[2] );
                break;
            }
            case 'W':						
                writeframes = !writeframes;
                if( writeframes ){
                    printf( "Now writing frames to PPM files\n" );
                }						 
                break;
        }
    }
}

void osxMouseEventHandler(int button, int state, int x, int y)
{
    prev_x = x;
    prev_y = y;
	bool buttonDown = false;
    switch( state ){
        case GLUT_DOWN:
			buttonDown = true;
        case GLUT_UP:
            if( button == GLUT_LEFT_BUTTON ){
                int modifierMask = osxGetModifierMask();
                if( modifierMask & GLUT_ACTIVE_CTRL ){
                    // Ctrl+button == right
                    button = GLUT_RIGHT_BUTTON;
                    mouseWithControl = true;
                }	
                else if( modifierMask & GLUT_ACTIVE_ALT ){
                    // Alt+button == left+right
                    mouseButtonMode = 5;
                    mouseWithOption = true;
                    return;
                }
            }
            if( buttonDown ){
                if( button == GLUT_LEFT_BUTTON ) mouseButtonMode |= 1;		// Left
                if( button == GLUT_MIDDLE_BUTTON ) mouseButtonMode |= 2;	// Middle				
                if( button == GLUT_RIGHT_BUTTON ) mouseButtonMode |= 4;	    // Right
            }
            else{
                if( button == GLUT_LEFT_BUTTON ) mouseButtonMode &= (~1);	// Left
                if( button == GLUT_MIDDLE_BUTTON ) mouseButtonMode &= (~2);	// Middle									
                if( button == GLUT_RIGHT_BUTTON ) mouseButtonMode &= (~4);  // Right
            }		
            return;
    }
}

void osxMotionEventHandler(int x, int y)
{
    dsMotion( mouseButtonMode, x - prev_x, y - prev_y );
    prev_x = x;
    prev_y = y;
}

void osxWindowReshapeEventHandler(int width, int height)
{
    windowWidth = width;
    windowHeight = height;
}

static void osxCreateMainWindow( int width, int height )
{
    int argc = 1;
    char* argv[2];
    argv[0] = (char*)"";
    argv[1] = NULL;
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
	glutInitWindowSize(width, height);

    windowReference = glutCreateWindow("ODE - Drawstuff");
	windowWidth = width;
	windowHeight = height;
}

void osxRedisplayEventHandler()
{
    dsDrawFrame( windowWidth, windowHeight, functions, paused && !singlestep );
    singlestep = false;
    glutSwapBuffers();
    
    // capture frames if necessary
    if( !paused && writeframes ){
        captureFrame( frame );
        frame++;
    }
}

void osxTimerEventHandler(int);

void osxInstallTimerHandler()
{
    glutTimerFunc(1000/60, osxTimerEventHandler, 0);
}

void osxTimerEventHandler(int)
{
    glutPostRedisplay();
    osxInstallTimerHandler();
}

int  osxInstallEventHandlers()
{
    glutKeyboardFunc(osxKeyEventHandler);
    glutMouseFunc(osxMouseEventHandler);
    glutMotionFunc(osxMotionEventHandler);
    glutDisplayFunc(osxRedisplayEventHandler);
    glutReshapeFunc(osxWindowReshapeEventHandler);
    osxInstallTimerHandler();    
    return GL_TRUE;
}

extern void dsPlatformSimLoop( int givenWindowWidth, int givenWindowHeight, dsFunctions *fn, int givenPause ){
	
	functions = fn;
	
	paused = givenPause;
	
	osxCreateMainWindow( givenWindowWidth, givenWindowHeight );
	osxInstallEventHandlers();
	
	dsStartGraphics( windowWidth, windowHeight, fn );
	
	static bool firsttime=true;
	if( firsttime )
	{
		fprintf
		(
		 stderr,
		 "\n"
		 "Simulation test environment v%d.%02d\n"
		 "   Ctrl-P : pause / unpause (or say `-pause' on command line).\n"
		 "   Ctrl-O : single step when paused.\n"
		 "   Ctrl-T : toggle textures (or say `-notex' on command line).\n"
		 "   Ctrl-S : toggle shadows (or say `-noshadow' on command line).\n"
		 "   Ctrl-V : print current viewpoint coordinates (x,y,z,h,p,r).\n"
		 "   Ctrl-W : write frames to ppm files: frame/frameNNN.ppm\n"
		 "   Ctrl-X : exit.\n"
		 "\n"
		 "Change the camera position by clicking + dragging in the window.\n"
		 "   Left button - pan and tilt.\n"
		 "   Right button (or Ctrl + button) - forward and sideways.\n"
		 "   Left + Right button (or middle button, or Alt + button) - sideways and up.\n"
		 "\n",DS_VERSION >> 8,DS_VERSION & 0xff
		 );
		firsttime = false;
	}
	
	if( fn -> start ) fn->start();
	
    glutMainLoop();
}
ode-0.16/drawstuff/src/windows.cpp0000664000175200017520000003662613403272463014151 00000000000000/*************************************************************************
 *                                                                       *
 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
 * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
 *                                                                       *
 * This library is free software; you can redistribute it and/or         *
 * modify it under the terms of EITHER:                                  *
 *   (1) The GNU Lesser General Public License as published by the Free  *
 *       Software Foundation; either version 2.1 of the License, or (at  *
 *       your option) any later version. The text of the GNU Lesser      *
 *       General Public License is included with this library in the     *
 *       file LICENSE.TXT.                                               *
 *   (2) The BSD-style license that is included with this library in     *
 *       the file LICENSE-BSD.TXT.                                       *
 *                                                                       *
 * This library is distributed in the hope that it will be useful,       *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
 * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
 *                                                                       *
 *************************************************************************/

#if defined(WIN32) || defined(__CYGWIN__)// this prevents warnings when dependencies built
#include 
#endif
#include 
#include 
#include 

#include "config.h"
#include "common.h"
#include "resource.h"
#include "internal.h"

//***************************************************************************
// application globals

static HINSTANCE ghInstance = 0;
static int gnCmdShow = 0;
static HACCEL accelerators = 0;
static HWND main_window = 0;

//***************************************************************************
// error and message handling

static void errorBox (const char *title, const char *msg, va_list ap)
{
  char s[1000];
  vsprintf (s,msg,ap);
  MessageBox (0,s,title,MB_OK | MB_APPLMODAL | MB_ICONEXCLAMATION);
}


static void dsWarning (const char *msg, ...)
{
  va_list ap;
  va_start (ap,msg);
  errorBox ("Warning",msg,ap);
  va_end (ap);
}


extern "C" void dsError (const char *msg, ...)
{
  va_list ap;
  va_start (ap,msg);
  errorBox ("Error",msg,ap);
  va_end (ap);
  exit (1);
}


extern "C" void dsDebug (const char *msg, ...)
{
  va_list ap;
  va_start (ap,msg);
  errorBox ("INTERNAL ERROR",msg,ap);
  va_end (ap);
  // *((char *)0) = 0;	 ... commit SEGVicide ?
  abort();
  exit (1);	  // should never get here, but just in case...
}


extern "C" void dsPrint (const char *msg, ...)
{
  va_list ap;
  va_start (ap,msg);
  vprintf (msg,ap);
  va_end (ap);
}

//***************************************************************************
// rendering thread

// globals used to communicate with rendering thread

static volatile int renderer_run = 1;
static volatile int renderer_pause = 0;	  // 0=run, 1=pause
static volatile int renderer_ss = 0;	  // single step command
static volatile int renderer_width = 1;
static volatile int renderer_height = 1;
static dsFunctions *renderer_fn = 0;
static volatile HDC renderer_dc = 0;
static volatile int keybuffer[16];	  // fifo ring buffer for keypresses
static volatile int keybuffer_head = 0;	  // index of next key to put in (modified by GUI)
static volatile int keybuffer_tail = 0;	  // index of next key to take out (modified by renderer)


static void setupRendererGlobals()
{
  renderer_run = 1;
  renderer_pause = 0;
  renderer_ss = 0;
  renderer_width = 1;
  renderer_height = 1;
  renderer_fn = 0;
  renderer_dc = 0;
  keybuffer[16];
  keybuffer_head = 0;
  keybuffer_tail = 0;
}


static unsigned CALLBACK renderingThread (LPVOID lpParam)
{
  // create openGL context and make it current
  HGLRC glc = wglCreateContext (renderer_dc);
  if (glc==NULL) dsError ("could not create OpenGL context");
  if (wglMakeCurrent (renderer_dc,glc) != TRUE)
    dsError ("could not make OpenGL context current");

  // test openGL capabilities
  int maxtsize=0;
  glGetIntegerv (GL_MAX_TEXTURE_SIZE,&maxtsize);
  if (maxtsize < 128) dsWarning ("max texture size too small (%dx%d)",
				 maxtsize,maxtsize);

  dsStartGraphics (renderer_width,renderer_height,renderer_fn);
  if (renderer_fn->start) renderer_fn->start();

  while (renderer_run) {
    // need to make local copy of renderer_ss to help prevent races
    int ss = renderer_ss;
    dsDrawFrame (renderer_width,renderer_height,renderer_fn,
		 renderer_pause && !ss);
    if (ss) renderer_ss = 0;

    // read keys out of ring buffer and feed them to the command function
    while (keybuffer_head != keybuffer_tail) {
      if (renderer_fn->command) renderer_fn->command (keybuffer[keybuffer_tail]);
      keybuffer_tail = (keybuffer_tail+1) & 15;
    }

    // swap buffers
    SwapBuffers (renderer_dc);
  }

  if (renderer_fn->stop) renderer_fn->stop();
  dsStopGraphics();

  // delete openGL context
  wglMakeCurrent (NULL,NULL);
  wglDeleteContext (glc);

  return 123;	    // magic value used to test for thread termination
}

//***************************************************************************
// window handling

// callback function for "about" dialog box

static LRESULT CALLBACK AboutDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam,
				      LPARAM lParam)
{
  switch (uMsg) {
  case WM_INITDIALOG:
    return TRUE;
  case WM_COMMAND:
    switch (wParam) {
    case IDOK:
      EndDialog (hDlg, TRUE);
      return TRUE;
    }
    break;
  }
  return FALSE;
}


// callback function for the main window

static LRESULT CALLBACK mainWndProc (HWND hWnd, UINT msg, WPARAM wParam,
				     LPARAM lParam)
{
  static int button=0,lastx=0,lasty=0;
  int ctrl = int(wParam & MK_CONTROL);

  switch (msg) {
  case WM_LBUTTONDOWN:
  case WM_MBUTTONDOWN:
  case WM_RBUTTONDOWN:
    if (msg==WM_LBUTTONDOWN) button |= 1;
    else if (msg==WM_MBUTTONDOWN) button |= 2;
    else button |= 4;
    lastx = SHORT(LOWORD(lParam));
    lasty = SHORT(HIWORD(lParam));
    SetCapture (hWnd);
    break;

  case WM_LBUTTONUP:
  case WM_MBUTTONUP:
  case WM_RBUTTONUP:
    if (msg==WM_LBUTTONUP) button &= ~1;
    else if (msg==WM_MBUTTONUP) button &= ~2;
    else button &= ~4;
    if (button==0) ReleaseCapture();
    break;

  case WM_MOUSEMOVE: {
    int x = SHORT(LOWORD(lParam));
    int y = SHORT(HIWORD(lParam));
    if (button) dsMotion (button,x-lastx,y-lasty);
    lastx = x;
    lasty = y;
    break;
  }

  case WM_CHAR: {
    if (wParam >= ' ' && wParam <= 126) {
      int nexth = (keybuffer_head+1) & 15;
      if (nexth != keybuffer_tail) {
	keybuffer[keybuffer_head] = int(wParam);
	keybuffer_head = nexth;
      }
    }
    break;
  }

  case WM_SIZE:
    // lParam will contain the size of the *client* area!
    renderer_width = LOWORD(lParam);
    renderer_height = HIWORD(lParam);
    break;

  case WM_COMMAND:
    switch (wParam & 0xffff) {
    case IDM_ABOUT:
      DialogBox (ghInstance,MAKEINTRESOURCE(IDD_ABOUT),hWnd,
	(DLGPROC) AboutDlgProc);
      break;
    case IDM_PAUSE: {
      renderer_pause ^= 1;
      CheckMenuItem (GetMenu(hWnd),IDM_PAUSE,
		     renderer_pause ? MF_CHECKED : MF_UNCHECKED);
      if (renderer_pause) renderer_ss = 0;
      break;
    }
    case IDM_SINGLE_STEP: {
		if (renderer_pause)
			renderer_ss = 1;
		else
			SendMessage( hWnd, WM_COMMAND, IDM_PAUSE, 0 );
      break;
    }
    case IDM_PERF_MONITOR: {
      dsWarning ("Performance monitor not yet implemented.");
      break;
    }
    case IDM_TEXTURES: {
      static int tex = 1;
      tex ^= 1;
      CheckMenuItem (GetMenu(hWnd),IDM_TEXTURES,
		     tex ? MF_CHECKED : MF_UNCHECKED);
      dsSetTextures (tex);
      break;
    }
    case IDM_SHADOWS: {
      static int shadows = 1;
      shadows ^= 1;
      CheckMenuItem (GetMenu(hWnd),IDM_SHADOWS,
		     shadows ? MF_CHECKED : MF_UNCHECKED);
      dsSetShadows (shadows);
      break;
    }
    case IDM_SAVE_SETTINGS: {
      dsWarning ("\"Save Settings\" not yet implemented.");
      break;
    }
    case IDM_EXIT:
      PostQuitMessage (0);
      break;
    }
    break;

  case WM_CLOSE:    
    PostQuitMessage (0);
    break;
    
  default:
    return (DefWindowProc (hWnd, msg, wParam, lParam));
  }

  return 0;
}


// this comes from an MSDN example. believe it or not, this is the recommended
// way to get the console window handle.

static HWND GetConsoleHwnd()
{
  // the console window title to a "unique" value, then find the window
  // that has this title.
  char title[1024];
  wsprintf (title,"DrawStuff:%d/%d",GetTickCount(),GetCurrentProcessId());
  SetConsoleTitle (title);
  Sleep(40);			// ensure window title has been updated
  return FindWindow (NULL,title);
}


static void drawStuffStartup()
{
  static int startup_called = 0;
  if (startup_called) return;
  startup_called = 1;
  if (!ghInstance)
    ghInstance = GetModuleHandleA (NULL);
  gnCmdShow = SW_SHOWNORMAL;		// @@@ fix this later

  // redirect standard I/O to a new console (except on cygwin and mingw)
#if !defined(__CYGWIN__) && !defined(__MINGW32__)
  FreeConsole();
  if (AllocConsole()==0) dsError ("AllocConsole() failed");
  if (freopen ("CONIN$","rt",stdin)==0) dsError ("could not open stdin");
  if (freopen ("CONOUT$","wt",stdout)==0) dsError ("could not open stdout");
  if (freopen ("CONOUT$","wt",stderr)==0) dsError ("could not open stderr");
  BringWindowToTop (GetConsoleHwnd());
  SetConsoleTitle ("DrawStuff Messages");
#endif

  // register the window class
  WNDCLASS wc;
  wc.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW;
  wc.lpfnWndProc = mainWndProc;
  wc.cbClsExtra = 0;
  wc.cbWndExtra = 0;
  wc.hInstance = ghInstance;
  wc.hIcon = LoadIcon (NULL,IDI_APPLICATION);
  wc.hCursor = LoadCursor (NULL,IDC_ARROW);
  wc.hbrBackground = (HBRUSH) (COLOR_WINDOW+1);
  wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
  wc.lpszClassName = "SimAppClass";
  if (RegisterClass (&wc)==0) dsError ("could not register window class");

  // load accelerators
  accelerators = LoadAccelerators (ghInstance,
				   MAKEINTRESOURCE(IDR_ACCELERATOR1));
  if (accelerators==NULL) dsError ("could not load accelerators");
}


void dsPlatformSimLoop (int window_width, int window_height,
			dsFunctions *fn, int initial_pause)
{
  drawStuffStartup();
  setupRendererGlobals();
  renderer_pause = initial_pause;

  // create window - but first get window size for desired size of client area.
  // if this adjustment isn't made then the openGL area will be shifted into
  // the nonclient area and determining the frame buffer coordinate from the
  // client area coordinate will be hard.
  RECT winrect;
  winrect.left = 50;
  winrect.top = 80;
  winrect.right = winrect.left + window_width;
  winrect.bottom = winrect.top + window_height;
  DWORD style = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
  AdjustWindowRect (&winrect,style,1);
  char title[100];
  sprintf (title,"Simulation test environment v%d.%02d",
	   DS_VERSION >> 8,DS_VERSION & 0xff);
  main_window = CreateWindow ("SimAppClass",title,style,
    winrect.left,winrect.top,winrect.right-winrect.left,winrect.bottom-winrect.top,
    NULL,NULL,ghInstance,NULL);
  if (main_window==NULL) dsError ("could not create main window");
  ShowWindow (main_window, gnCmdShow);

  HDC dc = GetDC (main_window);			// get DC for this window
  if (dc==NULL) dsError ("could not get window DC");

  // set pixel format for DC

  PIXELFORMATDESCRIPTOR pfd = {
    sizeof(PIXELFORMATDESCRIPTOR),   // size of this pfd
    1,				     // version number
    PFD_DRAW_TO_WINDOW |	     // support window
    PFD_SUPPORT_OPENGL |	     // support OpenGL
    PFD_DOUBLEBUFFER,		     // double buffered
    PFD_TYPE_RGBA,		     // RGBA type
    24, 			     // 24-bit color depth
    0, 0, 0, 0, 0, 0,		     // color bits ignored
    0,				     // no alpha buffer
    0,				     // shift bit ignored
    0,				     // no accumulation buffer
    0, 0, 0, 0, 		     // accum bits ignored
    32, 			     // 32-bit z-buffer
    0,				     // no stencil buffer
    0,				     // no auxiliary buffer
    PFD_MAIN_PLANE,		     // main layer
    0,				     // reserved
    0, 0, 0			     // layer masks ignored
  };
  // get the best available match of pixel format for the device context
  int iPixelFormat = ChoosePixelFormat (dc,&pfd);
  if (iPixelFormat==0)
    dsError ("could not find a good OpenGL pixel format");
  // set the pixel format of the device context
  if (SetPixelFormat (dc,iPixelFormat,&pfd)==FALSE)
    dsError ("could not set DC pixel format for OpenGL");

  // **********
  // start the rendering thread

  // set renderer globals
  renderer_dc = dc;
  renderer_width = window_width;
  renderer_height = window_height;
  renderer_fn = fn;

  unsigned threadId;
  HANDLE hThread;

  hThread = (HANDLE)_beginthreadex(
	NULL,			     // no security attributes
	0,			     // use default stack size
	&renderingThread,	     // thread function
	NULL,		     // argument to thread function
	0,			     // use default creation flags
	&threadId);		     // returns the thread identifier

  if (hThread==NULL) dsError ("Could not create rendering thread");

  // **********
  // start GUI message processing

  MSG msg;
  while (GetMessage (&msg,main_window,0,0)) {
    if (!TranslateAccelerator (main_window,accelerators,&msg)) {
      TranslateMessage (&msg);
      DispatchMessage (&msg);
    }
  }

  // terminate rendering thread
  renderer_run = 0;
  DWORD ret = WaitForSingleObject (hThread,2000);
  if (ret==WAIT_TIMEOUT) dsWarning ("Could not kill rendering thread (1)");
  DWORD exitcode=0;
  if (!(GetExitCodeThread (hThread,&exitcode) && exitcode == 123))
    dsWarning ("Could not kill rendering thread (2)");
  CloseHandle (hThread);	     // dont need thread handle anymore

  // destroy window
  DestroyWindow (main_window);
}


extern "C" void dsStop()
{
  // just calling PostQuitMessage() here wont work, as this function is
  // typically called from the rendering thread, not the GUI thread.
  // instead we must post the message to the GUI window explicitly.

  if (main_window) PostMessage (main_window,WM_QUIT,0,0);
}


extern "C" double dsElapsedTime()
{
  static double prev=0.0;
  double curr = timeGetTime()/1000.0;
  if (!prev)
    prev=curr;
  double retval = curr-prev;
  prev=curr;
  if (retval>1.0) retval=1.0;
  if (retval
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "config.h"
#include "common.h"

#ifdef HAVE_SYS_TIME_H
#include 
#endif
#ifdef HAVE_UNISTD_H
#include 
#endif

#include 
#include 
#include "internal.h"

//***************************************************************************
// error handling for unix

static void printMessage (const char *msg1, const char *msg2, va_list ap)
{
  fflush (stderr);
  fflush (stdout);
  fprintf (stderr,"\n%s: ",msg1);
  vfprintf (stderr,msg2,ap);
  fprintf (stderr,"\n");
  fflush (stderr);
}


extern "C" void dsError (const char *msg, ...)
{
  va_list ap;
  va_start (ap,msg);
  printMessage ("Error",msg,ap);
  va_end (ap);
  exit (1);
}


extern "C" void dsDebug (const char *msg, ...)
{
  va_list ap;
  va_start (ap,msg);
  printMessage ("INTERNAL ERROR",msg,ap);
  va_end (ap);
  // *((char *)0) = 0;	 ... commit SEGVicide ?
  abort();
}


extern "C" void dsPrint (const char *msg, ...)
{
  va_list ap;
  va_start (ap,msg);
  vprintf (msg,ap);
  va_end (ap);
}

//***************************************************************************
// openGL window

// X11 display info
static Display *display=0;
static int screen=0;
static XVisualInfo *visual=0;		// best visual for openGL
static Colormap colormap=0;		// window's colormap
static Atom wm_protocols_atom = 0;
static Atom wm_delete_window_atom = 0;

// window and openGL
static Window win=0;			// X11 window, 0 if not initialized
static int width=0,height=0;		// window size
static GLXContext glx_context=0;	// openGL rendering context
static int last_key_pressed=0;		// last key pressed in the window
static int run=1;			// 1 if simulation running
static int pausemode=0;			// 1 if in `pause' mode
static int singlestep=0;		// 1 if single step key pressed
static int writeframes=0;		// 1 if frame files to be written


static void createMainWindow (int _width, int _height)
{
  // create X11 display connection
  display = XOpenDisplay (NULL);
  if (!display) dsError ("can not open X11 display");
  screen = DefaultScreen(display);

  // get GL visual
  static int attribListDblBuf[] = {GLX_RGBA, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE,16,
			     GLX_RED_SIZE,4, GLX_GREEN_SIZE,4, GLX_BLUE_SIZE,4, None};
  static int attribList[] = {GLX_RGBA, GLX_DEPTH_SIZE,16,
			     GLX_RED_SIZE,4, GLX_GREEN_SIZE,4, GLX_BLUE_SIZE,4, None};
  visual = glXChooseVisual (display,screen,attribListDblBuf);
  if (!visual) visual = glXChooseVisual (display,screen,attribList);
  if (!visual) dsError ("no good X11 visual found for OpenGL");

  // create colormap
  colormap = XCreateColormap (display,RootWindow(display,screen),
			      visual->visual,AllocNone);

  // initialize variables
  win = 0;
  width = _width;
  height = _height;
  glx_context = 0;
  last_key_pressed = 0;

  if (width < 1 || height < 1) dsDebug (0,"bad window width or height");

  // create the window
  XSetWindowAttributes attributes;
  attributes.background_pixel = BlackPixel(display,screen);
  attributes.colormap = colormap;
  attributes.event_mask = ButtonPressMask | ButtonReleaseMask |
    KeyPressMask | KeyReleaseMask | ButtonMotionMask | PointerMotionHintMask |
    StructureNotifyMask;
  win = XCreateWindow (display,RootWindow(display,screen),50,50,width,height,
		       0,visual->depth, InputOutput,visual->visual,
		       CWBackPixel | CWColormap | CWEventMask,&attributes);

  // associate a GLX context with the window
  glx_context = glXCreateContext (display,visual,0,GL_TRUE);
  if (!glx_context) dsError ("can't make an OpenGL context");

  // set the window title
  XTextProperty window_name;
  window_name.value = (unsigned char *) "Simulation";
  window_name.encoding = XA_STRING;
  window_name.format = 8;
  window_name.nitems = strlen((char *) window_name.value);
  XSetWMName (display,win,&window_name);

  // participate in the window manager 'delete yourself' protocol
  wm_protocols_atom = XInternAtom (display,"WM_PROTOCOLS",False);
  wm_delete_window_atom = XInternAtom (display,"WM_DELETE_WINDOW",False);
  if (XSetWMProtocols (display,win,&wm_delete_window_atom,1)==0)
    dsError ("XSetWMProtocols() call failed");

  // pop up the window
  XMapWindow (display,win);
  XSync (display,win);
}


static void destroyMainWindow()
{
  glXDestroyContext (display,glx_context);
  XDestroyWindow (display,win);
  XSync (display,0);
  XCloseDisplay(display);
  display = 0;
  win = 0;
  glx_context = 0;
}


static void handleEvent (XEvent &event, dsFunctions *fn)
{
  static int mx=0,my=0; 	// mouse position
  static int mode = 0;		// mouse button bits

  switch (event.type) {

  case ButtonPress: {
    if (event.xbutton.button == Button1) mode |= 1;
    if (event.xbutton.button == Button2) mode |= 2;
    if (event.xbutton.button == Button3) mode |= 4;
    mx = event.xbutton.x;
    my = event.xbutton.y;
  }
  return;

  case ButtonRelease: {
    if (event.xbutton.button == Button1) mode &= (~1);
    if (event.xbutton.button == Button2) mode &= (~2);
    if (event.xbutton.button == Button3) mode &= (~4);
    mx = event.xbutton.x;
    my = event.xbutton.x;
  }
  return;

  case MotionNotify: {
    if (event.xmotion.is_hint) {
      Window root,child;
      unsigned int mask;
      XQueryPointer (display,win,&root,&child,&event.xbutton.x_root,
		     &event.xbutton.y_root,&event.xbutton.x,&event.xbutton.y,
		     &mask);
    }
    dsMotion (mode, event.xmotion.x - mx, event.xmotion.y - my);
    mx = event.xmotion.x;
    my = event.xmotion.y;
  }
  return;

  case KeyPress: {
    KeySym key;
    XLookupString (&event.xkey,NULL,0,&key,0);
    if ((event.xkey.state & ControlMask) == 0) {
      if (key >= ' ' && key <= 126 && fn->command) fn->command (key);
    }
    else if (event.xkey.state & ControlMask) {
      switch (key) {
      case 't': case 'T':
	dsSetTextures (dsGetTextures() ^ 1);
	break;
      case 's': case 'S':
	dsSetShadows (dsGetShadows() ^ 1);
	break;
      case 'x': case 'X':
	run = 0;
	break;
      case 'p': case 'P':
	pausemode ^= 1;
	singlestep = 0;
	break;
      case 'o': case 'O':
	if (pausemode) singlestep = 1;
	break;
      case 'v': case 'V': {
	float xyz[3],hpr[3];
	dsGetViewpoint (xyz,hpr);
	printf ("Viewpoint = (%.4f,%.4f,%.4f,%.4f,%.4f,%.4f)\n",
		xyz[0],xyz[1],xyz[2],hpr[0],hpr[1],hpr[2]);
	break;
      }
      case 'w': case 'W':
	writeframes ^= 1;
	if (writeframes) printf ("Now writing frames to PPM files\n");
	break;
      }
    }
    last_key_pressed = key;		// a kludgy place to put this...
  }
  return;

  case KeyRelease: {
    // hmmmm...
  }
  return;

  case ClientMessage:
    if (event.xclient.message_type == wm_protocols_atom &&
	event.xclient.format == 32 &&
	Atom(event.xclient.data.l[0]) == wm_delete_window_atom) {
      run = 0;
      return;
    }
    return;

  case ConfigureNotify:
    width = event.xconfigure.width;
    height = event.xconfigure.height;
    return;
  }
}


// return the index of the highest bit
static int getHighBitIndex (unsigned int x)
{
  int i = 0;
  while (x) {
    i++;
    x >>= 1;
  }
  return i-1;
}


// shift x left by i, where i can be positive or negative
#define SHIFTL(x,i) (((i) >= 0) ? ((x) << (i)) : ((x) >> (-i)))


static void captureFrame (int num)
{
  fprintf (stderr,"capturing frame %04d\n",num);

  char s[100];
  sprintf (s,"frame/frame%04d.ppm",num);
  FILE *f = fopen (s,"wb");
  if (!f) dsError ("can't open \"%s\" for writing",s);
  fprintf (f,"P6\n%d %d\n255\n",width,height);
  XImage *image = XGetImage (display,win,0,0,width,height,~0,ZPixmap);

  int rshift = 7 - getHighBitIndex (image->red_mask);
  int gshift = 7 - getHighBitIndex (image->green_mask);
  int bshift = 7 - getHighBitIndex (image->blue_mask);

  for (int y=0; yred_mask,rshift);
      b[1] = SHIFTL(pixel & image->green_mask,gshift);
      b[2] = SHIFTL(pixel & image->blue_mask,bshift);
      fwrite (b,3,1,f);
    }
  }
  fclose (f);
  XDestroyImage (image);
}

void processDrawFrame(int *frame, dsFunctions *fn)
{
  dsDrawFrame (width,height,fn,pausemode && !singlestep);
  singlestep = 0;

  glFlush();
  glXSwapBuffers (display,win);
  XSync (display,0);

  // capture frames if necessary
  if (pausemode==0 && writeframes) {
    captureFrame (*frame);
    (*frame)++;
  }
}

void microsleep(int usecs)
{
#ifdef HAVE_UNISTD_H
  usleep(usecs);
#endif
}

void dsPlatformSimLoop (int window_width, int window_height, dsFunctions *fn,
			int initial_pause)
{
  pausemode = initial_pause;
  createMainWindow (window_width, window_height);
  glXMakeCurrent (display,win,glx_context);

  dsStartGraphics (window_width,window_height,fn);

  static bool firsttime=true;
  if (firsttime)
  {
    fprintf
    (
      stderr,
      "\n"
      "Simulation test environment v%d.%02d\n"
      "   Ctrl-P : pause / unpause (or say `-pause' on command line).\n"
      "   Ctrl-O : single step when paused.\n"
      "   Ctrl-T : toggle textures (or say `-notex' on command line).\n"
      "   Ctrl-S : toggle shadows (or say `-noshadow' on command line).\n"
      "   Ctrl-V : print current viewpoint coordinates (x,y,z,h,p,r).\n"
      "   Ctrl-W : write frames to ppm files: frame/frameNNN.ppm\n"
      "   Ctrl-X : exit.\n"
      "\n"
      "Change the camera position by clicking + dragging in the window.\n"
      "   Left button - pan and tilt.\n"
      "   Right button - forward and sideways.\n"
      "   Left + Right button (or middle button) - sideways and up.\n"
      "\n",DS_VERSION >> 8,DS_VERSION & 0xff
    );
    firsttime = false;
  }

  if (fn->start) fn->start();

#if HAVE_GETTIMEOFDAY
  timeval tv;
  gettimeofday(&tv, 0);
  double prev = tv.tv_sec + (double) tv.tv_usec / 1000000.0 ;
#endif

  int frame = 1;
  run = 1;
  while (run) {
    // read in and process all pending events for the main window
    XEvent event;
    while (run && XPending (display)) {
      XNextEvent (display,&event);
      handleEvent (event,fn);
    }
    
#if HAVE_GETTIMEOFDAY
    gettimeofday(&tv, 0);
    double curr = tv.tv_sec + (double) tv.tv_usec / 1000000.0 ;
    if (curr-prev >= 1.0/60.0)
    {
      prev = curr;
      processDrawFrame(&frame, fn);
    }
    else
      microsleep(1000);
#else
    processDrawFrame(&frame, fn);
#endif
  };

  if (fn->stop) fn->stop();
  dsStopGraphics();

  destroyMainWindow();
}


extern "C" void dsStop()
{
  run = 0;
}


extern "C" double dsElapsedTime()
{
#if HAVE_GETTIMEOFDAY
  static double prev=0.0;
  timeval tv ;

  gettimeofday(&tv, 0);
  double curr = tv.tv_sec + (double) tv.tv_usec / 1000000.0 ;
  if (!prev)
    prev=curr;
  double retval = curr-prev;
  prev=curr;
  if (retval>1.0) retval=1.0;
  if (retval&2; \
         exit 1;; \
  esac; \
  has_opt=no; \
  sane_makeflags=$$MAKEFLAGS; \
  if $(am__is_gnu_make); then \
    sane_makeflags=$$MFLAGS; \
  else \
    case $$MAKEFLAGS in \
      *\\[\ \	]*) \
        bs=\\; \
        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
    esac; \
  fi; \
  skip_next=no; \
  strip_trailopt () \
  { \
    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
  }; \
  for flg in $$sane_makeflags; do \
    test $$skip_next = yes && { skip_next=no; continue; }; \
    case $$flg in \
      *=*|--*) continue;; \
        -*I) strip_trailopt 'I'; skip_next=yes;; \
      -*I?*) strip_trailopt 'I';; \
        -*O) strip_trailopt 'O'; skip_next=yes;; \
      -*O?*) strip_trailopt 'O';; \
        -*l) strip_trailopt 'l'; skip_next=yes;; \
      -*l?*) strip_trailopt 'l';; \
      -[dEDm]) skip_next=yes;; \
      -[JT]) skip_next=yes;; \
    esac; \
    case $$flg in \
      *$$target_option*) has_opt=yes; break;; \
    esac; \
  done; \
  test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
@WIN32_TRUE@am__append_1 = windows.cpp resource.h resources.rc
@X11_TRUE@am__append_2 = x11.cpp
@OSX_TRUE@am__append_3 = osx.cpp
subdir = drawstuff/src
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
	$(top_srcdir)/m4/pkg.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
	$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/ode/src/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
LTLIBRARIES = $(noinst_LTLIBRARIES)
am__DEPENDENCIES_1 =
@X11_TRUE@libdrawstuff_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__libdrawstuff_la_SOURCES_DIST = drawstuff.cpp internal.h \
	windows.cpp resource.h resources.rc x11.cpp osx.cpp
@WIN32_TRUE@am__objects_1 = windows.lo
@X11_TRUE@am__objects_2 = x11.lo
@OSX_TRUE@am__objects_3 = osx.lo
am_libdrawstuff_la_OBJECTS = drawstuff.lo $(am__objects_1) \
	$(am__objects_2) $(am__objects_3)
libdrawstuff_la_OBJECTS = $(am_libdrawstuff_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
am__v_lt_0 = --silent
am__v_lt_1 = 
libdrawstuff_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
	$(AM_CXXFLAGS) $(CXXFLAGS) $(libdrawstuff_la_LDFLAGS) \
	$(LDFLAGS) -o $@
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo "  GEN     " $@;
am__v_GEN_1 = 
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 = 
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/ode/src
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
	$(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \
	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
	$(AM_CXXFLAGS) $(CXXFLAGS)
AM_V_CXX = $(am__v_CXX_@AM_V@)
am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@)
am__v_CXX_0 = @echo "  CXX     " $@;
am__v_CXX_1 = 
CXXLD = $(CXX)
CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
	$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
	$(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
AM_V_CXXLD = $(am__v_CXXLD_@AM_V@)
am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@)
am__v_CXXLD_0 = @echo "  CXXLD   " $@;
am__v_CXXLD_1 = 
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
	$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
	$(AM_CFLAGS) $(CFLAGS)
AM_V_CC = $(am__v_CC_@AM_V@)
am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
am__v_CC_0 = @echo "  CC      " $@;
am__v_CC_1 = 
CCLD = $(CC)
LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
	$(AM_LDFLAGS) $(LDFLAGS) -o $@
AM_V_CCLD = $(am__v_CCLD_@AM_V@)
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo "  CCLD    " $@;
am__v_CCLD_1 = 
SOURCES = $(libdrawstuff_la_SOURCES)
DIST_SOURCES = $(am__libdrawstuff_la_SOURCES_DIST)
am__can_run_installinfo = \
  case $$AM_UPDATE_INFO_DIR in \
    n|no|NO) false;; \
    *) (install-info --version) >/dev/null 2>&1;; \
  esac
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates.  Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
  BEGIN { nonempty = 0; } \
  { items[$$0] = 1; nonempty = 1; } \
  END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique.  This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
  list='$(am__tagged_files)'; \
  unique=`for i in $$list; do \
    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
  done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
ALLOCA = @ALLOCA@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
AS = @AS@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CCD_CFLAGS = @CCD_CFLAGS@
CCD_LIBS = @CCD_LIBS@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
DOXYGEN = @DOXYGEN@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
EXTRA_LIBTOOL_LDFLAGS = @EXTRA_LIBTOOL_LDFLAGS@
FGREP = @FGREP@
GL_LIBS = @GL_LIBS@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBSTDCXX = @LIBSTDCXX@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
ODE_PRECISION = @ODE_PRECISION@
ODE_VERSION = @ODE_VERSION@
ODE_VERSION_INFO = @ODE_VERSION_INFO@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
WINDRES = @WINDRES@
X11_CFLAGS = @X11_CFLAGS@
X11_LIBS = @X11_LIBS@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
ac_ct_WINDRES = @ac_ct_WINDRES@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
subdirs = @subdirs@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
noinst_LTLIBRARIES = libdrawstuff.la
libdrawstuff_la_SOURCES = drawstuff.cpp internal.h $(am__append_1) \
	$(am__append_2) $(am__append_3)
AM_CPPFLAGS = -I$(top_srcdir)/include \
        -I$(top_builddir)/include \
        -I$(top_srcdir)/ode/src \
        -DDEFAULT_PATH_TO_TEXTURES='"$(top_srcdir)/drawstuff/textures/"' \
        $(X11_CFLAGS)

@WIN32_TRUE@libdrawstuff_la_LIBADD = -lwinmm -lgdi32
@X11_TRUE@libdrawstuff_la_LIBADD = $(X11_LIBS)
@WIN32_TRUE@libdrawstuff_la_LDFLAGS = -no-undefined
all: all-am

.SUFFIXES:
.SUFFIXES: .cpp .lo .o .obj
$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
	@for dep in $?; do \
	  case '$(am__configure_deps)' in \
	    *$$dep*) \
	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
	        && { if test -f $@; then exit 0; else break; fi; }; \
	      exit 1;; \
	  esac; \
	done; \
	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign drawstuff/src/Makefile'; \
	$(am__cd) $(top_srcdir) && \
	  $(AUTOMAKE) --foreign drawstuff/src/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
	@case '$?' in \
	  *config.status*) \
	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
	  *) \
	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
	esac;

$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh

$(top_srcdir)/configure:  $(am__configure_deps)
	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):

clean-noinstLTLIBRARIES:
	-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
	@list='$(noinst_LTLIBRARIES)'; \
	locs=`for p in $$list; do echo $$p; done | \
	      sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
	      sort -u`; \
	test -z "$$locs" || { \
	  echo rm -f $${locs}; \
	  rm -f $${locs}; \
	}

libdrawstuff.la: $(libdrawstuff_la_OBJECTS) $(libdrawstuff_la_DEPENDENCIES) $(EXTRA_libdrawstuff_la_DEPENDENCIES) 
	$(AM_V_CXXLD)$(libdrawstuff_la_LINK)  $(libdrawstuff_la_OBJECTS) $(libdrawstuff_la_LIBADD) $(LIBS)

mostlyclean-compile:
	-rm -f *.$(OBJEXT)

distclean-compile:
	-rm -f *.tab.c

@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drawstuff.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osx.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/windows.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/x11.Plo@am__quote@

.cpp.o:
@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $<

.cpp.obj:
@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`

.cpp.lo:
@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $<

mostlyclean-libtool:
	-rm -f *.lo

clean-libtool:
	-rm -rf .libs _libs

ID: $(am__tagged_files)
	$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-am
TAGS: tags

tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
	set x; \
	here=`pwd`; \
	$(am__define_uniq_tagged_files); \
	shift; \
	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
	  test -n "$$unique" || unique=$$empty_fix; \
	  if test $$# -gt 0; then \
	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
	      "$$@" $$unique; \
	  else \
	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
	      $$unique; \
	  fi; \
	fi
ctags: ctags-am

CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
	$(am__define_uniq_tagged_files); \
	test -z "$(CTAGS_ARGS)$$unique" \
	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
	     $$unique

GTAGS:
	here=`$(am__cd) $(top_builddir) && pwd` \
	  && $(am__cd) $(top_srcdir) \
	  && gtags -i $(GTAGS_ARGS) "$$here"
cscopelist: cscopelist-am

cscopelist-am: $(am__tagged_files)
	list='$(am__tagged_files)'; \
	case "$(srcdir)" in \
	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
	  *) sdir=$(subdir)/$(srcdir) ;; \
	esac; \
	for i in $$list; do \
	  if test -f "$$i"; then \
	    echo "$(subdir)/$$i"; \
	  else \
	    echo "$$sdir/$$i"; \
	  fi; \
	done >> $(top_builddir)/cscope.files

distclean-tags:
	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags

distdir: $(DISTFILES)
	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
	list='$(DISTFILES)'; \
	  dist_files=`for file in $$list; do echo $$file; done | \
	  sed -e "s|^$$srcdirstrip/||;t" \
	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
	case $$dist_files in \
	  */*) $(MKDIR_P) `echo "$$dist_files" | \
			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
			   sort -u` ;; \
	esac; \
	for file in $$dist_files; do \
	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
	  if test -d $$d/$$file; then \
	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
	    if test -d "$(distdir)/$$file"; then \
	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
	    fi; \
	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
	    fi; \
	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
	  else \
	    test -f "$(distdir)/$$file" \
	    || cp -p $$d/$$file "$(distdir)/$$file" \
	    || exit 1; \
	  fi; \
	done
check-am: all-am
check: check-am
all-am: Makefile $(LTLIBRARIES)
installdirs:
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am

install-am: all-am
	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am

installcheck: installcheck-am
install-strip:
	if test -z '$(STRIP)'; then \
	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
	      install; \
	else \
	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
	fi
mostlyclean-generic:

clean-generic:

distclean-generic:
	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)

maintainer-clean-generic:
	@echo "This command is intended for maintainers to use"
	@echo "it deletes files that may require special tools to rebuild."
clean: clean-am

clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
	mostlyclean-am

distclean: distclean-am
	-rm -rf ./$(DEPDIR)
	-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
	distclean-tags

dvi: dvi-am

dvi-am:

html: html-am

html-am:

info: info-am

info-am:

install-data-am:

install-dvi: install-dvi-am

install-dvi-am:

install-exec-am:

install-html: install-html-am

install-html-am:

install-info: install-info-am

install-info-am:

install-man:

install-pdf: install-pdf-am

install-pdf-am:

install-ps: install-ps-am

install-ps-am:

installcheck-am:

maintainer-clean: maintainer-clean-am
	-rm -rf ./$(DEPDIR)
	-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic

mostlyclean: mostlyclean-am

mostlyclean-am: mostlyclean-compile mostlyclean-generic \
	mostlyclean-libtool

pdf: pdf-am

pdf-am:

ps: ps-am

ps-am:

uninstall-am:

.MAKE: install-am install-strip

.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
	clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \
	ctags-am distclean distclean-compile distclean-generic \
	distclean-libtool distclean-tags distdir dvi dvi-am html \
	html-am info info-am install install-am install-data \
	install-data-am install-dvi install-dvi-am install-exec \
	install-exec-am install-html install-html-am install-info \
	install-info-am install-man install-pdf install-pdf-am \
	install-ps install-ps-am install-strip installcheck \
	installcheck-am installdirs maintainer-clean \
	maintainer-clean-generic mostlyclean mostlyclean-compile \
	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
	tags tags-am uninstall uninstall-am

.PRECIOUS: Makefile


# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
ode-0.16/drawstuff/textures/0000775000175200017520000000000013403272463013112 500000000000000ode-0.16/drawstuff/textures/checkered.ppm0000664000175200017520000002304013403272463015464 00000000000000P6
57 57
255
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿode-0.16/drawstuff/textures/wood.ppm0000664000175200017520000060005313403272463014524 00000000000000P6
# Created by Paint Shop Pro
256 256
255
ÛÛÛÐÐÐÇÇÇÉÉÉÌÌÌÌÌÌÌÌÌÍÍÍÎÎÎÐÐÐÑÑÑÑÑÑÑÑÑÑÑÑÐÐÐÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÍÍÍÊÊÊÉÉÉÇÇÇÃÃÃÌÌÌÌÌÌÇÇÇ¿¿¿°°°¬¬¬¸¸¸±±±±±±µµµ»»»»»»¼¼¼ÉÉÉØØØÕÕÕÔÔÔØØØâââêêêæææØØØÊÊÊÃÃÃÑÑÑÜÜÜîîîîîîäääçççäääÙÙÙÛÛÛÐÐÐÇÇÇÅÅż¼¼æææçççèèèæææÛÛÛæææèèèâââãããÛÛÛèèèçççæææãããàààâââçççêêêêêêëëëîîîñññòòòòòòñññïïïëëëçççääääääèèèêêêêêêççççççÝÝÝíííèèèÎÎÎÂÂÂÂÂÂÇÇÇÆÆÆÅÅÅÂÂÂÂÂÂÂÂÂÃÃÃÅÅÅÅÅÅÅÅÅÆÆÆÅÅÅÎÎÎÅÅ۰°´´´······ÍÍÍØØØÌÌÌ»»»¼¼¼ÇÇÇÐÐÐÊÊÊÉÉÉÎÎÎÀÀÀººº¾¾¾¸¸¸¼¼¼¾¾¾ÃÃÿ¿¿³³³³³³¼¼¼¿¿¿¸¸¸ÂÂÂÉÉÉÇÇÇ»»»¸¸¸ÅÅÅÑÑÑÕÕÕØØØÑÑÑÆÆÆØØØãããÒÒÒÉÉÉÉÉÉÆÆÆÍÍÍÊÊÊ»»»ÍÍÍäää×××ÐÐÐÐÐÐÔÔÔØØØØØØ×××ÒÒÒÑÑÑÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÎÎÎÌÌÌÊÊÊÇÇÇÊÊÊÍÍÍÌÌÌÀÀÀºººÅÅÅÇÇÇ»»»ÍÍÍÆÆÆÇÇÇÅÅÅ»»»»»»¿¿¿¸¸¸¸¸¸¿¿¿ÃÃÃÃÃÃÆÆÆÇÇÇÃÃÿ¿¿ÆÆÆÂ¸¸¸ÝÝÝçççØØØÇÇÇÐÐÐÍÍÍÕÕÕÔÔÔäääíííßßßÝÝÝãããÝÝÝÜÜÜÙÙÙÕÕÕÑÑÑÍÍÍÊÊÊÉÉÉÆÆÆÆÆÆÇÇÇÉÉÉÌÌÌÌÌÌÇÇÇÅÅÅÀÀÀÆÆÆÉÉÉÃÃø¸¸±±±±±±´´´³³³¿¿¿ÍÍÍÑÑÑÌÌÌÉÉÉÎÎÎÕÕÕÒÒÒÊÊÊÅÅÅÇÇÇÊÊÊÊÊÊÌÌÌÎÎÎÎÎÎÐÐÐÐÐÐÑÑÑÑÑÑÑÑÑÐÐÐÐÐÐÐÐÐÎÎÎÎÎÎÍÍÍÌÌÌÊÊÊÊÊÊÉÉÉÂÂÂÍÍÍÎÎÎÉÉÉÀÀÀ´´´­­­³³³³³³···ººº¸¸¸ºººÀÀÀÍÍÍ×××ÒÒÒÔÔÔÙÙÙâââèèèæææÛÛÛÐÐÐÌÌÌÎÎÎÑÑÑâââêêêæææçççàààßßßÜÜÜÑÑÑÌÌÌÅÅŸ¸¸ßßßçççßßßàààÛÛÛãããäääÝÝÝãããàààßßßâââæææçççççççççêêêíííêêêêêêèèèçççæææäääääääääãããßßßÝÝÝßßßâââãããâââßßßãããÜÜÜèèèÛÛÛ¼¼¼»»»ÀÀÀÀÀÀÆÆÆÆÆÆÅÅÅÃÃÃÃÃÃÃÃÃÆÆÆÇÇÇÇÇÇÉÉÉÉÉÉÊÊÊÀÀÀ±±±´´´»»»¿¿¿ÌÌÌÐÐÐÆÆÆ¿¿¿ÆÆÆÍÍÍÐÐÐÍÍÍÌÌÌÌÌ̼¼¼ºººÀÀÀ»»»ÀÀÀÀÀÀÃÃÿ¿¿¸¸¸ºººÂÂÂÃÃÿ¿¿¾¾¾ÂÂÂÀÀÀººº¼¼¼ÌÌÌ×××ØØØÕÕÕÎÎÎÂÂÂÒÒÒÝÝÝÐÐÐÊÊÊÊÊÊÇÇÇÂÂÂÃÃÃÂÂÂÔÔÔâââÒÒÒÍÍÍÑÑÑÔÔÔÕÕÕÕÕÕÒÒÒÐÐÐÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÍÍÍÊÊÊÉÉÉÇÇÇÅÅÅÉÉÉÐÐÐÊÊÊ»»»¸¸¸ÀÀÀÃÃõµµ´´´¿¿¿ÆÆÆ¼¼¼µµµººº¼¼¼ÀÀÀÃÃÃÃÃÃÃÃÃÆÆÆÇÇÇÀÀÀ¸¸¸ÉÉÉ¿¿¿±±±ÒÒÒÛÛÛÑÑÑÇÇÇÒÒÒÇÇÇÕÕÕÐÐÐäääçççÝÝÝÝÝÝàààÝÝÝÜÜÜÙÙÙÕÕÕÑÑÑÍÍÍÊÊÊÉÉÉÇÇÇÉÉÉÉÉÉÊÊÊÌÌÌÊÊÊÇÇÇÅÅÅÂÂÂÉÉÉÐÐÐÑÑÑÍÍÍÉÉÉÊÊÊÍÍÍÊÊÊÉÉÉÊÊÊÍÍÍÑÑÑÑÑÑÎÎÎÊÊÊÇÇÇÅÅÅÃÃÃÆÆÆÇÇÇÉÉÉÊÊÊÎÎÎÎÎÎÎÎÎÐÐÐÑÑÑÑÑÑÑÑÑÑÑÑÐÐÐÐÐÐÐÐÐÍÍÍÌÌÌÌÌÌÌÌÌÌÌÌÍÍÍÇÇÇÐÐÐÐÐÐÇÇǾ¾¾´´´°°°´´´···¾¾¾¾¾¾······ÃÃÃÑÑÑÕÕÕÑÑÑÒÒÒÙÙÙâââçççæææßßßØØØÒÒÒÌÌÌÅÅÅÑÑÑçççæææçççÝÝÝàààÙÙÙÐÐÐÎÎÎÃÃø¸¸ÝÝÝêêêàààãããßßßäääâââÛÛÛâââããããããçççêêêêêêçççæææèèèíííóóóóóóïïïêêêãããààààààãããëëëçççäääæææêêêëëëêêêèèèæææßßßíííØØØ´´´ºººÅÅÅ¿¿¿ÆÆÆÇÇÇÇÇÇÆÆÆÃÃÃÃÃÃÆÆÆÊÊÊÇÇÇÉÉÉÌÌÌ···´´´µµµ¿¿¿ÌÌÌÌÌÌÇÇÇÂÂÂÆÆÆÑÑÑÕÕÕÑÑÑÑÑÑÐÐÐÉÉÉ»»»ÂÂÂÉÉÉÃÃÃÊÊÊÎÎÎÌÌÌÇÇÇÅÅÅÅÅÅÅÅÅÃÃÃÂÂÂÃÃÃÆÆÆÃÃþ¾¾ÂÂÂÎÎÎÕÕÕÔÔÔÎÎÎÌÌÌÅÅÅÔÔÔÝÝÝÎÎÎÇÇÇÇÇÇÇÇǼ¼¼ÅÅÅÑÑÑ×××ØØØÐÐÐÎÎÎÒÒÒÒÒÒÒÒÒÑÑÑÍÍÍÌÌÌÊÊÊÌÌÌÍÍÍÍÍÍÍÍÍÌÌÌÊÊÊÉÉÉÆÆÆÆÆÆÃÃÃÀÀÀÌÌÌÑÑÑÀÀÀ´´´»»»ÅÅÅÆÆÆ¾¾¾¿¿¿ÅÅÅ»»»°°°µµµ¾¾¾¾¾¾¾¾¾ÀÀÀÃÃÃÉÉÉÍÍÍÇÇǼ¼¼ÊÊÊ¿¿¿¯¯¯ÎÎÎÕÕÕÎÎÎÉÉÉÒÒÒÀÀÀ×××ÊÊÊæææàààÝÝÝßßßßßßÜÜÜÛÛÛØØØÕÕÕÑÑÑÎÎÎÌÌÌÊÊÊÊÊÊÌÌÌÍÍÍÍÍÍÊÊÊÇÇÇÆÆÆÆÆÆ¿¿¿ÃÃÃÊÊÊÐÐÐÐÐÐÎÎÎÎÎÎÎÎÎÊÊÊÃÃÿ¿¿ÅÅÅÐÐÐÕÕÕÒÒÒÌÌÌÀÀÀÂÂÂÅÅÅÆÆÆÆÆÆÆÆÆÊÊÊÍÍÍÍÍÍÎÎÎÎÎÎÐÐÐÐÐÐÑÑÑÑÑÑÑÑÑÑÑÑÐÐÐÍÍÍÊÊÊÊÊÊÌÌÌÎÎÎÐÐÐÒÒÒÐÐÐÌÌÌÇÇÇ¿¿¿³³³³³³ººº»»»¿¿¿¾¾¾···¸¸¸ÂÂÂÎÎÎÔÔÔÐÐÐÒÒÒÙÙÙàààäääæææãããààà×××ÌÌÌÀÀÀÊÊÊæææäääçççÝÝÝØØØ×××ÐÐÐÌÌÌÂÂÂÃÃÃâââíííàààÛÛÛÕÕÕÕÕÕÑÑÑÌÌÌÎÎÎÒÒÒÌÌÌÐÐÐÒÒÒÔÔÔÕÕÕÛÛÛäääíííøøøùùùöööñññèèèäääæææèèèêêêäääßßßÝÝÝâââæææèèèèèèçççßßßíííÙÙÙ³³³¸¸¸ÅÅÅ¿¿¿ÅÅÅÇÇÇÇÇÇÆÆÆÂÂÂÂÂÂÆÆÆÊÊÊÆÆÆÆÆÆÌÌ̺ºº°°°¸¸¸»»»ÇÇÇÔÔÔÎÎÎÅÅÅÀÀÀÇÇÇÔÔÔ×××ÒÒÒÐÐÐÒÒÒÇÇÇÀÀÀÍÍÍÔÔÔÎÎÎÒÒÒÒÒÒÍÍÍÍÍÍÑÑÑÐÐÐÉÉÉÅÅÅÅÅÅÊÊÊÍÍÍÊÊÊÃÃÃÀÀÀÅÅÅÉÉÉÉÉÉ¿¿¿ÅÅÅÆÆÆÛÛÛäääÕÕÕÎÎÎÍÍÍÆÆÆÂÂÂÒÒÒßßßÔÔÔÌÌÌÐÐÐÔÔÔÔÔÔÒÒÒÑÑÑÍÍÍÉÉÉÇÇÇÇÇÇÊÊÊÌÌÌÌÌÌÊÊÊÉÉÉÇÇÇÆÆÆÅÅÅÃÃÃÇÇǼ¼¼ÀÀÀÌÌÌÉÉÉ¿¿¿¼¼¼»»»ÍÍÍ»»»¾¾¾¿¿¿¾¾¾¿¿¿ÀÀÀÀÀÀÀÀÀÆÆÆÇÇÇÆÆÆÉÉÉÆÆÆ¼¼¼ÇÇÇ¿¿¿´´´ÕÕÕÛÛÛÔÔÔÌÌÌÐÐп¿¿ØØØÉÉÉèèèÝÝÝßßßâââßßßÜÜÜÛÛÛØØØÕÕÕÑÑÑÎÎÎÌÌÌÊÊÊÌÌÌÍÍÍÎÎÎÍÍÍÉÉÉÆÆÆÆÆÆÆÆÆ¿¿¿ÀÀÀÀÀÀÃÃÃÃÃÃÀÀÀ¼¼¼ººº······¸¸¸¾¾¾ÃÃÃÊÊÊÎÎÎÐÐп¿¿ÃÃÃÆÆÆÆÆÆÅÅÅÆÆÆÉÉÉÌÌÌÍÍÍÍÍÍÍÍÍÍÍÍÎÎÎÐÐÐÐÐÐÑÑÑÑÑÑÐÐÐÍÍÍÊÊÊÌÌÌÍÍÍÑÑÑÒÒÒ×××ÌÌÌÊÊÊÑÑÑÇÇǵµµ³³³¼¼¼¾¾¾ººº¸¸¸ººº»»»¾¾¾ÇÇÇÒÒÒÑÑÑÔÔÔØØØÝÝÝâââäääææææææÔÔÔÎÎÎÆÆÆÊÊÊèèèàààæææßßßÒÒÒÙÙÙÒÒÒÉÉÉÀÀÀÑÑÑççççççæææØØØÐÐÐÌÌÌÌÌÌÊÊÊÉÉÉÊÊÊÉÉÉÌÌÌÍÍÍÎÎÎÐÐÐÕÕÕÝÝÝäääëëëîîîñññîîîèèèææææææèèèæææßßßÕÕÕÑÑÑÕÕÕÝÝÝãããæææààà×××æææØØØµµµ´´´¼¼¼»»»ÃÃÃÅÅÅÆÆÆÃÃÃÀÀÀ¿¿¿ÃÃÃÉÉÉÉÉÉÉÉÉÌÌ̸¸¸³³³ÂÂÂÇÇÇÔÔÔÒÒÒÎÎÎÆÆÆÀÀÀÃÃÃÊÊÊÍÍÍÌÌÌÉÉÉÍÍÍÅÅÅÅÅÅÔÔÔÙÙÙÕÕÕÑÑÑÀÀÀÀÀÀÇÇÇÒÒÒÔÔÔÌÌÌÇÇÇÊÊÊÊÊÊÐÐÐÐÐÐÉÉÉÀÀÀÀÀÀÆÆÆÉÉÉÍÍÍÔÔÔÒÒÒßßßãããÐÐÐÉÉÉÇÇÇÍÍÍÑÑÑßßßãããÔÔÔÍÍÍÔÔÔÔÔÔÔÔÔÒÒÒÐÐÐÌÌÌÇÇÇÆÆÆÇÇÇÉÉÉÊÊÊÉÉÉÇÇÇÆÆÆÅÅÅÃÃÃÃÃÃÂÂÂÇÇǼ¼¼¾¾¾ÆÆÆÉÉÉÉÉÉÀÀÀ³³³¿¿¿ÂÂÂÀÀÀ¿¿¿ÃÃÃÇÇÇÀÀÀ¸¸¸¾¾¾ÂÂÂÌÌÌÌÌÌÅÅÅÆÆÆÉÉÉÀÀÀÇÇÇ¿¿¿¸¸¸ÙÙÙÜÜÜ×××ÍÍÍÍÍÍÃÃÃÕÕÕÌÌÌëëëßßßââââââàààÛÛÛÛÛÛØØØÕÕÕÑÑÑÎÎÎÌÌÌÌÌÌÌÌÌÍÍÍÎÎÎÌÌÌÇÇÇÅÅÅÅÅÅÆÆÆÅÅž¾¾¼¼¼¾¾¾¼¼¼···´´´±±±µµµººº»»»»»»»»»ÀÀÀÅÅÅ¿¿¿ÃÃÃÆÆÆÅÅÅÃÃÃÆÆÆÉÉÉÉÉÉÊÊÊÊÊÊÊÊÊÌÌÌÍÍÍÎÎÎÐÐÐÑÑÑÑÑÑÎÎÎÍÍÍÌÌÌÌÌÌÎÎÎÒÒÒÔÔÔÒÒÒÉÉÉÎÎÎÙÙÙÑÑѾ¾¾µµµ¸¸¸¼¼¼······¼¼¼¾¾¾¼¼¼ÃÃÃÎÎÎÕÕÕÕÕÕ×××ÙÙÙßßßãããæææçççÒÒÒÐÐÐÌÌÌÌÌÌíííÝÝÝâââÝÝÝÔÔÔÛÛÛÒÒÒÉÉÉÂÂÂÝÝÝêêêàààèèèÙÙÙÒÒÒÐÐÐÒÒÒ×××ÑÑÑÔÔÔØØØÛÛÛÛÛÛÛÛÛÛÛÛÙÙÙÛÛÛÛÛÛàààäääêêêíííëëëêêêêêêëëëêêêâââÙÙÙ×××ÛÛÛãããèèèêêêÝÝÝ×××âââ×××¼¼¼ººº¼¼¼¿¿¿ÃÃÃÅÅÅÅÅÅÃÃÃÀÀÀÀÀÀÃÃÃÇÇÇÌÌÌÌÌÌÊÊʾ¾¾»»»ÉÉÉÔÔÔßßßÐÐÐÎÎÎÉÉÉÃÃÃÀÀÀÀÀÀÃÃÃÃÃÃÂÂÂÅÅÅÂÂÂÊÊÊÔÔÔ×××ÕÕÕÇÇǸ¸¸¼¼¼ÆÆÆÐÐÐÎÎÎÇÇÇÅÅÅÉÉÉÐÐÐÕÕÕ×××ÔÔÔÎÎÎÐÐÐÕÕÕÛÛÛÛÛÛàààØØØÙÙÙØØØÇÇÇÆÆÆÉÉÉØØØÝÝÝàààãããÜÜÜ×××ØØØÐÐÐÕÕÕÔÔÔÑÑÑÌÌÌÇÇÇÆÆÆÉÉÉÌÌÌÉÉÉÉÉÉÆÆÆÅÅÅÃÃÿ¿¿ÂÂÂÃÃÃÃÃÃÇÇÇÅÅŵµµºººÉÉÉÌÌÌÃÃÃÂÂÂÇÇÇÆÆÆÃÃÃÅÅÅÆÆÆÑÑÑÐÐÐÃÃÃÃÃÃÆÆÆ»»»ÉÉÉ¿¿¿···××××××ÕÕÕÐÐÐÎÎÎÌÌÌÎÎÎÎÎÎëëëâââäääàààâââÛÛÛÙÙÙØØØÕÕÕÑÑÑÎÎÎÍÍÍÌÌÌÌÌÌÌÌÌÊÊÊÉÉÉÆÆÆÅÅÅÃÃÃÃÃÃÀÀÀ¼¼¼ºººººº¼¼¼¾¾¾»»»¸¸¸µµµ···¸¸¸»»»¼¼¼¼¼¼¼¼¼¼¼¼¾¾¾ÂÂÂÃÃÃÀÀÀÀÀÀÆÆÆÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÊÊÊÍÍÍÎÎÎÐÐÐÐÐÐÎÎÎÍÍÍÍÍÍÎÎÎÐÐÐÒÒÒÕÕÕÑÑÑÍÍÍÔÔÔØØØÐÐÐÆÆÆ¿¿¿······¸¸¸»»»¾¾¾¿¿¿ÂÂÂÆÆÆÉÉÉÙÙÙ×××ÕÕÕ×××ÜÜÜâââææææææÔÔÔÑÑÑÍÍÍÊÊÊïïïÜÜÜßßßÙÙÙ×××ÕÕÕÍÍÍÌÌÌÊÊÊèèèëëëàààÝÝÝÒÒÒÔÔÔÑÑÑÒÒÒÕÕÕÎÎÎÕÕÕÎÎÎÎÎÎÑÑÑÔÔÔØØØÛÛÛÜÜÜÜÜÜßßßãããçççëëëîîîîîîîîîíííâââÝÝÝÛÛÛÜÜÜàààääääääãããÜÜÜÝÝÝàààÌÌ̼¼¼ÀÀÀÂÂÂÆÆÆÆÆÆÅÅÅÅÅÅÃÃÃÂÂÂÃÃÃÅÅÅÆÆÆÌÌÌÌÌ̾¾¾¾¾¾ÆÆÆ×××ÜÜÜÒÒÒÒÒÒÑÑÑÎÎÎÉÉÉÅÅÅÃÃÃÃÃÃÅÅÅÅÅÅÆÆÆÒÒÒÒÒÒÔÔÔ××׿¿¿¼¼¼ÅÅÅÎÎÎÑÑÑÌÌÌÆÆÆÇÇÇÍÍÍØØØ×××ÔÔÔÔÔÔÔÔÔÕÕÕØØØÙÙÙÉÉÉÑÑÑÊÊÊÐÐÐÒÒÒÌÌÌÔÔÔÝÝÝÙÙÙäääàààæææäääÙÙÙØØØÒÒÒÕÕÕÕÕÕÒÒÒÍÍÍÊÊÊÉÉÉÊÊÊÍÍÍÉÉÉÇÇÇÆÆÆÃÃÃÂÂÂÂÂÂÂÂÂÂÂÂÀÀÀÀÀÀÅÅÅÅÅÅÀÀÀÅÅÅÆÆÆ¼¼¼³³³ÂÂÂÆÆÆÀÀÀÅÅÅÊÊÊÐÐÐ×××ÒÒÒÌÌÌÑÑÑÐÐÐÃÃÃÃÃð°°ÍÍÍ»»»ÙÙÙØØØØØØÕÕÕÐÐÐÔÔÔÆÆÆÑÑÑèèèæææãããÛÛÛàààÛÛÛÙÙÙ×××ÕÕÕÑÑÑÐÐÐÍÍÍÌÌÌÊÊÊÉÉÉÆÆÆÅÅÅÅÅÅÃÃÃÃÃúºº¸¸¸µµµ···»»»»»»ººº···µµµµµµ···ººº¾¾¾ÀÀÀÀÀÀ¿¿¿»»»¿¿¿¿¿¿¼¼¼¿¿¿ÆÆÆÊÊÊÇÇÇÉÉÉÇÇÇÇÇÇÇÇÇÉÉÉÌÌÌÎÎÎÐÐÐÎÎÎÎÎÎÍÍÍÍÍÍÎÎÎÑÑÑÔÔÔÕÕÕÔÔÔÔÔÔÕÕÕÐÐÐÇÇÇÌÌÌÉÉɺºº³³³ººº¿¿¿¾¾¾ÀÀÀÇÇÇÉÉÉÅÅÅÜÜÜØØØÔÔÔÕÕÕÛÛÛâââäääæææÕÕÕÑÑÑÌÌÌÇÇÇñññÜÜÜÝÝÝÕÕÕÕÕÕÎÎÎÆÆÆÍÍÍÑÑÑïïïíííäääÛÛÛÕÕÕÝÝÝÛÛÛØØØØØØÐÐÐÙÙÙÕÕÕÑÑÑÍÍÍÎÎÎÔÔÔÙÙÙÜÜÜÝÝÝÝÝÝßßßãããçççêêêëëëëëëêêêÜÜÜÜÜÜßßßäääèèèèèèãããÝÝÝÕÕÕÝÝÝØØØººº³³³¿¿¿ÀÀÀÃÃÃÇÇÇÆÆÆÅÅÅÃÃÃÅÅÅÆÆÆÆÆÆÇÇÇÇÇÇÇÇǸ¸¸ººº¼¼¼¿¿¿ÑÑÑÕÕÕÛÛÛÛÛÛÛÛÛÙÙÙÕÕÕÐÐÐÊÊÊÇÇÇÍÍÍÊÊÊÍÍÍÛÛÛÔÔÔÔÔÔÛÛÛ¼¼¼¿¿¿ÊÊÊÔÔÔÔÔÔÎÎÎÎÎÎÕÕÕÜÜÜØØØÐÐÐÆÆÆÅÅÅÉÉÉÊÊÊÆÆÆÀÀÀÂÂÂÍÍÍÉÉÉÍÍÍÐÐÐÉÉÉÑÑÑÙÙÙÕÕÕæææãããêêêèèèÕÕÕÔÔÔÙÙÙ×××ÕÕÕÒÒÒÐÐÐÌÌÌÊÊÊÍÍÍÎÎÎÉÉÉÇÇÇÆÆÆÃÃÃÂÂÂÀÀÀÂÂÂÂÂÂÅÅÅ¿¿¿ÀÀÀÅÅÅÂÂÂÅÅÅÆÆÆ¿¿¿³³³¼¼¼¿¿¿ÃÃÃÊÊÊÅÅž¾¾ÀÀÀ¿¿¿···¿¿¿ÊÊÊÌÌÌ×××ØØØÃÃÃÎÎÎÆÆÆÂÂÂâââàààßßßÙÙÙÑÑÑØØØ¿¿¿ÒÒÒæææçççããã×××àààÛÛÛÙÙÙ×××ÕÕÕÑÑÑÐÐÐÍÍÍÌÌÌÉÉÉÆÆÆÃÃÃÃÃÃÃÃÃÃÃÃÂÂÂÀÀÀ¼¼¼»»»ººº»»»»»»ºººµµµ±±±···¸¸¸ººººººººº»»»¾¾¾ÀÀÀ¿¿¿ÀÀÀ¿¿¿»»»¼¼¼ÃÃÃÆÆÆÅÅÅÊÊÊÉÉÉÇÇÇÉÉÉÌÌÌÎÎÎÎÎÎÍÍÍÒÒÒÑÑÑÎÎÎÍÍÍÍÍÍÍÍÍÎÎÎÐÐÐÎÎÎÕÕÕÒÒÒÇÇÇÇÇÇÎÎÎÌÌÌÀÀÀ³³³µµµººº¼¼¼¾¾¾ÀÀÀÅÅÅÇÇÇâââÜÜÜÕÕÕÒÒÒ×××ÜÜÜàààâââ×××ÐÐÐÑÑÑÊÊÊñññàààÝÝÝÛÛÛÐÐÐÌÌÌßßßêêêèèèëëëçççêêêÛÛÛÙÙÙØØØÕÕÕÔÔÔÒÒÒÒÒÒÑÑÑÎÎÎÒÒÒÕÕÕØØØÙÙÙÙÙÙÜÜÜßßßØØØâââäääàààäääîîîëëëßßßçççßßßãããèèèæææââââââßßßÙÙÙ×××ÌÌ̼¼¼¸¸¸ÂÂÂÇÇÇÅÅÅÉÉÉÅÅÅÇÇÇÉÉÉÅÅÅÇÇÇÌÌÌÉÉÉÐÐÐÆÆÆ¾¾¾¿¿¿Â¿¿¿¿¿¿ÀÀÀÃÃÃÉÉÉÑÑÑÙÙÙÜÜÜØØØÒÒÒÒÒÒÑÑÑÕÕÕ×××ÑÑÑÔÔÔÎÎμ¼¼ÍÍÍØØØÍÍÍÍÍÍÕÕÕßßßßßßÆÆÆÇÇÇÇÇÇÅÅÅ¿¿¿¼¼¼ÂÂÂÅÅž¾¾ÀÀÀÆÆÆÆÆÆÃÃÃÌÌÌÜÜÜßßß×××ÙÙÙÜÜÜÝÝÝÜÜÜÙÙÙ××××××ØØØÕÕÕÑÑÑÎÎÎÎÎÎÐÐÐÑÑÑÐÐÐÎÎÎÌÌÌÉÉÉÃÃÿ¿¿¼¼¼»»»¼¼¼¾¾¾¾¾¾ÆÆÆÆÆÆÂÂÂÂÂÂÃÃÃÌÌÌÛÛÛÃÃúºº¾¾¾ÎÎÎÂÂÂÍÍÍÎÎÎÇÇÇÃÃÃÌÌÌÉÉÉÆÆÆÊÊÊÌÌÌÎÎÎÛÛÛÊÊÊÆÆÆ¸¸¸ßßßÙÙÙÛÛÛÍÍÍÒÒÒ×××ØØØÆÆÆããããããÛÛÛÛÛÛÔÔÔØØØÕÕÕÒÒÒÑÑÑÐÐÐÍÍÍÊÊÊÆÆÆÇÇÇÆÆÆÆÆÆÅÅÅÃÃÃÂÂÂÀÀÀ¿¿¿»»»¸¸¸¸¸¸»»»ººº´´´´´´¸¸¸ºººººººººººº»»»¼¼¼¾¾¾¿¿¿¾¾¾ÀÀÀÀÀÀ¾¾¾¿¿¿ÅÅÅÆÆÆÅÅÅÉÉÉÇÇÇÇÇÇÊÊÊÍÍÍÎÎÎÎÎÎÍÍÍÑÑÑÐÐÐÎÎÎÎÎÎÍÍÍÍÍÍÎÎÎÎÎÎÌÌÌÎÎÎÍÍÍÉÉÉÊÊÊÐÐÐÎÎÎÇÇÇ¿¿¿»»»ººº¾¾¾ÃÃÃÆÆÆÇÇÇÙÙÙÙÙÙÛÛÛÜÜÜÝÝÝÜÜÜÛÛÛÙÙÙÐÐÐÊÊÊÍÍÍÉÉÉíííÝÝÝÛÛÛØØØÐÐÐÎÎÎãããíííëëëíííæææäää×××××××××ÕÕÕÔÔÔÔÔÔÒÒÒÒÒÒÎÎÎÎÎÎÐÐÐÑÑÑÒÒÒ×××ÛÛÛßßßÝÝÝââââââßßßâââêêêëëëçççèèèâââçççîîîèèèãããàààÛÛÛÜÜÜÎÎξ¾¾¿¿¿ÂÂÂÅÅÅÇÇÇÉÉÉÅÅÅÇÇÇÉÉÉÆÆÆÉÉÉÍÍÍÊÊÊÎÎÎÅÅž¾¾ÀÀÀÅÅÅÅÅÅÅÅÅÅÅÅÃÃÃÃÃÃÅÅÅÇÇÇÌÌÌÒÒÒÙÙÙÝÝÝÕÕÕÒÒÒÔÔÔÔÔÔÒÒÒÒÒÒÌÌÌÀÀÀÉÉÉÔÔÔÌÌÌÌÌÌÑÑÑØØØàààÒÒÒÇÇÇÆÆÆÂÂÂÂÂÂÌÌÌÒÒÒÒÒÒÐÐÐÂÂÂÅÅÅÆÆÆÇÇÇÐÐÐÛÛÛÝÝÝ×××ÔÔÔÕÕÕ×××ÕÕÕÔÔÔÒÒÒÔÔÔÕÕÕÒÒÒÑÑÑÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÍÍÍÉÉÉÃÃÿ¿¿¾¾¾¾¾¾¾¾¾¾¾¾ÂÂÂÅÅÅÃÃÃÅÅÅÇÇÇÃÃÃÃÃÃÎÎÎÉÉÉ»»»»»»ÐÐÐÃÃÃÌÌÌÎÎÎÑÑÑÒÒÒÔÔÔÎÎÎÎÎÎÔÔÔÒÒÒÍÍÍÐÐÐÍÍÍÍÍÍ¿¿¿âââÛÛÛÛÛÛÐÐÐÔÔÔ×××ÙÙÙÉÉÉãããàààÙÙÙÙÙÙÔÔÔ×××ÕÕÕÒÒÒÑÑÑÐÐÐÍÍÍÉÉÉÆÆÆÆÆÆÆÆÆÅÅÅÃÃÃÂÂÂÀÀÀ¿¿¿¿¿¿»»»······ººººººµµµµµµ¸¸¸¸¸¸¸¸¸ºººººº»»»¼¼¼¿¿¿¿¿¿»»»¿¿¿ÂÂÂÀÀÀÃÃÃÆÆÆÇÇÇÅÅÅÇÇÇÇÇÇÉÉÉÌÌÌÎÎÎÐÐÐÎÎÎÍÍÍÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÍÍÍÍÍÍÉÉÉÇÇÇÇÇÇÊÊÊÍÍÍÎÎÎÎÎÎÎÎÎÇÇÇÀÀÀ»»»»»»ÂÂÂÅÅÅÃÃÃÀÀÀÐÐÐÔÔÔÙÙÙÝÝÝÜÜÜØØØÔÔÔÑÑÑÌÌÌÉÉÉÌÌÌÉÉÉçççÜÜÜÛÛÛØØØÑÑÑÒÒÒæææîîîíííîîîãããÜÜÜÔÔÔÔÔÔÕÕÕÕÕÕÕÕÕÔÔÔÒÒÒÑÑÑ×××ÕÕÕÔÔÔÔÔÔØØØßßßãããæææãããâââßßßÜÜÜÝÝÝãããêêêïïïëëëäääçççêêêæææâââßßßØØØÙÙÙÅÅŸ¸¸ÂÂÂÇÇÇÂÂÂÃÃÃÊÊÊÇÇÇÃÃÃÇÇÇÉÉÉÆÆÆÊÊÊÎÎÎÌÌÌÉÉÉ¿¿¿ººº¾¾¾ÂÂÂÃÃÃÂÂÂÂÂÂÂÂÂÃÃÃÃÃÃÂÂÂÃÃÃÊÊÊ×××âââÛÛÛÙÙÙ×××ØØØÛÛÛÔÔÔÌÌÌÌÌÌÂÂÂÊÊÊÆÆÆÆÆÆÆÆÆÇÇÇÎÎÎÊÊÊÌÌÌÊÊÊÂÂÂÆÆÆØØØÙÙÙÔÔÔÙÙÙÅÅÅÆÆÆÉÉÉÎÎÎÕÕÕÙÙÙÙÙÙ×××ÍÍÍÍÍÍÎÎÎÍÍÍÍÍÍÎÎÎÑÑÑÒÒÒÎÎÎÐÐÐÑÑÑÑÑÑÐÐÐÐÐÐÐÐÐÐÐÐÎÎÎÉÉÉÃÃÿ¿¿¿¿¿ÀÀÀ¿¿¿¿¿¿¾¾¾¿¿¿¿¿¿ÃÃÃÊÊÊÅÅÅÀÀÀÆÆÆÔÔÔÅÅÅÆÆÆÜÜÜÎÎÎÌÌÌÉÉÉÍÍÍÆÆÆÐÐÐÒÒÒÐÐÐÍÍÍÇÇÇÉÉÉÐÐÐÊÊÊÐÐÐÉÉÉäääÝÝÝßßßØØØÜÜÜ×××ÛÛÛÍÍÍâââÜÜÜ××××××ÕÕÕ×××ÔÔÔÒÒÒÑÑÑÐÐÐÍÍÍÉÉÉÆÆÆÆÆÆÅÅÅÃÃÃÂÂÂÀÀÀ¿¿¿¿¿¿¾¾¾¸¸¸µµµµµµºººººº······ººº¸¸¸¸¸¸¸¸¸ººº»»»¾¾¾¿¿¿ÀÀÀ»»»ÀÀÀÃÃÃÂÂÂÃÃÃÇÇÇÉÉÉÆÆÆÆÆÆÇÇÇÉÉÉÍÍÍÐÐÐÑÑÑÎÎÎÍÍÍÌÌÌÍÍÍÎÎÎÐÐÐÐÐÐÎÎÎÌÌÌÊÊÊÊÊÊÆÆÆÆÆÆÌÌÌÎÎÎÌÌÌÌÌÌÎÎÎÉÉÉ»»»¸¸¸¼¼¼ÀÀÀÀÀÀ¿¿¿ÉÉÉÍÍÍÑÑÑÒÒÒÑÑÑÐÐÐÐÐÐÐÐÐÐÐÐÍÍÍÎÎÎÊÊÊãããÜÜÜÜÜÜÛÛÛÒÒÒÔÔÔæææëëëèèèëëëààà×××ÕÕÕÕÕÕ×××ØØØØØØÕÕÕÒÒÒÑÑÑÒÒÒÑÑÑÐÐÐÔÔÔÙÙÙÝÝÝààààààäääßßßÛÛÛÛÛÛÙÙÙÜÜÜæææñññèèèââââââãããÝÝÝÝÝÝßßßÙÙÙÎÎο¿¿»»»ÆÆÆÌÌÌÅÅÅÃÃÃÌÌÌÇÇÇÃÃÃÇÇÇÊÊÊÇÇÇÌÌÌÐÐÐÍÍÍÃÃü¼¼¸¸¸¼¼¼ÀÀÀÀÀÀÀÀÀÂÂÂÀÀÀÂÂÂÅÅÅÆÆÆÇÇÇÌÌÌÑÑÑ×××ÎÎÎÐÐÐÌÌÌÎÎÎÔÔÔÊÊÊ¿¿¿ÅÅÅ¿¿¿ÃÃÃÆÆÆÊÊÊÌÌÌÊÊÊÍÍÍÍÍÍÇÇÇÊÊÊÂÂÂÆÆÆØØØÕÕÕÐÐÐÝÝÝÎÎÎÌÌÌÎÎÎ×××ÛÛÛØØØÕÕÕÕÕÕÌÌÌÊÊÊÉÉÉÇÇÇÇÇÇÊÊÊÍÍÍÐÐÐÍÍÍÐÐÐÒÒÒÒÒÒÑÑÑÐÐÐÑÑÑÒÒÒÑÑÑÌÌÌÃÃÃÀÀÀÂÂÂÃÃÿ¿¿···ÀÀÀÀÀÀ¾¾¾ÃÃÃÇÇÇÆÆÆÇÇÇØØØÊÊÊÂÂÂÎÎÎÂÂÂÇÇÇÌÌÌÕÕÕÜÜÜ×××ÌÌÌÅÅÅÆÆÆÌÌÌÑÑÑ×××ÊÊÊ×××ÔÔÔçççÝÝÝÜÜÜÙÙÙÙÙÙØØØÝÝÝÒÒÒâââØØØÔÔÔÔÔÔ×××ÕÕÕÒÒÒÑÑÑÐÐÐÎÎÎÍÍÍÉÉÉÆÆÆÅÅÅÅÅÅÃÃÃÂÂÂÀÀÀ¿¿¿¾¾¾¼¼¼¸¸¸´´´´´´¸¸¸ººº¸¸¸¸¸¸ººº¸¸¸¸¸¸¸¸¸ººº»»»¾¾¾¿¿¿ÀÀÀ¾¾¾ÂÂÂÅÅÅÂÂÂÀÀÀÆÆÆÉÉÉÉÉÉÅÅÅÆÆÆÉÉÉÌÌÌÐÐÐÑÑÑÐÐÐÍÍÍÊÊÊÌÌÌÎÎÎÐÐÐÐÐÐÍÍÍÊÊÊÉÉÉÎÎÎÇÇÇÆÆÆÌÌÌÌÌÌÇÇÇÅÅÅÉÉÉÎÎÎÊÊÊ»»»¸¸¸ººº¾¾¾ÂÂÂÃÃÃÆÆÆÌÌÌÍÍÍÍÍÍÎÎÎÐÐÐÑÑÑÒÒÒÐÐÐÎÎÎÊÊÊÙÙÙÙÙÙÛÛÛÙÙÙÔÔÔÑÑÑãããæææãããäääÜÜÜ×××ØØØÙÙÙÛÛÛÛÛÛØØØÕÕÕÒÒÒÑÑÑÐÐÐÑÑÑÔÔÔÙÙÙÝÝÝàààßßßÜÜÜâââÛÛÛØØØÙÙÙØØØ×××ßßßêêêâââÝÝÝàààãããßßßààààààÙÙÙÀÀÀ¿¿¿ÃÃÃÊÊÊÌÌÌÆÆÆÆÆÆÌÌÌÉÉÉÅÅÅÇÇÇÊÊÊÇÇÇÌÌÌÑÑÑÎÎξ¾¾ºººººº¿¿¿ÂÂÂÂÂÂÅÅÅÉÉÉÅÅÅÅÅÅÅÅÅÉÉÉÍÍÍÎÎÎÌÌÌÉÉÉÇÇÇÊÊÊÇÇÇÌÌÌÑÑÑÇÇǼ¼¼ÃÃÃÇÇÇÃÃÃÃÃÃÅÅÅÆÆÆÅÅÅÃÃÃÅÅÅ¿¿¿ÉÉÉÆÆÆÊÊÊ×××ÑÑÑÐÐÐããã×××ÒÒÒÕÕÕÜÜÜÝÝÝÕÕÕÑÑÑÔÔÔÎÎÎÌÌÌÉÉÉÆÆÆÇÇÇÉÉÉÌÌÌÎÎÎÌÌÌÐÐÐÒÒÒÔÔÔÒÒÒÒÒÒÒÒÒÔÔÔÕÕÕÎÎÎÆÆÆÃÃÃÃÃÃÅÅÅ¿¿¿ÀÀÀÒÒÒÎÎμ¼¼»»»ÆÆÆÌÌÌÌÌÌÐÐÐÍÍÍÅÅÅÇÇǸ¸¸ÂÂÂÂÂÂÃÃÃÊÊÊÇÇÇÉÉÉÌÌÌÐÐÐÔÔÔ×××ÕÕÕÍÍÍßßßßßßçççÛÛÛØØØÕÕÕÑÑÑÛÛÛàààØØØâââÕÕÕÔÔÔÒÒÒ×××ÔÔÔÑÑÑÐÐÐÎÎÎÎÎÎÍÍÍÉÉÉÆÆÆÅÅÅÃÃÃÃÃÿ¿¿¾¾¾¾¾¾¼¼¼···³³³±±±···ºººººº¸¸¸ººº······¸¸¸ººº»»»¾¾¾ÀÀÀ¾¾¾ÃÃÃÆÆÆÂÂÂÀÀÀÃÃÃÇÇÇÇÇÇÅÅÅÅÅÅÆÆÆÊÊÊÎÎÎÐÐÐÐÐÐÎÎÎÊÊÊÌÌÌÍÍÍÎÎÎÎÎÎÍÍÍÊÊÊÉÉÉÎÎÎÉÉÉÆÆÆÉÉÉÉÉÉÃÃÃÂÂÂÃÃÃÎÎÎÑÑÑÑÑÑÍÍÍÆÆÆ¾¾¾ººº¸¸¸¾¾¾ÃÃÃÉÉÉÎÎÎÐÐÐÐÐÐÐÐÐÐÐÐÎÎÎÎÎÎÍÍÍÉÉÉÑÑÑÔÔÔ×××ÕÕÕÔÔÔÎÎÎßßßäääàààßßßÙÙÙÛÛÛÛÛÛÛÛÛÛÛÛÙÙÙØØØÕÕÕÒÒÒÑÑÑÔÔÔ×××ÛÛÛßßßããããããâââàààÝÝÝÙÙÙØØØÙÙÙÙÙÙÕÕÕØØØßßßÙÙÙÛÛÛâââçççäääæææããã×××¼¼¼ÃÃÃÊÊÊÍÍÍÊÊÊÊÊÊÊÊÊÌÌÌÊÊÊÆÆÆÉÉÉÌÌÌÉÉÉÌÌÌÑÑÑÎÎδ´´´´´¸¸¸¼¼¼¼¼¼¼¼¼ÂÂÂÉÉÉÊÊÊÇÇÇÅÅÅÆÆÆÌÌÌÍÍÍÊÊÊÆÆÆÉÉÉÌÌÌÌÌÌÎÎÎÑÑÑÌÌÌÇÇÇÉÉÉÉÉÉÀÀÀ¿¿¿»»»¼¼¼ÂÂÂÀÀÀÅÅÅÇÇÇÒÒÒÔÔÔÒÒÒÕÕÕÐÐÐÑÑÑàààÛÛÛ×××ØØØÛÛÛÙÙÙÒÒÒÐÐÐÑÑÑÐÐÐÍÍÍÉÉÉÇÇÇÉÉÉÌÌÌÍÍÍÎÎÎÎÎÎÐÐÐÒÒÒÔÔÔÔÔÔÕÕÕ××××××ØØØÒÒÒÊÊÊÆÆÆÅÅÅÃÃÃÂÂÂÀÀÀÑÑÑãããÛÛÛÀÀÀºººÃÃÃÉÉÉÊÊÊÅÅÅÐÐÐÐÐÐÔÔÔÉÉÉÐÐÐÆÆÆÀÀÀ»»»ÀÀÀÍÍÍÔÔÔÑÑÑÐÐÐÑÑÑÎÎÎÉÉÉÝÝÝàààâââØØØÙÙÙÜÜÜÕÕÕßßßãããÜÜÜâââÒÒÒÕÕÕÑÑÑ×××ÒÒÒÐÐÐÎÎÎÎÎÎÎÎÎÌÌÌÉÉÉÆÆÆÅÅÅÃÃÃÃÃÃÂÂÂÀÀÀ¿¿¿¾¾¾¼¼¼¸¸¸³³³±±±···ºººººº¸¸¸¸¸¸······¸¸¸ººº»»»¾¾¾ÀÀÀ¼¼¼ÅÅÅÇÇÇÅÅÅÀÀÀÂÂÂÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÇÇÇÌÌÌÎÎÎÐÐÐÎÎÎÊÊÊÌÌÌÍÍÍÍÍÍÍÍÍÌÌÌÊÊÊÉÉÉÉÉÉÆÆÆÅÅÅÆÆÆÆÆÆÅÅÅÃÃÃÂÂÂÊÊÊÎÎÎÒÒÒÔÔÔÐÐÐÇÇÇ»»»´´´¼¼¼¿¿¿ÃÃÃÉÉÉÌÌÌÍÍÍÌÌÌÉÉÉÊÊÊÍÍÍÎÎÎÍÍÍÑÑÑ×××ØØØÔÔÔÒÒÒÌÌÌÝÝÝèèèâââÛÛÛØØØàààØØØØØØ××××××ÕÕÕÔÔÔÒÒÒÑÑÑÕÕÕÕÕÕ×××ØØØÙÙÙÛÛÛÝÝÝßßßÝÝÝÛÛÛÙÙÙÙÙÙÙÙÙØØØ××××××ÕÕÕ×××ÝÝÝàààßßßâââàààÔÔÔÃÃÃÆÆÆÉÉÉÌÌÌÌÌÌÍÍÍÍÍÍÍÍÍÌÌÌÇÇÇÊÊÊÍÍÍÉÉÉÌÌÌÐÐÐÍÍÍ»»»¾¾¾ÂÂÂÃÃü¼¼···¼¼¼ÆÆÆÉÉÉÇÇÇÆÆÆÅÅÅÆÆÆÇÇÇÉÉÉÉÉÉÃÃÃÃÃÃÆÆÆÆÆÆÃÃÃÇÇÇÊÊÊÆÆÆÅÅÅÅÅÅÎÎÎÊÊÊÌÌÌÕÕÕ×××ßßßÔÔÔÛÛÛÝÝÝØØØÔÔÔÑÑÑÒÒÒÕÕÕÙÙÙ×××ÕÕÕÕÕÕÒÒÒÐÐÐÐÐÐÑÑÑÐÐÐÌÌÌÉÉÉÉÉÉÌÌÌÎÎÎÐÐÐÐÐÐÑÑÑÑÑÑÑÑÑÒÒÒÕÕÕØØØÙÙÙÙÙÙÙÙÙÕÕÕÎÎÎÉÉÉÅÅÅÂÂÂÀÀÀÀÀÀÑÑÑØØØÐÐп¿¿¾¾¾ÂÂÂÆÆÆÌÌÌÅÅÅÌÌÌÊÊÊÒÒÒÎÎÎÛÛÛÛÛÛàààæææØØØÐÐÐÍÍÍÍÍÍÒÒÒÕÕÕÍÍÍÊÊÊààààààÛÛÛÕÕÕÙÙÙãããÜÜÜãããæææààààààÒÒÒ×××ÑÑÑ×××ÑÑÑÐÐÐÎÎÎÍÍÍÍÍÍÌÌÌÉÉÉÆÆÆÅÅÅÅÅÅÃÃÃÂÂÂÀÀÀ¿¿¿¾¾¾¾¾¾¸¸¸³³³±±±µµµººº¸¸¸······µµµ······ººº»»»¿¿¿ÀÀÀ»»»ÃÃÃÉÉÉÆÆÆÂÂÂÂÂÂÂÂÂÀÀÀÅÅÅÃÃÃÃÃÃÆÆÆÊÊÊÎÎÎÐÐÐÎÎÎÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÊÊÊÉÉÉÅÅÅÃÃÃÂÂÂÃÃÃÅÅÅÆÆÆÆÆÆÃÃÃÐÐÐÊÊÊÅÅÅÅÅÅÇÇÇÉÉÉÅÅÅ¿¿¿¼¼¼»»»»»»¾¾¾ÂÂÂÅÅÅÅÅÅÃÃÃÉÉÉÍÍÍÒÒÒÔÔÔÕÕÕÛÛÛÜÜÜ×××ÑÑÑÉÉÉÝÝÝíííäääÙÙÙØØØäääÕÕÕÔÔÔÔÔÔÒÒÒÒÒÒÒÒÒÒÒÒÒÒÒÝÝÝÝÝÝÛÛÛØØØØØØÛÛÛâââèèèàààÝÝÝÛÛÛÙÙÙÙÙÙÙÙÙ×××ÔÔÔ×××ÔÔÔÕÕÕÔÔÔÑÑÑØØØÜÜÜÒÒÒÍÍÍÆÆÆÅÅÅÊÊÊÎÎÎÎÎÎÎÎÎÐÐÐÍÍÍÉÉÉÌÌÌÍÍÍÉÉÉÌÌÌÐÐÐÍÍÍÑÑÑÕÕÕØØØÒÒÒÅÅÅ»»»¾¾¾ÇÇÇÂÂÂÅÅÅÇÇÇÇÇÇÃÃÃÃÃÃÆÆÆÊÊÊÆÆÆÃÃÃÇÇÇÅÅž¾¾ÉÉÉÑÑÑÊÊÊÎÎÎ×××çççÜÜÜÒÒÒÔÔÔÍÍÍÒÒÒÔÔÔØØØÛÛÛ×××ÔÔÔØØØÙÙÙÔÔÔÕÕÕÕÕÕÒÒÒÐÐÐÎÎÎÎÎÎÐÐÐÐÐÐÍÍÍÊÊÊÉÉÉÊÊÊÍÍÍÑÑÑÒÒÒÒÒÒÔÔÔÑÑÑÑÑÑÒÒÒ×××ÛÛÛÛÛÛÛÛÛÛÛÛØØØÑÑÑÊÊÊÃÃÃÀÀÀÀÀÀÀÀÀÂÂÂÀÀÀ»»»»»»ÀÀÀÂÂÂÃÃÃÎÎÎÑÑÑÑÑÑÌÌÌÔÔÔÊÊÊÍÍÍÊÊÊÕÕÕÒÒÒÌÌÌÐÐÐÑÑÑÎÎÎÒÒÒÙÙÙÕÕÕÙÙÙëëëæææØØØÐÐÐÔÔÔßßß××׿ææçççâââàààÒÒÒØØØÑÑÑ×××ÑÑÑÎÎÎÍÍÍÍÍÍÍÍÍÌÌÌÉÉÉÆÆÆÅÅÅÅÅÅÃÃÃÂÂÂÀÀÀ¿¿¿¾¾¾¾¾¾ººº³³³±±±µµµººº¸¸¸···µµµµµµ······ººº¼¼¼¿¿¿ÀÀÀÃÃÃÂÂÂÂÂÂÆÆÆÂÂÂÇÇÇÇÇǼ¼¼ÃÃÃÃÃÃÅÅÅÀÀÀÃÃÃÍÍÍÐÐÐÍÍÍÎÎÎÇÇÇÉÉÉÌÌÌÍÍÍÎÎÎÍÍÍÊÊÊÉÉÉÆÆÆÃÃÃÃÃÃÆÆÆÅÅÅÀÀÀÂÂÂÉÉÉÆÆÆÅÅÅÃÃÃÂÂÂÃÃÃÇÇÇÊÊÊÍÍÍÅÅÅÊÊÊÍÍÍÌÌÌÇÇÇÃÃÃÀÀÀ¿¿¿ÆÆÆÆÆÆÌÌÌÒÒÒÙÙÙÝÝÝÜÜÜ×××ÌÌÌÐÐÐÙÙÙâââßßß×××ÔÔÔÕÕÕÝÝÝÛÛÛØØØÕÕÕÔÔÔÒÒÒÑÑÑÐÐÐÙÙÙÙÙÙÛÛÛÝÝÝßßßààààààààà×××ØØØÙÙÙØØØÕÕÕÔÔÔÒÒÒÑÑÑÊÊÊÐÐÐãããßßßÔÔÔ×××ÕÕÕÕÕÕÔÔÔÃÃþ¾¾ÊÊÊÎÎÎÆÆÆÇÇÇÑÑÑÎÎÎÊÊÊÇÇÇÆÆÆÇÇÇÉÉÉÇÇÇÇÇÇÇÇÇÆÆÆÉÉÉÌÌÌÇÇÇÀÀÀÅÅÅÎÎÎÑÑÑÔÔÔÔÔÔÍÍÍÊÊÊÎÎÎÕÕÕ×××ÙÙÙßßßÒÒÒÂÂÂÅÅÅÊÊÊÊÊÊÍÍÍâââ×××ÐÐÐÐÐÐÐÐÐÍÍÍÎÎÎÔÔÔÒÒÒÔÔÔ××××××ÕÕÕÔÔÔÔÔÔÔÔÔÒÒÒÒÒÒÑÑÑÑÑÑÐÐÐÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÐÐÐÐÐÐÑÑÑÔÔÔÕÕÕ×××ÔÔÔÔÔÔÔÔÔ×××ØØØÙÙÙ×××ÔÔÔÜÜÜÙÙÙÒÒÒÒÒÒÛÛÛâââÝÝÝÔÔÔÃÃÿ¿¿¾¾¾ÀÀÀÂÂÂÂÂÂÆÆÆÊÊÊÍÍÍÐÐÐÒÒÒÑÑÑÎÎÎÌÌÌÊÊÊÌÌÌÊÊÊÌÌÌÌÌÌÍÍÍÎÎÎÒÒÒÒÒÒÒÒÒëëëÛÛÛßßßØØØÒÒÒÜÜÜÙÙÙÛÛÛêêêàààêêê×××ÑÑÑÐÐÐÔÔÔÍÍÍÑÑÑÐÐÐÎÎÎÍÍÍÌÌÌÊÊÊÉÉÉÇÇÇÀÀÀ¿¿¿ÃÃÃÃÃþ¾¾ÀÀÀ¿¿¿´´´µµµ¯¯¯³³³ººº···µµµºººººº»»»´´´³³³···»»»¼¼¼ÂÂÂÇÇÇÆÆÆÅÅÅÇÇÇÂÂÂÆÆÆÇÇÇ¿¿¿ÇÇÇÃÃÃÅÅÅÀÀÀÂÂÂÌÌÌÎÎÎÍÍÍÐÐÐÎÎÎÎÎÎÐÐÐÎÎÎÍÍÍÉÉÉÅÅÅÃÃÃÆÆÆÃÃÃÅÅÅÇÇÇÅÅÅÀÀÀÂÂÂÆÆÆÅÅÅÃÃÃÀÀÀÀÀÀÀÀÀÃÃÃÆÆÆÉÉÉÇÇÇÉÉÉÉÉÉÉÉÉÉÉÉÌÌÌÒÒÒ×××ÔÔÔÕÕÕÙÙÙÜÜÜÜÜÜØØØÑÑÑÍÍÍÊÊÊÎÎÎ×××ÜÜÜÙÙÙÒÒÒÐÐÐÒÒÒÑÑÑÒÒÒÒÒÒÑÑÑÎÎÎÍÍÍÐÐÐÒÒÒÕÕÕ×××××××××ØØØØØØÛÛÛÜÜÜÝÝÝÝÝÝÜÜÜØØØÔÔÔÎÎÎÌÌÌÉÉÉÎÎÎÒÒÒæææäääÝÝÝàààÛÛÛ×××ÍÍÍ¿¿¿ÉÉÉÍÍÍÇÇÇÇÇÇÐÐÐÍÍÍÊÊÊÆÆÆÅÅÅÆÆÆÇÇÇÇÇÇÆÆÆÊÊÊÊÊÊÌÌÌÍÍÍÌÌÌÌÌÌÑÑÑ×××ÛÛÛßßßÝÝÝ×××ÑÑÑÒÒÒ×××ØØØÔÔÔÛÛÛÔÔÔÊÊÊÒÒÒÝÝÝâââäääÜÜÜÙÙÙØØØÙÙÙÙÙÙÕÕÕÑÑÑÐÐÐÒÒÒÔÔÔÔÔÔÔÔÔÑÑÑÑÑÑÒÒÒÔÔÔÑÑÑÑÑÑÑÑÑÐÐÐÐÐÐÐÐÐÐÐÐÎÎÎÑÑÑÑÑÑÑÑÑÒÒÒÔÔÔÕÕÕØØØØØØ×××ÕÕÕÕÕÕ×××ØØØÙÙÙÙÙÙÙÙÙÙÙÙÕÕÕÐÐÐÑÑÑÛÛÛææææææßßßÔÔÔÇÇÇ¿¿¿ÂÂÂÉÉÉÊÊÊÊÊÊÊÊÊÎÎÎÐÐÐÑÑÑÑÑÑÎÎÎÍÍÍÊÊÊÊÊÊÌÌÌÌÌÌÍÍÍÎÎÎÍÍÍÉÉÉÅÅÅÃÃÃèèèàààçççÝÝÝÕÕÕÜÜÜßßßäääíííâââêêêÕÕÕÑÑÑÐÐÐÕÕÕÐÐÐÒÒÒÑÑÑÐÐÐÎÎÎÌÌÌÊÊÊÉÉÉÉÉÉÃÃÃÀÀÀÃÃþ¾¾ÀÀÀÀÀÀ······°°°´´´»»»······»»»ººº´´´±±±³³³¸¸¸»»»»»»¾¾¾ÂÂÂÉÉÉÇÇÇÇÇÇÀÀÀÅÅÅÇÇÇÀÀÀÊÊÊÃÃÃÃÃþ¾¾¿¿¿ÊÊÊÎÎÎÍÍÍÐÐÐÑÑÑÑÑÑÑÑÑÐÐÐÌÌÌÇÇÇÃÃÿ¿¿ÅÅÅÅÅÅÅÅÅÆÆÆÅÅÅÀÀÀÂÂÂÅÅÅÃÃÿ¿¿¾¾¾¾¾¾¿¿¿ÂÂÂÃÃÃÉÉÉÅÅÅÀÀÀ¼¼¼»»»»»»ÀÀÀÅÅÅÊÊÊÌÌÌÍÍÍÑÑÑÔÔÔÒÒÒÐÐÐÑÑÑÊÊÊÎÎÎÕÕÕÜÜÜÛÛÛÔÔÔÔÔÔØØØÕÕÕØØØÙÙÙÔÔÔÊÊÊÆÆÆÉÉÉÍÍÍÌÌÌÍÍÍÐÐÐÐÐÐÎÎÎÑÑÑÕÕÕÙÙÙÛÛÛØØØ×××ÕÕÕÒÒÒÎÎÎÊÊÊÉÉÉÐÐÐÑÑÑâââãããßßßâââ×××ÌÌÌÅÅÅÀÀÀÂÂÂÆÆÆÉÉÉÇÇÇÉÉÉÍÍÍÊÊÊÉÉÉÅÅÅÃÃÃÅÅÅÅÅÅÅÅÅÅÅÅÇÇÇÊÊÊÉÉÉÉÉÉÊÊÊÑÑÑÕÕÕ×××ÐÐÐ×××ØØØÔÔÔÑÑÑÔÔÔ××××××ÙÙÙßßßØØØÎÎÎÑÑÑÙÙÙÜÜÜÝÝÝÙÙÙØØØÔÔÔÑÑÑÑÑÑÒÒÒÒÒÒÑÑÑÒÒÒÒÒÒÑÑÑÎÎÎÌÌÌÍÍÍÐÐÐÔÔÔÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÑÑÑÑÑÑÑÑÑÔÔÔÔÔÔÔÔÔÕÕÕ×××ØØØÛÛÛÜÜÜÙÙÙÙÙÙÙÙÙØØØØØØÙÙÙÛÛÛÝÝÝÛÛÛÕÕÕÐÐÐÑÑÑÛÛÛäääçççãããØØØÌÌÌÂÂÂÃÃÃÊÊÊÍÍÍÎÎÎÎÎÎÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÎÎÎÌÌÌÉÉÉÎÎÎÇÇÇÅÅÅÉÉÉÉÉÉÉÉÉÍÍÍÕÕÕßßßÝÝÝäääÜÜÜÑÑÑÕÕÕÝÝÝçççîîîãããêêêÔÔÔÒÒÒÑÑÑÕÕÕÔÔÔÒÒÒÒÒÒÑÑÑÐÐÐÍÍÍÌÌÌÊÊÊÊÊÊÆÆÆÃÃÃÃÃþ¾¾ÂÂÂÃÃúºº···³³³µµµ¾¾¾···ººº»»»ººº°°°´´´ººº¾¾¾¿¿¿»»»»»»ÀÀÀÇÇÇÇÇÇÉÉÉÀÀÀÃÃÃÆÆÆ¿¿¿ÉÉɼ¼¼¾¾¾ÉÉÉÍÍÍÍÍÍÑÑÑÍÍÍÎÎÎÎÎÎÎÎÎÍÍÍÉÉÉÆÆÆÃÃÃÂÂÂÂÂÂÂÂÂÂÂÂÀÀÀ¿¿¿ÂÂÂÅÅÅÂÂÂÀÀÀ¿¿¿¼¼¼¼¼¼¾¾¾¿¿¿¿¿¿ÀÀÀ¿¿¿ÂÂÂÊÊÊÑÑÑÕÕÕÙÙÙÝÝÝÛÛÛÕÕÕÊÊÊÉÉÉÎÎÎÎÎÎÌÌÌÎÎÎÐÐÐÔÔÔÜÜÜããããããÝÝÝÝÝÝâââààààààßßßÙÙÙÒÒÒÍÍÍÍÍÍÎÎÎÌÌÌÐÐÐÑÑÑÐÐÐÌÌÌÌÌÌÎÎÎÒÒÒÑÑÑÎÎÎÐÐÐÔÔÔÕÕÕÕÕÕÕÕÕ×××ßßßÛÛÛçççèèèçççêêêÛÛÛÌÌ̾¾¾ÀÀÀÃÃÃÅÅÅÇÇÇÉÉÉÊÊÊÊÊÊÉÉÉÇÇÇÅÅÅÃÃÃÃÃÃÃÃÃÅÅÅÅÅÅÇÇÇÊÊÊÊÊÊÇÇÇÊÊÊÒÒÒÒÒÒÎÎÎÃÃÃÌÌÌÒÒÒÑÑÑÑÑÑÔÔÔÕÕÕÕÕÕÐÐÐÕÕÕÒÒÒÊÊÊÎÎÎÙÙÙßßßÝÝÝØØØØØØÒÒÒÊÊÊÊÊÊÑÑÑÕÕÕÒÒÒÒÒÒÑÑÑÍÍÍÉÉÉÆÆÆÉÉÉÎÎÎÒÒÒÎÎÎÎÎÎÎÎÎÐÐÐÑÑÑÑÑÑÒÒÒÒÒÒ×××××××××ØØØÙÙÙÛÛÛÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÜÜÜÙÙÙØØØÛÛÛÜÜÜßßßÙÙÙÔÔÔÔÔÔØØØÝÝÝÝÝÝÛÛÛÍÍÍÉÉÉÆÆÆÇÇÇÉÉÉÊÊÊÎÎÎÕÕÕÑÑÑÐÐÐÐÐÐÐÐÐÑÑÑÐÐÐÌÌÌÉÉÉÅÅÅÂÂÂÉÉÉ×××ÛÛÛ×××ÙÙÙãããÛÛÛÜÜÜßßßÙÙÙÒÒÒÔÔÔÝÝÝçççîîîäääêêêÒÒÒÔÔÔÒÒÒ××××××ÔÔÔÔÔÔÒÒÒÑÑÑÎÎÎÍÍÍÌÌÌÊÊÊÇÇÇÅÅÅÅÅÅÃÃÃÀÀÀÅÅÅÅÅźºº···µµµ···ÀÀÀ···¾¾¾»»»ººº±±±¼¼¼ÂÂÂÅÅÅÅÅÅ¿¿¿¼¼¼ÃÃÃÂÂÂÅÅÅÇÇÇÀÀÀºººÃÃÃÀÀÀ¼¼¼¼¼¼ÇÇÇÍÍÍÍÍÍÑÑÑÊÊÊÌÌÌÍÍÍÎÎÎÍÍÍÊÊÊÇÇÇÆÆÆ¿¿¿¿¿¿¿¿¿¼¼¼»»»¿¿¿ÃÃÃÇÇÇÂÂÂÀÀÀ¿¿¿¾¾¾¼¼¼¼¼¼¾¾¾¾¾¾¼¼¼ººº¼¼¼ÇÇÇÎÎÎÎÎÎÎÎÎÑÑÑää䨨ØÇÇÇÃÃÃÍÍÍÉÉÉÀÀÀÃÃÃØØØÜÜÜäääêêêèèèàààÝÝÝàààÝÝÝÛÛÛØØØØØØÜÜÜÝÝÝÜÜÜÛÛÛÙÙÙÝÝÝßßßÜÜÜÕÕÕÎÎÎÍÍÍÎÎÎÕÕÕÒÒÒÔÔÔÛÛÛÝÝÝÝÝÝàààäääæææÝÝÝççççççèèèîîîàààÑÑÑ»»»¿¿¿ÃÃÃÅÅÅÆÆÆÊÊÊÊÊÊÉÉÉÉÉÉÇÇÇÆÆÆÃÃÃÂÂÂÃÃÃÃÃÃÅÅÅÍÍÍÑÑÑÑÑÑÎÎÎÑÑÑÕÕÕÑÑÑÉÉÉÉÉÉÒÒÒÙÙÙÙÙÙ×××ØØØØØØÕÕÕÎÎÎÒÒÒÒÒÒÎÎÎÒÒÒàààèèèæææ×××ÛÛÛÙÙÙÔÔÔÒÒÒ××××××ÒÒÒÒÒÒÐÐÐÌÌÌÆÆÆÅÅÅÆÆÆÌÌÌÐÐÐÍÍÍÍÍÍÎÎÎÐÐÐÑÑÑÑÑÑÒÒÒÒÒÒØØØØØØØØØÙÙÙÛÛÛÜÜÜÝÝÝßßßßßßââââââàààÜÜÜØØØØØØØØØßßßÛÛÛ×××ÕÕÕÕÕÕÕÕÕÔÔÔÒÒÒÌÌÌÉÉÉÊÊÊÎÎÎÐÐÐÎÎÎÐÐÐÔÔÔÒÒÒÑÑÑÐÐÐÑÑÑÒÒÒÑÑÑÍÍÍÉÉÉÉÉÉÉÉÉÒÒÒâââäääÜÜÜÜÜÜäääããããããÜÜÜÛÛÛÛÛÛÜÜÜãããçççëëëæææêêêÔÔÔ×××ÔÔÔÕÕÕ×××ÕÕÕÔÔÔÒÒÒÑÑÑÐÐÐÍÍÍÌÌÌÌÌÌÇÇÇÅÅÅÆÆÆÆÆÆÅÅÅÇÇÇÅÅÅ···¸¸¸ººº¸¸¸ÃÃ÷··ÀÀÀ¼¼¼ººº´´´ÂÂÂÇÇÇÅÅÅÆÆÆÀÀÀ¼¼¼ÃÃþ¾¾ÂÂÂÇÇÇÂÂÂÂÂÂÀÀÀ···¿¿¿¿¿¿ÀÀÀ¼¼¼¾¾¾ÉÉÉÎÎÎÍÍÍÑÑÑÍÍÍÍÍÍÎÎÎÎÎÎÍÍÍÉÉÉÆÆÆÃÃþ¾¾ÀÀÀ¿¿¿¼¼¼»»»¿¿¿ÅÅÅÆÆÆÀÀÀ¿¿¿¾¾¾¾¾¾¼¼¼¼¼¼¼¼¼¾¾¾¿¿¿¸¸¸ºººÇÇÇÒÒÒÕÕÕ×××ÛÛÛÒÒÒÎÎÎÂÂÂÅÅÅÑÑÑÌÌÌÀÀÀÇÇÇàààãããçççêêêãããÙÙÙÕÕÕ×××ØØØÔÔÔÑÑÑÕÕÕÝÝÝãããâââÝÝÝÜÜÜàààääääääâââÝÝÝÜÜÜÜÜÜãããààààààæææãããßßßâââèèèâââÛÛÛããããããäääíííâââ×××¾¾¾¿¿¿ÂÂÂÅÅÅÉÉÉÊÊÊÊÊÊÉÉÉÉÉÉÉÉÉÇÇÇÅÅÅÃÃÃÃÃÃÅÅÅÇÇÇÍÍÍÎÎÎÐÐÐÑÑÑÑÑÑÑÑÑÊÊÊÃÃÃÉÉÉÔÔÔÛÛÛÜÜÜÛÛÛÜÜÜÜÜÜÙÙÙØØØÙÙÙØØØÑÑÑÐÐÐÛÛÛãããÝÝÝØØØÙÙÙØØØÒÒÒÐÐÐÑÑÑÔÔÔÔÔÔÑÑÑÐÐÐÌÌÌÇÇÇÅÅÅÆÆÆÊÊÊÎÎÎÍÍÍÎÎÎÎÎÎÐÐÐÑÑÑÑÑÑÒÒÒÒÒÒ××××××ØØØØØØÙÙÙÜÜÜÝÝÝßßßàààââââââàààÝÝÝÙÙÙ×××ÕÕÕÙÙÙÕÕÕÔÔÔÔÔÔÔÔÔÑÑÑÑÑÑÒÒÒØØØÑÑÑÎÎÎ×××ÜÜÜÛÛÛÒÒÒÎÎÎÒÒÒÒÒÒÒÒÒÔÔÔÒÒÒÑÑÑÎÎÎÌÌÌÍÍÍÍÍÍÕÕÕÝÝÝßßßÛÛÛÝÝÝäääääääää××××××ÜÜÜÜÜÜààààààçççäääêêêÕÕÕÙÙÙÕÕÕÔÔÔÕÕÕÕÕÕÕÕÕÔÔÔÑÑÑÐÐÐÎÎÎÍÍÍÌÌÌÇÇÇÅÅÅÆÆÆÇÇÇÆÆÆÉÉÉÅÅÅ···¸¸¸¼¼¼ºººÆÆÆµµµÃÃü¼¼ººº³³³ÅÅÅÆÆÆÂÂÂÅÅÅ¿¿¿ºººÀÀÀ¼¼¼ÂÂÂÇÇÇ¿¿¿µµµ¾¾¾¾¾¾ÀÀÀ¼¼¼¿¿¿ÌÌÌÎÎÎÍÍÍÑÑÑÍÍÍÎÎÎÎÎÎÎÎÎÍÍÍÉÉÉÆÆÆÃÃÃÀÀÀÅÅÅÅÅÅÀÀÀ¿¿¿ÂÂÂÃÃþ¾¾¼¼¼¼¼¼¼¼¼»»»»»»»»»¼¼¼ººº±±±´´´ÅÅÅÒÒÒÕÕÕØØØÜÜÜØØØÛÛÛÕÕÕ×××ÜÜÜÐÐÐÇÇÇ×××äääãããäääãããÜÜÜÒÒÒÑÑÑÔÔÔÙÙÙ×××ÔÔÔÕÕÕÙÙÙÜÜÜÛÛÛÙÙÙ×××ÙÙÙÝÝÝâââããããããããããããäääâââãããæææâââÙÙÙÝÝÝèèèêêêäääíííëëëêêêïïïçççÜÜÜÃÃÃÀÀÀÀÀÀÆÆÆÊÊÊÌÌÌÊÊÊÊÊÊÊÊÊÊÊÊÉÉÉÇÇÇÅÅÅÃÃÃÆÆÆÉÉÉÉÉÉÉÉÉÌÌÌÐÐÐÑÑÑÍÍÍÉÉÉÇÇÇÇÇÇÑÑÑÙÙÙÛÛÛÙÙÙÛÛÛÙÙÙØØØÔÔÔÒÒÒÒÒÒÍÍÍÌÌÌÙÙÙæææàààÙÙÙ×××ÔÔÔÐÐÐÍÍÍÊÊÊÎÎÎÔÔÔÐÐÐÎÎÎÍÍÍÉÉÉÆÆÆÆÆÆÉÉÉÌÌÌÎÎÎÎÎÎÐÐÐÐÐÐÑÑÑÑÑÑÑÑÑÒÒÒÕÕÕÕÕÕ××××××ØØØÛÛÛÜÜÜÝÝÝàààßßßÝÝÝÝÝÝÜÜÜÛÛÛØØØ××××××ÒÒÒÑÑÑÒÒÒÒÒÒÑÑÑÔÔÔØØØÜÜÜÕÕÕÔÔÔÜÜÜãããßßßØØØÒÒÒÔÔÔÕÕÕ×××ÕÕÕÔÔÔÑÑÑÐÐÐÎÎÎÃÃÃÍÍÍÙÙÙââââââÝÝÝÛÛÛÜÜÜâââæææÕÕÕÔÔÔÙÙÙ×××ÛÛÛÜÜÜâââãããêêê×××ÝÝÝ×××ÑÑÑÒÒÒÕÕÕÔÔÔÒÒÒÑÑÑÐÐÐÍÍÍÌÌÌÌÌÌÊÊÊÅÅÅÅÅÅÆÆÆÅÅÅÉÉÉÆÆÆ¸¸¸¸¸¸¿¿¿»»»ÉÉɵµµÆÆÆ¼¼¼ººº´´´ÇÇÇÉÉÉÃÃÃÉÉɸ¸¸¾¾¾¾¾¾ÃÃÃÉÉÉÂÂÂÀÀÀ¿¿¿µµµ¿¿¿¾¾¾ÀÀÀ¾¾¾ÀÀÀÍÍÍÐÐÐÍÍÍÐÐÐÊÊÊÌÌÌÍÍÍÎÎÎÍÍÍÊÊÊÇÇÇÆÆÆÃÃÃÉÉÉÊÊÊÆÆÆÃÃÃÅÅÅÃÃÿ¿¿»»»»»»»»»ººººººººº»»»»»»µµµ¯¯¯³³³ÆÆÆÔÔÔÔÔÔÒÒÒÔÔÔÕÕÕÝÝÝÛÛÛØØØØØØÊÊÊÌÌÌäääãããâââàààßßßØØØÒÒÒÔÔÔÛÛÛ×××ØØØØØØØØØ×××ØØØÙÙÙÛÛÛØØØØØØÙÙÙÙÙÙÛÛÛÛÛÛÙÙÙØØØÙÙÙØØØÛÛÛàààÛÛÛÔÔÔÛÛÛèèèëëëæææïïïëëëæææèèèÝÝÝÔÔÔÇÇÇÀÀÀ¿¿¿ÇÇÇÍÍÍÌÌÌÊÊÊÌÌÌÊÊÊÌÌÌÊÊÊÉÉÉÅÅÅÅÅÅÇÇÇÊÊÊÍÍÍÊÊÊÍÍÍÔÔÔ×××ÑÑÑÑÑÑÔÔÔÒÒÒÛÛÛàààÝÝÝÙÙÙ×××ÔÔÔÑÑÑÕÕÕÔÔÔÒÒÒÎÎÎÌÌÌÜÜÜèèèããã××××××ÛÛÛßßßÛÛÛÑÑÑÍÍÍÐÐÐÎÎÎÎÎÎÎÎÎÌÌÌÉÉÉÇÇÇÉÉÉÊÊÊÎÎÎÐÐÐÐÐÐÐÐÐÐÐÐÑÑÑÑÑÑÑÑÑÕÕÕÕÕÕÕÕÕÕÕÕØØØÙÙÙÛÛÛÜÜÜàààÝÝÝÛÛÛÙÙÙÛÛÛÜÜÜÛÛÛÙÙÙØØØÒÒÒÐÐÐÑÑÑÑÑÑÐÐÐÕÕÕÜÜÜÔÔÔÔÔÔØØØßßßàààÜÜÜÛÛÛÜÜÜÔÔÔÕÕÕØØØ×××ÔÔÔÑÑÑÐÐÐÑÑÑÐÐÐ×××ÜÜÜÜÜÜÙÙÙÙÙÙÛÛÛÜÜÜæææíííÜÜÜÙÙÙÜÜÜ×××ÝÝÝàààßßßãããëëëØØØàààØØØÐÐÐÐÐÐÕÕÕÔÔÔÒÒÒÑÑÑÐÐÐÍÍÍÌÌÌÌÌÌÌÌÌÆÆÆÅÅÅÃÃÃÃÃÃÉÉÉÆÆÆººº¸¸¸ÀÀÀ»»»ÊÊʵµµÇÇǼ¼¼ººº···ÌÌÌÍÍÍÉÉÉÎÎÎÇÇÇ»»»¾¾¾Â¿¿¿ÀÀÀÉÉÉÆÆÆ¾¾¾ÀÀÀÆÆÆ¼¼¼¿¿¿ÉÉɺººÕÕÕÎÎÎÕÕÕÐÐÐÌÌÌÍÍÍÇÇÇÉÉÉÑÑÑÑÑÑÍÍÍÍÍÍÌÌÌÌÌÌÎÎÎÒÒÒÒÒÒÎÎÎÅÅž¾¾¸¸¸···¸¸¸ººº»»»ºººµµµ³³³¬¬¬°°°ÂÂÂÑÑÑÐÐÐÍÍÍÐÐÐÑÑÑØØØÛÛÛÑÑÑÔÔÔÎÎÎÊÊÊÝÝÝçççÛÛÛãããÜÜÜÝÝÝ×××ÍÍÍÒÒÒÎÎÎÕÕÕÛÛÛßßßâââßßßÙÙÙ×××ÕÕÕÝÝÝÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÜÜÜßßßÙÙÙÙÙÙÙÙÙÛÛÛÜÜÜßßßâââäääãããæææíííîîîççççççâââÔÔÔÕÕÕÎÎÎÂÂÂÀÀÀÌÌÌÎÎÎÌÌÌÎÎÎÊÊÊÊÊÊÉÉÉÇÇÇÇÇÇÇÇÇÆÆÆÆÆÆÊÊÊÐÐÐÔÔÔÔÔÔÒÒÒÔÔÔÔÔÔÔÔÔàààÙÙÙÕÕÕÕÕÕÕÕÕÒÒÒÒÒÒÔÔÔÒÒÒÎÎÎÐÐÐÍÍÍÆÆÆãããââââââßßßàààëëëíííÛÛÛÍÍÍÌÌÌÌÌÌÑÑÑÐÐÐÐÐÐÎÎÎÍÍÍÌÌÌÉÉÉÉÉÉÐÐÐÉÉÉÇÇÇÎÎÎÒÒÒÐÐÐÍÍÍÍÍÍÑÑÑÔÔÔÕÕÕ×××ÙÙÙÛÛÛÝÝÝâââÝÝÝÜÜÜÙÙÙÙÙÙÛÛÛÛÛÛÙÙÙ××××××ÕÕÕÑÑÑÎÎÎÍÍÍÎÎÎÒÒÒÕÕÕÝÝÝÔÔÔØØØààààààßßßßßßÛÛÛÛÛÛÜÜÜÙÙÙÕÕÕÕÕÕØØØÕÕÕÎÎÎÊÊÊÔÔÔÝÝÝÝÝÝÜÜÜÜÜÜÜÜÜÛÛÛãããÝÝÝãããèèèàààÜÜÜßßßÝÝÝäääâââèèèèèèÛÛÛÒÒÒÒÒÒÒÒÒÕÕÕ×××××××××ÔÔÔÑÑÑÍÍÍÊÊÊÂÂÂÅÅÅÆÆÆÉÉÉÉÉÉÇÇÇÆÆÆÅÅž¾¾ÆÆÆÍÍÍÅÅż¼¼ÃÃÃÆÆÆ¾¾¾¸¸¸ÊÊÊÊÊÊÌÌÌÍÍÍÉÉÉÍÍÍÎÎÎÆÆÆ¿¿¿ÂÂÂÆÆÆÅÅÅ¿¿¿¼¼¼ÆÆÆ¾¾¾¾¾¾ÃÃ÷··ÑÑÑÌÌÌÒÒÒÌÌÌÌÌÌÑÑÑÎÎÎÍÍÍÑÑÑÎÎÎÊÊÊÎÎÎÌÌÌÍÍÍÐÐÐÒÒÒÒÒÒÎÎÎÇÇÇÂÂÂÅÅÅÃÃÃÂÂÂÀÀÀÀÀÀ¼¼¼¸¸¸´´´¯¯¯³³³ÆÆÆÒÒÒÊÊÊÉÉÉÐÐÐÐÐÐÔÔÔ×××ÑÑÑÕÕÕÐÐÐÇÇÇÔÔÔØØØÛÛÛÝÝÝÕÕÕØØØÔÔÔÍÍÍÑÑÑÌÌÌÍÍÍÎÎÎÐÐÐÐÐÐÎÎÎÍÍÍÌÌÌÌÌÌÜÜÜÝÝÝÜÜÜÙÙÙ××××××ÔÔÔÒÒÒØØØØØØØØØÙÙÙÛÛÛÝÝÝßßßàààâââàààäääççççççêêêæææÙÙÙØØØÕÕÕÉÉÉÂÂÂÊÊÊÌÌÌÉÉÉÉÉÉÊÊÊÊÊÊÉÉÉÇÇÇÆÆÆÆÆÆÇÇÇÉÉÉÑÑÑÌÌÌÊÊÊÎÎÎÑÑÑÒÒÒØØØàààßßßÙÙÙÕÕÕ××××××ÔÔÔÒÒÒÕÕÕÔÔÔÑÑÑÐÐÐÌÌÌÅÅÅââââââàààãããâââçççççç×××ÍÍÍÍÍÍÍÍÍÑÑÑÐÐÐÎÎÎÍÍÍÌÌÌÌÌÌÌÌÌÌÌÌÒÒÒÍÍÍÊÊÊÍÍÍÐÐÐÎÎÎÍÍÍÐÐÐÌÌÌÐÐÐÔÔÔÔÔÔÔÔÔÕÕÕÜÜÜãããÝÝÝÜÜÜÛÛÛÙÙÙÙÙÙØØØ×××ÕÕÕÐÐÐÎÎÎÍÍÍÎÎÎÑÑÑÔÔÔ×××ØØØØØØÑÑÑØØØãããâââÝÝÝÙÙÙÒÒÒàààâââßßßÛÛÛÙÙÙÙÙÙÔÔÔÍÍÍÐÐÐØØØßßßßßßßßßâââãããâââÝÝÝØØØÝÝÝãããÝÝÝÜÜÜââââââäääßßßâââÝÝÝÐÐÐÇÇÇÌÌÌÍÍÍÑÑÑÒÒÒÒÒÒÔÔÔÔÔÔÒÒÒÒÒÒÑÑÑÇÇÇÃÃÿ¿¿¾¾¾¾¾¾ÃÃÃÇÇÇÌÌÌ···ÃÃÃÎÎÎÇÇÇ»»»¾¾¾ÃÃþ¾¾ºººÌÌÌÊÊÊÊÊÊÌÌÌÆÆÆÊÊÊÌÌÌÌÌÌ¿¿¿ÂÂÂÅÅÅÀÀÀÃÃúººÆÆÆ¿¿¿»»»¾¾¾´´´ÍÍÍÉÉÉÐÐÐÉÉÉÊÊÊÔÔÔÔÔÔÑÑÑÑÑÑÊÊÊÇÇÇÎÎÎÊÊÊÍÍÍÒÒÒÔÔÔÒÒÒÎÎÎÊÊÊÉÉÉÌÌÌÊÊÊÇÇÇÆÆÆÅÅÅÀÀÀ»»»¸¸¸¯¯¯°°°ÇÇÇÒÒÒÆÆÆÆÆÆÒÒÒÑÑÑÑÑÑÒÒÒÍÍÍÐÐÐÍÍÍÉÉÉÑÑÑÔÔÔÜÜÜÛÛÛÒÒÒÔÔÔÒÒÒÐÐÐÔÔÔÐÐÐÑÑÑÎÎÎÊÊÊÉÉÉÉÉÉÌÌÌÍÍÍÍÍÍÑÑÑØØØÛÛÛØØØÙÙÙßßßßßßÙÙÙÛÛÛÛÛÛÛÛÛÜÜÜÜÜÜÝÝÝßßßßßßâââÜÜÜßßßâââäääëëëëëëâââ×××ÛÛÛÐÐÐÅÅÅÇÇÇÌÌÌÉÉÉÉÉÉÉÉÉÊÊÊÊÊÊÇÇÇÅÅÅÆÆÆÉÉÉÍÍÍÒÒÒÅÅÅÀÀÀÌÌÌÔÔÔÕÕÕÜÜÜèèèÝÝÝØØØÕÕÕØØØØØØÕÕÕÔÔÔÕÕÕÔÔÔÔÔÔÎÎÎÊÊÊÃÃÃàààããããããêêêããããããàààÒÒÒÌÌÌÎÎÎÐÐÐÑÑÑÎÎÎÍÍÍÊÊÊÊÊÊÌÌÌÎÎÎÐÐÐ×××ÑÑÑÍÍÍÍÍÍÍÍÍÍÍÍÎÎÎÑÑÑÐÐÐÒÒÒ×××ÒÒÒÊÊÊÊÊÊÒÒÒÙÙÙÛÛÛÜÜÜÜÜÜÛÛÛØØØÕÕÕÒÒÒÒÒÒÍÍÍÌÌÌÊÊÊÍÍÍÒÒÒ×××ØØØ×××ÜÜÜ×××ßßßêêêêêêèèèæææßßßäääæææäääàààÝÝÝÜÜÜ×××ÑÑÑÑÑÑ×××ÛÛÛÜÜÜßßßæææèèèèèèàààÛÛÛÝÝÝâââÝÝÝÝÝÝäääçççêêêäääæææâââÒÒÒÉÉÉÌÌÌÍÍÍÑÑÑÑÑÑÐÐÐÐÐÐÑÑÑÑÑÑÒÒÒÔÔÔÍÍÍÉÉÉÃÃÿ¿¿ÀÀÀÆÆÆÎÎÎÔÔÔ»»»ÆÆÆÕÕÕÑÑÑÂÂÂÀÀÀÇÇÇÅÅż¼¼ÎÎÎÌÌÌÊÊÊÊÊÊÅÅÅÇÇÇÉÉÉÎÎξ¾¾ÂÂÂÃÃþ¾¾ÉÉɸ¸¸ÉÉÉÃÃû»»»»»µµµÊÊÊÉÉÉÎÎÎÇÇÇÊÊÊÒÒÒÒÒÒÑÑÑÑÑÑÌÌÌÆÆÆÊÊÊÆÆÆÍÍÍÕÕÕ×××ÔÔÔÐÐÐÍÍÍÍÍÍÉÉÉÇÇÇÆÆÆÆÆÆÆÆÆÅÅÅÀÀÀ¾¾¾¬¬¬¬¬¬ÃÃÃÒÒÒÇÇÇÌÌÌ×××ÐÐÐÐÐÐÌÌÌÅÅÅÃÃÃÆÆÆÍÍÍØØØÝÝÝÙÙÙÙÙÙ×××ÔÔÔÑÑÑÐÐÐÔÔÔ×××ØØØÒÒÒÍÍÍÌÌÌÍÍÍÑÑÑÒÒÒÔÔÔÎÎÎØØØÙÙÙÒÒÒÔÔÔÛÛÛÛÛÛÒÒÒâââàààßßßÝÝÝßßßàààâââããããããßßßàààâââàààæææëëëçççÔÔÔÛÛÛÒÒÒÃÃÃÆÆÆÍÍÍÍÍÍÌÌÌÇÇÇÊÊÊÊÊÊÇÇÇÅÅÅÆÆÆÌÌÌÑÑÑÌÌÌÀÀÀ¾¾¾ÉÉÉÕÕÕÙÙÙßßßçççÜÜÜØØØ×××ÙÙÙÙÙÙÕÕÕÔÔÔÔÔÔÔÔÔÕÕÕÊÊÊÇÇÇÅÅÅàààæææêêêñññçççãããßßßÒÒÒÌÌÌÎÎÎÎÎÎÐÐÐÎÎÎÌÌÌÉÉÉÊÊÊÍÍÍÑÑÑÔÔÔ×××ÔÔÔÑÑÑÐÐÐÎÎÎÍÍÍÎÎÎÐÐÐÑÑÑÐÐÐÒÒÒÎÎÎÆÆÆÆÆÆÍÍÍÐÐÐØØØÛÛÛÜÜÜÛÛÛ×××ÒÒÒÐÐÐÐÐÐÐÐÐÌÌÌÉÉÉÌÌÌÑÑÑÕÕÕÕÕÕÔÔÔ×××ÐÐÐÒÒÒÛÛÛßßßæææëëëçççääääääãããâââàààßßßÜÜÜÙÙÙÎÎÎÒÒÒÕÕÕ×××ÜÜÜæææëëëëëëêêêæææääääääãããâââçççíííëëëèèèíííëëëÛÛÛÐÐÐÎÎÎÍÍÍÔÔÔÒÒÒÑÑÑÎÎÎÍÍÍÌÌÌÌÌÌÌÌÌÊÊÊÉÉÉÇÇÇÆÆÆÇÇÇÊÊÊÍÍÍÎÎÎÃÃÃÆÆÆÒÒÒÒÒÒÅÅÅÅÅÅÌÌÌÇÇÇÂÂÂÒÒÒÎÎÎÌÌÌÊÊÊÅÅÅÇÇÇÇÇÇÐÐп¿¿ÀÀÀÅÅž¾¾ÌÌ̺ººÌÌÌÅÅÅ»»»¼¼¼¼¼¼ÌÌÌÌÌÌÐÐÐÉÉÉÌÌÌÐÐÐÍÍÍÍÍÍÒÒÒÐÐÐÇÇÇÆÆÆÃÃÃÌÌÌÕÕÕÙÙÙÕÕÕÑÑÑÎÎÎÎÎÎÉÉÉÇÇÇÆÆÆÆÆÆÇÇÇÇÇÇÅÅÅÃÃí­­¯¯¯ÂÂÂÑÑÑÍÍÍÐÐÐÒÒÒÆÆÆÉÉɾ¾¾ººº¿¿¿ÌÌÌ×××ÝÝÝÒÒÒÕÕÕØØØÒÒÒÌÌÌÌÌÌÐÐÐØØØÕÕÕÑÑÑÍÍÍÌÌÌÎÎÎÑÑÑÒÒÒÒÒÒÜÜÜãããäääÝÝÝßßßêêêëëëæææãããàààÝÝÝÛÛÛÛÛÛÝÝÝàààãããäääâââææææææÜÜÜÝÝÝçççêêê×××ÜÜÜÑÑÑÂÂÂÅÅÅÌÌÌÌÌÌÊÊÊÇÇÇÉÉÉÊÊÊÇÇÇÆÆÆÇÇÇÎÎÎÔÔÔÅÅÅÀÀÀ¿¿¿ÃÃÃÎÎÎÙÙÙâââãããÜÜÜØØØ×××ÙÙÙÙÙÙÕÕÕÒÒÒÔÔÔÒÒÒÔÔÔÅÅÅÉÉÉÊÊÊàààèèèñññóóóèèèæææâââÔÔÔÍÍÍÍÍÍÌÌÌÎÎÎÍÍÍÌÌÌÊÊÊÌÌÌÎÎÎÒÒÒÕÕÕÔÔÔÕÕÕÕÕÕÒÒÒÑÑÑÐÐÐÎÎÎÍÍÍÊÊÊÆÆÆÊÊÊÍÍÍÇÇÇÌÌÌÒÒÒÐÐÐÔÔÔ×××ÙÙÙÙÙÙÕÕÕÑÑÑÎÎÎÎÎÎÐÐÐÊÊÊÆÆÆÇÇÇÍÍÍÒÒÒÔÔÔÔÔÔÙÙÙÒÒÒÔÔÔÙÙÙÝÝÝêêêòòòïïïçççæææäääâââßßßÜÜÜÛÛÛÜÜÜÐÐÐÒÒÒÕÕÕÕÕÕÜÜÜæææëëëëëëëëëèèèççççççæææäääèèèñññæææâââæææäääÕÕÕÌÌÌÍÍÍÍÍÍÒÒÒÑÑÑÐÐÐÎÎÎÌÌÌÇÇÇÆÆÆÃÃÃÂÂÂÃÃÃÅÅÅÆÆÆÆÆÆÅÅÅÃÃÃÃÃÃÇÇǼ¼¼ÅÅÅÊÊÊÀÀÀÂÂÂÉÉÉÂÂÂÆÆÆÕÕÕÑÑÑÎÎÎÍÍÍÆÆÆÊÊÊÊÊÊÐÐÐÅÅÅÀÀÀÊÊʾ¾¾ÊÊÊ»»»ÍÍÍÅÅÅ»»»¿¿¿ÆÆÆÐÐÐÐÐÐÑÑÑÌÌÌÎÎÎÐÐÐÌÌÌÌÌÌÒÒÒÐÐÐÇÇÇÆÆÆÃÃÃÌÌÌÔÔÔØØØÕÕÕÐÐÐÎÎÎÎÎÎÎÎÎÍÍÍÊÊÊÉÉÉÉÉÉÇÇÇÅÅÅÃÃñ±±¸¸¸ÆÆÆÐÐÐÎÎÎÎÎÎÉÉɼ¼¼¿¿¿»»»¼¼¼···»»»ÇÇÇÌÌÌÑÑÑÌÌÌÎÎÎ×××ÑÑÑÉÉÉÊÊÊÊÊÊÒÒÒÑÑÑÐÐÐÎÎÎÎÎÎÐÐÐÑÑÑÑÑÑÑÑÑÊÊÊÐÐÐÑÑÑÎÎÎÒÒÒÜÜÜàààÝÝÝÝÝÝÛÛÛØØØÕÕÕÕÕÕØØØÛÛÛÝÝÝâââàààççççççÜÜÜÙÙÙâââæææßßßÝÝÝÍÍÍ¿¿¿ÃÃÃÉÉÉÇÇÇÅÅÅÆÆÆÇÇÇÉÉÉÉÉÉÉÉÉÌÌÌÐÐÐÕÕÕÅÅÅÃÃÃÀÀÀ¾¾¾ÅÅÅÒÒÒÝÝÝâââßßßÙÙÙÕÕÕØØØ×××ÒÒÒÑÑÑÑÑÑÐÐÐÐÐÐÂÂÂÑÑÑ×××àààçççõõõñññçççäääâââÔÔÔÍÍÍÌÌÌÊÊÊÍÍÍÌÌÌÌÌÌÍÍÍÎÎÎÐÐÐÒÒÒÔÔÔÑÑÑÔÔÔÕÕÕÕÕÕÔÔÔÒÒÒÎÎÎÉÉÉÉÉÉÅÅÅÍÍÍÒÒÒÊÊÊÌÌÌÑÑÑÊÊÊÎÎÎÒÒÒÕÕÕØØØ×××ÒÒÒÐÐÐÍÍÍÌÌÌÇÇÇÃÃÃÅÅÅÊÊÊÐÐÐÔÔÔÕÕÕÌÌÌÇÇÇÌÌÌÐÐÐÒÒÒÜÜÜàààÙÙÙëëëèèèçççäääßßßØØØ×××ØØØÕÕÕÙÙÙÛÛÛÛÛÛÝÝÝäääèèèèèèæææçççäääæææèèèçççèèèòòòèèèââââââÜÜÜÎÎÎÉÉÉÐÐÐÔÔÔÐÐÐÎÎÎÎÎÎÍÍÍÌÌÌÉÉÉÆÆÆÆÆÆÅÅÅÅÅÅÅÅÅÃÃÃÅÅÅÆÆÆÇÇÇÇÇÇÎÎλ»»ÀÀÀÊÊÊÂÂÂÅÅÅÌÌÌÃÃÃÆÆÆ×××ÑÑÑÎÎÎÎÎÎÉÉÉÍÍÍÎÎÎÑÑÑÍÍÍÃÃÃÐÐп¿¿ÆÆÆ»»»ÊÊÊÀÀÀºººÂÂÂÎÎÎÒÒÒÒÒÒÒÒÒÌÌÌÒÒÒÕÕÕÑÑÑÎÎÎÑÑÑÎÎÎÇÇÇÉÉÉÆÆÆÌÌÌÑÑÑÒÒÒÑÑÑÎÎÎÎÎÎÎÎÎÎÎÎÌÌÌÉÉÉÆÆÆÆÆÆÅÅÅ¿¿¿°°°ÂÂÂÍÍÍÍÍÍÍÍÍÇÇÇÀÀÀ¿¿¿¼¼¼»»»ÀÀÀººº¼¼¼ÉÉÉÉÉÉÍÍÍÎÎÎÍÍÍÕÕÕÑÑÑÐÐÐÑÑÑÉÉÉÍÍÍÎÎÎÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÑÑÑÒÒÒÑÑÑÒÒÒÑÑÑÐÐÐÐÐÐÐÐÐÐÐÐÎÎÎ××××××ÕÕÕÕÕÕÕÕÕ×××ØØØÙÙÙÜÜÜØØØßßßäääßßßÜÜÜßßßÝÝÝäääÙÙÙÅÅÅ»»»ÃÃÃÉÉÉÅÅÅÅÅÅÅÅÅÆÆÆÇÇÇÉÉÉÌÌÌÎÎÎÒÒÒÔÔÔÃÃÃÂÂÂÂÂÂÂÂÂÃÃÃÇÇÇÒÒÒÝÝÝàààÙÙÙÕÕÕÕÕÕÕÕÕÑÑÑÎÎÎÐÐÐÌÌÌÍÍÍÂÂÂÝÝÝäääàààâââòòòèèèààààààÝÝÝÑÑÑÊÊÊÌÌÌÌÌÌÊÊÊÌÌÌÎÎÎÐÐÐÑÑÑÑÑÑÑÑÑÐÐÐÐÐÐÒÒÒÔÔÔÔÔÔÕÕÕÕÕÕÐÐÐÆÆÆÉÉÉÉÉÉÙÙÙÜÜÜÌÌÌÇÇÇÍÍÍÆÆÆÊÊÊÍÍÍÑÑÑÕÕÕØØØÕÕÕÑÑÑÍÍÍÉÉÉÇÇÇÅÅÅÅÅÅÇÇÇÌÌÌÎÎÎÑÑÑÐÐÐÎÎÎÒÒÒ×××ÙÙÙâââäääÜÜÜêêêèèèèèèêêêãããÙÙÙÕÕÕ×××ÙÙÙßßßâââÝÝÝÛÛÛÜÜÜÝÝÝÜÜÜæææêêêèèèêêêîîîèèèçççñññîîîæææãããÝÝÝÐÐÐÌÌÌÒÒÒØØØÑÑÑÑÑÑÎÎÎÍÍÍÌÌÌÊÊÊÊÊÊÊÊÊÊÊÊÇÇÇÆÆÆÅÅÅÆÆÆÊÊÊÐÐÐÒÒÒÑÑѼ¼¼ÆÆÆÒÒÒÇÇÇÆÆÆÐÐÐÉÉÉÅÅÅÔÔÔÐÐÐÎÎÎÍÍÍÉÉÉÎÎÎÑÑÑÔÔÔÔÔÔÅÅÅÕÕÕ¿¿¿ÃÃúººÇÇǾ¾¾¸¸¸ÃÃÃÒÒÒÔÔÔÔÔÔÒÒÒÍÍÍÔÔÔÛÛÛØØØÒÒÒÐÐÐÊÊÊÇÇÇÍÍÍÉÉÉÌÌÌÎÎÎÎÎÎÍÍÍÍÍÍÎÎÎÐÐÐÇÇÇÅÅÅÂÂÂÀÀÀÀÀÀÀÀÀ¾¾¾¼¼¼ªªªÅÅÅÐÐÐÌÌÌÊÊÊÃÃÿ¿¿ÇÇÇÀÀÀ¿¿¿ÅÅż¼¼¾¾¾ÍÍÍÎÎÎÕÕÕ×××ÐÐÐ×××ÕÕÕØØØÜÜÜÍÍÍÌÌÌÉÉÉÊÊÊÌÌÌÊÊÊÉÉÉÉÉÉÌÌÌÎÎÎÍÍÍÍÍÍÎÎÎÑÑÑÑÑÑÎÎÎÎÎÎÎÎÎÔÔÔÕÕÕ×××ØØØÙÙÙÙÙÙØØØØØØØØØÐÐÐÕÕÕââââââàààÝÝÝØØØãããÔÔÔ¼¼¼···ÅÅÅÊÊÊÇÇÇÉÉÉÅÅÅÅÅÅÇÇÇÊÊÊÍÍÍÑÑÑÒÒÒÔÔÔ¿¿¿¾¾¾ÃÃÃÌÌÌÇÇÇÀÀÀÇÇÇ×××âââÛÛÛÕÕÕÔÔÔÒÒÒÎÎÎÍÍÍÐÐÐÊÊÊÌÌÌÃÃÃçççîîîàààÝÝÝîîîâââÛÛÛÛÛÛÛÛÛÎÎÎÉÉÉÍÍÍÎÎÎÉÉÉÌÌÌÎÎÎÒÒÒÒÒÒÒÒÒÐÐÐÎÎÎÐÐÐÒÒÒÒÒÒÑÑÑÔÔÔ×××ÐÐÐÆÆÆÀÀÀÇÇÇßßßãããÌÌÌÆÆÆÐÐÐÍÍÍÇÇÇÊÊÊÎÎÎÔÔÔØØØ×××ÒÒÒÍÍÍÊÊÊÊÊÊÉÉÉÇÇÇÆÆÆÆÆÆÇÇÇÉÉÉÑÑÑÎÎÎÒÒÒÕÕÕØØØäääêêêâââääääääêêêîîîèèèÝÝÝØØØØØØÛÛÛàààãããÝÝÝ×××ÔÔÔÒÒÒÐÐÐíííñññïïïïïïóóóëëëæææîîîëëëääääääàààÑÑÑÊÊÊÐÐÐÒÒÒØØØÕÕÕÑÑÑÍÍÍÊÊÊÊÊÊÌÌÌÍÍÍÃÃÃÂÂÂÂÂÂÂÂÂÆÆÆÊÊÊÐÐÐÒÒÒÊÊʸ¸¸ÆÆÆÔÔÔÅÅÅÀÀÀÌÌÌÇÇÇÂÂÂÒÒÒÎÎÎÌÌÌÍÍÍÉÉÉÐÐÐÑÑÑÔÔÔ×××ÎÎÎÃÃÃÑÑѺºº¸¸¸ÇÇÇÀÀÀºººÑÑÑÐÐÐ×××ÔÔÔÒÒÒÐÐÐÑÑÑÔÔÔÕÕÕÎÎÎÎÎÎÎÎÎÆÆÆÐÐÐÆÆÆÎÎÎÑÑÑÍÍÍÊÊÊÎÎÎÑÑÑÐÐÐÇÇÇ¿¿¿¿¿¿¾¾¾µµµ···¸¸¸°°°ÎÎÎÕÕÕÑÑÑÀÀÀºººÂÂÂÇÇÇÃÃÿ¿¿»»»»»»ÂÂÂÉÉÉÍÍÍÐÐÐÔÔÔÔÔÔÍÍÍÔÔÔÒÒÒÕÕÕÙÙÙÌÌÌÌÌÌÑÑÑÌÌÌÌÌÌÊÊÊÂÂÂÀÀÀÅÅÅÀÀÀÅÅÅÆÆÆÊÊÊÊÊÊÊÊÊÇÇÇÅÅÅÃÃÃÆÆÆÍÍÍÐÐÐÇÇÇÃÃÃÉÉÉÑÑÑ×××ÔÔÔÙÙÙÒÒÒ×××èèèçççÛÛÛÝÝÝãããßßßÙÙÙÒÒÒÍÍÍÉÉÉÆÆÆÃÃÃÂÂÂÃÃÃÆÆÆÉÉÉÍÍÍÔÔÔÛÛÛßßßÅÅÅ¿¿¿ÃÃÃÇÇÇÅÅÅÉÉÉÍÍÍÆÆÆØØØÜÜÜÑÑÑÑÑÑÒÒÒÐÐÐÕÕÕÉÉÉÌÌ̼¼¼ÃÃÃàààîîîãããàààëëëØØØÒÒÒÕÕÕÒÒÒÔÔÔÔÔÔÆÆÆÅÅÅÐÐÐÍÍÍÌÌÌÊÊÊÍÍÍÒÒÒØØØÛÛÛÎÎÎÐÐÐÑÑÑÔÔÔÍÍÍÔÔÔÛÛÛÀÀÀÅÅÅÎÎÎÜÜÜÙÙÙÊÊÊÊÊÊÑÑÑÍÍÍÉÉÉÉÉÉÌÌÌÑÑÑ××××××ÑÑÑÌÌÌÉÉÉÌÌÌÊÊÊÅÅÅÍÍÍÉÉÉÇÇÇêêêÎÎÎÍÍÍÑÑÑØØØÙÙÙÙÙÙßßßççççççïïïòòòêêêßßßÙÙÙ×××ÕÕÕÜÜÜÜÜÜÙÙÙÕÕÕÑÑÑÑÑÑÔÔÔ×××ØØØãããíííòòòóóóïïïäääÙÙÙíííãããêêêçççÍÍÍÆÆÆÑÑÑÎÎÎÑÑÑ×××ØØØÑÑÑÍÍÍÍÍÍÌÌÌÉÉÉÕÕÕÒÒÒÊÊÊÊÊÊÉÉÉÑÑÑÜÜÜÍÍ;¾¾ÂÂÂÆÆÆØØØÅÅÅÉÉÉÍÍÍ¿¿¿ÀÀÀ×××ØØØÎÎÎÐÐÐÔÔÔÑÑÑÑÑÑÔÔÔÔÔÔÊÊÊÊÊÊÕÕÕ¼¼¼ÂÂÂÇÇÇÅÅż¼¼ÊÊÊÒÒÒ×××ÔÔÔÒÒÒÐÐÐØØØØØØÛÛÛØØØÜÜÜÙÙÙÇÇÇÇÇÇÎÎÎÎÎÎÍÍÍÊÊÊÊÊÊÍÍÍÌÌÌÉÉÉÀÀÀÉÉÉ×××ÜÜÜ×××ÔÔÔ××××××ÙÙÙÎÎÎÇÇÇÉÉÉÇÇÇÀÀÀ¾¾¾¿¿¿ÊÊÊÆÆÆÅÅÅÉÉÉÎÎÎÎÎÎÑÑÑÔÔÔ¼¼¼¾¾¾ÊÊÊÍÍÍÑÑÑÕÕÕÇÇÇÃÃÃÊÊÊÉÉÉÊÊÊÆÆÆ¸¸¸···»»»»»»»»»¼¼¼¾¾¾ÀÀÀÂÂÂÂÂÂÃÃÃÃÃÃÂÂÂÇÇÇÉÉÉÅÅÅÂÂÂÇÇÇÎÎÎÑÑÑÕÕÕÜÜÜÕÕÕ×××çççæææÙÙÙÛÛÛêêêææææææçççÙÙÙÉÉÉÅÅÅÍÍÍÅÅÅÆÆÆÇÇÇÊÊÊÍÍÍÑÑÑØØØÜÜÜØØØÎÎÎÌÌÌÍÍÍÌÌÌÍÍÍÊÊÊÀÀÀÛÛÛâââØØØ×××ÔÔÔÐÐÐÔÔÔÌÌÌÊÊÊÂÂÂÉÉÉßßßêêêäääàààæææäääÛÛÛÙÙÙÔÔÔ×××ÙÙÙÎÎÎÌÌÌÍÍÍÍÍÍÍÍÍÍÍÍÎÎÎÑÑÑÔÔÔÕÕÕÙÙÙÙÙÙØØØØØØÊÊÊÊÊÊÕÕÕÂÂÂÇÇÇÇÇÇÌÌÌÌÌÌÇÇÇÌÌÌÍÍÍÅÅÅÅÅÅÅÅÅÆÆÆÌÌÌÑÑÑÑÑÑÍÍÍÉÉÉÇÇÇÇÇÇÉÉÉÃÃÃÇÇÇÆÆÆÅÅÅÜÜÜÐÐÐÐÐÐÒÒÒÙÙÙÜÜÜÛÛÛÝÝÝâââãããêêêëëëäääÜÜÜÙÙÙØØØ×××ÝÝÝÜÜÜØØØÕÕÕÒÒÒÒÒÒÔÔÔ×××ÔÔÔÛÛÛãããçççêêêêêêãããÛÛÛæææßßßÜÜÜÝÝÝ×××ÌÌÌÊÊÊÐÐÐÌÌÌÐÐÐÑÑÑÌÌÌÊÊÊÍÍÍÐÐÐÎÎÎÎÎÎÐÐÐÎÎÎÑÑÑÎÎÎÍÍÍÑÑÑÀÀÀ¿¿¿ÅÅÅÆÆÆÛÛÛÌÌÌÎÎÎÑÑÑÊÊÊÇÇÇÒÒÒ×××ÒÒÒÒÒÒÒÒÒÒÒÒÔÔÔ×××ÐÐÐÅÅÅÎÎÎØØØÀÀÀÍÍÍÉÉÉÇÇǾ¾¾¿¿¿××××××ÔÔÔÒÒÒÐÐÐÜÜÜØØØÙÙÙÙÙÙäääãããÌÌÌÇÇÇÔÔÔÍÍÍÇÇÇÇÇÇÊÊÊÉÉÉÆÆÆÅÅÅ¿¿¿ÎÎÎÛÛÛßßßÝÝÝ×××ÔÔÔØØØÙÙÙÊÊÊÅÅÅÌÌÌÊÊʼ¼¼µµµºººººº´´´±±±´´´µµµ³³³´´´···¿¿¿ÂÂÂÇÇÇÃÃÃÅÅÅÌÌÌÆÆÆÃÃÃÉÉÉÇÇÇÌÌÌÅÅŵµµ±±±¸¸¸ººº¯¯¯°°°±±±µµµººº¾¾¾ÀÀÀ¿¿¿ÅÅÅÆÆÆÅÅÅÆÆÆÊÊÊÎÎÎÐÐÐÔÔÔØØØÔÔÔÕÕÕããããããÛÛÛßßßææææææêêêëëëßßßÊÊÊÀÀÀÂÂÂÆÆÆÇÇÇÊÊÊÌÌÌÍÍÍÐÐÐÕÕÕØØØßßßØØØÔÔÔÑÑÑÌÌÌÍÍÍÐÐÐÌÌÌÝÝÝãããßßßÜÜÜØØØÒÒÒÕÕÕÑÑÑÅÅÅÍÍÍØØØàààãããââââââãããíííßßßÙÙÙÔÔÔØØØÝÝÝÒÒÒÐÐÐÊÊÊÌÌÌÍÍÍÎÎÎÐÐÐÐÐÐÎÎÎÎÎÎÉÉÉÎÎÎ×××àààÔÔÔÍÍÍÔÔÔÉÉÉÆÆÆÂÂÂÂÂÂÂÂÂÃÃÃÉÉÉÊÊÊÃÃÃÃÃÃÃÃÃÆÆÆÌÌÌÒÒÒ×××ÕÕÕÒÒÒÊÊÊÆÆÆÊÊÊÆÆÆÆÆÆÌÌÌÌÌÌÕÕÕÔÔÔÒÒÒÕÕÕÛÛÛÝÝÝÝÝÝÜÜÜÝÝÝàààääääääßßßÛÛÛÛÛÛÛÛÛÙÙÙßßßÜÜÜØØØÕÕÕÔÔÔÕÕÕÕÕÕÕÕÕÒÒÒ×××ÛÛÛÝÝÝâââçççæææàààããããããÙÙÙØØØÛÛÛÇÇǺººÅÅÅÊÊÊÍÍÍÍÍÍÊÊÊÊÊÊÎÎÎÒÒÒÒÒÒÌÌÌÎÎÎÑÑÑÒÒÒÑÑÑÆÆÆÇÇǺººÀÀÀÆÆÆÅÅÅÛÛÛÒÒÒÑÑÑÒÒÒÕÕÕÉÉÉÆÆÆÎÎÎÕÕÕÔÔÔÒÒÒØØØÛÛÛÜÜÜÇÇÇÅÅÅÍÍÍÔÔÔÅÅÅÐÐÐÉÉÉÆÆÆ¾¾¾···ØØØ×××ÕÕÕÕÕÕÔÔÔÜÜÜ×××ÕÕÕÔÔÔßßßâââÒÒÒÑÑÑÔÔÔÌÌÌÆÆÆÇÇÇÆÆÆÂÂÂÂÂÂÇÇÇÉÉÉÔÔÔÕÕÕ×××ßßßÛÛÛÔÔÔÙÙÙÊÊÊÍÍÍÍÍÍÇÇÇ¿¿¿ººº······¾¾¾¸¸¸·········³³³´´´···¸¸¸¾¾¾ÀÀÀ»»»¾¾¾ÇÇÇÊÊÊÉÉÉÃÃÿ¿¿ÀÀÀ¼¼¼±±±¯¯¯³³³±±±¦¦¦©©©¬¬¬³³³¸¸¸¼¼¼¾¾¾¾¾¾ÃÃÃÅÅÅÇÇÇÊÊÊÎÎÎÑÑÑÒÒÒÒÒÒÎÎÎÑÑÑÍÍÍÎÎÎÛÛÛàààßßßäääÝÝÝãããçççäääàààÕÕÕÃÃó³³ÃÃÃÇÇÇÊÊÊÍÍÍÍÍÍÎÎÎÔÔÔØØØÝÝÝßßßÝÝÝÕÕÕÉÉÉÇÇÇÒÒÒÜÜÜââââââßßßÝÝÝÜÜÜÙÙÙØØØÒÒÒÀÀÀØØØçççãããÜÜÜßßßääääääæææÙÙÙÕÕÕÒÒÒØØØÜÜÜÐÐÐÌÌÌÊÊÊÌÌÌÍÍÍÎÎÎÎÎÎÍÍÍÊÊÊÉÉÉÇÇÇÉÉÉÐÐÐÜÜÜÒÒÒÆÆÆÉÉÉÀÀÀÂÂÂÂÂÂÂÂÂÂÂÂÀÀÀÅÅÅÇÇÇÇÇÇÃÃÃÅÅÅÇÇÇÎÎÎ×××ÜÜÜßßßÝÝÝÔÔÔÇÇÇÍÍÍÊÊÊÊÊÊ×××ØØØØØØ×××ÕÕÕÕÕÕÙÙÙÝÝÝßßßßßßßßßàààãããàààÜÜÜÛÛÛÝÝÝÝÝÝÛÛÛßßßÛÛÛ×××ÕÕÕ×××××××××ÕÕÕ×××ÙÙÙÛÛÛÜÜÜãããêêêêêêæææâââëëëæææâââäääÔÔÔÂÂÂÆÆÆÉÉÉÊÊÊÌÌÌÍÍÍÎÎÎÐÐÐÑÑÑÒÒÒÎÎÎÐÐÐÐÐÐÎÎÎÎÎο¿¿ÆÆÆ¾¾¾ÀÀÀÇÇÇÂÂÂØØØÔÔÔÐÐÐÎÎÎØØØÐÐÐÂÂÂÉÉÉØØØÕÕÕÑÑÑØØØÛÛÛßßßÂÂÂÉÉÉÆÆÆÊÊÊÇÇÇÊÊÊÇÇÇ»»»µµµØØØØØØ×××ØØØØØØÜÜÜÙÙÙÙÙÙÔÔÔÛÛÛÝÝÝÒÒÒØØØÍÍÍÉÉÉÇÇÇÆÆÆÀÀÀ¼¼¼ÃÃÃÎÎÎØØØÝÝÝÙÙÙ×××ÜÜÜØØØÑÑÑÕÕÕÇÇÇÐÐÐÐÐÐÃÃü¼¼¿¿¿¾¾¾¸¸¸»»»···µµµ···´´´±±±³³³···ºººÀÀÀÀÀÀ¿¿¿¼¼¼ººº···¯¯¯¸¸¸°°°­­­­­­ªªª¬¬¬­­­¦¦¦¦¦¦©©©­­­µµµ»»»¾¾¾»»»¸¸¸ÃÃÃÃÃÃÇÇÇÍÍÍÑÑÑÒÒÒÒÒÒÒÒÒÎÎÎÎÎÎÊÊÊÊÊÊÒÒÒØØØÜÜÜäääßßßæææêêêêêêèèèâââÑÑÑ¿¿¿¿¿¿ÅÅÅÊÊÊÍÍÍÍÍÍÐÐÐÔÔÔÙÙÙÝÝÝæææçççßßßÔÔÔÎÎÎÔÔÔÝÝÝëëëâââÜÜÜÛÛÛÜÜÜÛÛÛÒÒÒÍÍÍÉÉÉÝÝÝèèèâââÝÝÝäääçççàààÛÛÛÒÒÒÕÕÕÔÔÔÙÙÙÛÛÛÌÌÌÆÆÆÊÊÊÊÊÊÊÊÊÌÌÌÌÌÌÊÊÊÊÊÊÉÉÉÐÐÐÇÇÇ¿¿¿ÉÉÉÆÆÆ¾¾¾ÃÃÿ¿¿ÂÂÂÂÂÂÀÀÀÀÀÀÂÂÂÂÂÂÃÃÃÆÆÆÆÆÆÆÆÆÉÉÉÎÎÎÔÔÔØØØÛÛÛÜÜÜßßßÎÎÎÐÐÐÍÍÍÌÌÌÛÛÛÝÝÝØØØÙÙÙØØØ××××××ÜÜÜâââãããããããããäääâââÜÜÜÜÜÜßßßßßßÜÜÜßßßÛÛÛØØØ×××ØØØØØØØØØ×××ÛÛÛÜÜÜÜÜÜÝÝÝæææíííëëëæææäääêêêèèèãããâââÙÙÙÆÆÆ···ÂÂÂÂÂÂÅÅÅÊÊÊÍÍÍÍÍÍÍÍÍÎÎÎÍÍÍÍÍÍÐÐÐÍÍÍÒÒÒ¼¼¼ÆÆÆÅÅÅÆÆÆÌÌÌÅÅÅÛÛÛÕÕÕÐÐÐÍÍÍÕÕÕÝÝÝÌÌÌÎÎÎÛÛÛØØØÔÔÔ×××ØØØØØØÀÀÀÐÐÐÀÀÀÃÃÃÉÉÉÆÆÆÆÆÆ¾¾¾¸¸¸¾¾¾ÕÕÕ×××ÕÕÕÙÙÙÙÙÙÜÜÜÝÝÝâââÜÜÜßßßÜÜÜÎÎÎÒÒÒÉÉÉÉÉÉÉÉÉÃÃü¼¼¼¼¼ÇÇÇÔÔÔ×××ÝÝÝÝÝÝØØØÑÑÑÉÉÉÅÅÅÉÉÉÎÎÎÌÌÌÆÆÆÂÂÂÂÂÂÃÃÃÀÀÀ»»»¾¾¾»»»»»»¼¼¼»»»¸¸¸»»»ÀÀÀººº¾¾¾ººº¾¾¾¿¿¿»»»¼¼¼¸¸¸¸¸¸­­­©©©¬¬¬­­­³³³±±±¨¨¨¬¬¬­­­°°°µµµ»»»¾¾¾»»»···¿¿¿¿¿¿ÃÃÃÊÊÊÎÎÎÍÍÍÍÍÍÎÎÎÑÑÑÑÑÑÍÍÍÊÊÊÍÍÍÑÑÑ×××ÜÜÜàààãããêêêîîîêêêàààÙÙÙ×××»»»ÂÂÂÊÊÊÎÎÎÎÎÎÐÐÐÕÕÕÙÙÙÛÛÛãããæææçççêêêäääßßßàààñññâââÜÜÜ××××××ÔÔÔÇÇÇÅÅÅØØØßßßàààÜÜÜßßßçççããã×××ÔÔÔÑÑÑØØØØØØØØØ×××ÉÉÉÆÆÆÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÊÊÊÊÊÊÌÌÌÍÍÍÅÅźººÂÂÂÃÃþ¾¾ÃÃÃÀÀÀÇÇÇÃÃû»»»»»ÂÂÂÀÀÀ¾¾¾ÀÀÀÑÑÑÑÑÑÒÒÒÔÔÔÕÕÕ×××ØØØØØØæææÑÑÑÐÐÐÍÍÍÍÍÍØØØØØØÕÕÕÛÛÛÛÛÛÙÙÙ×××ÛÛÛâââææææææääääääãããÝÝÝÜÜÜààààààÜÜÜÝÝÝÛÛÛÙÙÙØØØØØØÙÙÙØØØØØØÛÛÛÛÛÛÜÜÜÝÝÝæææíííëëëããããããàààâââãããâââàààÑÑѸ¸¸¾¾¾»»»»»»¿¿¿ÃÃÃÆÆÆÇÇÇÌÌÌÉÉÉÇÇÇÐÐÐÐÐÐÜÜܾ¾¾ÅÅÅÅÅÅÍÍÍÑÑÑÍÍÍàààÕÕÕÑÑÑÐÐÐÑÑÑÜÜÜÑÑÑÐÐÐ×××ÜÜÜßßßßßßÝÝÝÌÌÌÆÆÆÒÒÒ¿¿¿ÃÃÃÇÇÇÇÇÇÃÃû»»···ÊÊÊÔÔÔÕÕÕÔÔÔ×××ØØØÛÛÛÜÜÜßßßÛÛÛÝÝÝÛÛÛÊÊÊÍÍÍÉÉÉÊÊÊÇÇÇ¿¿¿¼¼¼ÂÂÂÍÍÍÔÔÔÑÑÑÐÐÐÔÔÔÒÒÒÍÍÍÌÌÌÍÍÍÌÌÌÊÊÊÃÃÿ¿¿ÀÀÀÀÀÀ¼¼¼¸¸¸¸¸¸···µµµµµµ···µµµ´´´···¾¾¾ÆÆÆÂ···¿¿¿ÀÀÀ¸¸¸¼¼¼»»»¾¾¾´´´³³³µµµµµµººº»»»³³³´´´°°°­­­¯¯¯´´´ººº»»»»»»¼¼¼¼¼¼ÀÀÀÇÇÇÊÊÊÇÇÇÉÉÉÍÍÍÑÑÑÒÒÒÑÑÑÐÐÐÎÎÎÐÐÐÔÔÔ×××àààâââäääæææäääàààààààà຺ºÂÂÂÌÌÌÐÐÐÎÎÎÐÐÐÔÔÔÙÙÙØØØßßßàààæææïïïïïïêêêíííêêêÝÝÝÛÛÛÒÒÒÍÍÍÊÊÊÀÀÀÆÆÆßßßàààÝÝÝÛÛÛÜÜÜÜÜÜØØØÒÒÒÒÒÒÒÒÒÛÛÛÕÕÕÐÐÐÍÍÍÅÅÅÆÆÆÅÅÅÅÅÅÇÇÇÉÉÉÊÊÊÌÌÌÍÍÍÍÍÍÎÎÎÎÎÎÆÆÆÇÇÇÆÆÆ¿¿¿ÃÃÿ¿¿ÍÍÍÊÊʾ¾¾ÀÀÀ¼¼¼¼¼¼ÆÆÆÕÕÕ×××ØØØÙÙÙÙÙÙÙÙÙØØØØØØãããÐÐÐÍÍÍÎÎÎÔÔÔÙÙÙÕÕÕÛÛÛÜÜÜßßßÝÝÝÛÛÛÛÛÛàààäääãããàààãããâââÝÝÝÜÜÜßßßàààÝÝÝÛÛÛÜÜÜÛÛÛÛÛÛÙÙÙØØØÙÙÙÙÙÙÛÛÛÜÜÜÜÜÜßßßçççïïïíííæææàààÜÜÜãããëëëæææàààÝÝÝÙÙÙÍÍ͸¸¸···¸¸¸¼¼¼ÃÃÃÌÌÌÆÆÆÅÅÅÍÍÍÎÎÎßßß¾¾¾ÃÃÃÅÅÅÍÍÍÑÑÑÑÑÑâââÑÑÑÒÒÒÒÒÒÊÊÊÕÕÕÔÔÔÍÍÍÌÌÌØØØâââßßßØØØÂÂÂÊÊÊÔÔÔÂÂÂÆÆÆÆÆÆÌÌÌ»»»···ÔÔÔÑÑÑÕÕÕÑÑÑÔÔÔ×××ØØØÕÕÕÕÕÕÑÑÑØØØÙÙÙÊÊÊÊÊÊÌÌÌÌÌÌÅÅż¼¼¼¼¼ÇÇÇÐÐÐÑÑÑÙÙÙÊÊÊÅÅÅÅÅÅÀÀÀÅÅÅÆÆÆ»»»¼¼¼¾¾¾¿¿¿»»»µµµ°°°¯¯¯±±±´´´³³³³³³´´´³³³±±±´´´»»»µµµ³³³­­­ÀÀÀÆÆÆ¸¸¸ººº···¼¼¼······¸¸¸´´´···»»»···ººº±±±©©©¦¦¦¬¬¬µµµ¼¼¼¾¾¾¾¾¾¾¾¾ÂÂÂÉÉÉÊÊÊÇÇÇÉÉÉÎÎÎÍÍÍÐÐÐÔÔÔÕÕÕÑÑÑÑÑÑÕÕÕ×××äääçççâââÛÛÛâââíííëëëßßß»»»ÃÃÃÌÌÌÐÐÐÎÎÎÎÎÎÒÒÒØØØÝÝÝäääâââßßßãããäääçççòòòßßßÕÕÕÙÙÙÐÐÐÇÇÇÅÅÅÀÀÀÍÍÍßßßâââãããÝÝÝÔÔÔÍÍÍÎÎÎÔÔÔÒÒÒÒÒÒÙÙÙÐÐÐÆÆÆÃÃþ¾¾ÆÆÆÂÂÂÃÃÃÆÆÆÉÉÉÌÌÌÍÍÍÍÍÍÍÍÍÉÉÉÎÎÎÆÆÆÅÅÅÅÅÅÆÆÆÕÕÕÙÙÙÑÑÑÕÕÕÎÎÎÅÅÅ¿¿¿···¾¾¾ÔÔÔÍÍÍÐÐÐÒÒÒÔÔÔÕÕÕÕÕÕÕÕÕÕÕÕÝÝÝÍÍÍÌÌÌÒÒÒÜÜÜßßßÛÛÛäääÜÜÜââââââÝÝÝÜÜÜßßßâââàààÛÛÛààààààÝÝÝÜÜÜßßßàààßßßÛÛÛÜÜÜÜÜÜÛÛÛÙÙÙØØØÙÙÙÛÛÛÝÝÝÝÝÝÝÝÝàààêêêóóóòòòëëëäääãããêêêêêêÒÒÒ¸¸¸»»»ÑÑÑâââÐÐм¼¼´´´³³³···ÀÀÀÌÌÌÉÉÉÅÅÅÉÉÉÉÉÉÝÝݺººÂÂÂÅÅÅÉÉÉÌÌÌÐÐÐàààÌÌÌÐÐÐÒÒÒÃÃÃ×××ÛÛÛÍÍÍÀÀÀÎÎÎØØØÎÎÎÅÅÅÂÂÂÔÔÔ×××ÆÆÆÃÃÃÑÑÑÐÐп¿¿···¼¼¼ÐÐÐÙÙÙÑÑÑÐÐÐ×××ØØØÝÝÝÐÐÐÍÍÍÔÔÔÔÔÔÔÔÔÒÒÒÌÌÌÍÍÍÊÊÊÌÌ̼¼¼»»»ÑÑÑÕÕÕÍÍÍÊÊÊÆÆÆÅÅÅÇÇÇÊÊÊÆÆÆ¼¼¼µµµÂ¼¼¼¯¯¯»»»ÅÅÅ¿¿¿¾¾¾°°°¯¯¯¯¯¯¯¯¯¯¯¯­­­¬¬¬­­­¯¯¯´´´±±±ÃÃþ¾¾°°°´´´¬¬¬µµµ°°°¯¯¯¬¬¬¬¬¬µµµ»»»´´´´´´¯¯¯©©©©©©±±±ººº»»»¸¸¸¾¾¾¿¿¿ÃÃÃÆÆÆÉÉÉÊÊÊÌÌÌÌÌÌÎÎÎÐÐÐÕÕÕÎÎÎÕÕÕÙÙÙÐÐÐÛÛÛÕÕÕää䨨ØßßßòòòîîîííííííàààÂÂÂÊÊÊÍÍÍÐÐÐØØØÎÎÎÛÛÛØØØÛÛÛÝÝÝßßßàààâââããããããÝÝÝÒÒÒÌÌÌÉÉÉÍÍ;¾¾´´´ÙÙÙ×××ÝÝÝÔÔÔÉÉÉÌÌÌÌÌÌÆÆÆÇÇÇ×××ÒÒÒÛÛÛÕÕÕ¾¾¾ºººÃÃÿ¿¿¾¾¾ÀÀÀÅÅÅÉÉÉÌÌÌÍÍÍÍÍÍÌÌÌÌÌÌÊÊÊÆÆÆÍÍÍÛÛÛØØØÐÐÐÒÒÒÒÒÒÎÎÎÐÐÐÕÕÕ×××ÑÑÑÐÐÐÑÑÑÑÑÑÔÔÔ×××ØØØØØØÕÕÕÒÒÒÐÐÐÝÝÝÝÝÝÕÕÕÛÛÛÝÝÝÜÜÜßßß×××ÜÜÜàààßßßßßßæææäääâââäääÜÜÜÛÛÛÙÙÙÙÙÙÛÛÛÝÝÝàààâââààààààßßßÝÝÝÛÛÛÙÙÙÙÙÙØØØààààààâââãããæææêêêíííïïïíííëëëëëëêêêÙÙÙººº···ÑÑÑÔÔÔµµµ°°°³³³³³³···¼¼¼ÊÊÊÂÂÂÀÀÀÀÀÀÊÊÊÊÊÊÎÎλ»»ÅÅÅÂÂÂÇÇÇØØØßßß×××ÒÒÒÑÑÑÉÉÉÇÇÇÙÙÙÙÙÙÍÍÍÉÉÉÅÅÅÃÃÃÊÊÊÍÍÍÍÍÍÎÎÎÐÐÐÎÎÎÉÉÉÅÅÅÅÅŵµµÊÊÊ×××ÕÕÕÐÐÐÐÐÐÔÔÔØØØÜÜÜÎÎÎÌÌÌÐÐÐÎÎÎÎÎÎÐÐÐÌÌÌÊÊÊÃÃÃÆÆÆ¾¾¾¾¾¾ÐÐÐÐÐÐÉÉÉÃÃÃÉÉÉÍÍÍÊÊʼ¼¼¼¼¼ÀÀÀººº­­­¯¯¯ÀÀÀÅÅÅÅÅÅÉÉÉ¿¿¿³³³¦¦¦¥¥¥°°°¸¸¸¸¸¸´´´ººº¾¾¾ÇÇÇ···±±±©©©³³³¯¯¯¬¬¬¥¥¥¥¥¥¨¨¨¨¨¨¬¬¬­­­¨¨¨³³³···±±±©©©¬¬¬···ººº³³³ºººººº»»»¼¼¼¿¿¿ÅÅÅÊÊÊÐÐÐÒÒÒÕÕÕÛÛÛÕÕÕØØØÙÙÙÐÐÐÙÙÙàààæææÛÛÛßßßïïïíííèèèîîîæææÃÃÃÊÊÊÎÎÎÐÐÐÕÕÕÎÎÎØØØ×××ÙÙÙÝÝÝàààââââââàààßßßÝÝÝÔÔÔÑÑÑÍÍÍÇÇǸ¸¸¸¸¸ÝÝÝØØØÕÕÕÌÌÌÇÇÇÍÍÍÑÑÑÐÐÐÎÎÎÎÎÎÍÍÍØØØ×××¾¾¾Â»»»¾¾¾ÀÀÀÅÅÅÉÉÉÌÌÌÍÍÍÍÍÍÍÍÍÐÐÐÆÆÆÃÃÃÍÍÍ×××ÛÛÛ×××ÎÎÎÑÑÑÎÎÎÎÎÎÐÐÐÎÎÎÊÊÊÍÍÍÑÑÑÎÎÎÎÎÎÑÑÑÔÔÔ×××ØØØ×××ÕÕÕ×××ßßßÜÜÜàààÝÝÝ×××ÝÝÝÛÛÛßßßææææææãããæææàààÜÜÜâââßßßÝÝÝÜÜÜÜÜÜÝÝÝßßßâââããããããâââàààßßßÝÝÝÜÜÜÜÜÜÜÜÜàààââââââãããæææèèèêêêëëëêêêçççäääêêêæææÑÑÑÍÍÍÝÝÝÜÜÜ´´´ªªª³³³···¸¸¸ºººÇÇÇÂÂÂÂÂÂÂÂÂÊÊÊÍÍÍÑÑÑ»»»¿¿¿ÇÇÇÇÇÇÔÔÔÛÛÛÕÕÕÒÒÒÔÔÔÐÐÐÅÅÅÐÐÐ×××ÕÕÕÒÒÒÌÌÌÆÆÆÆÆÆÒÒÒÍÍÍÍÍÍÑÑÑÑÑÑÉÉÉÂÂÂÀÀÀÀÀÀ×××ÙÙÙÎÎÎÑÑÑÔÔÔÒÒÒÔÔÔÕÕÕÌÌÌÍÍÍÒÒÒÐÐÐÐÐÐÒÒÒÎÎÎÎÎÎÅÅÅÉÉÉÅÅÅÇÇÇ×××ÒÒÒÊÊÊÀÀÀÉÉÉÍÍÍÇÇǼ¼¼¸¸¸¾¾¾ÃÃúºº©©©···ÃÃü¼¼¼¼¼ÀÀÀÀÀÀÊÊʺººªªªªªª¸¸¸Â¼¼¼¿¿¿ÆÆÆÆÆÆ°°°···¸¸¸ÀÀÀ¼¼¼¼¼¼µµµ···ºººµµµ´´´°°°¥¥¥¨¨¨´´´µµµ©©©©©©µµµ»»»´´´ººº»»»¾¾¾¿¿¿ÀÀÀÆÆÆÍÍÍÒÒÒÒÒÒÕÕÕÛÛÛ×××ØØØ×××ÎÎÎÔÔÔæææâââÛÛÛÝÝÝíííîîîçççòòòëëëÂÂÂÉÉÉÒÒÒÑÑÑÕÕÕÑÑÑÕÕÕÔÔÔØØØÜÜÜßßßàààßßßÜÜÜÙÙÙÑÑÑÍÍÍÎÎÎÅÅźºº»»»ÉÉÉãããäääÕÕÕÌÌÌÊÊÊÌÌÌÎÎÎÍÍÍÇÇÇÍÍÍÊÊÊÒÒÒÒÒÒÅÅÅÂÂÂÅÅž¾¾¾¾¾ÀÀÀÅÅÅÉÉÉÌÌÌÍÍÍÍÍÍÌÌÌÊÊÊÅÅÅÍÍÍÕÕÕÕÕÕÙÙÙÙÙÙÌÌÌÔÔÔÔÔÔ×××ØØØÕÕÕÒÒÒÕÕÕÛÛÛÒÒÒÐÐÐÐÐÐÑÑÑÕÕÕÙÙÙÙÙÙÙÙÙÒÒÒÛÛÛÛÛÛßßßÛÛÛÔÔÔÙÙÙØØØÒÒÒÜÜÜàààâââæææäääâââçççâââààààààßßßßßßàààãããäääçççæææãããâââàààààààààâââããããããäääææææææçççççççççóóóíííçççëëëîîîäääÛÛÛßßßÐÐб±±­­­³³³´´´······ÀÀÀÀÀÀÃÃÃÂÂÂÉÉÉÍÍÍ×××¼¼¼ºººÇÇÇÆÆÆÐÐÐÜÜÜÙÙÙÒÒÒÐÐÐÍÍÍÊÊÊÎÎÎÙÙÙßßß×××ÍÍÍÉÉÉÆÆÆÍÍÍÕÕÕÒÒÒÉÉÉÉÉÉÎÎÎÇÇÇ···ÕÕÕÛÛÛÔÔÔÍÍÍÔÔÔÙÙÙÒÒÒÊÊÊÌÌÌÊÊÊÒÒÒÙÙÙ×××××××××ÑÑÑÐÐÐÉÉÉÌÌÌÅÅÅÉÉÉÜÜÜØØØÊÊÊÆÆÆÆÆÆÂ¼¼¼»»»¾¾¾¾¾¾¼¼¼¯¯¯©©©ºººººº³³³¸¸¸···¾¾¾ÀÀÀ¾¾¾»»»¼¼¼ÀÀÀÃÃÃÂÂÂÀÀÀ¿¿¿ÀÀÀººº¬¬¬ÅÅÅÊÊÊÊÊʾ¾¾¾¾¾ÃÃÃÅÅÅÅÅÅÉÉÉÅÅÅ´´´¤¤¤±±±µµµ­­­¨¨¨¯¯¯µµµµµµ···»»»ÀÀÀÅÅÅÅÅÅÆÆÆÊÊÊÍÍÍÎÎÎÑÑÑÕÕÕÒÒÒÑÑÑÎÎÎÍÍÍÑÑÑßßß×××ØØØÜÜÜëëëïïïæææóóóæææÀÀÀÇÇÇ×××ÔÔÔÕÕÕÔÔÔÒÒÒÕÕÕ×××ÙÙÙÜÜÜÝÝÝÜÜÜØØØÕÕÕÐÐÐÌÌÌÊÊÊÀÀÀ¼¼¼ÎÎÎàààãããÜÜÜÌÌÌÉÉÉÎÎÎÌÌÌÍÍÍÑÑÑÎÎÎÍÍÍÆÆÆÇÇÇÆÆÆ¾¾¾¾¾¾Â¾¾¾¾¾¾ÀÀÀÅÅÅÉÉÉÌÌÌÌÌÌÌÌÌÊÊÊÂÂÂÍÍÍÜÜÜààà×××ÔÔÔÔÔÔÐÐÐÎÎÎÐÐÐÒÒÒ×××××××××ÕÕÕ×××ÙÙÙ×××ÔÔÔÔÔÔ×××ØØØØØØÕÕÕÛÛÛÝÝÝØØØÝÝÝàààÜÜÜßßßØØØÕÕÕÜÜÜÜÜÜàààçççäääßßßàààââââââââââââàààâââäääæææêêêèèèæææäääääääääæææçççæææççççççççççççæææäääãããúúúòòòííííííïïïêêêàààÜÜܵµµ°°°···±±±¬¬¬´´´···¸¸¸ÀÀÀÃÃÃÀÀÀÆÆÆÍÍÍÙÙÙ¿¿¿¸¸¸ÃÃÃÃÃÃÑÑÑãããäääÕÕÕÌÌÌÉÉÉÐÐÐÎÎÎÜÜÜää䨨ØÐÐÐÔÔÔÕÕÕÐÐÐÔÔÔÑÑÑÉÉÉÆÆÆÊÊÊÆÆÆ¼¼¼ããã×××ÒÒÒÒÒÒÔÔÔÕÕÕÒÒÒÉÉÉÌÌÌÍÍÍÔÔÔØØØÔÔÔÔÔÔÕÕÕÐÐÐÇÇÇÇÇÇÊÊʼ¼¼¿¿¿ØØØ×××ÇÇÇÉÉÉÅÅż¼¼···»»»ÀÀÀ¾¾¾µµµ°°°ºººÂ´´´³³³µµµ­­­µµµ³³³¸¸¸¾¾¾ÀÀÀÀÀÀ¿¿¿¿¿¿ÀÀÀ¼¼¼µµµ¯¯¯ªªªÅÅÅÃÃþ¾¾ÂÂÂÅÅÅÆÆÆ¿¿¿»»»Âººº¡¡¡ªªª±±±···´´´ªªª¤¤¤¨¨¨¯¯¯±±±´´´ººº¾¾¾ÀÀÀÃÃÃÆÆÆÉÉÉÌÌÌÎÎÎÐÐÐÐÐÐÌÌÌÊÊÊÑÑÑÔÔÔÔÔÔÐÐÐØØØÜÜÜçççëëëâââëëë×××¾¾¾ÉÉÉØØØ××××××ÕÕÕÒÒÒ×××ÕÕÕÕÕÕ×××ØØØØØØÕÕÕÑÑÑÕÕÕÇÇÇÇÇÇÑÑÑ×××âââèèèÝÝÝÔÔÔÉÉÉÍÍÍÑÑÑÉÉÉÆÆÆÌÌÌÌÌÌÉÉÉÂÂÂÀÀÀ¿¿¿»»»¼¼¼¿¿¿»»»¿¿¿ÂÂÂÅÅÅÉÉÉÊÊÊÊÊÊÉÉÉÉÉÉÌÌÌÙÙÙàààÝÝÝØØØÑÑÑÑÑÑÙÙÙÜÜÜØØØÒÒÒÒÒÒ×××ÙÙÙ×××ÒÒÒ×××ÕÕÕÒÒÒÒÒÒÔÔÔÔÔÔÒÒÒÑÑÑ×××ÙÙÙÑÑÑÕÕÕ×××ÔÔÔÙÙÙÕÕÕÜÜÜÝÝÝÛÛÛâââïïïñññçççäääâââãããäääãããââââââäääçççêêêêêêèèèççççççèèèèèèêêêêêêêêêêêêèèèçççæææãããâââïïïëëëêêêëëëëëëèèèäääàà຺º´´´ººº°°°©©©³³³µµµ···¾¾¾Â¾¾¾ÂÂÂÉÉÉÙÙÙ¾¾¾ÀÀÀÃÃÃÑÑÑäääêêêÝÝÝÔÔÔÕÕÕ×××ÎÎÎØØØäääàààßßßâââÝÝÝÛÛÛÎÎÎÌÌÌÒÒÒÍÍÍ¿¿¿ÀÀÀÑÑÑàààÕÕÕ×××ØØØÎÎÎÍÍÍÒÒÒÐÐÐÑÑÑÎÎÎÑÑÑÐÐÐÉÉÉÍÍÍÐÐÐÊÊÊÇÇÇÇÇÇÍÍ;¾¾¼¼¼ÔÔÔ×××ÎÎÎÆÆÆÇÇǺººººº¾¾¾¼¼¼µµµ¦¦¦¸¸¸ºººµµµÂÂÂÇÇÇÂÂÂÌÌÌ´´´´´´´´´···ººº¼¼¼¼¼¼¼¼¼´´´¯¯¯³³³±±±Â¾¾¾ÃÃÃÆÆÆººº¾¾¾ÀÀÀ»»»»»»ÃÃû»»¡¡¡©©©­­­´´´···°°°¦¦¦©©©³³³µµµµµµ···ººº¿¿¿ÆÆÆÌÌÌÐÐÐÊÊÊÍÍÍÍÍÍÐÐÐÊÊÊÉÉÉ××××××ÎÎÎÐÐÐ×××ÙÙÙßßßâââßßßâââÅÅÅÀÀÀÊÊÊÕÕÕ×××ÕÕÕÕÕÕÒÒÒ×××ÔÔÔÒÒÒÒÒÒÕÕÕÔÔÔÑÑÑÍÍÍÉÉɸ¸¸¼¼¼ÝÝÝêêêâââßßßÕÕÕÑÑÑÎÎÎÑÑÑÎÎÎÅÅž¾¾¿¿¿ÀÀÀÇÇÇÅÅÅÅÅÅÇÇÇÇÇÇÇÇÇÆÆÆÂÂÂÂÂÂÃÃÃÆÆÆÉÉÉÉÉÉÉÉÉÆÆÆÅÅÅßßßßßßÕÕÕÒÒÒ×××ÔÔÔÔÔÔâââñññèèèÜÜÜÒÒÒÔÔÔÙÙÙÙÙÙÕÕÕÎÎÎÎÎÎÐÐÐÐÐÐÑÑÑÒÒÒÔÔÔÕÕÕÔÔÔÜÜÜØØØØØØÒÒÒÍÍÍÙÙÙÝÝÝââââââàààçççùùùÿÿÿõõõòòòæææèèèêêêçççäääâââãããæææèèèèèèèèèèèèêêêêêêêêêêêêêêêêêêèèèçççæææãããâââàààèèèäääçççêêêæææââââââßßßÒÒÒ¸¸¸³³³°°°­­­³³³´´´»»»¼¼¼ÀÀÀ¾¾¾ÃÃÃÇÇÇÒÒÒ¿¿¿ÀÀÀÃÃÃÇÇÇÎÎÎÛÛÛäääààààààèèèäääÛÛÛÙÙÙâââççççççßßßÔÔÔßßßÑÑÑÐÐÐÕÕÕÍÍ;¾¾ÇÇÇàààÙÙÙÙÙÙÙÙÙÔÔÔÍÍÍÎÎÎÒÒÒÒÒÒÍÍÍÌÌÌÐÐÐÎÎÎÊÊÊÎÎÎÎÎÎÆÆÆÊÊÊÅÅÅÎÎÎÇÇÇÀÀÀÍÍÍÔÔÔÙÙÙÇÇÇÍÍÍÊÊÊÀÀÀ¼¼¼¿¿¿¾¾¾······»»»···ÀÀÀÎÎÎÊÊÊÉÉÉÎÎÎÆÆÆ¿¿¿¸¸¸µµµ¸¸¸ººº¸¸¸µµµ¯¯¯¯¯¯¾¾¾¼¼¼ÅÅÅÂÂÂÇÇǾ¾¾»»»···»»»¿¿¿¿¿¿¾¾¾³³³¡¡¡¤¤¤ªªª´´´¸¸¸µµµ³³³´´´ºººÀÀÀ¼¼¼»»»¼¼¼ÃÃÃÉÉÉÌÌÌÌÌÌÆÆÆÊÊÊÌÌÌÐÐÐÇÇÇÆÆÆÕÕÕÔÔÔÊÊÊÔÔÔÔÔÔÒÒÒÔÔÔÛÛÛäääãã㸸¸ÆÆÆÍÍÍÐÐÐÒÒÒÒÒÒÒÒÒÔÔÔÕÕÕÒÒÒÑÑÑÒÒÒÔÔÔÒÒÒÍÍÍÇÇÇÅÅÅÂÂÂÆÆÆßßßâââÒÒÒÒÒÒÐÐÐÇÇÇÌÌÌÉÉÉÂÂÂÂÂÂÀÀÀ¿¿¿ÀÀÀ¿¿¿¿¿¿ÀÀÀÃÃÃÆÆÆÉÉÉÇÇÇÇÇÇÅÅÅÆÆÆÇÇÇÉÉÉÉÉÉÆÆÆÃÃÃÂÂÂæææØØØÎÎÎÑÑÑÔÔÔÑÑÑØØØæææëëëèèèßßßÒÒÒÍÍÍÐÐÐÒÒÒÑÑÑÐÐÐÒÒÒÒÒÒÒÒÒÒÒÒÕÕÕÜÜÜââââââëëëèèèèèèãããÝÝÝèèèëëëïïïñññîîîïïïøøøöööïïïïïïïïïñññòòòîîîçççââââââãããäääæææèèèêêêëëëêêêêêêèèèèèèèèèæææãããàààßßßÝÝÝÝÝÝíííâââäääêêêãããÝÝÝÜÜÜÙÙÙÔÔÔµµµ°°°°°°¯¯¯±±±´´´¾¾¾¼¼¼¿¿¿ÀÀÀÉÉÉÆÆÆÌÌ̸¸¸ÀÀÀÃÃÃÉÉÉÉÉÉÊÊÊÒÒÒÕÕÕÛÛÛçççêêêçççßßßÛÛÛàààâââÛÛÛÕÕÕÙÙÙÝÝÝÜÜÜÐÐÐÅÅÅÆÆÆÕÕÕãããÕÕÕÝÝÝÕÕÕÊÊÊÐÐÐ×××ÒÒÒÎÎÎÃÃÃÇÇÇÑÑÑ×××ÕÕÕ×××ÒÒÒÅÅÅÅÅÅ»»»ÇÇÇÉÉÉÀÀÀÀÀÀÉÉÉÙÙÙÌÌÌÐÐÐÍÍÍÃÃÃÂÂÂÅÅÅ¿¿¿´´´Â¸¸¸±±±ÊÊÊÔÔÔÇÇÇÌÌÌÎÎÎ×××ÑÑÑÇÇÇÀÀÀººº···´´´±±±¯¯¯°°°ÂÂÂÀÀÀÆÆÆÂ¼¼¼žžž¦¦¦›››¤¤¤···»»»´´´¬¬¬¡¡¡¦¦¦±±±¸¸¸¸¸¸···ºººººº···ÀÀÀ¾¾¾»»»¾¾¾ÃÃÃÃÃÿ¿¿»»»ÀÀÀÆÆÆÇÇÇÎÎÎÅÅÅÀÀÀÑÑÑÌÌÌÆÆÆÕÕÕÑÑÑÍÍÍÍÍÍØØØíííêêê±±±ÌÌÌÐÐÐÌÌÌÐÐÐÎÎÎÐÐÐÕÕÕÔÔÔÑÑÑÑÑÑÒÒÒÕÕÕÒÒÒÊÊÊÃÃÃ××׿ææãããßßßÒÒÒÆÆÆÍÍÍÊÊÊÎÎÎÔÔÔÆÆÆ»»»¿¿¿¿¿¿···µµµ°°°¯¯¯­­­¯¯¯´´´ººº¾¾¾ÂÂÂÆÆÆÇÇÇÉÉÉÉÉÉÇÇÇÆÆÆÂÂÂÀÀÀàààÎÎÎÑÑÑÙÙÙÑÑÑÌÌÌÙÙÙçççâââèèèèèèßßßÕÕÕÔÔÔ××××××ÙÙÙÛÛÛÛÛÛØØØ×××ÙÙÙãããëëëãããçççãããææææææâââçççäääèèèïïïïïïïïïóóóòòòïïïõõõöööøøøøøøòòòèèèâââàààâââãããäääçççêêêëëëêêêèèèççççççæææãããßßßÝÝÝÜÜÜÛÛÛÛÛÛíííÝÝÝßßßèèèæææßßßÝÝÝÛÛÛ¾¾¾°°°³³³°°°ªªª±±±´´´»»»»»»¿¿¿ÃÃÃÍÍÍÇÇÇÆÆÆ±±±¾¾¾ÂÂÂÉÉÉÅÅÅ¿¿¿ÃÃÃÆÆÆÌÌÌ×××ÝÝÝèèèâââÔÔÔÔÔÔÙÙÙàààíííÐÐÐØØØÙÙÙÌÌÌÎÎÎâââãããÛÛÛæææÝÝÝÕÕÕÑÑÑÒÒÒÔÔÔÎÎÎÊÊÊÑÑÑÒÒÒÔÔÔÕÕÕ×××ÕÕÕÕÕÕÔÔÔÎÎÎÆÆÆÂ¼¼¼ÂÂÂÅÅÅÆÆÆßßßÕÕÕÆÆÆÐÐо¾¾ÀÀÀ»»»­­­¿¿¿¿¿¿ÆÆÆÐÐÐÑÑÑÍÍÍÍÍÍÒÒÒØØØ×××ÕÕÕÑÑÑÇÇǸ¸¸°°°°°°©©©±±±¿¿¿ÉÉÉÉÉɵµµ­­­¥¥¥¤¤¤žžž¡¡¡©©©¨¨¨¦¦¦¯¯¯¯¯¯¸¸¸´´´°°°¢¢¢¯¯¯´´´¿¿¿¼¼¼»»»µµµ³³³ºººÆÆÆÊÊÊÇÇÇÇÇÇ···µµµºººÇÇÇÊÊÊÃÃÃ×××ØØØÐÐÐÍÍÍÕÕÕØØØÔÔÔ×××ÝÝÝßß߸¸¸ÉÉÉÐÐÐÊÊÊÔÔÔÍÍÍÔÔÔ×××ÑÑÑÑÑÑÕÕÕÎÎÎÅÅÅÉÉÉÕÕÕêêêØØØÌÌÌÊÊÊÆÆÆ¿¿¿ÃÃÃÎÎÎÀÀÀÇÇÇÀÀÀ»»»°°°­­­¼¼¼ÀÀÀ¿¿¿ÀÀÀÇÇÇÇÇǾ¾¾´´´±±±ºººµµµ¾¾¾ÉÉÉÉÉÉÇÇÇÆÆÆÀÀÀÛÛÛÑÑÑÍÍÍÑÑÑØØØÝÝÝæææïïïßßßâââãããßßßØØØÕÕÕØØØÜÜÜÑÑÑãããíííçççäääëëëîîîêêêèèèãããääääääøøøêêêääääääêêêíííïïïñññïïïïïïñññóóóøøøòòòõõõêêêâââãããÜÜÜãããæææÜÜÜäääñññêêêâââäääæææääääääâââßßßÜÜÜÙÙÙØØØ×××èèèæææãããâââââââââßßßÜÜÜØØØ¼¼¼¯¯¯°°°¬¬¬°°°¼¼¼Â¿¿¿ÀÀÀÉÉÉÒÒÒ×××ÔÔÔÑÑÑÑÑѺººººº¿¿¿ÆÆÆÇÇÇÆÆÆÇÇÇÌÌÌÙÙÙïïïæææØØØÝÝÝíííóóóßßßßßßÒÒÒÊÊÊÎÎÎÙÙÙàààÜÜÜ×××ÝÝÝÙÙÙ×××ÕÕÕÑÑÑÌÌÌÌÌÌÎÎÎÔÔÔÕÕÕ×××ØØØØØØØØØ×××ÕÕÕÒÒÒÊÊÊÇÇÇ¿¿¿»»»»»»ÒÒÒÕÕÕÆÆÆÐÐо¾¾¸¸¸»»»ººº¸¸¸ÀÀÀÍÍÍÒÒÒÕÕÕÒÒÒÎÎÎÊÊÊÌÌÌÍÍÍÒÒÒÕÕÕÎÎξ¾¾±±±¬¬¬´´´»»»ÃÃÃÉÉÉÉÉÉÃÃû»»´´´ººº´´´¨¨¨¢¢¢¦¦¦¥¥¥¨¨¨³³³³³³»»»¸¸¸³³³©©©­­­±±±···ÀÀÀÀÀÀ¼¼¼µµµ···¾¾¾ÅÅÅÇÇÇÇÇÇÅÅÅÃÃúºº¼¼¼ÅÅÅÅÅÅÕÕÕÉÉÉÌÌÌÔÔÔÜÜÜØØØÑÑÑ×××ääääää¾¾¾¾¾¾ÀÀÀÂÂÂÌÌÌÇÇÇÎÎÎÑÑÑÍÍÍÌÌÌÌÌÌÉÉÉÊÊÊ×××çççàààÕÕÕÎÎÎÎÎÎÎÎÎÊÊÊÌÌÌÑÑѵµµÂ¼¼¼µµµµµµ¼¼¼ÉÉÉÃÃÃÃÃÃÂÂÂÃÃÃÉÉÉÊÊÊÆÆÆÃÃÿ¿¿´´´ºººÉÉÉÊÊÊÅÅÅÃÃÃÂÂÂÝÝÝÕÕÕÑÑÑ×××àààãããâââààà×××ÛÛÛàààæææèèèêêêêêêêêêÝÝÝæææèèèääääääçççäääÝÝÝÛÛÛÛÛÛæææäääíííèèèîîîçççïïïíííèèèääääääçççíííñññòòòñññúúúõõõñññïïïæææèèèëëëäääççççççßßßÝÝÝââââââàààßßßÜÜÜÙÙÙØØØ×××××××××ààààààâââãããäääãããâââàààæææÍÍͺºº´´´±±±´´´ººº¼¼¼ÂÂÂÂÂÂÅÅÅÌÌÌÐÐÐÑÑÑÕÕÕÜÜÜàààâââçççëëëäää×××ÍÍÍÊÊÊÂÂÂÝÝÝäääãããæææÝÝÝÔÔÔÐÐÐÜÜÜÊÊÊÆÆÆÜÜÜêêêãããÝÝÝÝÝÝÔÔÔÕÕÕ×××ÕÕÕÍÍÍÅÅÅÊÊÊÔÔÔ×××ØØØÙÙÙÙÙÙÙÙÙÙÙÙ××××××ÎÎÎÇÇÇÊÊÊÆÆÆ¿¿¿µµµ···ÑÑÑØØØÆÆÆÌÌÌÀÀÀ¾¾¾´´´¼¼¼Â¸¸¸ÇÇÇÒÒÒÔÔÔÔÔÔÕÕÕÎÎÎÅÅÅÂÂÂÅÅÅÍÍÍÕÕÕÒÒÒÆÆÆ¸¸¸³³³¿¿¿ÀÀÀÃÃÃÅÅÅÃÃÃÀÀÀ¼¼¼ºººÂ¾¾¾±±±¨¨¨¨¨¨¤¤¤¦¦¦°°°µµµµµµµµµªªª©©©¨¨¨°°°³³³¿¿¿¿¿¿¼¼¼···´´´¸¸¸»»»»»»¿¿¿ÆÆÆÆÆÆ»»»¿¿¿ÇÇǼ¼¼¸¸¸ÀÀÀÆÆÆÑÑÑØØØÔÔÔÐÐÐØØØçççóóóÕÕÕ¾¾¾»»»ÀÀÀÃÃÃÂÂÂÆÆÆÌÌÌÇÇÇÃÃÃÃÃÃÉÉÉÒÒÒÜÜÜãããÔÔÔÎÎÎÇÇǼ¼¼¸¸¸´´´±±±ÃÃü¼¼³³³¼¼¼ÃÃÿ¿¿¾¾¾µµµ»»»¼¼¼¾¾¾¾¾¾¿¿¿ÃÃÃÇÇÇÉÉÉÆÆÆ´´´µµµÆÆÆÉÉÉÃÃÃÃÃÃÃÃÃ×××ÕÕÕÒÒÒÒÒÒÙÙÙãããæææäääÜÜÜÜÜÜÝÝÝãããçççêêêèèèæææíííèèèæææçççêêêèèèâââÛÛÛ³³³¼¼¼ÒÒÒ×××ÙÙÙâââñññèèèîîîíííëëëëëëíííïïïïïïñññîîîïïïùùùùùùøøøöööïïïñññóóóóóóóóóëëëààààààäääãããèèèæææâââÜÜÜÙÙÙ×××××××××ææææææäääâââàààßßßßßßààààààÒÒÒ»»»¯¯¯³³³¸¸¸¾¾¾ÅÅÅÃÃÃÅÅÅÊÊÊÐÐÐÐÐÐÍÍÍÎÎÎÔÔÔÕÕÕÕÕÕØØØÜÜÜÜÜÜØØØÙÙÙÝÝÝÊÊÊÑÑÑâââëëëæææ×××ÐÐÐÜÜÜÎÎÎÒÒÒÛÛÛíííîîîâââßßßÝÝÝÐÐÐÕÕÕ×××ÑÑÑÉÉÉÉÉÉÐÐÐ×××ØØØØØØÙÙÙÙÙÙÙÙÙØØØ×××ÕÕÕÍÍÍÇÇÇÍÍÍÇÇǼ¼¼´´´ºººÔÔÔÛÛÛÆÆÆÅÅÅ»»»¾¾¾¸¸¸¿¿¿¼¼¼ÆÆÆÎÎÎÔÔÔÒÒÒÑÑÑÐÐÐÌÌÌÆÆÆÅÅÅÃÃÃÇÇÇÐÐÐÒÒÒÌÌÌÅÅÅÂÂÂÇÇÇÇÇÇÆÆÆÅÅÅÃÃÃÂÂÂÀÀÀ¿¿¿¾¾¾Â¾¾¾···´´´­­­¨¨¨¬¬¬¼¼¼µµµ´´´¥¥¥¬¬¬ªªªººº¾¾¾¾¾¾¾¾¾»»»ººººººººº¸¸¸µµµºººÀÀÀ¼¼¼´´´¼¼¼ÉÉÉÅÅż¼¼»»»¾¾¾ÂÂÂÃÃÃÅÅÅÎÎÎÙÙÙäääØØØ»»»¸¸¸¿¿¿¸¸¸ººº¼¼¼µµµµµµ¸¸¸ÀÀÀÒÒÒâââäääÝÝÝÌÌÌÌÌÌÇÇÇÂÂÂÂÂÂÆÆÆÅÅÅÀÀÀººº´´´°°°ÂÂÂÆÆÆºººººº»»»¸¸¸¼¼¼¼¼¼¸¸¸···»»»ÀÀÀÃÃÃÉÉɸ¸¸µµµ¿¿¿ÃÃÃÅÅÅÆÆÆÂ¿¿¿ÉÉÉÎÎÎÊÊÊÉÉÉÐÐÐØØØÜÜÜàààÜÜÜ×××ÔÔÔÔÔÔ×××ÛÛÛÜÜÜëëëãããàààæææêêêçççâââààà°°°´´´¼¼¼¼¼¼¿¿¿ÐÐÐçççîîîäääæææèèèîîîòòòóóóñññîîîóóóòòòóóóòòòòòòöööùùùÿÿÿóóóöööùùùóóóèèèââââââäääßßßÝÝÝÛÛÛÛÛÛÜÜÜàààãããæææîîîëëëçççàààÜÜÜÝÝÝâââæææâââÝÝÝÆÆÆ°°°­­­¯¯¯³³³¿¿¿ÃÃÃÆÆÆÌÌÌÑÑÑÎÎÎÊÊÊÌÌÌÑÑÑÙÙÙÔÔÔÐÐÐÐÐÐÐÐÐÒÒÒÜÜÜæææÛÛÛÀÀÀÐÐÐÛÛÛÑÑÑÒÒÒØØØàààÉÉÉæææîîîëëëàààÙÙÙÛÛÛÍÍÍÑÑÑØØØÕÕÕÊÊÊÉÉÉÔÔÔÙÙÙÕÕÕ×××ØØØØØØØØØØØØÕÕÕÔÔÔÒÒÒÔÔÔÍÍÍÑÑÑÇÇǸ¸¸´´´¼¼¼ÔÔÔÔÔÔÉÉÉÆÆÆ¸¸¸»»»ºººÃÃø¸¸ÒÒÒÒÒÒÔÔÔ×××ÒÒÒÉÉÉÃÃÃÅÅÅÇÇÇÆÆÆÉÉÉÐÐÐÔÔÔÐÐÐÍÍÍÌÌÌÌÌÌÊÊÊÉÉÉÇÇÇÆÆÆÆÆÆÅÅÅÅÅÅ¿¿¿ÇÇÇÉÉÉÅÅÅ···¬¬¬ªªª¸¸¸°°°¯¯¯¤¤¤ªªª¨¨¨µµµººº¾¾¾¾¾¾¿¿¿¾¾¾ºººººº¾¾¾Â¼¼¼ÇÇÇÅÅž¾¾»»»¸¸¸¼¼¼ÅÅÅÀÀÀ¿¿¿¿¿¿ÀÀÀÃÃÃÆÆÆÍÍÍÕÕÕäääëëëÛÛÛÝÝÝæææÝÝÝâââäääçççíííîîîëëëëëëêêêàààÒÒÒÎÎÎÍÍÍÃÃõµµ°°°³³³±±±ªªª­­­ººº»»»¼¼¼µµµ±±±ÀÀÀÆÆÆÅÅÅÇÇÇÇÇǼ¼¼ººº»»»¿¿¿ÆÆÆ¿¿¿¼¼¼¸¸¸ºººÆÆÆÊÊÊ¿¿¿»»»ÌÌÌØØØÕÕÕÎÎÎÍÍÍÎÎÎÍÍÍÔÔÔÒÒÒÐÐÐÌÌÌÉÉÉÎÎÎÙÙÙãããàààÜÜÜÝÝÝääääääßßßßßßäääßßßÔÔÔ¾¾¾³³³±±±¾¾¾ÔÔÔîîîïïïîîîîîîñññõõõùùùùùùùùùæææèèèëëëïïïòòòñññïïïíííïïïîîîïïïñññêêêÝÝÝÝÝÝçççææææææäääæææèèèíííñññóóóèèèèèèçççäääããããããèèèíííâââçççÙÙÙÃÃ÷··­­­­­­ºººÂÂÂÂÂÂÅÅÅÇÇÇÉÉÉÊÊÊÔÔÔÝÝÝãããàààßßßÝÝÝÙÙÙÕÕÕ×××ÛÛÛæææÂÂÂÅÅÅÍÍÍÎÎÎÛÛÛÙÙÙÕÕÕÃÃÃêêêëëëÝÝÝÔÔÔØØØàààÆÆÆ×××ØØØÑÑÑÉÉÉÎÎÎÛÛÛÝÝÝÕÕÕ×××ØØØØØØØØØ×××ÔÔÔÑÑÑÐÐÐÑÑÑÌÌÌÎÎη··¾¾¾ÉÉÉØØØÉÉÉÊÊÊÌÌ̼¼¼¸¸¸µµµÊÊÊÀÀÀ×××ÔÔÔ×××ÙÙÙÔÔÔÆÆÆ¿¿¿ÀÀÀÇÇÇÆÆÆÌÌÌÒÒÒÔÔÔÐÐÐÊÊÊÊÊÊÀÀÀÀÀÀ¿¿¿¿¿¿¿¿¿ÀÀÀÂÂÂÃÃÃÀÀÀÉÉÉÇÇÇ¿¿¿¸¸¸­­­ªªª¾¾¾»»»¼¼¼ººº»»»µµµººº¼¼¼µµµ¸¸¸»»»···¯¯¯¬¬¬¸¸¸ÆÆÆºººÂ¿¿¿ÀÀÀ¾¾¾­­­­­­³³³»»»¿¿¿ÅÅÅÆÆÆÆÆÆÆÆÆÌÌÌÒÒÒÕÕÕäääßßßäääêêêãããææææææàààêêêïïïçççÝÝÝØØØÒÒÒÎÎÎÇÇÇÆÆÆ¾¾¾µµµ´´´ººº»»»¸¸¸ººº¼¼¼µµµ······¸¸¸ÇÇÇÌÌÌÐÐÐÎÎÎÍÍÍÊÊʸ¸¸µµµ»»»ÂÂÂÃÃ÷··³³³ÃÃÃÌÌÌ¿¿¿ÃÃÃÊÊÊÐÐÐÑÑÑÐÐÐÑÑÑÑÑÑÎÎÎÉÉÉÍÍÍÑÑÑÑÑÑÎÎÎÒÒÒÜÜÜäääßßßßßßäääèèèçççâââãããèèèñññèèèÍÍÍÀÀÀ······¾¾¾ØØØëëëíííïïïñññòòòòòòïïïîîîöööõõõíííîîîïïïñññùùùøøøòòòîîîëëëïïïíííâââäääõõõõõõóóóñññîîîíííííííííîîîçççèèèëëëëëëêêêçççæææäääãããçççäää×××ÆÆÆ···´´´¼¼¼ÂÂÂÂÂÂÅÅÅÉÉÉÊÊÊÊÊÊÐÐÐØØØÕÕÕÕÕÕÙÙÙÝÝÝÝÝÝØØØØØØÛÛÛêêê×××ÅÅÅÃÃÃÔÔÔßßßÔÔÔÍÍ;¾¾ãããäääßßßÙÙÙÜÜÜæææÎÎÎØØØÒÒÒÎÎÎÐÐÐÕÕÕÙÙÙÙÙÙØØØØØØÙÙÙÙÙÙØØØ×××ÔÔÔÑÑÑÐÐÐÌÌÌÆÆÆÊÊʼ¼¼µµµÇÇÇÔÔÔÙÙÙÇÇÇÇÇÇÇÇÇÀÀÀ¿¿¿¸¸¸ÑÑÑÎÎÎØØØØØØ×××ÔÔÔÍÍÍÆÆÆÂÂÂÂÂÂÆÆÆÆÆÆÊÊÊÐÐÐÎÎÎÆÆÆÂÂÂÃÃø¸¸¸¸¸¸¸¸¸¸¸»»»¿¿¿ÂÂÂÅÅÅÀÀÀÇÇÇÅÅÅ¿¿¿ÂÂÂÀÀÀ¸¸¸´´´³³³´´´µµµ»»»µµµ´´´±±±···´´´³³³´´´µµµ³³³¯¯¯°°°µµµ°°°···¯¯¯µµµ»»»´´´ººº¾¾¾­­­­­­°°°´´´ººº¿¿¿ÃÃÃÅÅÅÎÎÎØØØ×××ØØØÜÜÜÛÛÛÛÛÛÕÕÕÔÔÔÙÙÙÝÝÝÜÜÜØØØÕÕÕÔÔÔÒÒÒ¾¾¾¼¼¼ºººººº»»»¿¿¿¿¿¿¾¾¾ººº···±±±¿¿¿ÊÊÊÌÌÌÔÔÔÒÒÒÑÑÑÊÊÊÉÉÉÌÌÌÅÅŵµµ³³³»»»ÀÀÀÅÅÅÅÅźºº±±±¼¼¼ÉÉÉÃÃÃÀÀÀ¾¾¾»»»¼¼¼¾¾¾ÂÂÂÉÉÉÑÑÑÉÉÉÌÌÌÎÎÎÐÐÐÐÐÐÐÐÐÔÔÔ×××ÙÙÙÜÜÜâââççççççææææææèèèßßßäääÛÛÛÒÒÒºººµµµ´´´ÀÀÀäääèèèíííïïïïïïëëëèèèæææèèèàààÇÇÇÀÀÀÃÃÃÌÌÌâââçççñññòòòïïïñññóóóïïïïïïüüüíííëëëëëëêêêèèèêêêêêêêêêëëëëëëëëëêêêèèèæææâââÝÝÝîîîâââÙÙÙÑÑÑÀÀÀ´´´µµµ¸¸¸ÃÃÃÃÃÃÇÇÇÎÎÎÐÐÐÊÊÊÉÉÉÊÊÊÕÕÕÕÕÕÙÙÙÝÝÝÝÝÝÛÛÛÛÛÛßßßàààÝÝÝÇÇÇÃÃÃÒÒÒÒÒÒÌÌÌÇÇǼ¼¼âââèèèïïïæææÙÙÙâââÑÑÑØØØÍÍÍÌÌÌØØØÜÜÜÕÕÕÒÒÒÙÙÙÙÙÙÛÛÛÛÛÛÙÙÙØØØÔÔÔÑÑÑÐÐÐÎÎÎÊÊÊÍÍÍ»»»´´´ÉÉÉÑÑÑÐÐÐÎÎÎÃÃþ¾¾ÀÀÀÇÇÇ¿¿¿ØØØÕÕÕÛÛÛÜÜÜ×××ÉÉÉÃÃÃÆÆÆÉÉÉÇÇÇÇÇÇÆÆÆÇÇÇÉÉÉÅÅž¾¾¼¼¼ÀÀÀ¾¾¾¼¼¼¼¼¼¾¾¾ÀÀÀÆÆÆÍÍÍÐÐÐÅÅÅÍÍÍÍÍÍÊÊÊÑÑÑÒÒÒÌÌÌÇÇÇÅÅÅÇÇÇÅÅÅÐÐÐÇÇÇÌÌÌÊÊÊÕÕÕ¿¿¿µµµµµµÀÀÀÊÊʱ±±¥¥¥¯¯¯ÅÅÅÆÆÆÉÉÉÅÅÅ···»»»¾¾¾µµµ¬¬¬¥¥¥ªªª¼¼¼ÊÊÊÍÍÍÇÇÇÔÔÔÕÕÕÔÔÔÔÔÔÙÙÙââââââÙÙÙßßßØØØÔÔÔ×××ÙÙÙÕÕÕÊÊÊÀÀÀÃÃÃÂÂÂÀÀÀÀÀÀ¿¿¿ººº´´´°°°°°°ÇÇÇÐÐÐÒÒÒÐÐÐÎÎÎÒÒÒÉÉÉÒÒÒÇÇÇÆÆÆÎÎÎÉÉɸ¸¸···ÂÂÂÂÂÂÃÃÃÅÅž¾¾±±±···ÅÅÅÉÉÉÅÅÅÅÅÅÆÆÆÆÆÆ¿¿¿»»»ÅÅÅÒÒÒÉÉÉÆÆÆÅÅÅÆÆÆÉÉÉÊÊÊÊÊÊÊÊÊÊÊÊÎÎÎÔÔÔÙÙÙßßßãããâââßßßÜÜÜææææææÙÙÙ³³³³³³¸¸¸¾¾¾¼¼¼¼¼¼¼¼¼ºººººº¼¼¼ÂÂÂÆÆÆÃÃÃÉÉÉÂÂÂÊÊÊÍÍÍÇÇÇÊÊÊÂÂÂäääïïïññññññöööõõõïïïòòòÿÿÿÿÿÿúúúøøøõõõòòòñññïïïëëëçççãããâââãããææææææææææææÊÊʼ¼¼ººº³³³³³³¿¿¿ÅÅÅÆÆÆÃÃÃÃÃÃÇÇÇÊÊÊÊÊÊÍÍÍÑÑÑÒÒÒÕÕÕÜÜÜããããããÝÝÝÛÛÛÜÜÜØØØàààÛÛÛßßßßßßÕÕÕÔÔÔÌÌ̼¼¼ÀÀÀæææêêêÙÙÙääääää×××ÛÛÛÎÎÎÐÐÐØØØØØØÛÛÛÝÝÝÙÙÙÕÕÕØØØÙÙÙÛÛÛØØØÒÒÒÎÎÎÌÌÌÑÑÑÎÎο¿¿ºººÎÎÎÛÛÛÔÔÔÎÎÎÉÉÉÂÂÂÎÎÎÊÊÊÅÅÅÑÑÑ×××ÝÝÝäääÛÛÛÑÑÑÍÍÍÉÉÉÅÅÅÆÆÆÌÌÌÊÊÊÊÊÊÊÊÊÇÇÇÅÅž¾¾¼¼¼Â¿¿¿¾¾¾ÃÃÃÍÍÍÑÑÑÐÐÐÊÊÊÍÍÍÂÂÂÂÂÂÌÌÌÐÐÐÒÒÒÔÔÔÎÎÎÎÎÎÍÍÍÑÑÑ×××ØØØÔÔÔÒÒÒÔÔÔÐÐÐÐÐÐÎÎÎÌÌÌÊÊÊÉÉÉÇÇÇÆÆÆÃÃÃÅÅÅÉÉÉÌÌÌÊÊÊÃÃ÷··¯¯¯···ÀÀÀÇÇÇÀÀÀ···µµµÀÀÀÌÌÌÅÅÅÀÀÀÅÅÅÆÆÆÜÜÜÐÐÐÊÊÊÅÅÅÐÐÐÍÍÍÊÊÊÊÊÊÌÌÌÌÌÌÊÊÊÉÉÉÃÃþ¾¾ÀÀÀºººººº³³³¬¬¬ÅÅÅÍÍÍÍÍÍÐÐÐÑÑÑÒÒÒÒÒÒÒÒÒÑÑÑÇÇÇÉÉÉÎÎÎÉÉɸ¸¸³³³¼¼¼ÂÂÂÀÀÀÉÉÉÇÇÇÃÃþ¾¾°°°¯¯¯¾¾¾ÉÉÉÇÇÇÇÇÇÅÅÅ¿¿¿»»»ººº»»»ÕÕÕÐÐÐÊÊÊÇÇÇÃÃÃÂÂÂÇÇÇÎÎÎÊÊÊÐÐÐÒÒÒÒÒÒÙÙÙãããäääàààâââÒÒÒàààÔÔÔ···µµµººº¼¼¼¾¾¾ÂÂÂÆÆÆÅÅÅÂÂÂÀÀÀÃÃÃÆÆÆÆÆÆÉÉÉÎÎÎÎÎÎÌÌÌÇÇÇÆÆÆÆÆÆÇÇÇÜÜÜíííïïïëëëíííñññóóóöööõõõòòòòòòóóóöööúúúÿÿÿöööïïïèèèçççëëëëëëäääßßß´´´¸¸¸¾¾¾ÀÀÀÀÀÀ¿¿¿¾¾¾¿¿¿ÅÅÅÅÅÅÇÇÇÌÌÌÐÐÐÑÑÑÑÑÑÐÐÐÑÑÑÕÕÕÛÛÛàààâââàààÝÝÝÛÛÛÛÛÛØØØÛÛÛààààààØØØÑÑÑÐÐÐÃÃÃÒÒÒïïïëëëßßßäääßßß×××ÜÜÜÒÒÒÔÔÔÜÜÜÛÛÛÛÛÛÛÛÛÕÕÕÛÛÛÙÙÙÙÙÙ×××ÔÔÔÒÒÒÑÑÑÐÐÐÍÍÍÉÉɼ¼¼¾¾¾ÐÐÐÙÙÙÔÔÔÐÐÐÒÒÒÆÆÆÍÍÍÇÇÇÅÅÅÒÒÒ×××ÜÜÜÙÙÙÒÒÒÎÎÎÎÎÎÍÍÍÉÉÉÇÇÇÊÊÊÌÌÌÊÊÊÉÉÉÇÇÇÅÅÅÃÃÃÀÀÀ¿¿¿ÅÅÅÂÂÂÃÃÃÇÇÇÐÐÐÔÔÔÒÒÒÐÐÐÒÒÒÉÉÉÇÇÇÍÍÍÌÌÌÎÎÎÔÔÔÔÔÔÒÒÒÌÌÌÅÅÅÅÅÅÅÅÅÇÇÇÐÐÐØØØ××××××ÕÕÕÒÒÒÑÑÑÐÐÐÎÎÎÍÍÍÅÅÅÇÇÇÌÌÌÑÑÑÔÔÔÐÐÐÉÉÉÃÃû»»¼¼¼¿¿¿ÃÃþ¾¾µµµµµµ¼¼¼ÎÎÎÌÌÌÍÍÍÉÉÉÕÕÕÌÌÌÐÐÐÔÔÔÎÎÎÎÎÎÍÍÍÍÍÍÌÌÌÊÊÊÆÆÆÃÃû»»´´´»»»¿¿¿ÉÉÉÌÌÌÉÉÉÙÙÙÐÐÐÒÒÒÕÕÕØØØØØØ×××ÕÕÕÒÒÒÕÕÕÎÎÎÌÌÌÃÃ÷··¸¸¸¿¿¿¼¼¼ÃÃÃÆÆÆÆÆÆÆÆÆÅÅż¼¼···¸¸¸ÂÂÂÆÆÆÅÅÅÀÀÀ¿¿¿ÂÂÂÀÀÀ»»»¿¿¿¿¿¿ÃÃÃÉÉÉÉÉÉÆÆÆÇÇÇÍÍÍÒÒÒÑÑÑÐÐÐÍÍÍÍÍÍÑÑÑÒÒÒÒÒÒÜÜÜØØØäääàààÆÆÆ¸¸¸ººº¾¾¾ÀÀÀÅÅÅÉÉÉÌÌÌÌÌÌÉÉÉÃÃÃÀÀÀÇÇÇÌÌÌÎÎÎÐÐÐÍÍÍÊÊÊÇÇÇÇÇÇÂÂÂÔÔÔãããççççççêêêïïïòòòóóóñññîîîîîîîîîñññòòòòòòëëëÜÜÜÇÇǺºº···ººº¾¾¾¿¿¿ÀÀÀÃÃÃÇÇÇÇÇÇÆÆÆÃÃÃÃÃÃÃÃÿ¿¿ÂÂÂÆÆÆÊÊÊÎÎÎÐÐÐÎÎÎÎÎÎÒÒÒ×××ÛÛÛßßßàààßßßÜÜÜÙÙÙÛÛÛØØØÙÙÙÝÝÝÝÝÝÕÕÕÎÎÎÍÍÍÃÃÃàààòòòçççãããâââ×××ÙÙÙÙÙÙÔÔÔÕÕÕÛÛÛÙÙÙ×××ÔÔÔÎÎÎØØØØØØØØØ×××ÕÕÕÒÒÒÑÑÑÎÎÎÉÉɼ¼¼ÅÅÅÔÔÔØØØÒÒÒÑÑÑÕÕÕÉÉÉÉÉÉÆÆÆÇÇÇÒÒÒØØØÝÝÝÐÐÐÍÍÍÌÌÌÎÎÎÐÐÐÍÍÍÌÌÌÌÌÌÌÌÌÊÊÊÉÉÉÇÇÇÆÆÆÅÅÅÃÃÃÃÃÃÅÅÅÅÅÅÆÆÆÊÊÊÎÎÎÒÒÒÑÑÑÐÐÐÐÐÐÊÊÊÐÐÐÔÔÔÎÎÎÍÍÍÕÕÕØØØÊÊÊÃÃÿ¿¿ÀÀÀÀÀÀÀÀÀÅÅÅÊÊÊÇÇÇÇÇÇÆÆÆÃÃÿ¿¿¾¾¾¾¾¾»»»¾¾¾ÃÃÃÉÉÉÎÎÎÑÑÑÑÑÑÐÐл»»¼¼¼ÊÊÊÐÐÐÊÊÊÉÉÉÐÐЯ¯¯´´´ººº¸¸¸Â¾¾¾ÉÉÉ××××××ÒÒÒÌÌÌÅÅÅ¿¿¿¾¾¾¿¿¿ÂÂÂÉÉɼ¼¼ÃÃÃÌÌÌÑÑÑÕÕÕÑÑÑÒÒÒÑÑÑÒÒÒ×××ÙÙÙÙÙÙ×××ÔÔÔÑÑÑÒÒÒÍÍÍÇÇÇ»»»³³³»»»ÃÃÿ¿¿Â¿¿¿¿¿¿ÃÃÃÆÆÆÇÇÇÀÀÀ´´´»»»ÅÅÅÇÇÇÀÀÀ¾¾¾ÃÃÃÃÃü¼¼ººº¼¼¼ÂÂÂÊÊÊÌÌÌÇÇÇÇÇÇÌÌÌÉÉÉÇÇÇÉÉÉÊÊÊÌÌÌÊÊÊÌÌÌÎÎÎÕÕÕÜÜÜâââäääÎÎγ³³³³³»»»ÀÀÀÃÃÃÉÉÉÎÎÎÒÒÒÑÑÑÌÌÌÆÆÆÊÊÊÍÍÍÑÑÑÑÑÑÐÐÐÍÍÍÊÊÊÉÉÉ¿¿¿ÇÇÇÍÍÍÊÊÊÅÅÅÂÂÂÂÂÂÂÂÂÛÛÛØØØÒÒÒÐÐÐÎÎÎÌÌÌÇÇÇÃÃÃÌÌÌÉÉÉÆÆÆÅÅÅÆÆÆÆÆÆÅÅÅÃÃÃÍÍÍÎÎÎÎÎÎÍÍÍÊÊÊÇÇÇÆÆÆÆÆÆ¿¿¿ÂÂÂÇÇÇÌÌÌÎÎÎÐÐÐÐÐÐÐÐÐÕÕÕØØØÜÜÜßßßßßßÝÝÝÙÙÙ×××ÙÙÙ×××ØØØÛÛÛÙÙÙÒÒÒÌÌÌÉÉÉ»»»ãããëëëÜÜÜâââÜÜÜÐÐÐÛÛÛÕÕÕÑÑÑÑÑÑÔÔÔÒÒÒÑÑÑÎÎÎÊÊÊÎÎÎÑÑÑÔÔÔØØØØØØÔÔÔÎÎÎÉÉÉÇÇÇ¿¿¿ÀÀÀÎÎÎÙÙÙÕÕÕÐÐÐÒÒÒÐÐÐÇÇÇÆÆÆÆÆÆÇÇÇÎÎÎ×××ßßßÑÑÑÎÎÎÍÍÍÍÍÍÎÎÎÎÎÎÍÍÍÍÍÍÍÍÍÌÌÌÉÉÉÇÇÇÆÆÆÆÆÆÆÆÆÇÇÇÅÅÅÆÆÆÇÇÇÉÉÉÊÊÊÊÊÊÊÊÊÊÊÊÅÅÅÇÇÇÔÔÔÛÛÛÑÑÑÍÍÍÒÒÒÕÕÕÆÆÆÂÂÂÀÀÀÃÃÃÃÃÿ¿¿¼¼¼¾¾¾¿¿¿¿¿¿¾¾¾»»»ººº¸¸¸···µµµ±±±´´´···¼¼¼ÃÃÃÉÉÉÍÍÍÐÐÐÐÐÐÆÆÆÀÀÀÂÂÂÅÅÅÃÃÃÃÃÃÆÆÆÆÆÆÌÌÌÎÎÎÌÌÌÉÉɼ¼¼¸¸¸ÂÂÂÃÃÃÂÂÂÀÀÀ¾¾¾¾¾¾ÂÂÂÉÉÉÐÐÐÅÅż¼¼ÆÆÆÑÑÑÒÒÒØØØÙÙÙÒÒÒ××××××ØØØÙÙÙÙÙÙØØØ×××ÕÕÕÊÊÊÍÍÍÌÌ̼¼¼­­­´´´¾¾¾ºººÀÀÀººººººººº¸¸¸¾¾¾»»»©©©µµµÀÀÀÉÉÉÅÅÅ¿¿¿¿¿¿ÀÀÀ¿¿¿ººº¸¸¸¸¸¸ººº···´´´µµµººº¼¼¼¾¾¾ÆÆÆÐÐÐÒÒÒÎÎÎÌÌÌÎÎÎÎÎÎÛÛÛÛÛÛâââÒÒÒ±±±³³³ÀÀÀÃÃÃÆÆÆÉÉÉÍÍÍÎÎÎÐÐÐÎÎÎÎÎÎÌÌÌÎÎÎÑÑÑÔÔÔÒÒÒÐÐÐÍÍÍÌÌÌÍÍÍÎÎÎÐÐÐÍÍÍÉÉÉÆÆÆÆÆÆÅÅÅÎÎÎÍÍÍÍÍÍÐÐÐÒÒÒÔÔÔÑÑÑÍÍÍÌÌÌÍÍÍÑÑÑÔÔÔÔÔÔÒÒÒÑÑÑÐÐÐÑÑÑÑÑÑÐÐÐÎÎÎÌÌÌÉÉÉÇÇÇÇÇÇÆÆÆÉÉÉÌÌÌÎÎÎÐÐÐÑÑÑÒÒÒÔÔÔØØØÙÙÙÜÜÜßßßÝÝÝÜÜÜØØØÕÕÕ×××ÕÕÕ×××××××××ÑÑÑÌÌÌÇÇÇ¿¿¿äääãããØØØààà×××ÍÍÍÛÛÛÔÔÔÔÔÔÑÑÑÐÐÐÑÑÑÒÒÒÐÐÐÎÎÎÊÊÊÌÌÌÎÎÎÒÒÒÔÔÔÒÒÒÍÍÍÇÇÇÇÇÇÀÀÀÆÆÆ×××ÜÜÜÕÕÕÐÐÐÑÑÑÉÉÉÉÉÉÇÇÇÉÉÉÇÇÇÅÅÅÍÍÍ×××ÕÕÕÕÕÕÒÒÒÎÎÎÌÌÌÍÍÍÎÎÎÎÎÎÍÍÍÌÌÌÊÊÊÇÇÇÇÇÇÇÇÇÇÇÇÉÉÉÇÇÇÉÉÉÊÊÊÉÉÉÇÇÇÆÆÆÅÅÅÅÅÅÃÃÃÇÇÇÔÔÔÙÙÙÍÍÍÆÆÆÌÌÌÐÐÐÒÒÒÉÉÉ¿¿¿¿¿¿¾¾¾¾¾¾ÀÀÀ¾¾¾¾¾¾¼¼¼»»»ººº¸¸¸······µµµ···¸¸¸»»»¿¿¿ÅÅÅÊÊÊÎÎÎÒÒÒÔÔÔÍÍÍ»»»¾¾¾¿¿¿¼¼¼¼¼¼ÀÀÀÀÀÀÆÆÆÉÉÉÀÀÀ¸¸¸¼¼¼···¾¾¾ÅÅÅÊÊÊÊÊÊÉÉÉÇÇÇÇÇǺºº¾¾¾ÌÌÌÕÕÕÒÒÒØØØàààÙÙÙÜÜÜÛÛÛØØØ××××××ØØØÙÙÙÛÛÛÒÒÒ××××××ÆÆÆµµµµµµµµµªªª···´´´······µµµÂÂÂÉÉÉÀÀÀµµµµµµ¼¼¼ÅÅÅÆÆÆÂ¿¿¿ÂÂÂÇÇÇÃÃÃÀÀÀÀÀÀ¼¼¼¸¸¸»»»ÀÀÀ¿¿¿¿¿¿ÆÆÆÐÐÐÑÑÑÌÌÌÇÇÇÉÉÉÉÉÉ×××ÕÕÕàààÙÙÙ¸¸¸µµµÂÂÂÂÂÂÆÆÆÌÌÌÍÍÍÊÊÊÉÉÉÊÊÊÎÎÎÌÌÌÎÎÎÑÑÑÔÔÔÔÔÔÒÒÒÐÐÐÎÎÎÊÊÊÉÉÉÉÉÉÉÉÉÉÉÉÇÇÇÉÉÉÊÊÊÆÆÆÇÇÇÌÌÌÑÑÑÕÕÕØØØ×××ÔÔÔ××××××ÕÕÕÒÒÒÑÑÑÒÒÒÔÔÔ×××ÒÒÒÒÒÒÑÑÑÑÑÑÐÐÐÎÎÎÍÍÍÌÌÌÍÍÍÍÍÍÍÍÍÎÎÎÐÐÐÒÒÒÔÔÔÕÕÕÙÙÙÛÛÛÝÝÝßßßÝÝÝÛÛÛØØØÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÔÔÔÑÑÑÍÍÍÇÇÇÔÔÔèèèàààÜÜÜàààÒÒÒÍÍÍØØØ×××ÛÛÛ×××ÔÔÔ×××ØØØ××××××ÎÎÎÌÌÌÉÉÉÉÉÉÌÌÌÍÍÍÌÌÌÉÉÉÅÅÅ¿¿¿ÊÊÊÛÛÛÜÜÜÔÔÔÑÑÑÐÐÐÉÉÉÌÌÌÆÆÆÊÊÊÉÉɾ¾¾ÂÂÂÌÌÌÔÔÔØØØ×××ÑÑÑÌÌÌÌÌÌÎÎÎÎÎÎÌÌÌÌÌÌÊÊÊÉÉÉÉÉÉÇÇÇÇÇÇÇÇÇÌÌÌÌÌÌÌÌÌÊÊÊÉÉÉÆÆÆÅÅÅÃÃÃÉÉÉÉÉÉÑÑÑÑÑÑÅÅÅ¿¿¿ÇÇÇÍÍÍÕÕÕÊÊÊÀÀÀ¿¿¿¿¿¿¾¾¾¿¿¿Â¸¸¸¸¸¸······µµµµµµµµµµµµ¸¸¸¸¸¸ººº»»»¼¼¼¿¿¿ÅÅÅÇÇÇÇÇÇ×××ÜÜÜÒÒÒÎÎÎÒÒÒÕÕÕÒÒÒÊÊÊÉÉɾ¾¾ÆÆÆÌÌÌÎÎÎÆÆÆÌÌÌÉÉÉÌÌÌÎÎÎÎÎÎÌÌÌÅÅÅ¿¿¿»»»»»»ÊÊÊÔÔÔØØØÔÔÔÔÔÔÜÜÜ×××ØØØÔÔÔÎÎÎÊÊÊÊÊÊÎÎÎÔÔÔØØØÛÛÛØØØ×××ÐÐÐÉÉÉÇÇÇ¿¿¿­­­¥¥¥¦¦¦©©©ªªªªªª´´´¿¿¿Âººº­­­¬¬¬¼¼¼ÉÉÉÇÇÇÃÃÃÃÃþ¾¾¼¼¼¾¾¾¿¿¿¾¾¾ººº»»»¿¿¿ÅÅÅÂÂÂÀÀÀÅÅÅÇÇÇÉÉÉÇÇÇÉÉÉÇÇÇÑÑÑÔÔÔÝÝÝØØØºººªªª¯¯¯´´´¼¼¼ÆÆÆÊÊÊÌÌÌÌÌÌÍÍÍÎÎÎÊÊÊÌÌÌÎÎÎÒÒÒÕÕÕÕÕÕÒÒÒÐÐÐÔÔÔÐÐÐÍÍÍÌÌÌÉÉÉÆÆÆÅÅÅÇÇÇÑÑÑÔÔÔØØØÛÛÛÜÜÜÛÛÛÙÙÙØØØ×××ØØØÛÛÛÜÜÜÝÝÝÝÝÝÝÝÝÝÝÝÕÕÕÕÕÕÕÕÕ×××ØØØØØØÕÕÕÔÔÔÐÐÐÎÎÎÎÎÎÐÐÐÔÔÔÕÕÕ×××ÕÕÕÛÛÛÜÜÜÝÝÝßßßÝÝÝÛÛÛØØØ×××ÕÕÕÕÕÕÕÕÕÒÒÒÑÑÑÐÐÐÊÊÊÅÅÅäääçççÜÜÜßßßÝÝÝÎÎÎÐÐÐÔÔÔØØØßßßÜÜÜ×××ÛÛÛÜÜÜØØØØØØÕÕÕÐÐÐÉÉÉÇÇÇÉÉÉÊÊÊÉÉÉÆÆÆ¾¾¾¼¼¼ÌÌÌÛÛÛØØØÔÔÔÒÒÒÎÎÎÌÌÌÌÌÌ¿¿¿ÇÇÇÍÍÍÀÀÀÂÂÂÆÆÆÉÉÉÔÔÔÛÛÛ×××ÎÎÎÍÍÍÍÍÍÍÍÍÌÌÌÌÌÌÌÌÌÊÊÊÉÉÉÇÇÇÆÆÆÅÅÅÉÉÉÉÉÉÇÇÇÇÇÇÆÆÆÅÅÅÃÃÃÂÂÂÇÇÇÅÅÅÊÊÊÍÍÍÃÃÃÀÀÀÇÇÇÌÌÌÉÉɾ¾¾ÀÀÀ¿¿¿¼¼¼¼¼¼¸¸¸¸¸¸¸¸¸ºººººººººººººººµµµ¸¸¸ººººººººº»»»¿¿¿ÂÂÂÂÂÂÑÑÑÜÜÜÛÛÛ×××××××××ÕÕÕÔÔÔÎÎλ»»ÀÀÀÃÃÃÌÌÌÅÅÅÎÎÎÊÊÊÇÇÇÅÅÅÂÂÂÂÂÂÂÂÂÂÂÂÀÀÀ´´´ÌÌÌÐÐÐÔÔÔÕÕÕÕÕÕÜÜÜ×××ÒÒÒÍÍÍÇÇÇÃÃÃÃÃÃÉÉÉÐÐÐÕÕÕÙÙÙÒÒÒÒÒÒÔÔÔÒÒÒÒÒÒÍÍÍÀÀÀÇÇÇÉÉÉÆÆÆÂ¿¿¿¸¸¸···¼¼¼¼¼¼³³³­­­´´´¾¾¾ÀÀÀÃÃÃÅÅÅÅÅÅÃÃÃÅÅÅÇÇÇÅÅÅÀÀÀÂÂÂÆÆÆÅÅÅ¿¿¿¿¿¿ÅÅÅÌÌÌÍÍÍÉÉÉÉÉÉÊÊÊÔÔÔÙÙÙØØØÇÇÇ´´´±±±µµµ¸¸¸¼¼¼ÃÃÃÊÊÊÎÎÎÎÎÎÌÌÌÆÆÆÇÇÇÌÌÌÑÑÑÕÕÕ×××ÔÔÔÑÑÑÌÌÌÇÇÇÆÆÆÉÉÉÇÇÇÅÅÅÅÅÅÉÉÉÇÇÇÍÍÍÔÔÔØØØÙÙÙÛÛÛÝÝÝàààÝÝÝÜÜÜÙÙÙØØØØØØÙÙÙÛÛÛÛÛÛØØØ×××ØØØÛÛÛÜÜÜÜÜÜÙÙÙ×××ÔÔÔÑÑÑÒÒÒ×××ßßßâââßßßÛÛÛÜÜÜÝÝÝßßßßßßßßßÜÜÜÙÙÙØØØÕÕÕ×××ÕÕÕÐÐÐÍÍÍÌÌÌÆÆÆ¾¾¾ëëëàààÔÔÔßßßÛÛÛÌÌÌÒÒÒÑÑÑÕÕÕàààÝÝÝØØØÜÜÜÛÛÛÔÔÔÔÔÔ×××ÑÑÑÍÍÍÍÍÍÍÍÍÊÊÊÅÅÅ¿¿¿···ºººÊÊÊØØØÕÕÕÒÒÒÔÔÔÎÎÎÌÌÌÇÇǵµµÃÃÃÑÑÑÇÇÇÇÇÇÉÉɼ¼¼ÍÍÍÛÛÛÛÛÛÒÒÒÎÎÎÍÍÍÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÉÉÉÇÇÇÅÅÅÃÃÃÃÃÃÂÂÂÂÂÂÂÂÂÃÃÃÂÂÂÀÀÀ¾¾¾¾¾¾¼¼¼ÆÆÆÎÎÎÉÉÉÆÆÆÌÌÌÍÍÍ»»»···»»»¾¾¾¾¾¾»»»»»»µµµµµµ······¸¸¸¸¸¸ºººººº¸¸¸»»»¾¾¾¾¾¾¾¾¾¿¿¿ÂÂÂÅÅÅÂÂÂÊÊÊÔÔÔÛÛÛÙÙÙ××××××ÙÙÙÕÕÕÎÎθ¸¸»»»ºººÀÀÀ»»»ÅÅÅÃÃÃÀÀÀ¾¾¾¾¾¾¾¾¾¼¼¼¸¸¸µµµµµµÐÐÐÌÌÌÍÍÍÔÔÔÒÒÒÕÕÕÎÎÎØØØÒÒÒÍÍÍÉÉÉÊÊÊÐÐÐØØØÜÜÜØØØÒÒÒÕÕÕ×××ÐÐÐÍÍÍÎÎÎÊÊÊÇÇÇÊÊÊÆÆÆÆÆÆÆÆÆ¸¸¸­­­´´´¾¾¾¾¾¾ººº±±±¯¯¯´´´¿¿¿ÇÇÇÊÊÊÆÆÆÂ¿¿¿»»»µµµ···¼¼¼ÉÉÉÇÇÇÅÅÅÃÃÃÉÉÉÑÑÑÍÍÍÃÃÃÉÉÉÃÃÃÒÒÒÛÛÛâââäää×××ÔÔÔÊÊÊ»»»¼¼¼ÅÅÅÊÊÊÇÇÇÀÀÀÅÅÅÆÆÆÊÊÊÐÐÐÕÕÕØØØÕÕÕÒÒÒÐÐÐÌÌÌÊÊÊÍÍÍÌÌÌÇÇÇÉÉÉÎÎÎÌÌÌÒÒÒÙÙÙÛÛÛÙÙÙØØØÛÛÛßßß×××××××××ÙÙÙÛÛÛÜÜÜÛÛÛØØØ××××××ØØØÛÛÛÜÜÜÜÜÜØØØÔÔÔ×××ÕÕÕØØØàààëëëîîîèèèâââÝÝÝÝÝÝßßßàààßßßÝÝÝÛÛÛÙÙÙ×××ØØØÕÕÕÍÍÍÉÉÉÇÇÇÀÀÀ¸¸¸îîîïïïÙÙÙâââââââââÕÕÕÐÐÐÕÕÕÕÕÕ×××ÙÙÙÛÛÛÙÙÙ×××ÔÔÔÔÔÔÐÐÐÎÎÎÐÐÐÎÎÎÇÇÇÃÃÃÅÅŵµµÌÌÌÙÙÙÕÕÕÔÔÔÙÙÙÔÔÔÉÉÉÎÎÎÇÇǾ¾¾´´´±±±µµµÀÀÀÇÇÇÇÇÇÆÆÆÌÌÌÜÜÜãããÎÎÎÅÅÅÒÒÒÊÊÊÊÊÊÆÆÆÀÀÀÃÃÃÉÉÉÆÆÆ¿¿¿ÃÃÃÂÂÂÀÀÀ¿¿¿¾¾¾¾¾¾¾¾¾¾¾¾ÂÂÂÀÀÀ¾¾¾¼¼¼ÅÅÅÌÌÌÇÇÇ¿¿¿¸¸¸¸¸¸ººº»»»»»»»»»ºººººº¸¸¸···µµµµµµµµµ···¸¸¸ºººººº¾¾¾»»»ºººÀÀÀÀÀÀÃÃÃÑÑÑ×××ÙÙÙÛÛÛ×××ØØØÛÛÛÙÙÙÕÕÕØØØÉÉÉ»»»ººº¾¾¾¾¾¾¿¿¿ÀÀÀ¿¿¿¼¼¼»»»¼¼¼¿¿¿¾¾¾»»»¸¸¸´´´ÅÅÅÐÐÐÎÎÎÊÊÊÍÍÍÎÎÎÎÎÎÐÐÐÑÑÑÌÌÌÅÅÅÊÊÊ×××ÙÙÙÕÕÕ××××××ÕÕÕÔÔÔÑÑÑÐÐÐÎÎÎÎÎÎÊÊÊÌÌÌÆÆÆÇÇÇÉÉɺºº©©©¬¬¬±±±»»»ÀÀÀ»»»¯¯¯ªªª³³³¾¾¾ÅÅž¾¾¸¸¸µµµ±±±¯¯¯´´´¾¾¾ÍÍ;¾¾ÉÉÉÒÒÒÒÒÒÎÎÎÍÍÍÆÆÆÇÇÇÊÊÊÐÐÐ×××ÜÜÜßßßßßßâââØØØÀÀÀ´´´¼¼¼¿¿¿¼¼¼ÀÀÀ¿¿¿ÂÂÂÆÆÆÉÉÉÎÎÎÔÔÔÑÑÑÌÌÌÉÉÉÆÆÆÊÊÊÊÊÊÊÊÊÌÌÌÉÉÉÇÇÇÌÌÌÎÎÎÒÒÒÔÔÔÕÕÕ×××ÙÙÙÛÛÛÙÙÙ××××××ØØØÜÜÜÝÝÝÝÝÝÜÜÜÙÙÙÛÛÛÜÜÜÝÝÝßßßÝÝÝÜÜÜÛÛÛÝÝÝÙÙÙÙÙÙãããîîîñññçççÜÜÜßßßÛÛÛØØØÙÙÙÝÝÝßßßÛÛÛ×××ÑÑÑ×××ÅÅż¼¼ÆÆÆäääâââäääèèèíííÙÙÙâââàààâââØØØÔÔÔÛÛÛÙÙÙØØØØØØØØØ×××ÔÔÔÑÑÑÎÎÎÍÍÍÌÌÌÍÍÍÉÉÉÃÃÿ¿¿¾¾¾¿¿¿ÐÐÐÙÙÙÕÕÕÔÔÔ×××ÑÑÑÆÆÆÊÊÊÇÇÇÀÀÀºººµµµ···¼¼¼ÀÀÀÇÇÇÃÃÃÀÀÀÌÌÌÛÛÛ×××ÊÊÊÉÉÉÇÇÇÊÊÊÉÉÉÅÅÅÃÃÃÃÃÃÃÃÃÂÂÂÀÀÀÀÀÀ¿¿¿¼¼¼»»»»»»»»»»»»»»»»»»¸¸¸···¼¼¼Â¿¿¿¸¸¸µµµ···¸¸¸ººº»»»»»»ºººººº···············¸¸¸ººº»»»···µµµºººÆÆÆÍÍÍÇÇÇÉÉÉÔÔÔÍÍÍÎÎÎÐÐÐÒÒÒÙÙÙßßßØØØÍÍÍÃÃúºº´´´···¾¾¾¿¿¿ÀÀÀÃÃþ¾¾¾¾¾¿¿¿¿¿¿¿¿¿¾¾¾¼¼¼»»»°°°¸¸¸ÀÀÀÅÅÅÊÊÊÍÍÍÍÍÍÌÌÌ×××ÜÜÜÕÕÕÉÉÉÌÌÌÙÙÙÛÛÛÐÐÐÍÍÍÍÍÍÎÎÎÎÎÎÎÎÎÎÎÎÐÐÐÐÐÐÆÆÆÅÅŵµµ©©©¥¥¥³³³ºººÀÀÀÀÀÀ»»»······ººº±±±±±±±±±±±±­­­¬¬¬¯¯¯´´´ÉÉÉÆÆÆÀÀÀ¿¿¿ÃÃÃÊÊÊÉÉÉÅÅÅÊÊÊÊÊÊÉÉÉÉÉÉÊÊÊÎÎÎÒÒÒÕÕÕÝÝÝããããããÝÝÝ×××ÉÉɺºº´´´³³³µµµ¸¸¸¸¸¸¾¾¾ÆÆÆÌÌÌÌÌÌÌÌÌÊÊÊÊÊÊÉÉÉÇÇÇÉÉÉÉÉÉÉÉÉÊÊÊÍÍÍÑÑÑÒÒÒÔÔÔÔÔÔ×××ØØØØØØ××××××ØØØÛÛÛÝÝÝÝÝÝÜÜÜÜÜÜÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÜÜÜÜÜÜÙÙÙÙÙÙÙÙÙßßßãããäääàààÜÜÜÜÜÜÙÙÙÙÙÙÛÛÛßßßßßßÛÛÛ×××ÐÐÐÒÒÒÉÉÉÒÒÒÛÛÛëëëãããçççÜÜÜãããÔÔÔßßßâââçççãããäääçççâââÙÙÙÔÔÔÒÒÒÔÔÔÔÔÔÕÕÕÐÐÐÎÎÎÌÌÌÇÇÇÅÅÅÃÃÃÃÃÃÃÃÃÌÌÌÒÒÒØØØ×××ÔÔÔÒÒÒÍÍÍÃÃÃÇÇÇÇÇÇÆÆÆÂ¼¼¼¸¸¸······ÆÆÆÇÇÇÀÀÀÀÀÀÐÐÐÛÛÛÔÔÔÊÊÊÇÇÇÉÉÉÊÊÊÉÉɾ¾¾¿¿¿ÅÅÅÀÀÀ¿¿¿¼¼¼»»»¸¸¸¸¸¸······¸¸¸¸¸¸···µµµ···ººº¸¸¸´´´³³³´´´µµµ¸¸¸ºººººººººººº······¸¸¸¸¸¸¸¸¸ººº»»»»»»¿¿¿µµµ¼¼¼ÊÊÊÅÅŵµµ°°°µµµººº¿¿¿ÇÇÇÎÎÎÔÔÔÒÒÒÇÇÇ»»»¾¾¾»»»»»»¿¿¿ÂÂÂÂÂÂÀÀÀ¿¿¿ÃÃÃÆÆÆÅÅÅÂÂÂÀÀÀ¾¾¾¾¾¾´´´¯¯¯¯¯¯¸¸¸ÅÅÅÉÉÉÊÊÊÊÊÊÑÑÑØØØÕÕÕÇÇÇÌÌÌÝÝÝàààÒÒÒÑÑÑÑÑÑÐÐÐÐÐÐÎÎÎÎÎÎÍÍÍÍÍÍÌÌÌÉÉÉÉÉÉÇÇÇÃÃÿ¿¿µµµ¨¨¨¬¬¬°°°···¾¾¾Â¿¿¿¼¼¼ÀÀÀÂÂÂÃÃÃÂÂÂÂÂÂÀÀÀ»»»µµµ¿¿¿ÇÇÇÇÇǼ¼¼¾¾¾ÌÌÌÑÑÑÌÌÌÆÆÆÆÆÆÃÃÃÂÂÂÂÂÂÇÇÇÒÒÒÛÛÛâââãããëëëîîîçççäääãããßßßââââââÙÙÙÉÉɾ¾¾¾¾¾¿¿¿ÀÀÀÂÂÂÆÆÆÅÅÅÆÆÆÇÇÇÆÆÆÆÆÆÇÇÇÊÊÊÍÍÍÐÐÐÑÑÑÑÑÑÑÑÑÒÒÒÕÕÕ×××ÕÕÕÕÕÕØØØÛÛÛÜÜÜÜÜÜÜÜÜßßßÜÜÜÙÙÙ××××××ØØØÛÛÛÜÜÜÙÙÙÛÛÛÜÜÜÛÛÛÙÙÙÙÙÙÜÜÜßßßØØØØØØÙÙÙÜÜÜàààßßßÙÙÙÕÕÕÐÐÐÌÌÌÇÇÇãããëëëíííãããëëëæææíííÙÙÙßßßÜÜÜàààßßßãããçççäääßßßÜÜÜÙÙÙØØØÔÔÔÑÑÑÒÒÒÑÑÑÊÊÊÅÅÅÅÅÅÌÌÌÑÑÑÒÒÒÕÕÕÔÔÔ××××××ÒÒÒÒÒÒÎÎÎÅÅÅÇÇÇÊÊÊÊÊÊÇÇÇÀÀÀººº³³³°°°ÆÆÆÎÎÎÍÍÍÅÅÅÉÉÉÔÔÔÙÙÙØØØÎÎÎÊÊÊÇÇÇÇÇǼ¼¼¿¿¿ÆÆÆÀÀÀ¿¿¿¾¾¾»»»¸¸¸······µµµººººººººº······µµµµµµ´´´°°°±±±³³³µµµ···¸¸¸ººº»»»¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¿¿¿ºººÅÅÅÎÎÎÀÀÀ´´´µµµ···ººº¾¾¾¾¾¾ºººµµµµµµ¸¸¸¼¼¼ÀÀÀÂÂÂÅÅÅÆÆÆÅÅÅÂÂÂÀÀÀÀÀÀÂÂÂÅÅÅÅÅÅÃÃÃÃÃÃÃÃÿ¿¿ººº»»»­­­¨¨¨³³³¿¿¿ÂÂÂÆÆÆÌÌÌÌÌÌÌÌÌÉÉÉÃÃÃÇÇÇØØØßßßÕÕÕÔÔÔÒÒÒÑÑÑÐÐÐÐÐÐÎÎÎÍÍÍÌÌÌÊÊÊÆÆÆÇÇÇÆÆÆ¿¿¿ÀÀÀ»»»©©©¬¬¬­­­°°°´´´¸¸¸»»»¼¼¼¼¼¼Â¿¿¿¿¿¿ÅÅÅÉÉÉÀÀÀ´´´µµµÃÃÃÉÉÉÀÀÀ¿¿¿ÉÉÉÐÐÐÍÍÍÎÎÎÎÎÎÌÌÌÅÅÅ¿¿¿ÂÂÂÊÊÊÔÔÔßßß×××ÛÛÛàààßßßçççíííçççèèèêêêâââÐÐÐÀÀÀ»»»¼¼¼¿¿¿µµµ¿¿¿¼¼¼ÂÂÂÉÉÉÅÅÅÅÅÅÃÃÃÊÊÊÍÍÍÐÐÐÐÐÐÐÐÐÐÐÐÑÑÑÒÒÒÔÔÔÔÔÔÕÕÕ×××ÙÙÙÛÛÛÜÜÜÜÜÜßßßÜÜÜØØØÕÕÕÔÔÔÕÕÕ×××ÙÙÙÙÙÙÛÛÛÛÛÛÙÙÙØØØÙÙÙÜÜÜàààÕÕÕ×××ÙÙÙÝÝÝàààßßßÙÙÙÔÔÔÎÎÎÇÇÇÂÂÂãããëëëëëëçççïïïëëëñññÛÛÛßßßÛÛÛßßßßßßæææÝÝÝâââæææêêêèèèàààÔÔÔÌÌÌÎÎÎÌÌÌÇÇÇÉÉÉÍÍÍÕÕÕÙÙÙÛÛÛ×××ÒÒÒÕÕÕ×××ÑÑÑÔÔÔÔÔÔÉÉÉÉÉÉÌÌÌÍÍÍÉÉɺºº³³³¯¯¯ÆÆÆÌÌÌÑÑÑÍÍÍÇÇÇÌÌÌÕÕÕÛÛÛØØØÍÍÍÅÅÅÃÃÃÃÃÃÀÀÀÀÀÀÆÆÆÃÃÿ¿¿¼¼¼»»»ººº¸¸¸¸¸¸»»»ºººººº¸¸¸µµµ³³³³³³´´´°°°°°°±±±³³³µµµ¸¸¸ººº»»»ºººººº¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸»»»ÀÀÀÌÌÌÊÊʺºº¸¸¸ÂÂÂÃÃÃÃÃÃÆÆÆÉÉÉÇÇǼ¼¼¼¼¼¿¿¿ÀÀÀÅÅÅÉÉÉÇÇÇÃÃÃÃÃÃÃÃÃÅÅźººººº¸¸¸¸¸¸¿¿¿ÅÅÅÀÀÀµµµµµµªªªªªª¸¸¸ÂÂÂÂÂÂÅÅÅÍÍÍÒÒÒÅÅÅÂÂÂÅÅÅÅÅÅÍÍÍØØØ×××ÎÎÎÍÍÍÌÌÌÍÍÍÐÐÐÑÑÑÐÐÐÎÎÎÌÌÌÇÇÇÉÉÉÇÇÇÀÀÀÅÅÅÃÃô´´¾¾¾¼¼¼¸¸¸±±±­­­¯¯¯´´´ºººªªª°°°´´´´´´ºººÃÃÃÅÅÅÀÀÀ³³³»»»ÂÂÂÃÃÃÀÀÀ¾¾¾¿¿¿ÀÀÀÍÍÍÐÐÐÐÐÐÊÊÊÂÂÂÀÀÀÆÆÆÍÍÍÊÊÊÉÉÉ×××ããããããäääâââÕÕÕäääëëëîîîçççàààßßßâââäää¿¿¿ÆÆÆººº¼¼¼ÆÆÆÂÂÂÅÅÅÅÅÅÉÉÉÌÌÌÎÎÎÐÐÐÐÐÐÐÐÐÑÑÑÒÒÒÑÑÑÒÒÒÔÔÔ×××ØØØÙÙÙÛÛÛÜÜÜÜÜÜÛÛÛØØØ×××ÔÔÔÒÒÒÒÒÒÒÒÒÔÔÔÔÔÔÒÒÒÔÔÔØØØÛÛÛÜÜÜÜÜÜÕÕÕ×××ÙÙÙÜÜÜÝÝÝÜÜÜØØØÔÔÔÌÌÌÉÉÉÂÂÂäääëëëîîîïïïñññçççîîîÙÙÙàààÝÝÝäääæææíííãããããããããäääãããßßßÙÙÙÕÕÕÇÇÇÂÂÂÃÃÃÎÎÎØØØÙÙÙ×××ÕÕÕÔÔÔÑÑÑÕÕÕÕÕÕÐÐÐØØØÛÛÛÍÍÍÊÊÊÌÌÌÌÌÌÉÉɺºº´´´±±±ÃÃÃÂÂÂÇÇÇÍÍÍÊÊÊÊÊÊÎÎÎÎÎÎÜÜÜÑÑÑÇÇÇÃÃÃÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÃÃÃÀÀÀ¿¿¿¼¼¼¼¼¼»»»»»»ººº·········´´´°°°°°°±±±°°°°°°±±±³³³´´´···ººº»»»»»»ººº¸¸¸¸¸¸¸¸¸ººº¼¼¼¾¾¾ÆÆÆÍÍÍÑÑÑÅÅŵµµ···¾¾¾¿¿¿ÍÍÍÅÅž¾¾¿¿¿ÂÂÂÃÃÃÃÃÃÃÃð°°´´´µµµ°°°ªªª©©©ªªªªªª°°°°°°¯¯¯¯¯¯¸¸¸Â¿¿¿´´´ªªª¦¦¦¬¬¬¾¾¾ÇÇÇÆÆÆÆÆÆÌÌÌÔÔÔ¿¿¿¿¿¿ÉÉÉÉÉÉÍÍÍÙÙÙÝÝÝ×××ÔÔÔÑÑÑÑÑÑÔÔÔÔÔÔÑÑÑÍÍÍÍÍÍÊÊÊÊÊÊÇÇÇÅÅÅÇÇÇÉÉÉÅÅÅÊÊÊÉÉÉÃÃúºº³³³³³³¼¼¼ÆÆÆÇÇÇÐÐÐÒÒÒÉÉÉ»»»µµµººº¿¿¿µµµ´´´»»»ÆÆÆÇÇÇÀÀÀ¾¾¾ÃÃÿ¿¿ÆÆÆÌÌÌÊÊÊÆÆÆÂÂÂÅÅÅÉÉÉ¿¿¿ÆÆÆÔÔÔÝÝÝßßßâââæææäääÝÝÝæææíííëëëèèèèèèçççää䨨ØÙÙÙ»»»···ÀÀÀ¼¼¼ÅÅÅÆÆÆÆÆÆÉÉÉÌÌÌÍÍÍÍÍÍÎÎÎÐÐÐÑÑÑÎÎÎÑÑÑÔÔÔÕÕÕ×××ØØØÛÛÛÜÜÜÛÛÛÛÛÛØØØ×××ÔÔÔÑÑÑÎÎÎÍÍÍÍÍÍÊÊÊÉÉÉÍÍÍÒÒÒ××××××ÕÕÕØØØØØØÙÙÙÛÛÛÛÛÛÙÙÙ×××ÕÕÕÌÌÌÍÍÍÇÇÇëëëñññóóóøøøòòòñññöööâââçççâââãããßßßàààêêêäääÝÝÝÙÙÙÙÙÙÛÛÛÜÜÜÜÜÜÎÎÎÂÂÂÀÀÀÑÑÑÛÛÛ×××ÑÑÑÑÑÑÑÑÑÑÑÑØØØÕÕÕÎÎÎÛÛÛàààÎÎÎÊÊÊÌÌÌÌÌÌÉÉÉ»»»···´´´ººº¸¸¸ÂÂÂÍÍÍÎÎÎÐÐÐÍÍÍÂÂÂÙÙÙ×××ÐÐÐÉÉÉÆÆÆÆÆÆÆÆÆÅÅÅÃÃÃÂÂÂÀÀÀ¿¿¿¾¾¾¾¾¾¼¼¼¼¼¼ºººµµµ´´´···µµµ±±±¯¯¯±±±±±±±±±±±±±±±´´´µµµ¸¸¸ººº»»»ººº¸¸¸ººº»»»ÀÀÀÅÅÅÉÉÉÍÍÍÐÐÐÌÌÌÅÅÅÂÂÂÀÀÀÀÀÀÅÅźºº±±±¯¯¯´´´ººººººµµµ³³³ÀÀÀÆÆÆÆÆÆ¾¾¾¸¸¸······µµµ³³³¸¸¸···±±±´´´¾¾¾¾¾¾···¬¬¬¦¦¦©©©···ÃÃÃÇÇÇÇÇÇÉÉÉÎÎξ¾¾ÀÀÀÊÊÊÉÉÉÑÑÑÜÜÜÛÛÛÙÙÙÕÕÕÐÐÐÎÎÎÎÎÎÍÍÍÉÉÉÃÃÃÀÀÀÀÀÀ¼¼¼»»»¼¼¼¼¼¼¿¿¿ÇÇÇÊÊÊÊÊÊÊÊÊÆÆÆÃÃÃÅÅÅÌÌÌÑÑÑÎÎÎÔÔÔØØØÕÕÕÇÇǾ¾¾¿¿¿ÆÆÆ»»»³³³´´´ÀÀÀÊÊÊÇÇÇÆÆÆÊÊÊÃÃÃÉÉÉÎÎÎÎÎÎÇÇÇÀÀÀ¾¾¾¼¼¼ÅÅÅÇÇÇÆÆÆÉÉÉÐÐÐ×××ÝÝÝæææÛÛÛàààæææçççêêêíííêêêäääãããââ⺺º³³³¾¾¾¸¸¸¿¿¿¿¿¿ÂÂÂÅÅÅÇÇÇÊÊÊÊÊÊÌÌÌÍÍÍÎÎÎÍÍÍÐÐÐÒÒÒÕÕÕÕÕÕ×××ÙÙÙÜÜÜÛÛÛÛÛÛØØØÕÕÕÑÑÑÎÎÎÍÍÍÌÌÌÉÉÉÇÇÇÇÇÇÊÊÊÎÎÎÒÒÒÕÕÕÕÕÕÛÛÛÛÛÛÙÙÙØØØ×××ÕÕÕÕÕÕÕÕÕÐÐÐÎÎÎÆÆÆïïïóóóóóóüüüöööîîîõõõãããêêêççççççßßßÝÝÝãããàààßßßÝÝÝÜÜÜÛÛÛ×××ÔÔÔÝÝÝÇÇÇÀÀÀÐÐÐÛÛÛÕÕÕÐÐÐÔÔÔÎÎÎÑÑÑÛÛÛÕÕÕÍÍÍÜÜÜâââÎÎÎÉÉÉÊÊÊÌÌÌÉÉÉÃÃü¼¼¸¸¸µµµ°°°···ÆÆÆÐÐÐÐÐÐÔÔÔÎÎξ¾¾ÔÔÔÙÙÙØØØÎÎÎÆÆÆÆÆÆÇÇÇÅÅÅÂÂÂÂÂÂÀÀÀ¿¿¿¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾···µµµ¸¸¸¸¸¸´´´±±±´´´±±±±±±±±±±±±³³³µµµ¸¸¸ººº»»»ººº¸¸¸ººº¿¿¿ÆÆÆÍÍÍÑÑÑÉÉÉÆÆÆ»»»»»»ÃÃû»»±±±µµµÇÇÇ¿¿¿ºººººººººººº¿¿¿ÆÆÆ¿¿¿ÆÆÆÉÉÉÅÅÅÂÂÂÅÅÅÅÅÅÃÃÿ¿¿ÇÇÇÇÇÇ»»»µµµººº¼¼¼ººº¸¸¸ªªª¢¢¢©©©¸¸¸ÃÃÃÆÆÆÆÆÆÎÎÎÂÂÂÆÆÆÌÌÌÆÆÆÎÎÎÕÕÕÌÌÌÇÇÇÃÃÿ¿¿¿¿¿Â¾¾¾ººº¿¿¿¿¿¿ººº¸¸¸¾¾¾ººº¾¾¾ÎÎÎÌÌÌÍÍÍÎÎÎÐÐÐÑÑÑÐÐÐÎÎÎÍÍÍÙÙÙÕÕÕÕÕÕ×××ÑÑÑÃÃúºº¸¸¸Âµµµ¯¯¯µµµÀÀÀÃÃÃÂÂÂÀÀÀ¾¾¾ÅÅÅÍÍÍÐÐÐÌÌÌÇÇÇÃÃÃÃÃÃÀÀÀÅÅÅÂÂÂÌÌÌàààæææßßßàààÜÜÜàààâââãããèèèíííêêêäääÝÝÝÝÝݵµµ±±±¿¿¿···ºººµµµ¾¾¾ÀÀÀÅÅÅÆÆÆÇÇÇÉÉÉÊÊÊÍÍÍÍÍÍÐÐÐÒÒÒÔÔÔÕÕÕ×××ÙÙÙÜÜÜÜÜÜÛÛÛ×××ÔÔÔÐÐÐÍÍÍÌÌÌÊÊÊÊÊÊÌÌÌÌÌÌÌÌÌÌÌÌÐÐÐÕÕÕÛÛÛÝÝÝÜÜÜÙÙÙÕÕÕÔÔÔÔÔÔÕÕÕ×××ÕÕÕÍÍÍÀÀÀîîîñññîîîüüüüüüöööúúúúúúòòòçççâââãããèèèãããàààÝÝÝÛÛÛÙÙÙØØØÙÙÙÙÙÙÕÕÕÆÆÆÂÂÂÐÐÐÛÛÛ×××ÑÑÑÒÒÒÒÒÒÎÎÎ×××ÒÒÒØØØàààÎÎÎÅÅÅÆÆÆÇÇÇÇÇÇÆÆÆÃÃþ¾¾ºººµµµ±±±···¾¾¾³³³ºººÎÎÎÍÍÍÇÇǸ¸¸×××àààÔÔÔÍÍÍÇÇÇÃÃÃÆÆÆÀÀÀÂÂÂÃÃÿ¿¿¾¾¾¾¾¾¿¿¿ººººººººº¸¸¸···µµµµµµµµµ±±±···ºººµµµ´´´······´´´´´´···ºººÀÀÀÆÆÆÉÉÉÉÉÉÇÇÇ¿¿¿¸¸¸¼¼¼Â¼¼¼ºººÀÀÀÅÅÅÆÆÆÅÅÅÃÃÃÃÃÃÆÆÆÉÉÉÉÉÉÉÉÉÆÆÆÅÅÅÂÂÂÀÀÀÀÀÀÀÀÀÂÂÂÃÃÃÂÂÂÂÂÂÃÃÃÅÅÅ´´´¬¬¬¼¼¼¿¿¿»»»´´´ªªª¦¦¦©©©´´´¿¿¿ÇÇÇÉÉÉÍÍÍÂÂÂÃÃÃÊÊÊÆÆÆÊÊÊÊÊÊÉÉÉÆÆÆÃÃÿ¿¿¼¼¼¼¼¼¼¼¼¾¾¾Â¾¾¾»»»»»»»»»»»»»»»¼¼¼ÍÍÍÐÐÐÎÎÎÉÉÉÂÂÂÂÂÂÊÊÊÒÒÒÙÙÙ×××ÛÛÛÔÔÔÌÌÌÔÔÔÊÊʨ¨¨ÀÀÀ¼¼¼±±±­­­µµµ¿¿¿Â¾¾¾¾¾¾ÅÅÅÍÍÍÑÑÑÎÎÎÌÌÌÍÍÍÀÀÀ¾¾¾ÊÊÊÙÙÙàààçççæææÛÛÛØØØßßßßßßàààëëëïïïèèèäääâââãããÕÕÕ»»»°°°µµµ»»»···¸¸¸¼¼¼¼¼¼ÇÇÇÆÆÆ¼¼¼ÅÅÅÇÇÇÌÌÌÒÒÒÕÕÕÒÒÒÒÒÒ×××ÕÕÕÑÑÑÙÙÙÙÙÙØØØ×××ÔÔÔÐÐÐÍÍÍÊÊÊÊÊÊÊÊÊÊÊÊÌÌÌÎÎÎÑÑÑÔÔÔÕÕÕ×××ÝÝÝÙÙÙÒÒÒÔÔÔÑÑÑÐÐÐ×××ØØØÅÅÅÆÆÆëëëõõõñññÿÿÿõõõõõõùùùúúúõõõëëëãããàààâââààààààÝÝÝÜÜÜÛÛÛÛÛÛÙÙÙÙÙÙ×××ÎÎÎÍÍÍØØØàààÜÜÜ×××ÔÔÔÑÑÑÐÐÐÒÒÒÑÑÑ×××ÙÙÙÐÐÐÉÉÉÆÆÆÇÇÇÉÉÉÉÉÉÆÆÆ¿¿¿ºººµµµ¬¬¬¯¯¯···³³³´´´ÂÂÂÉÉÉÔÔÔÆÆÆ×××ÝÝÝÕÕÕÎÎÎÊÊÊÆÆÆÆÆÆÇÇÇÉÉÉÇÇÇÆÆÆÃÃÿ¿¿¾¾¾¼¼¼ÃÃÃÀÀÀ»»»···´´´µµµ¸¸¸ºººººº¼¼¼ººº´´´³³³¸¸¸¼¼¼¼¼¼¼¼¼¾¾¾ÀÀÀÆÆÆÌÌÌÍÍÍÌÌÌÉÉɺºººººÀÀÀÀÀÀººº¾¾¾ÅÅÅÃÃþ¾¾¾¾¾¾¾¾¿¿¿ÀÀÀÀÀÀ¾¾¾¼¼¼ÂÂÂÂÂÂÃÃÃÃÃÃÂÂÂÂÂÂÀÀÀÀÀÀ¿¿¿ÂÂÂÀÀÀÃÃø¸¸¯¯¯¼¼¼Â¼¼¼ººº´´´¯¯¯¬¬¬°°°ºººÂÂÂÉÉÉÍÍÍÂÂÂÃÃÃÊÊÊÆÆÆÉÉÉÊÊÊÇÇÇÆÆÆÂ¿¿¿¼¼¼¼¼¼¼¼¼¼¼¼ººººººººº¼¼¼ÅÅÅÌÌÌÐÐÐÎÎÎÀÀÀÃÃÃÆÆÆÃÃÿ¿¿ÀÀÀÆÆÆÌÌÌÜÜÜÕÕÕ×××ÔÔÔÎÎÎÕÕÕÎÎΰ°°³³³¼¼¼ÀÀÀ¸¸¸­­­¬¬¬´´´¼¼¼ºººººº¿¿¿ÆÆÆÊÊÊÊÊÊÍÍÍÒÒÒÉÉÉÂÂÂÆÆÆÍÍÍÑÑÑÛÛÛâââÝÝÝßßßãããÝÝÝÜÜÜçççîîîêêêèèèÜÜÜßßßÜÜÜÎÎμ¼¼³³³³³³···ºººÀÀÀ¼¼¼¾¾¾»»»ºººÅÅÅÆÆÆÆÆÆÆÆÆÊÊÊÑÑÑ×××ÙÙÙßßßâââÜÜÜÛÛÛØØØÕÕÕÒÒÒÎÎÎÌÌÌÊÊÊÊÊÊÊÊÊÌÌÌÍÍÍÎÎÎÐÐÐÑÑÑÒÒÒÕÕÕÙÙÙÕÕÕÔÔÔÕÕÕÎÎÎÇÇÇÌÌÌÀÀÀ¾¾¾ÉÉÉæææîîîñññÿÿÿïïïóóóöööùùùöööïïïæææßßßÜÜÜßßßÝÝÝÜÜÜÜÜÜÛÛÛÛÛÛÛÛÛÛÛÛÑÑÑÒÒÒÕÕÕÙÙÙÝÝÝÛÛÛÕÕÕÐÐÐÑÑÑÐÐÐÍÍÍÒÒÒÒÒÒÎÎÎÎÎÎÌÌÌÅÅÅÇÇÇÊÊÊÊÊÊÇÇÇÀÀÀºººµµµ±±±³³³»»»···µµµ¿¿¿ÃÃÃÎÎÎÃÃÃÍÍÍÙÙÙÜÜÜÒÒÒÌÌÌÍÍÍÌÌÌÇÇÇÆÆÆÃÃÃÂÂÂÀÀÀÀÀÀÀÀÀÀÀÀ¿¿¿¼¼¼»»»»»»¾¾¾ÃÃÃÇÇÇÊÊÊÉÉÉÉÉÉÆÆÆÀÀÀ¿¿¿ÃÃÃÉÉÉÊÊÊÌÌÌÌÌÌÌÌÌÍÍÍÍÍÍÊÊÊÅÅÅÀÀÀ¼¼¼¼¼¼¼¼¼¸¸¸¸¸¸ÅÅÅÌÌÌÂÂÂÀÀÀ¾¾¾»»»»»»»»»¼¼¼»»»»»»¾¾¾¾¾¾¾¾¾¾¾¾¿¿¿ÀÀÀÀÀÀÂÂÂÀÀÀÇÇÇÀÀÀ¾¾¾³³³ºººÀÀÀ¾¾¾¿¿¿¿¿¿¸¸¸±±±¯¯¯´´´ºººÉÉÉÎÎÎÂÂÂÅÅÅÊÊÊÆÆÆÉÉÉÉÉÉÇÇÇÅÅÅ¿¿¿¼¼¼»»»»»»»»»ººº¼¼¼¼¼¼¾¾¾ÇÇÇÒÒÒÕÕÕÎÎθ¸¸»»»¿¿¿ÀÀÀÂÂÂÂÂÂÅÅÅÇÇÇ×××ÒÒÒ×××ØØØÑÑÑÒÒÒÑÑÑÀÀÀ´´´µµµººº»»»¸¸¸±±±¯¯¯¯¯¯¼¼¼»»»¼¼¼¿¿¿ÀÀÀ¿¿¿ÆÆÆÍÍÍÉÉÉÃÃÃÂÂÂÂÂÂÅÅÅÎÎÎÜÜÜßßßâââäääÝÝÝÜÜÜçççîîîêêêçççâââßßßââââââÑÑѸ¸¸­­­°°°ºººÆÆÆÂ»»»µµµ¸¸¸ÅÅÅÂÂÂÊÊÊÆÆÆÇÇÇÐÐÐÔÔÔÐÐÐÑÑÑØØØÜÜÜÛÛÛ×××ÒÒÒÐÐÐÌÌÌÊÊÊÉÉÉÉÉÉÊÊÊÍÍÍÎÎÎÐÐÐÑÑÑÐÐÐÐÐÐÔÔÔÒÒÒÎÎÎÐÐÐÐÐÐÉÉÉÇÇÇÎÎÎÆÆÆÎÎÎÜÜÜêêêëëëöööÿÿÿñññóóóõõõööööööòòòëëëãããÝÝÝÝÝÝÜÜÜÙÙÙØØØØØØØØØÙÙÙÛÛÛÎÎÎ×××ÜÜÜÛÛÛÙÙÙÙÙÙÕÕÕÎÎÎÐÐÐÒÒÒÌÌÌÔÔÔÑÑÑÅÅÅÊÊÊÉÉÉÆÆÆÇÇÇÉÉÉÇÇÇÅÅÅÀÀÀ»»»¸¸¸¸¸¸¼¼¼Âººº¾¾¾ÍÍÍÇÇÇ»»»ÂÂÂ×××ããã×××ÌÌÌÍÍÍÌÌÌÎÎÎÍÍÍÌÌÌÍÍÍÎÎÎÑÑÑÒÒÒÔÔÔÑÑÑÑÑÑÑÑÑÑÑÑÐÐÐÌÌÌÆÆÆÂÂÂÅÅÅÆÆÆÇÇÇÆÆÆÃÃÃÃÃÃÅÅÅÆÆÆÇÇÇÆÆÆÃÃÿ¿¿¼¼¼ºººÀÀÀººº´´´³³³¸¸¸ÉÉÉÍÍÍÀÀÀ¼¼¼»»»»»»¼¼¼¾¾¾¼¼¼ºººµµµ¿¿¿¾¾¾¼¼¼»»»¾¾¾ÀÀÀÅÅÅÇÇÇÅÅÅÎÎÎÅÅÅÃÃô´´µµµ¼¼¼ÀÀÀÂÂÂÀÀÀ¾¾¾¸¸¸³³³±±±°°°ÉÉÉÎÎÎÃÃÃÅÅÅÌÌÌÇÇÇÉÉÉÉÉÉÆÆÆÅÅÅ¿¿¿¼¼¼»»»»»»»»»»»»¿¿¿¼¼¼»»»ÃÃÃÎÎÎÍÍÍ»»»¾¾¾ÀÀÀÃÃÃÆÆÆÉÉÉÉÉÉÊÊÊÍÍÍÎÎÎØØØÜÜÜÒÒÒÐÐÐÒÒÒÐÐÐÀÀÀµµµ°°°¸¸¸¿¿¿»»»±±±­­­´´´µµµººº¼¼¼¼¼¼»»»¿¿¿ÇÇÇ¿¿¿¿¿¿ÀÀÀÀÀÀÂÂÂÊÊÊ×××ÝÝÝßßßãããààààààëëëîîîçççãããçççßßßÝÝÝæææàààÍÍͼ¼¼¸¸¸ÛÛÛäääàààØØØÉÉɼ¼¼¾¾¾···¾¾¾¼¼¼ÀÀÀÉÉÉÍÍÍÌÌÌÎÎÎÒÒÒ×××ÕÕÕÒÒÒÎÎÎÌÌÌÉÉÉÉÉÉÉÉÉÇÇÇÊÊÊÎÎÎÑÑÑÒÒÒÒÒÒÒÒÒÑÑÑÔÔÔÎÎÎÊÊÊÉÉÉÆÆÆÆÆÆÑÑÑãããäääèèèîîîîîîíííöööÿÿÿñññóóóóóóóóóóóóòòòîîîèèèäääÝÝÝÛÛÛ×××ÔÔÔÒÒÒÔÔÔ×××ÙÙÙÔÔÔßßßäääàààÜÜÜÜÜÜÙÙÙÔÔÔÐÐÐÒÒÒÍÍÍÔÔÔÎÎο¿¿ÅÅÅÃÃÃÇÇÇÇÇÇÆÆÆÃÃÃÀÀÀ¾¾¾¼¼¼»»»ººº¼¼¼Â¼¼¼ÀÀÀÐÐÐÌÌÌÊÊÊÆÆÆÂÂÂÐÐÐßßßÛÛÛÔÔÔÑÑÑÍÍÍÐÐÐÒÒÒÕÕÕØØØ×××ÔÔÔÐÐÐÌÌÌÌÌÌÊÊÊÊÊÊÉÉÉÅÅž¾¾´´´¬¬¬ªªªªªª¬¬¬¬¬¬©©©¨¨¨¨¨¨ªªª©©©¨¨¨¦¦¦¨¨¨¬¬¬¯¯¯±±±±±±ººº´´´···¼¼¼¾¾¾ÅÅÅÇÇÇ¿¿¿ÂÂÂÉÉÉÎÎÎÐÐÐÌÌÌÃÃü¼¼¾¾¾¾¾¾¼¼¼¼¼¼¼¼¼¼¼¼¾¾¾¾¾¾ÆÆÆÐÐÐÆÆÆÆÆÆÅÅÅ···¸¸¸ÀÀÀÅÅÅÀÀÀ¾¾¾¿¿¿ÀÀÀ¼¼¼³³³ªªªÊÊÊÐÐÐÅÅÅÇÇÇÍÍÍÇÇÇÉÉÉÇÇÇÆÆÆÅÅÅÃÃÃÀÀÀ¾¾¾¼¼¼»»»»»»µµµ»»»»»»ºººÂÂÂÎÎÎÌÌÌÀÀÀÃÃÃÂÂÂÃÃÃÅÅÅÇÇÇÊÊÊÌÌÌÌÌÌÊÊÊÉÉÉÐÐÐ×××ÕÕÕÔÔÔÔÔÔÑÑÑÇÇǸ¸¸¯¯¯±±±···¸¸¸······¢¢¢¨¨¨³³³¼¼¼¿¿¿¾¾¾ÀÀÀÇÇǼ¼¼ÀÀÀÂÂÂÂÂÂÂÂÂÇÇÇÐÐÐÙÙÙÝÝÝäääâââàààêêêíííçççäääãããßßßÝÝÝàààâââÝÝÝ×××ÐÐÐØØØÝÝÝÙÙÙÛÛÛÎÎλ»»ººº¸¸¸ÂÂÂÆÆÆÆÆÆÃÃÃÃÃÃÉÉÉÎÎÎÐÐÐÐÐÐÎÎÎÌÌÌÉÉÉÇÇÇÇÇÇÇÇÇÇÇÇÆÆÆÊÊÊÎÎÎÒÒÒÕÕÕÕÕÕÔÔÔÒÒÒÒÒÒÐÐÐÍÍÍÉÉÉÀÀÀÆÆÆÜÜÜòòòòòòíííîîîîîîíííòòòñññêêêòòòñññïïïïïïîîîíííëëëêêêàààÜÜÜ×××ÒÒÒÑÑÑÑÑÑÒÒÒÕÕÕÑÑÑÜÜÜãããßßßÙÙÙØØØÕÕÕÒÒÒÎÎÎÒÒÒÑÑÑÑÑÑÊÊÊÀÀÀÀÀÀÂÂÂÇÇÇÅÅÅ¿¿¿¼¼¼»»»»»»¼¼¼¿¿¿¼¼¼ÃÃÿ¿¿¼¼¼¿¿¿ÂÂÂÐÐÐÐÐÐÃÃÃÃÃÃÐÐÐÛÛÛàààßßßÙÙÙÐÐÐÕÕÕÙÙÙÙÙÙÑÑÑÅÅŸ¸¸³³³³³³°°°¯¯¯±±±µµµ···µµµ´´´»»»¸¸¸µµµµµµ³³³±±±´´´ºººµµµ´´´³³³µµµººº¾¾¾ÀÀÀ°°°µµµÅÅÅÊÊÊÂÂÂÀÀÀÅÅÅÅÅÅÌÌÌÌÌÌÌÌÌÎÎÎÐÐÐÐÐÐÍÍÍÊÊÊÒÒÒÔÔÔ×××ØØØÕÕÕÐÐÐÊÊÊÆÆÆÃÃÃÌÌÌÆÆÆÉÉÉÆÆÆ¼¼¼ÅÅÅÌÌÌÉÉɾ¾¾ÀÀÀÅÅÅÃÃø¸¸­­­ÌÌÌÑÑÑÇÇÇÊÊÊÎÎÎÉÉÉÊÊÊÉÉÉÆÆÆÆÆÆÃÃÿ¿¿¾¾¾¼¼¼»»»ººº¾¾¾¿¿¿ÀÀÀÇÇÇÐÐÐÎÎÎÅÅÅÅÅÅÃÃÃÃÃÃÃÃÃÅÅÅÆÆÆÇÇÇÇÇÇÌÌÌÃÃÃÃÃÃÌÌÌÕÕÕÙÙÙÔÔÔÌÌÌÎÎμ¼¼ªªª©©©±±±¸¸¸¸¸¸···¤¤¤±±±¾¾¾Â¿¿¿¾¾¾ÀÀÀÀÀÀÆÆÆÅÅÅÀÀÀÀÀÀÂÂÂÉÉÉÔÔÔßßßäääàààÜÜÜâââçççèèèëëëäääêêêèèèàààÜÜÜÝÝÝßßßÝÝÝÛÛÛÜÜÜÙÙÙãããâââÙÙÙâââæææâââäääÝÝÝÌÌÌÀÀÀÂÂÂÇÇÇÇÇÇÊÊÊÉÉÉÉÉÉÇÇÇÆÆÆÆÆÆÆÆÆÆÆÆÇÇÇÊÊÊÎÎÎÒÒÒÔÔÔÔÔÔÒÒÒÒÒÒÎÎÎÎÎÎÑÑÑÌÌÌÃÃÃÌÌÌâââïïïîîîçççíííïïïòòòóóóíííëëëïïïïïïíííëëëèèèçççèèèèèèâââßßßÛÛÛ×××ÔÔÔÑÑÑÐÐÐÐÐÐÊÊÊÔÔÔÝÝÝÝÝÝØØØÒÒÒÎÎÎÍÍÍÎÎÎÐÐÐÒÒÒÊÊÊÅÅÅÅÅÅÂÂÂÅÅÅÃÃÿ¿¿¾¾¾»»»ºººººººººÂ¾¾¾ÆÆÆÃÃþ¾¾»»»ºººÆÆÆÐÐÐÊÊÊÃÃÃÆÆÆÒÒÒÙÙÙÛÛÛÝÝÝÛÛÛÝÝÝÝÝÝÕÕÕÉÉɾ¾¾¸¸¸···¾¾¾ººº´´´µµµººº¿¿¿ÀÀÀÀÀÀ»»»¸¸¸···¸¸¸µµµ±±±³³³¸¸¸···µµµ´´´´´´·········µµµµµµ¿¿¿ÊÊÊÉÉÉÂÂÂÇÇÇÍÍÍÇÇÇÐÐÐÌÌÌÇÇÇÅÅÅÆÆÆÇÇÇÉÉÉÉÉÉÊÊÊÌÌÌÎÎÎÐÐÐÎÎÎÌÌÌÇÇÇÅÅÅÅÅÅÉÉÉÉÉÉÍÍÍÅÅž¾¾ÍÍÍÒÒÒÎÎÎÇÇÇÃÃÃÅÅÅÇÇÇÆÆÆ¿¿¿···ÍÍÍÔÔÔÊÊÊÌÌÌÑÑÑÊÊÊÊÊÊÉÉÉÇÇÇÆÆÆÅÅÅÃÃÃÀÀÀ¿¿¿¼¼¼»»»¿¿¿ÀÀÀÅÅÅÉÉÉÎÎÎÑÑÑÎÎÎÉÉÉÂÂÂÂÂÂÃÃÃÃÃÃÃÃÃÃÃÃÅÅÅÆÆÆÇÇÇÃÃÿ¿¿ÂÂÂÌÌÌÔÔÔÒÒÒÍÍÍÐÐÐÃÃô´´¬¬¬±±±ºººººº´´´¤¤¤¨¨¨±±±¼¼¼ÀÀÀ¼¼¼ººº»»»¾¾¾ÆÆÆÆÆÆÃÃÃÅÅÅÂÂÂÅÅÅÎÎÎÛÛÛãããâââÛÛÛßßßäääèèèïïïêêêîîîíííãããÜÜÜÛÛÛÛÛÛÛÛÛßßßàààÛÛÛààààààßßßçççççççççíííëëëßßßÎÎÎÇÇÇÉÉÉÍÍÍÉÉÉÉÉÉÉÉÉÉÉÉÇÇÇÆÆÆÅÅÅÅÅÅÇÇÇÊÊÊÍÍÍÎÎÎÐÐÐÎÎÎÍÍÍÍÍÍÉÉÉÇÇÇÊÊÊÆÆÆÅÅÅ×××çççèèèëëëêêêóóóïïïïïïòòòëëëïïïîîîíííëëëèèèæææãããääääääãããâââßßßÜÜÜØØØÒÒÒÎÎÎÌÌÌÌÌÌÕÕÕàààäääßßßÕÕÕÐÐÐÎÎÎÎÎÎÍÍÍÒÒÒÅÅÅÀÀÀÉÉÉÅÅÅÉÉÉÀÀÀÀÀÀ¿¿¿¾¾¾»»»ººº······¸¸¸»»»ÆÆÆÅÅÅÇÇÇÍÍÍÀÀÀ»»»ÎÎÎ×××ÑÑÑÇÇÇÆÆÆÃÃÃÅÅÅÐÐÐÛÛÛÙÙÙÑÑÑÅÅŸ¸¸µµµ¾¾¾ÆÆÆÂ¼¼¼······»»»¿¿¿¿¿¿¾¾¾ºººººº¼¼¼Â¿¿¿···´´´···µµµµµµ···ººº»»»»»»¸¸¸µµµÆÆÆÇÇÇÅÅż¼¼¿¿¿ÒÒÒØØØÇÇÇÕÕÕ×××ÙÙÙÜÜÜÜÜÜ×××ÐÐÐÊÊÊÎÎÎÍÍÍÍÍÍÎÎÎÐÐÐÒÒÒ×××ØØØÉÉÉÊÊÊÍÍÍÑÑѼ¼¼ÐÐÐÒÒÒÑÑÑÍÍÍÊÊÊÇÇÇÇÇÇÆÆÆÃÃÿ¿¿ÎÎÎÕÕÕÊÊÊÍÍÍÒÒÒÌÌÌÌÌÌÉÉÉÇÇÇÇÇÇÆÆÆÅÅÅ¿¿¿¾¾¾¼¼¼»»»¼¼¼ÂÂÂÌÌÌÑÑÑÒÒÒÑÑÑÑÑÑÀÀÀÂÂÂÅÅÅÅÅÅÅÅÅÃÃÃÅÅÅÆÆÆ¿¿¿ÆÆÆÅÅÅ¿¿¿¿¿¿ÇÇÇÐÐÐÔÔÔÉÉÉÎÎÎÊÊʼ¼¼±±±³³³¸¸¸»»»¤¤¤¥¥¥­­­¸¸¸¿¿¿¿¿¿¿¿¿ÀÀÀ´´´ÀÀÀÅÅÅÆÆÆÊÊÊÆÆÆÃÃÃÊÊÊÒÒÒàààãããàààâââäääæææíííäääããããããããããããâââßßßÜÜÜÜÜÜäääÝÝÝÝÝÝàààãããèèèßßßàààçççñññïïïßßßÌÌÌÆÆÆÍÍÍÌÌÌÌÌÌÌÌÌÊÊÊÉÉÉÆÆÆÅÅÅÃÃÃÉÉÉÊÊÊÌÌÌÌÌÌÌÌÌÊÊÊÉÉÉÇÇÇÅÅÅÀÀÀ¾¾¾»»»ÃÃÃÝÝÝîîîçççíííñññøøøèèèàààçççäääíííóóóâââêêêæææàààèèèäääàààÝÝÝßßßÛÛÛãããÝÝÝÎÎÎÐÐÐÐÐÐÃÃÃÙÙÙßßßÙÙÙÙÙÙ×××ÎÎÎÊÊÊÊÊÊÔÔÔÔÔÔÆÆÆ¿¿¿ÅÅÅÉÉÉÅÅž¾¾»»»ººº¸¸¸······¸¸¸»»»±±±¸¸¸ÂÂÂÊÊÊÎÎÎÌÌÌÆÆÆÂ¾¾¾ÇÇÇÑÑÑÕÕÕÑÑÑÌÌÌÉÉÉÉÉɸ¸¸µµµµµµººº¾¾¾¿¿¿¿¿¿¿¿¿ººº¸¸¸¸¸¸ººº¾¾¾ÀÀÀ¿¿¿¾¾¾ÀÀÀ¸¸¸¸¸¸¿¿¿¿¿¿···±±±´´´´´´µµµµµµ³³³°°°³³³»»»ÂÂÂÃÃÃÇÇÇÌÌÌÃÃÃÂÂÂÉÉÉÌÌÌÎÎÎ×××ÒÒÒ×××ÛÛÛÑÑÑÎÎÎÕÕÕØØØàààÝÝÝÝÝÝÒÒÒÆÆÆÌÌÌØØØØØØÙÙÙÐÐÐÌÌÌÉÉÉÇÇÇÍÍÍÒÒÒÐÐÐÔÔÔÒÒÒÆÆÆÉÉÉÌÌÌÉÉÉÌÌÌÃÃÃÐÐÐØØØÝÝÝÔÔÔÉÉÉÐÐÐÒÒÒÉÉÉÇÇÇÉÉÉÉÉÉÅÅÅÀÀÀ¾¾¾¾¾¾¿¿¿¾¾¾ÂÂÂÍÍÍ×××ÐÐÐÀÀÀ¼¼¼ÃÃÃÅÅÅÅÅÅÅÅÅÃÃÃÂÂÂÀÀÀÀÀÀ¿¿¿¿¿¿¾¾¾¾¾¾¼¼¼¾¾¾¿¿¿ÂÂÂÂÂÂÐÐÐÒÒÒÎÎÎÉÉÉÅÅźºº´´´¼¼¼µµµ´´´©©©´´´Â¿¿¿ÀÀÀÀÀÀ¼¼¼¼¼¼ÐÐÐÃÃÃÂÂÂÍÍÍÀÀÀÆÆÆÍÍÍÔÔÔÛÛÛÝÝÝßßßâââçççíííóóóîîîçççâââßßßßßßààààààßßßßßßßßßÝÝÝÝÝÝßßßãããçççèèèçççíííîîîàààÌÌÌÇÇÇÑÑÑÎÎÎÌÌÌÇÇÇÅÅÅÅÅÅÆÆÆÅÅÅÂÂÂÇÇÇÊÊÊÉÉÉÃÃÃÂÂÂÅÅÅÅÅÅÀÀÀÃÃúººÇÇÇÅÅÅÝÝÝèèèêêêêêêñññëëëäääâââãããçççëëëîîîëëëçççíííëëëçççèèèäääâââÝÝÝßßßØØØÛÛÛØØØÎÎÎÐÐÐÊÊÊÌÌÌÜÜÜâââÝÝÝàààßßßÕÕÕÐÐÐÌÌÌÒÒÒÐÐÐÆÆÆÀÀÀÅÅÅÆÆÆÀÀÀ­­­±±±´´´´´´±±±¯¯¯ªªª¦¦¦±±±···ÀÀÀÉÉÉÎÎÎÎÎÎÌÌÌÉÉÉÃÃÃÃÃÿ¿¿¾¾¾ÀÀÀÆÆÆÌÌÌÃÃÃÉÉÉÉÉÉÅÅÅÃÃÃÆÆÆÃÃü¼¼ÂÂÂÀÀÀÀÀÀÂÂÂÃÃÃÀÀÀ¼¼¼ºººÀÀÀ···´´´ººº»»»···¸¸¸¾¾¾žžžžžž¡¡¡©©©´´´¾¾¾ÀÀÀ¾¾¾ÃÃÃÇÇÇÇÇÇÇÇÇÎÎÎÔÔÔØØØãããÙÙÙÙÙÙÙÙÙÔÔÔÔÔÔÝÝÝâââÜÜÜÛÛÛÝÝÝÛÛÛÒÒÒ×××ÙÙÙÑÑÑÛÛÛØØØÙÙÙØØØÎÎÎÊÊÊÊÊÊÃÃû»»ÂÂÂÂÂÂÌÌÌÐÐÐÍÍÍÐÐÐÊÊÊÅÅÅÎÎÎÝÝÝÝÝÝÐÐÐÐÐÐÒÒÒÉÉÉÉÉÉÉÉÉÉÉÉÆÆÆÂ¿¿¿¿¿¿¿¿¿ÀÀÀÂÂÂÉÉÉÑÑÑÌÌÌÀÀÀ¿¿¿ÆÆÆÅÅÅÅÅÅÃÃÃÂÂÂÂÂÂÀÀÀ¿¿¿¿¿¿¾¾¾¾¾¾¼¼¼»»»¼¼¼¾¾¾¿¿¿ÀÀÀÀÀÀÇÇÇÊÊÊÍÍÍÌÌÌ¿¿¿µµµ¸¸¸»»»¸¸¸ªªª³³³ÂÂÂÀÀÀÂÂÂÀÀÀÅÅÅÀÀÀÐÐÐÆÆÆÃÃÃÊÊʾ¾¾ÅÅÅÃÃÃÑÑÑßßßàààÛÛÛØØØÝÝÝäääÙÙÙÝÝÝäääçççæææâââßßßÝÝÝßßßßßßßßßÝÝÝÝÝÝßßßãããæææîîîëëëíííîîîãããÑÑÑÇÇÇÆÆÆÒÒÒÌÌÌÆÆÆÅÅÅÀÀÀ¾¾¾ÃÃÃÌÌÌÅÅÅÇÇÇÆÆÆÂÂÂÂÂÂÅÅž¾¾ÇÇÇÃÃÃØØØÛÛÛçççãããäääëëëòòòîîîçççããããããäääæææçççãããîîîïïïïïïëëëÝÝÝØØØ×××ÝÝÝãããÛÛÛÛÛÛØØØÔÔÔÕÕÕÌÌÌÌÌÌ×××ÙÙÙ×××ÛÛÛÜÜÜÒÒÒÉÉÉÍÍÍÎÎÎÊÊÊÃÃÃÂÂÂÅÅÅÀÀÀººº···ÀÀÀÉÉÉÉÉÉÆÆÆÃÃø¸¸¬¬¬°°°µµµ¿¿¿ÇÇÇÎÎÎÐÐÐÑÑÑÐÐÐÐÐÐÎÎÎÌÌÌÇÇÇÅÅÅÃÃÃÂÂÂÃÃÃÂÂÂÌÌÌÌÌÌÀÀÀ»»»ÀÀÀ¾¾¾¾¾¾¾¾¾¿¿¿ÀÀÀ¿¿¿¼¼¼ººº±±±¬¬¬­­­¬¬¬¦¦¦¥¥¥©©©¯¯¯¯¯¯³³³ºººÀÀÀÅÅž¾¾ÉÉÉÌÌÌÎÎÎÒÒÒÑÑÑÐÐÐÕÕÕÛÛÛÝÝÝÕÕÕÛÛÛÜÜÜÜÜÜØØØÜÜÜ×××ÜÜÜÛÛÛÝÝÝßßßÝÝÝßßßÝÝÝÔÔÔÕÕÕÙÙÙäääæææÛÛÛ×××ÙÙÙ×××ÍÍÍÌÌÌÂÂÂÊÊÊÒÒÒÒÒÒÑÑÑÇÇÇÆÆÆÆÆÆÙÙÙâââÔÔÔÒÒÒÕÕÕÊÊÊÊÊÊÊÊÊÊÊÊÇÇÇÃÃÃÀÀÀÀÀÀÀÀÀÅÅÅÂÂÂÃÃÃÉÉÉÆÆÆÀÀÀÂÂÂÉÉÉÅÅÅÃÃÃÃÃÃÂÂÂÀÀÀ¿¿¿¿¿¿¾¾¾¼¼¼»»»ººººººººº»»»¼¼¼¾¾¾ºººÀÀÀÆÆÆÍÍÍÐÐеµµµµµÀÀÀ¼¼¼ªªª±±±ÀÀÀÂÂÂÅÅÅÃÃÃÉÉÉÂÂÂÍÍÍÇÇÇÆÆÆÇÇǼ¼¼ÅÅÅ¿¿¿ÌÌÌÙÙÙàààßßßÛÛÛÜÜÜàààßßßäääèèèêêêçççãããããããããàààààààààßßßÝÝÝßßßãããçççîîîíííííííííèèèÝÝÝÐÐÐÃÃÃÎÎÎÇÇÇÊÊÊÕÕÕÕÕÕÇÇÇÀÀÀÂÂÂÆÆÆÅÅÅÀÀÀ¾¾¾¿¿¿ÃÃÃÃÃÃÀÀÀ»»»ÂÂÂàààíííñññäääçççõõõîîîêêêæææããããããääääääãããßßßöööïïïëëëæææÌÌÌÂÂÂÃÃÃÐÐÐààààààÝÝÝØØØÕÕÕØØØÎÎÎ×××ÛÛÛÙÙÙÙÙÙÜÜÜÝÝÝÔÔÔÉÉÉÎÎÎÊÊÊÅÅÅÂÂÂÃÃü¼¼µµµ¯¯¯»»»ÃÃõµµ¥¥¥±±±¸¸¸ÂÂÂÊÊÊÐÐÐÒÒÒÒÒÒÒÒÒ××××××ØØØÙÙÙ×××ÐÐÐÇÇÇÀÀÀ¾¾¾ÂÂÂÀÀÀµµµ°°°···ÂÂÂÇÇǼ¼¼¾¾¾ÀÀÀÀÀÀ¾¾¾···°°°¬¬¬µµµ±±±³³³······°°°­­­¯¯¯±±±µµµººº¼¼¼¼¼¼¼¼¼¾¾¾¿¿¿ÀÀÀÅÅÅÇÇÇÔÔÔÕÕÕÒÒÒÜÜÜââââââÕÕÕØØØÔÔÔØØØÕÕÕÝÝÝ×××ßßßÝÝÝÝÝÝßßßßßßâââãããâââÛÛÛÝÝÝäääâââÑÑÑÌÌÌÑÑÑÒÒÒÛÛÛÒÒÒÀÀÀÃÃÃÊÊÊÎÎÎÕÕÕÐÐÐÔÔÔÆÆÆÒÒÒßßßÕÕÕÔÔÔØØØÍÍÍÍÍÍÌÌÌÊÊÊÉÉÉÆÆÆÃÃÃÂÂÂÂÂÂÅÅÅÀÀÀ¿¿¿ÃÃÃÃÃÃÂÂÂÃÃÃÉÉÉÃÃÃÂÂÂÂÂÂÀÀÀ¿¿¿¾¾¾¾¾¾¾¾¾»»»ººº¸¸¸······¸¸¸ººº»»»¾¾¾ÃÃÃÆÆÆÌÌÌÎÎεµµµµµÀÀÀ¼¼¼©©©­­­¾¾¾ÂÂÂÇÇÇÆÆÆÆÆÆ¾¾¾ÅÅÅÅÅÅÆÆÆÆÆÆ¿¿¿ÇÇÇÃÃÃÅÅÅÍÍÍÛÛÛäääæææææææææííííííëëëêêêèèèçççççççççãããããããããààààààâââäääèèèëëëîîîîîîííííííëëëßßßÒÒÒÊÊÊÇÇÇÎÎÎâââîîîæææÑÑÑÃÃÃÃÃÿ¿¿ººº···ººº¿¿¿ÀÀÀÀÀÀ³³³ÃÃÃßßßîîîïïïèèèíííøøøäääâââââââââäääçççççççççßßßøøøîîîçççàààÃÃ÷··ººº»»»×××àààÝÝÝÕÕÕÒÒÒÙÙÙÔÔÔÝÝÝÛÛÛÙÙÙØØØØØØ×××ÎÎÎÃÃÃÍÍÍÆÆÆÂ¿¿¿¸¸¸´´´···ÂÂÂÆÆÆÃÃÃÆÆÆÉÉÉÀÀÀ³³³´´´¼¼¼ÇÇÇÐÐÐÒÒÒÒÒÒÒÒÒÑÑÑÕÕÕÔÔÔÒÒÒÔÔÔ×××ÕÕÕÒÒÒÎÎÎÆÆÆÃÃÃÀÀÀ¾¾¾···µµµ¿¿¿ÍÍÍÆÆÆ¿¿¿µµµ­­­¬¬¬°°°¸¸¸¿¿¿¿¿¿¾¾¾¿¿¿ÀÀÀ¿¿¿ººº···¸¸¸»»»ºººººº······¸¸¸¼¼¼¿¿¿¼¼¼ÃÃÃÂÂÂÐÐÐÒÒÒÌÌÌÙÙÙÝÝÝçççÛÛÛÝÝÝÒÒÒØØØÔÔÔàààÙÙÙÝÝÝàààââââââààààààæææîîîââââââæææàààÐÐÐÌÌÌÑÑÑÔÔÔÑÑÑÔÔÔÊÊÊÆÆÆ¿¿¿»»»ÇÇÇÌÌÌ×××ÌÌÌ×××àààÕÕÕÐÐÐÕÕÕÑÑÑÎÎÎÍÍÍÌÌÌÉÉÉÇÇÇÆÆÆÃÃÃÂÂÂÃÃÃÀÀÀ¿¿¿ÂÂÂÃÃÃÃÃÃÃÃÃÅÅÅÂÂÂÂÂÂÀÀÀ¿¿¿¾¾¾¾¾¾¼¼¼¼¼¼ººº¸¸¸···µµµ···¸¸¸ººº»»»ÀÀÀÆÆÆÉÉÉÍÍÍÐÐÐÃÃ÷·····¾¾¾»»»¨¨¨ªªª»»»ÂÂÂÇÇÇÆÆÆÅÅÅ»»»¾¾¾ÀÀÀÃÃÃÃÃÿ¿¿ÅÅÅÆÆÆÂÂÂÆÆÆÒÒÒÝÝÝâââçççëëëëëëèèèçççêêêîîîïïïêêêäääèèèèèèçççæææääääääèèèëëëëëëòòòóóóïïïîîîñññíííæææíííêêêææææææíííëëëÙÙÙÆÆÆÀÀÀ¿¿¿¾¾¾¿¿¿ÂÂÂÂÂÂÀÀÀ¿¿¿ÅÅÅ×××ãããêêêèèèëëëíííêêêÝÝÝÝÝÝßßßâââæææèèèèèèèèèàààóóóîîîæææàààÉÉɺºº¾¾¾¸¸¸ÔÔÔßßßÝÝÝÕÕÕÕÕÕâââàààÝÝÝØØØØØØÕÕÕÎÎÎÌÌÌÇÇÇ¿¿¿ÌÌÌÃÃÃÀÀÀÂÂÂÀÀÀººº···¸¸¸¼¼¼ÀÀÀÂÂÂÀÀÀÃÃÃÇÇÇÃÃúºº¸¸¸ÀÀÀÌÌÌÒÒÒÔÔÔÒÒÒÑÑÑÑÑÑÕÕÕÔÔÔÒÒÒÔÔÔ×××ØØØÕÕÕÔÔÔÎÎÎÉÉÉÉÉÉÌÌÌÃÃ÷··µµµ¿¿¿±±±µµµ»»»¿¿¿ÀÀÀÂÂÂÂÂÂÃÃÃÅÅÅ¿¿¿»»»µµµ±±±±±±´´´¾¾¾···³³³···ÅÅÅÐÐÐÕÕÕÕÕÕÍÍÍÕÕÕÐÐÐØØØ×××ÎÎÎÜÜÜÜÜÜãããØØØÜÜÜÊÊÊÎÎÎÉÉÉÙÙÙÒÒÒÙÙÙàààæææççççççãããæææñññÝÝÝÝÝÝãããäääÝÝÝßßßæææäääÐÐÐ×××ÒÒÒÒÒÒÌÌÌÀÀÀ¼¼¼ÊÊÊÎÎÎÜÜÜãããØØØÎÎÎÐÐÐÒÒÒÐÐÐÍÍÍÊÊÊÉÉÉÉÉÉÆÆÆÅÅÅÂÂÂÂÂÂÀÀÀÀÀÀÃÃÃÃÃÃÃÃÃÂÂÂÂÂÂÀÀÀÀÀÀ¿¿¿¾¾¾¾¾¾¼¼¼»»»»»»······µµµµµµ···¸¸¸»»»¼¼¼¿¿¿ÆÆÆÌÌÌÑÑÑÒÒÒÅÅÅ···¸¸¸»»»¼¼¼ªªª¬¬¬ºººÀÀÀÇÇÇÅÅÅÆÆÆ¿¿¿»»»¼¼¼ÀÀÀ¿¿¿¿¿¿ÃÃÃÂÂÂÅÅÅÌÌÌÍÍÍÎÎÎÙÙÙèèèöööïïïêêêëëëïïïòòòïïïíííîîîîîîíííëëëèèèêêêîîîñññòòòøøøøøøòòòïïïñññòòòïïïíííóóóòòòêêêêêêñññîîîäääæææääääääâââØØØÉÉɼ¼¼¸¸¸ÛÛÛêêêæææêêêèèèñññîîîâââàààßßßßßßâââäääææææææäääâââëëëîîîæææàààÑÑѾ¾¾ÀÀÀ¼¼¼ÎÎÎÑÑÑÑÑÑÎÎÎÑÑÑãããæææãããßßßàààÝÝÝÑÑÑÍÍÍÎÎÎÉÉÉÉÉÉ¿¿¿Â¾¾¾´´´µµµ¾¾¾ÂÂÂÂÂÂÂÂÂÃÃÃÇÇÇÇÇÇÃÃü¼¼¾¾¾ÅÅÅÎÎÎÒÒÒÒÒÒÑÑÑÒÒÒÔÔÔÔÔÔÕÕÕØØØÙÙÙÛÛÛØØØÕÕÕÑÑÑÐÐÐÌÌÌÍÍÍÐÐÐÊÊÊ¿¿¿¸¸¸¸¸¸¿¿¿ÃÃÃÉÉÉÊÊÊÇÇÇÃÃÃÀÀÀ¿¿¿Â¾¾¾»»»»»»¾¾¾ÀÀÀÃÃü¼¼···»»»ÆÆÆÐÐÐÑÑÑÐÐÐÒÒÒàààØØØßßßßßßÛÛÛíííçççêêêÙÙÙÔÔÔ±±±³³³´´´ÕÕÕÛÛÛÛÛÛàààâââæææëëëçççæææïïïäääÜÜÜÜÜÜÝÝÝÛÛÛßßßàààÛÛÛÕÕÕÒÒÒÉÉÉÐÐÐ×××ÔÔÔÑÑÑÅÅÅÀÀÀÊÊÊÒÒÒÙÙÙÝÝÝØØØÐÐÐÑÑÑÐÐÐÍÍÍÊÊÊÉÉÉÉÉÉÇÇÇÅÅÅÂÂÂÂÂÂÃÃÃÃÃÃÃÃÃÂÂÂÂÂÂÂÂÂÂÂÂÀÀÀ¿¿¿¿¿¿¾¾¾¼¼¼»»»»»»ººº···µµµµµµµµµ¸¸¸ººº¼¼¼¾¾¾ÆÆÆÌÌÌÎÎÎÐÐÐÍÍÍ¿¿¿´´´¸¸¸»»»ÀÀÀ±±±±±±»»»¿¿¿ÅÅÅÂÂÂÅÅÅÀÀÀºººººº¿¿¿ÅÅÅÅÅž¾¾Â¿¿¿ÂÂÂÇÇÇÆÆÆÃÃÃÎÎÎÝÝÝöööóóóñññïïïïïïòòòõõõøøøóóóóóóòòòïïïîîîïïïòòòõõõùùùøøøöööóóóòòòòòòóóóòòòîîîóóóõõõïïïíííîîîîîîêêêçççèèèíííîîîèèèàààÜÜÜßßßçççñññæææïïïëëëñññíííàààâââààààààâââäääæææäääããããããæææîîîæææßßßÔÔÔ¼¼¼¾¾¾ºººÀÀÀ»»»»»»¾¾¾ÆÆÆÙÙÙÝÝÝßßßÜÜÜßßßÜÜÜÍÍÍÉÉÉÍÍÍÊÊÊÇÇÇÀÀÀÀÀÀ¼¼¼±±±µµµÀÀÀ¿¿¿¼¼¼¼¼¼ÂÂÂÅÅÅ»»»µµµÀÀÀÇÇÇÎÎÎÒÒÒÑÑÑÑÑÑÔÔÔ×××ÍÍÍÍÍÍÐÐÐÑÑÑÔÔÔ××××××ØØØÐÐÐÐÐÐÎÎÎÎÎÎÐÐÐÎÎÎÇÇÇÂÂÂÇÇÇÊÊÊÊÊÊÉÉÉÅÅÅÃÃÃÃÃÃÅÅÅÇÇÇÊÊÊÊÊÊÇÇǾ¾¾»»»ººº¸¸¸ººº¼¼¼ÂÂÂÉÉÉÐÐÐÕÕÕØØØØØØçççÛÛÛÜÜÜÙÙÙÕÕÕæææÜÜÜëëëÜÜÜØØØ±±±°°°°°°×××ÝÝÝââââââÜÜÜàààëëëèèèçççñññòòòãããÛÛÛÙÙÙÛÛÛàààâââÙÙÙâââÛÛÛÇÇÇÆÆÆÉÉÉÉÉÉÎÎÎÉÉÉÂÂÂÅÅÅÀÀÀÊÊÊâââäääÔÔÔÍÍÍÐÐÐÍÍÍÊÊÊÉÉÉÉÉÉÇÇÇÅÅÅÂÂÂÃÃÃÅÅÅÅÅÅÃÃÃÂÂÂÀÀÀ¿¿¿¿¿¿¾¾¾¾¾¾¼¼¼»»»ººººººµµµµµµµµµ···¸¸¸»»»¾¾¾ÀÀÀÒÒÒÔÔÔÐÐÐÉÉÉÃÃ÷··±±±¸¸¸¼¼¼ÅÅŸ¸¸µµµ¼¼¼¾¾¾ÃÃÃÀÀÀÀÀÀ¿¿¿¸¸¸¸¸¸ÀÀÀÊÊÊÌÌÌÃÃÃÃÃü¼¼¼¼¼ÆÆÆÉÉÉÇÇÇÌÌÌÕÕÕÙÙÙãããïïïõõõõõõóóóõõõùùùøøøøøøöööóóóñññòòòõõõøøøùùùõõõñññòòòõõõöööóóóòòòöööñññëëëëëëëëëíííííííííèèèææææææäääàààÜÜÜâââëëëîîîóóóæææõõõíííêêêâââÙÙÙâââààààààâââäääææææææäääâââêêêæææèèèßßßÇÇÇÀÀÀ···¾¾¾ÀÀÀÅÅÅÃÃÃÀÀÀ¿¿¿ÂÂÂÆÆÆÝÝÝßßß×××ÑÑÑÒÒÒÍÍÍÉÉÉÐÐп¿¿Â¾¾¾······¼¼¼ÀÀÀ¿¿¿¾¾¾¿¿¿»»»ÆÆÆÅÅÅÍÍÍÀÀÀ»»»¼¼¼ÀÀÀÉÉÉÐÐÐÕÕÕ×××ÕÕÕÔÔÔÐÐÐÑÑÑÔÔÔ×××ØØØØØØ×××ÕÕÕÕÕÕÐÐÐÍÍÍÎÎÎÔÔÔ×××ÒÒÒÍÍÍÎÎÎÍÍÍÊÊÊÇÇÇÆÆÆÅÅÅÆÆÆÆÆÆÇÇÇÆÆÆÃÃÃÃÃÃÃÃÃÃÃÃÀÀÀ¾¾¾»»»¸¸¸ÅÅÅÕÕÕ××××××ÙÙÙØØØàààäääÝÝÝäää×××ÔÔÔíííÝÝÝçççààà×××ÀÀÀ¬¬¬³³³ÒÒÒçççÜÜÜæææäääãããèèèæææäääíííãããîîîíííßßßÙÙÙÝÝÝßßßÜÜÜØØØÛÛÛÜÜÜÙÙÙÔÔÔÍÍÍÉÉÉÇÇÇÇÇÇÉÉÉÅÅÅÐÐÐÒÒÒêêêãããÒÒÒÑÑÑÎÎÎÍÍÍÌÌÌÊÊÊÇÇÇÇÇÇÉÉÉÅÅÅÃÃÃÂÂÂÂÂÂÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀ¿¿¿¼¼¼»»»ºººººº¸¸¸¸¸¸ººº¸¸¸¸¸¸µµµµµµ»»»ÅÅÅÍÍÍÌÌÌÌÌÌÍÍÍÊÊÊÀÀÀµµµ³³³µµµ¸¸¸¿¿¿¸¸¸±±±ºººÀÀÀ¾¾¾¼¼¼¼¼¼¼¼¼»»»³³³¯¯¯¿¿¿ÉÉÉ¿¿¿ÀÀÀÃÃÃÆÆÆÆÆÆÇÇÇÇÇÇÊÊÊÌÌÌÕÕÕ×××ÝÝÝêêêöööúúúõõõîîîîîîøøøüüüõõõîîîïïïöööúúúòòòòòòòòòòòòóóóõõõööööööóóóòòòïïïîîîíííííííííîîîãããâââãããæææäääßßßâââçççîîîïïïñññîîîèèèãããßßßßßßààà×××ÛÛÛãããâââãããæææâââíííîîîãããÝÝÝÌÌ̵µµµµµ±±±¾¾¾ÀÀÀÃÃÃÆÆÆÉÉÉÉÉÉÆÆÆÅÅÅÕÕÕÙÙÙÕÕÕÔÔÔØØØÒÒÒÌÌÌÎÎÎÃÃÃÃÃþ¾¾¸¸¸¸¸¸¾¾¾ÀÀÀ¾¾¾ÀÀÀ¿¿¿ÇÇÇÃÃÃÇÇǼ¼¼¸¸¸¾¾¾ÂÂÂÊÊÊÑÑÑ×××ØØØØØØ×××××××××ÕÕÕ××××××ÕÕÕÔÔÔÒÒÒÔÔÔÕÕÕ××××××ÕÕÕÔÔÔÔÔÔÔÔÔÌÌÌÍÍÍÍÍÍÍÍÍÍÍÍÊÊÊÉÉÉÆÆÆÅÅÅÆÆÆÆÆÆÅÅÅÃÃÃÂÂÂÂÂÂÃÃÃÀÀÀ¿¿¿ÇÇÇÎÎÎÌÌÌÑÑÑÜÜÜààààààäääÝÝÝâââÕÕÕ×××íííÜÜÜîîîèèèãããÒÒÒ¿¿¿ÀÀÀÕÕÕâââàààâââØØØÑÑÑÜÜÜëëëñññïïïññññññïïïíííæææÜÜÜ×××ÕÕÕÕÕÕØØØÛÛÛÛÛÛØØØÒÒÒÌÌÌÉÉÉÑÑÑÇÇÇÂÂÂÑÑÑÌÌÌØØØØØØÛÛÛâââÝÝÝÕÕÕÌÌÌÉÉÉÊÊÊÉÉÉÅÅÅ¿¿¿¿¿¿¼¼¼»»»ºººººº¸¸¸¸¸¸···¸¸¸ººº»»»¼¼¼ÂÂÂÊÊÊÒÒÒÍÍÍÎÎÎÎÎÎÊÊÊ¿¿¿µµµºººÂ¸¸¸³³³¼¼¼Â¿¿¿Â¿¿¿···´´´³³³¸¸¸ÆÆÆÉÉÉ»»»ÀÀÀÃÃÃÆÆÆÇÇÇÆÆÆÇÇÇÉÉÉÊÊÊÍÍÍÐÐÐ×××ßßßçççïïïõõõøøøïïïöööøøøóóóïïïñññóóóóóóïïïïïïïïïïïïñññóóóõõõöööóóóòòòïïïíííëëëëëëíííîîîèèèææææææçççæææãããæææëëëöööóóóîîîçççãããààààààâââãããÛÛÛßßßæææãããããããããàààëëëãããÒÒÒÉÉɸ¸¸¬¬¬´´´ººº¿¿¿¿¿¿ÃÃÃÊÊÊÑÑÑÑÑÑÊÊÊÅÅÅÇÇÇÍÍÍÎÎÎÐÐÐ×××ÕÕÕÍÍÍÊÊÊÅÅÅÃÃþ¾¾»»»»»»¿¿¿¾¾¾»»»¿¿¿ÂÂÂÀÀÀÇÇǺºººººÀÀÀÆÆÆÍÍÍÒÒÒ×××ÙÙÙÙÙÙÙÙÙÙÙÙ×××ÕÕÕÔÔÔÕÕÕÕÕÕÔÔÔÑÑÑÕÕÕÕÕÕÕÕÕÔÔÔÑÑÑÑÑÑÔÔÔ×××ÐÐÐÐÐÐÐÐÐÎÎÎÌÌÌÊÊÊÉÉÉÇÇÇÅÅÅÆÆÆÉÉÉÊÊÊÉÉÉÆÆÆÂÂÂÀÀÀ¿¿¿ÉÉÉØØØÝÝÝ×××ÙÙÙààààààßßßäääÝÝÝÝÝÝÕÕÕÛÛÛíííÛÛÛêêêçççèèèããã××××××ßßßâââçççÒÒÒ¾¾¾···ÂÂÂØØØæææãããäääçççïïïóóóíííäääßßßÝÝÝÕÕÕÔÔÔÕÕÕØØØÛÛÛØØØÒÒÒÌÌÌÃÃÃÅÅÅÆÆÆÑÑÑÅÅÅÌÌÌÊÊÊÊÊÊÝÝÝàààÜÜÜÑÑÑÌÌÌÌÌÌÊÊÊÃÃÃÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÃÃÿ¿¿¾¾¾¼¼¼»»»ººººººººººººµµµººº¼¼¼¼¼¼¾¾¾ÃÃÃÌÌÌÑÑÑÌÌÌÉÉÉÅÅż¼¼±±±¬¬¬µµµÃÃû»»³³³µµµ¾¾¾¾¾¾»»»¾¾¾¼¼¼³³³±±±¸¸¸ÀÀÀÉÉÉÇÇǾ¾¾ÀÀÀÃÃÃÆÆÆÇÇÇÆÆÆÆÆÆÆÆÆÇÇÇÇÇÇÌÌÌÐÐÐÑÑÑÔÔÔÝÝÝíííùùùïïïóóóõõõñññïïïïïïîîîëëëëëëëëëëëëíííîîîñññòòòóóóõõõòòòîîîëëëêêêêêêíííîîîîîîëëëêêêêêêèèèçççêêêîîîóóóïïïêêêæææããããããããããããçççàààãããèèèçççãããâââßßßäääÐÐп¿¿ººº±±±°°°ººº¿¿¿¾¾¾ÀÀÀÆÆÆÍÍÍÑÑÑÐÐÐÊÊÊÅÅž¾¾ÀÀÀÂÂÂÅÅÅÍÍÍÑÑÑÍÍÍÆÆÆÂ¿¿¿¼¼¼¼¼¼¿¿¿ÀÀÀ»»»µµµººº¼¼¼ÂÂÂÇÇǾ¾¾»»»¾¾¾ÆÆÆÊÊÊÐÐÐÕÕÕØØØØØØØØØÙÙÙÔÔÔÑÑÑÐÐÐÑÑÑÔÔÔÕÕÕÔÔÔÑÑÑÐÐÐÐÐÐÑÑÑ×××ÜÜÜÛÛÛÔÔÔÍÍÍÒÒÒÐÐÐÌÌÌÉÉÉÉÉÉÌÌÌÐÐÐÒÒÒÑÑÑÍÍÍÉÉÉÇÇÇÇÇÇÆÆÆÂ¿¿¿¾¾¾ÊÊÊÝÝÝãããÝÝÝßßßàààØØØÝÝÝãããÝÝÝÙÙÙÕÕÕÝÝÝëëëÛÛÛæææãããèèèêêêââââââäääàààÜÜÜ¿¿¿µµµÀÀÀÅÅÅÆÆÆÇÇÇÃÃÃÇÇÇØØØêêêîîîèèèëëëîîîçççÙÙÙÔÔÔÐÐÐÑÑÑØØØÛÛÛ×××ÒÒÒÌÌÌÌÌÌÇÇÇÌÌ̾¾¾ÇÇÇÊÊÊÍÍÍÅÅÅÎÎÎ×××ØØØÔÔÔÍÍÍÉÉÉÇÇÇÊÊÊÊÊÊÊÊÊÉÉÉÆÆÆÃÃÃÂÂÂÀÀÀ¿¿¿¾¾¾¼¼¼»»»ºººººººººººº¸¸¸¼¼¼¼¼¼ººº»»»ÀÀÀÆÆÆÉÉÉÊÊÊ···¯¯¯¦¦¦¦¦¦±±±¿¿¿¿¿¿´´´°°°ºººÃÃÿ¿¿¸¸¸ºººµµµ±±±µµµ¿¿¿ÅÅÅÅÅÅÃÃÃÅÅÅÀÀÀÃÃÃÆÆÆÇÇÇÆÆÆÅÅÅÅÅÅÆÆÆÇÇÇÊÊÊÊÊÊÉÉÉÇÇÇÎÎÎÜÜÜèèèëëëïïïòòòñññíííêêêççççççççççççèèèêêêëëëîîîñññòòòõõõòòòíííêêêèèèêêêíííîîîñññïïïííííííëëëêêêëëëíííæææææææææèèèêêêêêêæææâââçççãããæææêêêèèèäääââââââæææÆÆÆ···µµµ³³³´´´······¼¼¼ÂÂÂÉÉÉÍÍÍÌÌÌÉÉÉÇÇÇÇÇǼ¼¼¼¼¼»»»»»»ÂÂÂÌÌÌÎÎÎÉÉɼ¼¼ººº»»»¿¿¿Â¿¿¿¸¸¸³³³¸¸¸»»»ÃÃÃÆÆÆÃÃø¸¸ººº¾¾¾ÇÇÇÍÍÍÔÔÔ××××××ÕÕÕÕÕÕÕÕÕÎÎÎÍÍÍÍÍÍÐÐÐÑÑÑÒÒÒÑÑÑÎÎÎÊÊÊÑÑÑßßßëëëïïïèèèÛÛÛÐÐÐÑÑÑÐÐÐÎÎÎÎÎÎÑÑÑ×××ÜÜÜàààßßßÙÙÙÐÐÐÆÆÆ¿¿¿¿¿¿ÃÃÃÇÇÇÆÆÆÇÇÇÎÎÎÎÎÎÍÍÍ×××ÜÜÜ×××ÜÜÜàààÜÜÜØØØÕÕÕÝÝÝçççÜÜÜëëëçççêêêëëëäääãããäääÝÝÝÛÛÛÃÃþ¾¾ÇÇÇÇÇÇÆÆÆÉÉÉÇÇÇÂÂÂÉÉÉÙÙÙãããæææíííîîîãããâââØØØÎÎÎÌÌÌÒÒÒØØØÛÛÛÙÙÙÜÜÜÎÎÎÆÆÆ×××ÊÊÊÌÌÌÌÌÌÔÔÔÀÀÀÂÂÂÌÌÌ×××ÙÙÙÒÒÒÊÊÊÇÇÇÉÉÉÉÉÉÇÇÇÆÆÆÃÃÃÂÂÂÀÀÀ¿¿¿¾¾¾¼¼¼¼¼¼»»»ºººººº»»»»»»¼¼¼¾¾¾¼¼¼¸¸¸»»»ÃÃÃÆÆÆÅÅÅÉÉÉ»»»­­­¨¨¨©©©­­­···ÀÀÀ¿¿¿°°°­­­ºººÂ¾¾¾»»»¾¾¾´´´±±±´´´¿¿¿ÆÆÆÃÃÃÂÂÂÆÆÆÀÀÀÃÃÃÆÆÆÆÆÆÆÆÆÅÅÅÅÅÅÆÆÆÉÉÉÉÉÉÇÇÇÆÆÆÆÆÆÉÉÉÐÐÐÔÔÔæææëëëññññññêêêäääãããçççääääääæææçççèèèëëëîîîïïïóóóñññíííêêêèèèêêêíííïïïïïïïïïïïïîîîîîîíííêêêçççàààâââäääèèèëëëèèèäääßßßããããããäääèèèêêêäääãããæææããã¾¾¾´´´······»»»¸¸¸´´´»»»ÂÂÂÉÉÉÌÌÌÉÉÉÆÆÆÆÆÆÉÉÉÃÃÃÀÀÀ¾¾¾ººº¼¼¼ÊÊÊÑÑÑÌÌ̼¼¼»»»¼¼¼ÀÀÀ¼¼¼···³³³¼¼¼¼¼¼ÅÅÅÅÅÅÃÃó³³´´´ºººÅÅÅÌÌÌÔÔÔØØØ×××ÔÔÔÑÑÑÑÑÑÍÍÍÎÎÎÍÍÍÍÍÍÍÍÍÌÌÌÍÍÍÍÍÍØØØâââíííñññïïïëëëêêêêêêÜÜÜÝÝÝÝÝÝÝÝÝÜÜÜÜÜÜÛÛÛÛÛÛØØØßßßàààØØØÊÊÊÂÂÂÃÃÃÉÉÉÎÎÎÉÉÉÇÇÇÆÆÆÆÆÆÒÒÒÝÝÝÜÜÜÜÜÜÝÝÝÜÜÜØØØ×××ÜÜÜâââàààêêêæææêêêëëëæææçççêêêæææÂÂÂÃÃÃÉÉÉÎÎÎÑÑÑÕÕÕÒÒÒÊÊÊÉÉɺººÅÅÅßßßêêêîîîíííâââèèèàààÕÕÕÐÐÐÒÒÒ×××ÛÛÛÜÜÜÕÕÕÎÎÎÊÊÊ×××ÍÍÍÑÑÑÊÊÊÆÆÆÑÑÑÇÇÇÃÃÃÍÍÍØØØØØØÐÐÐÆÆÆÆÆÆÅÅÅÃÃÃÀÀÀ¿¿¿¿¿¿¿¿¿¿¿¿¾¾¾¼¼¼»»»»»»ººº»»»»»»»»»¿¿¿¿¿¿¼¼¼ºººÀÀÀÌÌÌÊÊÊÃÃúºº¯¯¯¥¥¥¥¥¥ªªª±±±¸¸¸ÀÀÀ¼¼¼¬¬¬¦¦¦°°°´´´µµµ¸¸¸»»»ººº´´´°°°¸¸¸ÅÅÅÅÅÅÀÀÀÃÃÃÂÂÂÃÃÃÆÆÆÆÆÆÅÅÅÅÅÅÇÇÇÉÉÉÇÇÇÆÆÆÆÆÆÆÆÆÇÇÇÉÉÉÊÊÊÊÊÊãããçççëëëîîîêêêããããããçççäääääääääæææèèèêêêííííííñññïïïíííêêêêêêíííïïïñññïïïññññññïïïîîîîîîèèèãããææææææäääããããããâââßßßÝÝÝàààââââââäääçççãããâââèèèÛÛÛ···µµµ»»»¸¸¸¼¼¼»»»¼¼¼ººº¿¿¿ÅÅÅÊÊÊÌÌÌÊÊÊÉÉÉÇÇÇÃÃÃÃÃü¼¼ºººÆÆÆÎÎÎÆÆÆÅÅÅÀÀÀÀÀÀÂÂÂÀÀÀºººµµµµµµ¾¾¾»»»ÅÅÅÃÃÃÃÃñ±±´´´¸¸¸¿¿¿ÇÇÇÑÑÑ×××ÕÕÕÒÒÒÑÑÑÐÐÐÍÍÍÎÎÎÍÍÍÊÊÊÇÇÇÉÉÉÎÎÎÔÔÔæææèèèèèèæææâââãããíííóóóèèèçççæææãããßßßÙÙÙÕÕÕÒÒÒ×××ÝÝÝäääæææßßßÕÕÕÍÍÍÉÉÉÎÎÎÉÉÉÌÌÌÐÐÐÌÌÌÑÑÑÝÝÝâââÜÜÜÛÛÛÛÛÛÙÙÙØØØÙÙÙÝÝÝäääßßßßßßçççëëëæææçççíííëëë¾¾¾ÆÆÆÆÆÆÃÃÃÍÍÍÕÕÕÕÕÕÐÐÐÉÉɺººÇÇÇãããëëëîîîñññçççíííèèèãããÜÜÜØØØØØØØØØÙÙÙØØØÙÙÙÑÑÑÎÎÎÀÀÀÑÑÑÎÎÎÆÆÆÎÎÎÎÎÎÇÇÇÂÂÂÌÌÌÙÙÙØØØÍÍÍÐÐÐÍÍÍÉÉÉÅÅÅÀÀÀÀÀÀÀÀÀÀÀÀ¼¼¼¼¼¼»»»»»»»»»»»»»»»¼¼¼¿¿¿¿¿¿¼¼¼¼¼¼ÆÆÆÎÎÎÇÇǸ¸¸¬¬¬©©©¨¨¨ªªª¬¬¬­­­´´´¼¼¼»»»­­­ªªª±±±±±±³³³···µµµ¼¼¼»»»³³³´´´¾¾¾ÀÀÀ¿¿¿ÅÅÅÃÃÃÅÅÅÅÅÅÅÅÅÅÅÅÆÆÆÊÊÊÍÍÍÊÊÊÌÌÌÌÌÌÊÊÊÇÇÇÆÆÆÇÇÇÉÉÉäääââââââèèèëëëèèèääääääææææææææææææçççêêêëëëëëëîîîííííííëëëíííïïïñññóóóòòòóóóòòòîîîîîîïïïêêêãããçççæææãããßßßÜÜÜÜÜÜÜÜÜßßßßßßâââààààààäääàààßßßèèèÛÛÛ···ººº¼¼¼´´´···¸¸¸¾¾¾»»»¼¼¼ÀÀÀÉÉÉÐÐÐÐÐÐÌÌÌÆÆÆÀÀÀÀÀÀÃÃþ¾¾¸¸¸ÂÂÂÉÉɾ¾¾ÍÍÍÇÇÇÃÃþ¾¾···µµµ¸¸¸ºººµµµÂÂÂÂÂÂÅÅų³³···»»»ºººÃÃÃÐÐÐ×××ÕÕÕÒÒÒÑÑÑÐÐÐÌÌÌÌÌÌÌÌÌÇÇÇÆÆÆÊÊÊÕÕÕÝÝÝâââßßßÝÝÝÜÜÜÝÝÝßßßààààààæææãããàààÜÜÜÙÙÙØØØØØØØØØæææßßßÙÙÙÝÝÝäääæææÜÜÜÑÑÑÌÌÌÆÆÆÌÌÌÎÎÎÆÆÆÉÉÉÙÙÙæææÜÜÜØØØÛÛÛÛÛÛÙÙÙ×××ÛÛÛèèèÜÜÜßßßèèèëëëâââàààãããâââÃÃÃÊÊÊÇÇÇÌÌÌØØØÕÕÕÊÊÊÊÊÊÆÆÆÇÇÇÜÜÜêêêäääêêêòòòèèèîîîîîîíííçççßßßÙÙÙ××××××ÝÝÝßßßÝÝÝâââÐÐÐÔÔÔÎÎÎÌÌ̺ººÌÌÌÍÍ;¾¾ÀÀÀ×××ààà×××ßßßÛÛÛÔÔÔÌÌÌÆÆÆÂ¼¼¼¼¼¼»»»»»»»»»»»»»»»¼¼¼¿¿¿¿¿¿¼¼¼¼¼¼ÅÅÅÌÌÌ¿¿¿ªªª¯¯¯±±±···¸¸¸³³³¯¯¯´´´¾¾¾¿¿¿···¼¼¼ÃÃÃÀÀÀ¾¾¾¼¼¼µµµ¸¸¸¿¿¿»»»´´´···¸¸¸¾¾¾ÊÊÊÅÅÅÅÅÅÅÅÅÃÃÃÃÃÃÆÆÆÌÌÌÐÐÐÎÎÎÑÑÑÑÑÑÌÌÌÅÅÅÀÀÀÅÅÅÊÊÊçççÝÝÝÛÛÛäääîîîîîîçççãããççççççæææççççççèèèêêêëëëííííííííííííîîîñññòòòóóóõõõöööòòòííííííïïïíííæææâââââââââàààÜÜÜÛÛÛÜÜÜßßßßßßâââßßßÝÝÝâââÜÜÜÜÜÜèè謬¬¾¾¾¿¿¿ººº»»»»»»···ººººººÃÃÃÊÊÊÌÌÌÌÌÌÌÌÌÉÉÉÃÃÃÆÆÆÅÅÅÇÇÇÂÂÂÀÀÀ¼¼¼µµµÃÃÃÎÎÎÍÍÍÇÇǾ¾¾ººº»»»¸¸¸³³³³³³µµµÂÂÂÆÆÆ¼¼¼¸¸¸¸¸¸³³³¸¸¸ÂÂÂÎÎÎÔÔÔÒÒÒÎÎÎÍÍÍÌÌÌÇÇÇÐÐÐÍÍÍÀÀÀÀÀÀÐÐÐÝÝÝàààØØØÙÙÙÛÛÛÛÛÛÙÙÙÙÙÙÜÜÜßßßÜÜÜâââæææäääßßßÙÙÙ×××ØØØÜÜÜÝÝÝÜÜÜÙÙÙÙÙÙÝÝÝçççîîîÎÎÎÍÍÍÌÌÌÌÌÌÌÌÌÎÎÎÑÑÑÒÒÒÐÐÐÎÎÎÙÙÙÝÝÝÝÝÝÛÛÛÒÒÒØØØâââèèèæææçççãããÝÝÝæææäääÂÂÂÆÆÆÊÊÊÐÐÐÑÑÑÑÑÑÐÐÐÍÍÍÇÇÇ¿¿¿ççççççïïïóóóêêêîîîñññèèèàààÜÜÜÜÜÜÜÜÜÛÛÛ×××ÙÙÙ×××ÝÝÝäääÛÛÛÊÊÊÉÉÉÔÔÔÒÒÒÀÀÀÎÎÎÊÊʺºº¿¿¿ÊÊÊ××××××ØØØÙÙÙÕÕÕÉÉÉ¿¿¿ÅÅÅÐÐÐÐÐÐÀÀÀµµµ···ºººººº»»»¿¿¿ÅÅÅ¿¿¿ÊÊÊÊÊÊÅÅż¼¼©©©ªªª¸¸¸···¸¸¸ººº¾¾¾¾¾¾ºººµµµ¸¸¸¼¼¼ÀÀÀÀÀÀ¼¼¼»»»¾¾¾ÀÀÀªªªÀÀÀ¾¾¾´´´»»»¸¸¸´´´¿¿¿¼¼¼¸¸¸ÀÀÀÎÎÎÑÑÑÉÉÉÉÉÉÑÑÑÊÊÊÐÐÐÑÑÑÊÊÊÃÃÃÅÅÅÆÆÆÅÅÅÇÇÇÆÆÆ××׿ææäääæææëëëêêêèèèççççççæææææææææææææææççççççæææçççëëëñññöööúúúõõõöööøøøöööóóóñññòòòòòòâââäääÝÝÝßßßîîîñññíííïïïïïïîîîëëëêêêíííïïïæææÙÙÙººº···»»»¿¿¿¾¾¾ºººººº»»»¼¼¼ÅÅÅÌÌÌÊÊÊÊÊÊÊÊÊÇÇÇÃÃÃÅÅÅÂÂÂÅÅÅÀÀÀ¿¿¿µµµÂÂÂÂÂÂÆÆÆÆÆÆ¿¿¿ººº···´´´¯¯¯¸¸¸···¿¿¿ÅÅÅÃÃÃÆÆÆÆÆÆ¼¼¼µµµ¿¿¿ÊÊÊÑÑÑÑÑÑÎÎÎÌÌÌÌÌÌÉÉÉÉÉÉÆÆÆÅÅÅÍÍÍÙÙÙÛÛÛÕÕÕÙÙÙÛÛÛÝÝÝÜÜÜÙÙÙÙÙÙÛÛÛÝÝÝàààãããæææãããÝÝÝÙÙÙÙÙÙÜÜÜÙÙÙÙÙÙØØØÔÔÔÒÒÒØØØàààèèèÌÌÌÍÍÍÎÎÎÑÑÑÑÑÑÐÐÐÍÍÍÌÌÌÐÐÐÊÊÊÒÒÒ×××ÙÙÙÙÙÙÐÐÐÔÔÔØØØããããããçççëëëëëëëëëÜÜÜÀÀÀÃÃÃÉÉÉÍÍÍÐÐÐÎÎÎÍÍÍÌÌÌÃÃÃÃÃÃæææçççñññòòòîîîêêêäääàààÜÜÜÛÛÛÜÜÜÝÝÝÝÝÝÛÛÛ×××ØØØÙÙÙÜÜÜÛÛÛØØØÕÕÕÕÕÕÔÔÔÀÀÀÐÐÐÒÒÒ¾¾¾ºººÅÅÅ×××ÔÔÔÕÕÕØØØØØØÒÒÒÎÎÎÐÐÐÒÒÒÊÊÊÇÇÇÃÃþ¾¾¸¸¸¸¸¸¾¾¾ÃÃÃÐÐÐÅÅÅÅÅż¼¼´´´±±±©©©±±±¸¸¸ººº»»»»»»ººº¸¸¸¸¸¸¸¸¸³³³µµµ······µµµµµµººº¼¼¼ªªªººº¼¼¼»»»¿¿¿¼¼¼ºººÀÀÀÐÐÐÅÅž¾¾ÆÆÆÑÑÑÒÒÒÊÊÊÂÂÂÍÍÍÑÑÑÐÐÐÉÉÉÃÃÃÃÃÃÃÃÃÂÂÂÅÅÅÃÃÃÌÌÌ×××ÜÜÜàààçççëëëêêêèèèçççæææääääääääääääææææææçççèèèëëëïïïòòòõõõòòòóóóõõõõõõòòòòòòòòòóóóçççãããÜÜÜÝÝÝçççëëëèèèçççëëëíííêêêèèèêêêëëëãããÙÙÙÌÌ̵µµµµµÂ¿¿¿ººº¾¾¾¾¾¾ÂÂÂÇÇÇÊÊÊÊÊÊÉÉÉÉÉÉÇÇÇÅÅÅÆÆÆÂÂÂÃÃÃÀÀÀÃÃÿ¿¿³³³ººº¸¸¸ÂÂÂÇÇÇÃÃû»»µµµ±±±°°°³³³¸¸¸ÂÂÂÅÅÅÂÂÂÉÉÉÎÎÎÊÊÊ´´´¼¼¼ÇÇÇÍÍÍÎÎÎÌÌÌÊÊÊÊÊÊÆÆÆÅÅÅÆÆÆÍÍÍØØØÜÜÜ×××ÐÐÐÙÙÙÜÜÜàààßßßÛÛÛÙÙÙÛÛÛßßßãããääääääâââÜÜÜÛÛÛÝÝÝàààÛÛÛÛÛÛØØØÔÔÔÑÑÑÔÔÔÝÝÝäääÎÎÎÐÐÐÐÐÐÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÊÊÊÑÑÑÔÔÔÙÙÙÛÛÛÑÑÑÔÔÔÙÙÙèèèäääãããèèèëëëÝÝÝ»»»¾¾¾ÀÀÀÅÅÅÉÉÉÌÌÌÌÌÌÊÊÊÉÉÉÅÅÅÎÎÎèèèêêêòòòòòòõõõæææßßßÝÝÝÝÝÝßßßßßßßßßÝÝÝÝÝÝ×××ÛÛÛÙÙÙÕÕÕÛÛÛäääàààÒÒÒØØØÀÀÀÌÌÌÕÕÕÇÇǼ¼¼¿¿¿ÍÍÍÔÔÔÔÔÔÒÒÒÑÑÑÑÑÑÐÐÐÌÌÌÇÇÇÍÍÍÑÑÑÌÌ̼¼¼···¿¿¿ÇÇÇÊÊÊÎÎÎÃÃü¼¼¯¯¯¨¨¨©©©¬¬¬···µµµ······ººº»»»ººº···´´´³³³´´´´´´µµµ···¸¸¸¼¼¼¾¾¾¸¸¸»»»¾¾¾ÀÀÀ¿¿¿ÂÂÂÆÆÆÆÆÆÇÇÇÆÆÆÆÆÆÊÊÊÒÒÒÒÒÒÎÎÎÇÇÇÊÊÊÊÊÊÇÇÇÆÆÆÉÉÉÊÊÊÉÉÉÅÅÅÃÃÃÃÃÃÍÍÍÙÙÙßßßàààçççêêêèèèçççæææããããããââââââãããäääçççêêêíííîîîïïïïïïòòòóóóóóóóóóïïïîîîíííîîîçççßßßÛÛÛÜÜÜßßßäääçççâââèèèèèèèèèççççççæææàààÛÛÛØØØÀÀÀ···¾¾¾¿¿¿¼¼¼¿¿¿ÂÂÂÆÆÆÉÉÉÊÊÊÉÉÉÆÆÆÆÆÆÆÆÆÆÆÆÌÌÌÅÅÅÅÅÅÀÀÀÃÃü¼¼­­­±±±¼¼¼ÅÅÅÊÊÊÆÆÆ»»»´´´µµµ¸¸¸´´´µµµ¾¾¾ÂÂÂÀÀÀÇÇÇÌÌÌÆÆÆ¸¸¸¿¿¿ÆÆÆÌÌÌÌÌÌÊÊÊÇÇÇÇÇÇÅÅÅÇÇÇÎÎÎ××××××ÑÑÑÑÑÑÕÕÕ×××ÛÛÛßßßßßßÜÜÜÛÛÛÝÝÝàààäääæææäääâââßßßÝÝÝàààããããããâââßßßÙÙÙÕÕÕØØØàààçççÐÐÐÐÐÐÑÑÑÒÒÒÔÔÔÔÔÔÕÕÕÕÕÕÒÒÒÐÐÐÙÙÙÙÙÙÛÛÛÝÝÝÕÕÕØØØ×××êêêçççàààçççîîîÝÝݵµµººº¼¼¼ÀÀÀÅÅÅÇÇÇÇÇÇÆÆÆÅÅÅÑÑÑàààñññîîîóóóñññúúúããããããäääææææææâââÝÝÝÜÜÜÛÛÛÛÛÛÝÝÝÛÛÛ×××ÛÛÛäääßßßÑÑÑÙÙÙÃÃÃÃÃÃÑÑÑÑÑÑÉÉÉÃÃÿ¿¿ÑÑÑÑÑÑÐÐÐÌÌÌÌÌÌÌÌÌÉÉÉÅÅÅÍÍÍÒÒÒÍÍÍÂÂÂÂÂÂÍÍÍÌÌÌÀÀÀ¼¼¼¸¸¸´´´­­­©©©ªªª°°°¸¸¸³³³­­­ªªª³³³¾¾¾ÀÀÀ···­­­³³³³³³´´´···ººº¼¼¼¾¾¾¾¾¾ÇÇǺººµµµ···­­­¬¬¬³³³´´´¸¸¸ÃÃÃÍÍÍÌÌÌÇÇÇÌÌÌÕÕÕÝÝÝÔÔÔÑÑÑÍÍÍÇÇÇÅÅÅÂÂÂÀÀÀ¿¿¿ÅÅÅÅÅÅÃÃÃÍÍÍßßßàààÙÙÙßßßêêêèèèæææãããâââàààààààààâââäääçççêêêíííïïïïïïïïïòòòóóóóóóñññëëëæææäääãããâââÛÛÛÝÝÝàààÜÜÜàààçççãããäääççççççæææäääãããàààÝÝÝßßßÔÔÔÀÀÀ···¼¼¼ÀÀÀÂÂÂÆÆÆÇÇÇÇÇÇÉÉÉÇÇÇÅÅÅÃÃÃÅÅÅÆÆÆÉÉÉÃÃþ¾¾¿¿¿»»»¬¬¬³³³ÃÃÃÇÇÇÉÉɸ¸¸³³³¸¸¸ÀÀÀÃÃõµµ´´´¾¾¾ÇÇÇÍÍÍÆÆÆ´´´¾¾¾ÂÂÂÇÇÇÊÊÊÊÊÊÇÇÇÅÅÅÃÃÃÌÌÌÎÎÎÔÔÔ×××ÐÐÐÇÇÇÍÍÍÙÙÙÔÔÔØØØÜÜÜÜÜÜÜÜÜÜÜÜàààããããããäääääääääãããâââââââââççççççäääßßßÛÛÛÛÛÛâââçççÑÑÑÒÒÒÔÔÔÔÔÔÔÔÔÒÒÒÑÑÑÐÐÐÐÐÐÔÔÔàààÝÝÝÛÛÛÛÛÛÕÕÕÛÛÛÔÔÔèèèãããÙÙÙÜÜÜäääÙÙÙµµµ···¸¸¸¼¼¼ÀÀÀÂÂÂÃÃÃÃÃÃÂÂÂãããóóóùùùòòòóóóñññÿÿÿãããäääçççèèèçççâââÜÜÜÛÛÛÛÛÛÜÜÜÝÝÝÜÜÜÜÜÜÝÝÝÝÝÝÛÛÛ×××ÒÒÒÇÇÇÅÅÅÍÍÍÐÐÐÎÎÎÉÉɾ¾¾ÃÃÃÊÊÊÑÑÑÒÒÒÐÐÐÍÍÍÍÍÍÍÍÍÇÇÇÑÑÑÔÔÔÎÎÎÎÎÎÎÎÎÀÀÀ¯¯¯±±±³³³±±±°°°¯¯¯¯¯¯´´´µµµ­­­¨¨¨¤¤¤ªªª···¾¾¾ººº³³³¯¯¯°°°±±±´´´···ºººººº¸¸¸»»»¬¬¬­­­´´´±±±···ÃÃÃÅÅÅÀÀÀÂÂÂÉÉÉÎÎÎÐÐÐÌÌÌÌÌÌÐÐÐÕÕÕÑÑÑÌÌÌÇÇÇÅÅÅÀÀÀ¿¿¿¿¿¿ÂÂÂÃÃÃÀÀÀÊÊÊÜÜÜßßßÙÙÙßßßæææäääãããâââàààßßßßßßßßßãããäääçççêêêîîîñññòòòòòòîîîïïïïïïíííèèèãããàààßßßßßßßßßçççèèèÜÜÜÜÜÜääääääãããäääææææææäääâââââââââàààâââÍÍ͸¸¸»»»ÀÀÀÂÂÂÆÆÆÇÇÇÆÆÆÆÆÆÆÆÆÅÅÅÂÂÂÂÂÂÆÆÆÀÀÀ¼¼¼¾¾¾ººº»»»ººº³³³¿¿¿ÆÆÆÅÅž¾¾···´´´»»»ÅÅÅÍÍÍ»»»¸¸¸ÅÅÅÉÉÉÆÆÆ¿¿¿µµµÂÂÂÅÅÅÇÇÇÉÉÉÉÉÉÆÆÆÂÂÂÀÀÀØØØÒÒÒÐÐÐÑÑÑÎÎÎÌÌÌÎÎÎ×××ÒÒÒÔÔÔ×××ØØØÙÙÙÝÝÝàààäääâââãããäääææææææäääãããâââääääääãããßßßÛÛÛÙÙÙÝÝÝâââãããÝÝÝÕÕÕÎÎÎÍÍÍÎÎÎÒÒÒÕÕÕÒÒÒ×××ãããÜÜÜØØØÙÙÙÕÕÕÙÙÙßßßëëëãããÛÛÛÜÜÜàààÙÙÙ¾¾¾´´´µµµººº¼¼¼¿¿¿¿¿¿ÀÀÀ¿¿¿îîîùùùÿÿÿóóóóóóïïïÿÿÿæææàààãããäääãããâââààààààãããâââÝÝÝÝÝÝàààßßßÛÛÛÛÛÛßßßÉÉÉÎÎÎÌÌÌÍÍÍÊÊÊÇÇÇÍÍÍÆÆÆ»»»ÂÂÂÍÍÍÒÒÒÌÌÌÂÂÂÀÀÀÆÆÆÎÎÎÑÑÑÒÒÒÍÍÍÆÆÆ¾¾¾µµµ°°°³³³···³³³³³³³³³±±±´´´¯¯¯¬¬¬ªªªªªª©©©¬¬¬±±±¸¸¸¼¼¼³³³µµµ···¸¸¸¸¸¸ºººººº»»»Â»»»¿¿¿ÆÆÆÂÂÂÅÅÅÌÌÌÉÉÉÂÂÂÂÂÂÇÇÇÑÑÑÔÔÔÎÎÎÇÇÇÅÅÅÍÍÍÉÉÉÇÇÇÆÆÆÅÅÅÃÃÃÆÆÆÊÊÊÀÀÀ¾¾¾¼¼¼ÅÅÅÒÒÒÙÙÙÜÜÜãããàààßßßßßßÝÝÝÝÝÝÝÝÝßßßßßßäääæææèèèëëëîîîïïïñññòòòçççèèèëëëëëëèèèäääããããããäääçççíííëëëàààÜÜÜßßßààààààßßßâââääääääããããããæææâââæææÛÛÛÆÆÆ»»»¾¾¾ÂÂÂÃÃÃÅÅÅÃÃÃÃÃÃÆÆÆÅÅÅÀÀÀÂÂÂÆÆÆºººººº¼¼¼µµµµµµ···µµµÉÉÉÇÇÇÃÃÃÀÀÀ¿¿¿¾¾¾¾¾¾ÂÂÂÊÊÊÌÌ̼¼¼ÀÀÀÌÌÌÃÃ÷··ºººÀÀÀÀÀÀÂÂÂÅÅÅÆÆÆÆÆÆÃÃÃÀÀÀ¿¿¿ÜÜÜÔÔÔÍÍÍÍÍÍÐÐÐÑÑÑÑÑÑÒÒÒÕÕÕÒÒÒÒÒÒÔÔÔ×××ÜÜÜßßßâââââââââäääæææææææææäääãããßßßââââââÝÝÝÙÙÙØØØÙÙÙÝÝÝïïïèèèàààØØØÕÕÕØØØßßßãããÝÝÝÜÜÜâââÙÙÙØØØßßßØØØØØØëëëîîîäääæææííííííæææÑÑѳ³³´´´···ººº¼¼¼¾¾¾¾¾¾¾¾¾ëëëòòòúúúòòòóóóïïïùùùçççââââââãããäääæææèèèîîîñññïïïçççàààßßßßßßÜÜÜÜÜÜßßßÊÊÊÑÑÑÌÌÌÍÍÍÇÇÇ¿¿¿ÌÌÌÐÐо¾¾ÀÀÀÅÅÅ¿¿¿³³³µµµÂÂÂÐÐÐÆÆÆÂÂÂÅÅÅÀÀÀµµµ±±±µµµ´´´»»»µµµ¸¸¸ºººµµµµµµ©©©¬¬¬±±±´´´³³³­­­¬¬¬°°°µµµ»»»¼¼¼¼¼¼ººº···¸¸¸¼¼¼¿¿¿¸¸¸ººº¿¿¿ÀÀÀÀÀÀÆÆÆÉÉÉÆÆÆ¸¸¸ÃÃÃÎÎÎÔÔÔÒÒÒÐÐÐÊÊÊÆÆÆÔÔÔÐÐÐÌÌÌÉÉɼ¼¼¾¾¾ÃÃÃÅÅÅÀÀÀÅÅÅÍÍÍÐÐÐÕÕÕÜÜÜâââÛÛÛÛÛÛÛÛÛÛÛÛÜÜÜÝÝÝßßßàààäääçççêêêíííîîîíííëëëêêêæææèèèííííííëëëèèèçççæææëëëíííèèèææææææâââÝÝÝÝÝÝÜÜÜÙÙÙÛÛÛàààãããâââãããæææããããããâââÒÒÒ»»»ºººÂÂÂÀÀÀÃÃÃÂÂÂÂÂÂÆÆÆÅÅÅ¿¿¿ÀÀÀÆÆÆ»»»»»»¾¾¾´´´±±±±±±µµµÌÌÌÉÉÉÃÃÃÂÂÂÆÆÆÉÉÉÇÇÇÊÊÊÐÐÐÍÍ͸¸¸ºººÇÇÇÀÀÀ±±±···ÃÃþ¾¾¿¿¿ÀÀÀÂÂÂÃÃÃÂÂÂÀÀÀ¾¾¾ØØØÔÔÔÐÐÐÍÍÍÐÐÐÒÒÒÒÒÒÑÑÑ×××ÔÔÔÐÐÐÐÐÐÕÕÕÛÛÛÝÝÝÝÝÝââââââãããääääääæææääääääÝÝÝàààâââßßßÛÛÛØØØÙÙÙÜÜÜèèèëëëïïïòòòñññîîîêêêçççëëëãããàààØØØÜÜÜæææßßßÛÛÛñññêêêÜÜÜâââçççÝÝÝÑÑÑ»»»±±±´´´µµµ¸¸¸»»»¼¼¼¾¾¾¾¾¾äääçççöööïïïòòòïïïöööèèèçççççççççèèèíííòòòøøøüüüÿÿÿòòòäääÜÜÜÜÜÜÝÝÝÝÝÝÛÛÛÒÒÒÑÑÑÅÅÅÍÍÍÊÊʾ¾¾ÉÉÉÑÑÑÎÎξ¾¾µµµººº¸¸¸³³³¾¾¾ÒÒÒÃÃó³³³³³ÇÇÇÎÎο¿¿¯¯¯­­­±±±»»»¸¸¸¿¿¿ÃÃü¼¼¸¸¸¥¥¥¯¯¯´´´»»»¾¾¾ººº±±±©©©¥¥¥»»»»»»¸¸¸³³³¯¯¯°°°···¼¼¼ºººÀÀÀÀÀÀ»»»¼¼¼ÃÃÃÆÆÆÆÆÆºººÉÉÉÒÒÒÑÑÑÑÑÑÕÕÕÍÍÍ¿¿¿ÒÒÒÎÎÎÌÌÌÉÉÉ»»»¾¾¾ÆÆÆÊÊÊÇÇÇÒÒÒÛÛÛÕÕÕÕÕÕÛÛÛÙÙÙ××××××ØØØÙÙÙÛÛÛÝÝÝàààâââäääçççëëëîîîîîîëëëæææâââêêêíííïïïïïïíííêêêçççæææîîîíííàààßßßêêêèèèßßßÝÝÝÙÙÙÕÕÕ×××ÝÝÝâââââââââæææßßßçççßßßßßßÛÛÛ±±±¼¼¼¿¿¿ÀÀÀÅÅÅÅÅÅÂÂÂÀÀÀÃÃÃÃÃÃÀÀÀººº¾¾¾°°°¼¼¼»»»­­­ÂÂÂÇÇÇÆÆÆÊÊÊÎÎÎÑÑÑÑÑÑÐÐÐÎÎÎÎÎÎÌÌ̾¾¾»»»ºººÅÅ۰°°°°ºººµµµººº¾¾¾ÂÂÂÂÂÂÀÀÀÂÂÂÂÂÂ×××ÙÙÙÉÉÉÌÌÌÑÑÑÊÊÊÎÎÎÎÎÎÎÎÎÊÊÊÑÑÑÔÔÔÐÐÐÔÔÔÜÜÜÙÙÙßßßàààãããäääääääääãããâââæææâââàààâââßßßØØØÕÕÕ×××ßßßãããææææææãããâââäääèèèêêêäääãããäääãããÝÝÝÝÝÝâââëëëëëëâââêêêÜÜÜÐÐеµµ±±±´´´µµµµµµ»»»¼¼¼ÃÃü¼¼âââæææòòòííííííîîîêêêõõõÿÿÿæææäääæææíííõõõùùùùùùöööóóóñññëëëãããÛÛÛØØØØØØÙÙÙÒÒÒæææÍÍÍÅÅÅÕÕÕÎÎÎÊÊÊÎÎÎÍÍÍÊÊʾ¾¾¾¾¾»»»¸¸¸ÊÊÊÔÔÔÍÍÍÍÍÍÑÑÑÎÎÎÉÉÉÌÌÌÃÃí­­±±±³³³»»»¾¾¾»»»¾¾¾¸¸¸ªªª°°°¾¾¾Âººº···ººº³³³¨¨¨¼¼¼»»»´´´©©©¨¨¨¯¯¯µµµµµµ»»»···ºººÂ¿¿¿µµµµµµ¼¼¼ÂÂÂÍÍÍÑÑÑÐÐÐÑÑÑÕÕÕÍÍÍÀÀÀÎÎÎÍÍÍÃÃÃÊÊÊÉÉɾ¾¾ÃÃÃÂÂÂÉÉÉÑÑÑÙÙÙØØØÕÕÕÔÔÔÔÔÔÔÔÔÔÔÔÎÎÎÎÎÎÕÕÕÛÛÛÛÛÛÜÜÜâââääääääçççíííïïïíííçççãããâââæææëëëïïïïïïîîîëëëëëëíííæææßßßÛÛÛØØØØØØâââíííàààÜÜÜÙÙÙÛÛÛàààæææçççæææëëëñññæææäääããã···ººº»»»¿¿¿Â¾¾¾¾¾¾ÀÀÀÀÀÀ¾¾¾¼¼¼¾¾¾°°°ººº¸¸¸¯¯¯ÅÅÅÍÍÍÉÉÉÌÌÌÑÑÑÒÒÒÒÒÒÑÑÑÐÐÐÐÐÐÐÐÐÅÅž¾¾ÆÆÆ´´´´´´¼¼¼···ººº¾¾¾ÀÀÀÀÀÀ¿¿¿ÀÀÀÂÂÂÊÊÊÒÒÒÉÉÉÉÉÉÎÎÎÌÌÌÑÑÑÑÑÑÉÉÉÉÉÉÐÐÐÒÒÒÎÎÎÒÒÒÛÛÛÛÛÛßßßàààâââãããäääãããâââàààçççäääãããæææäääßßßÝÝÝàààäääææææææäääâââãããèèèîîîæææãããâââããããããâââæææíííêêêëëëæææäääÍÍÍÃÃ÷··µµµ´´´µµµ³³³»»»¾¾¾ÀÀÀºººâââçççñññêêêèèèëëëèèèòòòúúúæææëëëòòòøøøùùùøøøöööõõõõõõòòòëëëãããÜÜÜÙÙÙÜÜÜààà×××âââÊÊÊÅÅÅÔÔÔÐÐÐÌÌÌÊÊÊÅÅÅÍÍÍÍÍÍÐÐÐÆÆÆ¼¼¼ÊÊÊÕÕÕÑÑÑÑÑÑÔÔÔÔÔÔÐÐÐÐÐÐÅÅÅ­­­±±±³³³ººº¼¼¼»»»ÀÀÀ¸¸¸¬¬¬¸¸¸ÃÃÃÀÀÀ»»»µµµ°°°¬¬¬­­­¬¬¬¨¨¨¢¢¢¦¦¦±±±¸¸¸»»»¿¿¿ºººººº¾¾¾»»»³³³µµµ¾¾¾ÆÆÆÐÐÐÔÔÔÑÑÑÒÒÒÕÕÕÎÎÎÂÂÂÍÍÍÍÍÍÉÉÉÌÌÌÌÌÌÆÆÆÂºººÊÊÊ×××ßßßÛÛÛØØØÛÛÛÕÕÕÌÌÌÅÅŵµµ´´´ÊÊÊÜÜÜÝÝÝÛÛÛÜÜÜâââæææèèèçççäääæææïïïøøøóóóïïïëëëèèèëëëîîîñññòòòßßßÙÙÙ××××××ÕÕÕÔÔÔØØØÝÝÝãããßßßÙÙÙÛÛÛàààæææèèèèèèëëëîîîàààÛÛÛßßß···ººº¿¿¿¾¾¾¿¿¿¾¾¾ºººººº¾¾¾¾¾¾»»»¼¼¼¾¾¾±±±¸¸¸µµµ°°°ÉÉÉÔÔÔÌÌÌÐÐÐÔÔÔÕÕÕÔÔÔÒÒÒÒÒÒÒÒÒÑÑÑÌÌÌÉÉÉ¿¿¿ÆÆÆµµµ¸¸¸¾¾¾ººº¼¼¼¾¾¾¾¾¾¾¾¾¾¾¾¿¿¿ÀÀÀÇÇÇ×××ÑÑÑÍÍÍÎÎÎÍÍÍÑÑÑÐÐÐÎÎÎÐÐÐÕÕÕÕÕÕÑÑÑÒÒÒÙÙÙÛÛÛßßßßßßâââââââââàààßßßßßßãããââââââææææææããããããæææäääçççèèèçççæææçççëëëïïïëëëêêêêêêèèèäääàààâââæææëëëëëëêêêßßß¼¼¼µµµººº»»»ººº»»»´´´»»»ÀÀÀºººµµµßßßæææíííãããâââæææãããíííòòòæææïïïøøøùùùóóóîîîïïïòòòõõõóóóîîîæææÝÝÝÛÛÛßßßäääÜÜÜÝÝÝÍÍÍÉÉÉÑÑÑÑÑÑÍÍÍÇÇǸ¸¸ÅÅÅÊÊÊÑÑÑÉÉɼ¼¼ÃÃÃÅÅÅÔÔÔÔÔÔÕÕÕÕÕÕÔÔÔÔÔÔÉÉɵµµ´´´´´´ººº¼¼¼ºººÀÀÀÆÆÆÂ¬¬¬³³³¿¿¿ÆÆÆ¿¿¿³³³¯¯¯³³³³³³°°°ªªª¦¦¦ªªª´´´¸¸¸¸¸¸ÀÀÀ¼¼¼»»»¼¼¼ºººµµµ¼¼¼ÉÉÉÊÊÊÑÑÑÔÔÔÒÒÒÔÔÔÕÕÕÎÎÎÃÃÃÐÐÐÊÊÊÉÉÉÃÃÃÅÅÅÊÊÊÇÇÇÆÆÆÔÔÔÜÜÜÙÙÙÌÌÌÆÆÆÉÉÉÀÀÀ°°°³³³¨¨¨¦¦¦¸¸¸ÎÎÎÙÙÙÜÜÜÜÜÜÛÛÛÝÝÝâââããããããæææèèèèèèõõõïïïëëëëëëïïïññññññïïïãããÝÝÝÙÙÙÙÙÙØØØ××××××ØØØæææàààÛÛÛÛÛÛàààæææêêêêêêäääçççßßßÙÙÙÜÜÜ···¸¸¸ÀÀÀ¿¿¿ÀÀÀ¼¼¼¸¸¸¸¸¸¾¾¾¾¾¾»»»¼¼¼¾¾¾´´´¸¸¸···µµµÌÌÌØØØÐÐÐÒÒÒ×××ØØØ×××ÕÕÕÕÕÕÕÕÕÑÑÑÎÎÎÌÌ̾¾¾Â´´´···¼¼¼¼¼¼¾¾¾¾¾¾¼¼¼»»»¼¼¼¾¾¾ÀÀÀÀÀÀÔÔÔÔÔÔÊÊÊÉÉÉÊÊÊÊÊÊÊÊÊÉÉÉÍÍÍÑÑÑÒÒÒÑÑÑÔÔÔÛÛÛßßßßßßßßßààààààßßßßßßÝÝÝÜÜÜÜÜÜÙÙÙÜÜÜàààâââßßßßßßâââÜÜÜâââèèèííííííëëëëëëëëëãããæææêêêëëëèèèæææäääæææïïïëëëîîîÝÝݸ¸¸µµµÂººº¾¾¾ÃÃõµµµµµÝÝÝëëëñññäääãããèèèçççîîîòòòíííòòòõõõòòòíííêêêîîîóóóóóóóóóñññèèèàààÜÜÜßßßãããßßßÜÜÜÕÕÕÒÒÒÐÐÐÐÐÐÐÐÐÌÌÌ»»»¾¾¾ºººÃÃÃÉÉÉ¿¿¿³³³ÌÌÌÑÑÑÔÔÔÔÔÔÒÒÒÔÔÔÎÎÎÅÅŵµµµµµ¼¼¼¿¿¿»»»¿¿¿ÅÅÅ´´´°°°···ÂÂÂÀÀÀ´´´±±±ººº´´´°°°ªªª¬¬¬±±±¸¸¸»»»ººº°°°­­­­­­°°°¯¯¯°°°ºººÆÆÆÉÉÉÍÍÍÑÑÑÑÑÑÒÒÒÔÔÔÎÎÎÆÆÆØØØÎÎÎÎÎÎÃÃü¼¼¿¿¿¼¼¼ÇÇÇÜÜÜØØØÉÉÉ···±±±µµµ°°°¤¤¤­­­´´´³³³¯¯¯···ÌÌÌÙÙÙÛÛÛÝÝÝßßßÜÜÜÛÛÛÝÝÝãããäääãããëëëííííííîîîîîîîîîííííííëëëäääÛÛÛ×××ÔÔÔÒÒÒÑÑÑÑÑÑäääßßßÛÛÛÛÛÛàààæææççççççããããããæææàààÜÜܺºº¸¸¸¿¿¿ÅÅÅÃÃÿ¿¿»»»¼¼¼ÀÀÀÀÀÀ¼¼¼»»»¼¼¼¸¸¸ºººººº»»»ÍÍÍØØØÔÔÔ×××ÙÙÙÙÙÙØØØ××××××ØØØÔÔÔÑÑÑÍÍ;¾¾ÃÃõµµ¸¸¸¾¾¾¾¾¾¿¿¿¾¾¾¼¼¼»»»»»»¾¾¾ÀÀÀÆÆÆØØØÜÜÜÑÑÑÐÐÐÒÒÒÐÐÐÑÑÑÜÜÜßßßßßßÜÜÜÙÙÙØØØÛÛÛßßßßßßßßßßßßÝÝÝÜÜÜÛÛÛÛÛÛÙÙÙØØØ×××ØØØÜÜÜÝÝÝÛÛÛÛÛÛÝÝÝÙÙÙßßßæææëëëííííííëëëëëëäääçççêêêèèèçççæææææææææóóóëëëïïïâââÅÅž¾¾ÉÉÉÅÅÅÃÃÃÃÃþ¾¾ÂÂÂÆÆÆµµµÀÀÀàààæææëëëÝÝÝÝÝÝãããâââçççêêêïïïïïïñññïïïîîîîîîïïïòòòïïïòòòòòòîîîæææßßßÜÜÜÜÜÜßßßÜÜÜßßßÛÛÛÑÑÑÎÎÎÐÐÐÑÑÑÍÍÍÆÆÆ···¼¼¼ÇÇÇÇÇÇÆÆÆ¸¸¸ºººÆÆÆÑÑÑÔÔÔÕÕÕÔÔÔÐÐÐÎÎα±±³³³¼¼¼ÃÃÿ¿¿¾¾¾ÀÀÀ¾¾¾¿¿¿±±±­­­¸¸¸¿¿¿ººº¸¸¸¿¿¿¿¿¿¸¸¸±±±°°°°°°°°°­­­ªªª¯¯¯¯¯¯°°°³³³´´´µµµ¾¾¾ÆÆÆÃÃÃÇÇÇÊÊÊÍÍÍÐÐÐÑÑÑÎÎÎÉÉÉÀÀÀ»»»ÉÉÉÊÊÊÅÅÅÀÀÀ¿¿¿ÑÑÑÔÔÔÉÉÉ»»»µµµµµµ···¸¸¸¸¸¸µµµÀÀÀÀÀÀ±±±­­­»»»ÇÇÇÊÊÊÍÍÍÙÙÙââââââßßßãããçççèèèèèèíííîîîëëëçççæææêêêîîîïïïëëëäääßßßÝÝÝÜÜÜØØØÕÕÕàààÜÜÜÛÛÛÜÜÜàààäääãããâââãããÒÒÒÔÔÔÎÎÎÉÉÉ···ÃÃÃÊÊÊÉÉÉÇÇÇÃÃÿ¿¿ÂÂÂÆÆÆÃÃÿ¿¿¼¼¼¼¼¼»»»»»»¼¼¼ÂÂÂÎÎÎ××××××ÙÙÙÛÛÛÛÛÛÙÙÙØØØÙÙÙÙÙÙÙÙÙÒÒÒÎÎÎÂÂÂÇÇǸ¸¸»»»Â¿¿¿¿¿¿¿¿¿¾¾¾¼¼¼¼¼¼¿¿¿Â»»»ÉÉÉÒÒÒÐÐÐÕÕÕÝÝÝÛÛÛàààßßßâââßßßÜÜÜÝÝÝÛÛÛÙÙÙÝÝÝßßßÝÝÝÝÝÝÜÜÜÙÙÙØØØØØØ×××ÙÙÙØØØÙÙÙÝÝÝßßßÜÜÜÜÜÜßßßßßßàààãããæææçççêêêíííîîîîîîîîîêêêääääääçççèèèçççõõõëëëñññçççÕÕÕÅÅÅÊÊÊÆÆÆÀÀÀ¿¿¿ÀÀÀÃÃÃÅÅŸ¸¸ÑÑÑäääâââèèèÜÜÜÝÝÝãããàààäääçççääääääçççêêêíííëëëèèèæææíííïïïòòòòòòíííäääÜÜÜØØØÜÜÜÛÛÛãããßßß×××ÑÑÑÎÎÎÔÔÔÔÔÔÑÑÑÀÀÀ¼¼¼¾¾¾ÀÀÀÉÉÉÅÅÅ­­­¼¼¼ÊÊÊÒÒÒØØØÕÕÕÎÎÎÎÎΰ°°¯¯¯ºººÃÃÃÀÀÀÀÀÀ¾¾¾ÅÅÅ´´´ªªª¯¯¯»»»¿¿¿¿¿¿¿¿¿»»»···´´´¸¸¸»»»»»»ººº»»»¿¿¿¿¿¿ÀÀÀÂÂÂÃÃÃÅÅÅÇÇÇÊÊÊÂÂÂÃÃÃÆÆÆÊÊÊÍÍÍÐÐÐÎÎÎÊÊÊ¿¿¿¾¾¾ÆÆÆÉÉÉÃÃþ¾¾¿¿¿ÍÍÍÀÀÀººº···¼¼¼¿¿¿¼¼¼¾¾¾ÃÃÃÀÀÀÀÀÀÀÀÀ¼¼¼µµµ³³³³³³´´´±±±ÀÀÀÎÎÎ×××ÝÝÝäääâââÛÛÛÜÜÜäääíííîîîêêêääääääæææêêêíííïïïîîîîîîëëëæææßßßÝÝÝÜÜÜÛÛÛÜÜÜàààãããâââßßßààà»»»ºººººº»»»ºººÐÐÐÐÐÐÌÌÌÊÊÊÇÇÇÃÃÃÆÆÆÉÉÉÆÆÆ¿¿¿¿¿¿¾¾¾»»»ººº¾¾¾ÇÇÇÐÐÐ×××ÙÙÙÛÛÛÜÜÜÜÜÜÛÛÛÙÙÙÙÙÙÛÛÛÜÜÜÐÐÐÉÉÉÂÂÂÊÊʸ¸¸ºººÃÃþ¾¾¿¿¿ÀÀÀ¿¿¿¾¾¾¿¿¿ÀÀÀÃÃÃÆÆÆÇÇÇÌÌÌÅÅÅÇÇÇÇÇǺºº¿¿¿¾¾¾ÃÃÃÃÃÃÇÇÇÔÔÔØØØÙÙÙàààßßßÝÝÝÜÜÜÙÙÙØØØ×××ÕÕÕÕÕÕÛÛÛÙÙÙÛÛÛàààâââßßßàààãããäääääääääæææçççèèèêêêêêêäääæææäääæææíííõõõöööóóóòòòêêêòòòëëëàààÃÃÃÂÂÂÅÅÅÀÀÀ¼¼¼ÅÅÅÅÅÅ¿¿¿¸¸¸ÛÛÛàààèèèñññçççèèèîîîêêêîîîñññâââãããæææèèèèèèèèèæææäääëëëîîîòòòóóóòòòëëëâââÙÙÙÛÛÛ×××ÝÝÝÜÜÜÜÜÜØØØÊÊÊÑÑÑÐÐÐÔÔÔÉÉɾ¾¾······ÆÆÆÇÇÇ···¼¼¼¾¾¾ÆÆÆÔÔÔÕÕÕÍÍÍÍÍ͸¸¸³³³¸¸¸ÀÀÀ¿¿¿¿¿¿ÀÀÀ¿¿¿¿¿¿¸¸¸°°°­­­···ÃÃÃÃÃü¼¼ÅÅÅÀÀÀÀÀÀÃÃÃÃÃÃÀÀÀ¿¿¿ÀÀÀ¾¾¾¼¼¼¼¼¼¾¾¾ÀÀÀÂÂÂÃÃÃÂÂÂÃÃÃÃÃÃÅÅÅÉÉÉÍÍÍÎÎÎÍÍÍÌÌÌ¿¿¿ÃÃÃÀÀÀÀÀÀÂÂÂÇÇÇÌÌÌÆÆÆ³³³µµµ»»»ÀÀÀ¿¿¿¼¼¼¼¼¼¾¾¾Â¿¿¿¿¿¿ÀÀÀ¾¾¾µµµ°°°­­­°°°³³³±±±µµµÃÃÃÒÒÒÑÑÑÆÆÆÃÃÃÍÍÍÛÛÛæææëëëêêêãããßßßÝÝÝæææëëëëëëêêêèèèãããÝÝÝàààÝÝÝÛÛÛÜÜÜàààããããããàààâââ³³³¸¸¸ÀÀÀÃÃÃÅÅÅÑÑÑÂÂÂÌÌÌÌÌÌÉÉÉÆÆÆÇÇÇÌÌÌÆÆÆ¿¿¿ÃÃþ¾¾»»»¸¸¸¾¾¾ÉÉÉÐÐÐ×××ÛÛÛÜÜÜÝÝÝÜÜÜÛÛÛÙÙÙÙÙÙÛÛÛÙÙÙÊÊÊÃÃþ¾¾ÇÇÇ´´´µµµÀÀÀ¾¾¾¿¿¿ÀÀÀÀÀÀ¿¿¿ÀÀÀÂÂÂÃÃÃÆÆÆÃÃÃÇÇÇÅÅÅÍÍÍÐÐÐÂÂÂÉÉÉÃÃÃÇÇÇÃÃÃÇÇÇÔÔÔÙÙÙ×××ÜÜÜßßßÝÝÝÛÛÛÙÙÙ×××ÕÕÕÕÕÕÔÔÔÙÙÙØØØÙÙÙàààâââàààâââææææææçççêêêëëëëëëêêêæææãããâââæææêêêîîîöööüüüöööíííïïïêêêòòòíííäää¿¿¿»»»ÃÃÃÃÃÿ¿¿ÉÉÉÆÆÆººº´´´ÜÜÜØØØßßßèèèâââãããçççãããçççêêêîîîññññññïïïííííííñññõõõêêêíííñññõõõöööñññæææßßßÛÛÛÔÔÔØØØØØØàààÜÜÜÇÇÇÌÌÌÑÑÑØØØÎÎÎÃÃúºº¸¸¸ÆÆÆÇÇÇÉÉÉ´´´¸¸¸ÌÌÌÔÔÔÎÎÎÎÎÎÅÅźººººº¿¿¿¼¼¼¼¼¼¿¿¿¾¾¾¸¸¸»»»···°°°µµµÅÅÅÅÅźºº¿¿¿¾¾¾¿¿¿ÃÃÃÃÃÃÀÀÀ¿¿¿ÃÃúºº¸¸¸¸¸¸»»»¿¿¿ÃÃÃÃÃÃÂÂÂÆÆÆÅÅÅÆÆÆÊÊÊÍÍÍÍÍÍÌÌÌÊÊÊÃÃÃÑÑÑÇÇÇÅÅÅÉÉÉÍÍÍÇÇÇ©©©­­­ºººÂÂÂÀÀÀ¿¿¿ÀÀÀÂÂÂÀÀÀ¿¿¿ÃÃÃÃÃÿ¿¿¼¼¼¼¼¼ºººµµµ­­­´´´µµµ³³³µµµ¿¿¿¾¾¾´´´µµµ¸¸¸ÂÂÂÑÑÑâââêêêèèèããããããêêêîîîêêêççççççæææâââäääàààÜÜÜÜÜÜàààääääääãããÔÔÔÅÅźºº¼¼¼ÅÅÅÉÉÉÉÉÉÉÉÉÍÍÍÊÊÊÇÇÇÇÇÇÉÉÉÉÉÉÇÇÇÆÆÆÃÃÃÆÆÆÀÀÀÃÃÃÀÀÀ¾¾¾ÐÐÐÙÙÙàààÝÝÝØØØÑÑÑÐÐÐÔÔÔÙÙÙÜÜÜÕÕÕÐÐп¿¿¿¿¿ÊÊÊ»»»¯¯¯¾¾¾»»»ÀÀÀ¾¾¾¾¾¾ÃÃÃÇÇÇÆÆÆÊÊÊÉÉÉÉÉÉÊÊÊÍÍÍÍÍÍÌÌÌÉÉÉÇÇÇÇÇÇÇÇÇÂÂÂÙÙÙØØØÙÙÙØØØÝÝÝàààßßßØØØÔÔÔÕÕÕ×××ÔÔÔÛÛÛÜÜÜÜÜÜÝÝÝàààäääçççèèèëëëèèèâââäääîîîèèèãããêêêñññõõõöööõõõõõõøøøøøøóóóøøøúúúøøøàà྾¾ÅÅÅ¿¿¿Â¿¿¿ÅÅÅÊÊʼ¼¼­­­···ÎÎÎÙÙÙçççÛÛÛÙÙÙÍÍÍÀÀÀØØØÛÛÛèèèççççççèèèææææææëëëóóóñññíííñññïïïêêêñññòòòæææÜÜÜØØØ×××ÕÕÕÛÛÛßßßÕÕÕÌÌÌÌÌÌÕÕÕÑÑÑÐÐп¿¿ÍÍÍÐÐÐÉÉÉÊÊÊÂÂÂÂÂÂÌÌÌÒÒÒÐÐÐÎÎÎÐÐÐÌÌÌÑÑÑÊÊÊ»»»µµµ¼¼¼Â¿¿¿¼¼¼ÃÃúºº¯¯¯ºººÆÆÆÃÃÿ¿¿ÀÀÀÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÀÀÀÀÀÀ¾¾¾¸¸¸···¼¼¼¿¿¿¾¾¾¾¾¾ÀÀÀÃÃÃÃÃÃÆÆÆÉÉÉÆÆÆÃÃÃÉÉÉÔÔÔÐÐÐÊÊÊÉÉÉÔÔÔÎÎÎÐÐкºº´´´···¸¸¸¾¾¾ÆÆÆÉÉÉÆÆÆÅÅÅÆÆÆÇÇÇÆÆÆÃÃÃÂÂÂÀÀÀ¿¿¿¿¿¿¾¾¾¼¼¼»»»»»»¾¾¾ÂÂÂÃÃÃÃÃÃÂÂÂÀÀÀºººµµµ»»»ÉÉÉÛÛÛæææëëëæææãããäääïïïëëëçççíííàààÛÛÛßßßàààÔÔÔßßßÛÛÛàààãããÃÃÿ¿¿ÀÀÀÇÇÇÊÊÊÉÉÉÇÇÇÉÉÉÐÐÐÍÍÍÌÌÌÌÌÌÍÍÍÍÍÍÌÌÌÉÉÉÇÇÇÉÉÉÀÀÀÃÃÃÀÀÀ¿¿¿ÑÑÑÜÜÜâââßßßØØØÒÒÒÐÐÐÑÑÑÕÕÕ×××ÙÙÙÕÕÕÆÆÆÀÀÀÃÃû»»´´´¼¼¼ººº¿¿¿ÀÀÀ¾¾¾¼¼¼ÀÀÀÂÂÂÂÂÂÊÊÊÊÊÊÊÊÊÊÊÊÌÌÌÌÌÌÊÊÊÉÉÉÉÉÉÅÅÅÇÇÇÇÇÇÛÛÛÒÒÒ×××ÜÜÜÛÛÛÝÝÝÝÝÝÙÙÙ×××ØØØÙÙÙØØØØØØØØØÛÛÛßßßæææèèèèèèæææäääíííîîîîîîïïïíííîîîúúúäääëëëïïïïïïïïïñññïïïëëëêêêïïïíííÛÛÛÇÇÇÅÅÅÇÇÇÃÃþ¾¾»»»ÀÀÀÇÇÇÀÀÀ³³³´´´¿¿¿···Â¸¸¸¾¾¾»»»³³³ÀÀÀ»»»ÙÙÙÜÜÜàààãããàààÝÝÝäääîîîõõõõõõöööóóóïïïòòòòòòëëëçççäääÝÝÝ××××××ÛÛÛ×××ÑÑÑÍÍÍÒÒÒÑÑÑÑÑÑ»»»ÂÂÂÆÆÆÊÊÊÍÍ;¾¾ºººÌÌÌ×××ÑÑÑÍÍÍÑÑÑÎÎÎÒÒÒÐÐÐÀÀÀ´´´´´´»»»¿¿¿¿¿¿Â¸¸¸³³³¾¾¾ÆÆÆÃÃÃÂÂÂÀÀÀÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÀÀÀÀÀÀ¾¾¾ººº¸¸¸¼¼¼¾¾¾¾¾¾ÀÀÀÅÅÅ»»»»»»¼¼¼¿¿¿¾¾¾¿¿¿ÅÅÅÌÌÌÐÐÐÆÆÆÊÊÊÒÒÒÐÐÐÑÑѱ±±­­­»»»ººº¾¾¾ÅÅÅÇÇÇÅÅÅÅÅÅÇÇÇÀÀÀÃÃÃÇÇÇÇÇÇÃÃü¼¼»»»¾¾¾¾¾¾ÃÃÃÇÇÇÊÊÊÉÉÉÆÆÆÅÅÅÅÅÅÀÀÀ¾¾¾ººº¸¸¸»»»ÆÆÆÒÒÒÜÜÜäääçççæææîîîîîîëëëíííßßßßßßÜÜÜßßßÝÝÝòòòèèèâââÛÛÛ···¾¾¾ÇÇÇÎÎÎÎÎÎÊÊÊÌÌÌÐÐÐÒÒÒÑÑÑÐÐÐÑÑÑÑÑÑÑÑÑÐÐÐÎÎÎÌÌÌÌÌÌÂÂÂÃÃÃÀÀÀ¿¿¿ÑÑÑÜÜÜâââÝÝÝØØØÕÕÕÒÒÒÐÐÐÐÐÐÑÑÑÙÙÙÙÙÙÑÑÑÆÆÆ¿¿¿¾¾¾ººº´´´¾¾¾¿¿¿¾¾¾¸¸¸¸¸¸¾¾¾ÃÃÃÆÆÆÉÉÉÊÊÊÌÌÌÍÍÍÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÃÃÃÇÇÇÌÌÌÜÜÜÐÐÐÕÕÕÜÜÜÙÙÙÜÜÜÝÝÝÙÙÙØØØÙÙÙÛÛÛÛÛÛ×××ØØØÜÜÜâââäääèèèëëëïïïòòòöööóóóõõõüüüüüüõõõòòòêêêïïïïïïëëëæææææææææãããêêêêêêÜÜÜÇÇÇ¿¿¿ÃÃÃÆÆÆÉÉÉÇÇÇÅÅÅÅÅÅÇÇÇÆÆÆÀÀÀ¼¼¼¾¾¾µµµ¼¼¼´´´ÀÀÀÆÆÆ¿¿¿Â´´´···¼¼¼ÉÉÉ×××ÝÝÝàààæææíííëëëòòòóóóïïïïïïïïïïïïòòòèèèæææÝÝÝ××××××ÜÜÜâââàààÎÎÎÑÑÑÒÒÒÔÔÔ»»»¿¿¿ÃÃÃÎÎÎÍÍͺºº···ÍÍÍÛÛÛÔÔÔÎÎÎÒÒÒÍÍÍÒÒÒÑÑÑÃÃô´´°°°¸¸¸Â¿¿¿······ÂÂÂÆÆÆÃÃÃÃÃÃÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÀÀÀ¿¿¿»»»¸¸¸¸¸¸»»»¾¾¾ÀÀÀÆÆÆÍÍÍÑÑÑÑÑÑÍÍÍÆÆÆÃÃÃÆÆÆÇÇÇÆÆÆÇÇÇÀÀÀÌÌÌÒÒÒÒÒÒÒÒÒ±±±±±±¾¾¾»»»¾¾¾ÂÂÂÅÅÅÅÅÅÆÆÆÊÊÊÌÌÌÇÇÇÇÇÇÌÌÌÊÊÊÃÃÃÀÀÀÃÃÿ¿¿ÂÂÂÅÅÅÆÆÆÇÇÇÆÆÆÃÃÃÂÂÂÉÉÉÉÉÉÇÇÇÃÃþ¾¾ººº¸¸¸¸¸¸ØØØçççããããããæææãããäääÝÝÝòòòèèèæææâââëëëÑÑÑÀÀÀ···¾¾¾ÃÃÃÊÊÊÎÎÎÎÎÎÎÎÎÒÒÒ×××ÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÒÒÒÒÒÒÌÌÌÌÌÌÃÃÃÅÅÅ¿¿¿ÎÎÎ×××ÝÝÝØØØÕÕÕÕÕÕÔÔÔÐÐÐÎÎÎÎÎÎÑÑÑ×××ÙÙÙÌÌ̾¾¾ÀÀÀ¾¾¾¯¯¯···ºººººººººººº¾¾¾ÃÃÃÇÇÇÇÇÇÊÊÊÎÎÎÐÐÐÎÎÎÎÎÎÐÐÐÒÒÒÑÑÑÇÇÇÊÊÊÊÊÊÙÙÙÒÒÒ×××ÕÕÕÛÛÛÜÜÜÜÜÜÙÙÙØØØØØØÙÙÙÛÛÛÙÙÙÜÜÜàààããããããæææòòòÿÿÿúúúÿÿÿüüüööööööùùùøøøóóóóóóñññæææÔÔÔÆÆÆÂÂÂÀÀÀ¿¿¿ÜÜÜÜÜÜÉÉɸ¸¸¾¾¾ÅÅÅÉÉÉÐÐÐÑÑÑÎÎÎÉÉÉÆÆÆÆÆÆÆÆÆÆÆÆÃÃÃÅÅÅÇÇÇ¿¿¿ÉÉÉÐÐÐÉÉÉÇÇǺºº···´´´µµµÀÀÀÍÍÍÕÕÕÝÝÝãããîîîùùùøøøññññññëëëèèèñññòòòïïïàààØØØ×××ØØØÜÜÜÕÕÕÍÍÍÑÑÑ×××ÕÕÕÀÀÀÌÌÌÊÊÊÑÑÑÅÅż¼¼¿¿¿ÐÐÐÛÛÛ×××ÑÑÑÒÒÒÊÊÊÑÑÑÍÍͼ¼¼±±±µµµ¿¿¿ÅÅźºº´´´ºººÂÂÂÃÃÃÂÂÂÃÃÃÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÀÀÀ¿¿¿¿¿¿µµµµµµ···ººº¼¼¼ÃÃÃÍÍÍÔÔÔÍÍÍÍÍÍÉÉÉÂÂÂÃÃÃÉÉÉÊÊÊÆÆÆÆÆÆÊÊÊÑÑÑØØØÕÕÕÆÆÆ´´´···¿¿¿»»»»»»ÀÀÀÃÃÃÅÅÅÉÉÉÎÎÎÆÆÆ¸¸¸°°°ºººÅÅÅÇÇÇÆÆÆÆÆÆÎÎÎÎÎÎÎÎÎÍÍÍÌÌÌÊÊÊÊÊÊÊÊÊÇÇÇÅÅÅÅÅÅÇÇÇÌÌÌÇÇÇ¿¿¿······àààïïïîîîêêêæææïïïöööîîîçççèèèâââßßß¾¾¾···¿¿¿ÉÉÉÊÊÊÌÌÌÎÎÎÑÑÑÕÕÕ×××ØØØÔÔÔÔÔÔÕÕÕÕÕÕÕÕÕÔÔÔÕÕÕÕÕÕÉÉÉÊÊÊÃÃÃÆÆÆÃÃÿ¿¿ÊÊÊÎÎÎÕÕÕÑÑÑÐÐÐÕÕÕ×××ÒÒÒÎÎÎÐÐÐÎÎÎÒÒÒÙÙÙÍÍÍ»»»¿¿¿Â³³³©©©­­­´´´ººº¼¼¼¼¼¼¾¾¾¿¿¿ÅÅÅÉÉÉÍÍÍÎÎÎÐÐÐÑÑÑÔÔÔ×××ÕÕÕÍÍÍÎÎÎÆÆÆÕÕÕØØØÛÛÛÎÎÎØØØØØØÙÙÙÙÙÙØØØØØØÛÛÛÝÝÝâââÝÝÝàààçççëëëïïïøøøÿÿÿüüüúúúõõõïïïòòòøøøöööíííçççæææÜÜÜÎÎÎÆÆÆÅÅÅÆÆÆÆÆÆÀÀÀÅÅż¼¼ºººÇÇÇÐÐÐÐÐÐÔÔÔÐÐÐÐÐÐÍÍÍÇÇÇÅÅÅÆÆÆÆÆÆÆÆÆÊÊÊÌÌÌÅÅÅÉÉÉÉÉÉÆÆÆÆÆÆÀÀÀÃÃû»»´´´±±±´´´¿¿¿ÑÑÑâââæææïïïïïïíííïïïêêêçççïïïóóóñññÝÝÝÙÙÙÛÛÛØØØØØØÉÉÉÍÍÍÒÒÒØØØÑÑÑÂÂÂ×××ÎÎÎÉÉɾ¾¾ÆÆÆÎÎÎÕÕÕÙÙÙÙÙÙÕÕÕÑÑÑÎÎÎÑÑÑÆÆÆ³³³°°°¾¾¾ÅÅÅ¿¿¿Â´´´°°°ºººÀÀÀÂÂÂÀÀÀÀÀÀÀÀÀÂÂÂÂÂÂÀÀÀÀÀÀ¿¿¿¾¾¾¼¼¼···¸¸¸ºººººº»»»ÂÂÂÊÊÊÐÐÐÉÉÉÊÊÊÅÅÅ¿¿¿ÀÀÀÇÇÇÇÇÇÂÂÂÎÎÎâââÛÛÛâââÕÕÕ°°°³³³µµµ¼¼¼ºººººº¿¿¿ÂÂÂÅÅÅÊÊÊÑÑÑÀÀÀµµµ°°°»»»ÌÌÌÔÔÔÕÕÕÕÕÕÎÎÎÑÑÑÑÑÑÐÐÐÍÍÍÌÌÌÍÍÍÎÎÎÐÐÐÊÊÊÅÅÅÅÅÅÊÊÊÍÍÍÊÊÊÇÇǺººØØØßßßãããêêêçççæææàààçççãããçççßßß×××´´´µµµÆÆÆÍÍÍÎÎÎÐÐÐÑÑÑÕÕÕÙÙÙØØØÔÔÔÔÔÔÕÕÕÕÕÕÔÔÔÔÔÔÔÔÔ×××ØØØÉÉÉÊÊÊÃÃÃÇÇÇÅÅÅ¿¿¿ÇÇÇÊÊÊÐÐÐÉÉÉÊÊÊÔÔÔØØØÔÔÔÐÐÐÒÒÒÐÐÐÒÒÒÕÕÕÌÌ̺ºººººÂ¿¿¿¬¬¬ªªª¬¬¬¯¯¯°°°³³³ºººÀÀÀ¿¿¿ÂÂÂÆÆÆÉÉÉÌÌÌÎÎÎÐÐÐÑÑÑÔÔÔÐÐÐÒÒÒÅÅÅÐÐÐ×××ßßßÐÐÐ××××××ØØØÛÛÛÛÛÛÛÛÛßßßãããäääÝÝÝßßßîîîúúúüüüöööõõõöööòòòòòòööööööñññàààÊÊÊÀÀÀÅÅÅÅÅÅÃÃÃÆÆÆÌÌÌÎÎÎÌÌÌÀÀÀ¾¾¾¾¾¾ÉÉÉÐÐÐÒÒÒÕÕÕÐÐÐÔÔÔ×××ÔÔÔÐÐÐÍÍÍÌÌÌÊÊÊÉÉÉÉÉÉÆÆÆÅÅÅÃÃÃÂÂÂÆÆÆÇÇÇ¿¿¿ÀÀÀ¾¾¾´´´³³³ÃÃÃÕÕÕâââæææèèèîîîòòòîîîëëëïïïíííîîîÛÛÛÜÜÜßßßÛÛÛÝÝÝÌÌÌÎÎÎÔÔÔÙÙÙÌÌ̼¼¼ØØØÉÉÉ¿¿¿ÂÂÂÑÑÑÜÜÜÙÙÙØØØÛÛÛÙÙÙÑÑÑÕÕÕÑÑÑÀÀÀ°°°³³³ÀÀÀÃÃû»»Â³³³¯¯¯···¾¾¾ÂÂÂÃÃÿ¿¿ÀÀÀÀÀÀÀÀÀ¿¿¿¿¿¿¼¼¼»»»»»»»»»¾¾¾¼¼¼ººº»»»¿¿¿ÂÂÂÂÂÂÕÕÕÒÒÒÎÎÎÉÉÉÉÉÉÊÊÊÇÇÇÃÃÃÍÍÍçççÛÛÛâââ×××¥¥¥µµµººº»»»¸¸¸ººº¿¿¿ÃÃÃÅÅÅÉÉÉÐÐШ¨¨ªªª°°°´´´¸¸¸¼¼¼¾¾¾¾¾¾ÀÀÀ»»»ºººÃÃÃÒÒÒÙÙÙÕÕÕÍÍÍÒÒÒÒÒÒÐÐÐÌÌÌÇÇÇÅÅÅÆÆÆÇÇÇ»»»¾¾¾³³³»»»ÑÑÑâââêêêãããäääàààæææààààààÂÂÂÀÀÀÍÍÍÍÍÍÑÑÑÒÒÒÑÑÑÒÒÒØØØØØØÕÕÕ×××××××××ÕÕÕÔÔÔÕÕÕÙÙÙÜÜÜÍÍÍÌÌÌÅÅÅÇÇÇÆÆÆ¿¿¿ÇÇÇÊÊÊÌÌÌÅÅÅÆÆÆÑÑÑØØØÔÔÔÑÑÑÔÔÔÑÑÑÑÑÑ×××ÒÒÒÃÃø¸¸¼¼¼ÅÅÅ»»»µµµ°°°¯¯¯­­­¯¯¯···ÀÀÀºººººº¼¼¼¿¿¿ÃÃÃÅÅÅÅÅÅÅÅÅÐÐÐÍÍÍÕÕÕÉÉÉÌÌÌÐÐÐâââÝÝÝßßßÜÜÜÝÝÝàààßßßÜÜÜÝÝÝãããâââÝÝÝäääóóóÿÿÿøøøòòòóóóïïïóóóÿÿÿüüüäääÑÑÑÉÉÉÂÂÂÎÎÎÐÐÐÐÐÐÎÎÎÑÑÑÕÕÕÒÒÒÌÌÌÔÔÔÍÍÍÉÉÉÆÆÆÅÅÅÊÊÊÒÒÒÔÔÔÙÙÙØØØÙÙÙÛÛÛÛÛÛ×××ÒÒÒÒÒÒÇÇÇÆÆÆÆÆÆÃÃÃÂÂÂÃÃÃÅÅÅÇÇÇÅÅÅÊÊÊÎÎÎÎÎεµµ´´´»»»äääàààæææñññóóóñññíííçççòòòøøøäääâââÝÝÝÕÕÕßßßÑÑÑÒÒÒÒÒÒÛÛÛÌÌÌ»»»ÔÔÔÇÇÇÆÆÆÒÒÒÛÛÛßßßÜÜÜÛÛÛÜÜÜÙÙÙÔÔÔÕÕÕÉÉÉ»»»···ººº¾¾¾¿¿¿¿¿¿ÃÃô´´°°°µµµ¼¼¼ÅÅÅÇÇÇ¿¿¿¿¿¿¿¿¿¿¿¿¾¾¾¼¼¼»»»ººº¸¸¸ººº¼¼¼¼¼¼»»»»»»¿¿¿¾¾¾¸¸¸ÍÍÍÊÊÊÉÉÉÌÌÌÌÌÌÉÉÉÉÉÉÉÉÉÅÅÅÜÜÜÒÒÒÙÙÙ××צ¦¦···¾¾¾»»»¸¸¸»»»ÀÀÀÃÃÃÃÃÃÅÅÅÉÉɬ¬¬···¿¿¿¼¼¼¾¾¾ÂÂÂÅÅÅÃÃÃÃÃúºº³³³¼¼¼ÐÐÐÜÜÜÜÜÜÕÕÕÎÎÎÐÐÐÑÑÑÑÑÑÍÍÍÊÊÊÉÉÉÉÉÉÆÆÆÇÇǾ¾¾¼¼¼ºººÂÂÂÛÛÛâââêêêääääääÜÜÜßßßÆÆÆÃÃÃÊÊÊÍÍÍÒÒÒÔÔÔÎÎÎÌÌÌÒÒÒÙÙÙÛÛÛÙÙÙÙÙÙØØØÕÕÕÔÔÔÕÕÕÛÛÛßßßÑÑÑÎÎÎÆÆÆÇÇÇÆÆÆÀÀÀÉÉÉÌÌÌÌÌÌÃÃÃÅÅÅÑÑÑØØØÔÔÔÑÑÑÔÔÔÍÍÍÑÑÑÙÙÙÝÝÝÐÐкºº···ÃÃþ¾¾¼¼¼¾¾¾ÀÀÀ¼¼¼´´´³³³µµµµµµ´´´´´´···»»»¼¼¼»»»ºººÊÊÊÉÉÉ×××ÎÎÎÊÊÊÉÉÉâââëëëèèèæææääääääàààÛÛÛÛÛÛßßßÝÝÝàààíííöööóóóëëëïïïúúúÿÿÿóóóïïïäääÍÍÍÂÂÂÌÌÌÒÒÒÔÔÔÑÑÑÎÎÎÌÌÌÑÑÑØØØ×××ÑÑÑÔÔÔÎÎÎÒÒÒÔÔÔÌÌÌÎÎÎÔÔÔÑÑÑßßßÕÕÕÐÐÐÔÔÔ×××ÕÕÕÔÔÔÔÔÔÕÕÕÒÒÒÒÒÒÐÐÐÐÐÐÑÑÑÌÌÌÌÌÌÊÊÊÅÅÅÃÃÃÇÇÇÊÊÊÆÆÆÀÀÀ¿¿¿ººº³³³ÀÀÀØØØäääëëëíííæææëëëöööæææãããÜÜÜ×××êêêæææÔÔÔÑÑÑÜÜÜÐÐм¼¼ÔÔÔÌÌÌ×××âââßßßÜÜÜÝÝÝÝÝÝÜÜÜÙÙÙ×××ÑÑÑ¿¿¿···¾¾¾ÀÀÀ»»»¾¾¾ÇÇÇÅÅŵµµ±±±µµµ»»»ÆÆÆÊÊÊÀÀÀ¾¾¾¾¾¾¾¾¾¾¾¾¼¼¼ººº¸¸¸···´´´¸¸¸ºººººº¾¾¾Â¾¾¾···ÔÔÔÎÎÎÍÍÍÐÐÐÌÌÌÃÃÃÀÀÀÃÃÃÅÅÅÕÕÕÎÎÎÒÒÒÕÕÕ¨¨¨¯¯¯µµµ»»»ººº¼¼¼ÂÂÂÃÃÃÂÂÂÂÂÂÅÅű±±¼¼¼ÂÂÂÂÂÂÌÌÌÜÜÜãããÝÝÝÆÆÆÃÃþ¾¾···³³³ºººÉÉÉÕÕÕäääÛÛÛÑÑÑÌÌÌÌÌÌÌÌÌÉÉÉÆÆÆÌÌÌÆÆÆÃÃÃÇÇǾ¾¾¸¸¸ÀÀÀ···ººº¸¸¸¾¾¾»»»ÆÆÆ»»»ÃÃÃÑÑÑÒÒÒ×××ÒÒÒÒÒÒÛÛÛÙÙÙÕÕÕÙÙÙØØØßßßÒÒÒÑÑÑ××××××ÛÛÛÙÙÙÒÒÒÐÐÐÇÇÇÅÅÅÇÇÇÃÃÃÂÂÂÌÌÌÍÍÍÀÀÀÃÃÃÑÑÑÔÔÔÒÒÒÒÒÒÒÒÒÎÎÎÐÐÐÙÙÙÜÜÜÐÐÐÅÅž¾¾±±±ÅÅÅÃÃÃÂÂÂÂÂÂÀÀÀ¼¼¼´´´¯¯¯°°°³³³ÅÅÅÑÑÑÅÅźºº¸¸¸µµµÀÀÀÇÇÇÊÊÊÉÉÉÇÇÇÊÊÊÊÊÊÇÇÇÌÌÌÍÍÍèèèÜÜÜããããããÜÜÜÝÝÝÜÜÜàààíííïïïîîîöööÿÿÿöööüüüãããÉÉÉÊÊÊÔÔÔÑÑÑÒÒÒÔÔÔÑÑÑÔÔÔÎÎÎÕÕÕÙÙÙÔÔÔ×××ÔÔÔÍÍÍÐÐÐÑÑÑÐÐÐÍÍÍÍÍÍÒÒÒØØØÛÛÛØØØ××××××ÔÔÔÑÑÑ×××àààßßßÜÜÜ×××ÑÑÑÎÎÎÍÍÍÐÐÐÒÒÒÑÑÑÕÕÕÉÉÉÎÎÎÔÔÔÑÑÑÐÐл»»¿¿¿ºººÆÆÆ¿¿¿¿¿¿ÜÜÜîîîöööïïïñññóóóëëëÜÜÜàààæææßßß×××ÎÎÎÔÔÔÑÑÑÆÆÆÐÐÐÑÑÑ¿¿¿ãããàààßßßààààààßßßÛÛÛØØØÇÇÇ¿¿¿ºººººº»»»»»»¾¾¾ÂÂÂÂÂÂÃÃꪪªªª¾¾¾¿¿¿ÀÀÀÅÅÅ¿¿¿¾¾¾¼¼¼»»»ººº¸¸¸¸¸¸¸¸¸ºººººº¾¾¾ÃÃõµµ»»»···ÊÊÊÃÃÃÌÌÌÐÐÐÌÌÌÇÇÇÆÆÆÅÅÅÂÂÂÂÂÂÇÇÇÐÐÐÍÍÍÑÑÑÉÉɱ±±¯¯¯¼¼¼······ÅÅž¾¾¼¼¼ÌÌ̼¼¼±±±´´´¾¾¾ÎÎÎÑÑÑâââÙÙÙâââÝÝÝÍÍÍÆÆÆÂ¸¸¸···»»»ºººÙÙÙØØØÔÔÔÍÍÍÍÍÍÎÎÎÊÊÊÃÃÃÌÌÌÌÌÌÌÌÌÊÊÊÇÇÇÃÃÿ¿¿¼¼¼ººº»»»¼¼¼¾¾¾ÀÀÀÅÅÅÊÊÊÐÐÐÕÕÕØØØÔÔÔÔÔÔÛÛÛÛÛÛÙÙÙßßßÝÝÝëëëâââÜÜÜßßßÝÝÝÙÙÙÍÍÍÒÒÒÐÐÐÇÇÇÃÃÃÆÆÆÂÂÂÂÂÂÌÌÌÍÍÍÂÂÂÆÆÆÔÔÔÔÔÔÑÑÑÒÒÒÑÑÑÌÌÌÉÉÉÑÑÑØØØÔÔÔÑÑÑÉÉÉ»»»¼¼¼»»»»»»¾¾¾ÀÀÀÃÃÃÂÂÂÀÀÀÇÇÇÅÅÅÊÊÊÐÐÐÇÇÇÂÂÂÀÀÀºººÅÅÅÊÊÊÌÌÌÉÉÉÇÇÇÊÊÊÌÌÌÊÊÊÌÌÌÎÎÎëëëßßßæææäääÜÜÜÝÝÝãããæææîîîñññíííòòòöööñññÜÜÜÔÔÔÉÉÉÉÉÉÐÐÐÔÔÔ×××ÕÕÕÑÑÑÙÙÙÔÔÔ×××ØØØÛÛÛÝÝÝÔÔÔÕÕÕÔÔÔÑÑÑÐÐÐÑÑÑÕÕÕÛÛÛÝÝÝõõõæææØØØ××××××ÐÐÐÆÆÆ¿¿¿¿¿¿¿¿¿¾¾¾ººººººÃÃÃÕÕÕäääÒÒÒÝÝÝ×××ÔÔÔÌÌÌÇÇÇÐÐÐÍÍÍÆÆÆÅÅÅÉÉɾ¾¾¼¼¼ÊÊÊ×××íííóóóïïïùùùùùùæææÝÝÝßßßØØØçççØØØÙÙÙ×××ÊÊÊÒÒÒÜÜÜÒÒÒÛÛÛßßßßßßÛÛÛÙÙÙÜÜÜÜÜÜ××׿¿¿ººº¸¸¸»»»¼¼¼¼¼¼¿¿¿ÅÅÅÃÃÃÅÅÅ­­­¬¬¬¾¾¾¾¾¾¼¼¼¾¾¾ÂÂÂÀÀÀ¾¾¾»»»¸¸¸·········¸¸¸ººº¼¼¼ÀÀÀ···Â¼¼¼ÊÊÊÆÆÆÍÍÍÐÐÐÊÊÊÆÆÆÆÆÆÆÆÆÅÅÅÇÇÇÂÂÂÌÌÌÎÎÎÐÐÐÎÎμ¼¼´´´ººº¸¸¸ºººÂ¿¿¿ÅÅÅÌÌÌ´´´´´´´´´¸¸¸ÂÂÂÆÆÆÛÛÛÕÕÕÝÝÝâââÎÎÎÃÃÿ¿¿¿¿¿ÀÀÀ¼¼¼ÇÇÇÑÑÑÕÕÕÑÑÑÊÊÊÉÉÉÊÊÊÉÉÉÉÉÉÊÊÊÌÌÌÌÌÌÊÊÊÆÆÆÂ¿¿¿ÂÂÂÂÂÂÂÂÂÃÃÃÇÇÇÌÌÌÑÑÑÔÔÔÕÕÕÛÛÛÛÛÛÛÛÛÝÝÝÜÜÜØØØÙÙÙÔÔÔàààÐÐÐÅÅÅÌÌÌ×××ÙÙÙÎÎÎÔÔÔÐÐÐÆÆÆÂÂÂÃÃÃÀÀÀÀÀÀÊÊÊÊÊÊÃÃÃÊÊÊÕÕÕÔÔÔÐÐÐÐÐÐÎÎÎÌÌÌÇÇÇÌÌÌÔÔÔÙÙÙÙÙÙÎÎο¿¿ÀÀÀ¾¾¾¼¼¼¼¼¼¿¿¿ÂÂÂÃÃÃÅÅÅÐÐÐÊÊÊÉÉÉÉÉÉÉÉÉÌÌÌÆÆÆ»»»ÆÆÆÊÊÊÌÌÌÊÊÊÉÉÉÌÌÌÍÍÍÍÍÍÍÍÍÑÑÑîîîâââçççäääÜÜÜÝÝÝäääçççîîîñññîîîñññóóóïïïÃÃÃÊÊÊÎÎÎÌÌÌÎÎÎØØØÛÛÛ×××ÒÒÒßßßØØØÙÙÙØØØßßßàààÒÒÒ×××ÔÔÔÑÑÑÑÑÑÕÕÕØØØÛÛÛÛÛÛÃÃÃÇÇÇÉÉÉÆÆÆ¼¼¼ºººÃÃÃÐÐÐâââäääæææààà×××ÍÍÍÉÉÉÇÇÇÌÌÌ×××ØØØÙÙÙÔÔÔÐÐÐÕÕÕÒÒÒÎÎÎÐÐÐÌÌÌ¿¿¿¼¼¼ÃÃÃäääöööîîîõõõùùùèèèßßßãããäääàààÑÑÑ×××ÜÜÜÎÎÎÐÐÐÜÜÜ×××ÐÐÐÜÜÜàààÛÛÛÙÙÙÝÝÝÛÛÛÑÑѺºº···¸¸¸»»»¼¼¼»»»¿¿¿ÅÅÅÅÅÅÅÅů¯¯°°°¿¿¿¿¿¿¿¿¿¾¾¾ÂÂÂÀÀÀ¾¾¾ººº¸¸¸µµµµµµµµµ»»»¼¼¼¼¼¼¾¾¾¸¸¸ÉÉÉÀÀÀÆÆÆÉÉÉÍÍÍÎÎÎÊÊÊÅÅÅÆÆÆÇÇÇÉÉÉÇÇÇ»»»ÉÉÉÒÒÒÑÑÑÐÐо¾¾¬¬¬¸¸¸ººº¼¼¼ÂÂÂÂÂÂÉÉÉÇÇǬ¬¬°°°³³³´´´¼¼¼ÂÂÂßßßÛÛÛßßßâââÔÔÔÍÍÍÊÊÊÆÆÆÃÃÃÃÃÃÀÀÀºººÊÊÊØØØÕÕÕÊÊÊÅÅÅÇÇÇÍÍÍÇÇÇÉÉÉÌÌÌÍÍÍÌÌÌÊÊÊÇÇÇÅÅÅÃÃÃÂÂÂÂÂÂÃÃÃÇÇÇÍÍÍÑÑÑÔÔÔÜÜÜßßßÝÝÝÙÙÙØØØØØØ×××ÕÕÕâââäääÌÌÌ¿¿¿ÉÉÉÒÒÒÜÜÜ×××ÒÒÒÐÐÐÅÅÅÀÀÀ¿¿¿¿¿¿ÉÉÉÇÇÇÅÅÅÎÎÎØØØÒÒÒÍÍÍÍÍÍÌÌÌÎÎÎÍÍÍÐÐÐ×××ÙÙÙÕÕÕÉÉÉ»»»ÆÆÆÃÃÿ¿¿¼¼¼¼¼¼¾¾¾¿¿¿ÀÀÀÆÆÆÆÆÆÅÅÅÂÂÂÅÅÅÇÇÇ¿¿¿±±±ÀÀÀÅÅÅÉÉÉÌÌÌÌÌÌÍÍÍÎÎÎÎÎÎÐÐÐÒÒÒïïïâââäääãããÜÜÜßßßßßßãããèèèîîîñññóóóõõõóóóÌÌÌÊÊÊÔÔÔÒÒÒÐÐÐÙÙÙØØØÕÕÕ×××àààßßßêêêãããêêêêêêàààëëëêêêäääÝÝÝÕÕÕÍÍÍÇÇÇÃÃÃÉÉÉÆÆÆÆÆÆÌÌÌÔÔÔØØØØØØ×××ÂÂÂÀÀÀÅÅÅÎÎÎÙÙÙââââââßßßÐÐÐÍÍÍÉÉÉÐÐÐÙÙÙÛÛÛÕÕÕÊÊÊÑÑÑÐÐÐÍÍÍÍÍÍÌÌÌ¿¿¿ÂÂÂÜÜÜîîîñññõõõóóóíííääääääííí×××ÌÌÌÐÐÐÛÛÛÎÎÎÉÉÉÙÙÙÙÙÙÍÍÍÕÕÕÛÛÛÝÝÝßßßÝÝÝÒÒÒÆÆÆ»»»ºººººº»»»¸¸¸···»»»ÂÂÂÃÃÃÃÃð°°±±±¾¾¾¿¿¿Â¾¾¾¼¼¼»»»¸¸¸······µµµ···¾¾¾ÀÀÀ¼¼¼»»»¸¸¸ÎÎÎÃÃÃÂÂÂÉÉÉÍÍÍÐÐÐÍÍÍÉÉÉÆÆÆÇÇÇÊÊÊÊÊʼ¼¼ÅÅÅÊÊÊÍÍÍÉÉɵµµ¨¨¨ºººººº¿¿¿ÃÃÿ¿¿ÀÀÀ¼¼¼ªªªªªª°°°´´´»»»ÃÃÃàààÙÙÙ×××ÜÜÜÛÛÛÛÛÛØØØÍÍÍÃÃÃÃÃÃÇÇÇ»»»ÇÇÇÔÔÔÕÕÕÐÐÐÌÌÌÊÊÊÌÌÌÌÌÌÌÌÌÌÌÌÍÍÍÍÍÍÌÌÌÊÊÊÊÊÊÆÆÆÅÅÅÅÅÅÆÆÆÊÊÊÎÎÎÒÒÒÕÕÕâââàààÜÜÜÔÔÔÑÑÑ×××ÜÜÜÙÙÙÜÜÜÜÜÜÍÍÍÑÑÑÜÜÜÛÛÛÝÝÝÜÜÜÒÒÒÎÎÎÅÅÅÀÀÀ¾¾¾¾¾¾ÇÇÇÆÆÆÆÆÆÑÑÑØØØÒÒÒÍÍÍÎÎÎÌÌÌÍÍÍÒÒÒ×××ÙÙÙØØØÍÍÍ¿¿¿¸¸¸¿¿¿¿¿¿¾¾¾¾¾¾¾¾¾¿¿¿ÂÂÂÃÃÃÅÅÅÉÉÉÆÆÆÀÀÀÀÀÀÀÀÀ»»»³³³µµµ»»»ÅÅÅÌÌÌÎÎÎÎÎÎÎÎÎÐÐÐÒÒÒÒÒÒëëëÜÜÜàààâââÜÜÜàààÜÜÜßßßäääëëëñññóóóóóóõõõàààÉÉÉÎÎÎÒÒÒÑÑÑ×××ÒÒÒÕÕÕÝÝÝßßßÙÙÙèèèÑÑÑÉÉÉÃÃþ¾¾ÂÂÂÅÅÅÆÆÆÃÃÿ¿¿¾¾¾ÂÂÂÆÆÆÉÉÉÌÌÌÎÎÎÒÒÒ×××ÔÔÔÊÊÊÂÂÂßßßÕÕÕÌÌÌÉÉÉÍÍÍÐÐÐÎÎÎÌÌÌçççÛÛÛÐÐÐÎÎÎÔÔÔÙÙÙ×××ÔÔÔÎÎÎÌÌÌÌÌÌÕÕÕÔÔÔÇÇÇÆÆÆÐÐÐÜÜÜöööúúúõõõöööêêêÛÛÛâââãããÛÛÛÑÑÑ×××ÎÎÎÆÆÆÙÙÙãããÕÕÕÍÍÍÌÌÌÔÔÔÙÙÙÒÒÒÅÅż¼¼¾¾¾ººº¸¸¸¸¸¸···µµµ¼¼¼ÃÃÃÂÂÂÀÀÀ°°°¯¯¯µµµµµµ»»»»»»···············¸¸¸¸¸¸¸¸¸»»»¾¾¾»»»ººººººÑÑÑÇÇÇÃÃÃÇÇÇÌÌÌÐÐÐÑÑÑÎÎÎÉÉÉÇÇÇÉÉÉÎÎÎÅÅÅÃÃÃÃÃÃÉÉÉÅÅű±±³³³¾¾¾¸¸¸ÀÀÀÅÅž¾¾µµµ°°°¯¯¯­­­±±±³³³¸¸¸¿¿¿ÛÛÛÒÒÒÐÐÐØØØÛÛÛÝÝÝßßßØØØÍÍÍÇÇÇÌÌÌÃÃÃÃÃÃÉÉÉÑÑÑØØØØØØÒÒÒÎÎÎÒÒÒÑÑÑÎÎÎÍÍÍÌÌÌÍÍÍÍÍÍÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÒÒÒ×××ÛÛÛÝÝÝÜÜÜÝÝÝàààßßßÝÝÝãããâââÕÕÕÊÊÊÍÍÍÆÆÆÔÔÔàààÛÛÛÙÙÙÛÛÛÐÐÐÍÍÍÅÅÅÀÀÀ¼¼¼»»»ÃÃÃÊÊÊÊÊÊÕÕÕÛÛÛÕÕÕÒÒÒÒÒÒÎÎÎÌÌÌÕÕÕÛÛÛÛÛÛ×××ÉÉɾ¾¾»»»¾¾¾¿¿¿ÀÀÀÀÀÀ¿¿¿ÀÀÀÂÂÂÅÅÅÅÅÅÉÉÉÆÆÆÀÀÀÃÃÃÅÅÅÅÅÅÆÆÆ¯¯¯µµµÀÀÀÌÌÌÐÐÐÎÎÎÎÎÎÐÐÐÒÒÒÐÐÐæææ×××ÝÝÝàààÜÜÜßßßÝÝÝàààâââèèèññññññîîîñññêêêÀÀÀÂÂÂÍÍÍÐÐÐÔÔÔÎÎÎØØØààààààÝÝÝóóóÕÕÕÍÍÍÌÌÌÍÍÍÑÑÑÐÐÐÌÌÌÆÆÆÀÀÀÃÃÃÊÊÊÑÑÑÍÍÍØØØÝÝÝØØØÐÐÐÍÍÍÒÒÒ×××ÍÍÍÐÐÐÔÔÔ×××ØØØØØØÙÙÙÛÛÛÐÐÐÍÍÍÐÐÐÊÊÊÃÃÃÃÃÃÆÆÆÑÑÑÌÌÌÐÐÐÍÍÍÔÔÔÔÔÔÌÌÌÉÉÉÅÅÅÍÍÍíííöööñññöööíííßßßäääçççëëë×××ØØØ×××ÅÅÅÎÎÎÛÛÛÝÝÝÊÊÊ¿¿¿ÅÅÅÌÌÌÅÅż¼¼»»»¾¾¾¸¸¸µµµ···¸¸¸ºººÀÀÀÇÇÇÃÃÃÃÃô´´°°°­­­¨¨¨¯¯¯­­­­­­°°°³³³µµµ¸¸¸¸¸¸¸¸¸¸¸¸µµµ¸¸¸¸¸¸¸¸¸¸¸¸ÑÑÑÉÉÉÉÉÉÆÆÆÊÊÊÑÑÑ×××ÒÒÒÊÊÊÇÇÇÉÉÉÅÅÅÇÇÇÎÎÎÑÑÑÕÕÕÇÇǰ°°···ÀÀÀ¸¸¸ÀÀÀÅÅÅ¿¿¿´´´¬¬¬³³³³³³´´´´´´»»»ÀÀÀÝÝÝÛÛÛàààØØØ×××ÔÔÔÛÛÛãããÜÜÜÐÐÐÌÌÌÇÇÇÀÀÀ¿¿¿ÉÉÉ×××ÛÛÛÙÙÙÕÕÕ×××ÕÕÕÑÑÑÎÎÎÍÍÍÎÎÎÎÎÎÐÐÐÎÎÎÐÐÐÑÑÑÑÑÑÒÒÒÕÕÕÛÛÛßßßãããäääëëëíííêêêîîîæææÑÑÑÔÔÔÙÙÙÑÑÑÕÕÕÜÜÜÕÕÕÔÔÔÒÒÒÎÎÎÍÍÍÅÅÅÂÂÂÃÃü¼¼ºººÀÀÀÐÐÐÐÐÐÙÙÙßßßÛÛÛÙÙÙÛÛÛÔÔÔÑÑÑÙÙÙÛÛÛØØØÕÕÕÊÊÊ¿¿¿¿¿¿ÃÃÃÅÅÅÅÅÅÃÃÃÀÀÀÀÀÀÂÂÂÅÅÅÆÆÆÆÆÆÂÂÂÂÂÂÉÉÉÆÆÆÀÀÀÆÆÆ¯¯¯´´´¿¿¿ÌÌÌÐÐÐÎÎÎÎÎÎÑÑÑÐÐÐÌÌÌàààÒÒÒÜÜÜàààÛÛÛÛÛÛÝÝÝààààààçççñññîîîèèèîîîèè躺º¿¿¿ÌÌÌÎÎÎÕÕÕÐÐÐÛÛÛßßßãããßßßïïïÉÉÉÇÇÇÊÊÊÎÎÎæææßßßÕÕÕÎÎÎÌÌÌÌÌÌÊÊÊÊÊÊßßß×××ÌÌÌÉÉÉÎÎÎ×××ÒÒÒÉÉÉÅÅÅÆÆÆÉÉÉÊÊÊÉÉÉÉÉÉÌÌÌÎÎÎÐÐÐÎÎÎÛÛÛÙÙÙÕÕÕÔÔÔÐÐÐÛÛÛÇÇÇÝÝÝÔÔÔÍÍÍÒÒÒÎÎÎÎÎÎÌÌÌÅÅÅÙÙÙëëëññññññêêêçççêêêâââóóóØØØ×××ßßßÆÆÆÅÅÅÒÒÒÝÝÝÐÐÐÅÅÅÃÃÃÅÅÅÀÀÀ¿¿¿¿¿¿ÀÀÀ»»»···ººº¼¼¼¼¼¼ÀÀÀÅÅÅÅÅÅÇÇǾ¾¾¸¸¸¯¯¯¥¥¥ªªª¨¨¨¨¨¨¬¬¬±±±µµµ¸¸¸¸¸¸···µµµµµµ¸¸¸ººº»»»···ÊÊÊÃÃÃÇÇÇÆÆÆÊÊÊÒÒÒØØØÔÔÔÌÌÌÇÇÇÊÊÊÀÀÀÆÆÆÛÛÛààà××ׯ¯¯µµµÂ¸¸¸¿¿¿ÂÂÂÃÃÿ¿¿°°°³³³´´´´´´µµµ¿¿¿ÃÃÃÛÛÛØØØâââÝÝÝØØØÐÐÐ×××äääàààÑÑÑÌÌÌÊÊÊÃÃÃÀÀÀÃÃÃÉÉÉÍÍÍÒÒÒÙÙÙÕÕÕÕÕÕÔÔÔÒÒÒÒÒÒÑÑÑÑÑÑÐÐÐÍÍÍÐÐÐÒÒÒÑÑÑÐÐÐÑÑÑÙÙÙßßßúúúõõõñññêêêæææîîîëëëØØØÍÍÍÙÙÙÔÔÔÕÕÕÛÛÛ×××ÕÕÕÎÎÎÍÍÍÌÌÌÅÅÅÂÂÂÃÃü¼¼¸¸¸¿¿¿ÔÔÔÔÔÔÜÜÜâââßßßßßßàààÙÙÙÙÙÙÝÝÝÙÙÙÕÕÕ×××ÍÍÍÀÀÀÀÀÀÅÅÅÆÆÆÆÆÆÃÃÃÂÂÂÃÃÃÇÇÇÌÌÌÌÌÌÉÉÉÂÂÂÅÅÅÊÊʼ¼¼¬¬¬¬¬¬³³³µµµ¿¿¿ÌÌÌÐÐÐÍÍÍÎÎÎÔÔÔÌÌÌÇÇÇÝÝÝÑÑÑÜÜÜàààØØØØØØÛÛÛÝÝÝÝÝÝäääñññîîîèèèïïïççç»»»ÅÅÅÎÎÎÐÐÐØØØÒÒÒÜÜÜÝÝÝçççâââëëëÀÀÀÇÇÇÐÐÐÑÑÑçççßßßÙÙÙÛÛÛââââââÛÛÛÑÑÑÅÅÅÐÐÐÕÕÕÒÒÒÍÍÍÊÊÊÇÇÇÂÂÂßßßÜÜÜÛÛÛÝÝÝâââãããàààÜÜÜÛÛÛÊÊÊÊÊÊÊÊÊÒÒÒ×××ÉÉÉÊÊÊÆÆÆëëëÙÙÙÉÉÉÒÒÒÔÔÔ×××ÙÙÙÂÂÂÍÍÍëëëÿÿÿõõõæææâââÝÝÝäääüüü×××ÐÐÐàààÊÊÊÊÊÊÝÝÝØØØ×××ÒÒÒÌÌÌÇÇÇÆÆÆÅÅÅÃÃÃÅÅž¾¾»»»¼¼¼¿¿¿¼¼¼¼¼¼¿¿¿ÅÅÅÊÊÊÆÆÆÃÃõµµªªª¯¯¯¬¬¬¥¥¥©©©°°°µµµ¸¸¸···´´´³³³ººº¼¼¼¼¼¼¼¼¼´´´Â»»»ÃÃÃÇÇÇÊÊÊÑÑÑØØØÕÕÕÌÌÌÉÉÉÌÌÌÌÌÌÉÉÉÜÜÜÜÜÜÅÅÅ´´´°°°¸¸¸ÀÀÀººº¿¿¿¿¿¿ÇÇÇÍÍÍ···°°°³³³±±±´´´¾¾¾¼¼¼ÉÉÉ¿¿¿ÇÇÇãããßßßÕÕÕ×××ßßßÙÙÙÍÍÍÍÍÍÍÍÍÉÉÉÆÆÆÂ¼¼¼¼¼¼ÉÉÉØØØÒÒÒÔÔÔÕÕÕ×××ÕÕÕÔÔÔÑÑÑÐÐÐÐÐÐÕÕÕÙÙÙ×××ÔÔÔÕÕÕÝÝÝæææèèèíííäääÛÛÛñññøøøæææèèèÊÊÊÔÔÔßßßàààÙÙÙÑÑÑÌÌÌÊÊÊÐÐÐÍÍÍ¿¿¿ÌÌÌÀÀÀ»»»¼¼¼ÅÅÅÒÒÒÙÙÙßßßÝÝÝÜÜÜÝÝÝÜÜÜØØØÙÙÙÔÔÔÒÒÒÔÔÔÌÌ̾¾¾ºººÀÀÀÃÃÃÆÆÆÅÅÅÂÂÂÀÀÀÀÀÀ»»»±±±°°°±±±¼¼¼ÇÇÇ¿¿¿­­­©©©°°°···ºººÀÀÀÉÉÉÎÎÎÑÑÑÎÎÎÌÌÌÇÇÇÌÌÌÕÕÕÝÝÝÝÝÝØØØÙÙÙâââßßßÝÝÝßßßöööñññèèèÿÿÿîîîßßßÆÆÆºººÊÊÊÇÇÇÕÕÕÔÔÔ×××ÛÛÛààààààäääÒÒÒ¿¿¿ÌÌÌÔÔÔÜÜÜÐÐÐÐÐÐÆÆÆÃÃÃÉÉÉÉÉÉØØØÉÉÉÍÍÍÌÌ̾¾¾ÆÆÆÒÒÒÛÛÛÒÒÒÒÒÒÔÔÔÕÕÕ×××ØØØÙÙÙÙÙÙÙÙÙ×××ØØØÙÙÙÒÒÒÉÉÉÍÍÍÙÙÙÎÎÎÉÉÉÛÛÛÙÙÙØØØÑÑÑÛÛÛÑÑÑÎÎλ»»õõõøøøòòòõõõêêêãããëëëîîîÝÝÝØØØâââÐÐÐÆÆÆßßßßßß×××ÎÎÎÊÊÊÊÊÊÌÌÌÊÊÊÇÇÇÃÃÿ¿¿¼¼¼»»»»»»¼¼¼¼¼¼ÂÂÂÉÉÉ»»»»»»³³³ªªª­­­¦¦¦¢¢¢¦¦¦´´´¼¼¼ºººµµµ´´´µµµººº¼¼¼»»»»»»¿¿¿ÀÀÀ¿¿¿ÉÉÉÐÐÐÎÎÎÔÔÔÇÇÇÌÌÌÉÉÉÐÐÐÊÊÊÆÆÆÕÕÕÝÝÝÐÐЬ¬¬···»»»¼¼¼¼¼¼ººº¾¾¾ÎÎÎÙÙÙÉÉÉ­­­³³³±±±···¿¿¿ÃÃÃÂÂÂÃÃÃÉÉÉÉÉÉÑÑÑÔÔÔÒÒÒØØØÝÝÝ×××ÉÉÉÉÉÉÒÒÒÐÐÐÇÇÇÇÇÇÇÇÇÆÆÆÊÊÊÕÕÕÒÒÒÙÙÙ×××ÕÕÕØØØÑÑÑÕÕÕÙÙÙÛÛÛÛÛÛÙÙÙÙÙÙßßßêêêóóóâââèèèëëëãããçççêêêàààëëëçççâââÙÙÙÔÔÔÑÑÑÎÎÎÌÌÌÉÉÉÎÎÎÊÊʺººÇÇǾ¾¾¿¿¿ÅÅÅÎÎÎÐÐÐØØØÝÝÝÜÜÜÙÙÙÙÙÙØØØÕÕÕÒÒÒÍÍÍÎÎÎÒÒÒÌÌÌ¿¿¿»»»¿¿¿¿¿¿ÃÃÃÅÅÅÂÂÂÀÀÀ¾¾¾···´´´±±±±±±³³³­­­¨¨¨­­­¸¸¸ººº¼¼¼ÂÂÂÉÉÉÎÎÎÐÐÐÍÍÍÊÊÊÉÉÉÉÉÉÍÍÍÕÕÕÜÜÜÜÜÜÝÝÝÝÝÝÜÜÜàààâââõõõïïïíííÿÿÿîîîêêê×××¾¾¾ÆÆÆÃÃÃÐÐÐÔÔÔØØØÜÜÜàààßßßààà×××ÅÅÅÇÇÇÑÑÑÑÑÑÐÐÐ×××ÙÙÙ×××ÔÔÔÐÐÐÔÔÔÃÃÃÐÐÐÛÛÛÛÛÛ×××ÔÔÔÑÑÑÍÍÍÌÌÌÌÌÌÌÌÌÍÍÍÎÎÎÐÐÐÐÐÐÑÑÑÍÍÍÉÉÉÊÊÊÑÑÑÐÐÐÇÇÇÆÆÆÍÍÍÑÑÑßßßÑÑÑÅÅÅçççÜÜÜÍÍÍÙÙÙÔÔÔ¾¾¾ÝÝÝîîîõõõòòòïïïæææîîîèèèÛÛÛØØØàààÕÕÕÊÊÊÒÒÒÛÛÛÕÕÕÒÒÒÔÔÔ×××ÔÔÔÌÌÌÃÃÃÆÆÆÅÅÅ¿¿¿¼¼¼¼¼¼¼¼¼¼¼¼ÂÂÂÅÅÅÆÆÆÆÆÆÃÃþ¾¾¾¾¾ÆÆÆÂ¸¸¸°°°°°°µµµººº»»»¼¼¼»»»µµµ³³³¸¸¸¿¿¿ÀÀÀÂÂÂÃÃÃÙÙÙÙÙÙÑÑÑ×××ÍÍÍÒÒÒÊÊÊÊÊÊÌÌÌÍÍÍÝÝÝäääÒÒÒ¬¬¬¸¸¸¾¾¾¸¸¸¾¾¾¿¿¿¿¿¿ÆÆÆÐÐÐÒÒÒÎÎÎÃÃÃÀÀÀººº±±±³³³¼¼¼ÀÀÀ¾¾¾ÐÐÐÕÕÕ×××ÕÕÕÙÙÙàààÜÜÜÑÑÑÑÑÑÝÝÝßßßÕÕÕÐÐÐÊÊÊÉÉÉÍÍÍîîîßßßØØØÐÐÐÔÔÔßßßÝÝÝâââãããêêêîîîëëëäääàààãããçççããããããëëëæææàààßßßÜÜÜçççàààÛÛÛÔÔÔÑÑÑÒÒÒÒÒÒÎÎÎÊÊÊÇÇÇÆÆÆ¸¸¸ÉÉÉÅÅÅÇÇÇÍÍÍÔÔÔÍÍÍ×××ÜÜÜÛÛÛ×××ÕÕÕÒÒÒÐÐÐÑÑÑÍÍÍÎÎÎÑÑÑÍÍÍÀÀÀ¼¼¼¿¿¿¼¼¼ÀÀÀÃÃÃÃÃÃÂÂÂÂÂÂÀÀÀ¾¾¾ªªª­­­°°°±±±°°°°°°³³³´´´»»»¾¾¾ÂÂÂÇÇÇÍÍÍÍÍÍÊÊÊÇÇÇÊÊÊÇÇÇÆÆÆÌÌÌØØØâââàààÛÛÛÛÛÛàààãããòòòïïïïïïÿÿÿîîîîîîæææÀÀÀÅÅÅÅÅÅÍÍÍÕÕÕØØØÜÜÜÝÝÝÜÜÜÛÛÛÜÜÜÎÎÎÂÂÂÎÎÎÑÑÑÑÑÑÎÎÎÑÑÑÐÐÐÌÌÌÒÒÒÕÕÕÐÐÐÒÒÒÑÑÑÍÍÍÊÊÊÌÌÌÎÎÎÐÐÐÆÆÆÇÇÇÇÇÇÇÇÇÇÇÇÇÇÇÉÉÉÉÉÉÆÆÆ¿¿¿¿¿¿ÇÇÇÊÊÊÇÇÇÅÅÅÇÇÇÑÑÑÐÐÐÐÐÐÊÊÊÒÒÒÍÍÍÍÍÍÍÍÍÒÒÒÂÂÂÇÇÇäääùùùñññóóóæææîîîãããØØØØØØÝÝÝÜÜÜÑÑÑÇÇÇÜÜÜÙÙÙ×××××××××ÕÕÕÑÑÑÎÎÎÊÊÊÉÉÉÅÅÅ¿¿¿¾¾¾¾¾¾¾¾¾ÀÀÀ¿¿¿ÅÅÅÇÇÇÀÀÀ¼¼¼ÀÀÀÆÆÆ¿¿¿¸¸¸°°°­­­±±±¸¸¸ººº···µµµ¸¸¸»»»¼¼¼¿¿¿ÀÀÀÀÀÀ¿¿¿ÇÇÇÐÐÐÐÐÐ×××ÌÌÌÎÎÎÊÊÊÐÐÐÍÍÍÑÑÑäääèèè××ׯ¯¯»»»ÅÅÅ»»»ÀÀÀÃÃÃÃÃÃÃÃÃÊÊÊØØØãããÕÕÕÒÒÒÉÉÉ»»»···¼¼¼ÂÂÂÂÂÂÐÐÐ×××ÙÙÙÛÛÛàààäääààà×××ãããçççãããàààãããÜÜÜÎÎÎÇÇÇæææÜÜÜßßßÜÜÜàààäääÜÜÜÜÜÜàààæææêêêæææÛÛÛÐÐÐÌÌÌÌÌÌïïïÝÝÝââââââÜÜÜÝÝÝÛÛÛÜÜÜÑÑÑÒÒÒÔÔÔÒÒÒÎÎÎÌÌÌÉÉÉÇÇÇÀÀÀÅÅž¾¾ÔÔÔÒÒÒÒÒÒÐÐÐÐÐÐÊÊÊÔÔÔÛÛÛØØØÔÔÔÑÑÑÐÐÐÍÍÍÔÔÔÐÐÐÎÎÎÐÐÐÊÊʼ¼¼¿¿¿¼¼¼ÀÀÀÅÅÅÃÃÃÂÂÂÀÀÀÀÀÀÀÀÀ¥¥¥¯¯¯¸¸¸»»»¿¿¿ÀÀÀ¼¼¼´´´ººº»»»¿¿¿ÆÆÆÊÊÊÌÌÌÉÉÉÆÆÆÉÉÉÇÇÇÃÃÃÆÆÆÒÒÒààààààÙÙÙÛÛÛÝÝÝâââòòòòòòîîîøøøïïïæææêêêÀÀÀÆÆÆÉÉÉÎÎÎÕÕÕÔÔÔØØØØØØØØØ×××ßßßÕÕÕ¿¿¿ÎÎÎÕÕÕÕÕÕÇÇÇÇÇÇÆÆÆÅÅÅÕÕÕØØØÎÎÎÌÌÌÇÇÇÃÃÃÂÂÂÅÅÅÉÉÉÊÊÊÊÊÊÊÊÊÉÉÉÉÉÉÇÇÇÇÇÇÇÇÇÆÆÆÊÊʾ¾¾ÀÀÀÅÅÅÆÆÆÉÉÉÎÎÎÅÅÅÎÎÎÎÎÎÍÍÍÙÙÙ×××ÔÔÔÜÜÜÎÎÎÇÇÇÂÂÂÙÙÙòòòòòòñññæææèèèäääÛÛÛ×××ÝÝÝâââØØØÌÌÌ×××ÙÙÙÛÛÛØØØÕÕÕÔÔÔ×××ÛÛÛÐÐÐÍÍÍÉÉÉÅÅÅÂÂÂÀÀÀ¿¿¿¿¿¿¾¾¾»»»ÂÂÂÃÃü¼¼¼¼¼¿¿¿···¬¬¬­­­¬¬¬¬¬¬³³³¼¼¼»»»´´´¾¾¾ÐÐÐÒÒÒ¿¿¿±±±¸¸¸¼¼¼ººº···ÅÅÅÌÌÌÕÕÕÊÊÊÍÍÍÉÉÉÐÐÐÎÎÎÑÑÑßßßäääÙÙÙµµµ¿¿¿ÉÉÉÆÆÆÂÂÂÂÂÂÆÆÆÉÉÉÊÊÊÑÑÑÙÙÙÌÌÌÌÌÌÌÌÌÊÊʸ¸¸¸¸¸¿¿¿ÆÆÆÐÐÐÙÙÙßßßääääääÜÜÜÑÑÑççççççâââæææñññêêêÔÔÔÇÇÇÑÑÑÙÙÙîîîóóóóóóñññãããâââçççäääâââÝÝÝ×××ÑÑÑÌÌÌÇÇÇõõõÜÜÜÛÛÛÛÛÛØØØÜÜÜØØØÔÔÔÙÙÙÕÕÕÎÎÎÆÆÆÀÀÀ¿¿¿ÀÀÀÃÃÃÅÅÅÌÌÌÆÆÆÛÛÛÙÙÙÙÙÙÑÑÑÊÊÊÇÇÇÐÐÐ×××ÕÕÕÑÑÑÐÐÐÎÎÎÌÌÌÎÎÎÊÊÊÆÆÆÆÆÆÃÃÿ¿¿¿¿¿ÀÀÀÀÀÀÂÂÂÅÅÅÅÅÅ¿¿¿¿¿¿Â­­­µµµ»»»»»»ÀÀÀÇÇÇÆÆÆÀÀÀ···¸¸¸¼¼¼ÂÂÂÇÇÇÊÊÊÉÉÉÇÇÇÉÉÉÉÉÉÇÇÇÆÆÆÎÎÎÛÛÛßßßÛÛÛÝÝÝÛÛÛâââóóóóóóíííñññïïïäääççç¿¿¿ÃÃÃÇÇÇÍÍÍÒÒÒÑÑÑÒÒÒÒÒÒÔÔÔÒÒÒÝÝÝÕÕÕÀÀÀÑÑÑÎÎÎØØØÔÔÔÙÙÙÙÙÙÔÔÔÛÛÛÕÕÕÊÊÊÉÉÉÇÇÇÉÉÉÊÊÊÊÊÊÊÊÊÊÊÊÍÍÍÍÍÍÌÌÌÊÊÊÉÉÉÇÇÇÆÆÆÅÅÅÆÆÆÃÃÃÂÂÂÂÂÂÂÂÂÂÂÂÉÉÉÐÐÐØØØÂÂÂÌÌÌØØØÌÌÌØØØãããÎÎÎÐÐÐÎÎÎÊÊÊÍÍÍßßßñññîîîëëëâââêêêààà×××ßßßâââÛÛÛÛÛÛÐÐÐÒÒÒ×××ÛÛÛÜÜÜÛÛÛ×××ÔÔÔÒÒÒÐÐÐÌÌÌÇÇÇÅÅÅÂÂÂÂÂÂÀÀÀ¿¿¿ÀÀÀÆÆÆÅÅÅÃÃÃÌÌÌÇÇDZ±±°°°³³³³³³³³³ºººÂ¼¼¼¸¸¸ÉÉÉÊÊʸ¸¸³³³ÀÀÀÐÐÐÒÒÒÉÉÉÌÌÌÆÆÆÑÑÑÌÌÌÒÒÒÉÉÉÇÇÇÍÍÍÌÌÌÔÔÔÜÜÜÜÜÜ»»»ÃÃÃÌÌÌÌÌÌÃÃÿ¿¿ÅÅÅÉÉÉÆÆÆÇÇÇÌÌÌÇÇÇÆÆÆÌÌÌÒÒÒÑÑÑÅÅÅ»»»¸¸¸¾¾¾ÆÆÆÑÑÑØØØÜÜÜÛÛÛÔÔÔÌÌÌ×××ÝÝÝàààèèèñññèèè×××ÐÐÐÀÀÀÉÉÉÜÜÜâââæææêêêæææëëëäääÝÝÝ××××××ÜÜÜÜÜÜÔÔÔÌÌÌîîîÜÜÜÜÜÜ×××ÐÐÐÔÔÔÒÒÒÒÒÒÒÒÒÌÌÌÃÃÃÀÀÀÆÆÆÌÌÌÎÎÎÎÎÎÒÒÒÕÕÕÉÉÉÙÙÙ×××ØØØÐÐÐÇÇÇÃÃÃÊÊÊÎÎÎÎÎÎÍÍÍÐÐÐÎÎÎÊÊÊÀÀÀ¼¼¼ºººººº¼¼¼¿¿¿ÂÂÂÅÅÅÅÅÅÃÃÃÅÅÅÆÆÆÃÃÿ¿¿¿¿¿ÀÀÀ¯¯¯µµµººº»»»ÀÀÀÇÇÇÇÇÇÃÃ÷··¸¸¸¼¼¼ÂÂÂÇÇÇÊÊÊÉÉÉÇÇÇÉÉÉÉÉÉÊÊÊÌÌÌÑÑÑÙÙÙÝÝÝÝÝÝßßßßßßæææóóóõõõïïïîîîïïïëëëâââ¼¼¼ÀÀÀÃÃÃÌÌÌÐÐÐÎÎÎÎÎÎÐÐÐÑÑÑÒÒÒ×××ÍÍÍÅÅÅÔÔÔÅÅÅÑÑÑÙÙÙàààâââÜÜÜÙÙÙÑÑÑÍÍÍÉÉÉÅÅÅÆÆÆÇÇÇÉÉÉÌÌÌÑÑÑÍÍÍÍÍÍÊÊÊÇÇÇÆÆÆÃÃÃÀÀÀÀÀÀ¼¼¼¿¿¿ÂÂÂÃÃÃÂÂÂÀÀÀÂÂÂÆÆÆÇÇÇÝÝÝÅÅž¾¾ÕÕÕÔÔÔÂÂÂßßß×××ÕÕÕÒÒÒÃÃÃÉÉÉííííííõõõßßßëëëæææÜÜÜààààààÝÝÝäääÙÙÙÒÒÒÎÎÎÑÑÑÙÙÙÜÜÜ×××ÐÐÐÔÔÔÑÑÑÎÎÎÊÊÊÆÆÆÅÅÅÃÃÃÃÃÃÇÇÇÉÉÉÉÉÉÆÆÆÇÇÇÌÌ̯¯¯¸¸¸¾¾¾ÂÂÂÃÃÃÃÃþ¾¾¸¸¸ÃÃÃÅÅÅÅÅÅÅÅÅÅÅÅÆÆÆÆÆÆÆÆÆÍÍÍÍÍÍÅÅÅÌÌÌÇÇÇÐÐÐÊÊÊÌÌÌÌÌÌÉÉÉÍÍÍ×××ÜÜܼ¼¼ÀÀÀÇÇÇÆÆÆÀÀÀ¾¾¾ÀÀÀÀÀÀ¿¿¿ÃÃÃÊÊÊÎÎÎÍÍÍÊÊÊÍÍÍÕÕÕØØØÉÉÉ···¼¼¼ÀÀÀÅÅÅÉÉÉÍÍÍÎÎÎÍÍÍÌÌÌÌÌÌÐÐÐÕÕÕâââïïïêêêÙÙÙÒÒÒÕÕÕÎÎÎÐÐÐÌÌÌÍÍÍÑÑÑÌÌÌÎÎÎÕÕÕÎÎÎÊÊÊÑÑÑÜÜÜÝÝÝÑÑÑÅÅÅâââÛÛÛÝÝÝÒÒÒÌÌÌÐÐÐÌÌÌÌÌÌÉÉÉÇÇÇÉÉÉÍÍÍÔÔÔÛÛÛÜÜÜÜÜÜÙÙÙÛÛÛÊÊÊÕÕÕÒÒÒÔÔÔÌÌÌ¿¿¿ÂÂÂÅÅÅÆÆÆÉÉÉÎÎÎÍÍÍÉÉɸ¸¸µµµ´´´···¼¼¼ÂÂÂÆÆÆÇÇÇÆÆÆÂÂÂÂÂÂÅÅÅÆÆÆÂÂÂÀÀÀ¬¬¬³³³»»»ÀÀÀÃÃÃÅÅÅÃÃû»»¼¼¼¿¿¿ÅÅÅÉÉÉÌÌÌÊÊÊÉÉÉÊÊÊÆÆÆÇÇÇÐÐÐÙÙÙÝÝÝßßßßßßßßßçççïïïñññóóóöööòòòëëëëëëÕÕÕºººÅÅÅÅÅÅÑÑÑÐÐÐÎÎÎÍÍÍÑÑÑÑÑÑÔÔÔÍÍÍÀÀÀÇÇÇÔÔÔÊÊÊÎÎÎÔÔÔÑÑÑÐÐÐÒÒÒÐÐÐÎÎÎÇÇÇÅÅÅÅÅÅÉÉÉÉÉÉÆÆÆÇÇÇÌÌÌÍÍÍÍÍÍÊÊÊÇÇÇÃÃÃÀÀÀ¾¾¾¼¼¼ºººººº¼¼¼¿¿¿ÂÂÂÂÂÂÀÀÀ¿¿¿¾¾¾ÎÎÎÍÍÍÒÒÒÐÐÐÕÕÕÕÕÕçççÛÛÛÕÕÕÔÔÔÇÇÇÅÅÅçççëëëøøøâââçççêêêäääßßßÝÝÝßßßâââãããÛÛÛÐÐÐÌÌÌÎÎÎÒÒÒÕÕÕÕÕÕÔÔÔÒÒÒÎÎÎÊÊÊÇÇÇÆÆÆÆÆÆÅÅÅÊÊÊÌÌÌÉÉÉÇÇÇÇÇÇÀÀÀ¸¸¸µµµ¿¿¿ÃÃÃÉÉÉÌÌÌÇÇÇ¿¿¿»»»»»»ÀÀÀ¾¾¾ÀÀÀÉÉÉÎÎÎÊÊÊÃÃÃÀÀÀÂÂÂÇÇÇÇÇÇÔÔÔÎÎÎ×××ÐÐÐÑÑÑÌÌÌÍÍÍÑÑÑØØØÛÛÛ······¿¿¿¿¿¿¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼ÀÀÀÃÃÃÅÅÅÃÃÃÂÂÂÃÃÃÍÍÍÒÒÒÌÌÌ¿¿¿»»»¼¼¼¿¿¿ÂÂÂÅÅÅÆÆÆÇÇÇÉÉÉÉÉÉÉÉÉÌÌÌÜÜÜîîîêêêÙÙÙÑÑÑÝÝÝØØØÛÛÛ×××ØØØßßßÛÛÛßßßØØØÔÔÔÒÒÒØØØßßßÝÝÝÒÒÒÉÉÉÛÛÛÙÙÙÙÙÙÍÍÍÌÌÌÐÐÐÆÆÆÃÃÃØØØÜÜÜßßßÛÛÛÕÕÕÔÔÔØØØÜÜÜÛÛÛÛÛÛÊÊÊÕÕÕÑÑÑÒÒÒÇÇÇ»»»»»»¾¾¾¾¾¾¿¿¿ÆÆÆÍÍÍÍÍÍÇÇǺºº¸¸¸¸¸¸»»»ÀÀÀÆÆÆÉÉÉÉÉÉÇÇÇÀÀÀÀÀÀÅÅÅÆÆÆÃÃÃÂÂÂÃÃñ±±µµµ»»»¿¿¿ÂÂÂÂÂÂÅÅÅÆÆÆÀÀÀÀÀÀÃÃÃÇÇÇÊÊÊÌÌÌÊÊÊÉÉÉÌÌÌÃÃÃÅÅÅÒÒÒßßßâââààààààßßßñññùùùïïïòòòÿÿÿöööèèèãããÇÇǺººÌÌÌÍÍÍÙÙÙÑÑÑÎÎÎÎÎÎÒÒÒÑÑÑÕÕÕÆÆÆ¸¸¸ÉÉÉÔÔÔÕÕÕÒÒÒÕÕÕÆÆÆÂÂÂÊÊÊÆÆÆÊÊÊÌÌÌÉÉÉÉÉÉÊÊÊÊÊÊÆÆÆÉÉÉÐÐÐÐÐÐÎÎÎÌÌÌÇÇÇÅÅÅÀÀÀ¾¾¾¼¼¼¾¾¾ºººµµµ¸¸¸ÀÀÀÆÆÆÅÅÅÀÀÀÅÅÅÊÊÊÎÎÎÙÙÙÍÍÍÐÐÐÆÆÆÅÅÅØØØÑÑÑÑÑÑÒÒÒÊÊÊæææëëëóóóæææãããêêêëëëÝÝÝÛÛÛßßßÛÛÛÛÛÛßßßßßß×××ÌÌÌÇÇÇÍÍÍÕÕÕÔÔÔÒÒÒÎÎÎÌÌÌÉÉÉÇÇÇÆÆÆÆÆÆÇÇÇÇÇÇÆÆÆÌÌÌÍÍÍ¿¿¿»»»ÌÌÌÍÍÍÉÉÉÉÉÉÇÇÇÃÃÿ¿¿ÇÇÇÔÔÔÆÆÆÇÇÇÃÃþ¾¾¾¾¾ÂÂÂÆÆÆÆÆÆÆÆÆÊÊÊÌÌÌâââçççíííØØØÌÌÌÊÊÊÑÑÑØØØÝÝÝÛÛÛ±±±°°°¸¸¸»»»»»»»»»¼¼¼ÀÀÀ¼¼¼¸¸¸¿¿¿¿¿¿ÆÆÆÎÎÎÎÎÎÍÍÍÐÐÐØØØ···ººº¿¿¿ÃÃÃÅÅÅÅÅÅÃÃÃÅÅÅÂÂÂÊÊÊÒÒÒßßßèèèààà×××ØØØòòòïïïóóóçççÝÝÝÜÜÜÙÙÙâââÝÝÝÜÜÜÛÛÛÛÛÛÛÛÛØØØÑÑÑÌÌÌÔÔÔÙÙÙÐÐÐÐÐÐÅÅÅÅÅÅÂÂÂÜÜÜãããæææãããÙÙÙÕÕÕ×××ØØØØØØÐÐÐÒÒÒ××××××ÒÒÒÌÌÌÆÆÆÃÃÿ¿¿¼¼¼»»»¾¾¾¿¿¿¿¿¿ÆÆÆÍÍÍÇÇǼ¼¼µµµ»»»ÃÃÃÇÇÇÊÊÊÌÌÌÇÇÇÌÌÌÌÌÌÊÊÊÊÊÊÇÇÇ»»»¬¬¬­­­³³³»»»ÂÂÂÆÆÆÇÇÇÅÅÅÂÂÂÂÂÂÀÀÀÅÅÅÌÌÌÌÌÌÇÇÇÉÉÉÐÐÐÊÊÊÌÌÌÍÍÍâââÜÜÜÜÜÜÙÙÙçççüüüõõõóóóøøøøøøñññíííïïïÝÝÝÇÇÇÃÃÃÎÎÎÐÐÐÎÎÎÑÑÑÑÑÑÆÆÆÒÒÒÊÊÊÌÌÌÛÛÛ¼¼¼ÙÙÙÀÀÀÃÃÃÎÎÎÌÌÌÃÃÃÆÆÆÇÇÇÆÆÆÊÊÊÇÇÇÇÇÇÇÇÇÇÇÇÇÇÇÉÉÉÊÊÊÌÌÌÍÍÍÊÊÊÇÇÇÃÃÃÀÀÀ¿¿¿¾¾¾¾¾¾ººº¸¸¸¸¸¸¸¸¸ººº¼¼¼¿¿¿ÀÀÀÃÃÃÃÃÃÐÐÐÎÎÎÅÅÅÒÒÒÛÛÛÆÆÆÛÛÛÑÑÑÐÐÐÑÑѾ¾¾ÂÂÂçççòòòîîîäääÜÜÜßßßèèèñññëëëßßßØØØÒÒÒÒÒÒÙÙÙÜÜÜÒÒÒÇÇÇ»»»ÑÑÑÊÊÊÐÐÐÆÆÆÆÆÆÅÅÅÉÉÉÉÉÉÌÌÌÎÎÎÇÇǼ¼¼ÂÂÂÐÐÐÑÑÑÅÅÅÀÀÀ¿¿¿¿¿¿»»»¸¸¸ÀÀÀÍÍÍÊÊÊÂÂÂÀÀÀÆÆÆÌÌÌÊÊÊÊÊÊÍÍÍèèèâââßßßàààãããèèèëëëêêêäääàààÕÕÕÜÜÜäääÌÌ̯¯¯¯¯¯±±±µµµÀÀÀµµµ³³³···µµµÂÂÂÂÂÂÅÅÅÊÊÊÎÎÎÎÎÎÍÍÍÊÊÊàààÌÌÌ······Â¿¿¿»»»ÃÃÃÇÇÇÆÆÆÌÌÌÕÕÕ×××ÕÕÕÔÔÔÕÕÕñññíííêêêëëëçççàààßßßààààààÙÙÙÜÜÜÒÒÒ×××ÜÜÜÌÌÌÅÅÅÛÛÛÙÙÙÌÌÌÊÊÊÅÅÅÍÍÍÑÑÑâââäääçççæææßßßØØØÕÕÕÒÒÒÐÐÐÌÌÌÎÎÎÑÑÑÑÑÑÎÎÎÉÉÉÃÃÃÀÀÀ¿¿¿¿¿¿ÀÀÀ¿¿¿»»»¼¼¼ÂÂÂÑÑÑÇÇÇÀÀÀÅÅÅÉÉÉÊÊÊÉÉÉÇÇÇÊÊÊÍÍÍÎÎÎÍÍÍÊÊÊÃÃõµµ©©©­­­³³³»»»ÃÃÃÇÇÇÉÉÉÇÇÇÆÆÆÅÅÅÇÇÇÇÇÇÇÇÇÇÇÇÉÉÉÉÉÉÉÉÉÒÒÒ××××××ãããßßßæææçççïïïïïïëëëÿÿÿòòòÇÇÇÉÉÉãããàààÂÂÂÀÀÀÊÊÊÒÒÒÑÑÑÐÐÐÒÒÒÐÐÐÌÌÌÌÌÌÉÉÉÎÎÎÊÊÊ»»»ÕÕÕÍÍÍÇÇÇÎÎÎÊÊÊÂÂÂÆÆÆÇÇÇÆÆÆÊÊÊÇÇÇÇÇÇÇÇÇÇÇÇÇÇÇÉÉÉÊÊÊÌÌÌÌÌÌÉÉÉÆÆÆÂ¿¿¿¾¾¾¼¼¼¼¼¼ººº¸¸¸¸¸¸¸¸¸ººº¼¼¼¿¿¿ÀÀÀÆÆÆÂÂÂÊÊÊÎÎÎÍÍÍÔÔÔÕÕÕÆÆÆÛÛÛÝÝÝ××××××ÎÎÎÃÃÃÔÔÔæææíííëëëçççààààààæææçççäääïïïãããØØØØØØÛÛÛØØØÎÎÎÇÇǼ¼¼ÒÒÒÍÍÍÒÒÒÉÉÉÉÉÉÇÇÇÌÌÌÎÎÎÊÊÊÇÇÇÃÃÿ¿¿ÆÆÆÊÊʺººÆÆÆÍÍÍÍÍÍÐÐÐÕÕÕÑÑÑÆÆÆÌÌÌÆÆÆÅÅÅÍÍÍÙÙÙÝÝÝÜÜÜÙÙÙÝÝÝçççíííêêêææææææèèèêêêàààäääÛÛÛÙÙÙßßßÌÌ̱±±¬¬¬±±±¬¬¬­­­¯¯¯¬¬¬°°°···´´´ººº¼¼¼ÂÂÂÃÃÃÅÅÅÇÇÇÌÌÌÐÐÐÑÑÑÒÒÒÑÑÑÑÑÑÎÎμ¼¼ÆÆÆÂÂÂÇÇÇÐÐÐÔÔÔÐÐÐÍÍÍÕÕÕàààïïïçççæææïïïøøøöööîîîèèèÝÝÝÝÝÝãããÛÛÛ×××ØØØÊÊÊÆÆÆßßß×××ÊÊÊÆÆÆÂÂÂÔÔÔâââæææÛÛÛàààãããßßßÜÜÜÙÙÙÕÕÕÑÑÑÐÐÐÑÑÑÑÑÑÑÑÑÐÐÐÌÌÌÇÇÇÃÃÃÂÂÂÀÀÀÂÂÂÃÃÿ¿¿¸¸¸···ºººÂ¼¼¼¼¼¼ÅÅÅÍÍÍÎÎÎÎÎÎÎÎÎÒÒÒÑÑÑÑÑÑÐÐÐÊÊÊ¿¿¿···³³³±±±···¾¾¾ÃÃÃÉÉÉÊÊÊÊÊÊÉÉÉÆÆÆÊÊÊÊÊÊÅÅÅÆÆÆÍÍÍÎÎÎÊÊÊÜÜÜàààÝÝÝâââàààîîîòòòöööñññòòòÿÿÿëëëÀÀÀÀÀÀÑÑÑ¿¿¿ÅÅÅÎÎÎÐÐÐÍÍÍÒÒÒ×××ÒÒÒÐÐÐÇÇÇÌÌÌÒÒÒººº¼¼¼ÅÅÅÌÌÌÌÌÌÍÍÍÇÇÇÂÂÂÅÅÅÇÇÇÇÇÇÉÉÉÇÇÇÆÆÆÆÆÆÆÆÆÇÇÇÉÉÉÊÊÊÊÊÊÉÉÉÇÇÇÅÅÅ¿¿¿¼¼¼¼¼¼»»»¸¸¸¸¸¸¸¸¸¸¸¸ººº¼¼¼¿¿¿ÀÀÀÆÆÆÀÀÀÃÃÃÎÎÎÕÕÕÒÒÒÍÍÍÊÊÊ¿¿¿ØØØÐÐÐÐÐÐ×××ÇÇÇÆÆÆÔÔÔçççíííêêêßßßÛÛÛàààæææêêêïïïäää×××ÑÑÑ×××ÜÜÜ×××ÍÍÍ¿¿¿ÕÕÕÎÎÎÕÕÕÌÌÌÌÌÌÊÊÊÍÍÍÑÑÑÉÉÉÆÆÆÅÅÅÃÃÃÉÉÉÇÇǾ¾¾ÊÊÊÍÍÍÇÇÇÀÀÀÅÅÅÐÐÐÎÎÎÃÃÃÀÀÀÆÆÆÍÍÍ×××àààççççççâââæææííííííçççæææèèèèèèçççÝÝÝçççâââÜÜÜäääßßßÑÑÑÍÍÍÊÊʵµµªªª¯¯¯»»»ÆÆÆÅÅÅ···±±±¸¸¸ÀÀÀÅÅÅÅÅÅÅÅÅÅÅÅÃÃÃÌÌÌÒÒÒÕÕÕÙÙÙßßß×××ÇÇÇÂÂÂÂÂÂÇÇÇÐÐÐÔÔÔÔÔÔÔÔÔÝÝÝêêêçççÝÝÝÙÙÙâââñññúúúüüüúúúüüüóóóîîîàààØØØÕÕÕÉÉÉÅÅÅ×××ÒÒÒÌÌÌÇÇǾ¾¾ÑÑÑêêêãããÙÙÙÝÝÝßßßÛÛÛÙÙÙÙÙÙØØØÒÒÒÑÑÑÐÐÐÐÐÐÎÎÎÎÎÎÌÌÌÉÉÉÆÆÆ¿¿¿¿¿¿ÀÀÀÃÃü¼¼»»»¿¿¿¾¾¾¼¼¼¿¿¿ÉÉÉÎÎÎÎÎÎÌÌÌÍÍÍÒÒÒÍÍÍÊÊÊÉÉÉÃÃúºº¸¸¸¾¾¾ººº¼¼¼ÀÀÀÆÆÆÉÉÉÊÊÊÊÊÊÊÊÊÅÅÅÇÇÇÇÇÇÇÇÇÍÍÍÕÕÕØØØ×××àààßßßÝÝÝâââæææïïïõõõùùùüüüüüüçççÎÎÎÌÌÌÑÑÑÍÍÍÉÉÉÑÑÑÐÐÐÐÐÐÐÐÐÒÒÒ×××ÕÕÕÐÐÐÒÒÒÌÌÌÒÒÒ×××»»»ÐÐо¾¾ÍÍÍÑÑÑÍÍÍÅÅÅÂÂÂÅÅÅÇÇÇÇÇÇÆÆÆÆÆÆÅÅÅÅÅÅÅÅÅÆÆÆÇÇÇÉÉÉÉÉÉÆÆÆÅÅÅÃÃÃÀÀÀ¿¿¿¼¼¼»»»ººº¸¸¸¸¸¸¸¸¸¸¸¸ººº¼¼¼¿¿¿ÀÀÀÆÆÆÂÂÂÀÀÀÍÍÍ×××ÍÍÍÇÇÇÒÒÒÃÃÃÜÜÜÛÛÛØØØÙÙÙÐÐÐÇÇÇÀÀÀäääíííèèèÜÜÜÛÛÛßßßàààããããããàààÙÙÙÔÔÔ×××ÜÜÜØØØÎÎÎÀÀÀ×××ÐÐÐÕÕÕÌÌÌÌÌÌÊÊÊÎÎÎÐÐÐÊÊÊÌÌÌÊÊÊÃÃÃÆÆÆÊÊÊÆÆÆÊÊÊÀÀÀ¾¾¾ÃÃÃÅÅÅ¿¿¿¼¼¼¾¾¾ÊÊÊÙÙÙäääãããÝÝÝÝÝÝßßßÝÝÝâââäääãããæææëëëèèèãããäääíííòòòêêêâââæææäääàààãããÛÛÛÑÑÑÐÐÐÎÎÎÌÌÌÎÎÎÒÒÒÍÍͰ°°µµµººº¾¾¾ÅÅÅÊÊÊÌÌÌÉÉÉÊÊÊÍÍÍÇÇÇÍÍÍßßßäääÕÕÕÉÉÉÉÉÉÉÉÉÊÊÊ××׿ææèèèæææèèèÜÜÜ×××ÒÒÒÔÔÔÜÜÜæææîîîòòòëëëäääâââãããèèèæææÕÕÕÇÇÇÉÉÉÍÍÍÐÐÐÊÊʼ¼¼ÇÇÇçççÜÜÜààààààÜÜÜÔÔÔÑÑÑÒÒÒÑÑÑÎÎÎÉÉÉÉÉÉÉÉÉÇÇÇÆÆÆÅÅÅÃÃÃÂÂÂÂÂÂÀÀÀÀÀÀÃÃÿ¿¿ÂÂÂÆÆÆÃÃÃÃÃÃÇÇÇÑÑÑÔÔÔÑÑÑÎÎÎÐÐÐÅÅÅÂÂÂÂÂÂÃÃÿ¿¿ººº»»»ÂÂÂÂÂÂÃÃÃÅÅÅÇÇÇÉÉÉÉÉÉÉÉÉÉÉÉÆÆÆÅÅÅÉÉÉÑÑÑ×××ÙÙÙÝÝÝããããããÛÛÛÜÜÜçççïïïïïïóóóúúúîîîäääÎÎÎÅÅÅÐÐÐ×××ÕÕÕÙÙÙÕÕÕÒÒÒÔÔÔØØØÛÛÛÕÕÕÍÍÍÌÌÌÊÊÊÊÊÊÇÇÇÃÃü¼¼ØØØ¸¸¸ÇÇÇÔÔÔÌÌÌÅÅÅÃÃÃÅÅÅÆÆÆÆÆÆÅÅÅÃÃÃÃÃÃÃÃÃÃÃÃÅÅÅÅÅÅÆÆÆÇÇÇÅÅÅÃÃÃÂÂÂÀÀÀ¿¿¿¼¼¼»»»ººº¸¸¸¸¸¸···¸¸¸ººº»»»¾¾¾¿¿¿ÃÃÃÅÅÅÂÂÂÉÉÉÑÑÑÇÇÇÆÆÆÛÛÛÌÌÌÐÐÐ×××ßßß×××ÐÐÐÐÐм¼¼ÛÛÛíííëëëßßßÜÜÜÜÜÜØØØÛÛÛâââçççæææÝÝÝ××××××ÕÕÕÑÑÑÀÀÀ×××ÑÑÑ×××ÍÍÍÍÍÍÌÌÌÎÎÎÑÑÑÊÊÊÊÊÊÉÉÉÂÂÂÂÂÂÇÇÇÇÇÇÉÉÉÂÂÂÉÉÉÛÛÛßßßÒÒÒÑÑÑÜÜÜÒÒÒÛÛÛÙÙÙÊÊÊ»»»···¸¸¸ºººÅÅÅÎÎÎÜÜÜîîîõõõæææÜÜÜæææííííííæææâââàààÛÛÛÙÙÙàààâââÝÝÝàààÜÜÜÒÒÒÒÒÒÙÙÙÙÙÙ××××××ÍÍÍ¿¿¿···ººº¿¿¿ÂÂÂÃÃÃÍÍÍÌÌÌÊÊÊÕÕÕÝÝÝÝÝÝÜÜÜÍÍÍÍÍÍÌÌÌÛÛÛïïïîîîßßßÛÛÛÕÕÕÕÕÕÕÕÕ×××ÛÛÛÝÝÝÝÝÝÜÜÜ×××ÒÒÒÎÎÎ×××àààßßßØØØÎÎÎÀÀÀÍÍÍÒÒÒÍÍ;¾¾¿¿¿ãããÙÙÙÝÝÝÜÜÜÕÕÕÎÎÎÍÍÍÐÐÐÐÐÐÍÍÍÅÅÅÇÇÇÉÉÉÇÇÇÅÅÅÃÃÃÃÃÃÃÃÃÆÆÆÃÃÃÃÃÃÅÅÅÃÃÃÀÀÀÃÃÃÊÊÊÃÃÃÃÃÃÉÉÉÐÐÐÐÐÐÌÌÌÊÊÊÍÍÍÀÀÀÃÃÃÇÇÇÍÍÍÌÌÌÇÇÇÇÇÇÊÊÊÉÉÉÉÉÉÇÇÇÇÇÇÇÇÇÇÇÇÉÉÉÉÉÉÊÊÊÉÉÉÐÐÐÛÛÛÝÝÝÛÛÛÝÝÝäääæææÙÙÙßßßíííúúúóóóöööúúúêêêÍÍÍÉÉÉÔÔÔÒÒÒØØØÝÝÝÒÒÒÑÑÑÒÒÒÒÒÒÔÔÔÔÔÔÎÎÎÍÍÍÕÕÕÕÕÕÎÎÎÀÀÀ···ÀÀÀÐÐеµµÀÀÀÕÕÕÊÊÊÆÆÆÆÆÆÅÅÅÅÅÅÆÆÆÃÃÃÂÂÂÀÀÀÀÀÀÀÀÀÂÂÂÃÃÃÅÅÅÅÅÅÃÃÃÃÃÃÂÂÂÀÀÀ¿¿¿¼¼¼»»»ººº¸¸¸·········¸¸¸»»»¾¾¾¿¿¿ÂÂÂÆÆÆÃÃÃÅÅÅÊÊÊÇÇÇÊÊÊÙÙÙÎÎξ¾¾ÅÅÅÛÛÛÒÒÒÊÊÊÔÔÔÆÆÆÂÂÂâââíííãããààààààßßßæææßßßääääääÝÝÝÔÔÔÑÑÑÕÕÕØØØÂÂÂØØØÑÑÑØØØÍÍÍÎÎÎÌÌÌÐÐÐÒÒÒÇÇÇÅÅÅÆÆÆÂÂÂÂÂÂÆÆÆÃÃÃØØØÔÔÔÐÐÐÍÍÍÉÉÉÃÃÃÃÃÃÉÉÉâââÛÛÛÌÌ̾¾¾···»»»¿¿¿Â¼¼¼ÂÂÂÉÉÉßßßõõõîîîäääíííääääääãããäääààà×××ÒÒÒ××׿ææÛÛÛØØØÙÙÙÙÙÙßßßãããÝÝÝàààçççãããÐÐо¾¾»»»¾¾¾¿¿¿ÀÀÀÎÎÎÑÑÑÎÎÎÔÔÔÙÙÙÝÝÝäääÇÇÇÐÐÐÒÒÒÝÝÝëëëâââÑÑÑÑÑÑ×××ÕÕÕÕÕÕÛÛÛäääíííêêêâââçççãããÕÕÕÒÒÒÎÎÎÉÉÉÐÐÐÑÑÑÂÂÂÎÎÎÑÑÑÌÌ̼¼¼ãããÝÝÝÕÕÕÕÕÕÑÑÑÍÍÍÍÍÍÐÐÐÍÍÍÇÇÇÂÂÂÇÇÇÌÌÌÊÊÊÆÆÆÂÂÂÃÃÃÆÆÆÅÅÅÂÂÂÂÂÂÅÅÅÃÃÃÂÂÂÆÆÆÌÌÌÍÍÍÌÌÌÍÍÍÍÍÍÇÇǾ¾¾»»»¾¾¾ÇÇÇÌÌÌÐÐÐÐÐÐÐÐÐÒÒÒÒÒÒÑÑÑÌÌÌÊÊÊÉÉÉÇÇÇÇÇÇÇÇÇÊÊÊÌÌÌÆÆÆÍÍÍØØØßßßßßßÜÜÜÝÝÝâââãããÛÛÛãããêêêüüüøøøúúúøøøëëëÐÐÐÊÊÊÒÒÒÒÒÒ×××ÛÛÛÒÒÒÐÐÐÕÕÕÑÑÑÌÌÌÑÑÑÔÔÔÕÕÕÛÛÛâââÑÑÑÆÆÆÂÂÂÕÕÕÊÊÊÅÅÅÉÉÉÕÕÕÉÉÉÇÇÇÊÊÊÅÅÅÃÃÃÅÅÅ¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿ÀÀÀÂÂÂÃÃÿ¿¿¾¾¾»»»ººº············¸¸¸»»»¾¾¾¿¿¿ÀÀÀÅÅÅÃÃÃÀÀÀÇÇÇÐÐÐÑÑÑÐÐÐÛÛÛÔÔÔÊÊÊÑÑÑÒÒÒÎÎÎÑÑÑÇÇǵµµÙÙÙçççãããèèèëëëèèèîîîàààââââââßßßØØØÒÒÒÔÔÔÛÛÛÅÅÅÛÛÛÔÔÔÙÙÙÐÐÐÐÐÐÎÎÎÒÒÒÌÌÌÅÅÅÉÉÉÌÌÌÆÆÆÆÆÆÌÌÌÎÎÎÔÔÔ×××ÔÔÔÐÐÐÐÐÐÒÒÒÍÍÍÅÅÅÆÆÆ¼¼¼³³³³³³···¾¾¾ÅÅÅÊÊÊÍÍÍÊÊÊ¿¿¿ÉÉÉêêêöööîîîëëëèèèêêêèèèâââÙÙÙÕÕÕÑÑÑÍÍÍØØØÙÙÙâââãããÛÛÛÝÝÝæææçççàààèèèëëëâââØØØÎÎο¿¿°°°¿¿¿ÉÉÉÌÌÌÍÍÍ×××ÛÛÛÝÝÝäääÂÂÂÐÐÐÕÕÕÜÜÜäääÙÙÙÍÍÍ×××ØØØÛÛÛÝÝÝâââêêêóóóòòòíííäääçççàààãããÛÛÛÍÍÍÐÐÐÎÎÎÉÉÉÑÑÑÎÎÎÇÇÇÆÆÆ¿¿¿æææãããÕÕÕ×××ÔÔÔÐÐÐÍÍÍÌÌÌÅÅÅ»»»ºººÀÀÀÇÇÇÆÆÆÀÀÀ¼¼¼¾¾¾Â¿¿¿¾¾¾ÀÀÀÅÅÅÅÅÅÅÅÅÇÇÇÎÎÎÌÌÌÊÊÊÍÍÍÎÎÎÊÊÊÃÃÃÅÅÅÉÉÉÌÌÌÍÍÍÊÊÊÅÅÅÅÅÅÍÍÍÑÑÑÐÐÐÌÌÌÊÊÊÇÇÇÆÆÆÇÇÇÉÉÉÌÌÌÍÍ;¾¾ÎÎÎÜÜÜßßßÝÝÝààààààßßßÝÝÝÛÛÛããããããøøøøøøüüüñññÆÆÆÐÐÐÍÍÍÐÐÐÝÝÝÕÕÕÌÌÌ×××ÎÎÎØØØÒÒÒÎÎÎÜÜÜæææÛÛÛÐÐÐÍÍ͵µµ···ÃÃÃÛÛÛ¼¼¼ÊÊÊÊÊÊÕÕÕÉÉÉÉÉÉÌÌÌÅÅÅÂÂÂÃÃÃÀÀÀ¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¿¿¿ÀÀÀÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÀÀÀ¾¾¾»»»ººº············¸¸¸»»»¾¾¾¿¿¿ÂÂÂÃÃÃÀÀÀ¾¾¾ÇÇÇ×××ÕÕÕÇÇÇÉÉÉÛÛÛÅÅŸ¸¸ÌÌÌÕÕÕÑÑÑÆÆÆÀÀÀÝÝÝæææâââïïïóóóèèèæææïïïíííííííííæææØØØÒÒÒÔÔÔÆÆÆÜÜÜ×××ÜÜÜÒÒÒÒÒÒÑÑÑÕÕÕ¿¿¿ÃÃÃÒÒÒØØØÌÌÌÉÉÉ×××ãããÎÎÎÎÎÎÉÉÉÅÅÅÆÆÆÆÆÆººº¨¨¨¬¬¬©©©­­­µµµººº»»»ÀÀÀÉÉÉÐÐÐØØØÌÌÌÇÇÇãããõõõíííæææÝÝÝâââßßßÒÒÒÎÎÎÙÙÙÝÝÝ×××ÎÎÎÔÔÔâââèèèâââßßßàààÝÝÝ×××ÙÙÙÛÛÛßßßêêêëëëÔÔÔ¸¸¸···ÀÀÀÆÆÆÊÊÊÒÒÒ×××ÝÝÝêêêÀÀÀÎÎÎÒÒÒØØØäääÜÜÜÕÕÕàààÕÕÕäääññññññîîîêêêäääßßßæææäääÛÛÛâââßßßÐÐÐÑÑÑÊÊÊàààÌÌÌÍÍÍÊÊÊÇÇÇÔÔÔÛÛÛæææÔÔÔÜÜÜÒÒÒÔÔÔÙÙÙÎÎÎÅÅż¼¼ÇÇÇÆÆÆÅÅÅÅÅÅÃÃÃÃÃÃÃÃÃÅÅÅÃÃÃÀÀÀ»»»¿¿¿ÉÉÉÉÉÉÇÇÇÎÎÎÍÍÍÌÌÌÎÎÎÌÌÌ¿¿¿µµµ»»»ÆÆÆÍÍÍÑÑÑÐÐÐÉÉÉÇÇÇÌÌÌÐÐÐÐÐÐÑÑÑÌÌÌÍÍÍÃÃÃÊÊÊÅÅÅÍÍÍÌÌÌëëëãããÜÜÜÜÜÜàààãããàààÛÛÛßßßæææâââñññòòòóóóÿÿÿäääÍÍÍÑÑÑ×××ÙÙÙ×××ÒÒÒÎÎÎÌÌÌÐÐÐÌÌÌÉÉÉÔÔÔÊÊÊØØØ°°°¼¼¼···µµµÆÆÆÝÝÝÆÆÆºººÐÐÐÆÆÆÝÝÝÐÐÐÅÅÅÃÃÃÅÅÅÆÆÆÅÅÅ¿¿¿¾¾¾¾¾¾¼¼¼¼¼¼¼¼¼¿¿¿ÀÀÀÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÀÀÀ¿¿¿¾¾¾ººº¸¸¸¸¸¸ººº»»»¼¼¼¾¾¾¾¾¾ÀÀÀÅÅÅÂÂÂÆÆÆÉÉÉÒÒÒÜÜÜÌÌÌÕÕÕÉÉÉÉÉɾ¾¾ÒÒÒÎÎÎÇÇÇÊÊÊÀÀÀ···°°°±±±¼¼¼ÍÍÍãããõõõòòòõõõïïïïïïâââßßßÑÑÑÕÕÕÊÊÊÛÛÛßßßÛÛÛÜÜÜØØØÒÒÒÔÔÔÅÅÅÃÃÃÉÉÉÃÃÃÃÃÃàààêêêÎÎγ³³ÅÅÅ···°°°©©©µµµ¯¯¯¬¬¬±±±°°°­­­°°°´´´ººº¿¿¿ÆÆÆÒÒÒÑÑÑÃÃÃÍÍÍæææööööööÜÜÜäääÜÜÜØØØÛÛÛÜÜÜÙÙÙØØØÛÛÛÒÒÒÙÙÙçççÜÜÜÜÜÜæææÙÙÙÒÒÒçççêêêèèèääääääçççäääÝÝݸ¸¸···¿¿¿ÍÍÍÑÑÑÒÒÒÜÜÜêêê¿¿¿ÊÊÊÑÑÑÜÜÜíííëëëßßßÛÛÛßßßëëëïïïçççäääèèèæææÝÝÝçççÝÝÝâââÕÕÕØØØÒÒÒ×××ÆÆÆÔÔÔÉÉÉÀÀÀ¸¸¸ÂÂÂÙÙÙÜÜÜÒÒÒÍÍÍÙÙÙÑÑÑÑÑÑÎÎÎÂÂÂÀÀÀÀÀÀÇÇÇÇÇÇÆÆÆÆÆÆÅÅÅÃÃÃÂÂÂÂÂÂÆÆÆÅÅÅ¿¿¿ÅÅÅÎÎÎÌÌÌÇÇÇÍÍÍÌÌÌÎÎÎÎÎÎÉÉÉ¿¿¿ººº¿¿¿ÉÉÉÎÎÎÑÑÑÐÐÐÉÉÉÇÇÇÊÊÊÎÎÎÎÎÎÊÊÊÆÆÆÉÉÉÂÂÂÍÍÍÍÍÍÜÜÜàààãããßßßÜÜÜÝÝÝãããäääâââÝÝÝããããããßßßïïïïïïòòòóóóÇÇÇÍÍÍÑÑÑ×××ØØØÕÕÕÒÒÒÐÐÐÎÎÎÐÐÐÍÍÍÌÌÌÒÒÒÍÍÍÛÛÛµµµ¾¾¾¿¿¿¸¸¸ÆÆÆÒÒÒÆÆÆÆÆÆÑÑÑÀÀÀ×××ÔÔÔÊÊÊÃÃÃÂÂÂÀÀÀ»»»¸¸¸¾¾¾¼¼¼¼¼¼»»»¼¼¼¾¾¾ÀÀÀÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÀÀÀ¿¿¿¿¿¿ºººººººººººº»»»¼¼¼¾¾¾¿¿¿ÅÅÅÉÉÉÅÅÅÇÇÇÉÉÉÐÐÐ×××ÆÆÆÒÒÒÌÌÌÐÐÐÅÅÅÒÒÒÍÍÍÆÆÆÆÆÆÂ¼¼¼¸¸¸»»»¾¾¾ÀÀÀÇÇÇÐÐÐèèèóóóöööòòòäääèèèãããÝÝÝÒÒÒØØØßßßâââàààßßß×××ÌÌÌÊÊÊÌÌÌÔÔÔÔÔÔÔÔÔßßßÕÕÕ´´´¦¦¦­­­©©©¯¯¯ŸŸŸ¥¥¥¥¥¥ªªª°°°¯¯¯¯¯¯¯¯¯³³³···¼¼¼ÀÀÀÃÃÃÂÂÂÊÊÊäääõõõïïïèèèâââÜÜÜÝÝÝÛÛÛÕÕÕÕÕÕØØØÕÕÕÎÎÎÑÑÑÕÕÕßßßØØØØØØßßß×××ÕÕÕÔÔÔÕÕÕÔÔÔÕÕÕÝÝÝæææçççãããÐÐо¾¾µµµÂÂÂÎÎÎÔÔÔßßßîîîÊÊÊÊÊÊÑÑÑßßßèèèêêêäääÝÝÝßßßèèèîîîîîîîîîñññíííæææâââØØØØØØÎÎÎÐÐÐÐÐÐØØØÌÌÌÌÌÌÊÊʼ¼¼¾¾¾ÐÐÐßßßßßßÎÎÎÐÐÐØØØÐÐÐÐÐÐÍÍÍÃÃÃÇÇÇÊÊÊÅÅÅÅÅÅÆÆÆÆÆÆÆÆÆÅÅÅÅÅÅÅÅÅÉÉÉÉÉÉÅÅÅÉÉÉÑÑÑÎÎÎÉÉÉÌÌÌÍÍÍÑÑÑÐÐÐÆÆÆÀÀÀ¿¿¿ÅÅÅÌÌÌÐÐÐÑÑÑÐÐÐÉÉÉÇÇÇÊÊÊÍÍÍÍÍÍÌÌÌÊÊÊÑÑÑÊÊÊÒÒÒÑÑÑßßßâââÝÝÝÝÝÝÝÝÝàààããããããàààßßßââââââæææõõõóóóøøøóóó¿¿¿ÎÎÎÑÑÑÕÕÕÕÕÕÔÔÔÒÒÒÑÑÑÐÐÐÑÑÑÐÐÐÎÎÎÑÑÑÐÐÐÛÛÛ¼¼¼¿¿¿Â¾¾¾ÎÎÎÉÉÉÃÃÃÎÎÎÑÑÑ¿¿¿¿¿¿ÍÍÍÊÊÊ¿¿¿Â¼¼¼¿¿¿¼¼¼»»»»»»»»»»»»¼¼¼¿¿¿ÀÀÀÂÂÂÂÂÂÃÃÃÃÃÃÃÃÃÂÂÂÀÀÀÀÀÀ¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¾¾¾¿¿¿ÀÀÀÅÅÅÇÇÇÆÆÆÊÊÊÊÊÊÎÎÎÕÕÕÅÅÅÑÑÑÊÊÊÐÐÐÃÃÃÒÒÒÒÒÒÎÎÎÍÍÍÀÀÀ¾¾¾¿¿¿Â¾¾¾¼¼¼¾¾¾ÀÀÀ×××îîîîîîàààããããããÎÎÎÛÛÛÔÔÔÙÙÙßßßÜÜÜÝÝÝ×××ÃÃÃÐÐÐÌÌÌÅÅÅÃÃÃÎÎÎÝÝÝÝÝÝÒÒÒ¯¯¯©©©¯¯¯¼¼¼©©©¨¨¨©©©···±±±±±±±±±°°°±±±¸¸¸¾¾¾¾¾¾¿¿¿ÉÉÉàààòòòóóóêêêÝÝÝßßßßßßâââàààÛÛÛØØØØØØÒÒÒÊÊÊÍÍÍÎÎÎ×××ÔÔÔÔÔÔ×××ÔÔÔØØØØØØ×××ÒÒÒÔÔÔÜÜÜæææêêêçççíííÑÑÑ»»»¾¾¾ÌÌÌÒÒÒØØØâââ×××ÊÊÊÐÐÐÝÝÝàààäääêêêäää×××ÜÜÜæææîîîòòòñññíííèèèÝÝÝÝÝÝàààÒÒÒÍÍÍÌÌÌÛÛÛÛÛÛÅÅÅÃÃþ¾¾ÔÔÔäääÛÛÛÙÙÙ×××ÔÔÔÒÒÒÉÉÉÍÍÍÎÎÎÉÉÉÌÌÌÊÊÊÃÃÃÃÃÃÃÃÃÃÃÃÅÅÅÆÆÆÉÉÉÊÊÊÊÊÊÌÌÌÆÆÆÇÇÇÐÐÐÎÎÎÉÉÉÌÌÌÎÎÎ×××ÑÑÑÅÅÅÂÂÂÅÅÅÇÇÇÍÍÍÎÎÎÐÐÐÎÎÎÉÉÉÉÉÉÍÍÍÎÎÎÍÍÍÊÊÊÎÎÎÜÜÜØØØÝÝÝÔÔÔØØØ×××ßßßßßßàààââââââàààßßßÝÝÝÜÜÜàààîîîùùùñññõõõóóóÃÃÃÍÍÍÐÐÐÒÒÒÒÒÒÒÒÒÑÑÑÑÑÑÒÒÒÒÒÒÑÑÑÑÑÑÍÍÍÑÑÑÕÕÕ¾¾¾»»»¼¼¼ÂÂÂÜÜÜÅÅÅ¿¿¿ÐÐÐÎÎÎÀÀÀ¸¸¸ÒÒÒÑÑÑÀÀÀÀÀÀ¼¼¼µµµ»»»»»»»»»ººººººººº¼¼¼¾¾¾¿¿¿ÂÂÂÂÂÂÃÃÃÃÃÃÃÃÃÃÃÃÂÂÂÀÀÀ¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¿¿¿ÀÀÀÀÀÀ¿¿¿ÅÅÅÅÅÅÌÌÌÌÌÌÐÐÐ×××ÉÉÉÒÒÒÇÇÇÇÇÇ´´´ÂÂÂÉÉÉÉÉÉÅÅÅÊÊÊÆÆÆÆÆÆÉÉÉÉÉÉÅÅÅÅÅÅÇÇÇ···ÊÊÊçççñññãããàààèèèÕÕÕÝÝÝÔÔÔÑÑÑÑÑÑÑÑÑÒÒÒÎÎÎÃÃÃÔÔÔÑÑÑÃÃÃÂÂÂÐÐÐ×××ØØØÝÝÝÑÑÑÉÉÉÇÇÇÐÐо¾¾´´´¦¦¦´´´³³³±±±¯¯¯¨¨¨¥¥¥°°°¸¸¸´´´ßßßçççúúúöööîîîëëëâââäääæææâââßßßàààÛÛÛÑÑÑÌÌÌÍÍÍÊÊÊÉÉÉÐÐÐÔÔÔÔÔÔÑÑÑÒÒÒÙÙÙÛÛÛÙÙÙÕÕÕÒÒÒÒÒÒØØØßßßãããñññãããÍÍÍÅÅÅÌÌÌÒÒÒÒÒÒÕÕÕÝÝÝÎÎÎÌÌÌÔÔÔØØØßßßèèèîîîæææßßßÜÜÜàààâââßßßÝÝÝßßßÜÜÜÕÕÕÎÎÎÆÆÆÉÉÉÍÍÍÍÍÍÅÅÅ¿¿¿µµµ´´´×××äääÔÔÔÒÒÒÕÕÕÒÒÒÎÎÎÅÅÅÉÉÉÆÆÆ¾¾¾ÃÃÃÀÀÀÉÉÉÇÇÇÅÅÅÂÂÂÂÂÂÅÅÅÇÇÇÉÉÉÊÊÊÊÊÊÃÃÃÀÀÀÉÉÉÌÌÌÉÉÉÌÌÌÑÑÑÙÙÙÑÑÑÅÅÅÆÆÆÉÉÉÉÉÉÎÎÎÍÍÍÐÐÐÎÎÎÊÊÊÊÊÊÐÐÐÐÐÐÍÍÍÆÆÆÍÍÍÝÝÝÜÜÜâââ×××ÙÙÙ×××ßßßßßßàààààààààßßßàààâââßßßàààíííòòòèèèíííççç¾¾¾ÊÊÊÍÍÍÎÎÎÐÐÐÐÐÐÐÐÐÐÐÐÑÑÑÔÔÔÑÑÑÑÑÑÊÊÊÑÑÑÊÊʺºº···»»»ÂÂÂàààÀÀÀÃÃÃÑÑÑÊÊÊ¿¿¿¸¸¸ÒÒÒÒÒÒ¾¾¾···¾¾¾»»»»»»ººººººººº»»»¾¾¾¿¿¿ÀÀÀÂÂÂÃÃÃÃÃÃÃÃÃÃÃÃÂÂÂÂÂÂÀÀÀ¿¿¿¿¿¿¿¿¿¿¿¿ÀÀÀÀÀÀ¿¿¿ÃÃÃÅÅÅÌÌÌÌÌÌÎÎÎ×××ÌÌÌÇÇÇÆÆÆÎÎθ¸¸¾¾¾ÇÇÇÑÑÑÑÑÑÙÙÙÔÔÔÐÐÐÐÐÐÎÎÎÊÊÊÌÌÌÎÎÎÊÊÊÍÍÍÙÙÙîîîàààÝÝÝïïïëëëÙÙÙÙÙÙÒÒÒÎÎÎÐÐÐÊÊÊÅÅÅÇÇÇÔÔÔÕÕÕÎÎÎÍÍÍÔÔÔÐÐÐÌÌÌ×××××××××ÎÎÎÐÐÐÍÍÍÆÆÆ¦¦¦±±±±±±±±±´´´±±±µµµÎÎÎâââßßßîîîêêêñññèèèââââââÜÜÜäääâââÜÜÜØØØ×××ÑÑÑÉÉÉÆÆÆÊÊÊÉÉÉÇÇÇÌÌÌÕÕÕ×××ÐÐÐÒÒÒØØØÕÕÕ×××ØØØÔÔÔÎÎÎÑÑÑÝÝÝèèèàààêêêÝÝÝÉÉÉÊÊÊÔÔÔ×××ÙÙÙÛÛÛÔÔÔÉÉÉÇÇÇÐÐÐ×××ãããóóóõõõêêêãããäääçççèèèîîîøøøÜÜÜÜÜÜÔÔÔÑÑÑÑÑÑÔÔÔÌÌÌÅÅÅÀÀÀ±±±´´´ÎÎÎÛÛÛÙÙÙÙÙÙÑÑÑÕÕÕÒÒÒÍÍÍÎÎο¿¿³³³¾¾¾ÂÂÂÐÐÐÍÍÍÉÉÉÅÅÅÂÂÂÂÂÂÂÂÂÃÃÃÆÆÆÇÇǾ¾¾ºººÃÃÃÊÊÊÊÊÊÍÍÍÒÒÒØØØÎÎÎÆÆÆÌÌÌÌÌÌÉÉÉÑÑÑÐÐÐÑÑÑÎÎÎÌÌÌÍÍÍÑÑÑÑÑÑÍÍÍÐÐÐÑÑÑÜÜÜ×××ÝÝÝÕÕÕÛÛÛÙÙÙÛÛÛÜÜÜÝÝÝàààâââãããæææçççäääàààçççîîîîîîïïïàà྾¾ÅÅÅÇÇÇÌÌÌÍÍÍÍÍÍÍÍÍÎÎÎÐÐÐÒÒÒÎÎÎÑÑÑÇÇÇÑÑѾ¾¾···µµµ¼¼¼¿¿¿ØØØ»»»ÊÊÊÑÑÑÇÇǼ¼¼»»»ÍÍÍÌÌÌÂÂÂÂÂÂÀÀÀ¾¾¾ÅÅÅ»»»»»»ººººººººº¼¼¼¾¾¾¿¿¿ÀÀÀÀÀÀÂÂÂÃÃÃÃÃÃÃÃÃÂÂÂÂÂÂÂÂÂÀÀÀÀÀÀ¿¿¿¿¿¿ÀÀÀÀÀÀÂÂÂÂÂÂÅÅÅÅÅÅÍÍÍÌÌÌÌÌÌÔÔÔÌÌ̼¼¼ÉÉÉÝÝÝÃÃû»»ÀÀÀÐÐÐÒÒÒØØØÔÔÔÒÒÒÔÔÔÒÒÒÎÎÎÎÎÎÑÑÑÐÐÐÊÊÊÆÆÆíííâââÜÜÜæææêêêØØØÝÝÝÛÛÛØØØØØØÍÍÍÃÃÃÊÊÊÒÒÒÔÔÔÍÍÍÌÌÌÑÑÑÎÎÎÎÎÎÛÛÛÐÐÐÕÕÕÐÐÐÎÎÎÕÕÕÒÒÒ¨¨¨°°°±±±±±±³³³¬¬¬­­­ÊÊÊàààÙÙÙãããâââàààÙÙÙÛÛÛãããßßßÛÛÛÛÛÛÝÝÝÙÙÙÐÐÐÊÊÊÌÌÌÍÍÍÊÊÊÉÉÉÊÊÊÉÉÉÔÔÔ×××ÒÒÒ××××××ÕÕÕØØØÛÛÛØØØÑÑÑÐÐÐÜÜÜêêêßßßîîîàààÆÆÆÅÅÅÐÐÐÔÔÔÙÙÙ×××ØØØÌÌÌÂÂÂÉÉÉÑÑÑÛÛÛíííúúúöööóóóõõõïïïæææÝÝÝÝÝÝÅÅÅÔÔÔÕÕÕÑÑÑÃÃÃÀÀÀ¾¾¾ÃÃþ¾¾±±±ÃÃÃÔÔÔÕÕÕààààààÑÑÑ×××ÑÑÑÌÌÌÍÍÍ¿¿¿´´´ÅÅÅÌÌÌÍÍÍÌÌÌÊÊÊÇÇÇÅÅÅÃÃÃÂÂÂÀÀÀÂÂÂÃÃû»»···ÀÀÀÊÊÊÌÌÌÎÎÎÐÐÐÔÔÔÊÊÊÇÇÇÑÑÑÎÎÎÊÊÊÕÕÕÔÔÔÔÔÔÑÑÑÎÎÎÎÎÎÑÑÑÎÎÎÊÊÊÜÜÜÙÙÙÝÝÝÕÕÕÛÛÛÔÔÔÙÙÙØØØÙÙÙÛÛÛßßßâââæææççççççæææäääãããêêêòòòóóóëëëÔÔÔ¾¾¾ÀÀÀÃÃÃÇÇÇÊÊÊÊÊÊÊÊÊÌÌÌÍÍÍÑÑÑÊÊÊÑÑÑÉÉÉÔÔÔ´´´µµµ¸¸¸¼¼¼¾¾¾ÒÒÒºººÍÍÍÇÇÇÃÃÃÂÂÂÎÎÎÎÎÎÉÉɾ¾¾¼¼¼»»»¼¼¼¼¼¼»»»ºººººº»»»¼¼¼¾¾¾¿¿¿¿¿¿¿¿¿ÀÀÀÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÀÀÀ¿¿¿¿¿¿ÀÀÀÀÀÀÀÀÀÂÂÂÃÃÃÃÃÃÌÌÌÊÊÊÊÊÊÕÕÕÎÎÎÀÀÀÌÌÌßßß¿¿¿°°°´´´¿¿¿»»»ÒÒÒÐÐÐÑÑÑÔÔÔÕÕÕÒÒÒÒÒÒÕÕÕÒÒÒÑÑÑÂÂÂøøøñññëëëãããæææßßßÝÝÝÝÝÝÝÝÝÛÛÛÑÑÑÊÊÊÌÌÌ×××ÔÔÔÎÎÎÐÐÐÔÔÔÑÑÑÌÌÌÌÌÌ×××ÙÙÙÙÙÙÙÙÙØØØÐÐС¡¡©©©°°°±±±´´´¯¯¯°°°ÑÑÑêêêàààãããçççâââßßßäääêêêçççØØØØØØÛÛÛØØØÐÐÐÌÌÌÎÎÎÑÑÑÐÐÐÌÌÌÍÍÍÆÆÆÐÐÐÕÕÕÒÒÒÙÙÙÕÕÕÕÕÕÕÕÕ×××ÕÕÕÑÑÑÎÎÎ×××àààæææêêêÔÔÔÀÀÀÆÆÆÌÌÌÊÊÊÑÑÑÒÒÒÙÙÙ×××ÉÉÉÅÅÅÌÌÌ×××ßßß×××ÛÛÛàààäääàààØØØÑÑÑÎÎÎÒÒÒÜÜÜÑÑÑÎÎÎÆÆÆÉÉɾ¾¾ÀÀÀ³³³ªªªÐÐÐàààÔÔÔÛÛÛÜÜÜÑÑÑÑÑÑÅÅÅ»»»Â»»»¸¸¸ÉÉÉÍÍÍÆÆÆÇÇÇÉÉÉÉÉÉÉÉÉÆÆÆÅÅÅÃÃÿ¿¿ÂºººµµµÂÂÂÌÌÌÎÎÎÐÐÐÍÍÍÐÐÐÇÇÇÉÉÉÕÕÕÑÑÑÌÌÌÙÙÙØØØØØØÔÔÔÐÐÐÎÎÎÐÐÐÍÍÍÇÇÇÝÝÝÙÙÙÝÝÝÕÕÕÝÝÝ×××ÜÜÜÙÙÙÜÜÜÝÝÝâââæææèèèçççäääàààßßßçççñññóóóîîî×××»»»°°°¾¾¾ÂÂÂÆÆÆÉÉÉÉÉÉÉÉÉÉÉÉÊÊÊÑÑÑÉÉÉÐÐÐÉÉÉÕÕÕ°°°µµµ¾¾¾¸¸¸¿¿¿ÒÒÒ»»»ÊÊÊ»»»ÂÂÂÌÌÌÑÑÑÇÇÇÀÀÀ¿¿¿¼¼¼¾¾¾ÀÀÀ¿¿¿¼¼¼»»»»»»ººº»»»¼¼¼¿¿¿ÀÀÀ¾¾¾¿¿¿ÀÀÀÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÀÀÀ¿¿¿¿¿¿¿¿¿ÀÀÀÀÀÀ¾¾¾¿¿¿ÀÀÀÊÊÊÊÊÊÍÍÍÙÙÙÕÕÕÇÇÇÊÊÊØØØ¼¼¼¼¼¼ÌÌÌØØØÎÎÎØØØÔÔÔÑÑÑÒÒÒÒÒÒÐÐÐÒÒÒ×××ØØØÙÙÙ¼¼¼öööòòòóóóäääçççèèèÛÛÛÙÙÙÜÜÜÕÕÕÒÒÒÑÑÑÌÌÌÙÙÙÐÐÐÉÉÉÊÊÊÒÒÒ×××ÒÒÒÌÌÌÉÉÉÇÇÇÕÕÕßßßØØØÐÐШ¨¨³³³­­­°°°µµµ¯¯¯°°°ÔÔÔëëëàààçççßßßÔÔÔãããæææÕÕÕÒÒÒÍÍÍÒÒÒÎÎÎÎÎÎÎÎÎÌÌÌÆÆÆÉÉÉÐÐÐÎÎÎÎÎÎÃÃÃÊÊÊÑÑÑÒÒÒÜÜÜÔÔÔÛÛÛØØØØØØÜÜÜßßßßßßãããèèèäääÜÜÜÃÃü¼¼ÍÍÍÐÐÐÇÇÇÎÎÎÑÑÑÙÙÙßßßÒÒÒÂÂÂÉÉÉÕÕÕÒÒÒ××××××ÕÕÕÔÔÔÕÕÕÜÜÜæææíííØØØßßßÎÎÎÇÇǾ¾¾ÀÀÀµµµ»»»°°°­­­ÑÑÑØØØÔÔÔàààÔÔÔÊÊÊÀÀÀÉÉÉÉÉÉ»»»ÅÅÅÐÐÐÇÇÇÇÇÇÉÉÉÊÊÊÊÊÊÉÉÉÆÆÆÅÅÅÃÃÃÅÅÅÆÆÆ»»»´´´¸¸¸ÇÇÇÐÐÐÇÇÇ»»»ÀÀÀÂÂÂÉÉÉÒÒÒ×××ÔÔÔÒÒÒÕÕÕÕÕÕÕÕÕÎÎÎÔÔÔÒÒÒÉÉÉÊÊÊÆÆÆÙÙÙÝÝÝââââââàààÝÝÝÜÜÜÜÜÜàààâââãããææææææääääääæææßßßøøøòòòñññêêêÝÝݼ¼¼ººº¼¼¼ÂÂÂÇÇÇÇÇÇÆÆÆÅÅÅÉÉÉÌÌÌÐÐÐÎÎÎÑÑÑ××׺ºº´´´¸¸¸ÅÅÅÙÙÙÑÑÑÂÂÂÐÐÐÅÅŵµµÐÐÐØØØÕÕÕÆÆÆÂÂÂÀÀÀ¼¼¼¿¿¿ÃÃü¼¼ºººººº»»»¼¼¼¼¼¼¾¾¾¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿ÂÂÂÃÃÃÅÅÅÂÂÂÀÀÀ¾¾¾¼¼¼¼¼¼¿¿¿ÂÂÂÃÃÿ¿¿ÌÌÌÊÊÊÊÊÊÛÛÛÒÒÒºººÌÌÌÔÔÔ¿¿¿ÝÝÝÊÊÊÑÑÑÍÍÍÕÕÕÕÕÕÑÑÑÒÒÒÎÎÎÌÌÌÔÔÔÙÙÙÔÔÔÍÍÍîîîëëëøøøäääææææææ×××ÝÝÝÜÜÜÝÝÝÍÍÍÐÐÐÊÊÊÎÎÎÕÕÕÒÒÒÆÆÆÂÂÂÌÌÌÑÑÑÎÎÎÒÒÒÂÂÂÅÅÅÐÐÐÒÒÒØØØÊÊʨ¨¨±±±¸¸¸­­­°°°³³³ÔÔÔßßßäääÙÙÙÔÔÔÛÛÛäääææææææßßßÐÐÐÐÐÐÒÒÒÔÔÔÑÑÑÎÎÎÍÍÍÎÎÎÐÐÐÔÔÔÉÉÉÃÃÃÐÐÐÕÕÕÑÑÑ×××ÝÝÝêêêæææíííêêêííííííßßßããã××׿¿¿ÊÊÊÊÊÊÉÉÉÌÌÌÌÌÌÙÙÙÒÒÒîîîÙÙÙ¼¼¼ÉÉÉÇÇÇÉÉÉÅÅÅÒÒÒÝÝÝæææñññùùùòòòäääâââÛÛÛÅÅÅÐÐÐÀÀÀµµµ±±±¸¸¸ÎÎÎÆÆÆÙÙÙÕÕÕÉÉÉÎÎÎÅÅźººÅÅÅÅÅÅÀÀÀ´´´»»»ÉÉÉÆÆÆÍÍÍÐÐÐÐÐÐÍÍÍÊÊÊÆÆÆÃÃÃÅÅÅÆÆÆÆÆÆ¿¿¿»»»¿¿¿ÆÆÆÇÇÇÃÃþ¾¾¾¾¾¾¾¾ÃÃÃÍÍÍÒÒÒÒÒÒÔÔÔØØØÛÛÛØØØÍÍÍÒÒÒÑÑÑÊÊÊÎÎÎÍÍÍÙÙÙÛÛÛÜÜÜÜÜÜÛÛÛÜÜÜßßßâââàààâââäääæææææææææääääääèèèõõõñññøøøíííØØØººº»»»¿¿¿ÃÃÃÇÇÇÇÇÇÅÅÅÅÅÅÉÉÉÍÍÍÍÍÍÊÊÊÉÉÉÆÆÆµµµ¸¸¸ÆÆÆÒÒÒÔÔÔÌÌ̼¼¼ÌÌÌÆÆÆºººÊÊÊÇÇÇÎÎÎÉÉÉÉÉÉÇÇÇÅÅÅÃÃÃÃÃÿ¿¿ºººººº»»»¼¼¼¼¼¼¾¾¾¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿ÀÀÀÂÂÂÃÃÃÅÅÅÅÅÅÃÃÃÀÀÀ¿¿¿¼¼¼¾¾¾¿¿¿ÂÂÂÃÃÃÃÃÃÅÅÅÃÃÃÊÊÊÇÇÇÇÇÇÒÒÒÉÉɾ¾¾ÐÐÐÔÔÔ»»»¸¸¸ÙÙÙÉÉÉÉÉÉÒÒÒÕÕÕÐÐÐÌÌÌÐÐÐÎÎÎÍÍÍÒÒÒÔÔÔ×××ÎÎÎææææææùùùèèèâââãããÔÔÔÝÝÝââââââÐÐÐÍÍÍÆÆÆÎÎÎÙÙÙßßßÔÔÔÇÇÇÃÃÃÃÃÃÂÂÂ×××ÐÐÐÍÍÍÉÉÉÊÊÊ×××ÎÎί¯¯¯¯¯³³³±±±ÀÀÀÉÉÉàààæææëëëÙÙÙÕÕÕÜÜÜæææææææææàààÒÒÒÒÒÒÔÔÔÕÕÕÒÒÒÐÐÐÎÎÎÎÎÎÐÐÐÊÊÊÊÊÊÎÎÎÙÙÙÝÝÝÙÙÙ×××ÕÕÕîîîææææææãããæææíííèèèäääÉÉÉ¿¿¿ÂÂÂÊÊÊÉÉÉÉÉÉÐÐÐÔÔÔÌÌÌÒÒÒîîîâââÍÍÍÑÑÑÌÌÌÉÉÉÕÕÕâââêêêèèèèèèëëëæææÛÛÛÙÙÙÎÎÎÆÆÆÇÇǰ°°­­­¥¥¥¦¦¦ÝÝÝÕÕÕ×××ÐÐÐÃÃÃÇÇÇÇÇǾ¾¾ÆÆÆÀÀÀ¼¼¼µµµ¼¼¼ÆÆÆÅÅÅÎÎÎÎÎÎÍÍÍÊÊÊÆÆÆÃÃÃÂÂÂÅÅÅÇÇÇÇÇÇÃÃÃÅÅÅÇÇÇÅÅž¾¾¾¾¾ÃÃÃÀÀÀÀÀÀÃÃÃÍÍÍÒÒÒÔÔÔØØØÝÝÝÙÙÙ×××ÍÍÍÒÒÒÔÔÔÑÑÑÙÙÙÙÙÙÝÝÝßßßàààßßßÝÝÝÜÜÜÛÛÛÜÜÜääääääææææææçççççççççäääóóóøøøöööõõõÜÜÜÊÊʼ¼¼¿¿¿ÃÃÃÆÆÆÇÇÇÇÇÇÆÆÆÇÇÇÌÌÌÐÐÐÙÙÙÕÕÕÐÐÐÀÀÀ»»»ÃÃÃÕÕÕÙÙÙÐÐÐÇÇǺººÆÆÆÇÇÇÀÀÀÇÇǺººÌÌÌÐÐÐÎÎÎÍÍÍÍÍÍÇÇÇ¿¿¿¼¼¼ºººººº»»»¼¼¼¼¼¼¾¾¾¿¿¿¿¿¿¿¿¿ÀÀÀÂÂÂÃÃÃÅÅÅÅÅÅÅÅÅÅÅÅÃÃÃÂÂÂÀÀÀ¾¾¾¾¾¾ÀÀÀÂÂÂÃÃÃÅÅÅÉÉÉÇÇÇÇÇÇÅÅÅÅÅÅÊÊÊ¿¿¿¿¿¿ÇÇÇÊÊʸ¸¸´´´ÊÊʼ¼¼¿¿¿ÉÉÉÊÊÊÇÇÇÇÇÇÎÎÎÐÐÐÎÎÎÑÑÑÒÒÒ×××ÐÐÐæææëëëüüüèèèâââêêê×××ÛÛÛãããàààÍÍÍÉÉÉÅÅÅÂÂÂÌÌÌÔÔÔÔÔÔÎÎÎÉÉÉÇÇÇÇÇÇÆÆÆÇÇÇÅÅÅÀÀÀÌÌÌßßßâââÔÔÔ©©©¯¯¯¸¸¸ÑÑÑßßßêêêçççêêêØØØØØØßßßæææææææææâââÙÙÙÔÔÔÕÕÕÔÔÔÒÒÒÐÐÐÎÎÎÎÎÎÎÎÎâââÝÝÝÙÙÙÕÕÕÕÕÕØØØÙÙÙÛÛÛíííäääßßßàààâââêêêëëëÕÕÕ¾¾¾ÀÀÀÉÉÉÌÌÌÇÇÇÊÊÊÔÔÔ×××ÑÑÑßßßèèèàààØØØÙÙÙÜÜÜßßßÛÛÛæææíííçççããããããâââÝÝÝØØØÇÇÇÌÌÌÆÆÆ···ÑÑÑÙÙÙÛÛÛàààÛÛÛÔÔÔÍÍÍÃÃÃÆÆÆÌÌÌ»»»ÂÂÂÃÃÃÉÉÉÊÊÊÃÃÃÊÊÊÃÃÃÃÃÃÃÃÃÂÂÂÀÀÀÂÂÂÅÅÅÇÇÇÊÊÊÆÆÆÇÇÇÍÍÍÆÆÆ»»»¾¾¾ÇÇÇÊÊÊÉÉÉÌÌÌÒÒÒÕÕÕ×××ÛÛÛßßßÕÕÕÔÔÔÍÍÍ×××ÛÛÛÙÙÙââââââãããââââââàààààààààãããäääóóóõõõóóóòòòóóóööööööóóóõõõøøøöööàà྾¾ºººÂÂÂÅÅÅÆÆÆÇÇÇÉÉÉÉÉÉÉÉÉÍÍÍÒÒÒØØØâââßßßÙÙÙÀÀÀÅÅÅÍÍÍÜÜÜÕÕÕÍÍÍÉÉÉ¿¿¿ÆÆÆÇÇÇÆÆÆÌÌ̼¼¼ÃÃÃÌÌÌÉÉÉÇÇÇÑÑÑÎÎÎÀÀÀ¼¼¼ºººººº»»»¼¼¼¼¼¼¾¾¾¿¿¿¿¿¿¿¿¿ÀÀÀÂÂÂÅÅÅÆÆÆÆÆÆÆÆÆÅÅÅÅÅÅÃÃÃÂÂÂÀÀÀ¿¿¿ÀÀÀÂÂÂÃÃÃÆÆÆÊÊÊÊÊÊÅÅÅÃÃÃÆÆÆÆÆÆ¾¾¾ÅÅÅ···¸¸¸¾¾¾ÇÇÇÌÌ̺ºººººÀÀÀÅÅÅÇÇÇÌÌÌÎÎÎÎÎÎÍÍÍÎÎÎÔÔÔÑÑÑÍÍÍêêêõõõúúúæææçççøøøßßßØØØÝÝÝØØØÉÉÉÇÇÇÊÊÊÆÆÆÃÃÃÂÂÂÆÆÆÊÊÊÍÍÍÌÌÌÊÊÊÅÅÅÅÅÅÂÂÂÅÅÅÎÎÎ×××ÝÝÝãããâââàààßßßäääæææäääÛÛÛÕÕÕ×××ÙÙÙßßßäääæææææææææãããøøøöööóóóîîîèèèãããàààÝÝÝçççàààßßß×××ÕÕÕØØØØØØÝÝÝêêêãããßßßäääâââæææäää¼¼¼ÀÀÀÉÉÉÐÐÐÍÍÍÊÊÊÎÎÎÒÒÒÒÒÒÛÛÛëëëäääàààààààààëëëñññÛÛÛãããçççäääãããäääãããàààÙÙÙÌÌÌÅÅÅ···³³³ÑÑÑÜÜÜÕÕÕÉÉÉÇÇÇÆÆÆÇÇÇÇÇÇÎÎÎÒÒÒÌÌÌ¿¿¿¸¸¸ÃÃÃÊÊÊÍÍÍÊÊÊÀÀÀÅÅÅ¿¿¿ÀÀÀÃÃÃÃÃÃÃÃÃÃÃÃÆÆÆÇÇÇÍÍÍÇÇÇÇÇÇÍÍÍÉÉÉÀÀÀÃÃÃÍÍÍÒÒÒÐÐÐÑÑÑÕÕÕ×××ÕÕÕÕÕÕØØØÔÔÔÕÕÕÒÒÒßßßãããÝÝÝâââßßßÝÝÝÛÛÛÙÙÙÛÛÛàààèèèñññõõõîîîîîîíííèèèêêêîîîîîîèèèëëëäääßßßÉÉɳ³³µµµÆÆÆÇÇÇÇÇÇÇÇÇÉÉÉÊÊÊÎÎÎÔÔÔÛÛÛßßßßßßÝÝÝÔÔÔ¸¸¸ÅÅÅÑÑÑÜÜÜÑÑÑÎÎÎÍÍÍÊÊÊÊÊÊÆÆÆÉÉÉÒÒÒÌÌ̾¾¾Â»»»¾¾¾ÐÐÐÔÔÔÇÇǾ¾¾ºººººº»»»¼¼¼¼¼¼¾¾¾¿¿¿¿¿¿¿¿¿ÀÀÀÂÂÂÅÅÅÅÅÅÆÆÆÅÅÅÅÅÅÆÆÆÅÅÅÃÃÃÂÂÂÂÂÂÂÂÂÃÃÃÃÃÃÆÆÆÉÉÉÉÉÉÃÃÃÃÃÃÇÇÇÅÅÅÃÃÃÅÅÅ»»»ÅÅÅÍÍÍÎÎεµµ···¼¼¼ÀÀÀÇÇÇÉÉÉÅÅÅÃÃÃÆÆÆÇÇÇÑÑÑÌÌÌÅÅÅÝÝÝñññöööæææêêêùùùâââ×××ÛÛÛÒÒÒÌÌÌÍÍÍÒÒÒÙÙÙÐÐÐÆÆÆÂ¿¿¿¼¼¼»»»ÅÅÅÆÆÆÆÆÆÉÉÉÎÎÎÐÐÐÕÕÕÜÜÜæææçççäääÝÝÝâââèèèèèèßßßÕÕÕÙÙÙßßßãããççççççèèèêêêâââàààâââãããääääääææææææÛÛÛ×××àààÝÝÝÝÝÝàààÜÜÜçççêêêäääàààèèèäääæææßßßµµµÅÅÅÍÍÍÎÎÎÍÍÍÐÐÐÕÕÕÕÕÕÐÐÐÔÔÔêêêãããçççîîîäääèèèçççàààãããããããããääääääÝÝÝ×××ÐÐÐÍÍÍ¿¿¿¼¼¼ÎÎÎßßßæææÒÒÒÇÇÇÆÆÆÇÇÇÅÅÅÅÅÅÉÉÉ»»»ÃÃø¸¸ÀÀÀÅÅÅÅÅÅÆÆÆÀÀÀÃÃÃÅÅÅÆÆÆÉÉÉÉÉÉÇÇÇÇÇÇÇÇÇÉÉÉÎÎÎÊÊÊÊÊÊÍÍÍÊÊÊÆÆÆÊÊÊÔÔÔÔÔÔÑÑÑÑÑÑÔÔÔÔÔÔÐÐÐÐÐÐÒÒÒÙÙÙÜÜÜÙÙÙäääæææÝÝÝÝÝÝÙÙÙÕÕÕØØØÝÝÝäääêêêîîîîîîîîîõõõùùùöööòòòòòòõõõîîîäääÙÙÙÅÅž¾¾¾¾¾¼¼¼ÇÇÇÅÅÅÉÉÉÉÉÉÉÉÉÌÌÌÐÐÐ×××ÝÝÝâââæææäääÒÒÒºººÂÂÂÒÒÒ×××ÍÍÍÍÍÍÎÎÎÒÒÒÐÐÐÅÅÅÆÆÆÑÑÑÒÒÒÇÇÇÆÆÆ¼¼¼ºººÇÇÇÐÐÐÅÅÅ···ºººººº»»»¼¼¼¼¼¼¾¾¾¿¿¿¿¿¿¾¾¾¿¿¿ÀÀÀÂÂÂÃÃÃÃÃÃÃÃÃÅÅÅÇÇÇÆÆÆÅÅÅÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÆÆÆÆÆÆÉÉÉÅÅÅÇÇÇÇÇÇ¿¿¿ÅÅŵµµµµµÅÅÅÃÃÃÀÀÀ······³³³···¸¸¸¾¾¾¿¿¿»»»¾¾¾ÆÆÆÉÉÉÆÆÆÇÇǾ¾¾ÉÉÉäääòòòèèèçççíííßßßØØØÝÝÝÒÒÒÔÔÔÕÕÕÙÙÙÕÕÕÕÕÕÒÒÒÊÊʾ¾¾¼¼¼¼¼¼»»»ÀÀÀÆÆÆÆÆÆÉÉÉÕÕÕÜÜÜØØØÎÎÎÙÙÙäääÝÝÝääääääàààÐÐÐ×××ÜÜÜÝÝÝàààçççèèèèèèíííèèèçççäääãããâââàààßßßÜÜÜàààâââñññêêêçççîîîäääííííííæææâââäääãããæææÜÜÜ¿¿¿ÃÃÃÊÊÊÉÉÉÊÊÊÔÔÔÛÛÛØØØÔÔÔÐÐÐàààÝÝÝäääëëëâââàààÜÜÜâââààààààâââäääãããÛÛÛÑÑÑÊÊÊÇÇǸ¸¸¾¾¾ÙÙÙÝÝÝßßßÌÌÌÃÃÃÀÀÀÉÉÉÃÃÃÇÇÇÐÐÐÂÂÂÀÀÀÉÉɼ¼¼ÂÂÂÀÀÀ¾¾¾ÅÅÅÅÅÅÆÆÆÆÆÆÇÇÇÉÉÉÉÉÉÉÉÉÉÉÉÌÌÌÍÍÍÍÍÍÐÐÐÑÑÑÍÍÍÆÆÆÆÆÆÐÐÐÜÜÜ×××ÑÑÑÐÐÐÑÑÑÒÒÒÐÐÐÒÒÒ×××ÝÝÝßßßÙÙÙâââãããÜÜÜßßßÛÛÛßßßâââèèèïïïóóóòòòíííçççíííóóóóóóïïïíííêêêÛÛÛÊÊÊÇÇǺºº»»»»»»ÅÅÅ¿¿¿ÆÆÆÃÃÃÉÉÉÉÉÉÉÉÉÌÌÌÐÐÐÕÕÕÛÛÛÝÝÝäääçççÒÒÒÂÂÂÆÆÆ×××ÑÑÑÉÉÉÉÉÉÊÊÊÔÔÔÔÔÔÆÆÆÂÂÂÇÇÇÌÌÌÑÑÑÍÍÍÇÇÇÀÀÀÀÀÀÉÉÉÅÅÅ´´´ºººººº»»»¼¼¼¼¼¼¾¾¾¿¿¿¿¿¿¾¾¾¾¾¾¾¾¾¿¿¿ÀÀÀÂÂÂÃÃÃÃÃÃÇÇÇÇÇÇÆÆÆÅÅÅÅÅÅÃÃÃÃÃÃÃÃÃÆÆÆÃÃÃÉÉÉÇÇÇÊÊÊÃÃô´´¿¿¿ÎÎξ¾¾ººº±±±´´´¬¬¬¯¯¯ŸŸŸ¨¨¨¤¤¤©©©¯¯¯¯¯¯±±±³³³¬¬¬¼¼¼ÀÀÀ»»»ÉÉÉèèèóóóçççäääçççãããÜÜÜßßßÑÑÑØØØØØØÛÛÛÌÌÌÔÔÔØØØÑÑÑÌÌÌÍÍÍÎÎÎÊÊÊÆÆÆÃÃÃÇÇÇÇÇÇÅÅÅÐÐÐÙÙÙÑÑÑÎÎÎØØØèèèæææëëëâââÜÜÜÎÎÎÜÜÜâââßßßßßßæææçççäääêêêêêêçççääääääääääääâââßßßâââíííÿÿÿæææßßßïïïäääâââëëëâââßßßÝÝÝÝÝÝÜÜÜÍÍÍ¿¿¿¿¿¿ÆÆÆÅÅÅÇÇÇÒÒÒ×××ÕÕÕØØØ×××ÛÛÛØØØÜÜÜàààÝÝÝßßßÝÝÝÝÝÝßßßàààâââàààÝÝÝØØØÕÕÕÎÎο¿¿ÃÃÃÎÎÎãããââââââÔÔÔÊÊÊÃÃÃÎÎÎÆÆÆÊÊÊ×××ÅÅÅÇÇÇÎÎÎÂÂÂÇÇÇ¿¿¿ÇÇÇÉÉÉÇÇÇÂÂÂÂÂÂÃÃÃÃÃÃÅÅÅÉÉÉÍÍÍÑÑÑÌÌÌÕÕÕØØØÎÎÎÃÃÃÅÅÅÒÒÒàààØØØÒÒÒÐÐÐÑÑÑÒÒÒÔÔÔÙÙÙßßßßßßÝÝÝ×××ÝÝÝàààÜÜÜãããâââñññîîîêêêëëëïïïöööùùùüüüæææîîîñññíííèèèàààÌÌ̵µµ»»»¿¿¿ÆÆÆ¸¸¸¿¿¿»»»ÅÅÅÃÃÃÉÉÉÉÉÉÉÉÉÊÊÊÎÎÎÒÒÒ×××ØØØÍÍÍØØØÉÉÉÅÅÅÉÉÉÙÙÙÌÌÌÅÅÅÅÅÅÅÅÅÒÒÒÕÕÕÇÇǾ¾¾¼¼¼ÀÀÀÍÍÍÌÌÌÌÌÌÆÆÆ¿¿¿ÊÊÊÎÎÎÀÀÀºººººº»»»¼¼¼¼¼¼¾¾¾¿¿¿¿¿¿¾¾¾¼¼¼¼¼¼¼¼¼¾¾¾¿¿¿ÂÂÂÃÃÃÉÉÉÇÇÇÇÇÇÆÆÆÅÅÅÃÃÃÃÃÃÃÃÃÇÇÇÂÂÂÉÉÉÌÌÌÍÍÍÀÀÀªªª¸¸¸¾¾¾°°°···³³³°°°©©©ÇÇÇÕÕÕÝÝÝ×××ÛÛÛãããâââßßßÒÒÒ¾¾¾¸¸¸ººº¼¼¼×××úúúøøøääääääíííêêêàààßßßÌÌÌÕÕÕØØØÛÛÛØØØÝÝÝÜÜÜÒÒÒÒÒÒØØØÔÔÔÊÊÊÒÒÒ¿¿¿ÂÂÂÊÊÊÅÅÅÌÌÌØØØÕÕÕÙÙÙÕÕÕÜÜÜÕÕÕÜÜÜÒÒÒÜÜÜÝÝÝâââäääßßßÝÝÝæææäääâââæææèèèæææããããããääääääâââßßßâââëëëëëë¼¼¼´´´ÝÝÝäääçççæææÜÜÜÝÝÝØØØØØØÒÒÒºººµµµ¾¾¾ÅÅÅÅÅÅÇÇÇÐÐÐÐÐÐÐÐÐØØØÛÛÛØØØÙÙÙÝÝÝßßßààààààÝÝÝàààãããäääâââÛÛÛÔÔÔÒÒÒÔÔÔÊÊÊ´´´ÒÒÒäääíííãããÙÙÙÌÌÌÐÐÐÊÊÊÉÉÉÍÍÍÒÒÒÑÑÑÉÉÉ¿¿¿ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÃÃÿ¿¿ÅÅÅÍÍÍÑÑÑÒÒÒÒÒÒÑÑÑÑÑÑ×××ØØØÔÔÔÍÍÍÌÌÌÒÒÒÙÙÙÜÜÜàààÐÐÐÔÔÔÒÒÒÔÔÔÔÔÔÍÍÍÙÙÙ×××ÝÝÝâââóóóííííííæææïïïîîîïïïòòòõõõöööøøøùùùùùùñññóóóõõõíííØØØÃÃþ¾¾ÃÃÿ¿¿ÀÀÀÀÀÀ¿¿¿¾¾¾¿¿¿ÂÂÂÅÅÅÉÉÉÆÆÆÅÅÅÇÇÇÌÌÌÑÑÑÒÒÒÔÔÔÛÛÛÔÔÔÀÀÀÃÃÃÆÆÆ×××ÎÎÎÆÆÆÉÉÉÑÑÑÑÑÑÒÒÒÎÎÎÎÎÎÍÍÍ···¸¸¸ÀÀÀÐÐÐÀÀÀ¾¾¾ÔÔÔÎÎξ¾¾»»»¼¼¼¼¼¼¼¼¼»»»»»»¾¾¾¿¿¿¼¼¼¼¼¼¼¼¼¼¼¼¾¾¾ÀÀÀÃÃÃÅÅÅÉÉÉÇÇÇÆÆÆÅÅÅÃÃÃÃÃÃÅÅÅÆÆÆÆÆÆÊÊÊÆÆÆÌÌÌÔÔÔÃÃó³³»»»»»»³³³°°°­­­žžž©©©ÍÍÍÑÑÑ×××ÕÕÕÑÑÑ×××ãããÝÝÝÕÕÕÙÙÙØØØæææèèèèèèóóóõõõêêêäääëëëöööÜÜÜàààÒÒÒÔÔÔÝÝÝÕÕÕÙÙÙßßßÝÝÝÔÔÔÐÐÐÕÕÕÒÒÒÊÊÊÑÑÑÂÂÂÆÆÆÊÊÊÍÍÍÉÉÉâââÜÜÜØØØÑÑÑØØØÝÝÝØØØ×××ÝÝÝßßßâââßßßâââçççèèèææææææêêêäääàààßßßâââãããßßßßßßäääàààäääÝÝÝ»»»»»»±±±ÙÙÙÝÝÝÛÛÛ···³³³µµµ······°°°ºººÂÂÂÃÃÃÅÅÅÉÉÉÍÍÍÑÑÑÔÔÔ××××××ÙÙÙÛÛÛÝÝÝßßßàààààààààÛÛÛÝÝÝÜÜÜÕÕÕÒÒÒÔÔÔÑÑÑÌÌÌ···ºººÝÝÝâââÝÝÝæææÕÕÕÎÎÎÍÍÍÎÎÎÎÎÎÐÐÐÎÎÎÍÍÍÊÊÊÇÇÇ¿¿¿¿¿¿¿¿¿ÀÀÀÂÂÂÅÅÅÇÇÇÉÉÉÃÃÃÅÅÅÇÇÇÌÌÌÐÐÐÑÑÑÍÍÍÊÊÊØØØÙÙÙÕÕÕÍÍÍÌÌÌÑÑÑØØØÛÛÛÔÔÔÇÇÇÍÍÍÐÐÐÔÔÔÕÕÕÔÔÔààààààääääääóóóïïïõõõîîîòòòîîîîîîîîîïïïññññññïïïîîîöööîîîää䨨ØÉÉÉ»»»¸¸¸¾¾¾¿¿¿¿¿¿¿¿¿¾¾¾¾¾¾¾¾¾ÂÂÂÅÅÅÇÇÇÆÆÆÆÆÆÇÇÇÌÌÌÐÐÐÒÒÒÔÔÔÍÍÍÆÆÆºººÅÅÅÌÌÌÜÜÜÕÕÕÑÑÑÊÊÊÐÐÐÍÍÍÊÊÊÂÂÂÀÀÀÇÇǸ¸¸ÀÀÀÂÂÂÉÉɼ¼¼ÆÆÆÇÇǾ¾¾»»»¼¼¼¼¼¼¼¼¼»»»»»»¼¼¼¿¿¿¼¼¼¼¼¼¼¼¼¼¼¼¾¾¾ÀÀÀÃÃÃÅÅÅÉÉÉÇÇÇÆÆÆÅÅÅÃÃÃÃÃÃÅÅÅÆÆÆÆÆÆÉÉÉÆÆÆÍÍÍÕÕÕÆÆÆ´´´»»»Â¾¾¾´´´¬¬¬¦¦¦¾¾¾ÛÛÛÒÒÒ×××ÑÑÑÍÍÍÕÕÕãããæææãããäääãããëëëêêêêêêñññíííâââÜÜÜêêêïïïÛÛÛêêêÜÜÜÕÕÕÛÛÛÛÛÛÛÛÛßßßÜÜÜÒÒÒÐÐÐÕÕÕÕÕÕÐÐÐÊÊÊÀÀÀÇÇÇÌÌÌÎÎÎÌÌÌãããÛÛÛØØØ×××ÜÜÜÜÜÜ×××ÛÛÛâââßßßâââßßßàààãããàààÛÛÛÙÙÙÜÜÜâââãããäääæææãããÛÛÛÕÕÕÔÔÔãããäääÛÛÛ¸¸¸¸¸¸±±±ÕÕÕØØØÎÎεµµ´´´µµµ···¾¾¾¼¼¼Â¿¿¿ÂÂÂÅÅÅÉÉÉÍÍÍÑÑÑÒÒÒÔÔÔ×××ØØØÙÙÙÛÛÛÜÜÜÜÜÜÛÛÛÛÛÛàààÕÕÕÑÑÑ×××ÔÔÔÉÉÉÂÂÂÅÅÅÉÉÉÊÊÊäääâââßßßæææÕÕÕÔÔÔÔÔÔÒÒÒÑÑÑÎÎÎÍÍÍÌÌÌÍÍÍÍÍÍÐÐÐÐÐÐÐÐÐÎÎÎÍÍÍÌÌÌÊÊÊÊÊÊÎÎÎÌÌÌÉÉÉÍÍÍÔÔÔÕÕÕÐÐÐÊÊÊÙÙÙÙÙÙÕÕÕÎÎÎÍÍÍÒÒÒØØØÙÙÙÛÛÛÐÐÐÒÒÒÑÑÑÑÑÑÑÑÑÑÑÑÜÜÜæææëëëëëëóóóëëëóóóèèèãããçççæææçççíííòòòöööõõõóóóää䨨ØÌÌÌÃÃÿ¿¿¼¼¼¾¾¾¿¿¿¾¾¾¿¿¿¿¿¿¾¾¾¼¼¼¼¼¼ÀÀÀÃÃÃÆÆÆÆÆÆÉÉÉÉÉÉÊÊÊÍÍÍÐÐÐÒÒÒÃÃÃÃÃþ¾¾ÊÊÊÆÆÆÎÎÎÆÆÆÇÇÇÐÐÐÒÒÒÎÎÎÌÌ̾¾¾···¾¾¾µµµÊÊÊÆÆÆÃÃÃÅÅÅ»»»¸¸¸ÀÀÀ¿¿¿»»»¼¼¼¼¼¼»»»»»»»»»¼¼¼¿¿¿¾¾¾¼¼¼¼¼¼¼¼¼¾¾¾ÀÀÀÃÃÃÅÅÅÉÉÉÇÇÇÆÆÆÅÅÅÃÃÃÃÃÃÅÅÅÆÆÆÅÅÅÇÇÇÆÆÆÎÎÎÙÙÙÉÉÉ···»»»»»»ÀÀÀµµµªªª­­­ÊÊÊàààÎÎÎÑÑÑÐÐÐØØØâââäääãããâââÝÝÝêêêèèèçççêêêîîîçççÜÜÜÜÜÜÜÜÜãããÕÕÕçççÜÜÜÒÒÒÕÕÕ×××ÔÔÔÛÛÛßßßÛÛÛÙÙÙÛÛÛÕÕÕÌÌÌÃÃÃÃÃÃÍÍÍÎÎÎÑÑÑÎÎÎää䨨ØÛÛÛÝÝÝàààÜÜÜØØØÝÝÝâââÛÛÛãããâââââââââßßßÝÝÝàààæææÛÛÛÝÝÝàààßßßØØØÔÔÔÒÒÒÐÐÐäääâââØØØµµµ´´´¯¯¯ÊÊÊÊÊʰ°°¨¨¨°°°´´´···ÀÀÀ¿¿¿»»»¾¾¾ÀÀÀÅÅÅÉÉÉÍÍÍÐÐÐÐÐÐÑÑÑÕÕÕÕÕÕ××××××××××××ÕÕÕÕÕÕ×××ÒÒÒÒÒÒÒÒÒÇÇǼ¼¼ÃÃÃÔÔÔÕÕÕØØØæææàààãããêêêÝÝÝäääãããÙÙÙÎÎÎÉÉÉÌÌÌÐÐÐÎÎÎÌÌÌÉÉÉÌÌÌÐÐÐÒÒÒÒÒÒÐÐÐÌÌÌÉÉÉÑÑÑÎÎÎÌÌÌÎÎÎÒÒÒÔÔÔÑÑÑÍÍÍ×××ØØØÕÕÕÐÐÐÎÎÎÕÕÕÙÙÙÙÙÙÙÙÙÒÒÒÑÑÑÑÑÑÒÒÒÔÔÔÙÙÙäääãããîîîññññññÝÝÝàààÔÔÔÉÉÉÂÂÂÃÃÃÇÇÇÒÒÒßßßèèèëëëëëëÊÊÊÅÅÅÀÀÀ¿¿¿ÀÀÀÂÂÂÀÀÀÀÀÀ¿¿¿¿¿¿¿¿¿¾¾¾¼¼¼¼¼¼¿¿¿ÂÂÂÃÃÃÆÆÆÊÊÊÊÊÊÊÊÊÌÌÌÍÍÍÐÐи¸¸¼¼¼ºººÆÆÆÇÇÇÔÔÔÍÍÍÊÊÊ××××××ÔÔÔ×××ÉÉÉ»»»»»»¯¯¯ÊÊÊÊÊÊÃÃÃÆÆÆººº³³³ÀÀÀ¾¾¾ººº»»»¼¼¼»»»ºººººº¼¼¼¿¿¿¾¾¾¾¾¾¾¾¾¾¾¾¿¿¿ÂÂÂÅÅÅÆÆÆÉÉÉÇÇÇÆÆÆÃÃÃÃÃÃÃÃÃÅÅÅÅÅÅÂÂÂÆÆÆÅÅÅÐÐÐÛÛÛÌÌ̺ºº¾¾¾¨¨¨¸¸¸³³³©©©¬¬¬ÂÂÂ×××ÌÌÌØØØÕÕÕÜÜÜÝÝÝÔÔÔÕÕÕßßßàààãããÝÝÝÝÝÝçççíííæææâââæææÝÝÝêêêâââíííããããããâââÝÝÝÑÑÑØØØÜÜÜÙÙÙØØØ×××ÐÐÐÇÇÇÆÆÆÊÊÊÔÔÔÑÑÑÒÒÒÐÐÐää䨨ØÝÝÝßßßàààßßßÜÜÜÛÛÛÙÙÙ×××ÕÕÕÙÙÙßßßâââßßßÜÜÜÛÛÛÜÜÜàààßßßßßß×××ÍÍÍÐÐÐÕÕÕÕÕÕÜÜÜØØØÍÍͬ¬¬¨¨¨¤¤¤³³³°°°­­­¥¥¥¦¦¦©©©ªªªµµµÀÀÀÃÃþ¾¾¿¿¿ÂÂÂÆÆÆÉÉÉÌÌÌÎÎÎÐÐÐÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÍÍÍÕÕÕÒÒÒÃÃû»»ÆÆÆÛÛÛçççÝÝÝàààæææßßßæææëëëàààëëëëëëßßßÑÑÑÊÊÊÊÊÊÍÍÍÎÎÎÍÍÍÉÉÉÌÌÌÍÍÍÎÎÎÎÎÎÌÌÌÉÉÉÆÆÆÉÉÉÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÌÌÌÌÌÌÑÑÑÔÔÔÒÒÒÑÑÑÒÒÒÙÙÙÜÜÜÛÛÛØØØÒÒÒÌÌÌÍÍÍÐÐÐÔÔÔßßßæææàààîîîòòòêêêÉÉÉÌÌÌÇÇÇÀÀÀÌÌÌÇÇÇÅÅÅÆÆÆÉÉÉÉÉÉÅÅÅÀÀÀÅÅÅÇÇÇÉÉÉÇÇÇÃÃÃÀÀÀ¾¾¾¼¼¼ÀÀÀÀÀÀÀÀÀ¾¾¾¼¼¼¼¼¼¿¿¿ÂÂÂÃÃÃÆÆÆÊÊÊÌÌÌÊÊÊÊÊÊÌÌÌÍÍÍÃÃÃÅÅŸ¸¸¾¾¾ÃÃÃÛÛÛ×××ÎÎÎÕÕÕÑÑÑÍÍÍÔÔÔÎÎÎÅÅű±±ÃÃÃÌÌÌÇÇÇÆÆÆ»»»ºººÆÆÆ»»»ººº»»»¼¼¼»»»ºººººº¼¼¼¾¾¾¿¿¿¾¾¾¾¾¾¾¾¾ÀÀÀÂÂÂÅÅÅÆÆÆÇÇÇÆÆÆÅÅÅÂÂÂÂÂÂÂÂÂÃÃÃÃÃÃÀÀÀÅÅÅÅÅÅÎÎÎÛÛÛÍÍͼ¼¼Â¢¢¢···µµµ­­­©©©±±±ÊÊÊÕÕÕÛÛÛÕÕÕØØØ×××ÐÐÐ×××âââàààØØØÑÑÑÕÕÕäääêêêæææçççïïïÛÛÛâââÙÙÙäääÝÝÝàààÝÝÝÜÜÜÒÒÒÑÑÑÌÌÌÅÅÅÂÂÂÃÃÃÆÆÆÅÅÅÎÎÎÔÔÔÙÙÙÒÒÒÔÔÔÐÐÐâââØØØÙÙÙÕÕÕ×××àààâââÙÙÙ×××ÜÜÜàààêêêõõõùùùóóóçççÛÛÛÑÑÑÐÐÐÎÎÎÔÔÔÕÕÕÍÍÍÑÑÑÛÛÛÛÛÛàààÛÛÛÑÑÑ´´´¬¬¬©©©­­­¨¨¨±±±¨¨¨¨¨¨°°°¯¯¯°°°¾¾¾ÆÆÆ¿¿¿¿¿¿¿¿¿ÀÀÀÃÃÃÉÉÉÍÍÍÐÐÐÑÑÑÑÑÑÑÑÑÒÒÒÒÒÒÔÔÔÔÔÔÕÕÕÑÑÑÕÕÕÊÊʸ¸¸¼¼¼ÔÔÔäääâââèèèèèèçççâââçççæææÛÛÛäääæææãããÛÛÛÑÑÑÉÉÉÇÇÇÌÌÌÐÐÐÔÔÔÑÑÑÎÎÎÌÌÌÊÊÊÉÉÉÉÉÉÉÉÉÊÊÊÍÍÍÎÎÎÎÎÎÌÌÌÊÊÊÍÍÍÎÎÎÍÍÍÑÑÑÒÒÒÔÔÔØØØÜÜÜÝÝÝÙÙÙØØØÔÔÔÉÉÉÊÊÊÎÎÎÑÑÑÜÜÜÝÝÝâââîîîïïïããã¾¾¾ÅÅÅÌÌÌÍÍÍÑÑÑÎÎÎÍÍÍÎÎÎÑÑÑÑÑÑÎÎÎÌÌÌÉÉÉÎÎÎÐÐÐÊÊÊÃÃÃÀÀÀÀÀÀÀÀÀÂÂÂÃÃÃÂÂÂÀÀÀ¾¾¾¾¾¾ÀÀÀÃÃÃÃÃÃÆÆÆÊÊÊÌÌÌÌÌÌÊÊÊÉÉÉÉÉÉÎÎÎÒÒÒÆÆÆ¿¿¿±±±¾¾¾¿¿¿ÃÃÃÇÇÇ»»»ÃÃÃÆÆÆÇÇÇÌÌ̼¼¼»»»ÇÇÇÊÊÊÃÃü¼¼ÃÃÃÇÇǸ¸¸ººº»»»»»»»»»ºººººº»»»¾¾¾¿¿¿¿¿¿¿¿¿¿¿¿ÀÀÀÃÃÃÆÆÆÇÇÇÆÆÆÅÅÅÃÃÃÀÀÀÀÀÀÀÀÀ¿¿¿ÅÅÅÃÃÃÌÌÌ×××ÌÌÌ¿¿¿ÉÉɰ°°Â»»»³³³¬¬¬©©©ÂÂÂÙÙÙØØØÕÕÕÕÕÕØØØÙÙÙÝÝÝÙÙÙÐÐÐÒÒÒÍÍÍÕÕÕâââãããàààçççîîîíííãããÛÛÛîîîêêêçççàààèèèêêêçççâââÜÜÜÙÙÙÙÙÙÛÛÛÛÛÛ×××ÙÙÙÙÙÙÒÒÒÕÕÕÍÍÍÜÜÜÕÕÕÑÑÑÊÊÊÌÌÌÛÛÛäääÜÜÜÛÛÛèèèäääêêêëëëêêêçççâââÙÙÙÑÑÑÒÒÒÎÎÎÛÛÛæææÝÝÝÜÜÜâââÝÝÝâââÝÝÝ×××»»»±±±±±±¯¯¯ªªª¨¨¨¥¥¥©©©¸¸¸´´´­­­µµµµµµ¿¿¿¾¾¾¼¼¼¾¾¾ÀÀÀÅÅÅÊÊÊÎÎÎÐÐÐÐÐÐÐÐÐÐÐÐÑÑÑÒÒÒÔÔÔÔÔÔÒÒÒÒÒÒÊÊÊÀÀÀ¿¿¿ÉÉÉÕÕÕÛÛÛèèèçççææææææèèèäääßßßãããßßßàààÝÝÝØØØÐÐÐÊÊÊÊÊÊÍÍÍÅÅÅÆÆÆÉÉÉÌÌÌÎÎÎÑÑÑÒÒÒÒÒÒÕÕÕÔÔÔÔÔÔÔÔÔÔÔÔÒÒÒÐÐÐÎÎÎÌÌÌÐÐÐÔÔÔ×××ÛÛÛßßßÛÛÛÕÕÕÔÔÔÒÒÒÉÉÉÐÐÐ×××ÙÙÙâââÜÜÜäääêêêíííæææÀÀÀÉÉÉÒÒÒÔÔÔÒÒÒÒÒÒÒÒÒÒÒÒÔÔÔÒÒÒÑÑÑÐÐÐÊÊÊÍÍÍÍÍÍÉÉÉÆÆÆÇÇÇÉÉÉÆÆÆÅÅÅÅÅÅÅÅÅÂÂÂÀÀÀÀÀÀÂÂÂÅÅÅÅÅÅÆÆÆÉÉÉÌÌÌÍÍÍÌÌÌÇÇÇÅÅÅÅÅÅÌÌÌÌÌÌÎÎθ¸¸±±±¯¯¯¼¼¼¸¸¸¸¸¸³³³···»»»ÅÅÅÐÐи¸¸¿¿¿ÉÉɼ¼¼ÇÇÇÅÅŸ¸¸ººº»»»»»»ººººººººº»»»¾¾¾ÀÀÀ¿¿¿¿¿¿¿¿¿ÀÀÀÃÃÃÆÆÆÇÇÇÅÅÅÃÃÃÀÀÀ¿¿¿¿¿¿¿¿¿ÀÀÀÀÀÀ¾¾¾ÅÅÅÃÃÃÉÉÉÒÒÒÇÇÇÀÀÀÐÐкººÉÉɼ¼¼´´´´´´¬¬¬³³³ÀÀÀÌÌÌÒÒÒÒÒÒÑÑÑÔÔÔÔÔÔÐÐÐÍÍÍÎÎÎÍÍÍØØØâââÜÜÜÛÛÛãããèèèëëëÜÜÜÒÒÒæææääääääÙÙÙâââßßßàààââââââàààÛÛÛ×××ÒÒÒÙÙÙØØØÕÕÕÑÑÑØØØÊÊÊÕÕÕÒÒÒÐÐÐÌÌÌÉÉÉÒÒÒàààßßßâââïïïëëëèèèäääàààãããêêêíííêêêíííÛÛÛßßßæææÙÙÙÒÒÒÙÙÙÙÙÙÔÔÔÐÐÐÊÊʰ°°¦¦¦ªªª¨¨¨¨¨¨©©©¨¨¨¤¤¤ªªª¦¦¦¨¨¨¸¸¸µµµ¼¼¼¼¼¼»»»¼¼¼¿¿¿ÃÃÃÇÇÇÊÊÊÑÑÑÐÐÐÎÎÎÎÎÎÎÎÎÎÎÎÐÐÐÑÑÑÍÍÍÎÎÎÐÐÐÊÊÊ¿¿¿»»»ÍÍÍãããêêêääääääëëëëëëèèèèèèæææÜÜÜÛÛÛÙÙÙÙÙÙØØØÔÔÔÌÌÌÆÆÆÌÌÌÑÑÑØØØßßßâââßßßÛÛÛØØØØØØÔÔÔÐÐÐÑÑÑÔÔÔÒÒÒÌÌÌÅÅÅÌÌÌÑÑÑÕÕÕØØØÜÜÜßßßÙÙÙÑÑÑããããããÕÕÕÛÛÛÝÝÝÙÙÙÜÜÜÐÐÐãããæææëëëëëëÊÊÊÎÎÎÒÒÒÐÐÐÕÕÕÕÕÕÕÕÕÔÔÔÒÒÒÑÑÑÐÐÐÎÎÎÌÌÌÎÎÎÍÍÍÉÉÉÉÉÉÌÌÌÉÉÉÂÂÂÆÆÆÆÆÆÆÆÆÃÃÃÂÂÂÀÀÀÃÃÃÆÆÆÅÅÅÆÆÆÇÇÇÊÊÊÍÍÍÌÌÌÇÇÇÃÃÃÌÌÌÆÆÆÊÊÊãããÙÙÙÆÆÆ¯¯¯±±±°°°···µµµ······ÂÂÂÎÎκºº¸¸¸ÆÆÆ¿¿¿¼¼¼ÇÇÇÀÀÀ¸¸¸ºººººº»»»ººº¸¸¸ººº»»»¾¾¾ÀÀÀÀÀÀ¿¿¿ÀÀÀÂÂÂÃÃÃÆÆÆÇÇÇÃÃÃÂÂÂÀÀÀ¿¿¿¾¾¾¾¾¾¿¿¿¿¿¿¾¾¾ÅÅÅÂÂÂÇÇÇÐÐÐÆÆÆÂÂÂÔÔÔ···ÇÇǸ¸¸´´´»»»¯¯¯¢¢¢ŸŸŸ¤¤¤ÂÂÂÔÔÔÕÕÕÕÕÕÍÍÍÆÆÆÌÌÌÌÌÌÍÍÍÙÙÙàààØØØØØØâââäääëëëâââØØØããããããëëëÝÝÝÜÜÜàààààààààâââàààÜÜÜÙÙÙØØØØØØÔÔÔÑÑÑÑÑÑÙÙÙÉÉÉÑÑÑÐÐÐÔÔÔÒÒÒÌÌÌÍÍÍÛÛÛàààäääïïïÝÝÝÝÝÝÜÜÜÜÜÜãããëëëëëëäääÕÕÕ···°°°···¯¯¯³³³ÉÉÉÔÔÔÕÕÕÐÐÐÊÊʱ±±¨¨¨±±±¯¯¯´´´©©©¯¯¯©©©ªªª¨¨¨°°°Â···ººº»»»»»»¾¾¾ÀÀÀÃÃÃÆÆÆÇÇÇÑÑÑÐÐÐÎÎÎÌÌÌÌÌÌÌÌÌÌÌÌÍÍÍÌÌÌÊÊÊÊÊÊÇÇÇÀÀÀÂÂÂÕÕÕíííóóóêêêêêêñññëëëçççêêêãããæææÜÜÜàààãããÙÙÙ×××ÛÛÛÛÛÛÙÙÙ×××ÕÕÕ×××ÙÙÙÜÜÜÜÜÜÛÛÛâââÝÝÝÔÔÔÔÔÔÛÛÛÔÔÔÎÎÎÕÕÕÙÙÙÙÙÙÝÝÝÜÜÜÙÙÙßßßãããÝÝÝÌÌÌÎÎÎÑÑÑÒÒÒÙÙÙßßßÝÝÝ×××àààæææñññçççÉÉÉÒÒÒÊÊÊÎÎÎÐÐÐÑÑÑÔÔÔÔÔÔÔÔÔÑÑÑÎÎÎÌÌÌÍÍÍÔÔÔÍÍÍÍÍÍÌÌÌÉÉÉÐÐÐÃÃÃÀÀÀÆÆÆÉÉÉÆÆÆÃÃÃÆÆÆÉÉÉÆÆÆÅÅÅÅÅÅÆÆÆÆÆÆÆÆÆÆÆÆÅÅÅÅÅÅÅÅÅÐÐÐÌÌÌÉÉÉÆÆÆÌÌÌÍÍͪªª±±±¬¬¬±±±°°°´´´»»»ºººÂ¿¿¿°°°»»»ÀÀÀµµµÇÇÇ»»»»»»ººººººººººººººº»»»¼¼¼¾¾¾ÀÀÀÀÀÀ¿¿¿ÀÀÀÀÀÀÃÃÃÅÅÅÆÆÆÃÃÃÂÂÂÀÀÀ¾¾¾¾¾¾¾¾¾¿¿¿¿¿¿ÂÂÂÂÂÂÀÀÀÃÃÃÅÅÅÜÜÜÎÎÎÆÆÆ¸¸¸ÍÍÍÃÃþ¾¾°°°¯¯¯¿¿¿¤¤¤¥¥¥¿¿¿ÑÑÑÕÕÕÕÕÕÍÍÍÎÎÎÝÝÝÝÝÝâââÝÝÝÕÕÕ×××âââäääàààäääëëëÛÛÛÙÙÙßßßÝÝÝâââÝÝÝßßß×××ßßßæææÜÜÜ×××ØØØ×××ÙÙÙÎÎÎÕÕÕÙÙÙÎÎÎÐÐÐÛÛÛØØØÑÑÑÌÌÌÐÐÐæææÛÛÛßßßãããíííÜÜܸ¸¸±±±¼¼¼ÀÀÀÑÑÑÒÒÒ´´´¼¼¼¿¿¿Â¾¾¾µµµ¬¬¬¦¦¦ÐÐÐÀÀÀ°°°ªªª±±±···µµµ°°°°°°°°°°°°´´´¸¸¸ºººººº···¸¸¸¸¸¸ººº¼¼¼¿¿¿ÃÃÃÇÇÇÉÉÉÌÌÌÌÌÌÊÊÊÊÊÊÉÉÉÇÇÇÉÉÉÉÉÉÇÇÇÊÊÊÊÊÊÀÀÀºººÃÃÃÜÜÜòòòñññíííêêêêêêíííëëëçççãããâââÜÜÜãããçççßßßÙÙÙÙÙÙ×××ÛÛÛÙÙÙØØØÙÙÙÜÜÜÝÝÝÜÜÜÛÛÛßßßÛÛÛÒÒÒÒÒÒØØØÕÕÕÔÔÔÛÛÛÙÙÙÙÙÙÝÝÝÜÜÜØØØÝÝÝâââÜÜÜÕÕÕØØØØØØÕÕÕØØØÜÜÜÛÛÛ×××ÝÝÝæææòòòãããÌÌÌÐÐÐÊÊÊÇÇÇÎÎÎÐÐÐÒÒÒÒÒÒÑÑÑÎÎÎÌÌÌÉÉÉÉÉÉÎÎÎÇÇÇÉÉÉÊÊÊÇÇÇÍÍÍÃÃÿ¿¿¿¿¿ÀÀÀÅÅÅÉÉÉÊÊÊÉÉÉÆÆÆÇÇÇÉÉÉÊÊÊÊÊÊÉÉÉÇÇÇÆÆÆÆÆÆÌÌÌÌÌÌÎÎÎÊÊÊÎÎÎÜÜÜÔÔÔÀÀÀ°°°°°°°°°±±±´´´ºººÐÐл»»°°°¾¾¾ÂµµµÍÍÍ¿¿¿»»»ºººººººººººº»»»»»»¼¼¼¾¾¾ÀÀÀÀÀÀÀÀÀÂÂÂÃÃÃÃÃÃÅÅÅÅÅÅÂÂÂÀÀÀ¿¿¿¼¼¼¼¼¼¼¼¼¾¾¾¾¾¾¿¿¿ÂÂÂÂÂÂÅÅÅÆÆÆÙÙÙÇÇÇÀÀÀ¾¾¾¾¾¾»»»¿¿¿¸¸¸´´´ººº¯¯¯ªªªµµµÂÂÂÎÎÎ××××××ÑÑÑÑÑÑàààßßß×××ÍÍÍÐÐÐÜÜÜçççêêêèèèîîîßßßÛÛÛàààßßßãããßßßñññäääÝÝÝÝÝÝÜÜÜÝÝÝàààßßßÜÜÜØØØæææëëëÙÙÙÑÑÑ×××ÒÒÒÔÔÔ×××ÜÜÜÜÜÜÛÛÛóóóêêêäää¾¾¾´´´¼¼¼¿¿¿±±±···ÀÀÀ¸¸¸ÀÀÀÂÂÂÃÃþ¾¾¸¸¸³³³¯¯¯°°°­­­¬¬¬¯¯¯´´´¸¸¸¸¸¸···¸¸¸······ººº¼¼¼¾¾¾¼¼¼ºººººººººººº¼¼¼¾¾¾ÂÂÂÅÅÅÆÆÆÊÊÊÉÉÉÉÉÉÇÇÇÆÆÆÅÅÅÅÅÅÆÆÆÃÃÃÆÆÆÃÃü¼¼ÅÅÅØØØèèèîîîíííëëëèèèêêêëëëëëëçççäääâââßßßäääçççàààÛÛÛÛÛÛØØØÜÜÜÜÜÜÛÛÛÜÜÜÝÝÝÝÝÝÜÜÜÛÛÛÛÛÛØØØÒÒÒÑÑÑ××××××ÙÙÙàààÛÛÛÙÙÙÝÝÝÝÝÝÙÙÙÝÝÝßßßØØØÊÊÊÐÐÐÑÑÑÐÐÐÒÒÒØØØÜÜÜÜÜÜàààèèèòòòØØØÇÇÇÉÉÉÌÌÌÆÆÆÍÍÍÎÎÎÑÑÑÑÑÑÐÐÐÍÍÍÉÉÉÆÆÆÆÆÆÊÊÊÃÃÃÅÅÅÆÆÆÃÃÃÅÅÅ¿¿¿ÊÊÊÃÃû»»¼¼¼ÅÅÅÊÊÊÉÉÉÉÉÉÇÇÇÉÉÉÌÌÌÍÍÍÍÍÍÌÌÌÉÉÉÇÇÇÉÉÉÆÆÆÅÅÅÍÍÍÉÉÉÅÅÅÔÔÔÛÛÛÒÒÒ´´´­­­±±±µµµ´´´¸¸¸ÐÐл»»³³³¿¿¿Â···ÎÎλ»»»»»»»»ººº»»»»»»¼¼¼¾¾¾¿¿¿ÀÀÀÀÀÀÃÃÃÅÅÅÆÆÆÅÅÅÅÅÅÃÃÃÀÀÀ¿¿¿¾¾¾»»»»»»»»»¼¼¼¼¼¼¾¾¾ÀÀÀÀÀÀÆÆÆÆÆÆÕÕÕÀÀÀ»»»ÐÐл»»ºººÀÀÀÀÀÀ»»»³³³´´´¬¬¬¥¥¥¨¨¨³³³ÂÂÂÒÒÒÝÝÝÜÜÜÙÙÙÛÛÛÙÙÙØØØÜÜÜäääêêêíííæææêêêÙÙÙÔÔÔÛÛÛÛÛÛÜÜÜÙÙÙíííäää×××ÔÔÔàààëëëííííííàààÜÜÜäääãããÐÐÐÉÉÉÒÒÒ×××ÑÑÑÕÕÕàààÙÙÙÙÙÙäää¿¿¿µµµÂÂÂÂÂÂÊÊÊÌÌÌÂÂÂÂÂÂÆÆÆÅÅÅÇÇÇÆÆÆÅÅÅÃÃÿ¿¿¼¼¼¸¸¸···¥¥¥ªªª±±±´´´³³³³³³µµµººº¼¼¼¼¼¼¼¼¼¼¼¼¾¾¾¾¾¾»»»ººººººººº»»»»»»¼¼¼¿¿¿ÀÀÀÂÂÂÇÇÇÆÆÆÆÆÆÅÅÅÅÅÅÃÃÃÃÃÿ¿¿¼¼¼ÅÅÅ×××êêêïïïíííæææçççèèèêêêëëëêêêçççæææäääâââàààßßßÙÙÙØØØÛÛÛÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÛÛÛÙÙÙØØØ×××ÔÔÔÒÒÒÔÔÔ×××ÛÛÛàààÙÙÙÙÙÙßßßàààÜÜÜßßßÝÝÝÒÒÒÎÎÎÔÔÔ×××ÔÔÔÑÑÑÒÒÒ××××××èèèîîîíííÊÊÊÂÂÂÃÃÃÐÐÐÌÌÌÍÍÍÎÎÎÑÑÑÒÒÒÑÑÑÍÍÍÉÉÉÅÅÅÇÇÇÇÇÇÀÀÀÀÀÀÃÃþ¾¾»»»¼¼¼ØØØÕÕÕÆÆÆ»»»ÀÀÀÇÇÇÆÆÆÂÂÂÇÇÇÉÉÉÌÌÌÍÍÍÍÍÍÌÌÌÉÉÉÇÇÇÊÊÊÂÂÂÀÀÀÊÊÊÊÊÊÂÂÂÃÃÃÆÆÆ××׸¸¸°°°´´´»»»¸¸¸³³³¿¿¿ÇÇÇ···¿¿¿ÀÀÀ´´´ÊÊÊ¿¿¿¿¿¿»»»»»»»»»»»»¼¼¼¼¼¼¾¾¾¿¿¿ÀÀÀÂÂÂÅÅÅÇÇÇÇÇÇÆÆÆÅÅÅÃÃÃÂÂÂÀÀÀ¾¾¾¼¼¼»»»¼¼¼¼¼¼¾¾¾¼¼¼ÀÀÀÀÀÀÅÅÅÆÆÆÔÔÔ¿¿¿¾¾¾ÕÕÕÃÃü¼¼¼¼¼ÂÂÂÃÃþ¾¾»»»¿¿¿±±±¬¬¬©©©¦¦¦´´´ÇÇÇÊÊÊÛÛÛÛÛÛÙÙÙ×××ØØØÝÝÝæææêêêãããäääÙÙÙÑÑÑØØØÛÛÛÛÛÛÙÙÙæææèèèÜÜÜ×××äääëëëäääâââëëëããããããßßßÒÒÒÒÒÒàààèèèÜÜÜØØØàààââââââÕÕÕºººÇÇÇÉÉÉÇÇÇÇÇÇÉÉÉÍÍÍÍÍÍÇÇÇÅÅÅÌÌÌÊÊÊÇÇÇÅÅž¾¾»»»ººº³³³···ººº···±±±°°°···¾¾¾ººººººººº»»»»»»ººº¸¸¸¸¸¸»»»»»»»»»¼¼¼¼¼¼¾¾¾¾¾¾¾¾¾ÃÃÃÃÃÃÃÃÃÃÃÃÅÅÅÅÅÅÃÃÃÂÂÂÀÀÀ¼¼¼ÅÅÅÙÙÙèèèëëëëëëîîîâââäääçççêêêêêêèèèçççæææàààâââßßßÙÙÙ××××××ØØØÛÛÛÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙØØØØØØØØØØØØØØØØØØÔÔÔÑÑÑÔÔÔÙÙÙÜÜÜØØØÙÙÙàààãããààààààÜÜÜÎÎÎÒÒÒÛÛÛàààÝÝÝÙÙÙÛÛÛÜÜÜÜÜÜëëëîîîãããÃÃÃÂÂÂÃÃÃÑÑÑÍÍÍÍÍÍÐÐÐÒÒÒÔÔÔÒÒÒÐÐÐÊÊÊÇÇÇÅÅž¾¾¼¼¼ÀÀÀ»»»···ÃÃÃÝÝÝäääÒÒÒ»»»¼¼¼ÆÆÆÅÅÅÀÀÀÆÆÆÇÇÇÉÉÉÊÊÊÊÊÊÉÉÉÇÇÇÆÆÆÇÇÇÆÆÆÊÊÊÍÍÍÎÎÎÌÌÌÆÆÆÆÆÆÍÍÍ¿¿¿¼¼¼µµµ´´´···±±±···ÔÔÔ»»»¾¾¾¿¿¿°°°Â»»»Â»»»»»»»»»»»»¼¼¼¼¼¼¾¾¾¿¿¿ÀÀÀÃÃÃÆÆÆÉÉÉÉÉÉÆÆÆÃÃÃÂÂÂÃÃÿ¿¿¾¾¾¾¾¾¾¾¾¾¾¾¿¿¿¼¼¼Â¿¿¿ÃÃÃÇÇÇÔÔÔÂÂÂÆÆÆÅÅÅÉÉÉ»»»³³³ºººÉÉÉÎÎÎÃÃÃÆÆÆ¾¾¾¾¾¾¸¸¸ªªª©©©¯¯¯¬¬¬ØØØÝÝÝßßßÝÝÝÜÜÜàààããããããæææçççààà×××ÜÜÜàààßßßâââÝÝÝèèèäääÝÝÝäääæææßßßßßßäääßßßàààãããßßßÝÝÝâââãããÜÜÜâââæææäääÝÝÝÅÅž¾¾ÐÐÐÅÅÅÉÉÉÉÉÉÇÇÇÉÉÉÆÆÆÅÅÅÉÉÉÌÌÌÌÌÌÊÊÊÇÇÇÅÅÅ¿¿¿»»»¸¸¸ººº»»»ººº···µµµ···¼¼¼ÀÀÀ···¸¸¸ººº»»»»»»»»»»»»»»»¾¾¾¾¾¾¾¾¾¾¾¾¼¼¼¼¼¼¼¼¼¼¼¼ÂÂÂÀÀÀÀÀÀÃÃÃÇÇÇÇÇÇÆÆÆÅÅż¼¼ÇÇÇÜÜÜííííííæææäääëëëâââäääçççêêêêêêèèèçççæææÛÛÛàààßßßÛÛÛÙÙÙØØØÔÔÔÕÕÕ×××ØØØØØØ×××ÕÕÕÕÕÕØØØÙÙÙÙÙÙÙÙÙÙÙÙÔÔÔÌÌÌÐÐÐØØØÙÙÙÙÙÙÙÙÙàààãããàààâââÝÝÝÐÐÐÍÍÍ×××ÝÝÝÝÝÝÝÝÝàààããããããæææççç×××ÅÅÅÆÆÆÆÆÆÍÍÍÉÉÉÍÍÍÐÐÐÔÔÔÕÕÕÕÕÕÑÑÑÍÍÍÉÉÉÀÀÀ¾¾¾¼¼¼»»»ÀÀÀ»»»ºººÑÑÑÙÙÙãããÐÐз··»»»ÅÅÅÅÅÅÅÅÅÆÆÆÆÆÆÇÇÇÇÇÇÇÇÇÇÇÇÆÆÆÆÆÆÆÆÆÍÍÍÔÔÔÎÎÎÌÌÌÌÌÌÆÆÆÌÌÌÃÃÃÇÇÇÌÌ̸¸¸­­­´´´···¿¿¿ÔÔÔ¼¼¼¼¼¼¼¼¼­­­ÀÀÀ»»»ÀÀÀ»»»»»»ººº»»»»»»¼¼¼¾¾¾¿¿¿ÀÀÀÃÃÃÆÆÆÇÇÇÇÇÇÆÆÆÃÃÃÀÀÀÃÃÃÂÂÂÀÀÀ¿¿¿¾¾¾¾¾¾¿¿¿¿¿¿¼¼¼Â¼¼¼ÀÀÀÇÇÇÔÔÔÃÃÃÎÎλ»»ÌḬ̀°°±±±ÀÀÀÉÉÉÂÂÂÀÀÀ»»»¼¼¼¾¾¾»»»ºººµµµ­­­ºººÇÇÇÒÒÒÕÕÕÙÙÙâââäääâââàààäääãããØØØÙÙÙÝÝÝÙÙÙàààÛÛÛâââãããàààâââããããããçççàààÙÙÙÙÙÙßßßàààÝÝÝÝÝÝÝÝÝëëëÿÿÿÿÿÿæææ×××ÉÉÉÉÉÉÃÃÃÉÉÉÍÍÍÍÍÍÌÌÌÊÊÊÉÉÉÊÊÊÎÎÎÌÌÌÌÌÌÌÌÌÊÊÊÇÇǾ¾¾»»»¼¼¼»»»ººº»»»»»»»»»ººº¸¸¸¸¸¸»»»¾¾¾¿¿¿¿¿¿¿¿¿¿¿¿ÀÀÀ¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¾¾¾¼¼¼¼¼¼ÀÀÀ¿¿¿ÀÀÀÃÃÃÇÇÇÉÉÉÇÇÇÃÃ÷··×××ññññññèèèçççèèèçççæææçççèèèêêêëëëêêêçççæææÙÙÙãããàààÙÙÙÛÛÛÙÙÙÕÕÕ××××××××××××ÕÕÕÔÔÔÕÕÕÙÙÙÝÝÝÛÛÛÙÙÙÙÙÙÐÐÐÅÅÅÌÌÌÙÙÙÛÛÛÝÝÝÛÛÛßßßàààßßßãããàààÔÔÔÒÒÒÙÙÙÝÝÝÛÛÛØØØÛÛÛÜÜÜÛÛÛâââàààÆÆÆÂÂÂÅÅÅÆÆÆÇÇÇÆÆÆÊÊÊÍÍÍÒÒÒÕÕÕÕÕÕÒÒÒÍÍÍÊÊÊÅÅÅÀÀÀÀÀÀ»»»¿¿¿ººº···ØØØ×××ÕÕÕ¿¿¿±±±¼¼¼ÀÀÀ¿¿¿ÇÇÇÇÇÇÆÆÆÆÆÆÅÅÅÅÅÅÆÆÆÆÆÆÇÇÇÊÊÊÍÍÍÕÕÕÎÎÎÐÐÐÍÍÍ¿¿¿ÇÇÇÂÂÂÉÉÉÎÎξ¾¾µµµ¿¿¿ÀÀÀÆÆÆÅÅŸ¸¸¿¿¿ººº¬¬¬ÉÉÉÀÀÀ»»»ºººººººººººº»»»»»»¼¼¼¾¾¾ÂÂÂÃÃÃÆÆÆÆÆÆÆÆÆÅÅÅÃÃÃÀÀÀÂÂÂÀÀÀ¿¿¿¾¾¾¼¼¼¼¼¼¾¾¾¿¿¿»»»Â»»»ÀÀÀÇÇÇÒÒÒÂÂÂÐÐо¾¾ÌÌÌÎÎλ»»³³³µµµ···ÆÆÆÉÉÉÃÃúººµµµ»»»»»»µµµ´´´¨¨¨µµµººº±±±¸¸¸ÐÐÐààààààÜÜÜàààäääÕÕÕÒÒÒÕÕÕÎÎÎÙÙÙãããßßßààààààÛÛÛØØØÜÜÜÝÝÝæææàààÜÜÜÜÜÜÝÝÝßßßäääíííæææÝÝÝÛÛÛ¿¿¿¾¾¾ÅÅÅÍÍÍÆÆÆÌÌÌÉÉÉÉÉÉÌÌÌÊÊÊÌÌÌÌÌÌÇÇÇÊÊÊÌÌÌÌÌÌÌÌÌÊÊÊÇÇÇÃÃÃÂÂÂÂÂÂÀÀÀ¿¿¿¾¾¾¼¼¼»»»¸¸¸···»»»¾¾¾ÀÀÀÀÀÀÀÀÀÀÀÀÂÂÂÃÃÃÀÀÀÀÀÀÂÂÂÂÂÂÀÀÀ¿¿¿¾¾¾¼¼¼ÂÂÂÀÀÀÀÀÀÃÃÃÇÇÇÇÇÇÃÃÿ¿¿ºººÛÛÛòòòîîîèèèîîîñññêêêíííëëëèèèêêêëëëëëëçççäääßßßçççàààÕÕÕ×××ØØØØØØÜÜÜØØØØØØ×××ÔÔÔÔÔÔÕÕÕÛÛÛàààÜÜÜÙÙÙØØØÍÍÍ¿¿¿ÉÉÉÛÛÛÝÝÝâââÜÜÜÝÝÝÜÜÜÜÜÜããããããØØØÔÔÔÙÙÙÜÜÜÛÛÛÜÜÜâââææææææâââÜÜܸ¸¸¼¼¼¿¿¿ÃÃÃÅÅÅÉÉÉÇÇÇÌÌÌÑÑÑÕÕÕÕÕÕÒÒÒÍÍÍÊÊÊÍÍÍÇÇÇÆÆÆ¾¾¾¾¾¾µµµ³³³ØØØ×××ÉÉɰ°°­­­¾¾¾¼¼¼¸¸¸ÅÅÅÉÉÉÇÇÇÅÅÅÅÅÅÅÅÅÅÅÅÇÇÇÉÉÉÌÌÌÉÉÉÐÐÐÔÔÔßßßÛÛÛÃÃÃÇÇÇÆÆÆÅÅÅÉÉÉÃÃÃÆÆÆÐÐÐÉÉÉÆÆÆ³³³µµµÂ¸¸¸­­­ÒÒÒÆÆÆµµµººººººººººººººº»»»¼¼¼¾¾¾ÂÂÂÃÃÃÅÅÅÆÆÆÆÆÆÅÅÅÂÂÂÀÀÀÀÀÀ¿¿¿¾¾¾¼¼¼»»»»»»¼¼¼¾¾¾ºººÂ»»»ÀÀÀÇÇÇÑÑѾ¾¾ÍÍÍÀÀÀÃÃÃ×××ÉÉɼ¼¼µµµ°°°ÕÕÕÆÆÆÅÅŸ¸¸±±±¸¸¸µµµ±±±···´´´ÅÅÅÅÅŵµµ¸¸¸ÎÎÎÜÜÜØØØßßßäääëëëÛÛÛÔÔÔÕÕÕÍÍÍØØØÙÙÙÎÎÎÔÔÔÜÜÜØØØ×××ÜÜÜÛÛÛÛÛÛÙÙÙØØØ××××××ØØØãããñññââ⺺ºÀÀÀ¼¼¼ÊÊÊÐÐÐÎÎÎÒÒÒÍÍÍÊÊÊÐÐÐÒÒÒÌÌÌÍÍÍÐÐÐÌÌÌÊÊÊÌÌÌÌÌÌÌÌÌÌÌÌÊÊÊÉÉÉÉÉÉÃÃÃÃÃÿ¿¿¼¼¼¼¼¼¿¿¿Â»»»¾¾¾ÀÀÀÀÀÀ¿¿¿¾¾¾¿¿¿ÂÂÂÀÀÀÂÂÂÃÃÃÃÃÃÂÂÂÀÀÀ¿¿¿¾¾¾ÃÃÃÀÀÀÀÀÀÂÂÂÆÆÆÅÅÅ¿¿¿»»»ÀÀÀ×××èèèëëëíííòòòõõõññññññíííêêêêêêíííëëëçççãããßßßààààààÝÝÝØØØ×××ÙÙÙÝÝÝÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝÝÝÙÙÙÎÎÎØØØÕÕÕÉÉÉ×××ßßßßßßÜÜÜÝÝÝãããæææâââÜÜÜÜÜÜÛÛÛÜÜÜÙÙÙÕÕÕÙÙÙãããäääßßßÕÕÕ¾¾¾···ºººÃÃÃÀÀÀµµµÇÇÇÃÃÃÊÊÊÒÒÒÕÕÕÒÒÒÎÎÎÎÎÎÐÐÐÉÉÉÇÇÇÆÆÆÂ¼¼¼µµµ°°°¬¬¬ªªª¬¬¬­­­±±±µµµ»»»¿¿¿ÃÃÃÃÃÃÃÃÃÂÂÂÂÂÂÀÀÀÂÂÂÅÅÅÆÆÆÇÇÇÔÔÔÊÊÊÐÐÐÝÝÝÛÛÛØØØÎÎÎÉÉÉÍÍÍÒÒÒ±±±ÆÆÆ¼¼¼ººººººÀÀÀÀÀÀ±±±¸¸¸ÆÆÆÂ¼¼¼´´´³³³´´´···¸¸¸ººº»»»¾¾¾ÀÀÀÂÂÂÃÃÃÅÅÅÆÆÆÅÅÅ¿¿¿¾¾¾¼¼¼»»»ºººººº»»»»»»ººº¸¸¸ººº»»»¸¸¸¿¿¿ÂÂÂÎÎÎÀÀÀÊÊÊÅÅÅÂÂÂÕÕÕÌÌÌ···¿¿¿¿¿¿»»»ÅÅÅÆÆÆ»»»¾¾¾±±±¸¸¸µµµ¾¾¾ººº¾¾¾Â¿¿¿¸¸¸´´´´´´µµµ±±±âââêêêëëëÎÎÎÙÙÙÎÎÎÙÙÙÛÛÛÔÔÔÙÙÙæææçççßßßÙÙÙÛÛÛÒÒÒÛÛÛÙÙÙãããäääàààæææÝÝÝ···¸¸¸¾¾¾ÃÃÃÉÉÉÎÎÎÑÑÑÔÔÔÎÎÎÎÎÎÎÎÎÍÍÍÍÍÍÌÌÌÌÌÌÌÌÌÊÊÊÊÊÊÉÉÉÉÉÉÇÇÇÆÆÆÆÆÆÅÅÅÅÅÅÃÃÃÃÃÃÂÂÂÀÀÀ¿¿¿¾¾¾¾¾¾¼¼¼¾¾¾¿¿¿ÂÂÂÂÂÂÂÂÂÀÀÀ¿¿¿ÃÃÃÃÃÃÂÂÂÂÂÂÂÂÂÃÃÃÃÃÃÃÃþ¾¾ÂÂÂÅÅÅÇÇÇÃÃø¸¸¿¿¿×××äääæææëëëñññíííâââÝÝÝààààààëëëëëëêêêîîîêêêãããèèèßßßàààâââßßßÙÙÙÙÙÙÜÜÜààààààßßßÜÜÜÙÙÙÙÙÙÜÜÜßßßâââÝÝÝÜÜÜÒÒÒÙÙÙ×××ÐÐÐÛÛÛßßßßßßÝÝÝàààããããããÝÝÝÙÙÙÛÛÛßßßßßßÜÜÜÙÙÙÙÙÙßßßãããããã»»»µµµºººººº¾¾¾¼¼¼¼¼¼ÕÕÕ¾¾¾ÅÅÅÎÎÎÔÔÔÒÒÒÐÐÐÎÎÎÎÎÎÊÊÊÉÉÉÆÆÆÂ»»»´´´¯¯¯¬¬¬ªªªªªª¬¬¬°°°µµµ»»»¿¿¿ÂÂÂÂÂÂÀÀÀ¿¿¿¿¿¿¿¿¿ÂÂÂÅÅÅÆÆÆÊÊÊÔÔÔÎÎÎ×××âââãããæææÜÜÜÌÌÌÃÃÃÇÇǵµµÐÐо¾¾ÃÃø¸¸ÀÀÀ¸¸¸¼¼¼Â¸¸¸µµµ³³³³³³´´´···¸¸¸¸¸¸ººº¼¼¼¿¿¿ÂÂÂÃÃÃÅÅÅÅÅÅÃÃÃÀÀÀ¾¾¾¼¼¼ººº···µµµµµµ···¸¸¸···µµµ»»»»»»¸¸¸¾¾¾¿¿¿ÊÊʸ¸¸¿¿¿ÍÍÍ¿¿¿ÎÎÎÐÐÐÆÆÆÊÊÊÆÆÆÀÀÀ¸¸¸ÃÃÿ¿¿¼¼¼±±±¼¼¼···³³³»»»¾¾¾ÀÀÀ¿¿¿»»»·········¸¸¸ÕÕÕÙÙÙëëëàààèèèÔÔÔÔÔÔ×××ÒÒÒØØØçççîîîæææÙÙÙÔÔÔßßßæææãããàààâââæææäää×××µµµ¸¸¸¼¼¼ÂÂÂÆÆÆÌÌÌÎÎÎÑÑÑÎÎÎÍÍÍÍÍÍÍÍÍÌÌÌÌÌÌÌÌÌÊÊÊÊÊÊÊÊÊÉÉÉÉÉÉÇÇÇÆÆÆÅÅÅÅÅÅÃÃÃÃÃÃÃÃÃÂÂÂÂÂÂÀÀÀÀÀÀ¿¿¿¿¿¿¿¿¿ÀÀÀÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÅÅÅÅÅÅÅÅÅ¿¿¿¼¼¼ÂÂÂÀÀÀ¸¸¸ÂÂÂÜÜÜîîîîîîíííëëëèèèãããÝÝÝÜÜÜßßßÝÝÝãããæææèèèëëëêêêçççêêêàààâââãããàààÝÝÝÝÝÝâââäääâââàààßßßÝÝÝÝÝÝßßßâââãããÜÜÜßßßÙÙÙÜÜÜÛÛÛÙÙÙààààààØØØÛÛÛâââæææãããÛÛÛØØØÙÙÙâââØØØÔÔÔÛÛÛãããäääÝÝÝÙÙÙ±±±···¿¿¿»»»¸¸¸µµµºººÑÑѺºº¿¿¿ÉÉÉÐÐÐÒÒÒÑÑÑÎÎÎÌÌÌÌÌÌÉÉÉÆÆÆ¿¿¿ººº³³³­­­ªªªªªª©©©ªªª¯¯¯···¼¼¼¿¿¿¿¿¿¾¾¾¼¼¼»»»»»»¼¼¼ÀÀÀÅÅÅÇÇÇÊÊÊÎÎÎÎÎÎÔÔÔ×××ÛÛÛàààÕÕÕÇÇÇ···»»»ºººØØØÅÅž¾¾ÊÊʰ°°ÀÀÀÀÀÀÀÀÀ¼¼¼¯¯¯°°°°°°±±±´´´···¸¸¸¸¸¸ººº»»»¾¾¾ÂÂÂÃÃÃÅÅÅÅÅÅ¿¿¿¼¼¼ººº¸¸¸µµµ´´´´´´µµµ······µµµººº»»»¸¸¸¿¿¿ÂÂÂÌÌÌ···»»»ÉÉÉ»»»ÊÊÊÜÜÜÝÝÝÛÛÛÍÍÍÀÀÀµµµÅÅÅÇÇÇÆÆÆººº¾¾¾¸¸¸´´´¼¼¼¾¾¾¾¾¾¾¾¾¾¾¾¼¼¼»»»»»»¸¸¸ÀÀÀ»»»ÔÔÔÛÛÛîîîäääèèèââââââãããæææèèèçççæææèèèâââââââââÜÜÜßßßàààÎÎο¿¿µµµ···»»»¿¿¿ÃÃÃÇÇÇÌÌÌÍÍÍÍÍÍÍÍÍÌÌÌÌÌÌÌÌÌÌÌÌÊÊÊÊÊÊÊÊÊÊÊÊÉÉÉÉÉÉÇÇÇÆÆÆÆÆÆÅÅÅÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÂÂÂÂÂÂÂÂÂÃÃÃÃÃÃÅÅÅÅÅÅÃÃÃÃÃÃÅÅÅÅÅÅÆÆÆÆÆÆÆÆÆÆÆÆÇÇÇ¿¿¿¼¼¼¾¾¾ÔÔÔíííóóóîîîîîîêêêãããÝÝÝÜÜÜÜÜÜÛÛÛÜÜÜÛÛÛâââèèèêêêêêêêêêçççâââãããäääãããââââââæææèèèàààâââãããäääãããâââßßßÜÜÜÛÛÛâââàààßßßßßßãããæææâââÊÊÊÐÐÐÜÜÜäääãããÝÝÝÝÝÝââââââÕÕÕÒÒÒÛÛÛÜÜÜÌÌ̺ºº°°°¸¸¸¾¾¾¾¾¾ººº»»»ººº¸¸¸ÀÀÀ¼¼¼¿¿¿ÅÅÅÌÌÌÐÐÐÑÑÑÍÍÍÊÊÊÊÊÊÇÇÇÃÃü¼¼µµµ°°°¬¬¬©©©©©©¨¨¨¨¨¨­­­µµµ»»»¼¼¼»»»»»»¸¸¸···¸¸¸»»»ÀÀÀÅÅÅÆÆÆÇÇÇÆÆÆÊÊÊÎÎÎÌÌÌÑÑÑ×××ÍÍͼ¼¼°°°¸¸¸¾¾¾×××···ÇÇǰ°°ÅÅÅÅÅÅÀÀÀººº¬¬¬­­­°°°±±±´´´·········¸¸¸»»»¼¼¼ÂÂÂÃÃÃÅÅÅÃÃþ¾¾ººº¸¸¸ººº···´´´´´´···¸¸¸¸¸¸¸¸¸···¸¸¸¸¸¸ÃÃÃÊÊÊÔÔÔ¾¾¾¿¿¿ÆÆÆ¼¼¼ÇÇÇØØØÝÝÝÝÝÝÔÔÔÇÇDZ±±µµµ¾¾¾ÆÆÆÃÃÿ¿¿ÀÀÀÆÆÆ¿¿¿¾¾¾¼¼¼¾¾¾ÀÀÀÂÂÂÀÀÀ¿¿¿ÇÇÇÆÆÆºººÂÂÂÀÀÀÒÒÒÒÒÒÛÛÛæææçççßßßÙÙÙÜÜÜßßßàààäääâââØØØÜÜÜàààäää×××µµµ¯¯¯···¸¸¸»»»¾¾¾ÂÂÂÆÆÆÉÉÉÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÊÊÊÊÊÊÊÊÊÌÌÌÊÊÊÊÊÊÉÉÉÇÇÇÇÇÇÆÆÆÆÆÆÅÅÅÅÅÅÅÅÅÆÆÆÆÆÆÆÆÆÆÆÆÇÇÇÆÆÆÅÅÅÂÂÂÂÂÂÂÂÂÃÃÃÅÅÅÆÆÆÃÃÃÅÅÅÆÆÆÇÇÇÇÇÇÇÇÇÇÇÇÇÇÇÃÃÿ¿¿ºººÃÃÃÝÝÝíííîîîîîîæææèèèèèèàààÝÝÝßßßÜÜÜ×××ÛÛÛÕÕÕßßßêêêèèèççççççßßßæææææææææäääãããäääçççèèèãããäääæææäääãããàààÜÜÜÙÙÙÜÜÜâââäääâââãããëëëêêêæææãããââââââßßßØØØÎÎÎÎÎÎÒÒÒÒÒÒÑÑÑØØØßßßÔÔÔ¾¾¾µµµ»»»ººº¿¿¿»»»ºººÂÂÂÂÂÂÀÀÀ¿¿¿ÅÅÅÃÃÃÅÅÅÉÉÉÍÍÍÐÐÐÍÍÍÊÊÊÇÇÇÅÅÅ¿¿¿ººº³³³¯¯¯¬¬¬ªªªªªª©©©©©©¯¯¯µµµºººººº···¸¸¸···´´´···¼¼¼ÀÀÀÅÅÅÆÆÆÅÅÅÃÃÃÌÌÌÐÐÐÍÍÍ×××ÙÙÙÐÐг³³µµµÅÅÅÆÆÆÔÔÔ¿¿¿³³³Â···ÉÉÉÃÃþ¾¾¸¸¸°°°±±±°°°³³³´´´·········¸¸¸ººº¼¼¼ÂÂÂÃÃÃÃÃÃÃÃÃÀÀÀ¾¾¾ººº······´´´³³³±±±´´´·········´´´···¸¸¸ÆÆÆÍÍÍ××׿¿¿ÀÀÀÉÉÉÆÆÆÃÃÃÃÃÃÅÅÅÑÑÑÜÜÜØØØÃÃõµµ°°°···ÃÃÃÃÃÿ¿¿¼¼¼¾¾¾ÂÂÂÆÆÆÆÆÆÅÅÅÉÉÉÎÎÎÇÇÇÅÅźººÃÃÿ¿¿»»»ÎÎÎàààæææãããâââÜÜÜÙÙÙâââçççÝÝÝâââçççêêêÕÕÕ³³³³³³¸¸¸ººº»»»¾¾¾ÂÂÂÆÆÆÉÉÉÌÌÌÊÊÊÊÊÊÊÊÊÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÍÍÍÌÌÌÌÌÌÊÊÊÉÉÉÇÇÇÇÇÇÆÆÆÆÆÆÆÆÆÇÇÇÇÇÇÉÉÉÉÉÉÉÉÉÊÊÊÇÇÇÅÅÅÃÃÃÂÂÂÀÀÀÂÂÂÅÅÅÆÆÆÆÆÆÆÆÆÆÆÆÇÇÇÇÇÇÇÇÇÇÇÇÇÇÇÆÆÆÀÀÀÂÂÂØØØòòòòòòäääâââäääçççäääÜÜÜÙÙÙÜÜÜÛÛÛÕÕÕÛÛÛÔÔÔÝÝÝêêêçççãããâââÙÙÙèèèèèèçççäääääääääæææççççççæææâââßßßÜÜÜÜÜÜÜÜÜÜÜÜÝÝÝàààæææãããçççïïïëëëêêêêêêàààØØØÒÒÒÎÎÎÍÍÍÒÒÒÛÛÛ×××ÒÒÒÒÒÒÒÒÒÉÉɺºº¸¸¸ÀÀÀ»»»ÅÅÅ¿¿¿ÀÀÀÅÅÅÀÀÀÃÃÃÅÅÅÉÉÉÇÇÇÆÆÆÇÇÇÊÊÊÍÍÍÌÌÌÊÊÊÆÆÆÃÃþ¾¾¸¸¸´´´±±±±±±°°°¯¯¯­­­¯¯¯³³³···ºººººº······µµµ´´´···¾¾¾ÃÃÃÅÅÅÃÃÃÆÆÆÅÅÅÎÎÎÎÎÎÎÎÎÔÔÔÍÍÍÅÅű±±ÀÀÀÒÒÒÑÑÑÔÔÔ³³³Â»»»ÊÊÊÃÃü¼¼ººº´´´···³³³´´´µµµ¸¸¸¸¸¸¸¸¸¸¸¸ººº¼¼¼ÂÂÂÂÂÂÃÃÃÃÃþ¾¾»»»¸¸¸µµµ³³³°°°¯¯¯±±±´´´µµµ···´´´¸¸¸»»»ÆÆÆÊÊÊÑÑѺºººººÃÃÃÌÌÌÇÇÇÀÀÀ¼¼¼ÅÅÅØØØÙÙÙÛÛÛÃÃñ±±¯¯¯ÇÇÇÒÒÒÐÐп¿¿ÅÅÅ¿¿¿¿¿¿ÃÃÃÇÇÇÊÊÊÊÊÊÃÃÃÇÇÇÇÇÇÉÉÉÅÅÅÎÎÎÉÉɼ¼¼»»»ÌÌÌÔÔÔÜÜÜçççæææãããîîîäääæææãããÝÝÝÝÝÝÍÍ͵µµ¸¸¸¸¸¸¸¸¸ººº¼¼¼ÀÀÀÅÅÅÉÉÉÌÌÌÊÊÊÊÊÊÌÌÌÌÌÌÌÌÌÌÌÌÍÍÍÍÍÍÎÎÎÍÍÍÍÍÍÌÌÌÊÊÊÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÊÊÊÊÊÊÌÌÌÌÌÌÌÌÌÉÉÉÇÇÇÅÅÅÃÃÃÃÃÃÅÅÅÆÆÆÇÇÇÉÉÉÇÇÇÇÇÇÆÆÆÆÆÆÆÆÆÇÇÇÇÇÇÇÇÇÂÂÂÒÒÒëëëñññëëëèèèçççëëëçççßßß×××ÔÔÔÕÕÕ×××ÕÕÕÙÙÙÕÕÕÜÜÜçççæææàààÝÝÝÜÜÜíííêêêçççäääããããããããããããäääâââÝÝÝÛÛÛÙÙÙÛÛÛÜÜÜÝÝÝàààÝÝÝæææäääèèèòòòëëëíííëëëÝÝÝÒÒÒÎÎÎÐÐÐÐÐÐÒÒÒ×××ÀÀÀ···±±±···»»»»»»¼¼¼ÀÀÀÀÀÀÊÊÊÃÃÃÆÆÆÆÆÆ¼¼¼ÀÀÀÅÅÅÆÆÆÆÆÆÆÆÆÇÇÇÊÊÊÊÊÊÊÊÊÉÉÉÆÆÆÃÃÿ¿¿ººº······¸¸¸¸¸¸´´´µµµ···ººº»»»¼¼¼»»»»»»···µµµµµµºººÀÀÀÅÅÅÅÅÅÂÂÂÅÅÅÆÆÆÍÍÍÉÉÉÍÍÍÎÎκºº´´´µµµÂÂÂÒÒÒÔÔÔÕÕÕ³³³ÆÆÆ¸¸¸ÊÊÊÃÃû»»ºººµµµººº···µµµ···¸¸¸ººº¸¸¸¸¸¸»»»¼¼¼ÀÀÀÂÂÂÃÃÃÃÃÿ¿¿¼¼¼ººº¸¸¸µµµ³³³±±±´´´¸¸¸ººº»»»¸¸¸¾¾¾¿¿¿ÉÉÉÊÊÊÐÐз··¸¸¸¼¼¼ÌÌÌÌÌÌÍÍÍÆÆÆÀÀÀÍÍÍÑÑÑÕÕÕ···°°°ÇÇÇÑÑÑØØØÑÑÑÆÆÆÃÃÃÂÂÂÂÂÂÅÅÅÉÉÉÌÌÌÍÍÍÐÐÐÌÌÌÍÍÍÎÎÎÊÊÊÍÍÍÍÍÍÅÅÅ¿¿¿¸¸¸ªªªµµµÑÑÑØØØÔÔÔÝÝÝÙÙÙâââÙÙÙ×××ÑÑѺºº­­­···µµµµµµ···ººº¾¾¾ÃÃÃÇÇÇÊÊÊÊÊÊÌÌÌÌÌÌÌÌÌÍÍÍÍÍÍÍÍÍÎÎÎÐÐÐÐÐÐÎÎÎÍÍÍÌÌÌÌÌÌÊÊÊÊÊÊÊÊÊÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÍÍÍÍÍÍÌÌÌÊÊÊÉÉÉÇÇÇÇÇÇÇÇÇÉÉÉÉÉÉÌÌÌÊÊÊÇÇÇÅÅÅÃÃÃÅÅÅÆÆÆÇÇÇÇÇÇÉÉÉÜÜÜîîîîîîîîîòòòòòòêêêâââÛÛÛ×××ÕÕÕÔÔÔÔÔÔÕÕÕÕÕÕÔÔÔ×××ßßßäääßßßßßßèèèîîîëëëèèèäääãããâââààààààÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜâââÛÛÛääääääêêêòòòëëëïïïàààÕÕÕÎÎÎÒÒÒØØØØØØÔÔÔÒÒÒºººµµµµµµ¸¸¸»»»¼¼¼ÀÀÀÅÅÅÃÃÃÇÇǾ¾¾ÅÅÅÊÊÊ¿¿¿ÃÃÃÆÆÆÂÂÂÃÃÃÆÆÆÇÇÇÉÉÉÉÉÉÉÉÉÇÇÇÇÇÇÅÅÅÀÀÀ¼¼¼»»»»»»¾¾¾¿¿¿¸¸¸»»»¼¼¼¾¾¾¿¿¿¾¾¾¾¾¾¾¾¾···µµµ···»»»ÂÂÂÆÆÆÃÃÃÀÀÀ¿¿¿ÅÅÅÌÌÌÇÇÇÑÑÑÑÑÑ···´´´···¾¾¾ÊÊÊÒÒÒÔÔÔÀÀÀ±±±ÇÇÇ´´´ÉÉÉÅÅż¼¼¸¸¸µµµººº¸¸¸µµµ¸¸¸ºººººº¸¸¸ººº»»»¼¼¼ÀÀÀÂÂÂÃÃÃÃÃÃÃÃÃÀÀÀ¾¾¾»»»¿¿¿»»»¸¸¸¸¸¸»»»¾¾¾ÀÀÀ»»»ÀÀÀÅÅÅÍÍÍÍÍÍÒÒÒ»»»¾¾¾ÂÂÂÍÍÍÌÌÌÒÒÒÌÌ̼¼¼ÉÉÉÐÐÐÕÕÕÅÅÅÀÀÀ···»»»¯¯¯¼¼¼ÊÊÊÇÇÇÅÅÅÃÃÃÂÂÂÅÅÅÉÉÉÍÍÍÐÐÐÒÒÒÌÌÌÔÔÔÙÙÙÐÐÐÆÆÆÉÉÉÊÊÊÃÃÃÅÅźºº³³³´´´¬¬¬³³³ÒÒÒÔÔÔÜÜÜÔÔÔÜÜÜÔÔÔªªª¥¥¥¸¸¸³³³³³³´´´···»»»ÀÀÀÆÆÆÉÉÉÌÌÌÌÌÌÌÌÌÍÍÍÍÍÍÎÎÎÎÎÎÎÎÎÑÑÑÐÐÐÐÐÐÎÎÎÍÍÍÌÌÌÌÌÌÊÊÊÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÎÎÍÍÍÌÌÌÌÌÌÊÊÊÊÊÊÊÊÊÌÌÌÎÎÎÌÌÌÇÇÇÃÃÃÂÂÂÃÃÃÆÆÆÇÇÇàààëëëíííëëëîîîèèèßßßÝÝÝâââÙÙÙ×××ÛÛÛÛÛÛ×××ÔÔÔÕÕÕÑÑÑÒÒÒÑÑÑÙÙÙãããßßßâââõõõîîîèèèãããàààâââàààÝÝÝÙÙÙØØØÛÛÛ×××ØØØßßßàààÜÜÜßßßäääæææææææææíííõõõñññçççÕÕÕÔÔÔÔÔÔÕÕÕØØØÕÕÕÌÌÌÅÅž¾¾¼¼¼»»»¼¼¼¿¿¿ÃÃÃÇÇÇÊÊÊÃÃÃÀÀÀÂÂÂÉÉÉÌÌÌÇÇÇÃÃÃÃÃÃÉÉÉÉÉÉÊÊÊÌÌÌÌÌÌÊÊÊÊÊÊÉÉÉÆÆÆÅÅż¼¼µµµ···¿¿¿Â¿¿¿¿¿¿¾¾¾¾¾¾¿¿¿ÂÂÂÃÃÃÀÀÀ¿¿¿¾¾¾ÂÂÂÃÃþ¾¾¾¾¾ÂÂÂÇÇÇÂÂÂÅÅÅÊÊÊÆÆÆÑÑÑÒÒÒ»»»»»»»»»¸¸¸¿¿¿¼¼¼ÒÒÒµµµÃÃõµµÂÂÂÆÆÆ¾¾¾»»»¿¿¿¼¼¼´´´¸¸¸¸¸¸ººº»»»¼¼¼¾¾¾¿¿¿¿¿¿ÆÆÆÂÂÂÀÀÀÂÂÂÀÀÀ»»»¸¸¸¼¼¼»»»¾¾¾¾¾¾ÀÀÀÅÅž¾¾¼¼¼ÆÆÆÃÃþ¾¾ÃÃÃÅÅÅÎÎÎÎÎλ»»¿¿¿ÆÆÆÐÐÐ×××ÔÔÔÊÊÊÂÂÂÀÀÀÅÅÅÌÌÌ×××àààèèèÙÙÙÇÇDZ±±ÊÊÊÇÇÇÍÍÍÐÐÐÌÌÌÐÐÐÕÕÕÑÑÑØØØÎÎÎÎÎÎÑÑÑÐÐÐÔÔÔÒÒÒÉÉÉÇÇÇÃÃþ¾¾»»»ººº···±±±­­­ÙÙÙÒÒÒâââÔÔÔ¯¯¯···ªªª³³³´´´»»»¸¸¸µµµ¿¿¿ÆÆÆÃÃÃÃÃÃÐÐÐÐÐÐÎÎÎÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÐÐÐÐÐÐÐÐÐÎÎÎÎÎÎÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÎÎÑÑÑÒÒÒÑÑÑÎÎÎÉÉÉÆÆÆÉÉÉÎÎÎÎÎÎÊÊÊÉÉÉÌÌÌÇÇǼ¼¼¿¿¿ÃÃÃÆÆÆÀÀÀÃÃÃèèèõõõúúúïïïîîîää䨨ØßßßÛÛÛÔÔÔÜÜÜÜÜÜÜÜÜàààÛÛÛØØØàààÔÔÔÐÐÐÒÒÒ×××èèèçççÛÛÛóóóëëëçççãããâââàààßßßÛÛÛ×××ÐÐÐÙÙÙÙÙÙØØØÜÜÜÑÑÑÆÆÆÆÆÆÝÝÝâââæææèèèëëëëëëçççãããØØØÛÛÛàààäääãããØØØÇÇÇ»»»ÀÀÀÀÀÀÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÇÇÇÅÅÅÂÂÂÃÃÃÂÂÂÂÂÂÆÆÆÍÍÍÆÆÆÉÉÉÍÍÍÐÐÐÐÐÐÌÌÌÇÇÇÅÅÅÆÆÆÃÃþ¾¾¸¸¸ºººÀÀÀÃÃÃÀÀÀÅÅÅÃÃÃÀÀÀÀÀÀÂÂÂÅÅÅÆÆÆÆÆÆÆÆÆÀÀÀ¼¼¼¼¼¼ÀÀÀÅÅÅÃÃÃÂÂÂÇÇÇÇÇÇÌÌÌÆÆÆÍÍÍÑÑѼ¼¼µµµ»»»¾¾¾»»»ÂÂÂÒÒÒ¼¼¼¼¼¼¾¾¾»»»Â¼¼¼ººº¾¾¾¾¾¾¸¸¸ºººººº»»»¼¼¼¾¾¾¾¾¾¿¿¿¿¿¿ÅÅÅÂÂÂÂÂÂÃÃÿ¿¿ººº¸¸¸»»»ÂÂÂÃÃÃÅÅÅÉÉÉÍÍÍÍÍÍÊÊÊÉÉÉÇÇÇ¿¿¿ÂÂÂÅÅÅÐÐÐÎÎμ¼¼ÂÂÂÇÇÇÎÎÎÔÔÔÑÑÑÆÆÆ¾¾¾¾¾¾ÀÀÀÃÃÃÊÊÊÉÉÉÍÍÍÑÑÑÜÜÜàààÊÊÊÀÀÀ¼¼¼ÊÊÊØØØÔÔÔÊÊÊÌÌÌÍÍÍãããÍÍÍÍÍÍÜÜÜØØØÍÍÍÍÍÍÒÒÒÆÆÆÂ¾¾¾¼¼¼¾¾¾¾¾¾ºººµµµ¬¬¬­­­ÑÑÑÔÔÔ¬¬¬³³³¬¬¬°°°³³³ººº¸¸¸···ÀÀÀÇÇÇÆÆÆÉÉÉÐÐÐÐÐÐÎÎÎÍÍÍÍÍÍÍÍÍÎÎÎÎÎÎÐÐÐÐÐÐÐÐÐÎÎÎÎÎÎÎÎÎÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÐÐÐÑÑÑÑÑÑÐÐÐÐÐÐÒÒÒÍÍÍÉÉÉÉÉÉÊÊÊÊÊÊÊÊÊÌÌÌÆÆÆÐÐÐÝÝÝäääîîîíííêêêöööêêêêêêàààààààààÝÝÝäääâââßßßàààØØØÒÒÒØØØÙÙÙØØØÜÜÜÕÕÕÒÒÒÒÒÒÕÕÕæææèèèßßßñññæææäääãããâââßßßÜÜÜØØØÕÕÕ×××ßßßØØØ×××âââÛÛÛÌÌÌÎÎÎàààãããêêêïïïëëëâââÝÝÝÝÝÝàààààààààÝÝÝÙÙÙÑÑÑÉÉÉÅÅÅÃÃÃÃÃÃÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÆÆÆÃÃÃÃÃÃÇÇÇÇÇÇÅÅÅÆÆÆÉÉÉÉÉÉÌÌÌÎÎÎÑÑÑÐÐÐÌÌÌÇÇÇÃÃÃÃÃÃÃÃÿ¿¿¼¼¼¾¾¾ÂÂÂÃÃÃÂÂÂÃÃÃÃÃÿ¿¿¼¼¼»»»»»»¼¼¼Â¿¿¿¼¼¼¾¾¾ÂÂÂÅÅÅ¿¿¿¿¿¿ÀÀÀÊÊÊÉÉÉÍÍÍÕÕÕÅÅű±±µµµ¾¾¾¸¸¸ÃÃÃÊÊÊ´´´¾¾¾µµµÃÃÃÀÀÀ¾¾¾»»»»»»¼¼¼¾¾¾¾¾¾»»»»»»¼¼¼¾¾¾¾¾¾¿¿¿ÀÀÀÀÀÀÅÅÅÃÃÃÅÅÅÅÅÅÀÀÀ»»»ººº¼¼¼¿¿¿ÅÅÅÉÉÉÆÆÆÂÂÂÆÆÆÐÐÐ×××ÍÍÍÃÃÃÃÃÃÉÉÉÑÑÑÌÌ̾¾¾ÆÆÆÎÎÎÔÔÔ×××ÑÑÑÆÆÆ¿¿¿¾¾¾ÀÀÀ¾¾¾ÉÉÉÅÅÅ¿¿¿ÅÅÅÙÙÙàààÅÅÅÃÃû»»ÀÀÀÎÎÎÑÑÑÐÐÐÕÕÕÛÛÛÙÙÙÐÐÐØØØçççää䨨ØÔÔÔ×××ÊÊÊÆÆÆÂÂÂÂÂÂÃÃÃÃÃÃÀÀÀ¾¾¾³³³±±±×××ÜÜÜ­­­±±±´´´¸¸¸´´´»»»¼¼¼¼¼¼ÂÂÂÇÇÇÉÉÉÌÌÌÐÐÐÎÎÎÎÎÎÍÍÍÍÍÍÎÎÎÎÎÎÐÐÐÑÑÑÐÐÐÐÐÐÐÐÐÐÐÐÎÎÎÎÎÎÎÎÎÍÍÍÎÎÎÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÍÍÍÌÌÌÊÊÊÊÊÊÍÍÍÎÎÎÌÌÌÉÉÉ»»»âââøøøøøøóóóññññññîîîíííçççÙÙÙØØØÛÛÛÛÛÛßßßÛÛÛããããããØØØÎÎÎÒÒÒØØØÕÕÕÒÒÒÕÕÕÕÕÕÒÒÒÑÑÑâââêêêãããîîîããããããâââàààÝÝÝÙÙÙØØØ×××ÔÔÔÑÑѾ¾¾¿¿¿ÜÜÜãããÙÙÙÝÝÝãããÝÝÝàààæææâââÔÔÔÎÎÎÒÒÒãããàààØØØÎÎÎÇÇÇÅÅÅÆÆÆÉÉÉÇÇÇÆÆÆÅÅÅÅÅÅÇÇÇÊÊÊÍÍÍÐÐÐÇÇÇÃÃÃÅÅÅÌÌÌÐÐÐÌÌÌÆÆÆÃÃÃÐÐÐÎÎÎÍÍÍÌÌÌÊÊÊÉÉÉÇÇÇÇÇÇÂÂÂÂÂÂÀÀÀÀÀÀÀÀÀ¿¿¿ÃÃÃÇÇÇÉÉÉÇÇÇÅÅÅÃÃÃÅÅÅÃÃÃÊÊÊÐÐÐÎÎÎÆÆÆÃÃÃÆÆÆÌÌÌÒÒÒÎÎÎÎÎÎÉÉÉÍÍÍâââäääÑÑѵµµ»»»ÆÆÆÇÇÇÀÀÀ···»»»»»»ÇÇÇ¿¿¿»»»¼¼¼¿¿¿¼¼¼¾¾¾ÀÀÀ¾¾¾¾¾¾¾¾¾¿¿¿ÀÀÀÀÀÀÂÂÂÂÂÂÃÃÃÅÅÅÇÇÇÇÇÇÃÃÃÀÀÀÀÀÀÂÂÂÆÆÆÉÉÉÃÃúºº´´´°°°···ÆÆÆÍÍÍÉÉÉÉÉÉÎÎÎÐÐÐÃÃü¼¼ÉÉÉÒÒÒÔÔÔÔÔÔÎÎÎÆÆÆ¿¿¿¾¾¾¿¿¿ÇÇÇÙÙÙÙÙÙÎÎÎÇÇÇÒÒÒßßßÍÍÍÇÇÇÃÃÃÃÃÃÇÇÇÎÎÎÕÕÕÔÔÔÍÍÍÙÙÙæææèèèÝÝÝ×××ÛÛÛÙÙÙÍÍÍÑÑÑÌÌÌÇÇÇÅÅÅÆÆÆÅÅÅ¿¿¿···´´´ÍÍÍÕÕÕ¯¯¯°°°°°°¸¸¸···¼¼¼ÀÀÀÃÃÃÅÅÅÆÆÆÉÉÉÌÌÌÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÐÐÐÐÐÐÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÍÍÍÐÐÐÒÒÒÑÑÑÐÐÐÎÎÎÎÎÎÐÐÐÆÆÆÌÌÌÐÐÐÐÐÐÍÍÍÊÊÊÆÆÆÀÀÀÃÃÃëëëüüüüüüóóóñññúúúñññïïïêêêâââàààâââäääèèèèèèÛÛÛâââßßßÕÕÕÕÕÕÙÙÙÕÕÕÌÌÌÕÕÕØØØÒÒÒÎÎÎÝÝÝèèèçççëëëäääãããâââßßßÛÛÛØØØ××××××ÔÔÔÐÐп¿¿ÀÀÀÜÜÜäääÝÝÝààà×××ÉÉÉÃÃÃÌÌÌÍÍÍÆÆÆÂÂÂÇÇÇÃÃÃÆÆÆÊÊÊÌÌÌÌÌÌÎÎÎÔÔÔØØØÎÎÎÎÎÎÍÍÍÌÌÌÊÊÊÌÌÌÍÍÍÍÍÍÌÌÌÊÊÊÌÌÌÎÎÎÍÍÍÇÇÇÇÇÇÊÊÊÐÐÐÎÎÎÍÍÍÊÊÊÉÉÉÇÇÇÆÆÆÆÆÆÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÀÀÀÀÀÀÀÀÀÃÃÃÆÆÆÊÊÊÊÊÊÇÇÇÅÅÅÅÅÅÅÅż¼¼ÃÃÃÆÆÆ¼¼¼­­­©©©±±±¾¾¾ÌÌÌÍÍÍÍÍÍÊÊÊÌÌÌÜÜÜÝÝÝÆÆÆ¸¸¸»»»ØØØÌÌÌ»»»ÃÃúººÊÊÊÆÆÆ¾¾¾»»»ÀÀÀ¾¾¾¾¾¾ÂÂÂÀÀÀÀÀÀÀÀÀÀÀÀÂÂÂÂÂÂÃÃÃÃÃÃÂÂÂÆÆÆÉÉÉÊÊÊÉÉÉÇÇÇÇÇÇÇÇÇÍÍÍÃÃñ±±¯¯¯ººº±±±¬¬¬ºººÊÊÊÐÐÐÐÐÐÑÑÑÊÊÊ»»»»»»ÉÉÉÐÐÐÑÑÑÐÐÐÊÊÊÅÅÅ¿¿¿¾¾¾¿¿¿ÇÇÇÕÕÕØØØÒÒÒÆÆÆÍÍÍâââßßßÊÊÊÉÉÉÅÅÅÂÂÂÆÆÆÍÍÍÑÑÑÕÕÕÒÒÒÛÛÛÕÕÕÃÃÃÂÂÂÒÒÒâââæææÒÒÒÍÍÍÇÇÇÆÆÆÇÇÇÇÇÇÅÅż¼¼¼¼¼ÌÌÌßßßÍÍÍÃÃð°°´´´µµµºººÀÀÀÆÆÆÇÇÇÉÉÉÌÌÌÍÍÍÍÍÍÍÍÍÍÍÍÎÎÎÎÎÎÐÐÐÑÑÑÒÒÒÒÒÒÒÒÒÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÐÐÐÒÒÒÔÔÔÒÒÒÐÐÐÎÎÎÎÎÎÐÐÐÍÍÍÐÐÐÑÑÑÌÌÌÅÅÅÂÂÂÅÅÅÇÇÇèèèöööõõõøøøöööóóóöööçççÝÝÝÜÜÜÛÛÛÔÔÔÐÐÐÎÎÎÐÐÐÒÒÒÒÒÒßßßäääÜÜÜÕÕÕØØØØØØÑÑÑÔÔÔÙÙÙÒÒÒÎÎÎÙÙÙäääêêêèèèæææäääâââÝÝÝÛÛÛÕÕÕÑÑÑÎÎκºº¿¿¿¿¿¿ÀÀÀÆÆÆÂººº¸¸¸ÇÇǺºº´´´¾¾¾ÆÆÆÆÆÆÆÆÆÌÌÌÌÌÌÎÎÎÑÑÑÑÑÑÎÎÎÍÍÍÎÎÎÐÐÐÕÕÕÕÕÕÒÒÒÐÐÐÍÍÍÉÉÉÆÆÆÃÃÃÉÉÉÐÐÐÙÙÙÛÛÛÑÑÑÆÆÆÆÆÆÍÍÍÉÉÉÊÊÊÌÌÌÌÌÌÊÊÊÆÆÆÃÃÃÀÀÀÂÂÂÀÀÀÂÂÂÂÂÂÀÀÀ¼¼¼¼¼¼¿¿¿ÃÃÃÃÃÃÃÃÃÂÂÂÀÀÀÂÂÂÃÃÃÅÅÅÑÑÑÍÍ͵µµ¬¬¬¬¬¬µµµ¾¾¾ÐÐÐÝÝÝãããèèèçççàààÒÒÒµµµ³³³ºººÒÒÒÃÃ÷··ÆÆÆ···ÍÍÍÅÅÅ¿¿¿¾¾¾ÂÂÂÃÃÿ¿¿¿¿¿ÃÃÃÂÂÂÂÂÂÃÃÃÃÃÃÃÃÃÃÃÃÅÅÅÅÅÅÃÃÃÇÇÇÊÊÊÊÊÊÌÌÌÎÎÎÌÌÌÉÉÉÔÔÔÊÊÊ···¯¯¯´´´´´´ºººÌÌÌÉÉÉÒÒÒÍÍÍÊÊÊÃÃ÷··¾¾¾ÊÊÊÔÔÔÔÔÔÒÒÒÐÐÐÍÍÍÊÊÊÉÉÉÉÉÉÉÉÉÍÍÍÎÎÎÒÒÒÉÉÉÆÆÆÑÑÑÍÍÍÛÛÛ×××ÒÒÒÐÐÐÌÌÌÅÅÅÐÐÐäääÔÔÔÊÊÊÂÂÂÂÂÂÀÀÀ¾¾¾ÊÊÊãããÑÑÑÍÍÍÇÇÇÆÆÆÉÉÉÊÊÊÊÊÊÇÇǸ¸¸µµµ»»»ØØØ×××ÌÌÌ´´´´´´µµµ´´´¼¼¼ÆÆÆÇÇÇÊÊÊÐÐÐÑÑÑÍÍÍÍÍÍÍÍÍÎÎÎÐÐÐÑÑÑÒÒÒÔÔÔÕÕÕÕÕÕÕÕÕÕÕÕ××××××××××××ÔÔÔÔÔÔÕÕÕÔÔÔÒÒÒÐÐÐÐÐÐÐÐÐÑÑÑÊÊÊÅÅÅÃÃÃÃÃÃÊÊÊÙÙÙèèèüüüøøøóóóöööïïïæææãããÛÛÛàààßßßâââØØØÎÎÎÌÌÌÆÆÆÌÌÌÑÑÑÙÙÙâââÜÜÜÒÒÒÕÕÕÜÜÜÛÛÛÒÒÒØØØÑÑÑÑÑÑ×××ßßßèèèæææçççäääâââßßßÙÙÙÑÑÑÆÆÆ¾¾¾¸¸¸¼¼¼ÆÆÆÇÇǾ¾¾···´´´°°°¾¾¾···¸¸¸ÀÀÀÉÉÉÊÊÊÍÍÍÒÒÒÕÕÕÔÔÔÒÒÒÑÑÑÐÐÐÐÐÐÒÒÒÔÔÔÔÔÔÑÑÑÍÍÍÉÉÉÇÇÇÇÇÇÊÊÊÌÌÌÎÎÎÒÒÒÛÛÛàààÛÛÛÎÎÎÆÆÆÆÆÆÆÆÆÇÇÇÉÉÉÉÉÉÇÇÇÅÅÅ¿¿¿ÂÂÂÀÀÀÀÀÀ¾¾¾¸¸¸¸¸¸¼¼¼¾¾¾¿¿¿ÂÂÂÆÆÆÊÊÊÌÌÌÊÊÊÉÉÉÃÃû»»°°°ªªªªªª°°°´´´···ÊÊÊ×××ÑÑÑÑÑÑÑÑÑÇÇÇÀÀÀ±±±°°°ÃÃþ¾¾¼¼¼¼¼¼ÇÇÇÂÂÂÉÉÉÃÃÃÂÂÂÀÀÀÂÂÂÀÀÀÀÀÀÂÂÂÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÆÆÆÉÉÉÊÊÊÉÉÉÍÍÍÐÐÐÊÊÊÃÃÃÒÒÒÑÑÑÎÎξ¾¾ªªª³³³ÉÉÉÐÐÐÊÊÊÑÑÑ»»»¼¼¼ºººÆÆÆÊÊÊÒÒÒÒÒÒÒÒÒÒÒÒÔÔÔÒÒÒÑÑÑÐÐÐÒÒÒÔÔÔÔÔÔÙÙÙÑÑÑÊÊÊÎÎÎÃÃÃÝÝÝâââãããçççâââÍÍÍÂÂÂÌÌÌÅÅÅÀÀÀÀÀÀÌÌÌÍÍÍ¿¿¿ÀÀÀØØØÕÕÕÐÐÐÊÊÊÇÇÇÊÊÊÌÌÌÌÌÌÊÊÊÀÀÀ´´´µµµÛÛÛâââãããÙÙÙÜÜÜ¿¿¿···ºººÂÂÂÂÂÂÇÇÇÐÐÐÑÑÑÌÌÌÌÌÌÍÍÍÎÎÎÐÐÐÒÒÒÔÔÔÕÕÕ××××××ØØØØØØÙÙÙÙÙÙÙÙÙÙÙÙØØØ×××ÕÕÕÕÕÕÔÔÔÒÒÒÑÑÑÎÎÎÌÌÌ¿¿¿¼¼¼ÍÍÍÜÜÜãããîîîúúúõõõíííõõõöööêêêääääääèèèÎÎÎÊÊÊÑÑÑÌÌÌÌÌÌÐÐÐÊÊÊÐÐÐÑÑÑÒÒÒÙÙÙÙÙÙÒÒÒÕÕÕÝÝÝÜÜÜÐÐÐÕÕÕÐÐÐÔÔÔ×××ÙÙÙçççæææèèèæææãããàààÙÙÙÍÍ;¾¾±±±ºººµµµ¼¼¼¿¿¿µµµ···¾¾¾¸¸¸´´´···¼¼¼ÃÃÃÆÆÆÇÇÇÊÊÊÎÎÎÒÒÒÒÒÒÒÒÒÒÒÒÒÒÒÒÒÒÒÒÒÒÒÒÍÍÍÆÆÆ¿¿¿»»»¿¿¿ÊÊÊ×××àààãããØØØÑÑÑÕÕÕÛÛÛ×××ÍÍÍÅÅÅÉÉÉÇÇÇÅÅÅÃÃÃÂÂÂÂÂÂÂÂÂÃÃÿ¿¿¿¿¿ÀÀÀ¼¼¼µµµµµµ»»»ÃÃÃÆÆÆÉÉÉÌÌÌÉÉɾ¾¾°°°¦¦¦ªªª¨¨¨¦¦¦ªªª°°°µµµ···µµµ¸¸¸ÅÅŸ¸¸¸¸¸¾¾¾´´´´´´±±±···×××´´´ÂÂÂÍÍÍÐÐÐ×××ÌÌÌÂÂÂÃÃÃÃÃÃÀÀÀ¿¿¿ÀÀÀÅÅÅÇÇÇÅÅÅÅÅÅÅÅÅÅÅÅÆÆÆÆÆÆÆÆÆÆÆÆÉÉÉÊÊÊÉÉÉÇÇÇÌÌÌÎÎÎÇÇǾ¾¾¯¯¯···ÎÎÎÊÊʵµµÊÊÊßßßÊÊÊÌÌÌÐÐи¸¸°°°¸¸¸¿¿¿ÌÌÌÊÊÊÆÆÆÇÇÇÉÉÉÊÊÊÍÍÍÎÎÎÍÍÍÊÊÊÌÌÌÎÎÎÊÊÊÌÌÌÇÇÇÊÊÊØØØÑÑÑÆÆÆÎÎÎÐÐÐØØØäääàààÍÍÍÃÃÃÊÊÊÔÔÔÒÒÒÍÍÍÌÌÌÅÅÅ¿¿¿ÆÆÆÛÛÛÕÕÕÎÎÎÊÊÊÊÊÊÌÌÌÉÉÉÇÇÇÇÇdz³³´´´ÛÛÛÛÛÛÝÝÝÛÛÛÙÙÙÊÊʼ¼¼ººº¾¾¾¼¼¼ÂÂÂÌÌÌÍÍÍÌÌÌÌÌÌÍÍÍÎÎÎÐÐÐÒÒÒÕÕÕ×××ØØØØØØÙÙÙÙÙÙÛÛÛÛÛÛÛÛÛÜÜÜÙÙÙØØØÕÕÕÕÕÕ×××ÕÕÕÑÑÑÎÎÎÉÉɼ¼¼ÂÂÂâââøøøöööîîîîîîùùùçççíííêêêàààâââÜÜÜßßßÑÑÑÇÇÇÌÌÌÇÇÇÌÌÌÒÒÒÊÊÊÍÍÍÐÐÐÌÌÌÔÔÔÙÙÙ×××ØØØÛÛÛØØØÎÎÎÔÔÔÐÐÐÕÕÕÕÕÕÕÕÕææææææÝÝÝÝÝÝãããÛÛÛÒÒÒÇÇǵµµ´´´µµµ»»»ÀÀÀÂÂÂÀÀÀ¾¾¾»»»»»»¸¸¸»»»¾¾¾ÂÂÂÇÇÇÍÍÍÒÒÒ××××××àààÜÜÜÒÒÒÔÔÔÕÕÕÒÒÒ××׿¿¿ÊÊÊÊÊÊÃÃû»»´´´µµµÇÇÇÌÌÌÉÉÉÍÍÍãããÕÕÕÐÐÐÀÀÀÅÅÅÃÃÃÂÂÂÀÀÀ¾¾¾¾¾¾¼¼¼¼¼¼»»»ÀÀÀÃÃÿ¿¿ººº¸¸¸······»»»ÊÊÊÎÎξ¾¾¯¯¯­­­¯¯¯­­­ªªª©©©¸¸¸¾¾¾¬¬¬¬¬¬ºººººº¿¿¿´´´···¼¼¼······¾¾¾¿¿¿ÍÍͼ¼¼ÀÀÀººº···ÊÊÊÌÌ̾¾¾ÀÀÀÂÂÂÃÃÃÃÃÃÅÅÅÅÅÅÅÅÅÅÅÅÉÉÉÉÉÉÅÅÅÅÅÅÌÌÌÉÉÉÇÇÇÒÒÒÒÒÒÅÅÅÐÐÐÉÉÉÌÌÌÑÑѸ¸¸µµµººº¿¿¿ÍÍÍÔÔÔÐÐÐÐÐÐÑÑÑÌÌÌØØØÊÊÊ»»»···¾¾¾ÅÅÅÆÆÆÃÃÃÀÀÀÃÃÃÃÃÃÅÅÅÅÅż¼¼ºººÅÅÅÃÃÿ¿¿ÀÀÀÅÅÅÃÃÃÆÆÆÐÐÐÐÐп¿¿ÆÆÆ×××êêêÆÆÆÉÉÉÙÙÙêêêèèèãããÕÕÕÅÅÅÀÀÀºººÔÔÔÐÐÐ×××ÑÑÑÍÍÍÎÎÎÆÆÆÍÍÍÊÊÊÀÀÀ···´´´ÐÐÐäääÛÛÛààààààÑÑÑ»»»···¾¾¾¾¾¾ÂÂÂÒÒÒÌÌÌÅÅÅÉÉÉÉÉÉÍÍÍÒÒÒÎÎÎÔÔÔÔÔÔÔÔÔÕÕÕØØØÛÛÛÜÜÜÝÝÝßßßÛÛÛÑÑÑÑÑÑ××××××ÙÙÙÔÔÔÆÆÆ¼¼¼ÇÇÇæææøøøòòòõõõõõõäääâââäääëëëäääããããããÑÑÑÆÆÆÉÉÉÊÊÊÊÊÊÌÌÌÌÌÌÍÍÍÎÎÎÎÎÎÎÎÎÑÑÑÊÊÊÙÙÙçççÛÛÛÒÒÒÒÒÒÕÕÕÐÐÐÍÍÍÎÎÎÑÑÑ×××âââîîîèèèßßßàààØØØÌÌ̾¾¾³³³»»»¼¼¼¿¿¿Â¿¿¿¼¼¼»»»»»»¼¼¼¼¼¼¿¿¿ÅÅÅÊÊÊÎÎÎÎÎÎÍÍÍÃÃÃÍÍÍÌÌÌÆÆÆÉÉÉÊÊÊÇÇÇÊÊÊÅÅÅÍÍÍÌÌÌÅÅÅÆÆÆÅÅÅ¿¿¿ÀÀÀ¾¾¾¼¼¼¾¾¾ÌÌÌãããÔÔÔÐÐÐÉÉÉÃÃÃÃÃÃÀÀÀ¿¿¿¾¾¾¾¾¾¾¾¾¾¾¾Â¼¼¼ººº¼¼¼»»»···¸¸¸¼¼¼¿¿¿Â¾¾¾±±±­­­±±±´´´±±±ªªª­­­ÂÂÂÌÌ̺ºº±±±¸¸¸¸¸¸»»»¸¸¸¿¿¿ÃÃø¸¸µµµÃÃÃÎÎμ¼¼¸¸¸¸¸¸ÂÂÂÉÉÉÎÎÎÎÎÎÃÃÃÂÂÂÂÂÂÂÂÂÃÃÃÃÃÃÅÅÅÆÆÆÆÆÆÇÇÇÊÊÊÇÇÇÉÉÉÍÍÍÉÉÉÊÊÊÕÕÕÜÜÜÐÐÐØØØÑÑÑÐÐÐÎÎεµµµµµ¾¾¾¼¼¼ººº¿¿¿ÍÍÍÕÕÕÕÕÕÒÒÒÅÅž¾¾¸¸¸¼¼¼ÅÅÅÉÉÉÆÆÆÀÀÀ¿¿¿ÀÀÀ»»»»»»ÂÂÂÃÃÃÅÅÅÐÐÐÔÔÔÒÒÒÃÃÃÀÀÀÅÅÅ¿¿¿ÃÃÃÍÍÍÕÕÕÑÑÑÐÐÐÊÊÊÌÌÌãããÑÑÑØØØãããâââÝÝÝäääßßßÑÑÑÌÌÌ¿¿¿ÇÇÇÍÍÍÙÙÙÒÒÒÑÑÑ×××ÎÎÎÍÍÍÊÊÊÅÅÅ»»»´´´ÇÇÇßßßâââãããßßßàààÝÝÝØØØÍÍÍ»»»···ÆÆÆÆÆÆÆÆÆÊÊÊÃÃÃÆÆÆÒÒÒÒÒÒÕÕÕÑÑÑÔÔÔ×××ÕÕÕÔÔÔÕÕÕÙÙÙÝÝÝßßßÙÙÙàààäääÛÛÛÑÑÑÌÌÌÅÅÅÎÎÎÝÝÝñññõõõíííêêêèèèäääßßßÝÝÝãããÛÛÛ××××××ÍÍÍÌÌÌÊÊÊÊÊÊÊÊÊÌÌÌÌÌÌÍÍÍÍÍÍÍÍÍÊÊÊÍÍÍÊÊÊÛÛÛâââ×××ÒÒÒÑÑÑÐÐÐÍÍÍÌÌÌÎÎÎÑÑÑÔÔÔÜÜÜæææçççßßßÝÝÝÍÍͼ¼¼······ÂÂÂÂÂÂÂÂÂÃÃÃÀÀÀ¿¿¿¾¾¾¾¾¾¿¿¿¼¼¼ÃÃÃÊÊÊÉÉÉÅÅÅÅÅÅÊÊÊÑÑÑÇÇÇÎÎÎÍÍÍÉÉÉÉÉÉÆÆÆÃÃÃÃÃÃÅÅÅÐÐÐÔÔÔÔÔÔÙÙÙÒÒÒÅÅž¾¾ÃÃÃÀÀÀ»»»ÃÃÃÕÕÕÍÍÍÍÍÍÅÅÅÂÂÂÂÂÂÀÀÀ¿¿¿¿¿¿¿¿¿¿¿¿ÀÀÀÅÅż¼¼¼¼¼ÃÃÿ¿¿´´´³³³»»»ÊÊÊ»»»­­­­­­µµµ¼¼¼¸¸¸°°°¯¯¯­­­ÀÀÀÐÐÐÀÀÀ´´´¸¸¸»»»¾¾¾¾¾¾Âººº¸¸¸ÂÂÂÉÉÉÃÃúººÊÊÊÔÔÔÆÆÆÃÃþ¾¾ÂÂÂÂÂÂÂÂÂÂÂÂÃÃÃÅÅÅÇÇÇÇÇÇÇÇÇÌÌÌÌÌÌÌÌÌÌÌÌÊÊÊÍÍÍØØØÙÙÙÍÍÍÕÕÕÑÑÑÐÐÐÎÎο¿¿ÆÆÆÃÃÃÃÃø¸¸µµµÌÌÌÛÛÛ×××ÒÒÒ¼¼¼»»»¼¼¼ÂÂÂÉÉÉÊÊÊÅÅž¾¾¾¾¾¿¿¿¸¸¸¸¸¸ÆÆÆÑÑÑÔÔÔØØØÜÜÜßßß»»»ÅÅž¾¾ÀÀÀÌÌÌÐÐÐÐÐÐÕÕÕÎÎÎÅÅÅâââÜÜÜâââÎÎÎÅÅÅÃÃÃÔÔÔÛÛÛßßßâââÍÍÍ»»»ÇÇÇ×××ÒÒÒÔÔÔÜÜÜÕÕÕÍÍÍÊÊÊÉÉÉ¿¿¿ººº¼¼¼ÑÑÑçççäääæææîîîñññêêêØØØÅÅÅÅÅÅÕÕÕääääääâââÉÉÉÀÀÀÍÍÍÍÍÍÎÎÎÎÎÎÑÑÑÕÕÕ×××ØØØÙÙÙÜÜÜßßßÛÛÛÜÜÜããããããÒÒÒÅÅÅÆÆÆÉÉÉâââòòòùùùòòòçççààààààæææñññæææäääÙÙÙÑÑÑÍÍÍÇÇÇÐÐÐÊÊÊÊÊÊÊÊÊÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÆÆÆÆÆÆÌÌÌÝÝÝÜÜÜÑÑÑÔÔÔÐÐÐÌÌÌÊÊÊÌÌÌÐÐÐÑÑÑÐÐÐÕÕÕÜÜÜÛÛÛÜÜÜßßßÅÅű±±ººº¿¿¿ÂÂÂÃÃÃÃÃÃÃÃÃÂÂÂÀÀÀÀÀÀÀÀÀ¾¾¾ÅÅÅÊÊÊÇÇÇÂÂÂÃÃÃÍÍÍ×××ÕÕÕ×××ÕÕÕÑÑÑÐÐÐÍÍÍÊÊÊÉÉÉÑÑÑÙÙÙØØØÕÕÕÛÛÛ×××ÊÊÊÃÃÃÌÌÌÍÍÍÀÀÀ¼¼¼ÆÆÆÊÊÊÎÎÎÀÀÀÃÃÃÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÃÃÃÃÃÿ¿¿ÂÂÂÅÅž¾¾´´´···Â¾¾¾´´´°°°···¼¼¼¾¾¾¼¼¼¾¾¾¸¸¸¬¬¬³³³ÀÀÀ»»»³³³ºººÀÀÀÆÆÆÆÆÆÃÃÃÀÀÀÅÅÅÎÎÎÌÌÌ¿¿¿ÌÌÌ¿¿¿¸¸¸ÌÌÌÑÑÑÃÃÃÃÃÃÆÆÆÃÃÃÂÂÂÂÂÂÀÀÀÂÂÂÅÅÅÉÉÉÊÊÊÉÉÉÍÍÍÎÎÎÍÍÍÊÊÊÌÌÌÒÒÒÛÛÛ¿¿¿µµµ¼¼¼»»»»»»»»»¸¸¸ÅÅÅÃÃÃÊÊÊÅÅŸ¸¸ÂÂÂÕÕÕÔÔÔÀÀÀ¾¾¾¾¾¾¾¾¾ÂÂÂÇÇÇÊÊÊÇÇÇÅÅż¼¼ÀÀÀ»»»¼¼¼ÐÐÐÜÜÜÛÛÛØØØ×××ÝÝݼ¼¼µµµÇÇÇÀÀÀÂÂÂÌÌÌÉÉÉÆÆÆÎÎÎÑÑÑÅÅÅÛÛÛÕÕÕÕÕÕÌÌÌÉÉÉÆÆÆÉÉÉÇÇÇØØØãããÆÆÆºººÂÂÂÍÍÍÎÎÎÑÑÑ×××ÔÔÔÑÑÑÍÍÍÇÇÇÀÀÀÀÀÀ···ÃÃÃææææææêêêêêêëëëêêêãããÝÝÝâââîîîëëëíííëëëÔÔÔÅÅÅÇÇÇÀÀÀÂÂÂÍÍÍÎÎÎÑÑÑ×××ÜÜÜÝÝÝÜÜÜÙÙÙâââàààÙÙÙÌÌÌÂÂÂÉÉÉÛÛÛêêêïïïöööùùùïïïãããàààäääçççæææÔÔÔÐÐÐÌÌÌÊÊÊÉÉÉÇÇÇÔÔÔÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÃÃÃÃÃÃÍÍÍßßßÙÙÙÎÎÎÕÕÕÑÑÑÊÊÊÉÉÉÍÍÍÑÑÑÒÒÒÎÎÎÐÐÐÔÔÔÙÙÙÝÝÝæææÍÍ͵µµ¼¼¼ÃÃÃÅÅÅÆÆÆÆÆÆÅÅÅÃÃÃÃÃÃÀÀÀ¿¿¿¾¾¾Â¿¿¿¿¿¿ÅÅÅÍÍÍÑÑÑÑÑÑÎÎÎÐÐÐÍÍÍÍÍÍÎÎÎÎÎÎÎÎÎÎÎÎÍÍÍÒÒÒÛÛÛØØØÕÕÕÙÙÙ×××ÍÍÍÉÉÉÉÉÉÊÊÊ¿¿¿ÃÃÃÉÉÉÐÐÐÔÔÔÇÇÇÅÅÅÃÃÃÃÃÃÃÃÃÃÃÃÅÅÅÆÆÆÆÆÆÃÃÃÀÀÀ¾¾¾¼¼¼¼¼¼¿¿¿ÃÃÃÆÆÆ´´´ºººÃÃÃÉÉɾ¾¾ÌÌÌÝÝÝÉÉɳ³³­­­···¸¸¸´´´ºººÂÂÂÂÂÂÆÆÆÀÀÀ»»»ÉÉÉØØØÍÍÍ´´´ÑÑѸ¸¸ÀÀÀÎÎÎÇÇÇÃÃÃÂÂÂÇÇÇÃÃÃÃÃÃÂÂÂÂÂÂÃÃÃÇÇÇÊÊÊÌÌÌÍÍÍÎÎÎÎÎÎÌÌÌÉÉÉÍÍÍÕÕÕÙÙÙÃÃÃÀÀÀÇÇÇÇÇÇÃÃÃÀÀÀ¾¾¾ÆÆÆÀÀÀÆÆÆÇÇǸ¸¸···ÕÕÕØØØ³³³¼¼¼¼¼¼¾¾¾¿¿¿ÂÂÂÅÅÅÇÇÇÇÇǾ¾¾ÀÀÀ»»»¼¼¼ÎÎÎÛÛÛ×××ÒÒÒÐÐÐÙÙÙÀÀÀ¼¼¼ÐÐÐÊÊÊÃÃÃÊÊÊÌÌÌÅÅÅÊÊÊÕÕÕÃÃÃÉÉÉÃÃÃÉÉÉÙÙÙÙÙÙØØØÒÒÒÃÃÃÌÌÌßßßÎÎÎÃÃÃÂÂÂÂÂÂÉÉÉÊÊÊÇÇÇÍÍÍÔÔÔÐÐÐÅÅÅÂÂÂÇÇÇ···¼¼¼àààçççææææææëëëñññïïïíííîîîïïïñññòòòùùùîîîßßßÑÑÑÀÀÀ¾¾¾µµµ»»»ÃÃÃÉÉÉÍÍÍÒÒÒØØØÝÝÝÜÜÜßßß×××ÊÊÊÐÐÐãããóóóùùùöööñññóóóîîîàààãããêêêàààãããÌÌÌÆÆÆÆÆÆÊÊÊÊÊÊÅÅÅÎÎÎÊÊÊÊÊÊÊÊÊÉÉÉÉÉÉÇÇÇÇÇÇÇÇÇÂÂÂÂÂÂÌÌÌßßßÙÙÙÎÎÎ×××ÒÒÒÌÌÌÌÌÌÐÐÐÔÔÔÔÔÔÐÐÐÐÐÐÒÒÒæææßßßêêêÝÝÝ»»»¿¿¿ÇÇÇÌÌÌÉÉÉÆÆÆÃÃÿ¿¿»»»¸¸¸¼¼¼¾¾¾ÃÃÃÌÌÌÒÒÒÔÔÔÐÐÐÊÊÊÎÎÎÇÇÇÊÊÊÎÎÎÌÌÌÊÊÊÊÊÊÇÇÇÊÊÊÕÕÕØØØÕÕÕØØØ×××ÐÐÐÎÎÎÇÇÇÀÀÀ¼¼¼ÔÔÔÔÔÔÐÐÐÍÍÍÉÉÉÅÅÅÅÅÅÃÃÃÃÃÃÃÃÃÅÅÅÅÅÅÆÆÆÆÆÆÅÅÅÀÀÀÀÀÀÅÅÅÅÅż¼¼°°°µµµ´´´´´´µµµ³³³³³³¼¼¼ÉÉÉÕÕÕ¸¸¸¼¼¼¿¿¿»»»¼¼¼ÂÂÂÌÌÌÒÒÒÍÍÍÅÅÅÌÌÌÑÑÑÃÃó³³ÌÌ̸¸¸ÊÊÊÑÑÑÃÃÿ¿¿ÀÀÀÃÃÃÃÃÃÃÃÃÅÅÅÆÆÆÉÉÉÌÌÌÍÍÍÐÐÐÍÍÍÍÍÍÌÌÌÊÊÊÑÑÑÕÕÕÑÑÑ¿¿¿ÆÆÆÎÎÎÐÐÐÌÌÌÇÇÇÅÅÅÅÅÅÉÉÉÃÃÃÅÅÅ»»»¼¼¼àààççç»»»¿¿¿ÀÀÀÂÂÂÀÀÀ¼¼¼ºººººº»»»¼¼¼¼¼¼µµµ¸¸¸ÇÇÇÐÐÐÎÎÎÎÎÎÒÒÒÙÙÙÐÐÐÊÊÊØØØÕÕÕÃÃÃÅÅÅÆÆÆÅÅÅÇÇÇÔÔÔÃÃÃÂÂÂÂÂÂÑÑÑÑÑÑÐÐÐÒÒÒØØØÊÊÊÇÇÇÝÝÝäääÑÑÑÉÉÉ¿¿¿ÆÆÆÅÅž¾¾ÉÉÉÔÔÔÑÑÑÃÃÃÃÃÃÇÇÇ»»»ÃÃÃâââêêêëëëíííóóóõõõëëëæææèèèèèèëëëèèèòòòóóóòòòñññçççëëëëëëïïïñññäääÔÔÔÊÊÊÍÍÍÔÔÔÎÎÎÔÔÔÎÎÎÍÍÍÝÝÝñññõõõòòòøøøíííïïïëëëÜÜÜàààçççÙÙÙçççÑÑÑÌÌÌÊÊÊÍÍÍÊÊÊ¿¿¿ÅÅÅÊÊÊÉÉÉÉÉÉÇÇÇÆÆÆÆÆÆÅÅÅÅÅÅÂÂÂÃÃÃÇÇÇÙÙÙÛÛÛÑÑÑ×××ÔÔÔÑÑÑÐÐÐÑÑÑÔÔÔÒÒÒÐÐÐÑÑÑ×××êêêÜÜÜçççßß߸¸¸¾¾¾ÇÇÇÌÌÌÇÇÇ¿¿¿¿¿¿¿¿¿¾¾¾¼¼¼»»»ÃÃÃÍÍÍÐÐÐÍÍÍÊÊÊÌÌÌÎÎÎÎÎÎÇÇÇÍÍÍÔÔÔÐÐÐÌÌÌÉÉÉÂÂÂÑÑÑÙÙÙÔÔÔÊÊÊÊÊÊÍÍÍÔÔÔÝÝÝÊÊÊ¿¿¿»»»ÙÙÙÒÒÒÉÉÉÅÅÅÃÃÃÃÃÃÂÂÂÂÂÂÀÀÀÀÀÀÂÂÂÂÂÂÃÃÃÆÆÆÅÅÅÅÅÅÇÇÇÃÃúºº°°°¬¬¬ÎÎθ¸¸ºººÂÂÂÆÆÆÃÃÃÀÀÀÕÕÕÍÍÍÇÇÇÆÆÆÅÅÅÂÂÂÆÆÆÍÍÍßßßßßßØØØÕÕÕ×××ÌÌÌÂÂÂÅÅŸ¸¸»»»ÉÉÉÌÌÌÂÂÂÃÃÃÆÆÆÅÅÅÃÃÃÅÅÅÆÆÆÇÇÇÉÉÉÌÌÌÍÍÍÎÎÎÎÎÎÊÊÊÌÌÌÎÎÎÐÐÐÕÕÕÒÒÒÅÅÅÅÅÅÎÎÎÒÒÒÐÐÐÐÐÐÔÔÔÕÕÕÒÒÒÎÎÎÅÅÅÅÅÅÃÃÃÅÅÅÛÛÛßßßÅÅÅÆÆÆÇÇÇÆÆÆÀÀÀººº···¸¸¸¼¼¼µµµ···µµµ¼¼¼ÊÊÊÌÌÌÉÉÉÍÍÍÒÒÒÕÕÕÜÜÜÔÔÔÛÛÛÛÛÛÀÀÀ¿¿¿ººº¿¿¿¼¼¼ÊÊÊÇÇÇÌÌÌÊÊÊ×××ÇÇÇÅÅÅÃÃÃÒÒÒÎÎÎÅÅÅÒÒÒÜÜÜÛÛÛÕÕÕÇÇÇÇÇÇÅÅž¾¾ÌÌÌÒÒÒÐÐÐÆÆÆÇÇÇÀÀÀ¾¾¾ÔÔÔêêêññññññïïïóóóîîîàààßßßçççêêêîîîçççêêêæææêêêòòòíííëëëîîîòòòòòòêêêÛÛÛÌÌÌÃÃÃÂÂÂÍÍÍÇÇǾ¾¾ÅÅÅÜÜÜêêêîîîòòòñññííííííää䨨ØÛÛÛßßßÙÙÙÎÎÎÃÃÃÆÆÆÅÅÅÆÆÆÆÆÆÀÀÀÉÉÉÉÉÉÉÉÉÇÇÇÆÆÆÅÅÅÃÃÃÂÂÂÂÂÂÂÂÂÃÃÃÀÀÀÑÑÑÛÛÛÒÒÒÒÒÒÔÔÔÕÕÕÑÑÑÑÑÑÑÑÑÑÑÑÐÐÐÔÔÔÙÙÙâââØØØãããÕÕÕººº¸¸¸¿¿¿ÅÅÅÆÆÆÂ¼¼¼»»»¾¾¾ÀÀÀÃÃÃÅÅÅÉÉÉÊÊÊÊÊÊÉÉÉÇÇÇÇÇÇÊÊÊÎÎÎÆÆÆ¿¿¿ÉÉÉ×××ÔÔÔÐÐÐÍÍÍÅÅÅÐÐÐÛÛÛÙÙÙÍÍÍÉÉÉÉÉÉÎÎÎÙÙÙÇÇÇ¿¿¿¸¸¸ÑÑÑÉÉÉÇÇÇÇÇÇÃÃÃÂÂÂÀÀÀ¿¿¿¿¿¿¾¾¾¿¿¿¿¿¿¿¿¿Â¿¿¿ÀÀÀ¿¿¿³³³©©©´´´ÉÉɸ¸¸······»»»ÀÀÀÃÃÿ¿¿ÎÎÎÐÐÐÍÍÍÇÇÇÃÃÃÃÃÃÎÎÎÜÜÜÒÒÒÉÉÉÂÂÂÍÍÍÒÒÒÀÀÀ»»»ÌÌ̼¼¼ÎÎÎÌÌÌÆÆÆ¾¾¾¸¸¸ÀÀÀ¼¼¼ÃÃÃÅÅÅÆÆÆÉÉÉÌÌÌÍÍÍÎÎÎÎÎÎÍÍÍÇÇÇÌÌÌÑÑÑÔÔÔØØØÑÑÑ»»»ÂÂÂÌÌÌÆÆÆ¼¼¼»»»ÆÆÆÑÑÑÎÎÎÇÇÇÂÂÂÅÅÅÇÇÇÃÃÃÃÃÃÃÃþ¾¾ÃÃÃÅÅÅÅÅÅ¿¿¿»»»¿¿¿ÉÉÉÒÒÒ¯¯¯´´´»»»ÇÇÇÔÔÔÎÎÎÉÉÉÎÎÎÐÐÐÎÎÎàààÕÕÕØØØÜÜܾ¾¾»»»µµµ¿¿¿´´´ÃÃÃÍÍÍ×××ÊÊÊÊÊʾ¾¾¿¿¿¼¼¼ÊÊÊÒÒÒÎÎÎÑÑÑÒÒÒÝÝÝßßßÐÐÐÌÌÌÆÆÆÃÃÃÑÑÑÐÐÐÍÍÍÊÊÊÌÌ̺ºº¾¾¾ãããóóóöööêêêçççëëëëëëãããæææîîîëëëêêêëëëñññêêêïïïùùùêêêÜÜÜÜÜÜÝÝÝäääîîîóóóëëëØØØÇÇÇ¿¿¿»»»¾¾¾×××ñññîîîäääêêêçççíííëëëßßß××××××ÙÙÙßßßÌÌÌÇÇÇÐÐÐÌÌÌÆÆÆÆÆÆÃÃÃÎÎÎÉÉÉÇÇÇÆÆÆÅÅÅÃÃÃÂÂÂÀÀÀ¿¿¿ÀÀÀÃÃû»»ÊÊÊÛÛÛÒÒÒÐÐÐÒÒÒ×××ÒÒÒÐÐÐÐÐÐÎÎÎÎÎÎÔÔÔÜÜÜâââÜÜÜèèèÔÔÔ···»»»¾¾¾¼¼¼ÆÆÆ»»»ºººººº···¾¾¾ÅÅÅÂÂÂÃÃÃÊÊÊÍÍÍÌÌÌÌÌÌÎÎÎÌÌÌÆÆÆÉÉÉÍÍÍÑÑÑÑÑÑÎÎÎÍÍÍÎÎÎÑÑÑÝÝÝÑÑÑÌÌÌÔÔÔÕÕÕÎÎÎÌÌÌÐÐÐÑÑÑÜÜÜÔÔÔ¾¾¾ÉÉÉÔÔÔÅÅÅÆÆÆÂ¼¼¼»»»¿¿¿ÂÂÂÀÀÀ¿¿¿Â¼¼¼ÆÆÆÀÀÀ°°°­­­ººº¿¿¿¸¸¸¼¼¼µµµµµµ´´´°°°»»»ÍÍÍÑÑÑÀÀÀÍÍÍÙÙÙßßßÜÜÜ×××ÔÔÔÔÔÔÅÅż¼¼ººº¾¾¾ÀÀÀ¿¿¿ÀÀÀÆÆÆ»»»ÆÆÆÌÌÌÇÇÇÀÀÀÀÀÀÂÂÂÃÃÿ¿¿ÍÍÍÇÇÇÊÊÊÎÎÎÇÇÇÊÊÊÐÐÐÊÊÊÌÌÌÉÉÉØØØÒÒÒÕÕÕÉÉÉÊÊÊÐÐÐÅÅÅÅÅÅÍÍÍÉÉÉ¿¿¿ÅÅÅÒÒÒÆÆÆÇÇÇÇÇÇÆÆÆÆÆÆÅÅÅÅÅÅÇÇÇÃÃÃÆÆÆÊÊÊÃÃø¸¸ÕÕÕÐÐÐÎÎÎÎÎÎÎÎÎÎÎÎÌÌÌÉÉÉÇÇÇÉÉÉÊÊÊÍÍÍÎÎÎØØØÎÎÎÙÙÙ×××´´´¼¼¼ÜÜÜØØØÎÎÎÂÂÂÀÀÀÇÇÇÉÉÉÅÅÅÂÂÂÔÔÔÑÑÑÃÃÃÊÊÊÕÕÕÑÑÑÉÉÉÕÕÕäääÍÍÍÊÊÊÃÃÿ¿¿ÝÝÝÔÔÔÑÑÑÍÍÍÆÆÆ···çççëëëïïïèèèïïïîîîêêêæææèèèïïïòòòïïïõõõíííñññîîîëëëæææÙÙÙÛÛÛ×××ÙÙÙâââíííòòòñññêêêäääÇÇÇ­­­¾¾¾ãããæææàààèèèíííçççîîîëëëßßßØØØØØØÕÕÕÍÍÍÎÎÎÉÉÉÍÍÍÎÎÎÆÆÆÅÅÅÆÆÆ¿¿¿ÆÆÆÇÇÇÇÇÇÅÅÅÂÂÂÀÀÀÂÂÂÅÅÅ¿¿¿ÃÃÿ¿¿ÇÇÇÕÕÕ×××ÎÎÎÉÉÉÌÌÌÒÒÒ×××ÒÒÒÍÍÍÎÎÎÔÔÔäääÛÛÛâââ×××¼¼¼¸¸¸ÀÀÀ¿¿¿ººº¾¾¾Â¿¿¿ÃÃÃÆÆÆ¿¿¿ÉÉÉÊÊÊÉÉÉÇÇÇÆÆÆÉÉÉÊÊÊÉÉÉÔÔÔÑÑÑÍÍÍÇÇÇÃÃÃÆÆÆÍÍÍÔÔÔÝÝÝÔÔÔÐÐÐÑÑÑÑÑÑÉÉÉÂÂÂÂÂÂÊÊÊÔÔÔ×××ÀÀÀºººÊÊÊÌÌÌÉÉÉÉÉÉÆÆÆÂ¿¿¿ÀÀÀÃÃÃÆÆÆÇÇÇÇÇǾ¾¾³³³°°°³³³¸¸¸¼¼¼¾¾¾µµµ¾¾¾ÌÌÌÊÊʺºº¸¸¸ÆÆÆÍÍͼ¼¼ÃÃÃÌÌÌÐÐÐÐÐÐÊÊÊÃÃÿ¿¿ÉÉÉÅÅÅ¿¿¿»»»¼¼¼ÀÀÀÅÅÅÆÆÆÒÒÒÒÒÒÍÍÍÅÅÅÂÂÂÃÃÃÅÅÅÂÂÂÆÆÆÌÌÌÆÆÆÌÌÌÒÒÒÎÎÎÐÐÐÌÌÌÀÀÀÎÎÎÑÑÑÒÒÒÃÃÃÉÉÉÊÊÊÐÐÐÅÅÅÂÂÂÊÊÊÕÕÕÑÑÑÅÅÅÂÂÂÉÉÉÔÔÔÔÔÔÔÔÔÕÕÕÔÔÔÍÍÍÆÆÆÀÀÀÂÂÂÅÅÅÉÉÉÅÅż¼¼×××ÑÑÑÌÌÌÌÌÌÍÍÍÌÌÌÊÊÊÆÆÆÆÆÆÇÇÇÉÉÉÇÇÇÊÊÊÕÕÕÎÎÎÙÙÙÕÕÕµµµ»»»ÕÕÕ×××ÕÕÕÎÎÎÅÅÅÀÀÀÉÉÉÑÑÑÑÑÑ××××××ÐÐÐÍÍÍÔÔÔÒÒÒÊÊÊÎÎÎàààÍÍÍÍÍÍÃÃþ¾¾ÙÙÙÒÒÒÊÊÊÆÆÆ¿¿¿ÀÀÀçççîîîëëëëëëññññññïïïëëëëëëïïïïïïíííïïïàààÝÝÝÝÝÝâââæææÜÜÜÝÝÝäääâââÜÜÜØØØÝÝÝçççëëëêêêÛÛÛÆÆÆÍÍÍääääääÝÝÝâââçççòòòòòòêêêÜÜÜ×××ØØØÔÔÔÊÊÊÆÆÆÃÃÃÇÇÇÉÉÉÂÂÂÃÃÃÇÇÇÃÃÃÉÉÉÉÉÉÉÉÉÇÇÇÅÅÅÂÂÂÀÀÀÀÀÀÂÂÂÅÅÅ¿¿¿ÆÆÆÕÕÕÙÙÙÕÕÕÔÔÔÑÑÑÐÐÐÎÎÎÉÉÉÆÆÆÍÍÍÕÕÕßßßØØØÛÛÛÜÜÜÅÅŵµµ¼¼¼¼¼¼ÅÅż¼¼ººººººººº¿¿¿ÆÆÆÆÆÆÉÉÉÅÅÅÃÃÃÃÃÃÆÆÆÇÇÇÌÌÌÐÐÐÕÕÕÐÐÐÉÉÉÂÂÂÀÀÀÆÆÆÎÎÎÔÔÔàààØØØÑÑÑÐÐÐÑÑÑÑÑÑÑÑÑÒÒÒ»»»ÇÇÇÕÕÕÆÆÆ¿¿¿ÌÌÌÇÇÇÂÂÂÃÃÃÅÅÅÆÆÆÆÆÆÉÉÉÍÍÍÒÒÒÕÕÕ¼¼¼ºººµµµµµµ¼¼¼ÀÀÀ¾¾¾···´´´ÀÀÀÐÐÐÎÎξ¾¾»»»ÉÉÉÒÒÒÇÇÇ»»»ººº¾¾¾ÇÇÇÎÎÎÑÑÑÎÎÎÕÕÕÔÔÔÍÍÍÉÉÉÊÊÊÇÇÇÀÀÀÙÙÙÒÒÒÇÇÇÂÂÂÅÅÅÊÊÊÊÊÊÆÆÆÀÀÀÅÅÅÆÆÆÑÑÑÔÔÔÒÒÒØØØÐÐÐÙÙÙÎÎο¿¿ÃÃÃÇÇÇÐÐÐÅÅž¾¾»»»ÃÃÃÐÐÐÛÛÛÛÛÛÎÎÎÆÆÆÇÇÇÇÇÇÇÇÇÌÌÌÐÐÐÔÔÔÕÕÕÑÑÑÊÊÊÅÅÅÆÆÆÅÅÅÃÃü¼¼ÔÔÔÐÐÐÉÉÉÉÉÉÉÉÉÇÇÇÆÆÆÃÃÃÃÃÃÆÆÆÇÇÇÊÊÊÍÍÍ×××ÑÑÑ×××ÐÐб±±´´´ÒÒÒÒÒÒÕÕÕÕÕÕÍÍÍÅÅÅÌÌÌÙÙÙÔÔÔÌÌÌÑÑÑ×××ÑÑÑÒÒÒØØØÔÔÔÇÇÇÝÝÝÎÎÎÑÑÑÆÆÆ¾¾¾ÒÒÒÒÒÒÐÐÐÊÊÊ¿¿¿×××îîîùùùñññùùùõõõöööóóóëëëæææäääàààÜÜÜâââÜÜÜàààÛÛÛ×××ØØØØØØãããÝÝÝââââââÙÙÙÙÙÙãããëëëîîîñññææææææííííííääääääëëëããããããÜÜÜÔÔÔÔÔÔ×××ÎÎÎÃÃÃÇÇÇÆÆÆÉÉÉÇÇÇÂÂÂÀÀÀÅÅÅÃÃÿ¿¿¼¼¼ºººººº»»»¾¾¾¿¿¿ÀÀÀÅÅÅÆÆÆÃÃü¼¼¿¿¿ÌÌÌÒÒÒÒÒÒÒÒÒÑÑÑÑÑÑÐÐÐÊÊÊÆÆÆÇÇÇÌÌÌÔÔÔØØØÙÙÙàààÎÎκºº»»»°°°´´´³³³³³³µµµººº¿¿¿ÃÃÃÃÃÃÇÇÇ¿¿¿ÅÅÅÇÇÇÅÅÅÇÇÇÌÌÌÍÍÍÌÌÌÉÉÉÉÉÉÊÊÊÍÍÍÐÐÐÑÑÑÒÒÒÕÕÕØØØÙÙÙØØØÔÔÔÊÊÊÂÂÂÍÍÍÍÍÍÆÆÆ¸¸¸¾¾¾ÇÇÇÃÃÃÍÍͼ¼¼¸¸¸···±±±¬¬¬¯¯¯µµµ­­­»»»ÆÆÆÅÅÅ»»»···¾¾¾ÅÅÅÆÆÆÉÉÉÍÍÍÉÉÉÀÀÀ¼¼¼¾¾¾ÀÀÀÌÌÌÍÍÍÎÎÎÎÎÎÌÌÌÆÆÆ¿¿¿»»»¿¿¿ÆÆÆÊÊÊÆÆÆÃÃþ¾¾ºººÑÑÑÊÊÊÃÃÃÂÂÂÆÆÆÊÊÊÉÉÉÅÅÅÉÉÉÎÎÎ×××àààÕÕÕÑÑÑÜÜÜ×××ÒÒÒÐÐÐÉÉÉÆÆÆÃÃÃÆÆÆÇÇÇÊÊÊÌÌÌÕÕÕÛÛÛàààâââÜÜÜØØØÝÝÝÎÎÎÌÌÌÌÌÌÉÉÉÅÅÅÊÊÊÎÎÎÊÊÊÉÉÉÇÇÇ¿¿¿¿¿¿¸¸¸ÐÐÐÎÎÎÉÉÉÆÆÆÆÆÆÃÃÃÂÂÂÀÀÀÂÂÂÅÅÅÆÆÆÌÌÌÎÎÎÕÕÕÑÑÑÕÕÕÎÎθ¸¸¸¸¸ÔÔÔÎÎÎÍÍÍÑÑÑÕÕÕÔÔÔÒÒÒÔÔÔÎÎÎÃÃÃÇÇÇÔÔÔÒÒÒÎÎÎÔÔÔÙÙÙÉÉÉàààÑÑÑÔÔÔÆÆÆÀÀÀÎÎÎÒÒÒÍÍÍÅÅÅ»»»âââèèèõõõèèèøøøãããççççççâââÝÝÝÝÝÝÝÝÝÜÜÜàààØØØÜÜÜÜÜÜÝÝÝßßßÙÙÙßßßÝÝÝßßßàààßßßÝÝÝÜÜÜÙÙÙØØØãããæææâââàààãããÝÝÝÛÛÛääääääßßß×××ÒÒÒ×××ÛÛÛÔÔÔÉÉÉÉÉÉÊÊÊÍÍÍÌÌÌÆÆÆÃÃÃÅÅÅÅÅÅÉÉÉÀÀÀ···±±±´´´»»»ÂÂÂÆÆÆÆÆÆÇÇÇÃÃû»»¸¸¸¾¾¾ÂÂÂÂÂÂÆÆÆÉÉÉÌÌÌÐÐÐÐÐÐÎÎÎÎÎÎÎÎÎÍÍÍØØØÛÛÛàààÕÕÕÊÊÊÇÇǵµµ¯¯¯¯¯¯¬¬¬¯¯¯µµµ»»»¿¿¿Â¼¼¼¼¼¼ÃÃÃÅÅÅÀÀÀ¼¼¼¾¾¾ÌÌÌÍÍÍÎÎÎÐÐÐÑÑÑÐÐÐÎÎÎÍÍÍÍÍÍÒÒÒØØØÛÛÛÛÛÛØØØÐÐÐÇÇÇÌÌÌÉÉÉÑÑÑ×××ØØØÉÉɳ³³µµµ¼¼¼°°°¯¯¯···¸¸¸´´´¾¾¾ÑÑѺºººººÂÂÂÀÀÀ¸¸¸¿¿¿ÐÐÐÅÅÅÇÇÇÉÉÉÊÊÊÌÌÌÇÇÇ¿¿¿ººº¾¾¾ÀÀÀÂÂÂÀÀÀÂÂÂÊÊÊÕÕÕßßß¾¾¾»»»»»»¼¼¼¼¼¼¾¾¾ÅÅÅÍÍÍÎÎÎÊÊÊÅÅÅÃÃÃÃÃÃÅÅÅÅÅÅÆÆÆÐÐÐÔÔÔ×××ÛÛÛÎÎÎÆÆÆÐÐÐÇÇÇÅÅÅÇÇÇÉÉÉÆÆÆÊÊÊÎÎÎ×××ØØØÐÐÐÒÒÒÉÉÉÃÃÃÆÆÆÆÆÆÌÌÌÙÙÙÜÜÜÛÛÛÙÙÙÎÎÎÀÀÀÃÃÃÍÍÍÊÊÊÀÀÀ¼¼¼ÃÃþ¾¾ÐÐÐÐÐÐÆÆÆÅÅÅÂÂÂÀÀÀ¿¿¿¿¿¿ÂÂÂÃÃÃÅÅÅÇÇÇÉÉÉÎÎÎÍÍÍÒÒÒÒÒÒÉÉÉÊÊÊÎÎÎÊÊÊÇÇÇÉÉÉÒÒÒÛÛÛÕÕÕÊÊÊÐÐÐÉÉÉÆÆÆÎÎÎÔÔÔÊÊÊÉÉÉØØØÍÍÍçççÕÕÕÔÔÔÆÆÆÉÉÉÎÎÎÒÒÒÉÉÉÃÃÃÅÅÅîîîêêêïïïâââëëëãããæææãããÜÜÜ×××××××××ÕÕÕÝÝÝÕÕÕÙÙÙÙÙÙÛÛÛÝÝÝÙÙÙàààßßßÕÕÕÐÐÐÔÔÔÙÙÙØØØÒÒÒÐÐÐÛÛÛäääâââßßßäääßßßÛÛÛãããêêêàààÔÔÔÍÍÍÑÑÑÕÕÕÑÑÑÉÉÉÆÆÆÉÉÉÊÊÊÊÊÊÇÇÇÅÅÅÂÂÂÃÃü¼¼µµµ­­­ªªª¯¯¯···¿¿¿ÅÅÅÂÂÂÆÆÆÅÅÅ¿¿¿ººº¸¸¸¸¸¸¸¸¸ÕÕÕÔÔÔÐÐÐÍÍÍÊÊÊÊÊÊÇÇÇÆÆÆÌÌÌÕÕÕØØØÙÙÙØØØÙÙÙØØØÌÌÌÆÆÆÂ···°°°³³³´´´···»»»´´´³³³···¿¿¿ÅÅÅÅÅÅÂÂÂÀÀÀÕÕÕÕÕÕÔÔÔÑÑÑÎÎÎÍÍÍÌÌÌÌÌÌÔÔÔÒÒÒÒÒÒÕÕÕ××××××ØØØÛÛÛØØØÂÂÂÉÉÉÍÍÍÃÃÃÆÆÆÐÐÐÜÜÜÛÛÛÐÐÐÎÎÎÔÔÔÎÎμ¼¼¸¸¸ÀÀÀÉÉÉ»»»µµµ¾¾¾ÆÆÆÆÆÆÃÃÃÃÃþ¾¾ÃÃÃÅÅÅÆÆÆÌÌÌÌÌÌÌÌÌÑÑÑ­­­»»»ÍÍÍØØØØØØÕÕÕÒÒÒÔÔÔÔÔÔÍÍÍÌÌÌÐÐÐÐÐÐÌÌÌÐÐÐÙÙÙÍÍÍÉÉÉÅÅÅÃÃÃÅÅÅÆÆÆÍÍÍÒÒÒÑÑÑÎÎÎÇÇÇÍÍÍÍÍÍÉÉÉÍÍÍÂÂÂÑÑѼ¼¼¾¾¾ÌÌÌÛÛÛÎÎÎÑÑÑÙÙÙàààÛÛÛÉÉɾ¾¾ÀÀÀ¿¿¿ÉÉÉàààÕÕÕÕÕÕÙÙÙÑÑÑÂÂÂÇÇÇÑÑÑÊÊʵµµ¿¿¿¾¾¾ÎÎÎÇÇÇÒÒÒÐÐÐÃÃÃÃÃÃÀÀÀ¾¾¾¼¼¼¿¿¿ÂÂÂÅÅÅÆÆÆÊÊÊÊÊÊÊÊÊÉÉÉÌÌÌÍÍÍÊÊÊÍÍÍÃÃÃÆÆÆÅÅÅÂÂÂÇÇÇÐÐÐÐÐÐÉÉÉÊÊÊÌÌÌÆÆÆÌÌÌÕÕÕÐÐÐÎÎÎÝÝÝÐÐÐííí×××ÑÑÑÆÆÆÔÔÔÑÑÑÑÑÑÆÆÆÇÇÇÛÛÛøøøïïïíííãããßßßÛÛÛÝÝÝÝÝÝÙÙÙÙÙÙßßßâââààààààØØØÙÙÙÒÒÒÌÌÌÌÌÌÌÌÌØØØÙÙÙÙÙÙÜÜÜÜÜÜØØØÒÒÒÕÕÕÙÙÙÌÌÌÔÔÔÔÔÔÒÒÒÕÕÕÐÐÐÊÊÊÐÐÐ×××ÒÒÒÐÐÐÐÐÐÒÒÒÑÑÑÊÊÊÂÂÂÉÉÉÌÌÌÇÇÇÃÃÃÃÃþ¾¾······±±±¯¯¯¬¬¬¬¬¬¯¯¯±±±´´´µµµ»»»¿¿¿ÅÅÅÃÃÃÀÀÀ¾¾¾»»»¸¸¸ÂÂÂÅÅÅÇÇÇÊÊÊÐÐÐÔÔÔÒÒÒÍÍÍÌÌÌÌÌÌÑÑÑÔÔÔØØØÜÜÜ×××ÔÔÔÐÐÐÒÒÒÌÌÌÇÇÇÉÉÉ······µµµ···ººº¿¿¿ÇÇÇÐÐÐÑÑÑÎÎÎØØØØØØÕÕÕÐÐÐÊÊÊÉÉÉÊÊÊÎÎÎÒÒÒÐÐÐÒÒÒØØØÒÒÒÇÇÇ¿¿¿¿¿¿âââÑÑÑÛÛÛØØØÇÇÇÇÇÇÅÅÅÀÀÀ»»»»»»¿¿¿ÅÅÅÅÅž¾¾···µµµ···ÀÀÀÇÇÇÅÅÅÀÀÀÀÀÀ¿¿¿ÆÆÆÊÊÊÆÆÆÀÀÀÂÂÂÃÃÃÇÇÇÒÒÒÊÊÊÎÎÎÒÒÒÕÕÕÔÔÔÒÒÒÔÔÔ×××ÕÕÕÒÒÒÑÑÑÑÑÑÐÐÐÍÍÍÊÊÊÉÉÉÉÉÉÃÃÃÀÀÀÅÅÅÊÊÊÌÌÌÐÐÐÕÕÕ×××ÕÕÕÇÇÇÊÊÊÒÒÒÑÑÑÒÒÒÍÍÍÉÉÉÃÃÃÒÒÒ×××ÎÎα±±ÀÀÀßßßÕÕÕÐÐÐÀÀÀ¼¼¼ÀÀÀ»»»ÂÂÂÜÜÜ×××ÑÑÑÔÔÔÍÍÍ¿¿¿ÅÅÅÉÉɺºº¾¾¾ÉÉÉÆÆÆÕÕÕÌÌÌÐÐÐÎÎÎÀÀÀÅÅÅÀÀÀ¼¼¼¼¼¼¿¿¿ÃÃÃÆÆÆÇÇÇÍÍÍÌÌÌÇÇÇÅÅÅÂÂÂÀÀÀÂÂÂÀÀÀ¾¾¾¿¿¿¿¿¿¾¾¾¾¾¾ÂÂÂÆÆÆÉÉÉÅÅÅÆÆÆÇÇÇÉÉÉÐÐÐÕÕÕÙÙÙÝÝÝÍÍÍíííÔÔÔÍÍÍÆÆÆßßßÔÔÔÎÎÎÃÃÃÇÇÇäääëëëæææÝÝÝãããÕÕÕâââäääâââÝÝÝÝÝÝßßßÝÝÝÙÙÙäääÒÒÒÌÌÌÇÇÇÊÊÊÍÍÍÅÅÅÆÆÆÒÒÒäääëëëàààÔÔÔÔÔÔ××××××ÔÔÔ××××××ØØØ×××ÑÑÑÍÍÍÐÐÐÍÍÍÎÎÎÒÒÒÕÕÕ×××ÔÔÔÎÎÎÊÊÊÌÌÌÌÌ̼¼¼ÀÀÀ¾¾¾···¸¸¸ÇÇÇÆÆÆÅÅÅÀÀÀ»»»µµµ³³³³³³³³³¸¸¸¿¿¿ÃÃÃÅÅÅÀÀÀ¼¼¼ººº¸¸¸¾¾¾ÃÃÃÉÉÉÑÑÑ×××ÒÒÒÉÉÉÊÊÊÂÂÂÌÌÌÒÒÒØØØ×××ÉÉÉÍÍÍÑÑÑÕÕÕÐÐÐÎÎÎÕÕÕÒÒÒÍÍÍÐÐÐÊÊÊÊÊÊÇÇÇÅÅÅÌÌÌ×××ØØØÒÒÒÔÔÔÕÕÕÕÕÕÐÐÐÊÊÊÉÉÉÌÌÌÐÐÐ×××ÑÑÑÒÒÒÙÙÙÔÔÔÅÅž¾¾ÂÂÂÙÙÙÕÕÕØØØÒÒÒÕÕÕØØØÅÅŵµµ¾¾¾ÀÀÀ¼¼¼···»»»ÆÆÆÊÊÊÆÆÆÅÅž¾¾»»»¾¾¾ÂÂÂÀÀÀ¾¾¾¾¾¾¼¼¼ÂÂÂÀÀÀ¿¿¿ÆÆÆÅÅÅÂÂÂÉÉÉÍÍÍÎÎÎÒÒÒ×××ÙÙÙ×××ÐÐÐÊÊÊÊÊÊÊÊÊÆÆÆ¿¿¿ÀÀÀÉÉÉÊÊÊÆÆÆÉÉÉÂÂÂÀÀÀÉÉÉÎÎÎÍÍÍÇÇÇÅÅÅÒÒÒ×××ÅÅÅ¿¿¿Â¼¼¼¾¾¾ÀÀÀÃÃÃÌÌÌÔÔÔÃÃÃÃÃÿ¿¿ÊÊÊÇÇÇÆÆÆÆÆÆ¾¾¾ÃÃÃÌÌÌÂÂÂÃÃÃßßßÛÛÛÐÐÐÎÎÎÇÇǾ¾¾ÉÉÉÌÌÌ···ÐÐÐ×××ÍÍÍ×××ÇÇÇÉÉÉÊÊÊ¿¿¿ÅÅÅÀÀÀ¼¼¼»»»¿¿¿ÃÃÃÆÆÆÇÇÇÇÇÇÆÆÆÂÂÂÀÀÀ¼¼¼ººº¾¾¾¼¼¼¿¿¿¸¸¸µµµººº»»»ººº¾¾¾ÆÆÆÆÆÆÆÆÆÊÊÊÉÉÉÆÆÆÒÒÒÛÛÛÒÒÒÇÇÇëëëÑÑÑÉÉÉÇÇÇççç×××ÌÌÌÎÎÎÑÑÑïïïãããàààÙÙÙïïïßßßßßßâââàààßßßßßßàààÜÜÜÕÕÕÍÍÍÅÅÅÊÊÊÊÊÊÍÍÍÐÐÐÉÉÉÎÎο¿¿ÎÎÎÎÎÎÅÅÅÎÎÎçççëëëÛÛÛ×××ÔÔÔÔÔÔ×××ÔÔÔÐÐÐÍÍÍÎÎÎÕÕÕÑÑÑÊÊÊÅÅÅÂÂÂÃÃÃÉÉÉÍÍÍÃÃÃÃÃúºº¸¸¸ÃÃÃÇÇÇÆÆÆÊÊÊÃÃÃÃÃÃÅÅÅÃÃÃÂÂÂÂÂÂÅÅÅÉÉɯ¯¯³³³ºººÀÀÀ¾¾¾ºººµµµ»»»¼¼¼¼¼¼¾¾¾ÇÇÇÒÒÒÔÔÔÎÎÎÑÑÑÉÉÉÎÎÎÎÎÎ×××ßßßÔÔÔÔÔÔÐÐÐÑÑÑÔÔÔÙÙÙÝÝÝÝÝÝÛÛÛ×××ÒÒÒÒÒÒÒÒÒÕÕÕÙÙÙÛÛÛÙÙÙØØØ×××ÎÎÎÍÍÍÒÒÒÔÔÔÎÎÎÍÍÍÑÑÑÎÎÎÕÕÕÕÕÕÍÍÍÅÅÅÂÂÂÃÃÃÃÃÃÂÂÂÇÇÇÎÎÎÑÑÑÐÐÐÎÎÎÍÍÍÍÍÍÌÌÌÌÌÌÌÌÌÊÊÊÇÇÇÃÃÿ¿¿¼¼¼¿¿¿¾¾¾¾¾¾¼¼¼¼¼¼¼¼¼¾¾¾¾¾¾ÀÀÀ¿¿¿ÂÂÂÆÆÆÇÇÇÆÆÆÉÉÉÎÎÎÍÍÍÒÒÒººº¸¸¸¿¿¿ÇÇÇØØØÇÇÇÅÅÅÉÉÉÌÌÌÉÉÉÃÃÃÀÀÀÅÅÅÉÉÉÂÂÂÉÉÉÉÉÉÕÕÕÕÕÕÃÃÃÉÉÉØØØ¿¿¿ÉÉÉÒÒÒØØØ×××ÔÔÔÒÒÒÒÒÒÝÝÝÑÑÑÅÅÅÀÀÀÀÀÀÀÀÀÂÂÂÆÆÆÅÅÅÂÂÂÂÂÂÅÅÅÃÃÃÃÃÃÍÍÍØØØÕÕÕÑÑÑÇÇǼ¼¼ÆÆÆÇÇÇ¿¿¿×××ÌÌÌÐÐÐÊÊÊÆÆÆÉÉÉÅÅÅ¿¿¿ÂÂÂÃÃÃÂÂÂÂÂÂÂÂÂÅÅÅÇÇÇÊÊÊÌÌÌÇÇÇÅÅÅÀÀÀ¾¾¾»»»ººººººººººººººººººººº»»»¼¼¼¿¿¿¿¿¿ÂÂÂÇÇÇÍÍÍÉÉÉÅÅÅÒÒÒÛÛÛÐÐÐÒÒÒÒÒÒâââ¼¼¼ÅÅÅàààÜÜÜÎÎÎÉÉÉâââëëë×××ßßßèèèÙÙÙäääÍÍÍÐÐÐÌÌÌÔÔÔßßßíííÐÐÐÊÊÊÍÍÍÍÍÍÍÍÍÎÎÎÍÍÍÍÍÍÌÌÌÌÌÌÉÉÉÉÉÉÊÊÊÊÊÊÊÊÊÉÉÉÇÇÇÆÆÆÉÉÉâââÝÝÝÐÐÐÊÊÊÐÐÐ×××¼¼¼ÇÇÇÆÆÆÃÃÃÊÊÊÉÉÉÂÂÂÃÃþ¾¾ÊÊÊÑÑÑÌÌÌÊÊÊÎÎÎÐÐÐÌÌÌÃÃÃÃÃÃÂÂÂÂÂÂÂÂÂÃÃÃÃÃÃÅÅÅÃÃÃÃÃô´´µµµ¾¾¾ÂÂÂÇÇÇ···¼¼¼ÆÆÆÃÃÿ¿¿ÇÇÇÎÎÎÎÎÎÐÐÐÐÐÐÇÇÇÍÍÍÍÍÍÔÔÔÛÛÛÒÒÒÔÔÔÔÔÔÒÒÒÑÑÑÑÑÑÕÕÕÙÙÙÜÜÜßßßÛÛÛÕÕÕÎÎÎÌÌÌÍÍÍÔÔÔÙÙÙÝÝÝÔÔÔÑÑÑÌÌÌÊÊÊÌÌÌÑÑÑÔÔÔÕÕÕÒÒÒÕÕÕÒÒÒÇÇǾ¾¾¾¾¾ÀÀÀÃÃÃÑÑÑÒÒÒÒÒÒÎÎÎÉÉÉÅÅÅÂÂÂÀÀÀÃÃÃÃÃÃÂÂÂÂÂÂÀÀÀ¾¾¾¼¼¼»»»¿¿¿¾¾¾¾¾¾¼¼¼¼¼¼¼¼¼¾¾¾¾¾¾ÂÂÂÀÀÀÀÀÀÅÅÅÅÅÅÅÅÅÉÉÉÐÐд´´ÅÅźººººº¸¸¸¼¼¼ÑÑÑÊÊÊÉÉÉÆÆÆÅÅÅÅÅÅÇÇÇÉÉÉÉÉÉÉÉÉÌÌÌÔÔÔÀÀÀ¸¸¸ÆÆÆÔÔÔÑÑѾ¾¾ÕÕÕÒÒÒÍÍÍÉÉÉÉÉÉÎÎÎÙÙÙâââÙÙÙÎÎÎÃÃÿ¿¿¼¼¼ºººººº¼¼¼ÂÂÂÀÀÀÀÀÀÀÀÀ¿¿¿ÀÀÀÉÉÉÑÑÑÛÛÛÒÒÒÃÃþ¾¾ÇÇÇÃÃü¼¼ÍÍÍÌÌÌÍÍÍÇÇÇÅÅÅÊÊÊÆÆÆÀÀÀÂÂÂÀÀÀÀÀÀÂÂÂÂÂÂÅÅÅÆÆÆÉÉÉÊÊÊÅÅÅÃÃÃÀÀÀ¼¼¼ººº¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸ººº»»»¾¾¾¿¿¿ÀÀÀÃÃÃÆÆÆÌÌÌÊÊÊÆÆÆÑÑÑÙÙÙÕÕÕÑÑÑÔÔÔàààÉÉÉÔÔÔÜÜÜÕÕÕÍÍÍÆÆÆçççëëëÛÛÛàààßßßÐÐÐÙÙÙÑÑÑÔÔÔÎÎÎÎÎÎÒÒÒßßßÌÌÌÌÌÌÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÎÎÎÎÎÎÎÎÎÉÉÉÉÉÉÊÊÊÊÊÊÉÉÉÇÇÇÆÆÆÅÅż¼¼ÊÊÊÅÅÅ¿¿¿¼¼¼¿¿¿ÇÇǾ¾¾ÅÅÅÉÉÉÇÇÇÆÆÆÉÉÉÂÂÂÀÀÀÉÉÉÀÀÀÊÊÊÎÎÎÇÇÇÃÃÃÇÇÇÉÉÉÆÆÆÇÇÇÅÅÅ¿¿¿»»»»»»¿¿¿ÃÃÃÆÆÆÆÆÆÉÉɺººµµµ´´´¸¸¸ÆÆÆÂÂÂÃÃÃÉÉÉÅÅÅ¿¿¿ÃÃÃÃÃÃÂÂÂÅÅÅÍÍÍÉÉÉÌÌÌÊÊÊÎÎÎÔÔÔÐÐÐÑÑÑ×××ÔÔÔÑÑÑÎÎÎÐÐÐÔÔÔÙÙÙÝÝÝÕÕÕÔÔÔÔÔÔÕÕÕ××××××ÔÔÔÑÑÑÐÐÐÒÒÒÎÎÎÆÆÆÉÉÉÒÒÒÕÕÕÐÐÐÔÔÔÛÛÛÛÛÛÐÐÐÃÃü¼¼ººº···ÒÒÒÑÑÑÎÎÎÉÉÉÃÃÃÀÀÀ¿¿¿ÀÀÀ¼¼¼»»»»»»»»»ººº»»»»»»»»»¿¿¿¾¾¾¾¾¾¼¼¼¼¼¼¾¾¾¾¾¾¿¿¿ÃÃÃÀÀÀ¿¿¿ÂÂÂÂÂÂÂÂÂÉÉÉÐÐа°°ÅÅÅÅÅÅÇÇÇÂÂÂÀÀÀÔÔÔÒÒÒÍÍÍÊÊÊÇÇÇÆÆÆÊÊÊÎÎÎÑÑÑÑÑÑØØØÕÕÕÇÇÇÊÊÊÍÍÍÂÂÂÃÃÃÉÉÉÉÉÉÆÆÆÂ¿¿¿¼¼¼¿¿¿ÂÂÂÆÆÆÅÅÅ¿¿¿»»»»»»»»»···¸¸¸»»»¼¼¼¿¿¿¿¿¿»»»¸¸¸¼¼¼ÂÂÂÆÆÆ×××ÑÑÑ¿¿¿ÂÂÂÌÌÌÀÀÀ¸¸¸¾¾¾ÐÐÐÎÎÎÆÆÆÂÂÂÅÅÅÃÃÃÀÀÀÀÀÀ¾¾¾¿¿¿ÀÀÀÃÃÃÅÅÅÅÅÅÆÆÆÆÆÆÀÀÀÀÀÀ¾¾¾¼¼¼ººº¸¸¸···µµµ···¸¸¸¸¸¸ººº¼¼¼¿¿¿ÀÀÀÂÂÂÅÅÅÅÅÅÊÊÊÌÌÌÉÉÉÎÎÎØØØÜÜÜÔÔÔ×××ÙÙÙÑÑÑàààÔÔÔÍÍÍÍÍ;¾¾êêêçççÜÜÜãããÕÕÕÉÉÉÒÒÒÕÕÕ×××ÒÒÒÎÎÎÍÍÍÕÕÕÉÉÉÎÎÎÒÒÒÒÒÒÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÊÊÊÊÊÊÊÊÊÉÉÉÇÇÇÆÆÆÃÃÃÃÃÃÊÊÊÉÉÉÂÂÂÅÅÅÃÃÿ¿¿ÆÆÆÉÉÉÉÉÉÍÍÍÇÇǾ¾¾ÀÀÀÆÆÆÅÅÅÃÃÿ¿¿ÆÆÆÆÆÆ¾¾¾¸¸¸»»»»»»¸¸¸¾¾¾ºººµµµ±±±°°°³³³···ºººÂÂÂÉÉÉ»»»±±±°°°ÀÀÀÉÉÉÀÀÀÃÃÃÀÀÀ¿¿¿ÀÀÀ¿¿¿¿¿¿ÊÊÊÍÍÍÌÌÌÌÌÌÉÉÉÉÉÉÌÌÌÊÊÊÍÍÍÕÕÕÕÕÕ×××ÔÔÔÒÒÒÑÑÑÔÔÔ×××ØØØØØØÙÙÙÜÜÜÝÝÝÛÛÛÕÕÕÑÑÑÌÌÌÑÑÑÑÑÑÍÍÍÍÍÍÐÐÐÊÊÊÀÀÀ»»»ÇÇÇÒÒÒÔÔÔÑÑÑÑÑÑÑÑÑÐÐÐÌÌÌÊÊÊÇÇÇÃÃÃÀÀÀ¿¿¿ÀÀÀÀÀÀ¼¼¼»»»ººº¸¸¸¸¸¸»»»¼¼¼¾¾¾¾¾¾¾¾¾¼¼¼¼¼¼¼¼¼¾¾¾¿¿¿¿¿¿Â¿¿¿¼¼¼¿¿¿¿¿¿ÀÀÀÇÇÇÐÐи¸¸ÆÆÆÇÇÇÌÌÌÇÇÇÂÂÂÍÍÍÍÍÍÀÀÀÉÉÉÒÒÒ×××ÕÕÕÕÕÕÙÙÙÜÜÜ´´´ÊÊÊÇÇÇÃÃÃÆÆÆÎÎÎÝÝÝâââÅÅÅÅÅÅÃÃÃÃÃÃÂÂÂÀÀÀ¾¾¾¼¼¼µµµ³³³´´´¸¸¸¸¸¸···¸¸¸»»»ºººÀÀÀÀÀÀºººµµµººº¾¾¾¼¼¼ÇÇÇÌÌÌ»»»ÀÀÀÊÊÊ»»»°°°ÐÐÐÎÎÎÉÉÉ¿¿¿¾¾¾¾¾¾ÀÀÀ¼¼¼¾¾¾ÀÀÀÃÃÃÃÃÃÃÃÃÃÃþ¾¾¾¾¾¼¼¼»»»ººº···µµµ´´´······¸¸¸ººº¼¼¼¿¿¿ÂÂÂÃÃÃÅÅÅÅÅÅÉÉÉÍÍÍÊÊÊÌÌÌ×××ãããÔÔÔÛÛÛÑÑÑÍÍÍßßßÉÉÉÇÇÇÊÊÊ···èèèàààÝÝÝæææÐÐÐÊÊÊÕÕÕØØØÔÔÔÔÔÔÐÐÐÐÐÐÕÕÕÍÍÍÐÐÐÑÑÑÑÑÑÐÐÐÐÐÐÐÐÐÐÐÐÑÑÑÑÑÑÌÌÌÌÌÌÊÊÊÉÉÉÇÇÇÅÅÅÃÃÃÃÃÃÉÉÉÅÅÅÂÂÂÇÇÇÇÇÇÅÅÅÆÆÆÊÊÊÉÉÉÆÆÆ¾¾¾¸¸¸¾¾¾ÆÆÆÅÅÅ¿¿¿ÂÂÂÇÇÇÇÇÇÀÀÀ»»»»»»ººº···¬¬¬­­­±±±´´´µµµ···µµµµµµµµµ¿¿¿ÆÆÆÅÅźºº±±±¸¸¸ÂÂÂÉÉÉÊÊÊÅÅÅÃÃúºººººÆÆÆÍÍÍÎÎÎÌÌÌÉÉÉÆÆÆÅÅÅÇÇÇÇÇÇÐÐÐÒÒÒÕÕÕÕÕÕÔÔÔÒÒÒÔÔÔÕÕÕÛÛÛÜÜÜßßßããããããàààÙÙÙÔÔÔÌÌÌÍÍÍÎÎÎÐÐÐÐÐÐÌÌÌÅÅž¾¾ÆÆÆÎÎÎÔÔÔÐÐÐÌÌÌÌÌÌÎÎÎÎÎÎÌÌÌÊÊÊÆÆÆÂ¿¿¿¼¼¼ººº¸¸¸¼¼¼»»»¸¸¸······¸¸¸»»»¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¾¾¾¾¾¾¿¿¿ÀÀÀ¼¼¼¼¼¼¾¾¾¿¿¿ÀÀÀÇÇÇÐÐÐÀÀÀÊÊÊÌÌÌÐÐÐÊÊÊÃÃÃÊÊÊÎÎÎÐÐÐÑÑÑÐÐÐÉÉÉÀÀÀ¼¼¼¿¿¿ÅÅÅÂÂÂÊÊÊÃÃÃÉÉÉÐÐÐÇÇÇÃÃû»»ÆÆÆÂººº´´´´´´···¼¼¼¿¿¿···´´´´´´······´´´´´´¸¸¸»»»ÂÂÂÃÃü¼¼···¸¸¸ººº¸¸¸»»»ÇÇǺºº···¿¿¿ÂÂÂÃÃó³³ÀÀÀÅÅÅÌÌÌÊÊÊÃÃþ¾¾¾¾¾¾¾¾»»»¼¼¼¿¿¿ÂÂÂÃÃÃÃÃÃÀÀÀÀÀÀ¼¼¼¼¼¼»»»»»»ººº¸¸¸···µµµ···¸¸¸¸¸¸»»»¼¼¼¿¿¿ÂÂÂÃÃÃÅÅÅÅÅÅÇÇÇÌÌÌÍÍÍÌÌÌÕÕÕäääÎÎÎÙÙÙÌÌÌÆÆÆÙÙÙÅÅÅÅÅÅ¿¿¿¼¼¼çççÛÛÛÝÝÝæææÎÎÎÎÎÎØØØÕÕÕÊÊÊÌÌÌÇÇÇÍÍÍÔÔÔÐÐÐÐÐÐÊÊÊÌÌÌÌÌÌÌÌÌÍÍÍÎÎÎÎÎÎÐÐÐÍÍÍÌÌÌÊÊÊÇÇÇÆÆÆÅÅÅÃÃÃÃÃþ¾¾¿¿¿ÃÃÃÃÃÃÆÆÆÇÇÇÅÅÅÃÃÃÅÅŵµµ´´´ÀÀÀººº¾¾¾ÌÌÌÐÐÐÔÔÔÕÕÕÑÑÑÎÎÎÌÌÌÉÉÉÅÅÅÇÇÇÉÉÉÊÊÊÉÉÉÅÅż¼¼µµµ°°°°°°´´´ÀÀÀÇÇǸ¸¸µµµ¼¼¼ÊÊÊÌÌÌÉÉÉÇÇÇÆÆÆ¿¿¿¿¿¿ÌÌÌÌÌÌÎÎÎÉÉÉÊÊÊÇÇÇÃÃÃÇÇÇÅÅÅÌÌÌÌÌÌÍÍÍÎÎÎÐÐÐÔÔÔØØØÛÛÛØØØÙÙÙÜÜÜàààâââßßßÙÙÙÕÕÕÐÐÐÍÍÍÊÊÊÊÊÊÌÌÌÊÊÊÉÉÉÇÇǼ¼¼ÇÇÇÐÐÐÎÎÎÌÌÌÌÌÌÍÍÍÌÌÌÉÉÉÆÆÆÃÃÃÀÀÀ¾¾¾»»»···´´´¸¸¸···´´´³³³³³³´´´µµµ···»»»»»»ººº»»»»»»¼¼¼¾¾¾¿¿¿¾¾¾¼¼¼¾¾¾ÃÃÃÅÅÅÆÆÆÌÌÌÒÒÒÃÃÃÉÉÉÐÐÐÒÒÒÊÊÊÂÂÂÊÊÊÕÕÕÔÔÔÐÐÐÊÊÊÆÆÆÇÇÇÌÌÌÎÎÎÐÐÐÐÐÐÊÊÊÅÅÅÔÔÔÑÑÑ´´´³³³Â³³³µµµ¸¸¸¼¼¼ÀÀÀÅÅÅÉÉÉÌÌ̾¾¾¸¸¸µµµ···¸¸¸···¸¸¸¼¼¼¼¼¼ÂÂÂÃÃÿ¿¿ººº¸¸¸·········ÃÃþ¾¾³³³µµµ¿¿¿ÇÇÇÀÀÀ³³³ºººÇÇÇÎÎÎÉÉÉÅÅÅ»»»»»»¼¼¼¿¿¿ÂÂÂÂÂÂÂÂÂÀÀÀ¿¿¿¼¼¼¼¼¼»»»ºººººº¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸ººº»»»¾¾¾¿¿¿ÂÂÂÃÃÃÅÅÅÆÆÆÇÇÇÊÊÊÍÍÍÍÍÍÒÒÒâââÍÍÍÔÔÔÌÌÌÆÆÆØØØÇÇÇÃÃô´´ÊÊÊæææØØØÝÝÝãããÍÍÍÎÎÎÕÕÕÐÐп¿¿Â¾¾¾ÅÅÅÉÉÉÊÊÊÊÊÊÃÃÃÅÅÅÆÆÆÉÉÉÌÌÌÌÌÌÍÍÍÍÍÍÊÊÊÉÉÉÇÇÇÆÆÆÅÅÅÃÃÃÃÃÃÃÃÃÅÅÅÇÇÇÍÍÍÅÅÅÀÀÀÅÅž¾¾ººº¸¸¸³³³»»»ÃÃþ¾¾¸¸¸ÆÆÆÕÕÕ×××ØØØÛÛÛÙÙÙØØØÔÔÔÐÐÐÍÍÍÍÍÍÎÎÎÎÎÎÎÎÎÎÎÎÌÌÌÉÉÉÇÇǸ¸¸±±±ºººÂÂÂÃÃü¼¼µµµ¾¾¾ÃÃÃÉÉÉÇÇÇÇÇÇÌÌÌÉÉÉÉÉÉÑÑÑÇÇÇÌÌÌÆÆÆÊÊÊÊÊÊÆÆÆÊÊÊÅÅÅÉÉÉÇÇÇÇÇÇÉÉÉÍÍÍÑÑÑÔÔÔÕÕÕÛÛÛÕÕÕÎÎÎÌÌÌÎÎÎÔÔÔÙÙÙÜÜÜÔÔÔÕÕÕÐÐÐÇÇÇÇÇÇÎÎÎÐÐÐÊÊʵµµÃÃÃÐÐÐÒÒÒÐÐÐÎÎÎÍÍÍÊÊÊÅÅÅ¿¿¿¾¾¾¾¾¾¼¼¼ººº···´´´³³³³³³±±±±±±³³³´´´µµµ¸¸¸¸¸¸¸¸¸ºººººº»»»¼¼¼¾¾¾¾¾¾¾¾¾ÃÃÃÊÊÊÍÍÍÍÍÍÑÑÑ××׿¿¿ÅÅÅÌÌÌÇÇÇÀÀÀÂÂÂÌÌ̸¸¸»»»ÀÀÀÆÆÆÊÊÊÇÇÇÃÃþ¾¾ÅÅÅØØØÌÌ̸¸¸´´´¼¼¼ÐÐÐÕÕÕÐÐÐ×××ÝÝÝßßßÜÜÜÕÕÕÑÑÑÎÎÎÊÊÊÀÀÀ¸¸¸¸¸¸ººº»»»¾¾¾Â¾¾¾¿¿¿ÂÂÂÃÃü¼¼µµµ´´´···¸¸¸¿¿¿ÇÇÇÀÀÀ¸¸¸¼¼¼ÂÂÂÊÊʼ¼¼···¼¼¼ÅÅÅÆÆÆÉÉÉÆÆÆ»»»¼¼¼¾¾¾¿¿¿ÀÀÀÂÂÂÀÀÀÀÀÀ¿¿¿¾¾¾¼¼¼»»»ººººººººº»»»¼¼¼ºººººº»»»»»»¾¾¾¿¿¿ÀÀÀÂÂÂÃÃÃÉÉÉÇÇÇÉÉÉÎÎÎÎÎÎÑÑÑÜÜÜ×××ÐÐÐÊÊÊÉÉÉØØØÊÊÊÆÆÆµµµ×××ààà×××ÝÝÝàààÎÎÎÎÎÎÎÎÎÆÆÆ¸¸¸ÇÇÇÂÂÂÅÅÅ¿¿¿¿¿¿¾¾¾¼¼¼¿¿¿ÃÃÃÇÇÇÊÊÊÌÌÌÌÌÌÌÌÌÆÆÆÅÅÅÃÃÃÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÅÅÅÃÃÃÆÆÆ¸¸¸±±±µµµ¯¯¯³³³···¼¼¼Â¿¿¿»»»ÉÉÉ×××ÕÕÕØØØØØØØØØØØØ×××ÒÒÒÐÐÐÍÍÍÎÎÎÎÎÎÎÎÎÍÍÍÍÍÍÌÌÌÌÌÌÊÊÊÃÃô´´ºººÀÀÀÃÃÿ¿¿¸¸¸ÅÅÅÇÇÇÎÎÎÌÌÌÇÇÇÊÊÊÇÇÇÃÃÃÅÅÅÅÅÅÊÊÊÃÃÃÊÊÊÍÍÍÉÉÉÎÎÎÇÇÇÇÇÇÇÇÇÇÇÇÉÉÉÌÌÌÍÍÍÊÊÊÉÉÉÍÍÍÊÊÊÉÉÉÉÉÉÍÍÍÐÐÐÒÒÒÒÒÒØØØßßßÙÙÙÉÉÉÇÇÇÒÒÒÑÑÑÅÅÅÇÇÇÐÐÐÔÔÔÐÐÐÊÊÊÊÊÊÊÊÊÊÊÊÇÇÇÃÃþ¾¾»»»»»»ººº¸¸¸µµµ³³³³³³³³³³³³´´´µµµ···¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸ººº»»»¼¼¼¾¾¾¾¾¾ÀÀÀÇÇÇÐÐÐÔÔÔÒÒÒÕÕÕÙÙÙÒÒÒÅÅÅÃÃÃÍÍÍÒÒÒÍÍÍÅÅÅÆÆÆÅÅÅÇÇÇÊÊÊÉÉÉÇÇÇÌÌÌÕÕÕßßßÀÀÀ¿¿¿¯¯¯···ÊÊÊÍÍÍÌÌÌÅÅÅÉÉÉÉÉÉÉÉÉÇÇÇÉÉÉÐÐÐÜÜÜæææÜÜÜÎÎÎÀÀÀ»»»ººº¸¸¸ººº¼¼¼¾¾¾¼¼¼ÀÀÀÅÅž¾¾´´´±±±µµµ···»»»ÒÒÒÒÒÒÃÃû»»¸¸¸ÊÊÊÐÐм¼¼´´´···¼¼¼ÇÇÇÇÇÇ»»»¾¾¾¾¾¾¿¿¿ÀÀÀÀÀÀÀÀÀÀÀÀ¿¿¿¿¿¿¾¾¾»»»ºººººº»»»¼¼¼¾¾¾»»»»»»»»»¼¼¼¼¼¼¿¿¿ÀÀÀÂÂÂÂÂÂÊÊÊÇÇÇÆÆÆÎÎÎÐÐÐÐÐÐØØØäääÎÎÎÉÉÉÇÇÇÕÕÕÌÌÌÊÊÊ¿¿¿ÙÙÙÙÙÙÔÔÔÝÝÝßßßÒÒÒÐÐÐÍÍ;¾¾¸¸¸ÒÒÒÐÐÐÌÌÌ»»»···´´´¸¸¸¼¼¼ÂÂÂÇÇÇÌÌÌÍÍÍÌÌÌÌÌÌÂÂÂÀÀÀ¿¿¿¾¾¾¼¼¼¾¾¾¾¾¾¿¿¿¾¾¾···»»»°°°¬¬¬±±±±±±¿¿¿ÅÅž¾¾¼¼¼¾¾¾ÅÅÅØØØàààÔÔÔÝÝÝÜÜÜÙÙÙÙÙÙ×××ÕÕÕÒÒÒÑÑÑÍÍÍÎÎÎÐÐÐÐÐÐÐÐÐÎÎÎÌÌÌÊÊÊÉÉÉ···¾¾¾ÃÃÃÅÅÅÀÀÀ···ÆÆÆ¿¿¿ÉÉÉÇÇÇÃÃÃÉÉÉÌÌÌÆÆÆÅÅÅÆÆÆÅÅÅÅÅÅÉÉÉÍÍÍÐÐÐÍÍÍÉÉÉÍÍÍÉÉÉÆÆÆÆÆÆÊÊÊÎÎÎÐÐÐÑÑÑØØØ×××ÔÔÔÑÑÑÊÊÊÅÅÅÉÉÉÑÑÑÒÒÒÎÎÎÔÔÔÕÕÕÆÆÆ¿¿¿ÊÊÊÑÑÑÉÉÉÃÃÃÔÔÔØØØÑÑÑÍÍÍÅÅÅÅÅÅÃÃÿ¿¿»»»¼¼¼ÀÀÀ¾¾¾······³³³±±±µµµµµµ³³³µµµ¼¼¼µµµ···¸¸¸ººººººººººººººººººÐÐÐÇÇÇÀÀÀ¾¾¾ººº¿¿¿¸¸¸ÕÕÕÂÂÂÃÃÃÔÔÔÔÔÔÍÍÍÐÐÐÕÕÕÒÒÒÊÊʾ¾¾¿¿¿ÌÌÌÊÊÊÀÀÀ¾¾¾´´´¾¾¾ÊÊÊÎÎÎÊÊÊÆÆÆÆÆÆÉÉÉÅÅÅÃÃÃÂÂÂÂÂÂÅÅÅÉÉÉÍÍÍÐÐÐÐÐÐÒÒÒÕÕÕÒÒÒÉÉÉÀÀÀ»»»»»»¸¸¸¼¼¼ÀÀÀÀÀÀººº···ººº¼¼¼¼¼¼ÃÃÃÌÌÌÐÐÐÑÑÑÃÃø¸¸ÂÂÂÌÌÌÀÀÀÀÀÀÀÀÀµµµµµµÃÃÃÊÊÊÀÀÀ»»»¿¿¿ÀÀÀ»»»¾¾¾ÃÃþ¾¾¼¼¼¼¼¼¼¼¼¼¼¼¾¾¾¾¾¾¿¿¿ÀÀÀ¿¿¿¾¾¾¼¼¼»»»»»»¼¼¼¿¿¿ÀÀÀÆÆÆÌÌÌÉÉÉÍÍÍÒÒÒÍÍÍÍÍÍÛÛÛÇÇÇÑÑÑÉÉÉÉÉɸ¸¸ÑÑÑÀÀÀÆÆÆ¯¯¯ëëëßßßØØØßßßÐÐÐÑÑÑ»»»¾¾¾ÍÍÍÛÛÛÑÑѸ¸¸±±±»»»···¼¼¼ÃÃÃÉÉÉÌÌÌÌÌÌÌÌÌÌÌÌÂÂÂÀÀÀ¿¿¿¾¾¾¼¼¼ººº¸¸¸···±±±±±±±±±ÂÂÂÅÅÅÃÃÃÊÊÊ»»»ÅÅÅ»»»±±±»»»ÐÐÐÔÔÔÌÌÌÉÉÉÎÎÎÝÝÝÑÑÑÐÐÐÔÔÔÎÎÎÑÑÑÐÐÐÍÍÍÊÊÊÇÇÇÉÉÉÎÎÎÑÑÑÍÍÍÉÉɵµµººº»»»ÂÂÂÉÉÉ»»»ÀÀÀÆÆÆÆÆÆÇÇÇÉÉÉÊÊÊÊÊÊÊÊÊÉÉÉÇÇÇÉÉÉÊÊÊÉÉÉÉÉÉÊÊÊÎÎÎÒÒÒÊÊÊÊÊÊÉÉÉÊÊÊÌÌÌÍÍÍÍÍÍÌÌÌÒÒÒÑÑÑÒÒÒÒÒÒÍÍÍÅÅÅÃÃÃÇÇÇÎÎÎÉÉÉÎÎÎÒÒÒÍÍÍÌÌÌÎÎÎÌÌÌÊÊÊÀÀÀÌÌÌÎÎÎÉÉÉÊÊÊÇÇÇÊÊÊÅÅÅÇÇÇÅÅÅ¿¿¿»»»»»»¸¸¸´´´ºººººº¸¸¸¸¸¸´´´³³³µµµ»»»ººº»»»¼¼¼¼¼¼¾¾¾¿¿¿ÀÀÀÃÃÃÀÀÀÒÒÒÌÌÌÊÊÊÍÍÍÌÌÌÑÑÑÎÎÎÊÊÊÇÇÇÊÊÊÉÉɼ¼¼ººº¾¾¾¾¾¾ººº¾¾¾»»»ÅÅÅÑÑѱ±±»»»ÅÅÅÌÌÌÑÑÑÐÐÐÇÇÇ¿¿¿»»»»»»¾¾¾¾¾¾¼¼¼¼¼¼¾¾¾ÂÂÂÆÆÆÉÉÉÎÎÎÍÍÍÐÐÐÐÐÐÒÒÒÎÎÎÀÀÀ¼¼¼»»»¼¼¼ÀÀÀÂÂÂÀÀÀÀÀÀÂÂÂÂÂÂÑÑÑÔÔÔÆÆÆÃÃÃÒÒÒÎÎλ»»ºººÅÅÅÆÆÆÇÇÇÆÆÆÅÅÅÀÀÀÀÀÀÅÅÅÉÉÉÀÀÀ¿¿¿ÀÀÀ¼¼¼»»»¼¼¼¼¼¼¾¾¾¾¾¾¼¼¼¼¼¼¾¾¾¿¿¿ÀÀÀÀÀÀ¾¾¾¼¼¼¼¼¼»»»»»»¼¼¼¾¾¾¿¿¿ÂÂÂÉÉÉÌÌÌÌÌÌÍÍÍÌÌÌÑÑÑÜÜÜÍÍÍÐÐÐÎÎÎÒÒÒ¼¼¼ÐÐÐÂÂÂÃÃð°°çççÛÛÛÒÒÒÔÔÔÇÇÇÑÑÑÌÌ̺ºº¸¸¸¿¿¿ÉÉÉÆÆÆ¸¸¸µµµ¼¼¼¸¸¸¾¾¾ÅÅÅÊÊÊÍÍÍÍÍÍÍÍÍÍÍÍÌÌÌÅÅž¾¾ººº¸¸¸¸¸¸···´´´³³³¸¸¸»»»ÅÅÅÃÃÃÂÂÂÉÉÉ»»»···µµµµµµÃÃÃÕÕÕ×××ÍÍÍÌÌÌÍÍÍÛÛÛÔÔÔÑÑÑÔÔÔÍÍÍÑÑÑÎÎÎÎÎÎÌÌÌÌÌÌÍÍÍÎÎÎÉÉɼ¼¼³³³´´´¿¿¿ÃÃÃÃÃÿ¿¿µµµ¸¸¸ÇÇÇÆÆÆÇÇÇÇÇÇÇÇÇÇÇÇÆÆÆÇÇÇÇÇÇÅÅÅÉÉÉÌÌÌÇÇÇÃÃÃÅÅÅÍÍÍ×××ÊÊÊÍÍÍÐÐÐÑÑÑÐÐÐÎÎÎÍÍÍÌÌÌÎÎÎÍÍÍÎÎÎÒÒÒÑÑÑÊÊÊÇÇÇÉÉÉÆÆÆÂÂÂÅÅÅÊÊÊÎÎÎÔÔÔÑÑÑÅÅÅÎÎο¿¿ÀÀÀººº³³³······ºººÃÃÃÊÊÊÍÍÍÉÉÉÃÃÿ¿¿ººº´´´±±±µµµ···´´´´´´¸¸¸¼¼¼¿¿¿¸¸¸ºººººº¸¸¸···ººº¾¾¾Â°°°ÀÀÀÀÀÀÀÀÀ¿¿¿ÇÇÇÎÎÎÔÔÔÒÒÒÔÔÔÐÐÐÉÉÉÌÌÌÌÌÌÂÂÂÇÇÇÍÍÍÆÆÆÊÊÊÕÕÕÅÅž¾¾ÜÜÜÉÉÉÌÌÌÎÎÎÍÍÍÇÇÇÀÀÀ¼¼¼»»»»»»ººº¸¸¸¸¸¸»»»¾¾¾ÂÂÂÃÃÃÍÍÍÉÉÉÊÊÊÉÉÉØØØÙÙÙ¾¾¾¸¸¸»»»¾¾¾¼¼¼¼¼¼ÂÂÂÉÉÉÎÎÎÒÒÒÕÕÕ×××¼¼¼µµµÑÑÑÙÙÙÊÊÊÃÃþ¾¾ÊÊÊÊÊÊÇÇÇÍÍÍÉÉÉ¿¿¿ÀÀÀÌÌÌÆÆÆÀÀÀ¿¿¿¿¿¿ººº¸¸¸¾¾¾¿¿¿¿¿¿¾¾¾¾¾¾¾¾¾¿¿¿ÀÀÀ»»»»»»»»»»»»¼¼¼¼¼¼¼¼¼¾¾¾¿¿¿ÅÅÅÍÍÍÌÌÌÇÇÇÌÌÌÕÕÕÙÙÙÒÒÒÍÍÍÔÔÔÛÛÛ¾¾¾ÎÎÎÅÅž¾¾¬¬¬ßßßÛÛÛ××××××ÊÊÊÑÑÑÉÉÉÀÀÀ»»»¸¸¸»»»¼¼¼ºººººº¼¼¼»»»ÀÀÀÇÇÇÌÌÌÍÍÍÎÎÎÎÎÎÎÎÎÎÎÎÉÉÉÀÀÀ»»»¸¸¸µµµ³³³°°°···¿¿¿ÃÃÃÆÆÆÂÂÂÀÀÀÅÅÅ»»»³³³»»»ÃÃÃÎÎÎØØØÑÑÑÆÆÆÆÆÆÉÉÉ×××ÕÕÕÔÔÔÒÒÒÍÍÍÎÎÎÍÍÍÅÅÅÉÉÉÍÍÍÎÎÎÊÊÊÃÃû»»µµµºººÅÅÅÆÆÆ¾¾¾µµµ¬¬¬±±±ÃÃÃÅÅÅÇÇÇÉÉÉÆÆÆÃÃÃÂÂÂÅÅÅÆÆÆÀÀÀÅÅÅÇÇÇÆÆÆÂÂÂÃÃÃÉÉÉÐÐÐÌÌÌÐÐÐÔÔÔÔÔÔÒÒÒÑÑÑÐÐÐÑÑÑÎÎÎÉÉÉÉÉÉÎÎÎÒÒÒÑÑÑÒÒÒÕÕÕÀÀÀÀÀÀ¿¿¿ÀÀÀÉÉÉÑÑÑÎÎÎÃÃÃÐÐÐÃÃÃÆÆÆÀÀÀ¸¸¸¸¸¸°°°¬¬¬µµµ¾¾¾ÃÃÃÆÆÆÇÇÇÆÆÆ¾¾¾³³³³³³µµµ´´´±±±´´´»»»¼¼¼···Â¿¿¿¿¿¿ÂÂÂÊÊÊÐÐÐÂÂÂÆÆÆÂÂÂÂÂÂÅÅÅÀÀÀÂÂÂÇÇÇÇÇÇÃÃÃÌÌÌÔÔÔ×××ÜÜÜÝÝÝØØØ×××ÝÝÝÜÜÜÜÜÜÛÛÛÇÇǼ¼¼ÌÌÌÃÃÃÅÅÅÅÅÅÆÆÆÅÅÅÃÃÃÀÀÀ¿¿¿¼¼¼»»»»»»»»»¼¼¼¿¿¿ÂÂÂÅÅÅÊÊÊÅÅÅÅÅÅÂÂÂÔÔÔØØØººº³³³ººº¿¿¿»»»···¾¾¾ÉÉÉÕÕÕàààÐÐÐÍÍ͸¸¸µµµÇÇÇÒÒÒÕÕÕÒÒÒ»»»ÆÆÆÇÇÇÆÆÆÌÌÌÌÌÌÆÆÆÂÂÂÀÀÀÊÊÊÇÇÇ¿¿¿¿¿¿»»»ºººÂ¿¿¿¿¿¿ÀÀÀÀÀÀÂÂÂÀÀÀÀÀÀ¿¿¿ºººººº»»»¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¿¿¿ÂÂÂÌÌÌÍÍÍÇÇÇÐÐÐØØØÐÐÐÔÔÔÉÉÉÒÒÒÛÛÛ¼¼¼ÉÉÉÃÃúºº¬¬¬ÛÛÛÝÝÝÜÜÜÝÝÝØØØÙÙÙÇÇÇÊÊÊÆÆÆÂ¾¾¾¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼ÀÀÀÇÇÇÌÌÌÍÍÍÍÍÍÎÎÎÐÐÐÊÊÊÊÊÊÆÆÆÀÀÀ¸¸¸´´´³³³³³³¼¼¼ÅÅÅÇÇÇÅÅÅÀÀÀÂÂÂÀÀÀ···¸¸¸ÅÅÅÎÎÎ×××ØØØÌÌÌÂÂÂÆÆÆÆÆÆÒÒÒØØØ×××ÒÒÒÎÎÎÍÍÍÌÌÌÍÍÍÒÒÒÒÒÒÊÊʾ¾¾···¸¸¸¼¼¼ÀÀÀ»»»´´´´´´°°°­­­´´´¿¿¿ÃÃÃÇÇÇÇÇÇÃÃÃÂÂÂÃÃÃÆÆÆÂÂÂÂÂÂÃÃÃÆÆÆÉÉÉÊÊÊÉÉÉÇÇÇÉÉÉÊÊÊÍÍÍÎÎÎÍÍÍÍÍÍÐÐÐÑÑÑÌÌÌÆÆÆÆÆÆÌÌÌÑÑÑÑÑÑÒÒÒÔÔÔÃÃÃÆÆÆÃÃÿ¿¿ÃÃÃÊÊÊÌÌÌÇÇÇ¿¿¿ºººÆÆÆÆÆÆÂ···­­­ªªª­­­°°°µµµÀÀÀÇÇǸ¸¸¸¸¸···³³³³³³»»»ÃÃÃÀÀÀ······µµµ³³³¯¯¯­­­¯¯¯´´´¸¸¸ÅÅž¾¾ÃÃÃÔÔÔÛÛÛØØØÝÝÝÑÑÑÔÔÔÛÛÛ×××ÇÇǾ¾¾ÀÀÀÀÀÀ¿¿¿¾¾¾¿¿¿ÃÃÃÇÇÇÉÉÉÃÃÃÂÂÂÀÀÀÀÀÀÀÀÀ¿¿¿¾¾¾»»»¼¼¼¼¼¼¼¼¼¼¼¼¾¾¾ÀÀÀÂÂÂÃÃÃÆÆÆÅÅÅÅÅÅÀÀÀÎÎÎÔÔÔ¿¿¿¸¸¸···ÅÅÅÅÅż¼¼¾¾¾ÃÃÃÌÌÌØØØ×××ÇÇÇ···¾¾¾¾¾¾ÀÀÀÒÒÒÍÍÍ»»»ÀÀÀÉÉÉÌÌÌÌÌÌÐÐÐÐÐÐÅÅÅ···ÎÎÎÒÒÒÃÃþ¾¾¼¼¼»»»ÀÀÀ¾¾¾¿¿¿ÂÂÂÅÅÅÅÅÅ¿¿¿¼¼¼¸¸¸ººº»»»»»»¼¼¼¼¼¼¾¾¾¾¾¾ÃÃÃÂÂÂÉÉÉÍÍÍÍÍÍÕÕÕÕÕÕÇÇÇÑÑÑÇÇÇÎÎÎÎÎλ»»ÇÇǸ¸¸±±±ÜÜÜäääàààÜÜÜÜÜÜæææ×××ÌÌÌÎÎÎÌÌÌÆÆÆÂÂÂÀÀÀ¿¿¿¼¼¼¾¾¾ÂÂÂÇÇÇÊÊÊÌÌÌÍÍÍÎÎÎÐÐÐÉÉÉÌÌÌÉÉÉÀÀÀµµµ³³³ºººÀÀÀÅÅÅÆÆÆÆÆÆÀÀÀÀÀÀ»»»´´´¾¾¾ÉÉÉÒÒÒ××××××ÌÌÌÆÆÆÎÎÎÅÅÅÐÐÐÛÛÛØØØÑÑÑÐÐÐÍÍÍÌÌÌÍÍÍÌÌÌÇÇÇÀÀÀººº···»»»¿¿¿¸¸¸¸¸¸°°°¯¯¯···¸¸¸±±±±±±ºººÀÀÀÆÆÆÉÉÉÆÆÆÃÃÃÅÅÅÆÆÆÆÆÆÃÃÃÂÂÂÆÆÆÍÍÍÎÎÎÌÌÌÆÆÆÂÂÂÃÃÃÃÃÃÅÅÅÅÅÅÆÆÆÉÉÉÌÌÌÆÆÆÃÃÃÅÅÅÊÊÊÍÍÍÉÉÉÆÆÆÅÅÅÉÉÉÎÎÎÌÌÌÆÆÆÆÆÆÇÇÇÉÉÉÍÍÍÃÃû»»¿¿¿ººº´´´¼¼¼»»»ººº³³³°°°¬¬¬¯¯¯»»»ÉÉÉÌÌÌÆÆÆÃÃÿ¿¿»»»»»»ÀÀÀÃÃÿ¿¿¸¸¸ÀÀÀÀÀÀ¿¿¿ÀÀÀÃÃÃÉÉÉÍÍÍÎÎξ¾¾ÃÃÃÇÇÇ¿¿¿ÀÀÀÆÆÆÆÆÆÔÔÔÕÕÕÛÛÛÛÛÛÌÌÌ»»»¼¼¼»»»¯¯¯¸¸¸³³³±±±°°°³³³ÃÃÃÍÍÍÅÅÅ¿¿¿¿¿¿¾¾¾¾¾¾¾¾¾¼¼¼»»»»»»»»»»»»»»»»»»¼¼¼¾¾¾ÀÀÀÀÀÀÂÂÂÆÆÆÅÅÅÆÆÆÌÌÌÒÒÒÎÎÎÀÀÀ¸¸¸ÎÎÎÒÒÒÉÉÉÇÇǾ¾¾ÃÃÃÜÜÜÃÃô´´Â»»»¼¼¼ÔÔÔÆÆÆ¼¼¼¾¾¾ÌÌÌÔÔÔÐÐÐÒÒÒÔÔÔÉÉɺººÎÎÎÕÕÕÉÉÉ¿¿¿¼¼¼¼¼¼¼¼¼¼¼¼¿¿¿ÃÃÃÅÅÅÅÅž¾¾»»»ººººººººº»»»¼¼¼¾¾¾¿¿¿¿¿¿ÆÆÆÅÅÅÉÉÉÎÎÎÒÒÒ×××ÒÒÒÉÉÉÊÊÊÌÌÌÊÊÊÀÀÀÀÀÀÍÍÍÀÀÀ¾¾¾°°°ÑÑÑæææëëëßßßÙÙÙäääßßßÇÇÇÌÌÌÍÍÍÌÌÌÉÉÉÆÆÆÃÃÃÀÀÀÀÀÀÅÅÅÉÉÉÌÌÌÍÍÍÍÍÍÎÎÎÐÐÐÎÎÎÍÍÍÆÆÆ»»»³³³···ÃÃÃÐÐÐÉÉÉÇÇÇÆÆÆ¿¿¿ÀÀÀ¿¿¿µµµ»»»ÌÌÌÒÒÒÕÕÕØØØØØØÍÍÍÇÇÇÎÎÎÇÇÇÌÌÌÛÛÛÙÙÙÑÑÑÔÔÔÎÎÎÌÌÌ¿¿¿»»»···¸¸¸¾¾¾¿¿¿¼¼¼···¨¨¨¯¯¯¯¯¯°°°»»»¾¾¾»»»¼¼¼ººº¿¿¿ÅÅÅÇÇÇÇÇÇÆÆÆÆÆÆÇÇÇÇÇǾ¾¾¿¿¿ÅÅÅÉÉÉÊÊÊÉÉÉÂÂÂÀÀÀÀÀÀÀÀÀÂÂÂÅÅÅÅÅÅÅÅÅÇÇÇÃÃÃÃÃÃÇÇÇÇÇÇÃÃÃÀÀÀÂÂÂÇÇÇÍÍÍÍÍÍÌÌÌÍÍÍÅÅÅÀÀÀÇÇÇÒÒÒÉÉÉÉÉÉ»»»±±±»»»¾¾¾¾¾¾ºººººº¸¸¸µµµºººÂÂÂÅÅÅÃÃÃÇÇÇÆÆÆÃÃþ¾¾···µµµµµµ¾¾¾»»»¸¸¸···¸¸¸ººº···´´´»»»ÇÇÇÐÐм¼¼´´´ººº»»»ÍÍÍÒÒÒÎÎÎÉÉɼ¼¼³³³¸¸¸»»»±±±ªªª±±±¿¿¿ÍÍÍÔÔÔÒÒÒÇÇǺºº¼¼¼¼¼¼¾¾¾¾¾¾¾¾¾¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¾¾¾¿¿¿ÀÀÀÀÀÀÃÃÃÆÆÆÂÂÂÊÊÊÊÊÊÎÎÎØØØ¼¼¼¿¿¿ÕÕÕ×××ÎÎÎÒÒÒÌÌ̼¼¼»»»ÙÙÙÉÉÉ···ÀÀÀ¼¼¼ÀÀÀÙÙÙÉÉɾ¾¾¿¿¿ÇÇÇÍÍÍÌÌÌÊÊÊÌÌÌÎÎÎÂÂÂÅÅÅÌÌÌÍÍÍÃÃÿ¿¿¿¿¿¾¾¾¿¿¿ÀÀÀÂÂÂÂÂÂÂÂÂÀÀÀ¾¾¾¼¼¼»»»»»»ººº»»»¼¼¼¾¾¾ÀÀÀÂÂÂÆÆÆÉÉÉÊÊÊÎÎÎÔÔÔÒÒÒÑÑÑÕÕÕÃÃÃÔÔÔÉÉɸ¸¸ÌÌÌØØØÃÃÃÅÅŵµµ¼¼¼ÑÑÑíííççç×××ÛÛÛÜÜÜÎÎÎÌÌÌÊÊÊÎÎÎÑÑÑÎÎÎÉÉÉÆÆÆÅÅÅÇÇÇÌÌÌÎÎÎÎÎÎÐÐÐÑÑÑÔÔÔÒÒÒÌÌÌÀÀÀººº»»»ÂÂÂÌÌÌÑÑÑÌÌÌÉÉÉÊÊÊÃÃÿ¿¿ººº´´´ÇÇÇÔÔÔ×××ØØØÛÛÛÝÝÝÒÒÒÇÇÇÉÉÉÊÊÊÊÊÊÛÛÛØØØÑÑÑ×××ÐÐÐÌÌ̾¾¾¼¼¼¼¼¼¾¾¾¾¾¾¸¸¸°°°©©©¥¥¥°°°³³³´´´¾¾¾ÃÃÃÂÂÂÃÃÃÀÀÀÂÂÂÅÅÅÆÆÆÆÆÆÇÇÇÉÉÉÉÉÉÅÅÅ¿¿¿ºººµµµ¸¸¸¿¿¿ÆÆÆÊÊÊÆÆÆÃÃÃÂÂÂÃÃÃÆÆÆÆÆÆÅÅÅÃÃÃÌÌÌÆÆÆÃÃÃÃÃÃÃÃÃÃÃÃÆÆÆÊÊÊÂÂÂÇÇÇÉÉÉÍÍÍÐÐÐÃÃø¸¸¾¾¾ÀÀÀÀÀÀÌÌÌÅÅźººººº±±±©©©³³³ººº¾¾¾ººº´´´³³³³³³±±±©©©¯¯¯¸¸¸¿¿¿¼¼¼¸¸¸ÀÀÀÎÎδ´´´´´···ÀÀÀÎÎÎ×××ØØØ×××ÍÍÍÎÎÎÌÌÌ···¸¸¸Â¸¸¸»»»ÃÃû»»¾¾¾¾¾¾···ºººÍÍÍÛÛÛÒÒÒÎÎÎÃÃÃÂÂÂÅÅž¾¾¸¸¸¾¾¾ÀÀÀÂÂÂÂÂÂÀÀÀ¾¾¾»»»ºººººº¿¿¿¿¿¿¿¿¿ÀÀÀÀÀÀÂÂÂÂÂÂÃÃÃÅÅÅÆÆÆ¾¾¾ÊÊÊÇÇÇÉÉÉ×××±±±ÆÆÆØØØÔÔÔÍÍÍØØØÕÕÕÅÅÅ¿¿¿ØØØ×××ÀÀÀ¿¿¿»»»ÀÀÀÛÛÛÌÌÌÀÀÀ¾¾¾¾¾¾Â¾¾¾ÂÂÂÒÒÒÉÉɺºº¿¿¿ÍÍÍÊÊÊÃÃÃÃÃÃÅÅÅÂÂÂÀÀÀÀÀÀ¿¿¿¿¿¿¾¾¾¾¾¾¿¿¿¼¼¼»»»ºººººº»»»¾¾¾ÂÂÂÃÃÃÃÃÃÊÊÊÌÌÌÎÎÎÔÔÔÎÎÎÑÑÑâââÀÀÀÛÛÛÊÊÊ´´´ÕÕÕâââÆÆÆÊÊÊÉÉɯ¯¯´´´ÝÝÝæææÔÔÔ×××ÜÜÜÛÛÛÐÐÐÊÊÊÑÑÑØØØÕÕÕÎÎÎÊÊÊÇÇÇÊÊÊÎÎÎÑÑÑÑÑÑÒÒÒÔÔÔÕÕÕÒÒÒÉÉɾ¾¾¾¾¾ÆÆÆÍÍÍÍÍÍÊÊÊÌÌÌÊÊÊÐÐÐÇÇǾ¾¾´´´³³³ÒÒÒÎÎÎÑÑÑÔÔÔÜÜÜäääÜÜÜÎÎÎÍÍÍÌÌÌÊÊÊÛÛÛØØØÒÒÒØØØÑÑÑÌÌÌ´´´¾¾¾ÆÆÆÆÆÆ¼¼¼´´´±±±´´´­­­µµµµµµµµµÀÀÀÇÇÇÃÃÃÀÀÀÇÇÇÆÆÆÅÅÅÃÃÃÅÅÅÇÇÇÉÉÉÊÊÊÀÀÀ³³³°°°¸¸¸»»»µµµ¾¾¾ÎÎÎÆÆÆÇÇÇÇÇÇÆÆÆÅÅÅÆÆÆÉÉÉÌÌÌÕÕÕÒÒÒÌÌÌÀÀÀµµµÇÇÇÇÇÇÅÅÅÀÀÀÐÐÐÕÕÕÔÔÔÌÌÌ···¸¸¸···ºººÂÂÂÌÌÌÊÊʼ¼¼¾¾¾±±±°°°±±±ºººÀÀÀ¾¾¾µµµ­­­¯¯¯¼¼¼¿¿¿¸¸¸¿¿¿ÆÆÆ¸¸¸¯¯¯¯¯¯°°°±±±¬¬¬±±±±±±´´´ÝÝÝÛÛÛÃÃÿ¿¿¾¾¾¼¼¼ÀÀÀ¾¾¾¿¿¿ÆÆÆ±±±¸¸¸³³³ÀÀÀÇÇÇÉÉÉÂÂÂÀÀÀÃÃÃÆÆÆÂ¼¼¼¸¸¸»»»¾¾¾ÆÆÆ¾¾¾»»»¾¾¾»»»´´´³³³···µµµ»»»¾¾¾¼¼¼¾¾¾ÃÃÃÃÃÿ¿¿ÉÉÉ»»»ÅÅÅÇÇÇÅÅÅÌÌÌÆÆÆ¼¼¼ÆÆÆÕÕÕÑÑÑÌÌÌÅÅÅÛÛÛ´´´¿¿¿ÒÒÒÕÕÕÔÔÔººººººÑÑÑÐÐÐÌÌÌÉÉÉÂÂÂÂÂÂÌÌÌÐÐÐÉÉÉÀÀÀ¼¼¼ÅÅÅÌÌ̼¼¼ÕÕÕÌÌÌÃÃÃÇÇÇÀÀÀÀÀÀÀÀÀ¿¿¿¿¿¿¾¾¾¾¾¾¼¼¼¼¼¼¾¾¾ººº»»»¿¿¿Â¿¿¿ÀÀÀÅÅÅÃÃÃÍÍÍÉÉÉÎÎÎÙÙÙÍÍÍÇÇÇÜÜÜÊÊÊÎÎÎâââÉÉɳ³³»»»ØØØÌÌÌÀÀÀÀÀÀ¿¿¿ÌÌÌÛÛÛØØØÑÑÑÙÙÙÙÙÙèèèÕÕÕÉÉÉÎÎÎÊÊÊÐÐÐÙÙÙÑÑÑÒÒÒÒÒÒÒÒÒÔÔÔÕÕÕ×××ØØØÐÐÐÆÆÆ¸¸¸»»»ÍÍÍÍÍÍ»»»°°°¸¸¸ÌÌÌÎÎÎÃÃÿ¿¿ººº¸¸¸ÔÔÔÔÔÔÙÙÙÛÛÛØØØÙÙÙÒÒÒÃÃÃÌÌÌÒÒÒâââØØØÛÛÛÔÔÔÐÐи¸¸ºººÃÃÃÅÅźºº´´´ººº¾¾¾¾¾¾¸¸¸°°°¯¯¯³³³¸¸¸ÂÂÂÅÅż¼¼ÃÃÃÉÉÉÊÊÊÅÅÅÃÃÃÆÆÆÆÆÆÃÃû»»ºººÀÀÀÉÉɱ±±±±±¾¾¾ÉÉÉÊÊÊÌÌÌÌÌÌÌÌÌÍÍÍÑÑÑÔÔÔÑÑÑÑÑÑÇÇǵµµ¸¸¸´´´ÆÆÆÂÂÂÅÅÅÂÂÂÍÍÍÑÑÑÒÒÒÎÎμ¼¼¸¸¸¼¼¼¸¸¸»»»ÆÆÆÐÐÐÒÒÒÐÐÐÎÎÎÉÉÉÇÇÇÀÀÀººº¼¼¼ÀÀÀ¼¼¼´´´ººº¼¼¼ººº»»»ÃÃÃÀÀÀ³³³¯¯¯¯¯¯ªªªªªª©©©³³³¸¸¸ºººÒÒÒ···¼¼¼»»»ºººÀÀÀ¿¿¿¿¿¿Â¼¼¼ÕÕÕÎÎÎÑÑÑÍÍÍÇÇǾ¾¾ÀÀÀ¿¿¿¼¼¼ººº»»»¾¾¾¼¼¼¼¼¼¼¼¼»»»´´´­­­­­­±±±´´´ººº¾¾¾¼¼¼¼¼¼ÀÀÀ¿¿¿ÇÇǾ¾¾ÅÅÅÅÅÅÆÆÆÊÊÊÀÀÀ»»»ÊÊÊÔÔÔÎÎÎÍÍÍÊÊÊàààÃÃÃ×××ÍÍÍÒÒÒ×××ÆÆÆÇÇÇØØØÐÐÐÅÅÅÂÂÂÅÅÅÊÊÊÐÐÐÔÔÔÑÑÑÆÆÆ¼¼¼¾¾¾ÍÍÍÀÀÀÔÔÔÍÍÍ¿¿¿¿¿¿¿¿¿¿¿¿¾¾¾¾¾¾¾¾¾¾¾¾¼¼¼»»»¸¸¸ººº¿¿¿ÂÂÂÀÀÀÂÂÂÆÆÆÅÅÅÅÅÅÉÉÉÎÎÎÐÐÐÍÍÍÑÑÑÜÜÜÌÌÌÕÕÕÙÙÙÉÉÉ»»»´´´ÃÃÃÒÒÒÆÆÆÃÃúºººººÍÍÍÝÝÝÛÛÛÑÑÑÜÜÜàààÍÍÍÊÊÊÕÕÕÑÑÑÌÌÌÃÃÃÌÌÌÍÍÍÐÐÐÔÔÔ×××ØØØØØØ×××ÕÕÕÐÐÐÀÀÀ···¸¸¸ººº»»»Â¸¸¸ÆÆÆÐÐÐÊÊÊÀÀÀ¾¾¾¼¼¼···ÍÍÍÎÎÎØØØÜÜÜÜÜÜâââàààÕÕÕÒÒÒÎÎÎÜÜÜÛÛÛÛÛÛÐÐÐÍÍ͸¸¸ÀÀÀÅÅÅ¿¿¿´´´°°°¸¸¸¾¾¾¼¼¼ººº°°°¯¯¯¯¯¯¬¬¬´´´ÀÀÀÅÅÅÀÀÀÅÅÅÅÅÅÂÂÂÃÃÃÇÇÇÇÇÇÃÃô´´»»»ÇÇÇÎÎγ³³···ÅÅÅÌÌÌÍÍÍÎÎÎÎÎÎÎÎÎÐÐÐÒÒÒÕÕÕÎÎÎÑÑÑÆÆÆ±±±´´´µµµÇÇÇ¿¿¿ÃÃÃÃÃÃÊÊÊÌÌÌÐÐÐÑÑÑÃÃû»»¼¼¼µµµ±±±···¼¼¼¾¾¾¾¾¾¼¼¼³³³¿¿¿ÅÅž¾¾ººº¿¿¿¾¾¾···ÃÃû»»³³³¼¼¼ÆÆÆ»»»³³³µµµ¯¯¯¬¬¬¬¬¬¦¦¦©©©±±±³³³¼¼¼¾¾¾ºººÅÅž¾¾ÅÅÅ¿¿¿Â»»»ÛÛÛÎÎÎÍÍÍÌÌÌÆÆÆÉÉɼ¼¼¼¼¼¼¼¼¼¼¼¼¼¼»»»»»»»»»¾¾¾¼¼¼µµµ¬¬¬©©©­­­°°°°°°¯¯¯µµµ»»»¼¼¼¾¾¾ÂÂÂÃÃÃÃÃÃÅÅÅÂÂÂÃÃÃÀÀÀÉÉÉÊÊÊ»»»»»»ÝÝÝØØØÇÇÇÅÅÅÃÃÃÔÔÔ···ÃÃÃÒÒÒÕÕÕÕÕÕÇÇÇÉÉÉØØØÔÔÔÌÌÌÀÀÀÉÉÉÐÐÐÐÐÐÐÐÐÐÐÐÅÅŵµµ¸¸¸ÍÍÍÃÃÃÐÐÐÍÍÍÀÀÀ¼¼¼¾¾¾¼¼¼¼¼¼¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¼¼¼»»»¼¼¼¿¿¿ÂÂÂÀÀÀÃÃÃÆÆÆÉÉÉÅÅÅÐÐÐÕÕÕÊÊÊÊÊÊÒÒÒÍÍÍÆÆÆÙÙÙÎÎÎÃÃ÷·····ÙÙÙÊÊÊÇÇǼ¼¼°°°¼¼¼ÜÜÜæææ×××ÔÔÔÜÜÜÔÔÔÎÎÎÊÊÊÆÆÆÉÉÉÅÅÅÍÍÍÌÌÌÌÌÌÎÎÎÒÒÒÕÕÕÕÕÕÔÔÔÕÕÕØØØÑÑÑÅÅż¼¼¸¸¸»»»ÃÃü¼¼¿¿¿ÍÍÍÐÐÐÃÃÿ¿¿ÀÀÀ¸¸¸ÌÌÌÐÐÐÙÙÙÝÝÝÛÛÛÝÝÝàààÙÙÙàààÑÑÑàààãããâââÔÔÔÔÔÔ¿¿¿ÆÆÆÅÅÅ»»»°°°­­­···¾¾¾¼¼¼µµµ³³³»»»ÀÀÀµµµ±±±¼¼¼ÆÆÆ¿¿¿ÀÀÀÀÀÀÀÀÀÅÅÅÉÉÉÆÆÆÂ±±±»»»ÇÇÇÎÎÎÆÆÆ»»»¿¿¿ÉÉÉÌÌÌÍÍÍÎÎÎÍÍÍÌÌÌÊÊÊÊÊÊÌÌÌÎÎÎÐÐÐÉÉÉ»»»¿¿¿ºººÇÇÇ¿¿¿¿¿¿ÆÆÆÌÌÌÊÊÊÌÌÌÎÎÎÉÉÉÀÀÀ»»»»»»¼¼¼»»»¸¸¸µµµµµµ···­­­¼¼¼ÆÆÆÀÀÀººººººÀÀÀÅÅÅ···ººº¸¸¸ÇÇÇÎÎξ¾¾´´´µµµµµµ¸¸¸ººº¯¯¯¥¥¥ªªª±±±´´´´´´¯¯¯ººº»»»»»»ÅÅÅÅÅÅÅÅÅ¿¿¿µµµ×××ÍÍÍÍÍÍÌÌÌ¿¿¿¾¾¾¾¾¾»»»ºººººº»»»»»»ººº···µµµ´´´°°°¯¯¯¸¸¸ÀÀÀµµµ¤¤¤···»»»ÀÀÀÀÀÀ¿¿¿¾¾¾¾¾¾¿¿¿ÀÀÀÃÃþ¾¾ÍÍÍÌÌ̸¸¸¾¾¾×××ÍÍÍ»»»»»»ÀÀÀÒÒÒ···µµµ¿¿¿ÅÅÅÃÃø¸¸»»»ÊÊÊÑÑÑÑÑÑÐÐÐÔÔÔ×××ÔÔÔÐÐÐÉÉɼ¼¼±±±···ÌÌÌÀÀÀÅÅÅÍÍÍ»»»»»»»»»»»»¼¼¼¼¼¼¾¾¾¿¿¿¿¿¿¿¿¿ÂÂÂÀÀÀ¿¿¿¿¿¿ÀÀÀÂÂÂÃÃÃÆÆÆÆÆÆÅÅÅÔÔÔÙÙÙÍÍÍÎÎÎÒÒÒÇÇÇÌÌÌâââÊÊÊ¿¿¿Â¿¿¿±±±ÎÎÎÌÌÌÇÇÇÅÅŸ¸¸´´´ÊÊÊäääæææÑÑÑÛÛÛÙÙÙ×××ÍÍÍÇÇÇÍÍÍÅÅÅÌÌÌÊÊÊÌÌÌÑÑÑÕÕÕ×××ÑÑÑÌÌÌÑÑÑ××××××ÔÔÔÑÑÑÎÎÎÊÊÊÇÇÇÃÃÃÀÀÀÇÇÇÍÍÍÊÊÊÆÆÆÃÃü¼¼¼¼¼ÂÂÂÑÑÑÙÙÙÙÙÙÝÝÝâââßßßàààÒÒÒãããçççäääÛÛÛÙÙÙ¿¿¿ÅÅÅÅÅÅ¿¿¿´´´°°°µµµ»»»¼¼¼´´´³³³¿¿¿ÉÉɼ¼¼±±±···ÀÀÀÀÀÀÀÀÀÀÀÀÃÃÃÇÇÇÇÇǼ¼¼ºººÀÀÀÌÌÌÑÑÑÎÎÎÅÅÅ»»»¸¸¸ÆÆÆÉÉÉÊÊÊÊÊÊÉÉÉÆÆÆÆÆÆÆÆÆÌÌÌÊÊÊÊÊÊÊÊÊÍÍͺººÂ¿¿¿ºººÆÆÆÍÍÍÌÌÌÇÇÇÉÉÉÌÌÌÉÉÉÆÆÆÊÊÊÍÍÍÊÊÊÅÅż¼¼µµµ±±±´´´···¿¿¿ÅÅŸ¸¸´´´µµµ¬¬¬¿¿¿ÃÃÃÍÍÍÎÎλ»»´´´°°°¬¬¬±±±±±±ªªª¦¦¦­­­¸¸¸···ÆÆÆµµµ¸¸¸ººººººÂÂÂÂÂÂÅÅÅÆÆÆ¿¿¿ÜÜÜÒÒÒÑÑÑÊÊÊ¿¿¿¼¼¼¿¿¿»»»¸¸¸¸¸¸ººº¸¸¸µµµ³³³³³³±±±­­­¯¯¯¿¿¿ÎÎÎÅÅ۰°³³³···¼¼¼ÂÂÂÃÃÃÃÃÃÅÅÅÆÆÆ¾¾¾ÃÃþ¾¾ÎÎÎÍÍ͸¸¸¿¿¿ÅÅÅÉÉÉÃÃÃÃÃÃÇÇÇÕÕÕÀÀÀ¸¸¸¯¯¯¸¸¸¼¼¼»»»¼¼¼ÅÅÅÐÐÐÒÒÒ××××××ÙÙÙÜÜÜ×××ÆÆÆ¸¸¸±±±»»»ÉÉɼ¼¼¸¸¸ÉÉÉÅÅž¾¾ººº»»»»»»¼¼¼¾¾¾¾¾¾¿¿¿ÀÀÀÀÀÀÂÂÂÂÂÂÀÀÀ¿¿¿ÂÂÂÆÆÆÊÊÊÍÍÍÎÎÎÒÒÒ×××ÕÕÕÍÍÍÉÉÉÉÉÉÅÅÅßßßäääÊÊÊÂÂÂÀÀÀ¾¾¾¬¬¬¼¼¼ÐÐÐÅÅÅÆÆÆÅÅÅ´´´µµµÐÐÐäääèèèäääÕÕÕÔÔÔÔÔÔ×××ÙÙÙÌÌÌÃÃÃÇÇÇÐÐÐÛÛÛãããâââÛÛÛÒÒÒÔÔÔÔÔÔÔÔÔÔÔÔ×××ÝÝÝÝÝÝ×××ÎÎÎÊÊÊÂÂÂÅÅÅÐÐÐÐÐÐÆÆÆÃÃúºº¾¾¾ÍÍÍÙÙÙÙÙÙÜÜÜßßßÜÜÜÔÔÔÐÐÐàààÝÝÝßßßÛÛÛ×××···ÀÀÀÆÆÆÅÅż¼¼µµµµµµ»»»¾¾¾¾¾¾±±±±±±µµµ­­­©©©´´´¿¿¿ÃÃÃÃÃÃÆÆÆÉÉÉÉÉÉÃÃü¼¼···ÆÆÆÆÆÆÇÇÇÊÊÊÍÍÍÊÊÊ¿¿¿´´´¿¿¿ÃÃÃÇÇÇÉÉÉÉÉÉÇÇÇÇÇÇÇÇÇÅÅÅÃÃÃÊÊÊÐÐÐÒÒÒ···¾¾¾¼¼¼¸¸¸ÆÆÆÊÊÊÌÌÌÇÇÇÃÃÃÌÌÌÊÊÊÎÎÎÍÍÍÌÌÌÉÉÉÉÉÉÃÃ÷··ªªª¯¯¯¤¤¤¨¨¨¾¾¾ÍÍÍÅÅÅ···°°°»»»ÌÌÌÀÀÀ¼¼¼ººº¯¯¯···³³³¬¬¬³³³­­­±±±¿¿¿ÉÉÉÐÐÐÌÌÌÝÝÝÍÍÍÊÊÊÀÀÀ»»»ÂÂÂÂÂÂÂÂÂÆÆÆÇÇÇÝÝÝÕÕÕÐÐÐÅÅÅÉÉÉÇÇǾ¾¾»»»¸¸¸¸¸¸¸¸¸···´´´±±±µµµ´´´­­­ªªªºººÎÎÎÕÕÕÍÍͱ±±³³³¸¸¸ÂÂÂÆÆÆÇÇÇÇÇÇÉÉɾ¾¾Â¿¿¿ÍÍÍÌÌÌ···¼¼¼ºººÇÇÇÑÑÑÒÒÒÊÊÊÆÆÆ¸¸¸´´´¸¸¸¾¾¾ºººººº¸¸¸¸¸¸ÃÃÃÃÃÃÃÃÃÃÃÃÊÊÊÕÕÕÔÔÔÃÃó³³­­­¼¼¼ÅÅż¼¼±±±ÂÂÂÅÅÅ»»»¼¼¼¼¼¼¾¾¾¾¾¾¿¿¿ÀÀÀÀÀÀÀÀÀ¿¿¿ÂÂÂÂÂÂÃÃÃÇÇÇÎÎÎÔÔÔÔÔÔÑÑÑÔÔÔÐÐÐÊÊÊÉÉÉÆÆÆÆÆÆÐÐÐàààÒÒÒÂÂÂÅÅÅÀÀÀººº´´´¿¿¿ÕÕÕÅÅÅÂÂÂÆÆÆººº­­­ºººÎÎÎÝÝÝêêêäääßßßØØØÒÒÒÛÛÛÛÛÛàààßßßÝÝÝÝÝÝßßßÝÝÝÙÙÙÕÕÕÛÛÛÜÜÜßßßØØØÔÔÔÙÙÙÛÛÛÒÒÒÕÕÕÒÒÒÅÅÅÂÂÂÑÑÑÔÔÔÌÌÌÊÊÊÆÆÆÅÅÅÐÐÐÜÜÜÝÝÝÜÜÜÜÜÜ×××ÑÑÑÕÕÕâââÙÙÙßßßÛÛÛÔÔÔ¸¸¸ÀÀÀÅÅÅÆÆÆ¿¿¿¸¸¸···»»»¿¿¿ÅÅŵµµ¯¯¯¯¯¯ªªª­­­¸¸¸¾¾¾ÂÂÂÅÅÅÇÇÇÊÊÊÅÅż¼¼¸¸¸¸¸¸ÊÊÊÇÇÇÃÃÃÃÃÃÉÉÉÍÍÍÆÆÆ¼¼¼ººº¾¾¾ÃÃÃÆÆÆÆÆÆÅÅÅÅÅÅÅÅÅÀÀÀÆÆÆÎÎÎÎÎÎÎÎη··¿¿¿¾¾¾¼¼¼ÃÃÃÂÂÂÊÊÊÊÊÊÃÃÃÊÊÊÉÉÉÉÉÉÇÇÇÃÃÃÃÃÃÉÉÉÎÎÎÌÌÌÅÅž¾¾¬¬¬¢¢¢­­­ÀÀÀÉÉÉÇÇÇÅÅÅÃÃÃÍÍÍ´´´¯¯¯¯¯¯¨¨¨´´´°°°©©©´´´©©©±±±ÂÂÂÂÂÂÀÀÀ¾¾¾ÉÉÉÊÊÊÐÐо¾¾µµµÇÇÇÍÍÍÊÊÊÊÊÊÎÎÎÜÜÜÛÛÛÕÕÕÃÃÃÊÊÊ¿¿¿»»»ººº¸¸¸¸¸¸······µµµ³³³­­­­­­¬¬¬±±±ÃÃÃÕÕÕØØØÑÑѼ¼¼¸¸¸»»»ÂÂÂÅÅÅÀÀÀ»»»ººº¿¿¿ÀÀÀÀÀÀ¿¿¿ÉÉÉÇÇÇ´´´µµµ°°°µµµÅÅÅÔÔÔÎÎξ¾¾µµµ¸¸¸»»»ººº¯¯¯³³³µµµ±±±µµµ­­­³³³´´´»»»ÅÅÅÉÉÉÃÃø¸¸°°°¸¸¸¿¿¿ÃÃñ±±»»»ÂÂÂÇÇÇ¿¿¿¾¾¾¾¾¾¿¿¿¿¿¿ÀÀÀÀÀÀÀÀÀ¿¿¿ÅÅÅÉÉÉÊÊÊÎÎÎÔÔÔÕÕÕÑÑÑ¿¿¿ÀÀÀÀÀÀÅÅÅÊÊÊÉÉÉÐÐÐßßßÉÉɾ¾¾¾¾¾¾¾¾¾¾¾»»»ÅÅÅÍÍÍÎÎÎÉÉÉÃÃÃÃÃÃÀÀÀ¸¸¸···Â´´´ÕÕÕàààäääâââÔÔÔÔÔÔØØØÜÜÜÙÙÙ××××××ÛÛÛâââçççëëëßßßâââçççâââÙÙÙÜÜÜÛÛÛÎÎÎØØØØØØÑÑÑÉÉÉÍÍÍÔÔÔÔÔÔÐÐÐÇÇÇÀÀÀÇÇÇØØØßßßäääæææàààØØØÝÝÝãããÙÙÙâââ×××ÎÎÎÀÀÀÆÆÆÂ¼¼¼ººº¸¸¸ººº¼¼¼¿¿¿ÀÀÀ¸¸¸¸¸¸¸¸¸´´´···»»»¸¸¸¼¼¼¿¿¿ÅÅÅÅÅż¼¼µµµ¸¸¸ÂÂÂÆÆÆÉÉÉÉÉÉÉÉÉÍÍÍÎÎÎÃÃô´´···»»»ÀÀÀ¿¿¿¾¾¾¼¼¼ÀÀÀÌÌÌÔÔÔÍÍÍÊÊʺººÅÅÅÀÀÀÀÀÀÀÀÀ»»»ÉÉÉÎÎÎÆÆÆÉÉÉÅÅÅÇÇÇÇÇÇÃÃû»»»»»ÃÃÃÊÊÊÍÍÍÆÆÆººº¬¬¬¦¦¦¬¬¬³³³³³³°°°µµµ¿¿¿­­­···¼¼¼­­­¬¬¬žžžÉÉÉÛÛÛÎÎÎÐÐÐØØØÇÇÇÀÀÀÂÂÂÀÀÀÔÔÔâââÆÆÆ¸¸¸ÑÑÑÙÙÙÑÑÑóóóèèèÜÜÜÒÒÒÐÐп¿¿ÌÌ̺ºº¸¸¸¸¸¸¸¸¸············µµµ³³³©©©¤¤¤­­­ÆÆÆÛÛÛÛÛÛÑÑѰ°°­­­°°°¼¼¼ÆÆÆÆÆÆÂÂÂÂÂÂÀÀÀ¿¿¿ÀÀÀ¿¿¿ÅÅÅÃÃð°°¯¯¯¸¸¸­­­···ÔÔÔØØØÀÀÀµµµ¸¸¸´´´´´´°°°ÅÅÅÒÒÒÍÍÍÅÅű±±···ºººººº»»»ÃÃÃÌÌÌÉÉÉ¿¿¿³³³¼¼¼ÉÉÉ´´´···¾¾¾ÉÉÉ¿¿¿¿¿¿¿¿¿ÀÀÀÀÀÀÀÀÀÂÂÂÂÂÂÂÂÂÊÊÊÐÐÐÑÑÑÒÒÒÕÕÕÑÑÑÊÊÊÃÃÃÀÀÀÅÅÅÍÍÍÊÊÊÂÂÂÂÂÂÍÍ͵µµºººÃÃõµµ···ºººÎÎÎÐÐÐÂÂÂÐÐÐÌÌÌÂÂÂÅÅÅÆÆÆÂÂÂÃÃúººÀÀÀ°°°ºººÛÛÛâââÛÛÛÔÔÔÙÙÙÛÛÛÝÝÝßßßÝÝÝÛÛÛØØØ×××ÝÝÝÝÝÝâââàààßßßêêêíííÝÝÝ×××ÙÙÙÛÛÛÑÑÑÇÇÇÑÑÑÛÛÛÒÒÒÑÑÑÃÃÃÆÆÆÔÔÔÜÜÜââââââÛÛÛÛÛÛÝÝÝÝÝÝÔÔÔßßßÌÌÌÃÃÃÂÂÂÌÌÌÀÀÀ´´´±±±···¼¼¼¿¿¿¾¾¾¸¸¸µµµ¸¸¸¸¸¸±±±´´´¸¸¸³³³µµµ»»»ÀÀÀ¿¿¿µµµ±±±»»»ÊÊÊÃÃÃÂÂÂÀÀÀÃÃÃÇÇÇÌÌÌÍÍÍÍÍÍÇÇÇ»»»ººº¾¾¾ÀÀÀÀÀÀ¿¿¿ÎÎÎÌÌÌÍÍÍÐÐÐÊÊÊÀÀÀ¿¿¿ÅÅÅÃÃÃÂÂÂÂÂÂÅÅÅÉÉÉÊÊÊÉÉÉÆÆÆÂ¸¸¸¿¿¿ºººººº¾¾¾»»»ÌÌÌÌÌ̺ºº¨¨¨¥¥¥¦¦¦¨¨¨©©©­­­³³³­­­¯¯¯µµµ±±±©©©°°°Â»»»ÃÃÃÅÅž¾¾ÃÃÃÉÉÉÃÃÃÂÂÂÊÊÊÉÉÉÙÙÙÎÎÎÒÒÒãããÔÔÔÕÕÕÜÜÜÛÛÛØØØÒÒÒÍÍÍÇÇǾ¾¾¸¸¸······´´´³³³³³³´´´µµµ¥¥¥¢¢¢³³³ÊÊÊÒÒÒ××××××ÐÐÐ¥¥¥°°°ººº¾¾¾ÂÂÂÇÇÇÆÆÆ¿¿¿ÀÀÀ¾¾¾¿¿¿ÀÀÀÂÂÂÉÉÉÇÇÇ»»»­­­¬¬¬¼¼¼××××××¾¾¾°°°···³³³´´´±±±ÃÃÃßßßÛÛÛÉÉÉÊÊʵµµ······±±±»»»Â¾¾¾ÍÍÍÆÆÆ±±±ºººÇÇÇÌÌ̾¾¾³³³ÇÇÇÅÅÅ¿¿¿ÀÀÀÃÃÃÃÃÃÃÃÃÃÃÃÊÊÊÊÊÊÎÎÎÔÔÔÒÒÒÌÌÌÇÇÇÉÉÉÌÌÌÔÔÔÎÎÎÂÂÂÀÀÀÍÍÍÐÐÐÇÇǼ¼¼¿¿¿±±±¸¸¸ÌÌÌÑÑÑÑÑÑÊÊÊÊÊÊÊÊÊÉÉÉÆÆÆÅÅÅÅÅÅÅÅÅÆÆÆÍÍÍÊÊÊ¿¿¿ÃÃü¼¼···×××îîîÔÔÔØØØ×××ØØØ×××ÝÝÝèèèÛÛÛñññííííííúúúñññàààçççààààààæææÝÝÝÙÙÙÜÜÜÍÍÍÂÂÂÑÑÑØØØÔÔÔÀÀÀÂÂÂÝÝÝäääÙÙÙÝÝÝÑÑÑÙÙÙàààÙÙÙÊÊÊÀÀÀÂÂÂÇÇÇ¿¿¿ÇÇDZ±±¸¸¸Â¼¼¼ÅÅÅ»»»ÀÀÀ¼¼¼¸¸¸ººº¸¸¸±±±±±±»»»ºººÂÂÂÊÊÊ···µµµÊÊÊÍÍÍÍÍÍÅÅÅ¿¿¿ÂÂÂÆÆÆÊÊÊÊÊÊÊÊÊÉÉÉÃÃþ¾¾ººº»»»¼¼¼»»»ºººÌÌÌÎÎÎÑÑÑÎÎÎÅÅž¾¾ÀÀÀÆÆÆÅÅÅÃÃÃÂÂÂÂÂÂÃÃÃÅÅÅÅÅÅÃÃû»»···»»»ººº»»»¾¾¾¿¿¿ÉÉÉÀÀÀ¸¸¸­­­©©©¨¨¨¤¤¤¡¡¡¡¡¡¢¢¢©©©°°°³³³±±±³³³¸¸¸¿¿¿ÂÂÂ×××ÙÙÙÇÇÇÀÀÀÂÂÂÂÂÂÅÅÅÆÆÆÌÌÌÜÜÜÍÍÍÐÐÐæææÝÝÝßßßÛÛÛÙÙÙ×××ÒÒÒÌÌÌÆÆÆÀÀÀ¾¾¾´´´±±±±±±µµµ¸¸¸µµµ°°°ªªªµµµ±±±¿¿¿ÐÐÐÔÔÔ××××××ÒÒÒ¯¯¯°°°···¾¾¾¾¾¾ººº···¸¸¸¾¾¾»»»¿¿¿ÀÀÀÀÀÀÆÆÆÇÇǼ¼¼³³³±±±ºººÆÆÆÉÉÉÀÀÀ¸¸¸¸¸¸´´´ººº´´´¾¾¾ÛÛÛâââÑÑÑÉÉÉ´´´³³³´´´¬¬¬¬¬¬±±±°°°¾¾¾¾¾¾Â¿¿¿´´´¼¼¼ÆÆÆ¿¿¿ÌÌÌÍÍÍÇÇÇÀÀÀ¾¾¾ÃÃÃÇÇÇÇÇÇÃÃÃÃÃÃÇÇÇÎÎÎÑÑÑÌÌÌÂÂÂÀÀÀÅÅÅÑÑÑÊÊÊÂÂÂÀÀÀÍÍÍÕÕÕÎÎο¿¿»»»¼¼¼···ÊÊÊÜÜÜÕÕÕÎÎÎÌÌÌÎÎÎÊÊÊÊÊÊÍÍÍÍÍÍÊÊÊÌÌÌÐÐÐÉÉÉÉÉÉÂÂÂÌÌÌÍÍ;¾¾³³³æææßßßÙÙÙàààÛÛÛÙÙÙææææææíííêêêâââïïïöööíííïïïïïïãããæææãããßßßÙÙÙ×××ÐÐÐÉÉÉÕÕÕØØØÌÌÌÃÃÃÒÒÒÜÜÜÜÜÜßßßÜÜÜÙÙÙÔÔÔÊÊÊÃÃÃÀÀÀÃÃÃÇÇÇÉÉÉÇÇǪªª¯¯¯»»»¸¸¸Â¼¼¼¾¾¾»»»»»»···­­­©©©­­­³³³¸¸¸¾¾¾Âµµµ»»»ÉÉÉÃÃÃÂÂÂÅÅÅÀÀÀ¼¼¼¿¿¿ÅÅÅÊÊÊÌÌÌÌÌÌÌÌÌÉÉÉÃÃÿ¿¿¼¼¼»»»ººººººÌÌÌÒÒÒÔÔÔÊÊʾ¾¾»»»ÂÂÂÇÇÇÅÅÅÅÅÅÃÃÃÀÀÀ¿¿¿¾¾¾¿¿¿Âººº¾¾¾»»»¾¾¾¼¼¼¿¿¿ÉÉÉÆÆÆ¾¾¾¼¼¼ºººµµµ±±±¯¯¯©©©¢¢¢¤¤¤¯¯¯±±±ªªª¬¬¬ºººÅÅÅÇÇǸ¸¸ÑÑÑÒÒÒ¼¼¼ÃÃÃÍÍÍÔÔÔ¿¿¿ÎÎÎããã××××××èèèßßßØØØÛÛÛÙÙÙ×××ÑÑÑÌÌÌÆÆÆÂ¿¿¿´´´¯¯¯¯¯¯´´´···³³³°°°¯¯¯ÊÊÊÇÇÇÐÐÐØØØØØØØØØØØØÕÕÕÉÉɺºº´´´¿¿¿ÃÃúººµµµººº¸¸¸¸¸¸¾¾¾ÀÀÀ¿¿¿ÃÃÃÇÇÇÀÀÀººº³³³±±±ºººÀÀÀ¿¿¿¼¼¼ººº···ÀÀÀººº¸¸¸ÑÑÑààà×××ÊÊÊÆÆÆÂÂÂÉÉɼ¼¼­­­°°°±±±···ºººÇÇÇÍÍͺºº¸¸¸ÅÅÅÀÀÀ¼¼¼ÇÇÇÍÍÍÍÍÍÇÇÇÃÃÃÇÇÇÊÊÊÊÊÊÉÉÉÎÎÎÕÕÕÔÔÔÉÉɾ¾¾ÀÀÀÊÊÊÑÑѾ¾¾ºººÅÅÅÙÙÙÔÔÔÇÇÇ»»»ººº¸¸¸»»»ÙÙÙæææÒÒÒÌÌÌÎÎÎÐÐÐÊÊÊÉÉÉÌÌÌÌÌÌÉÉÉÊÊÊÎÎÎÑÑÑÑÑÑÇÇÇÉÉÉÐÐÐÒÒÒÑÑÑÅÅÅÉÉÉÀÀÀ¸¸¸¾¾¾»»»¼¼¼ÒÒÒÜÜÜäääãããÐÐÐÆÆÆÃÃþ¾¾ÎÎÎçççÝÝÝëëëîîîæææØØØÝÝÝØØØÍÍÍÒÒÒÛÛÛ×××ÉÉÉÆÆÆÒÒÒÛÛÛÛÛÛÜÜÜÑÑÑÆÆÆÀÀÀÂÂÂÆÆÆÇÇÇÇÇÇÉÉÉÅÅŪªª¯¯¯µµµ­­­···»»»ººº¸¸¸¿¿¿¾¾¾´´´¼¼¼ÆÆÆÂ´´´···ººº¸¸¸ÆÆÆÎÎÎÅÅÅÆÆÆÆÆÆÀÀÀ»»»»»»ÀÀÀÉÉÉÍÍÍÐÐÐÎÎÎÎÎÎÌÌÌÇÇÇÃÃÃÀÀÀÂÂÂÃÃÃÎÎÎÒÒÒÐÐÐÃÃû»»¾¾¾ÃÃÃÅÅÅÃÃÃÃÃÃÅÅÅ¿¿¿¾¾¾¿¿¿ÀÀÀ¿¿¿ÇÇǾ¾¾ÀÀÀ¿¿¿¿¿¿ÑÑÑÅÅž¾¾¾¾¾¸¸¸´´´µµµººº´´´©©©¢¢¢­­­°°°©©©ªªª···¿¿¿¿¿¿¿¿¿ÍÍÍÇÇÇÃÃÃÆÆÆÆÆÆÉÉÉÆÆÆ×××ÝÝÝëëëãããäääîîîâââÛÛÛÜÜÜÛÛÛ×××ÒÒÒÍÍÍÉÉÉÅÅÅÃÃø¸¸···´´´±±±­­­¯¯¯»»»ÉÉÉØØØØØØÜÜÜßßßÝÝÝÛÛÛÙÙÙØØØÕÕÕ»»»ªªª°°°¸¸¸···³³³³³³´´´µµµ¼¼¼ÀÀÀ¾¾¾ÂÂÂÆÆÆÃÃÃÃÃ󳳬¬¬···¿¿¿»»»ººº¾¾¾¼¼¼ÅÅż¼¼´´´ÃÃÃÒÒÒÔÔÔÑÑÑÉÉÉÅÅÅÒÒÒÇÇÇ­­­¬¬¬­­­©©©³³³°°°ÅÅÅÍÍÍÀÀÀÂÂÂÇÇÇÀÀÀ¾¾¾ÊÊÊÑÑÑÎÎÎÌÌÌÎÎÎÐÐÐÍÍÍÔÔÔÔÔÔÔÔÔÐÐÐÆÆÆ¿¿¿ÆÆÆÐÐÐÊÊʸ¸¸¿¿¿ÐÐÐÝÝÝÇÇǾ¾¾¼¼¼¸¸¸ººº¿¿¿ÙÙÙàààÎÎÎÎÎÎÑÑÑÍÍÍÌÌÌÉÉÉÇÇÇÉÉÉÍÍÍÐÐÐÐÐÐÕÕÕÍÍÍ¿¿¿»»»ÀÀÀÊÊÊÑÑÑÐÐÐÊÊÊÎÎÎÊÊÊÊÊÊÃÃþ¾¾ÉÉÉÊÊÊ¿¿¿ÃÃÃÅÅÅÌÌÌÒÒÒÎÎÎÐÐÐÙÙÙÒÒÒòòòøøøîîîÝÝÝÜÜÜÕÕÕÛÛÛÒÒÒÕÕÕÙÙÙÒÒÒÆÆÆÌÌÌÔÔÔÑÑÑÌÌÌÆÆÆÀÀÀÃÃÃÊÊÊÎÎÎÌÌÌÇÇÇÆÆÆÊÊÊÀÀÀÅÅÅ¿¿¿¬¬¬±±±¼¼¼¿¿¿»»»ÀÀÀ¾¾¾´´´ÂÂÂÍÍ;¾¾ÃÃÃÆÆÆÂÂÂÅÅÅÎÎÎÉÉÉ¿¿¿ÆÆÆÎÎÎÉÉÉÀÀÀ¼¼¼¾¾¾ÃÃÃÊÊÊÎÎÎÑÑÑÒÒÒÒÒÒÑÑÑÍÍÍÌÌÌÍÍÍÐÐÐÑÑÑÐÐÐÇÇǾ¾¾»»»ÂÂÂÃÃÿ¿¿¿¿¿ÂÂÂÆÆÆÆÆÆÃÃÃÀÀÀÀÀÀ¿¿¿ÆÆÆºººÀÀÀ¾¾¾¿¿¿×××ÆÆÆ¼¼¼´´´¨¨¨¢¢¢ªªª´´´°°°¥¥¥©©©···ÇÇÇÒÒÒÔÔÔÐÐÐÇÇÇÂÂÂÆÆÆÊÊÊ¿¿¿ÇÇÇÒÒÒÌÌÌÍÍÍÉÉÉßßßÔÔÔÐÐÐÍÍÍÐÐÐÕÕÕÒÒÒÕÕÕÜÜÜÛÛÛØØØÔÔÔÐÐÐÍÍÍÊÊÊÉÉÉ¿¿¿¸¸¸°°°¯¯¯¸¸¸ÌÌÌÜÜÜÜÜÜàààâââââââââßßßÛÛÛÙÙÙÜÜÜÌÌÌ···­­­­­­±±±´´´´´´³³³³³³»»»ÀÀÀ¾¾¾¿¿¿ÆÆÆÅÅÅÊÊÊ»»»°°°³³³¸¸¸¸¸¸¼¼¼ÀÀÀÂÂÂÃÃü¼¼´´´µµµ¼¼¼ÉÉÉØØØ¾¾¾¼¼¼ÒÒÒÌÌ̱±±°°°°°°¦¦¦···©©©ºººÑÑÑÆÆÆºººÃÃÃÆÆÆÀÀÀÂÂÂÃÃÃÇÇÇÑÑÑØØØÕÕÕÌÌÌØØØÎÎÎÅÅÅÀÀÀ¿¿¿ÀÀÀÉÉÉÑÑÑÉÉɸ¸¸ÆÆÆÕÕÕßßß¿¿¿¸¸¸¼¼¼µµµÀÀÀÊÊÊÛÛÛÛÛÛÐÐÐÔÔÔÒÒÒÌÌÌÑÑÑÐÐÐÉÉÉÍÍÍÙÙÙÜÜÜÔÔÔÃÃþ¾¾ÀÀÀÌÌÌØØØÛÛÛÔÔÔÐÐÐÇÇÇ×××ßßßëëëäääÒÒÒÎÎÎÍÍÍÍÍÍÍÍÍØØØàààßßßßßßààààààÒÒÒêêêñññöööãããßßßÕÕÕàààÕÕÕÌÌÌÔÔÔÛÛÛÐÐÐÊÊÊÌÌÌÆÆÆÂÂÂÃÃÃÆÆÆÍÍÍÑÑÑÑÑÑÍÍÍÉÉÉÀÀÀÇÇÇÅÅÅÉÉɬ¬¬©©©³³³¾¾¾¾¾¾ÇÇÇÀÀÀ±±±¾¾¾ÌÌÌ¿¿¿ÆÆÆÊÊÊÉÉÉÌÌÌÍÍÍÂÂÂÃÃÃÒÒÒÙÙÙÔÔÔÌÌÌÃÃþ¾¾¿¿¿ÅÅÅÉÉÉÑÑÑÒÒÒÕÕÕÕÕÕÒÒÒÑÑÑÑÑÑÒÒÒÐÐÐÊÊÊÀÀÀ»»»¾¾¾ÂÂÂÀÀÀ¼¼¼¾¾¾ÀÀÀÅÅÅÇÇÇÆÆÆÅÅÅ»»»¾¾¾´´´¿¿¿¼¼¼¿¿¿×××ÇÇǾ¾¾°°°¡¡¡¤¤¤ªªª©©©¡¡¡ŸŸŸ©©©¾¾¾ÑÑÑÕÕÕÊÊÊÀÀÀ¾¾¾ÀÀÀÃÃí­­´´´ÂÂÂÉÉÉßßßèèèäääÕÕÕÎÎÎÔÔÔÙÙÙØØØØØØÝÝÝÛÛÛÙÙÙ×××ÔÔÔÑÑÑÎÎÎÎÎÎÍÍÍÉÉÉÆÆÆ»»»³³³ºººÌÌÌÙÙÙÜÜÜÜÜÜââââââàààäääãããßßßÜÜÜààààààÕÕÕ¾¾¾¯¯¯°°°µµµ¸¸¸³³³±±±ºººÂ¾¾¾¿¿¿ÅÅÅÆÆÆÌÌÌÊÊÊ¿¿¿±±±¯¯¯ºººÀÀÀÂÂÂÃÃÿ¿¿ºººµµµ¯¯¯¯¯¯ÀÀÀÛÛÛ¾¾¾¿¿¿ÕÕÕÐÐм¼¼ÂÂÂÀÀÀ···³³³´´´···ÊÊÊÍÍÍ»»»···»»»ÀÀÀ¿¿¿¾¾¾ÀÀÀÆÆÆÍÍÍÒÒÒÔÔÔ×××ÉÉɼ¼¼¼¼¼ÂÂÂÇÇÇÐÐÐ×××ÌÌ̺ººÇÇÇÑÑÑâââÀÀÀ»»»¸¸¸´´´ÉÉÉÙÙÙäääÜÜÜÕÕÕÙÙÙÐÐÐÑÑÑ×××ÕÕÕÍÍÍÎÎÎÔÔÔÐÐÐÃÃúºº»»»ÊÊÊÒÒÒÒÒÒÍÍÍÂÂÂÆÆÆÉÉÉÌÌÌÎÎÎãããàààÅÅÅÃÃÃÐÐÐëëëàààäääÛÛÛÊÊÊÐÐÐÛÛÛäääÛÛÛÙÙÙàààúúúäääçççÜÜÜÛÛÛÙÙÙÊÊÊÐÐÐÝÝÝÙÙÙÐÐÐÉÉÉÂÂÂÅÅÅÉÉÉÍÍÍÐÐÐÐÐÐÍÍÍÊÊÊÉÉÉÇÇÇÅÅÅ¿¿¿ÂÂÂÃÃ÷··­­­±±±´´´¿¿¿ÊÊʰ°°¸¸¸ÉÉÉÇÇǼ¼¼ÂÂÂÅÅÅÌÌÌÇÇÇÀÀÀÑÑÑàààÛÛÛÙÙÙÕÕÕÌÌÌ¿¿¿ÂÂÂÇÇÇÐÐÐÑÑÑÒÒÒÑÑÑÎÎÎÌÌÌÊÊÊÉÉÉÌÌÌÃÃþ¾¾¾¾¾¿¿¿¾¾¾¼¼¼¼¼¼¿¿¿ÀÀÀÂÂÂÅÅÅÆÆÆÅÅÅÂÂÂÀÀÀ»»»¸¸¸ÇÇÇÂÂÂÂÂÂÒÒÒÅÅŸ¸¸¯¯¯¨¨¨¦¦¦©©©©©©¨¨¨¦¦¦¬¬¬¯¯¯µµµ¿¿¿ÃÃÃÅÅÅÇÇÇÍÍÍÃÃÃÍÍͰ°°©©©³³³ÂÂÂàààäääÒÒÒÐÐÐÐÐÐ××××××ÑÑÑÒÒÒÕÕÕ×××ÕÕÕÒÒÒÑÑÑÐÐÐÐÐÐÐÐÐÐÐÐÉÉÉÌÌ̵µµ¾¾¾ÕÕÕÝÝÝ×××ÝÝÝãããßßßÛÛÛãããæææâââàààÛÛÛâââÝÝÝÊÊʺººµµµ³³³¯¯¯µµµ±±±¸¸¸Â¿¿¿ÀÀÀÅÅÅÅÅÅÉÉÉÑÑÑÐÐп¿¿´´´¸¸¸¾¾¾¾¾¾¿¿¿ººº···´´´¯¯¯¯¯¯ÀÀÀÕÕÕÃÃÃÂÂÂÎÎÎÅÅźººÂÂÂÀÀÀºººžžž­­­¬¬¬¼¼¼ÎÎÎÇÇÇÃÃÃÀÀÀ¾¾¾¿¿¿Âººº···ÆÆÆØØØÉÉÉÀÀÀ»»»¿¿¿ÇÇÇÍÍÍÔÔÔÙÙÙÌÌ̾¾¾ÊÊÊÍÍÍßßßÅÅÅÀÀÀ¸¸¸´´´ÌÌÌßßßèèèÛÛÛÒÒÒÙÙÙÐÐÐÕÕÕÔÔÔÔÔÔ×××ÔÔÔÊÊʼ¼¼³³³¾¾¾ÇÇÇØØØÑÑÑÌÌÌÐÐÐÑÑÑÝÝÝÆÆÆÂ¿¿¿ÕÕÕÛÛÛÉÉÉÔÔÔíííÐÐÐÍÍÍÛÛÛßßßäääêêêßßßÛÛÛØØØÑÑÑÕÕÕöööäääëëëÝÝÝ×××ÜÜÜÒÒÒÑÑÑÙÙÙÜÜÜ×××ÎÎÎÆÆÆÇÇÇÊÊÊÎÎÎÐÐÐÎÎÎÌÌÌÉÉÉÆÆÆÎÎÎÌÌÌÅÅÅÃÃÃÊÊÊÇÇÇ¿¿¿ÀÀÀ³³³ººº¾¾¾···¯¯¯³³³»»»¼¼¼ÆÆÆÆÆÆÇÇÇÐÐÐÀÀÀ¼¼¼ÒÒÒØØØÕÕÕÙÙÙÙÙÙÒÒÒÇÇÇÂÂÂÅÅÅÊÊÊÎÎÎÐÐÐÎÎÎÍÍÍÊÊÊÅÅÅ¿¿¿ÆÆÆÀÀÀ¿¿¿ÀÀÀ¿¿¿ºººººº¿¿¿ÂÂÂÀÀÀÀÀÀÀÀÀÃÃÃÃÃÃÀÀÀ¿¿¿ÍÍÍÂÂÂÃÃÃÑÑÑÊÊÊÅÅÅÎÎά¬¬©©©ªªª¯¯¯­­­¨¨¨¨¨¨¬¬¬´´´³³³¯¯¯¯¯¯³³³¼¼¼ÇÇÇÐÐо¾¾ÕÕÕÀÀÀ¸¸¸ÃÃÃÐÐÐßßßÍÍÍÍÍÍÒÒÒÔÔÔÒÒÒÍÍÍÊÊÊÑÑÑÕÕÕÒÒÒÑÑÑÐÐÐÎÎÎÎÎÎÎÎÎÐÐÐÐÐÐÆÆÆÑÑÑÊÊÊ···ºººÑÑÑÝÝÝØØØàààäääÜÜÜØØØâââçççääääääâââãããâââÙÙÙÒÒÒÊÊʼ¼¼¯¯¯···±±±¸¸¸ÂÂÂÀÀÀÀÀÀÅÅÅÅÅÅÅÅÅÐÐÐØØØÒÒÒ···µµµººº¼¼¼···´´´´´´±±±µµµÂÂÂÐÐÐÐÐÐÌÌÌÍÍͼ¼¼´´´¿¿¿¼¼¼¸¸¸¦¦¦¬¬¬¢¢¢¯¯¯¿¿¿ÆÆÆÐÐÐÇÇÇ¿¿¿¼¼¼ÀÀÀÃÃúºº±±±»»»ÎÎεµµ³³³µµµ¾¾¾ÆÆÆÉÉÉÎÎÎÒÒÒÉÉÉ¿¿¿ÐÐÐÊÊÊÜÜÜÃÃÃÆÆÆ¾¾¾···ÊÊÊÜÜÜæææÕÕÕÊÊÊÕÕÕÒÒÒÑÑÑÌÌÌÒÒÒâââãããÐÐо¾¾»»»ÂÂÂÉÉÉÕÕÕÇÇÇÅÅÅÎÎÎÃÃÿ¿¿ÃÃÃÆÆÆÀÀÀÎÎÎÒÒÒÅÅÅÊÊÊÛÛÛÎÎÎÕÕÕàààÝÝÝââââââÒÒÒÙÙÙÎÎÎÕÕÕÔÔÔïïïãããëëëÙÙÙÛÛÛßßßÛÛÛÕÕÕÕÕÕÙÙÙÛÛÛÔÔÔÍÍÍÅÅÅÇÇÇÌÌÌÐÐÐÑÑÑÎÎÎÉÉÉÅÅż¼¼¿¿¿¿¿¿»»»ÀÀÀ»»»¿¿¿±±±±±±¯¯¯±±±¿¿¿ÊÊÊÌÌÌÊÊÊÉÉÉÅÅÅÇÇÇÒÒÒÂÂÂÂÂÂÜÜÜØØØ×××ÔÔÔÔÔÔÕÕÕÎÎÎÅÅÅÂÂÂÅÅÅÊÊÊÃÃÃÅÅÅÆÆÆÂÂÂÆÆÆÊÊÊÃÃÃÆÆÆÃÃÃÀÀÀ¿¿¿ÀÀÀÂÂÂÀÀÀ¿¿¿¾¾¾¿¿¿ÃÃþ¾¾»»»ÌÌÌÕÕÕÌÌ̺ºº­­­°°°···±±±¬¬¬°°°³³³ªªªªªª©©©©©©ªªª­­­¯¯¯¯¯¯³³³±±±······­­­ÅÅÅÂÂÂÇÇÇàààÙÙÙÑÑÑÐÐÐÔÔÔÕÕÕÒÒÒÍÍÍÔÔÔÔÔÔÒÒÒÒÒÒÒÒÒÒÒÒÒÒÒÒÒÒÒÒÒÒÒÒÑÑÑÐÐÐÎÎÎÎÎÎÎÎÎÐÐÐÌÌÌÐÐÐÍÍÍ¿¿¿»»»ÒÒÒçççÛÛÛææææææâââäääàààâââîîîèèèêêêêêêçççääääääßßßÐÐп¿¿°°°³³³ºººÂÂÂÃÃÃÀÀÀÀÀÀÃÃÃÇÇÇÀÀÀÉÉÉÐÐÐÃÃø¸¸¸¸¸···´´´±±±°°°³³³³³³³³³»»»ÅÅÅÅÅÅÅÅÅÇÇÇÃÃû»»ºººµµµ©©©ŸŸŸ¤¤¤©©©¯¯¯´´´¾¾¾ÇÇÇÎÎÎÆÆÆ¸¸¸¼¼¼ÅÅž¾¾´´´±±±°°°³³³µµµ´´´ºººÅÅÅÆÆÆÇÇÇÔÔÔÊÊʾ¾¾ÇÇÇÒÒÒàààÌÌÌÃÃþ¾¾ÂÂÂÆÆÆßßßãããÔÔÔÍÍÍÉÉÉÎÎÎÍÍÍ×××ÜÜÜÜÜÜØØØÊÊʾ¾¾¿¿¿ÍÍÍÜÜÜÊÊÊÊÊÊÐÐÐÂÂÂÀÀÀºººÑÑÑÎÎÎÍÍÍÐÐÐÒÒÒÔÔÔÐÐÐÌÌÌÌÌÌâââæææçççÝÝÝÕÕÕÝÝÝÙÙÙÔÔÔÛÛÛÎÎÎÀÀÀèèèàààçççØØØâââàààÕÕÕ¿¿¿ÙÙÙÜÜÜÔÔÔÍÍÍÂÂÂßßßÎÎÎÆÆÆÆÆÆÃÃÃÊÊʸ¸¸¿¿¿¸¸¸···¾¾¾ÃÃÃÃÃÃÃÃÃÅÅÅ©©©¯¯¯°°°ÃÃÃÌÌÌÃÃÃÊÊÊÇÇÇÇÇÇÇÇÇÆÆÆÅÅÅÆÆÆÊÊÊÑÑÑÕÕÕ¿¿¿¾¾¾¾¾¾ÀÀÀÀÀÀ¿¿¿ÂÂÂÆÆÆÉÉÉÃÃÃÇÇÇÌÌÌÇÇÇÇÇÇÇÇÇÀÀÀ¿¿¿ÂÂÂÆÆÆÊÊÊÌÌÌÉÉÉÅÅÅÀÀÀÅÅÅ¿¿¿»»»¾¾¾ÅÅÅÍÍÍÃÃð°°¸¸¸¬¬¬¯¯¯µµµ°°°¬¬¬°°°³³³­­­¬¬¬ªªªªªª¬¬¬­­­¯¯¯°°°¸¸¸···ººº¸¸¸¬¬¬ÃÃÃÇÇÇÐÐÐÝÝÝÝÝÝàààæææèèèäääÙÙÙÑÑÑÕÕÕÕÕÕÕÕÕÔÔÔÔÔÔÒÒÒÑÑÑÑÑÑÒÒÒÒÒÒÑÑÑÐÐÐÐÐÐÐÐÐÐÐÐÑÑÑÌÌÌÌÌÌÊÊÊÀÀÀ¾¾¾ÐÐÐääääääçççãããâââëëëäääàààííííííïïïíííçççààààààâââÛÛÛÒÒÒ¸¸¸±±±°°°¸¸¸¿¿¿¿¿¿¿¿¿ÃÃÃÆÆÆÇÇÇÌÌÌÇÇǼ¼¼»»»¼¼¼···³³³¯¯¯°°°······±±±¬¬¬ªªª¸¸¸···¿¿¿ÀÀÀ´´´©©©¤¤¤¢¢¢¤¤¤¨¨¨¬¬¬­­­³³³ÀÀÀÎÎθ¸¸¼¼¼ÅÅž¾¾µµµ´´´³³³³³³µµµµµµºººÃÃÃÅÅÅÇÇÇÔÔÔÐÐп¿¿ÆÆÆÑÑÑßßßÌÌÌÅÅÅÀÀÀ¼¼¼¾¾¾ÕÕÕßßßÛÛÛÙÙÙÕÕÕ×××ÐÐÐÙÙÙÕÕÕÊÊÊÆÆÆÂÂÂÀÀÀÆÆÆÐÐÐÐÐÐÀÀÀÉÉÉÎÎÎÅÅÅÊÊÊÐÐÐÍÍÍÌÌÌÊÊÊÌÌÌÎÎÎÐÐÐÍÍÍÌÌÌÉÉÉÔÔÔÒÒÒ×××ÕÕÕÕÕÕãããâââçççßßßØØØÌÌÌëëëëëëäääÐÐÐÙÙÙâââÛÛÛÉÉÉßßßàààÔÔÔÉÉÉçççóóóÛÛÛÎÎÎÆÆÆºººÃÃÿ¿¿ÌÌÌÀÀÀººº¿¿¿ÉÉÉÌÌÌÉÉÉÆÆÆÆÆÆÊÊÊÅÅÅÉÉÉÆÆÆÀÀÀÊÊÊÊÊÊÊÊÊÍÍÍÐÐÐÐÐÐÌÌÌÇÇÇÅÅÅÅÅÅÊÊÊÉÉÉÅÅÅÀÀÀÃÃÃÉÉÉÍÍÍÎÎÎÊÊÊÆÆÆÇÇÇÉÉÉÆÆÆÅÅÅÃÃü¼¼¿¿¿ÅÅÅÍÍÍÒÒÒÒÒÒÐÐÐÌÌÌÇÇÇÊÊÊÉÉÉÅÅÅÇÇÇÎÎÎÉÉɺºº¯¯¯···­­­¯¯¯´´´±±±­­­°°°³³³±±±°°°¯¯¯¬¬¬¬¬¬­­­±±±³³³ººº······ººº¯¯¯ÅÅÅÍÍÍÙÙÙÜÜÜØØØÔÔÔÒÒÒÕÕÕØØØØØØÙÙÙÙÙÙÙÙÙÙÙÙØØØ×××ÔÔÔÑÑÑÐÐÐÔÔÔÒÒÒÑÑÑÐÐÐÐÐÐÑÑÑÒÒÒÒÒÒÎÎÎÉÉÉÆÆÆÀÀÀººº¿¿¿ÐÐÐàààèèèãããäääñññêêêàààîîîòòòñññïïïèèèããããããææææææãããÑÑÑ¿¿¿´´´ºººÀÀÀ¿¿¿¾¾¾ÀÀÀÆÆÆÍÍÍÎÎÎÀÀÀµµµ¾¾¾ÀÀÀµµµ¸¸¸±±±°°°µµµ»»»¸¸¸±±±¬¬¬¨¨¨¥¥¥°°°···¬¬¬¤¤¤¥¥¥¨¨¨©©©¨¨¨¨¨¨ªªª©©©­­­¼¼¼ÍÍ;¾¾¸¸¸¾¾¾ÃÃþ¾¾···µµµµµµ³³³µµµ···ºººÀÀÀÃÃÃÊÊÊÕÕÕØØØÅÅÅÉÉÉÔÔÔäääÐÐÐÉÉÉÆÆÆ¾¾¾ºººÌÌÌØØØÝÝÝàààÙÙÙØØØÕÕÕÛÛÛÎÎλ»»µµµ»»»ÂÂÂÌÌÌÝÝÝÑÑÑÀÀÀÇÇÇÍÍÍÀÀÀÆÆÆÙÙÙÇÇÇÇÇÇÇÇÇÇÇÇÊÊÊÌÌÌÌÌÌÌÌÌÑÑÑÔÔÔÐÐÐÕÕÕÕÕÕÑÑÑÕÕÕÕÕÕäääÐÐÐØØØÐÐÐàààòòòæææÙÙÙÜÜÜäääÛÛÛÌÌÌÛÛÛÝÝÝÙÙÙÒÒÒçççëëëÜÜÜÝÝÝÕÕÕÃÃÃÎÎÎÕÕÕÕÕÕÊÊÊÀÀÀÀÀÀÃÃÃÅÅÅÃÃÃÃÃÃÀÀÀÊÊÊÊÊÊÉÉÉÃÃÿ¿¿ÇÇÇÇÇÇÅÅÅÊÊÊÐÐÐÒÒÒÐÐÐÌÌÌÇÇÇÆÆÆÒÒÒÒÒÒÌÌÌÃÃÃÅÅÅÍÍÍÎÎÎÌÌÌÐÐÐÊÊÊÅÅÅÂÂÂÀÀÀÀÀÀÀÀÀ¿¿¿ÉÉÉÌÌÌÐÐÐÑÑÑÐÐÐÐÐÐÑÑÑÑÑÑÍÍÍÐÐÐÌÌÌÍÍÍÑÑÑÅÅŸ¸¸¼¼¼¸¸¸±±±°°°´´´´´´±±±³³³´´´···µµµ±±±¯¯¯­­­°°°³³³···µµµ±±±°°°¼¼¼¸¸¸ÌÌÌÑÑÑÙÙÙÔÔÔÔÔÔÔÔÔÕÕÕÕÕÕ×××ÙÙÙÙÙÙÝÝÝÝÝÝÝÝÝÜÜÜÙÙÙ×××ÒÒÒÐÐÐÔÔÔÑÑÑÐÐÐÐÐÐÑÑÑÒÒÒÒÒÒÑÑÑÊÊÊÂÂÂÂÂÂÀÀÀ»»»···ÃÃÃãããêêêèèèêêêñññèèèãããóóóöööïïïïïïïïïíííêêêèèèçççäääÔÔÔ···¾¾¾Â¾¾¾¼¼¼ÂÂÂÃÃÃÍÍÍÌÌÌ¿¿¿···¼¼¼¾¾¾µµµººº´´´³³³µµµ»»»¼¼¼¸¸¸³³³­­­¨¨¨ªªª¬¬¬¨¨¨¬¬¬µµµ···­­­­­­ªªª©©©¬¬¬µµµÀÀÀÆÆÆ»»»¼¼¼ÀÀÀÃÃþ¾¾¸¸¸µµµµµµ´´´µµµ¸¸¸»»»¿¿¿ÅÅÅÍÍÍÕÕÕÙÙÙÇÇÇÐÐÐÜÜÜëëëÕÕÕÎÎÎÊÊÊÅÅÅ¿¿¿ÊÊÊÑÑÑ×××ØØØÑÑÑÔÔÔÛÛÛÛÛÛÎÎξ¾¾ººº¸¸¸¿¿¿ÌÌÌãããÙÙÙÉÉÉÆÆÆÎÎλ»»×××ÅÅÅÅÅÅÅÅÅÆÆÆÇÇÇÉÉÉÌÌÌÎÎÎÍÍÍÍÍÍÎÎÎ×××ÙÙÙÕÕÕÙÙÙßßßÕÕÕ¾¾¾ÔÔÔÉÉÉÇÇÇããã××××××ÝÝÝàààÕÕÕÑÑÑÛÛÛØØØÛÛÛÜÜÜæææèèèâââæææÜÜÜÊÊÊÔÔÔÜÜÜÕÕÕÒÒÒÌÌÌ···´´´¸¸¸¿¿¿ÂÂÂÉÉÉÇÇÇÀÀÀ¼¼¼¾¾¾Â¿¿¿ÂÂÂÆÆÆÊÊÊÍÍÍÍÍÍÎÎÎÑÑÑÒÒÒÍÍÍÎÎÎÌÌÌÆÆÆÉÉÉÐÐÐÑÑÑÍÍÍÍÍÍÊÊÊÆÆÆÅÅÅÇÇÇÉÉÉÉÉÉÊÊÊÐÐÐÑÑÑÑÑÑÐÐÐÎÎÎÎÎÎÑÑÑÔÔÔÎÎÎÎÎÎÇÇÇÊÊÊÎÎÎÀÀÀ´´´ººººººµµµ³³³µµµ¸¸¸¸¸¸µµµ¸¸¸ººº¸¸¸···³³³°°°±±±···»»»¼¼¼´´´±±±ÉÉÉÊÊÊÕÕÕÒÒÒÑÑÑÎÎÎÒÒÒÙÙÙßßßàààßßßÜÜÜÛÛÛàààààààààßßßÜÜÜØØØÒÒÒÑÑÑÒÒÒÑÑÑÎÎÎÐÐÐÑÑÑÑÑÑÐÐÐÎÎÎÊÊÊÂÂÂÆÆÆÃÃÿ¿¿µµµ»»»ãããëëëòòòñññïïïçççêêêúúúöööñññòòòòòòòòòîîîçççãããâââ»»»´´´´´´¼¼¼ÀÀÀ¼¼¼¾¾¾ÅÅÅÂÂÂÆÆÆÇÇÇÅÅÅ¿¿¿ººº···¸¸¸´´´µµµ¸¸¸ººº»»»ººº´´´¯¯¯³³³¯¯¯¬¬¬©©©¯¯¯ÂÂÂÌÌ̬¬¬­­­¨¨¨¥¥¥±±±ÂÂÂÃÃø¸¸¸¸¸ÀÀÀÅÅż¼¼¸¸¸´´´´´´´´´···ººº¼¼¼¿¿¿ÇÇÇÐÐÐÒÒÒÑÑÑÇÇÇÔÔÔßßßêêêÔÔÔÍÍÍÉÉÉÂÂÂÂÂÂÌÌÌÍÍÍÍÍÍÍÍÍÊÊÊÕÕÕÜÜÜÜÜÜÕÕÕÐÐÐÌÌÌ¿¿¿»»»ÅÅÅÑÑÑÙÙÙÑÑÑÃÃÃÑÑÑÌÌ̺ººØØØÅÅÅÅÅÅÆÆÆÆÆÆÇÇÇÊÊÊÍÍÍÎÎÎÔÔÔÐÐÐÑÑÑÑÑÑÎÎÎÐÐÐÙÙÙèèèÑÑÑ¿¿¿ÛÛÛ×××ÜÜÜöööêêêîîî××××××ÎÎÎßßßãããÕÕÕØØØßßßííííííæææãããØØØÒÒÒÜÜÜàààØØØÙÙÙÕÕÕÉÉɼ¼¼¸¸¸¼¼¼ÃÃÃÇÇÇÃÃÿ¿¿···¼¼¼ÊÊÊÎÎÎÎÎÎÇÇÇÉÉÉÊÊÊÌÌÌÊÊÊÌÌÌÐÐÐÑÑÑÑÑÑÒÒÒÒÒÒÑÑÑÒÒÒÔÔÔÒÒÒÐÐÐÆÆÆÌÌÌÍÍÍÑÑÑØØØØØØÔÔÔÕÕÕÒÒÒÒÒÒÒÒÒÒÒÒÐÐÐÎÎÎÎÎÎÐÐÐÐÐÐÑÑÑÒÒÒÐÐÐÉÉÉ»»»µµµ»»»»»»ºººµµµµµµ¼¼¼¼¼¼¸¸¸»»»ººº»»»ººº···´´´µµµººº¿¿¿ÆÆÆ¾¾¾¸¸¸×××ØØØÙÙÙÒÒÒÊÊÊÐÐÐÑÑÑÑÑÑÒÒÒÕÕÕÙÙÙÝÝÝßßßààààààßßßÝÝÝÙÙÙÕÕÕÒÒÒÐÐÐÑÑÑÎÎÎÎÎÎÐÐÐÑÑÑÐÐÐÌÌÌÇÇǾ¾¾¼¼¼Â»»»¼¼¼¸¸¸¸¸¸æææîîîøøøöööñññèèèïïïÿÿÿõõõõõõóóóòòòòòòíííæææââââââ³³³µµµ¼¼¼Â¿¿¿ÀÀÀÅÅÅÀÀÀÃÃÃÆÆÆÌÌÌÊÊÊ»»»µµµ¼¼¼ººº»»»»»»»»»¼¼¼ÂÂÂÃÃü¼¼»»»¸¸¸³³³ºººÍÍÍÎÎκºº©©©¨¨¨¢¢¢¥¥¥µµµÆÆÆÀÀÀ¯¯¯µµµÃÃÃÉÉɼ¼¼¸¸¸´´´´´´······»»»¿¿¿ÂÂÂÌÌÌÒÒÒÐÐÐÉÉÉÉÉÉØØØØØØÝÝÝÊÊÊÇÇÇÃÃþ¾¾ÃÃÃÐÐÐÎÎÎÌÌÌÉÉÉÇÇÇÙÙÙÙÙÙÝÝÝÜÜÜÜÜÜÛÛÛÌÌ̾¾¾¼¼¼ÂÂÂÒÒÒÙÙÙÃÃÃÎÎÎÐÐз··ÔÔÔÆÆÆÅÅÅÆÆÆÇÇÇÊÊÊÌÌÌÍÍÍÍÍÍÆÆÆÆÆÆÐÐÐÎÎÎÍÍÍÒÒÒØØØæææÎÎÎÂÂÂÍÍÍÉÉÉÝÝÝäääÒÒÒÎÎÎ×××ÕÕÕÇÇÇßßßßßßÔÔÔÝÝÝèèèæææææææææäääßßßàààãããÝÝÝÛÛÛÛÛÛØØØÒÒÒÐÐÐÐÐÐÐÐÐÍÍ͸¸¸´´´ººº¼¼¼ÉÉÉ×××ÔÔÔÒÒÒÆÆÆÉÉÉÍÍÍÍÍÍÍÍÍÌÌÌÌÌÌÍÍÍÒÒÒÑÑÑÒÒÒÔÔÔÑÑÑÌÌÌÉÉÉÉÉÉÉÉÉÐÐÐÑÑÑÕÕÕÝÝÝÜÜÜÕÕÕÕÕÕÕÕÕÔÔÔÒÒÒÑÑÑÑÑÑÑÑÑÐÐÐÐÐÐÔÔÔÔÔÔÕÕÕÎÎο¿¿···¼¼¼ÀÀÀººº»»»´´´´´´¼¼¼¾¾¾ººº»»»ººº»»»¼¼¼»»»¸¸¸¸¸¸¼¼¼ÂÂÂÅÅÅ¿¿¿»»»ÛÛÛØØØÔÔÔÑÑÑÍÍÍÎÎÎÐÐÐÒÒÒÕÕÕÙÙÙÜÜÜÝÝÝÝÝÝÝÝÝÜÜÜÛÛÛØØØÕÕÕÑÑÑÐÐÐÎÎÎÎÎÎÍÍÍÍÍÍÐÐÐÑÑÑÎÎÎÇÇÇÀÀÀººº¾¾¾Â´´´¼¼¼ÂÂÂÂÂÂñññòòòøøøøøøøøøñññòòòüüüòòòóóóññññññóóóñññêêêäääää人ºÀÀÀÅÅÅÅÅÅÅÅÅÅÅÅÃÃÃÂÂÂÀÀÀÆÆÆÊÊÊÑÑÑÑÑѺººÂÂÂÅÅÅÀÀÀ»»»ºººÂÂÂÐÐÐÕÕÕÒÒÒÐÐÐÍÍÍÊÊÊÅÅÅÂÂÂÉÉÉÃÃð°°­­­¥¥¥¢¢¢¬¬¬¼¼¼Âººº°°°°°°ÅÅÅÊÊÊÀÀÀ¼¼¼ºººµµµµµµ¸¸¸···¼¼¼ÀÀÀÅÅÅÐÐÐÕÕÕÍÍÍÌÌÌÔÔÔßßßÒÒÒÎÎÎÀÀÀÆÆÆÅÅÅÇÇÇÐÐÐÛÛÛ×××ÑÑÑÉÉÉÂÂÂÒÒÒÕÕÕâââàààÙÙÙÛÛÛ×××ÆÆÆ¸¸¸ÀÀÀÇÇÇÝÝÝÉÉÉÆÆÆÌÌ̸¸¸ÐÐÐÆÆÆÅÅÅÅÅÅÇÇÇÌÌÌÍÍÍÌÌÌÊÊÊÉÉÉÌÌÌ×××ÑÑÑÐÐÐÔÔÔÌÌÌÎÎÎÑÑÑÎÎÎÃÃû»»ãããÙÙÙÒÒÒÒÒÒØØØÙÙÙÆÆÆÙÙÙØØØÙÙÙêêêñññëëëãããäääæææàààÝÝÝ×××ÌÌÌÑÑÑÕÕÕØØØ××××××ÙÙÙ×××ÑÑÑ´´´³³³ÅÅÅÍÍÍÒÒÒÐÐп¿¿¼¼¼ÅÅÅÇÇÇÌÌÌÍÍÍÍÍÍÌÌÌÌÌÌÍÍÍÑÑÑÐÐÐÒÒÒÕÕÕÒÒÒÊÊÊÉÉÉÎÎÎÑÑÑÕÕÕÑÑÑÑÑÑØØØÕÕÕÎÎÎÑÑÑÛÛÛÕÕÕÐÐÐÎÎÎÐÐÐÒÒÒÔÔÔÔÔÔÛÛÛÊÊʺºº³³³ºººÀÀÀ»»»¸¸¸»»»´´´³³³¼¼¼¾¾¾¸¸¸ººº¸¸¸¼¼¼¾¾¾¼¼¼ºººººº¿¿¿ÃÃû»»ººº···ØØØÑÑÑÌÌÌÐÐÐÒÒÒÊÊÊÌÌÌÎÎÎÒÒÒ×××ÙÙÙÙÙÙØØØÛÛÛÙÙÙ×××ÔÔÔÐÐÐÎÎÎÍÍÍÌÌÌÍÍÍÌÌÌÌÌÌÎÎÎÑÑÑÍÍÍÅÅż¼¼ßßßâââÜÜÜ¿¿¿ÂÂÂÅÅž¾¾èèèõõõööööööÿÿÿøøøòòòùùùñññíííëëëïïïøøøøøøïïïæææããã···¾¾¾¿¿¿¾¾¾ÀÀÀÇÇÇÇÇÇÀÀÀÀÀÀÊÊÊÎÎÎÒÒÒÔÔÔÇÇÇ¿¿¿ÆÆÆÆÆÆÂ¼¼¼¾¾¾ÉÉÉÒÒÒÎÎÎÃÃÃÆÆÆÃÃÃÇÇÇÌÌÌÌÌÌÑÑÑÒÒÒÊÊÊ´´´¦¦¦¥¥¥···Â¾¾¾···¸¸¸¬¬¬ÃÃÃÊÊÊÀÀÀ¾¾¾»»»¸¸¸¸¸¸ººº···¼¼¼ÂÂÂÇÇÇÒÒÒ×××ÌÌÌÕÕÕßßßçççÐÐÐÆÆÆ¼¼¼ÉÉÉÉÉÉ×××ÝÝÝçççààà×××ÉÉɺººÆÆÆÒÒÒäääàààÐÐÐÕÕÕÝÝÝÎÎθ¸¸¾¾¾ºººÜÜÜÍÍ;¾¾ÉÉɾ¾¾ÔÔÔÆÆÆÃÃÃÃÃÃÆÆÆÌÌÌÍÍÍÊÊÊÆÆÆÊÊÊÇÇÇÐÐÐÉÉÉÐÐÐÝÝÝ×××ØØØßßßçççÊÊÊ···ãããÎÎÎ×××âââÐÐÐÜÜÜÊÊÊÝÝÝÛÛÛãããñññëëëñññÜÜÜØØØÙÙÙ××××××ÒÒÒÌÌÌÂÂÂÎÎÎØØØ×××ÑÑÑÑÑÑÐÐÐÎÎδ´´´´´ÊÊÊÔÔÔÔÔÔÎÎξ¾¾ÀÀÀÌÌÌÌÌÌÌÌÌÊÊÊÇÇÇÇÇÇÉÉÉÌÌÌÐÐÐÊÊÊÑÑÑÕÕÕÌÌÌÉÉÉÒÒÒØØØÕÕÕÑÑÑÌÌÌÉÉÉÊÊÊÍÍÍÐÐÐÑÑÑÕÕÕÕÕÕÔÔÔÔÔÔÔÔÔÕÕÕØØØØØØÌÌÌ»»»···ººº¸¸¸»»»¼¼¼µµµ´´´´´´µµµ¸¸¸»»»¼¼¼¸¸¸µµµ»»»¼¼¼¾¾¾¿¿¿¿¿¿¿¿¿ÃÃÃÇÇǼ¼¼ºººÍÍÍãããÔÔÔÔÔÔÊÊÊÒÒÒÕÕÕÎÎÎÑÑÑØØØÙÙÙßßßãããÜÜÜÕÕÕÔÔÔÑÑÑÍÍÍÍÍÍÍÍÍÊÊÊÇÇÇÌÌÌÊÊÊÉÉÉÌÌÌÑÑÑÒÒÒÊÊʾ¾¾âââäääâââæææçççíííóóóãããóóóõõõîîîèèèñññóóóïïïïïïêêêïïïöööüüüÿÿÿùùùñññêêêäää¾¾¾ÅÅÅÃÃÃÃÃÃÐÐÐÆÆÆÅÅÅÆÆÆÌÌÌÌÌÌÊÊÊÐÐз··¼¼¼ÂÂÂÅÅÅÆÆÆ¿¿¿ÃÃÃÕÕÕÛÛÛÉÉɺºº»»»ÀÀÀÅÅÅÇÇÇÆÆÆÆÆÆÊÊÊÎÎγ³³¯¯¯­­­´´´¾¾¾ÀÀÀººº±±±­­­»»»ÇÇÇÉÉÉÅÅÅÂÂÂÂÂÂÀÀÀ¿¿¿¾¾¾ÂÂÂÉÉÉÔÔÔÜÜÜÒÒÒÅÅÅÔÔÔèèèÒÒÒÉÉÉÇÇÇÂÂÂØØØÝÝÝòòòêêêçççèèèàààÒÒÒÌÌÌÐÐÐÝÝÝÝÝÝÐÐÐÒÒÒÊÊÊÌÌÌØØØµµµ¾¾¾¼¼¼ÍÍÍÑÑÑ¿¿¿ÍÍÍÆÆÆÔÔÔÍÍÍÊÊÊÇÇÇÇÇÇÊÊÊÊÊÊÉÉÉÆÆÆÉÉÉÎÎÎÎÎÎÐÐÐÌÌÌÒÒÒäääÝÝÝÒÒÒßßßÀÀÀ¼¼¼æææçççÐÐÐÕÕÕÎÎÎæææÇÇÇÛÛÛØØØíííñññãããÛÛÛØØØÕÕÕÔÔÔÒÒÒÑÑÑÍÍÍÊÊÊÉÉÉÃÃÃÆÆÆÆÆÆÅÅÅÔÔÔÐÐа°°°°°¿¿¿ÀÀÀÌÌÌÊÊʸ¸¸»»»ÀÀÀÇÇÇÍÍÍÎÎÎÅÅÅÉÉÉÌÌÌÅÅÅÐÐÐÎÎÎÌÌÌÍÍÍÊÊÊÀÀÀÅÅÅÒÒÒØØØÐÐÐÍÍÍÊÊÊÊÊÊÌÌÌÎÎÎÐÐÐÐÐÐÒÒÒÔÔÔÔÔÔÔÔÔÕÕÕÕÕÕÕÕÕÕÕÕÌÌ̺ºº´´´······¸¸¸»»»µµµ´´´´´´µµµ¸¸¸»»»»»»¸¸¸µµµ···ººº¼¼¼¼¼¼¾¾¾ÀÀÀ¼¼¼ÀÀÀÑÑÑàààÕÕÕÕÕÕÉÉÉÒÒÒÕÕÕÒÒÒÙÙÙßßßÛÛÛÛÛÛÜÜÜÕÕÕ×××ÔÔÔÌÌÌ¿¿¿¸¸¸¼¼¼ÆÆÆÍÍÍÉÉÉÊÊÊÇÇÇÉÉÉÉÉÉÇÇÇÃÃÃÅÅÅííííííæææçççêêêíííèèèÌÌÌàààíííîîîçççèèèêêêêêêíííëëëíííîîîòòòööööööóóóïïïààà»»»ÃÃÃÇÇÇÇÇÇÑÑÑÇÇÇÇÇÇÉÉÉÍÍÍÌÌÌÉÉÉÍÍ͵µµ»»»ÂÂÂÀÀÀÃÃÃÅÅÅÍÍÍÙÙÙÔÔÔÅÅž¾¾¼¼¼ÃÃÃÇÇÇÉÉÉÉÉÉÉÉÉÊÊÊÊÊÊÉÉÉÃÃÿ¿¿ÂÂÂÆÆÆÅÅźºº°°°­­­»»»ÇÇÇÉÉÉÅÅÅÅÅÅÅÅÅÅÅÅ¿¿¿ÆÆÆÐÐÐÕÕÕÛÛÛÜÜÜÔÔÔÊÊÊÛÛÛâââÊÊÊÃÃÿ¿¿¿¿¿ÝÝÝèèèÑÑÑÒÒÒßßßïïïòòòçççààààààÝÝÝ×××ÇÇÇÎÎÎÍÍÍÑÑÑßßßÂÂÂÅÅÅÂÂÂÌÌÌÎÎÎÆÆÆÐÐÐÅÅÅÜÜÜÌÌÌÊÊÊÇÇÇÉÉÉÌÌÌÍÍÍÌÌÌÌÌÌÊÊÊÍÍÍÊÊÊÐÐÐÐÐÐÕÕÕâââØØØÇÇÇÊÊÊÉÉÉÑÑÑàààãããÜÜÜÙÙÙÍÍÍÛÛÛÉÉÉÜÜÜÔÔÔëëëîîîÝÝÝÛÛÛØØØÕÕÕÒÒÒÒÒÒÐÐÐÍÍÍÊÊÊÇÇÇÃÃÃÆÆÆÆÆÆÆÆÆÕÕÕÒÒÒ···»»»ÀÀÀ···ººº»»»±±±»»»ÃÃÃÃÃÃÂÂÂÇÇÇÃÃÃÅÅÅÇÇÇÂÂÂÌÌÌÎÎÎÉÉÉÇÇÇÅÅÅÅÅÅÍÍÍÕÕÕÕÕÕÍÍÍÌÌÌÊÊÊÊÊÊÍÍÍÎÎÎÎÎÎÎÎÎÐÐÐÑÑÑÒÒÒÔÔÔÔÔÔÒÒÒÑÑÑÐÐÐÌÌÌ»»»±±±³³³´´´···¸¸¸µµµµµµµµµ···¸¸¸»»»»»»ººº¸¸¸···¼¼¼ÀÀÀÂÂÂÆÆÆÌÌÌÌÌÌÇÇÇ¿¿¿ÌÌÌÛÛÛßßß××××××ÌÌÌÕÕÕ×××ØØØÝÝÝàààÛÛÛØØØØØØÔÔÔÒÒÒÉÉɾ¾¾¸¸¸´´´»»»ÇÇÇÀÀÀÃÃþ¾¾ÀÀÀ¿¿¿¿¿¿ÅÅÅÜÜÜíííîîîæææèèèîîîñññäää¼¼¼ÇÇÇãããïïïèèèçççèèèêêêïïïòòòíííèèèêêêïïïóóóõõõóóóããã¿¿¿ÂÂÂÇÇÇÉÉÉÎÎÎÉÉÉÍÍÍÉÉÉÍÍÍÍÍÍÍÍÍÌÌÌ´´´¸¸¸¾¾¾¼¼¼ÅÅÅÍÍÍØØØÛÛÛÌÌÌ¿¿¿ÂÂÂÆÆÆÍÍÍÐÐÐÍÍÍÊÊÊÌÌÌÇÇÇÂÂÂÆÆÆÂ¿¿¿ÂÂÂÆÆÆÃÃúºº±±±¬¬¬»»»ÇÇÇÊÊÊÇÇÇÉÉÉÌÌÌÌÌ̾¾¾ÊÊÊÑÑÑÔÔÔÒÒÒÐÐÐÎÎÎÍÍÍÜÜÜ×××ÆÆÆÉÉÉÀÀÀ¾¾¾ÜÜÜçççÔÔÔÕÕÕßßßëëëîîîæææàààâââããã×××ÆÆÆÍÍÍÎÎÎÐÐÐÝÝÝÊÊʾ¾¾ÇÇÇÑÑÑÊÊÊÌÌÌ×××ÊÊÊßßßÐÐÐÍÍÍÌÌÌÊÊÊÌÌÌÍÍÍÍÍÍÍÍÍÊÊÊÊÊÊÇÇÇÎÎÎÒÒÒ×××ÝÝÝÑÑÑÊÊÊÌÌÌÎÎÎÔÔÔÜÜÜÜÜÜ×××ÕÕÕÔÔÔÕÕÕÔÔÔãããÔÔÔòòòóóóàààÛÛÛØØØÕÕÕÒÒÒÑÑÑÎÎÎÌÌÌÉÉÉÆÆÆÂÂÂÅÅÅÆÆÆÇÇÇ×××ØØØÂÂÂÌÌÌÉÉÉ···³³³······ÀÀÀÇÇǺººÃÃÃÇÇÇÆÆÆÇÇÇÆÆÆÎÎÎÌÌÌÅÅÅÆÆÆÐÐÐÙÙÙÜÜÜ×××ÑÑÑÐÐÐÎÎÎÌÌÌÌÌÌÍÍÍÎÎÎÐÐÐÎÎÎÐÐÐÐÐÐÑÑÑÑÑÑÐÐÐÎÎÎÎÎÎÍÍÍÐÐÐÀÀÀµµµ´´´´´´´´´´´´´´´µµµµµµ···ººº»»»»»»»»»»»»ÂÂÂÇÇÇÊÊÊÉÉÉÊÊÊÎÎÎÉÉÉ¿¿¿ÃÃÃ×××âââÛÛÛØØØÙÙÙÐÐÐÛÛÛÙÙÙÙÙÙÛÛÛÛÛÛÙÙÙØØØ×××ÕÕÕÆÆÆ»»»¿¿¿ÑÑÑÕÕÕÃÃø¸¸»»»ÀÀÀµµµ»»»¸¸¸¸¸¸ÂÂÂæææèèèíííèèèêêêîîîòòòäää¾¾¾¿¿¿ÝÝÝïïïîîîîîîñññòòòöööùùùñññèèèçççíííòòòóóóòòòèèèÆÆÆÂÂÂÆÆÆÆÆÆÉÉÉÆÆÆÎÎÎÇÇÇÍÍÍÍÍÍÒÒÒÊÊÊ´´´µµµ¸¸¸¾¾¾ÌÌÌÕÕÕØØØ×××ÉÉɼ¼¼¾¾¾ÂÂÂÇÇÇÉÉÉÃÃÃÃÃÃÆÆÆÃÃü¼¼¸¸¸······»»»¿¿¿¿¿¿¸¸¸³³³­­­»»»ÉÉÉÍÍÍÎÎÎÐÐÐÑÑÑÑÑÑÎÎÎ×××ÐÐÐÌÌÌÉÉÉÅÅÅÉÉÉÍÍÍâââÎÎÎÆÆÆÍÍÍ¿¿¿»»»ØØØààà×××ÙÙÙäääïïïòòòêêêãããàààÔÔÔÊÊÊÂÂÂÎÎÎÑÑÑÔÔÔäääààà´´´ÊÊÊÝÝÝÊÊÊÉÉÉÜÜÜÒÒÒ×××ÕÕÕÒÒÒÐÐÐÍÍÍÊÊÊÉÉÉÉÉÉÉÉÉÉÉÉÊÊÊÆÆÆÍÍÍÐÐÐÐÐÐ×××ÐÐÐÂÂÂÎÎÎÀÀÀ¸¸¸ÙÙÙãããÒÒÒßßßØØØÎÎÎÛÛÛãããÐÐÐóóóõõõàààÛÛÛØØØÔÔÔÒÒÒÐÐÐÎÎÎÊÊÊÇÇÇÆÆÆÂÂÂÅÅÅÇÇÇÉÉÉÕÕÕÙÙÙÍÍÍÑÑÑÎÎξ¾¾µµµ»»»¿¿¿ÂÂÂÅÅÅÀÀÀ±±±¿¿¿ÉÉÉÅÅÅÆÆÆÆÆÆÍÍÍÃÃÃÂÂÂÌÌÌÜÜÜãããÛÛÛÔÔÔ×××ØØØÔÔÔÎÎÎÌÌÌÍÍÍÎÎÎÐÐÐÐÐÐÑÑÑÐÐÐÎÎÎÍÍÍÌÌÌÌÌÌÌÌÌÌÌÌÒÒÒÇÇǼ¼¼¸¸¸···³³³±±±´´´´´´µµµ···ººº»»»¼¼¼¾¾¾¿¿¿¾¾¾ÃÃÃÇÇÇÉÉÉÌÌÌÎÎÎÉÉÉÀÀÀÅÅÅ×××âââÕÕÕÕÕÕ×××ÑÑÑÛÛÛÜÜÜÛÛÛØØØÙÙÙÜÜÜÙÙÙÑÑÑÍÍ;¾¾ÀÀÀÎÎÎâââæææØØØÇÇÇ¿¿¿³³³´´´­­­¾¾¾¸¸¸»»»ÂÂÂäääêêêñññïïïîîîêêêëëëæææÇÇÇÊÊÊâââîîîîîîóóóøøøóóóòòòöööïïïêêêëëëïïïóóóñññíííßßßÅÅÅÂÂÂÇÇÇÉÉÉÇÇÇÅÅÅÌÌÌÍÍÍÎÎÎÌÌÌÐÐа°°µµµ»»»ÂÂÂÔÔÔØØØÐÐÐÎÎÎÉÉɾ¾¾···µµµ¸¸¸¸¸¸µµµ···¼¼¼¾¾¾ººº¼¼¼»»»»»»¼¼¼¾¾¾»»»···³³³°°°¼¼¼ÉÉÉÎÎÎÒÒÒ×××ÕÕÕÒÒÒÔÔÔÙÙÙÊÊÊÍÍÍ×××ÕÕÕÝÝÝâââæææÌÌÌÂÂÂÆÆÆ¸¸¸¼¼¼ÛÛÛãããçççææææææêêêêêêèèèèèèëëëÍÍÍÉÉÉÉÉÉÔÔÔÒÒÒÑÑÑÝÝÝããã¾¾¾ÊÊÊãããÍÍÍÀÀÀÑÑÑÐÐÐÐÐÐÔÔÔÒÒÒÐÐÐÌÌÌÉÉÉÇÇÇÆÆÆÆÆÆÅÅÅÌÌÌÆÆÆÊÊÊÊÊÊÆÆÆÐÐÐÑÑÑ¿¿¿ÌÌ̾¾¾¬¬¬ÌÌÌâââÒÒÒÙÙÙÑÑÑÇÇÇØØØÙÙÙÊÊÊëëëíííÝÝÝÛÛÛØØØÕÕÕÒÒÒÐÐÐÍÍÍÊÊÊÇÇÇÆÆÆÃÃÃÅÅÅÇÇÇÊÊÊÒÒÒØØØÕÕÕÐÐÐÍÍÍÀÀÀ´´´ºººÀÀÀ¾¾¾¼¼¼¾¾¾­­­»»»ÅÅÅÂÂÂÂÂÂÂÂÂÇÇÇ»»»ÇÇÇÔÔÔÛÛÛ×××ÌÌÌÎÎÎÝÝÝÛÛÛ×××ÐÐÐÍÍÍÍÍÍÎÎÎÑÑÑÑÑÑÑÑÑÐÐÐÍÍÍÊÊÊÉÉÉÉÉÉÉÉÉÉÉÉÐÐÐÌÌÌÅÅž¾¾ººº±±±¯¯¯µµµ±±±´´´···ººº»»»¾¾¾ÀÀÀÃÃÃÉÉÉÊÊÊÐÐÐÔÔÔÕÕÕÒÒÒÍÍÍÉÉÉÃÃÃÎÎÎßßßÔÔÔÕÕÕÔÔÔÒÒÒØØØÛÛÛÝÝÝÙÙÙÙÙÙÜÜÜÕÕÕÇÇÇÂÂÂÂÂÂØØØæææãããßßßâââÝÝÝÑÑѳ³³······ÌÌ̺ºº»»»¾¾¾ØØØæææîîîïïïñññêêêèèèîîîßßßÜÜÜæææçççêêêóóóóóóëëëèèèíííêêêêêêîîîñññïïïèèèãããÉÉÉ¿¿¿ÀÀÀÉÉÉÍÍÍÊÊÊÆÆÆÇÇÇÑÑÑÑÑÑÉÉÉÍÍ͸¸¸­­­···¿¿¿ÂÂÂ×××ØØØÉÉÉÆÆÆÇÇÇ¿¿¿···ÂÂÂÀÀÀ¿¿¿»»»ººº¸¸¸¸¸¸ººº¼¼¼»»»ººººººººº¸¸¸µµµ´´´µµµ¾¾¾ÅÅÅÊÊÊÑÑÑØØØ×××ÑÑÑÍÍÍÕÕÕÅÅÅÒÒÒæææãããæææää䨨ØÇÇÇÅÅÅÆÆÆ¾¾¾ÇÇÇÜÜÜÝÝÝÝÝÝàààæææêêêçççÝÝÝÒÒÒÍÍÍÑÑÑÑÑÑÔÔÔ×××ÑÑÑÊÊÊÎÎÎÔÔÔ×××ÇÇÇÛÛÛÍÍÍÂÂÂÃÃÃÆÆÆÎÎÎÉÉÉÊÊÊÊÊÊÊÊÊÇÇÇÆÆÆÆÆÆÆÆÆÂÂÂÊÊÊÅÅÅÇÇÇÆÆÆ¿¿¿ÇÇÇÎÎÎÉÉÉÂÂÂÇÇǺºº¿¿¿ÙÙÙÔÔÔÌÌÌÍÍÍÍÍÍÙÙÙÕÕÕÒÒÒëëëèèèàààÜÜÜÙÙÙÕÕÕÒÒÒÑÑÑÎÎÎÊÊÊÇÇÇÇÇÇÅÅÅÆÆÆÉÉÉÊÊÊÎÎÎÔÔÔ×××ÒÒÒÒÒÒÇÇÇ´´´¸¸¸ÅÅÅ¿¿¿ÀÀÀÃÃ÷··¿¿¿ÃÃÃÅÅÅÆÆÆÂÂÂÇÇǼ¼¼ÑÑÑØØØÑÑÑÌÌÌÊÊÊÍÍÍ×××ØØØÔÔÔÐÐÐÍÍÍÎÎÎÐÐÐÐÐÐÐÐÐÐÐÐÎÎÎÍÍÍÌÌÌÉÉÉÇÇÇÆÆÆÆÆÆÇÇÇÌÌÌÇÇǼ¼¼±±±­­­···°°°³³³···ººº»»»¿¿¿ÃÃÃÇÇÇäääââââââäääÝÝÝÎÎÎÆÆÆÇÇÇÆÆÆÉÉÉâââÜÜÜÝÝÝÙÙÙÛÛÛÙÙÙÙÙÙßßßÛÛÛÕÕÕÒÒÒÌÌÌÅÅÅÇÇÇÒÒÒçççïïïäääÜÜÜâââãããÝÝÝÒÒÒÕÕÕÕÕÕßßß´´´µµµ¼¼¼ÔÔÔæææëëëîîîóóóíííëëëõõõïïïêêêèèèâââæææñññîîîççççççæææçççëëëîîîíííää䨨ØÎÎο¿¿¾¾¾¾¾¾ÅÅÅÉÉÉÉÉÉÆÆÆÅÅÅÌÌÌÍÍÍÉÉÉÔÔÔººº°°°µµµ»»»¾¾¾ÑÑÑÕÕÕÉÉÉÂÂÂÀÀÀ¾¾¾¾¾¾ÑÑÑÍÍÍÊÊÊÉÉɸ¸¸···¼¼¼·········µµµµµµµµµ¸¸¸ººº¼¼¼¼¼¼¼¼¼ÀÀÀÊÊÊÔÔÔÔÔÔÎÎÎÕÕÕÝÝÝÇÇÇÔÔÔãããÔÔÔÐÐÐÊÊÊÉÉÉÇÇÇÌÌÌÇÇÇÅÅÅÒÒÒÛÛÛÑÑÑÑÑÑÔÔÔ×××ØØØ×××ÔÔÔÐÐÐÍÍÍÉÉÉÊÊÊÎÎÎÒÒÒÒÒÒÒÒÒÑÑÑÒÒÒàààÃÃÃÍÍÍÊÊÊÑÑÑÉÉÉ¿¿¿ÊÊÊÂÂÂÅÅÅÇÇÇÇÇÇÅÅÅÂÂÂÂÂÂÂÂÂÀÀÀÇÇÇ¿¿¿ÃÃÃÇÇÇ¿¿¿ÂÂÂÆÆÆÎÎκººÂ¾¾¾ÇÇÇàààØØØÔÔÔÉÉÉØØØÜÜÜ×××âââïïïçççãããÝÝÝÛÛÛ×××ÔÔÔÑÑÑÎÎÎÊÊÊÇÇÇÉÉÉÇÇÇÇÇÇÊÊÊÊÊÊÉÉÉÍÍÍÕÕÕÒÒÒÕÕÕÍÍÍ´´´µµµÅÅÅÂÂÂÅÅÅÃÃÿ¿¿ÀÀÀ¼¼¼ÂÂÂÃÃû»»ÂÂÂÅÅÅÛÛÛÙÙÙÊÊÊÌÌÌÔÔÔÐÐÐÊÊÊÒÒÒÑÑÑÎÎÎÎÎÎÐÐÐÐÐÐÐÐÐÎÎÎÎÎÎÎÎÎÎÎÎÍÍÍÊÊÊÇÇÇÅÅÅÃÃÃÀÀÀÉÉÉÉÉÉÅÅž¾¾°°°¬¬¬¸¸¸¯¯¯±±±µµµººº¼¼¼ÀÀÀÆÆÆÊÊÊßßßÛÛÛÝÝÝæææàààÑÑÑÌÌÌÒÒÒÌÌÌÊÊÊèèèèèèèèèâââãããÝÝÝØØØßßßÙÙÙÍÍÍÇÇÇÃÃÃÇÇÇ×××ãããçççëëëíííçççàààÜÜÜÛÛÛßßßààààààççç³³³¾¾¾ÕÕÕóóóñññññññññøøøïïïèèèòòòîîîïïïçççßßßäääïïïíííèèèîîîæææèèèííííííçççØØØÇÇǼ¼¼ÂÂÂÃÃü¼¼¼¼¼¿¿¿ÃÃÃÆÆÆÃÃÃÂÂÂÉÉÉÍÍÍÝÝÝ´´´±±±³³³¸¸¸ÌÌÌÒÒÒÌÌ̺ºº»»»ÆÆÆÉÉÉÃÃÃÅÅÅÊÊÊÅÅÅ······Â¾¾¾¼¼¼»»»¸¸¸µµµ···ººº»»»ÀÀÀ¼¼¼······ÃÃÃÐÐÐÒÒÒÍÍÍÒÒÒÜÜÜÆÆÆÒÒÒâââÐÐÐÍÍÍÉÉÉÌÌÌÐÐÐÐÐÐÀÀÀÀÀÀÕÕÕÙÙÙÎÎÎÑÑÑÔÔÔ×××ØØØ×××ÕÕÕÒÒÒÐÐÐÍÍÍÌÌÌÌÌÌÍÍÍÔÔÔÕÕÕÎÎÎÊÊÊ××׿¿¿ÆÆÆÆÆÆàààØØØÂÂÂÅÅÅÂÂÂÅÅÅÇÇÇÆÆÆÂ¾¾¾»»»»»»ÀÀÀÅÅźººÂÂÂÌÌ̾¾¾¿¿¿ãããÉÉɺºº···ÙÙÙäääÉÉÉØØØ¿¿¿ÛÛÛÙÙÙÔÔÔçççíííßßßàààßßßÜÜÜØØØÔÔÔÒÒÒÎÎÎÊÊÊÇÇÇÉÉÉÉÉÉÉÉÉÌÌÌÊÊÊÅÅÅÉÉÉÒÒÒÉÉÉÎÎÎÌÌ̱±±±±±ÀÀÀ»»»¾¾¾ºººººº···­­­µµµ¸¸¸­­­³³³ode-0.16/drawstuff/textures/ground.ppm0000664000175200017520000060005313403272463015052 00000000000000P6
# Created by Paint Shop Pro
256 256
255
››”‹„‹œ››¦§¨œ¤¦ƒ„„œ¤¦œ¤¦ƒ„„œ¤¦„„Š“““¦§¨›”›“Œ”¦§¨mtt‹…’œ››‹’Š’ŒŒ”š”‚v{œ¤¦‘ˆ}”››{{tdc\„Š„‹‹‹„Š}dc\…‹‹„Š„‹’Š”››„Š}¦§¨ƒ||UTSu{{bVU{{t‹„„„Š„|„…Œ”•lritt{‹‹‹‹‹‹zllf]c‹„‹“Œ”SKJŒ‹“™š¤Œ”•‹…’|„…{ttlekzll””‹‹‹„|‚z[[Ttslƒƒ|uztœ¤¦‹’ŠlriŒ”•„Š„””‹ƒ„„“““ƒƒ|ƒƒ|“Œ”ƒ‚uƒ||ƒ}ƒƒ}ƒ¨©´„„Šmtttts“Œ”lks}|’Œ‹“lekŒ‹“›”›‹‹‹lld|‚z”š”|‚zSKJ]bZƒ}ƒttsddc{tt[TTult{tttll‚v{tllŠƒ}cbV‹„„dc\lrijcVsre[TTsleSKJj]\\[[¦§¨:97*)(ztlJHFlddJHFVTL‘…„bVUVTLddcb[U…‹‹lrib[Uultmttlldllklld|„…dc\|‚z‹‹‹mtt“““‹‹‹Œ”•tslƒƒ|‚|utts‹„‹ddc„Š„{{tŒ”•mtt\UZ‹„„‹„„Œ‹“‹„„lj‘Œ…ƒ||ŠŠ}ttslldkd\lddult|‚z|‚zu{{ek]ƒƒ|lri|‚zztltsltslztl[[T„„Š{u{Œ”•]bZldd]cddc\mttUMRlddƒ}ƒVZTSKJD;9mttlld\[[Œ”•JHFUTSJHF[TT‹‹‹Œ‹“Œ”•‹„„ƒ||Œ”•œ¤¦tzlŒ”•mttŒ‹“|„…lksddc|„……„’“Œ”Œ”•{{ƒ}‡’|„…œ§²}|’”“›™š¤|„…}|’|„…„„Š{{ƒ›²„„ŠŒŒš™š¤„†™Œ”•™š¤›²{{ƒ{{ƒŒ”•}‡’…‹š¬¶Ã™š¤™š¤¬¶Ãœ§²…‹‹tts“Œ”llk“““‹‹„{{tš””{||„Š„ƒ||‹‹‹{||…‹‹”š”„Š}¤¤¦§¨›¢›¦§¨«²«‹’Šmttd\\tllultVTL‹„‹ƒƒ|‹‹„cbVœ››{ttƒ}ƒ{ttµ¶·“Œ”ult‹„‹r]gultf]c‹’Šƒ„„bVU‘ˆ}Š}ƒtll“Œ”„Š„tlllekztl{{t{tt”››mttult“Œ”{u{tllultŠƒ}{||‹„‹‹„‹“Œ”{{ƒŒŒšldd…‹’{{ƒ™š¤]cdƒ}ƒ“Œ”£œ¥ª³·…‹‹¦§¨ª³·‹„„{{ƒ‹„‹ƒ„„|„…u{{„„Š…‹‹{{ƒlksŒ”•”“›ª³·ƒ„„’…‹‹‹‹‹„„UUYldddc\ŠŠ}{{t‹‹„‹„‹‹„„’ŒŒ‘…„ultŠƒ}sre{zmttsj]\VTL„Š„SKJrg]iWU‚v{ekd¦§¨:97$kd\uztultultlddbVUVTLSKJkk]ŠŠ}‘Œ…ŠŠ}››”ztlVTLtzl{||lld‚|utts””‹tsl‹‹‹‹‹‹tsl…‹‹dc\tzlsle|„…u{{ekdtyglri”“›{||]cd{u{tzl‚v{ztl{{t|‚z‹„‹‚v{‚|uƒ||VTLddcb[UbVZ|‚z[TT[[Tlri{tt{u{rfklldttsd\\ult‹„‹‹„„{tti\Vredtzlllk{{ƒiq]{ttdc\ekddc\ztlƒ„„tzl]cd…‹‹JHFjcVLKRŠƒ}™š¤¦§¨uzt{{ƒ”“››¢›mttd\\\[[|„…|‚zuztnv‚mttlks{{ƒ„„Šœ¤¦}‡’^^qŒ”•mttddcŒ”•ŒŒš{{ƒnv‚}|’|„…lks}‡’…‹’yl„nv‚›²ª³·…„’ª³·nv‚Œ‹“}‡’{{ƒŒ—£Œ”•ª³·™š¤™š¤™š¤Œ”•ŒŒš“““Œ‹“Œ”•edk{{ƒ”“›Œ”•f]c|‚z‚|u”š”ƒƒ|{{t””‹ƒ„„ƒƒ||„…””‹„Š}{||JHF|„…{{ƒultredƒ}ƒŒ”•|‚z{||ª³·“Œ”ƒ}ƒzll›¢›‹’Š‹’Šƒ„„’…‹‹„‹|‚z„Š}jcVtll„Š}¤¤‰‰w{||„Š}ttsmttœ¤¦u{{tt{ttsu{{VTLlrimtt\[[|‚zlrilldmtttt{lks|„…tsl|„…„Š„™š¤‹…’\[bf]c‹…’lkslriƒ|||„……‹‹lks‹’Šƒ}Šdc\ultƒ}Š{u{tts…„’ŒŒš”𔋒Šu{{ddc|„…‹‹‹‹„‹UUYŠƒ}]bZtslddc“Œ”slesre‹„„‚v{lddslecbVSKJ{{tdc\kd\tzltslƒ||‰v|j]\[[T“Œ”:97:97cbVlrid\\tlltllldd[[T|‚zcbV„„Š””‹‹’ŠŠŠ}£››ŠŠ}“““{||lkscbV””‹„Š}tzl{u{ƒ„„{tt„Š}ekd{{tek]f]c{u{‹’Šddctll{u{lekƒ}ƒtll‹‹„dc\‹„„{tt{||{||ult‰v|ultult]bZ‹‹„‘Œ…{||tzledk]cd…‹‹‹‹‹fkktllsle[[T\[[ttslriekdmtt|„…tsllri\[[b[U{{t‹„‹‹‹„uzt[[Tddc[[T|‚z{{ƒd\\UTSult{tt{{tyl„lkstt{ult|„…|„…{{ƒ{{ƒ{{ƒ|„…{{t{{ƒŒ”•lks{{ƒ…„’Œ”•|„…nv‚{{ƒ|„…Œ—£fkk…‹’{{ƒ}|’^fsŒ”•™š¤Œ—£lkslksnv‚}‡’™š¤Œ—£Œ—£Œ—£|„…nv‚}‡’¡¡»ÂÇ»ÂǪ³·œ¤¦Œ”•ekd¦§¨…‹‹uztƒ„„‹‹„¦§¨“Œ”‚utlld‹‹„”“›Œ”•„Š}™š¤™š¤{{ƒ™š¤”š”œ¤¦„Š„ddcedkddclritsl{{ƒŒŒš‹‹‹‹‹‹lek””‹‚|u‹‹„lddztlred’ŒŒ‚|uŒ‹“]bZtslSKJf]cœ››‘ˆ}œ¤¦[[T‰v|“Œ”ƒ||{{ƒ‹„‹ƒ}ƒŠ}ƒult“Œ”f]c[TTlddd\\ƒ||\[b[TTUMRult|„…£œ¥¦§¨š””ƒ||¦§¨lld“Œ”‹‹‹|„…lksd\\{tttt{{|||„…‹‹‹ƒƒ|‹‹‹{u{rfkŒŒštt{ª³·|„…›¢›…‹‹|„…‹’Š”››uztf]clddrfk{{tsle‹„‹‘Œ…tll‚|urfkzllb[Ukk]ztlztldc\cbV|‚z{{tbVZ[TTSKJ‚utllk¦§¨LKR*)(rg]llk‹’Šlekult{u{VTLVTLllkƒƒ|uztVTLVTLedk|‚z{{t”“›‹„‹tsl|‚z|‚z“““ddcddcekd”š”VTLlri‹‹„f]cult…‹’ƒ„„tslŠƒ}™š¤{{ƒztl{{ttslƒ||sle]cdtll{{t{{tultŠ}ƒ|‚z{{tult{||mttVZ[JHF]bZ|„…lks‚v{f]cekdtt{‹„‹tll[[Tƒ}ƒƒ||Œ‹“{{ƒ{u{{{t]bZ{tt””‹¤¤‚|u‹’Štts‹‹„lld]bZ\[bSKJlksd\\tll“Œ”{{ƒttsu{{Œ”•tslu{{{{ƒmttek]}‡’„„Š|„…{{ƒ„†™u{{Œ”•Œ”•mtt|„…„„Šttsmttyl„nv‚^^q\[b\[bnv‚tt{†~‘u{{}‡’\[bnv‚n…œ§²Œ—£œ§²n…œ¤¦œ››Œ”•”𔋒Ћ‹„{{tŒ”•”𔍩´œ¤¦ƒ„„™š¤{||Œ‹“’ŒŒ“Œ”…‹’Œ‹“‹‹‹”š”™š¤œ››ƒ}ƒ‚utult™š¤lekddc…„’„„Š„„Š”“›{{ƒ‹„‹tsl‹„„‹‹„“““{{tƒ„„leklks¦§¨{tt¨©´‹„„“Œ”’…‹‹„‹„„Š|„…£››Š}|“““ƒ}ƒ²¬µbVZultlksŒ—£ƒ„„„„Šedktsl{{t…‹‹lks|„…llkdc\ttsfkk|‚z|‚zuztuztztllld››”{tt¦§¨u{{|‚zƒƒ|“““Œ‹“””‹‹„„„Š„tt{“Œ”…‹‹™š¤‹’Šuztœ¤¦œ¤¦{u{‹’Š„„ŠŒ”•‹’Šdc\{u{ƒƒ|‹‹„lldtt{£››‚v{ƒ||j]\‚ut{{trg]PF=]bZ[TTlri{{t{{tddcSKJbVUlldUTS¦§¨JHF*)(d\\ŠŠ}‹‹„{tt‹„‹lddlldsref]cf]clritslsleƒ„„llkš””„Š„u{{‹‹‹ekdlrilrimttlks{zm|‚z‹’ŠaWM‹„„lek‹…’|„…red\[[dc\ttsUTSš””››”‹„‹Š~‹tsl›”›‹„„kk]ult{{tƒƒ|ultd\\‚|uultf]cLKR:97MRKŒ”•“““›¢›””‹llk‹’Š{||{{ttzllri\[[llktslu{{¦§¨ƒƒ|ƒ„„œ››[[Tztlƒ‚u{{ƒ[[Tlrirfk\[[VTLmtt‹’Š{||‚v‚ƒ}ƒ‹„‹{{t|„…uzt”››]cd|„…tt{fkk{{ƒ|„…{{ƒŒŒš{{ƒ|„…Œ—£~’“‰Š¡|„…”“›|„…ttsnv‚…‹’}‡’}‡’{{ƒŒŒšnv‚lks{{ƒ…‹’™š¤}|’…„’ƒ}ŠŒŒšnv‚mk…Œ”•Œ”•™š¤ƒ}ƒƒ„„Œ”•{{t™š¤‹’Š«²«œ¤¦™š¤Œ‹“…‹‹™š¤¦§¨”“›tts‹‹‹llk™š¤”“›{{ƒƒ}Šult£œ¥{{ƒlks|„…\UZ£œ¥’ŒŒ¨©´”“›‹„‹“Œ”£œ¥tts£œ¥“Œ”|„…œ››œ››²¬µ£››f]c“““red|‚zuzttts{{tJHFƒ||’…‹lddldd{ttultSKJ‹„‹›”›VZT{u{uzt…‹’{{ƒ|„…ƒ‚u”“›““““Œ”ƒ}ƒ‹‹‹|‚z£œ¥ƒ„„œ¤¦uztƒ}Š|„…‚v{‹…’|„…Œ‹“…‹’tt{edk|„…lks‹„‹{{ƒmtt]cdŒ”•|„…{{ƒtt{tll{{tmtt„Š}‹„‹lldrfk„Š}Š}ƒŒ”•ultrfk‘Œ…ztl””‹Šƒ}ztf{zmd\\|‚zdc\dc\]bZƒ}ƒaWMtt{\UZFD;™š¤?;C?;Cred””‹lldj]\f]ctlllldƒ„„{{ƒllk„„Šekdƒ||j]\ultlektt{\[[ldd…‹‹tygek]ult\UZ]bZƒ||lridc\{ttult…‹‹„Š}{u{rfk…‹’lri|„…ult‹‹„{||ƒ||tslŒ”•|„…ƒ‚uƒƒ|{{tdc\cbVƒ„„¦§¨„Š„„Š„MRK*)(UTSlldƒ„„”››mtt„Š„ddc”“›ekdllkttsllk{u{]bZƒ„„\[[…‹‹‚|u””‹„Š}ƒƒ|‹„„ddcleklldŠƒ}kjVSKJUMR‹’Šƒ}ƒ™š¤£œ¥…‹‹tts|„…|„…Œ‹“lks{{ƒ“Œ”u{{‹‹‹mtt†~‘Œ—£Œ”•Ž¡›}‡’}‡’™š¤¨©´…‹‹|„…^^q}‡’n…tt{Œ—£{{ƒ…‹’™š¤™š¤“Œ”…„’Œ—£™š¤Œ”•|‚zu{{Œ”•ƒƒ|ª³·‹’Š›¢›‹„„{||‹’Š|„…”š””››|‚z‹„‹œ››ƒ„„¦§¨²««¨©´™š¤llk„„Štt{œ¤¦œ§²’…‹Œ”•‹…š‹’Š|„…lks‚v‚ttsllk”“›™š¤“““…‹‹…‹‹ƒ||›¢›‹’Š‘…„’ŒŒƒ„„red£›››”›sre””‹’ˆ{{t{zmuztlddlldsle„Š„\UZtts‰Š¡tts|„…{u{{{ƒ‹…š’ŒŒ“Œ”‹„‹{{tuztƒ„„¦§¨””‹{tt‹‹„ƒƒ|rg]kk]ƒ„„’ŒŒ‹’Š“““™š¤¨©´”››¨©´|„…„„Š{{tœ¤¦…‹’”š”Œ‹“|„…|„…u{{fkk‹’Š”››”š”mtt|„…ª³·‹‹‹JHF‚v{™š¤tzli\VtslbVU‚v{”š”rfkr]gyleSKJtsl\[[„Š„leklldƒƒ|JHFztfb[U]bZ[[T¦§¨UUY:97lldsleuztrfkr]gekdVTLj]\d\\\[bdc\‚|u””‹ƒ||{u{{||tsl|„…‰ƒv[TTkk]lri‚|u|‚zu{{{tttsl{tt‹‹‹’…‹{||‹‹‹ultsle{u{\[[|„…‹‹‹…‹‹¦§¨š””ƒƒ|‹„‹{||ekd“““bVU‹’Šƒ„„“““lldtts{ttJHF:97o€wVTLuzttzlƒƒ|‹‹„lldrg]j]\ƒ‚usreJHFlrillkrg]dc\’ŒŒ‘Œ…ŠŠ}ddcƒ„„|‚z]bZ|„…mttSKJmwf]cf]clkslks“Œ”„„Š‹’Š|‚z|„…ult{{ƒ{{ƒƒ„„{||‹’Š…„’mttŒ—£{{ƒ}‡’„„Šn…{{ƒyl„Œ‹“mtt|„…{{ƒ}|’nv‚™š¤Œ—£^fs{{ƒ…‹’mtt¨©´™š¤Œ—£œ§²…„’Œ—£}|’lksedk›¢›“Œ”””‹“““›¢›œ¤¦··Ä‹„„™š¤„„Šƒ}ƒ£²£››¨©´”“›¨©´‹…’tts{{ƒmtt{{tŒ”•‹‹„llk”š”…„’ztl{{ƒ\[bŒ‹“bVZred{||ztl‹’Ф¤¦§¨„Š„””‹u{{ekdlek”“›mttœ¤¦Œ”•tslœ¤¦Œ”•lriu{{tts{||’ŒŒ…‹’{u{\[b‹…’{u{{{ƒ|„…ŒŒš…‹‹f]ctll”š”Œ”•|‚z]cd|„…edk|„……„’{{ƒ”››ttsŒ‹“u{{{{ƒŒ‹“{{ƒ²¬µ™š¤„„ŠŒ”•lek‹’Š››”tts…‹‹mttlkstt{„Š„Œ”•„Š„lriddc|„…|„…uzt™š¤sreUMR„„Š|„…tllbVUƒ||Š}ƒ“““SKJ‚utŠƒ}kd\‚wlultdc\“Œ”‹‹„””‹llkPF=]bZSKJVTL¨©´f]c:97lekztl‘Œ…ƒ‚uƒ„„‹‹‹tzllek[TTf]clks]bZ””‹‹‹„u{{{{ƒtsltll{||Š}|„Š}\[[u{{“Œ”mttVTL„Š}{tt‹„„‹‹„{{ƒ‹„‹œ››srettsLKRmtt{||sletzl‹‹„””‹“Œ”†~‘ulttts‹„„lks“““‹„„›”›f]cbVZUTSVTL[TT]cdƒ}ƒƒ||lddf]c{tt“Œ”[TT[TT{u{d\\UMRJHFJHFlekekdŠƒ}tzl]cdkd\ultu{{„Š„„Š„r]gf]cJHFddclrilriultŒ‹“Œ‹“…‹’Œ”•„vŒ{u{\[blks|„…mtt|„…]cdmttŒŒšmtt…‹‹Œ—£ƒ}Й𤅄’|„…|„…\[bmttOS`Œ—£lksŒ—£{{ƒ™š¤}‡’¨©´œ¤¦¬¶Ã…‹š|„…{{ƒŒ—£œ§²…‹šƒ}ƒ‹…’£²¨©´Œ”•›¢›œ¤¦‹„„›”›“““tts›¢›”“›“Œ”‹„„“Œ”slekk]”“›ƒƒ|tt{tts‹’Š{||uzt“““‹‹„ultztlekdtll{tttslƒ||››”‹‹‹ƒ||£œ¥”“›f]c“Œ”‹„„““““Œ”‹„‹“Œ”tt{„vŒlddJHFMRKfkkiq]uzttts™š¤Œ‹“lks™š¤\[b]bZlksultŒ—£]cdlri]cdSKJbVU‹„„MSS{{ƒ|„…\UZult|„…Œ”•tt{u{{ŒŒšƒ„„{u{lddŒ‹“mttlld‹„‹{||””‹œ››lrilri””‹|‚z‹‹„lldtsldc\dc\ƒƒ|mtt|‚zuztSKJtllkd\{ttultzlliWUztlsleSKJzllslekd\‚v{ekdtslUTS]bZllkVTLd\\VTLek]…‹‹\[b*)(f]credtllsre{{tekd[TTddcult‹„‹dc\dc\tsltsl|‚zu{{‹’Š„„Šƒ}ƒsreƒ‚u››”Œ”•ztl„Š„””‹‹„„ŠŠ}b[Ub[UŒ”•\UZlekulttt{„Š}|‚z„„Š„„Š”š”{u{ƒƒ|™š¤sletslsreœ¤¦“““’ŒŒƒƒ|{u{f]cedkUUYUMR|„…{{ƒ…‹‹Œ‹“lri„Š„ztl{u{|‚ztllUMR‹’ŠVTL\[[ƒƒ||‚zkd\sle””‹llk[TTult{tt“Œ”kd\D;9edkJHFllkd\\sretts|„…Š}ƒœ››llklkslks\[b}‡’ekd…‹’{{ƒo€w…‹’¦§¨|„…{{ƒlks{||ult{{ƒmttmtt^fsu{{}|’}‡’nv‚nv‚|„…|„…mttœ¤¦}‡’œ§²}‡’Œ”•¬¶Ã„„ŠŒ—£Œ”•|„…Œ‹“ª³·Œ”•„Š„›²œ¤¦··Ä™š¤uztlriœ¤¦Œ”•ƒƒ|„„ЄЄtzl””‹b[Uƒ||ƒ„„Š~‹ƒ„„u{{‹’Š{||‹„„lks™š¤lek„„Š…‹‹™š¤“Œ”ztlƒ||¤¤¦§¨””‹lri‹„‹¨©´””‹”“›£››ƒƒ|{{tdc\¦§¨ultŠŠ}‹„„„Š„‹„„ƒƒ|››”|‚zƒ}ƒœ››ƒ„„Œ‹“lek]cd\[bUTStt{ƒ}Š{{tSKJ[TTtt{lldŒ”•fkkŒ—£Š~‹Œ”•{{ƒŒŒšŒ”•“““‹…’ult”“›ttsultƒ||\[bultf]c‹„„…„’u{{{u{|„…™š¤tt{ttslddŠ}|‹‹„|‚zdc\j]\d\\VTLlri¤¤{ttf]ctslldd‚v‚š””ztl{ttldd‹„‹‚v{cbVuztƒ}ƒtllVTLllktsl¦§¨\[b)+2mtt‚|utlltsllekb[Urg]ƒ‚uƒ„„{||dc\ek]|‚z“Œ”¨©´›”›™š¤‹„‹zllsreƒƒ||„…{|||‚z|‚z‚|uƒ‚ulldztlttstt{ultttsulttt{rg]ƒ||{u{”“›‘Œ…’…‹ƒƒ|ult‚v‚Œ”•red’ŒŒŒ‹“‹„‹ldd’ŒŒ‹„‹ƒ}ƒd\\[TTƒ||ƒ}ƒlek|„…‹‹‹lri{u{lld{||\[[ek]SKJtsl[TTb[Ulld|„…dc\ƒ‚usresle\UZldd{u{ztltsl[TT>B9o€wulttslnv‚“Œ”£œ¥Œ‹“Œ‹“…„’ŒŒš}‡’{||”“›Œ”•|„…ultnv‚Œ”•™š¤{{ƒ„†™™š¤…„’ŒŒšŒ”•u{{u{{|„…lksmk…Œ—£œ§²{{ƒ‰Š¡Œ”•}‡’{{ƒ™š¤Œ”•˜Ž£™š¤™š¤ŒŒš™š¤„Š„|‚z”››œ››{||”š””š”£››‹„‹““““““redƒ„„…‹‹‹‹„{u{‹’Šlri””‹‹„„|‚zƒ||‹‹„š””{tttslƒ||ƒ„„™š¤„„Š{tt„Š„sle‹‹‹’ŒŒ‹’Šz‚l”››ƒƒ|uzt¦§¨ŒŒš{u{’ŒŒ›”›{u{„Š„ztl{{tlldœ¤¦ƒ‚usle“““sleŠŠ}tt{j]\f]cf]cultult™š¤˜Ž£lks{ttedk\[b{{ƒllkddc]bZ{{tlld{ttƒ}ƒ¦§¨‹„„]cd„„Š{u{tts…‹‹UTS|‚ztts“““uztekdlld|„…›¢›ztl\[b‹‹„£œ¥“““‹‹‹„„Šmtt›¢›lksSKJ{ttlrikk]dc\UUYsle[[TjcVmttkd\ƒ||rg]tts{||‹‹„tllsleJHFddcdc\b[Uult{||›”›\[[:97‹„„zll{{ttslztlsreUMRztltts\UZ{{t{{tttslekŠ}|”“›ult…„’{{tŠƒ}kk]d\\{u{„‰vtzlŒ”•‹„„tslzlllrif]c‹„‹‚|u‚utUTSult‹‹‹tzl“Œ”’ŒŒ“““Œ‹“f]cƒ||‹‹‹‹„‹‹„„ult{u{{u{ƒƒ|Š}ƒldd[TTSKJ{{t“Œ”Š~‹ztl{tt{ttreddc\{tt‹„„‹…’‹„„””‹{||uztSKJ{zmek]lrittsldd‚v‚u{{UMRultD;9UTSLKRlri…‹’›¢›{u{{u{’ŒŒ{{ƒŒ”•{{ƒtt{lekttslriƒ}ƒtts]cd{{ƒu{{{{ƒlks˜Ž£‰Š¡„†™‹„‹¦§¨ª³·mtt{{ƒ^fsœ¤¦…„’…‹’…‹šŒŒš|„…œ¤¦Œ—£mttœ¤¦Œ”•œ¤¦{{ƒŒ”•~’“™š¤tt{…‹‹”“›tllƒ„„“Œ”Œ”•ŒŒš“Œ”„„Š{{ƒ‹…’Œ‹“””‹{|||‚zedk|„…|„…¦§¨„Š„{tt“Œ”’ŒŒ£››ƒ„„SKJ’ŒŒš””{ttŠ}|j]\tllJHF{{ƒ™š¤{{ƒlri|‚zdc\ƒ„„tsl{||{{ƒ‹’Š„„Š{{ƒkd\ztl””‹š””„„Š…‹‹\UZƒ}ƒƒƒ|{||f]c‚v‚Š~‹f]c{{ƒ˜Ž£¦§¨{tt”››ƒ||lek‚|u{ttuztult…‹’ttsŒ”•ƒ}ƒƒ||Š}ƒƒ}ƒ””‹lldƒ}ƒ{tt‹…’™š¤“Œ”u{{ultlks’…‹“““Œ”•{{ƒ‹„„œ››‹‹‹Œ”•tts|‚z\UZllk[TTddctsl]bZtzlSKJreduzt”“›u{{lddŠ}|‹‹„{ttekd‹„„ztfred[[T{{tek]redllkŠƒ}¦§¨[TT:97‹‹„zll””‹kk]d\\kd\lldred\[bf]clldlri{u{„„Š’ŒŒ{||tzllddœ¤¦f]cƒƒ|llkult’ŒŒ{zmztl”“›ŠŠ}‚v{kd\tts‘…„£œ¥lks‹„‹ƒ}ƒmttu{{mttuzt‹„„ƒ„„]cd‹„„’ŒŒult‚ut|„…“““ƒ„„¤¤„Š„„Š„ƒƒ|[[T|„…{ttƒƒ|ƒ„„{||ƒ||lri„Š„ƒ||‹…’ztlbVZ“““[[T‹‹„ƒ||cbVlldMRKd\\ekdƒ}ƒƒ„„SKJj]\SKJUMRultƒ„„{zmƒƒ|mwŒ‹“Œ‹“{{ƒŒ”•ƒ}ƒƒ}Šult…‹‹…„’„†™Œ‹“‹‹„{{ƒƒ„„›²„„Š|„…œ¤¦…„’”“›”››Œ”•]cd]cd}‡’lkslks…„’tt{˜Ž£{{ƒ\[b{{ƒf]c…‹’mtt™š¤„„Š…‹‹™š¤{zmƒ}Š‚v{”“›„„Š…‹’œ¤¦œ¤¦™š¤¨©´¨©´¬¶Ã“““‹’Ф¤‹’Š‹’Ѝ©´‹‹‹ª³·œ¤¦›¢›{zm‹’Š‹‹„ƒ„„“Œ”tts|„…„„Š]cd“Œ”„„Šlek…‹‹tsltt{ztltts|‚ztsl{zm£››£œ¥tsl‹‹‹ultu{{tll‰|vƒƒ|tlltsl{{ƒŠŠ}b[U‰Š¡™š¤“Œ”‹…š‚v{ƒ}ƒ‚v{ldd”“›{{ƒ”“›…‹‹fkkƒ}ŠUTSƒ}ƒ“Œ”‹„‹“Œ”‹‹‹{|||„…„„Šllk{tt{{t‹„‹š””£››‹„‹£››ƒ}ƒtlllek‚v‚ƒ}Šldd{u{ƒ||tt{Œ‹“|„……„’‹‹‹{u{‹„„cbV„„Š|„…lldiq]jV[Šƒ}”››››”ztl‹„„tslSKJ‚utVTLlri‚v‚lriUTSlddJHFFD;llktts›¢›SKJ:97lld{u{Œ”•‘…„£››ƒ||rg]JHFlek[[T|‚zekdldd™š¤bVU‹‹‹|‚zVTLek]|‚zdc\…‹‹|‚z„Š}‹‹‹‹‹„š””ƒƒ|ƒƒ|tsl‹‹‹…‹’£œ¥tll‹„‹‹‹‹„„Š‚ut{||tt{‹‹„llk“Œ”ekd‘…„tllƒ‚uƒ„„{{t[[Tœ››{{ƒ…‹‹|‚z{{ƒVTLtt{””‹tllttsŠ}ƒtsl“Œ”{tttts[TTyl„{u{lddekdVTLUMR‚wlsre{u{kd\lksu{{\UZf]csleg\rred™š¤mtt‚v{{||Œ‹“{u{ƒ}ƒƒ||lek{||{{ƒ{{ƒŒ‹“™š¤{||‹…š}‡’‹„‹„„Š{{ƒ…‹šŒ”•tt{„„Š…‹’|„…mttmtt^fs{{ƒ‰Š¡|„…„„Š{{ƒ{{ƒŒ‹“Œ”•{{ƒ¦§¨|„…Œ‹“Œ”•‹‹‹¨©´¦§¨™š¤…‹’™š¤¨©´„Š„›¢›}‡’¦§¨¨©´··Äƒ„„‹‹‹ƒ}ƒldd‚v{‹‹‹‹’ŠšŒ›¢›””‹™š¤tlluzt“Œ”tsl{{tf]cJHFf]cult¦§¨Œ”•tt{œ¤¦Œ”•œ››ƒ‚u”š”Œ”•‹‹‹ƒƒ||„…œ¤¦™š¤”“›[[Tsle[[Tkd\f]c‹„„›”›“Œ”Œ‹“ƒ||tt{\UZ{{ƒ|„…\[blkslri]bZ¦§¨ttssle{ttŒ”•tts„Š„zllkd\tllultŠ}ƒlekmttedk“Œ”{{ƒ“Œ”{{ƒ{{ƒ…‹‹{{ƒlld¨©´ƒ„„|‚z„Š„lld‹‹‹¦§¨¦§¨œ››lri¦§¨tts…‹‹‹’ŠcbVUTStt{|‚z\[[{{t\UZ{ttttssre„Š„slerfkƒ||‚|u{ttƒ„„fkkddc[[Tllkz‚lmttlriztl¦§¨UMR:97ƒƒ|‚|ukd\ztlu{{šŒylekd\{tttll„Š„ek]llk|„…{ttƒ||{||‚wl„Š}]bZ‹’Šlriuzt…‹‹””‹ldd”“›ƒ}ƒ{{t‚|u‹„‹uztult“Œ”{{ƒult{||”š”ƒ||“““ƒƒ||‚z{{ƒf]czllultƒ||SKJ{ttsleuztƒ||{{ƒMRKUMRlek‘Œ…””‹“Œ”š””f]c{ttdc\tlld\\tsltllj]\VTLVTL‹u…tt{‚v‚tslƒƒ|[[T[TT\UZult’ŒŒzll“Œ”ultedkldd|‚z””‹{u{›”›lddddc{{ƒtts{{ƒ”“›Œ”•…‹’‹„‹{{ƒyl„„„Š™š¤lksŒŒšŒ—£|„…\UZŒ‹“mtt|„…{{ƒnv‚{{ƒ…‹š¦§¨˜Ž£“Œ”Œ‹“™š¤‹„‹|„…”“›{{ƒnv‚{{ƒ{{ƒ}‡’”›››¢›‹‹„Œ—£››”‹…’¦§¨“““’ŒŒ¨©´ª³·u{{”››”››„Š}™š¤‹’Š…‹‹Œ”•lri‹‹‹uzt”š”llk‹‹„lek{||f]c\[[›”›¤¤œ›››¢›“Œ”Œ‹“”“›…‹‹‹‹‹“““„„Š‹’Šllk|‚zŒ”•Œ”•{ttultmwlekb[Ulri”𔑅„”››mtt’…‹“““f]cƒ„„sle“Œ”›¢›{ttVZ[mtt‹’Š]cdnv‚|„…lks]bZŒ”•£››››”Œ”•Œ”•‹‹„‹‹„‹„‹¦§¨‹…’“Œ”“Œ”ª³·‹‹‹zlltsl‹‹‹”š”ldd{ttultfkku{{“““{{ƒ™š¤Œ”•‹„‹‹…’ldd„Š„tsl\[[lri{{t¤¤tt{d\\VTLƒ||‹‹‹””‹ttslrikd\ƒƒ|SKJaWM[[Tf]c[TTVTL‹’Šlldlri«²«JHFUUYsleƒ||lddƒ||‹’Š‹„‹…‹‹{ttultedk‰ƒvlritsltts{{ƒƒ||{zmult’ŒŒƒ‚ntzlsretts|‚zztl‹‹„{tt{{t{{ƒ|‚z‹‹„£²tll£››‚ut”𔍩´’ŒŒƒƒ|]bZkd\’ŒŒŒ‹“{u{ztlldd{{ƒd\\edktt{‹‹„œ››ƒ||UUY[[TLKR{{ƒf]cultttslksultUMRlksddc\UZ\UZlekƒ}ƒrfkŠ}|‹„„tsl|„…{{tultttsƒ}ƒ{||šŒtll“Œ”f]cmtt{{tj]\f]cƒ}ƒmk…{tt|‚zmttu{{lks{{ƒ|„…lksult\UZtlllek‹…’ƒ„„\[bƒƒ|^^qŒ”•\[[mtt|„…Œ”•n…{{ƒMSSultœ§²¨©´›²{{ƒ~’“{{ƒœ¤¦^fs}‡’Œ—£œ¤¦‰Š¡š””𔔦§¨“““‹‹‹¦§¨‹„„‹’Š“““œ¤¦›¢›{||„„Š}‡’Œ‹“™š¤|„…›¢›œ¤¦‹’ŠŒ”•llk{ttƒƒ|]bZƒƒ|‹‹‹„Š„„Š}ƒ„„{{ƒ‚ut“Œ”tll‹’Ѝ©´œ››‹„„“““ƒƒ|ƒ‚uƒ||‹„„‹„‹¦§¨œ¤¦{{tƒ||‹‹‹…‹‹lriŒ”•|‚z‹„‹tt{{||SKJekdƒ„„{{t„Š„œ¤¦|„…{{ƒlri|„…Œ‹“œ››ƒƒ|‹„‹{{t“““‹‹‹uzt”š””››‹’Šœ¤¦”››œ››Œ‹“¦§¨”“›‹‹‹£œ¥””‹“Œ”“Œ”{u{ƒ}ƒŒ—£mttfkkult‚|uuztuzt”››lks¨©´ult“Œ”ttsb[U|‚zult””‹lekƒ||ƒƒ|srerg]ƒ||d\\ddc„Š„ztllldFD;f]clkskk]|‚z|‚z””‹””‹››”llk3+*ttsUMRf]cr]g{u{‹„‹Œ”•tsl‹„„lek{zmsletzl…‹‹š””„Š„lek’…‹””‹£œ¥Šƒ}Šƒ}ttsldd|‚zztl{{t{u{{||Š}ƒƒ||Š}|Š}|‹„„kd\ult{{ƒ‹’Š›¢›Œ”•…‹‹tslƒƒ|ƒ}Š‹„‹{u{[[TddclldŒ‹“„Š„ƒ„„{||VTLJHFVZTtsllks‹„„{u{„„Š“““{||{{t{{ƒ„„Š\[[\[[„Š}f]c{ttlldš””tts‹‹„f]c‚|uttskk]aWMVTLedklksmttƒ||f]clddtt{\[bult{||Œ‹“ŒŒš„„Š™š¤ŒŒšŒŒš{{ƒ‹„‹{u{|„…{{t™š¤ƒ}ЄЄ{{ƒttstts…‹’mtt™š¤\[bedk\[bŒŒš™š¤™š¤™š¤…‹šmttª³·Œ”•{{ƒmttnv‚Œ”•œ§²µ¶·£œ¥£²Š~‹{{t’ŒŒ‹‹‹”››¦§¨¦§¨…‹‹ttssreƒƒ|tts{||‹…’œ¤¦|„…‹’Š›¢›¦§¨|„…‹’Štts…‹‹|‚z„Š}œ¤¦‹’Š|‚z„Š}”››„Š„¦§¨“““¦§¨{{t|‚z‚wlƒ‚u£››’ŒŒ’ŒŒ²««{u{ultŒŒš›”›tt{œ››lek””‹“““‹’Š™š¤\[[ƒ||{||llk{{ƒ\[blks}‡’}‡’VZ[UMRedk…‹’uzt™š¤ƒ}ƒ{{t™š¤¨©´ª³·œ¤¦œ¤¦™š¤›¢›”𔋒Д››œ¤¦œ¤¦fkk{{ƒ{{ƒ{{ƒ‘…„f]cŠ}ƒ“““‹„‹ultult[[Tmttfkk„„Šƒ„„…‹‹‹„‹lek{tt„Š„{tt¨©´ƒƒ|‹„„ddckk]yfdtts£œ¥ƒ||kk]|„…ttsSKJtt{tzl[[T]cdlek‘ˆ}²««UTS*)(“Œ”ultbVZlek{{t{u{ƒ||{{ƒ‚wluztlri””‹u{{{||f]cu{{|‚zƒ||‹„„£››Š}|šŒultrg]››”‚wl””‹£››Œ”•‹‹„sle‚utƒ||{ttƒƒ|tt{…‹’œ››{{t|‚z’ŒŒƒƒ|‹’ŠŒ‹“uztf]c[TTddctlld\\tllkd\ldd\[[ultttsekdlks‹„‹lksƒ||UTSd\\llk…‹‹VTLtt{ttsƒƒ|{||{||[[Tg\rLKR‹„„lksf]cek]dc\‹„„VTLkd\]cd]cdek]ƒ||ƒ„„‹…’™š¤”“›…„’ƒ}Š…‹‹…„’“““ultŒ”•|„…llk¦§¨”“›œ¤¦™š¤lks“Œ”mtt{{ƒ{{ƒ|„…{{ƒedk|„…\[[edk{{ƒ{{ƒ„vŒŒ”•uzt{{ƒ™š¤{{ƒtt{™š¤Œ”•œ¤¦™š¤¦§¨ƒ„„Š}ƒ{u{‹„„|‚z››”‹’Š“Œ”™š¤tsllksultultƒ||œ¤¦„„Štllƒƒ|Œ”•¨©´|„…{||„„Šœ››…‹‹Œ”•]bZtts”“›tt{…‹‹…‹‹\[[lri””‹|‚z¦§¨tzl]bZttsu{{tll‚wlƒ}Šƒ„„ƒ‚uƒ„„|‚zedkuztu{{Œ”•{{ƒ™š¤ƒ„„…‹’mttult{{t{{ƒlri\[b]cdmtt|‚zz}lri|„…lksœ¤¦„„Ѝ©´Œ”•œ¤¦…‹’Œ”•œ¤¦ª³·”››f]c|„…‹’Šš””u{{œ››Œ‹““Œ”\UZŠ}|ultƒ}ƒtll{tt‚|uUMRllk“Œ”{{t£œ¥™š¤lksultlks‹…’{u{mttttsŠƒ}ƒ}ƒ[[TSKJbVZŠƒ}tt{‹„„„Š}[TTllktslkd\ƒ||sle|‚ztll{{t¦§¨llk74,SKJtll’…‹ddcmttldd{{tsle‘Œ…“Œ”f]cslesle|„…lri|‚z‚|u{tt‹‹„£››¦§¨‚|u…‹‹ƒ„„‹’Šsreƒƒ|Œ‹“™š¤’ŒŒlld‹‹‹mtt‹„„ƒƒ|ddctt{”𔋒ЄЄ{u{tslr]Zu{{‹‹„‚|uultllkfkkSKJ]bZ]bZF=CF=Cmttlriœ¤¦ƒ„„|„…{{t‹…’Œ”•tsllkstlltts]bZlekuzt|„…ddc„Š„lkslrid\\sleu{{slesred\\cbVtllƒ}ƒuztlritll{tt„„Š…‹‹Œ‹“ŒŒš£œ¥œ§²{{ƒ‹„‹œ¤¦™š¤ŒŒšllk™š¤‹„‹Œ‹“‹„‹{u{ƒ}ƒlks|„…{{ƒŒ”•|„…tt{|„…|„…›²›”›nv‚|„…{{ƒlks“Œ”{||…„’ƒ}Š£²“Œ”£œ¥™š¤{{ƒ™š¤tll‹„„tts[TT{ttŒŒš”“›¦§¨¦§¨ƒ}ƒ’…‹‚v{š””‹‹‹ztlƒ||mtt{u{…„’{||Œ”•œ¤¦ƒ„„™š¤SKJŒ‹“‚|u{{tŠ~‹…‹’Œ‹“{{ƒ|„…”š”edk|„…tsltzl{{t‹’Š‹‹‹›¢››¢›’ŒŒ{{ƒƒ„„lekŒ”•Œ‹“tt{Œ”•…‹’{{ƒmttldd]cd‚v‚lksu{{\[bUUYŒ—£mttŒ—£|„…{{ƒ{{ƒVZ[„„Š…‹‹Œ”•«²«™š¤¦§¨|„…mtt”“›™š¤™š¤tt{„„Šlks™š¤lks…„’Œ‹“ult\[[dc\ƒ||UMRyflreddc\j]\„„Šj]\{ttllkedkb[Uultult]cddc\[TTVTLtll[[Ttllr]gƒ}ƒ{{t››”‹‹„ekdultbVZj]\UTSC8.JHFldd²««›¢›JHF!ekd{{ƒ{{tultllksle|‚zb[Uš””‹„‹{{ƒ“Œ”£››ƒ||œ››…‹‹ƒƒ|’ŒŒŠŠ}{ttŠŠ}‹„„œ››‚v{‹„„‘Œ…ƒƒ|ttssle’ŒŒƒ‚uƒ„„„Š„‹„‹œ¤¦”››f]cŠƒ}’ŒŒmtt{{t…‹‹lri|„…‹’Š{||‹„‹tt{™š¤dc\tllekdlld‚v‚mk…mttŒ”•œ››Œ”•„„Š{|||„…„Š„rfkekdƒ„„[TTekdlld‹‹„mttek]…‹‹ƒ}ƒ‹„„lek\UZVTLlksŠ}ƒred’ŒŒult„„Š‹‹„d\\“““››”…„’”“›…‹’‹…’{{ƒŒŒš{||¦§¨}‡’˜Ž£\[[ddcult{||ƒ}Šƒ„„¦§¨lks|„…ttsŒ”•„Š„ŒŒš‹‹‹|„…”››„vŒ‹…’…‹‹„„Š|„…”››|„…”››™š¤Œ‹“Š~‹™š¤‹…’Œ”•|„…Œ”•œ¤¦™š¤”››Œ”•›”›‹‹„£œ¥”“›lks{u{£œ¥›”›…‹‹“““…‹‹…‹‹ldd{{ƒ‹‹‹mttœ¤¦Œ”•œ¤¦MSSUTSttsŒ”•“~ˆztl‹„‹‰v|]bZ””‹cbV¦§¨””‹|‚z””‹Œ‹“Œ‹“„„Š„„Š„„Š\UZddc\[[[TT{||™š¤Œ”•|„…™š¤mtt\UZlksultJHF\[bŒŒšUMRƒ}Š|„…Œ”•ƒ||œ››“““ult{{tultœ¤¦œ¤¦…„’Œ‹“™š¤µ¶·|„…|‚z‹’ŠŒ”•…‹’“Œ”Š~‹‹„‹{{ƒœ¤¦£œ¥ƒ}Šf]c[TTleksleztl{u{red“Œ”{tt‹„„‘…„™š¤rfkultƒƒ|ddc‹‹‹”“›ztlƒƒ|œ››ƒ||j]\„„Šƒ‚uƒƒ|cbVddcztlllkƒ}ƒkd\ƒ‚u{{tƒ||{zmµ¶·MRK*)(|‚ztlltts[TTlriredtslƒƒ|””‹ƒ}ƒ’ŒŒlldƒ||„„Š‹‹‹ƒ‚n‹„„²¬µƒƒ|‚|uŠƒ}œ››«²«‹„‹“““{zmlri™š¤’ŒŒztlbVUŒ‹“{tt|‚ztt{””‹uzttts””‹‹’Š‹„„|‚z”››ƒ||“Œ”tts‹‹‹…‹‹“Œ”š””“““mttUTS^^qlks{u{…‹‹™š¤…‹‹Œ”•{{ƒŒ”•{||‹’Šlddztldc\œ››ult„Š„…‹‹ŠŠ}‹„„‹…’ƒ||ƒ}ƒ{{ƒ”“›…‹‹“““£››Š}ƒ\UZ{{ƒƒ||ƒ}ƒµ¶·¦§¨Œ‹“™š¤‹‹‹†~‘|„…Œ‹“{u{uzt…‹‹{{ƒ|„…‹‹‹ult‹‹‹„„Š„„Šœ¤¦mtt™š¤…‹‹œ¤¦…‹’…‹’Œ”•ƒ„„¦§¨„„Й𤔔‹“““edk‹‹‹“““Œ”•{tt…‹‹¦§¨™š¤llkŒ‹“‹’Šult|„…ult“““Œ”•“““‹‹‹›¢›œ››¨©´|‚zƒƒ|{||£››‹‹„tzl‹’Šsle{||„„Š|„……‹‹”𔋋„]bZŒ”•ult{||{zmƒ||{{ƒ|‚zŒ”•›¢›{{t””‹„Š}{{t{{tƒƒ|£›››¢›ƒ„„{{tdc\tsl[TT‹‹„kk]f]cf]c{{ƒtt{„„Štt{lek|„…tt{fkkmtt]cdŒ”•}‡’…„’™š¤”š”’ŒŒ£œ¥‹…’|„…£²¬¶Ã™š¤™š¤‰Š¡{{ƒ”“›£œ¥™š¤™š¤””‹š””ultƒƒ|”“›ƒ}ƒ{||tsl{||llkedkŒ”•„„Š‹„‹¨©´ƒ}ƒƒ||“Œ”Œ‹“{u{“Œ”ldd“Œ”{tt“Œ”ƒ||slesleŒ‹“‹„„{{tj]\„Š}kd\ek]dc\ekdredVTLb[UVTL]bZSKJlksµ¶·VTL*)(ƒƒ|{u{{u{ztltts‚utsre‚|u””‹{{ƒ‹’Š™š¤b[U|‚zult‚ut”››|„…iq]{{t””‹‹‹„œ››{||™‹†b[U{zmŒ”•Œ”•{{t‹‹‹‹„‹|‚z{||{u{tt{tt{”››«²«”š”tslmttuzt|‚z…‹‹ƒ}ƒŒ‹“„„Štts¤¤uztlritsl]cdMRKllkmtttll‹’Š\[[Œ‹“|„…ztl{{ƒ{{t{tt‚|utsl{tt|‚zbVZ‹‹‹Š}ƒŠ}ƒ“““‹„‹›”›{ttmtt‹‹„‘Œ…lldSKJlddJHF’ŒŒ|‚zƒ}ƒ|„…ƒ}Šlri’…‹œ››mtt£œ¥‹„„mtt{{ƒ|„…ƒ}ƒ›”›‚wl†~‘¨©´¦§¨™š¤Œ”•œ››œ¤¦mtt|‚z”››œ¤¦…‹’tt{|„……‹’‹…’{||…‹‹ultu{{mttmttŒ—£…„’lks””‹¦§¨«²«¦§¨¦§¨œ››œ¤¦{||Œ”•”››…„’œ¤¦„„Š”“›lks…‹‹|„……‹’ddcf]c”“›µ¶·{{ƒ{u{¦§¨…‹‹ƒ„„Œ‹“lks””‹[TT\[[dc\|‚ztsl“Œ””“›«²«„Š„››”œ››|‚z‹‹„Šƒ}ƒ}ƒ{{ƒd\\llk’ŒŒ‹‹„tsl™š¤{{tƒ}ƒttsdc\ult[[TUUYlriuztMRKtllllkyl„ddc{{ƒ“Œ”£²ŒŒš”“›ult””‹{||ƒ}ƒ‹…’™š¤tt{¨©´„„Šƒ„„ƒ„„Œ”•„„Šztl„Š„”š”{||tsltt{u{{ddc”“›™š¤œ¤¦”“›”››‹’ЄЄ‹‹‹„Š„Œ”•“Œ”\[blldlddedkdc\‹’Š{{t‹„„lldj]\{ttSKJSKJ]bZlridc\d\\j]\j]\lddekdttsƒ„„²««UTS*)({tti\Vldd{ttŒ‹“‹„‹Šƒ}£››zllsre‹„„{{t{{tllkš””’ŒŒtsl›”›lrid\\yle’ŒŒ‹’Ц§¨ƒ||“Œ”‹‹„{u{lldyle‹‹‹ttsŠ}|{||„„Šd\\…‹‹‚|u‹‹„ƒƒ|{|||„…lrikd\…‹‹kd\„Š„œ¤¦”››“Œ”uztu{{uzt]cdUMR]cdddcd\\Œ‹“]bZult\UZd\\ƒ‚nsleu{{ƒ||{ttf]c{{tdc\ƒƒ|ƒ„„Šƒ}JHF{tt[TT‚|utslƒƒ|mwUMRtts“Œ”‹„„lksultlkstts{u{‹’Й𤓓“{{ƒš””£œ¥|„…|„…{||œ››“Œ”””‹Œ—£„Š„‹…’ŒŒš…‹’ƒ„„…‹‹{{t¡¡“““|„…lks{{ƒ{{ƒ…‹’¨©´{{ƒ”“›‰Š¡{{ƒ{{ƒ…„’{{ƒnv‚lksŒ”•»ÂÇŒ‹“…‹š”“›…‹‹››””š”œ››‹’Š„„Ѝ©´œ¤¦”››ult‹’Šu{{‹„„›”›‹„‹“Œ”¦§¨‚ut„„Š”“›‹’Š£œ¥™š¤{{ƒ”“›tts{{ƒ{||‹„„”›››”›¦§¨ŒŒš…‹’¦§¨“Œ”\UZŒ‹“”“›ult‹…’]cdult„„Š{ttult™š¤“Œ”llkŒ‹“|„…ultedk“Œ”…„’Œ‹“tts\[bf]cult¨©´{u{ŒŒš{{ƒŒ”•ƒ„„„„Šttsmtt|„…tt{„„ŠmttŒ”•{{ƒ›¢›Œ‹“œ¤¦‹’ŠŠƒ}Œ”•lld|‚z‹…’œ››“““dc\‚v{tts”š”|‚z„Š„š””d\\lks…‹‹|„…d\\red{{ƒ“““ƒ}Š\[[tslSKJƒ||tsl{ttultdkVSKJVTLVZTmtt\UZredtllztl\[[SKJ{{t²««JHF*)(dc\ultd\\i\Vƒ„„{tt››”‘Œ…ƒƒ|~’“…„’sre‹„„d\\‚v{„„Š’ŒŒƒ„„lldek]f]c‹„„…‹‹|‚zƒ||£››‹„„’…‹””‹zll‹‹„ƒ„„‹‹„tll‹’Š‹„„„Š„{tt‹‹„””‹ƒ„„tt{|‚z‹‹„|„…llk››”™š¤|„…ƒ||„Š}ek]|„…cbV„„Šlldmttd\\lldllkedk{{ƒŒ‹“llkultttsŠ~‹’…‹bVU››”[[T‹„‹ƒƒ|sreddcttsf]c‰v|ƒ||ƒ„„sleb[U‚|u‹‹‹ƒ„„tt{d\\\[bLKR™š¤”“›™š¤“Œ”{{ƒƒ„„“Œ”llku{{”››”“›{||Š}ƒrfkŠ}ƒ™š¤{{ƒ{u{zllœ¤¦Œ”•¦§¨Œ‹“u{{…‹‹™š¤™š¤ult™š¤…„’ult…„’™š¤{{ƒ‹…’{{ƒ›²›²œ§²”“›{{ƒ‹‹‹™š¤””‹”“›œ››“““tsl…‹‹”“›ƒ}ƒŒ‹“Œ”•|„…{||lldmtt…‹‹›¢›Ž¡›œ¤¦¦§¨lri›¢›Œ”•tts…‹‹‹‹„slemtt\[bultƒ}ƒ|‚z“““uzt‹‹‹›¢›…‹‹lld„Š„‹‹‹…‹‹ttslri“““œ››ƒ‚uƒ„„rfkƒ}ƒ“Œ”‹„„dc\JHFf]cƒ„„ultlldult{u{f]cƒ}Š…‹‹{||mttlldŒ”•œ¤¦{{ƒ”“›‹„‹ƒ}ƒ„„Š…‹‹™š¤›”›{u{”››ztl|‚z¤¤‹‹‹{{ttslsleƒ‚udc\„Š„ztlƒƒ|tzl“““slelksekd{{t¦§¨{||ultleksleUTSŒ‹“{||d\\slett{‰ƒvldd{ttsle‹’Š{{tUUYztlult|„…ƒ„„”š”sremttSKJcbV””‹F=C*)(d\\tts[TT‚v{{tt”“›{{tƒ‚u{zmultred{{tŠƒ}ldd‘Œ…“Œ”llk|‚z\[blld{{ƒ‹‹‹Œ‹“ƒ„„‹‹„‚|uƒ‚u””‹£››|„…µ¶·”“›„„Šult„Š„‹„‹|‚z“““››”‹‹„”š”f]c”››|‚z‹’Š„Š„Šƒ}ttsu{{]cd”š”JHFƒ}Š[[Tf]c\[[tt{ulttlllriŒ”•{{ƒƒ}ƒlekedkllk|‚z„Š„‚|u‚|udc\llkb[Ui\VUTSlddUMRkd\VTLrg]f]cf]c“Œ”‹„‹¦§¨‹„‹‚|u|„……„’„„Š…‹‹‰ƒv…„’ŒŒšƒ„„œ¤¦Œ‹“™š¤{{ƒ{||tll¦§¨Šƒ}‹„‹™š¤”“›Œ”•“““Œ”•ª³·ƒ„„ƒƒ|‹’Šuztlks{{ƒ{{ƒ™š¤Œ‹“‹’Š…‹’|„…}‡’{{ƒ^fs}|’~’““Œ”œ¤¦œ¤¦ƒ}Šƒ„„‹‹‹ƒ„„tllƒƒ|tt{‹‹„œ¤¦tsl››”lriƒ‚u‹„‹llkƒ}ƒlektt{¦§¨¨©´ƒ}ƒŒ‹““Œ”‹’Šlld“Œ”f]ctts{tt|„…uztj]\™š¤’ŒŒœ››‹‹„ƒƒ|„Š}tzl””‹ŠŠ}”››µ¶·ƒ‚ukjVš””ƒ||ztlšŒtll\[[„„Šddcult‹…’„„Šult‹„‹›”›{u{{{ƒtll‹’Šuzt‚|uœ››tll{{ƒ˜Ž£„„Š|„……‹’”››…‹‹{{ƒ“Œ”{u{Œ‹“u{{ƒ„„œ¤¦œ››{||]bZlriUTSd\\u{{‹„‹f]cŠ}ƒult{||™š¤d\\{ttsle‚|uztlƒ}ƒ‹„‹u{{Œ”•ƒƒ|’ŒŒ{||{u{ƒ||’…‹¦§¨„Š„¦§¨‹’Š{||ƒƒ|ƒƒ|Œ”•Œ”•‚|uƒ}ƒJHF[TTkd\¤¤VTL74,ulttsltts“Œ””š”“Œ”bVUƒƒ|‚wl[TTsle{tt{ttult‰ƒvlek‹„‹lldlriekdƒ||tllŒ”•|„…‚ut‚|uŠŠ}ƒƒ|’ŒŒ{||‹‹„|‚z‹„„„„Š””‹{tt{{t›”›¤¤‹‹„|‚zult…‹’„Š„‹’Štslultƒ}ƒ”“›{||”››ekdf]cUMRVZ[\[bƒ}ƒƒ||‹‹‹u{{Œ”•ek]”››”“›™š¤‹„„[TTlri{{ƒƒƒ|ddclridc\j]\Œ”•lriultlekŠ}ƒ””‹[TTƒ}ƒ„„Š…‹‹¨©´Šƒ}Œ”•”››™š¤£²…‹‹…‹‹¦§¨{{ƒŠ~‹|„…„Š„ŒŒštt{ƒ}ƒuzt“Œ”lriƒ}ƒ„„Š™š¤Œ”•”“›‹’Š|‚zu{{Œ‹“lriuzt{||“Œ”“““Œ”•lkstt{‹…’›”›™š¤¨©´™š¤¨©´¨©´{{ƒ™š¤Œ”•¨©´™š¤“““ƒ||lld|„…”››|‚zƒ|||‚z”››œ››¦§¨¦§¨››”¦§¨‘…„tts{tt“Œ”Œ‹“¨©´“““£œ¥…‹‹‹‹„lekŒ”•UTSttsŒ‹“‹…’„„Š‹‹‹ƒ„„“Œ”ƒ}ƒš””Š}|£››{zm¤¤¤¤››”œ››¦§¨‹‹„{{t‚v{tts„Š„““““““VTLlldlldSKJ‹„‹™š¤lekedk›¢›«²«œ§²uztttsƒ}ƒƒ}ƒƒ„„…„’™š¤£œ¥“Œ”™š¤‹„‹{u{”“›{ttult¨©´µ¶·Š~‹ttsƒ||mttf]cŒŒšƒ}Šƒ„„lld‹‹„‚v{”››‹…’ƒ}ƒtt{ztlrfkult›”›bVU™š¤u{{ƒƒ|ult…‹‹sle”“›‰ƒv‹„„{{ƒƒ„„‹‹„ƒ}ƒ{||„Š„‹‹‹’ŒŒcbV{{tedk{||„Š„¤¤JHF*)({{ƒlddttsztl“““ultcbVƒ||””‹rfk{zm’ŒŒ„Š}tll‹‹„j]\‘Œ…uztuztztflddd\\ƒƒ|tt{¦§¨™š¤ƒ‚uƒƒ|’ŒŒ{||„„Šlri{{t”“›œ››››”™š¤‹„„”“›ƒƒ|llklek…‹‹«²«£››{||ƒ||‹’Štts…‹‹|„…‘Œ…‹„‹|„…}‡’mttƒ}ƒd\\š””{||srett{Œ”•›¢››”›™š¤lekztltzlkd\“Œ”ƒƒ|kk]kd\{zmƒ}Š{ttu{{lrilld‹„„f]cztlŠ~‹{{tddc‹„„Œ”•„vŒŒ”•„Š„…‹‹mtt›”›rfkUTStsl{{ƒ|„…lld’ŒŒ‹…’…‹‹tslyl„ult™š¤{||…‹’mtt{||{{tleku{{›”›ƒ}ƒ‹„‹|„…Œ‹“‹’Š“Œ”œ¤¦œ››¨©´”“›„„Š{u{„Š„”“›Œ”•ƒ„„Œ”•lri‹’Šƒ„„œ¤¦‹’Š…‹‹uzt{u{··Ä“““¨©´„„Š’ŒŒŠ}ƒ’ŒŒ’ŒŒbVZ„„Šsle£››“Œ”‹’Šult””‹¦§¨›”›‘Œ…Š}ƒ¦§¨²¬µ›”›”“›¨©´¦§¨lek¢—‹’Š›¢›œ››››”›¢›“““rg]sleŠŠ}lri{zm“““tzl{{t””‹[[Tllduztƒ‚u™š¤Œ”•{{ƒmtt„„Š™š¤ƒ}Š]bZ…„’ult‹uŠ{u{‹„‹“Œ”£œ¥“Œ”ult‹…’tsl“Œ”lksVZT{{ƒŒ”•u{{‹„‹™š¤ƒ}ƒ{u{ƒ}ƒ„„Š‹…’‹…’{{ƒƒ}Šlldsle|‚z{{ttslkd\ultlksultƒ}ƒddcu{{bVZ…‹‹„Š„’ŒŒ[TTd\\{tt{tttygtts{{t‹‹„lektllkd\‚|ulkslldtsl£œ¥FD;*)(Œ”•‰|vtt{rg]ƒƒ|ƒ„„‚|u‹‹„tsltsltll{u{kd\|„…‰ƒvztl›”›lri‹’Š’ŒŒedk{{ƒ£››Œ‹“‚|uultz‚llld{{ƒŠ}ƒ›”›”››lldf]cƒ}Š{{tŒ”•tll“““›¢›Œ”•ttsœ¤¦”››¦§¨|„…\[[rfkƒ||uzt|‚z”“›Œ”•u{{‹„‹ŒŒšlri{{ƒ””‹‹’Š…‹‹{{ƒ‹„„|‚zœ››ƒ||ƒ}Š‹’ŠŒ”•{ttƒ}ƒrg]‹‹‹{{t|‚z„Š}ƒ}ƒ“““|‚zlriuztƒ}ƒlek‹…’‹„„lldllk”š”†~‘u{{…‹‹llkŒ‹“{u{Œ‹“ƒ||{||ttsœ››™š¤{||‚v‚tts‹„„{ttf]ctt{£››|„…‹„„”“›{{t”š”{{t›¢›ddcƒ}ƒu{{¸Á¹œ§²™š¤¦§¨¦§¨‹’Štts{{ƒ|„…mtt™š¤œ¤¦tt{Œ‹“u{{{{ƒ|„…”“›”››“Œ”ƒ||‹‹‹²¬µœ¤¦””‹{u{edk‹„„{{ƒ…„’”››“““u{{¦§¨”“›‹…’’ŒŒ£››¤¤£››¦§¨¨©´Œ‹““Œ”¨©´¦§¨”“›‹‹„redtllš””›¢›¦§¨Šƒ}£œ¥VTLztl„Š}¤¤ƒ‚u‹„„sleztlVTL{u{Œ‹“Š}ƒ“Œ”“Œ”‹„‹f]c™š¤£²£œ¥…„’|„…u{{mtttt{lksŒ”•“““œ¤¦™š¤™š¤œ¤¦››”ƒƒ||‚z„Š„|„…‹’Š‹‹„|„…u{{¨©´Œ‹““Œ”“~ˆbVUtslŠ~‹”››„„ŠJHFek]lks\[[¦§¨lrilri\UZbVUŒŒšƒ„„’…‹ult“““kd\zll[TTd\\uzt‚|usre’ŒŒd\\uztmw[[TSKJƒƒ|JHFd\\ult”“›JHF*)(‚|uztl”š”redƒ‚ulekrg]ztl¦§¨’…‹”𔋋„ult‹’ŠŠƒ}sre£››ult|‚z‘Œ…tts‹„‹fkk|‚zŠ}ƒ‹„„””‹£››’ŒŒ“Œ”sre…‹‹œ¤¦llk{u{›¢›“Œ”¤¤ƒ„„›¢›{||„Š„¨©´¦§¨¦§¨”››{u{lldu{{…‹š|„…uztultLKRVTL\UZlek“Œ””››”››uzt‹„„‹‹‹tts{u{…‹’™š¤œ¤¦[[T{{ƒlldultllkƒƒ|‚|u‹’Šztlƒ}ƒred„Š„ƒ„„‚v‚lddš””tsl{ttœ››¨©´uzt…‹‹lldlksƒ||Š~‹›”›‹„„lri[TTtslf]c„„Š‚uttsltll‚v{Š}ƒ”“›ƒ||ƒ||‹„‹lksƒ||‹‹‹|‚zult{{ƒ¦§¨Œ”•œ¤¦™š¤Œ”•¡¡œ¤¦œ¤¦|„…|„…Œ”•„„Ц§¨{{ƒ”“›„„Š“Œ”£œ¥™š¤™š¤‹„‹¨©´¦§¨{{ƒ¨©´›”›™š¤™š¤““““Œ”Š}ƒ²««{u{llk…‹‹’…‹··Ä‚v‚yfdƒ||‹‹‹‹„‹™š¤™š¤rfk“Œ”‹…’ƒ}ƒ‹’Š›”›™š¤ƒ„„‹‹‹Œ‹“{||ƒ„„ztluztlri‹’Š|„…lrillktt{|„…‹’Š{{ƒ]cd]cdœ¤¦mttfkkfkk{{ƒŒ—£¬¶Ã™š¤|„…}‡’™š¤…‹’…„’”“›|„…Œ”•{{ƒ‹…’mtt{||„„Š‹‹‹¸Á¹lld””‹Œ”•lri‹‹„kk]ƒ„„ƒ„„lldŒ‹“…‹‹‹„‹…‹’ddc|‚zlld‹„‹ƒ||„„Šddcldd{{ƒ{{ƒJHFUUYu{{lddJHFf]clddƒ||ttsllkŒ‹“lri‚v{ddclldj]\dc\Š}ƒ„„Šƒ}ƒlriƒƒ|¦§¨JHFJHFuztlld{ttztlšŒllkjV[|‚z|‚zkd\“Œ””š”Œ”•uzttsl””‹‘…„„„Š„Š}|‚z“““ztlŠƒ}tsltts{tt„Š„¦§¨‹„„œ¤¦”››{||“Œ”Œ‹“ult|‚zlek£››µ¶·ª³·›¢›…‹’¦§¨Œ”•‹‹‹£œ¥œ¤¦‹‹‹”››uzt]bZMRKlld]bZ|„…tt{‹„‹…‹‹‹‹„™š¤{{tllk…‹‹‹’Šƒ||œ››u{{…‹‹„Š„ƒƒ|Œ‹“|‚zbVUtsl‹’Šlldfkk|„…‹„„tslsred\\fkklddŠ}|{{tƒ}Ц§¨{||…„’‹’Štts]bZ{u{¦§¨†~‘¤¤ƒƒ|ƒ||{u{tts{||f]c‚|u“Œ”|„…ttsœ¤¦””‹ŒŒšŠ~‹ldduztu{{…‹‹…‹’ƒ„„|„……‹‹Œ—£Œ”•}‡’|„…|„…mtt|„…ƒ„„‰Š¡Œ”•‹…’œ››™š¤{{ƒ|„…Œ”•™š¤|„…£œ¥‹…’“Œ”ttstt{²¬µ””‹¨©´“Œ”…‹‹™š¤uzt{ttƒ„„‚ut¦§¨Š~‹“Œ”ƒ}ƒ‘Œ…Š~‹f]cmw’…‹ƒ}ƒš”””“›‹„‹ª³·‹„‹llklek“““œ››tts{{ƒlrilri’ŒŒŒ‹“…‹‹…‹’™š¤edkultJHFlks{{ƒ…‹š{{ƒlksedk|‚z’ˆ|‚zŒ—£Œ”•lks””‹|‚zuzt‹‹‹„Š„¦§¨¦§¨‹„‹Œ‹“›¢›Š}|””‹Šƒ}ƒƒ|ƒ‚u””‹VTL””‹‰|vŠŠ}slerr]tzl|‚zƒƒ|[TTƒƒ|lriŠŠ}‹’Šƒƒ|tslUTS”“›d\\|„…ekd‹…’uztyl„[[TŠƒ}“““‹„‹Š~‹””‹VZT””‹lek‚v‚lldultztlf]c{ttF=Ckk]rg]²««UTS*)(slej]\…‹‹Š}|‚|ulddŠŠ}ŠŠ}‹’Š›”›”“›””‹“““ttsrg]sle‚|utt{VTLsleztlŠ}ƒ„„Š‹„„zll›”›”š”””‹¤¤ƒƒ|œ¤¦“Œ”¦§¨Š}ƒ‹„‹u{{{{ƒ“Œ”¤¤’…‹Œ”•ttsŒ‹“‹’Ц§¨“Œ”¦§¨£œ¥™š¤|‚z‹‹‹lriUTSJHF[TT{{ƒ{{ƒƒ„„œ››ŠŠ}œ¤¦ƒƒ|uzt{{t{||fkkŒ”•œ¤¦tslmttsre{ttu{{Šƒ}b[Uƒ„„…‹‹ƒ}ƒ{||””‹tzlkd\74,{u{ztlŠƒ}ztl™š¤ƒƒ|ƒƒ|uztmtt{u{™š¤‹…’f]clriŒ”•‹„„d\\„„ŠŒ‹“ƒ„„lddttsultult›²Œ‹“ƒ}Š“““ƒ„„[TTlks{{ƒŒ”•‹‹‹…„’|‚z|„…fkk‹’Š|„…‹’Š|„…¦§¨““““Œ”{{ƒ“Œ”‹‹‹‹…’”“›ttsu{{›¢›””‹]cdtts{u{ƒ||\[[ƒ}ƒ”“›“Œ”ƒƒ|kd\{zm‹‹‹Œ‹“ttsšŒŒ”•ekdttsf]ctlldc\tzlJHF{||lkstll’…‹¦§¨’…‹£œ¥‹…’”“›{{ƒ”“›¦§¨lkszlld\\dc\‚v{red‰v|{u{f]cedku{{ª³·””‹ƒ„„“~ˆllkekduzt›¢›|‚z‹’Š›¢›‹’ŠŒ”•ttsmtt‹’Š‹‹‹ƒ}Š£››“““›¢›{||tll„Š„kk]{||tll›¢›‹‹„llklri|‚zVTLek]„Š„””‹dc\‹’Š|‚z””‹ƒƒ|dc\{{t{||lksmttultœ¤¦mtt{{ƒƒ}ƒ{{ƒ…„’Œ”•‹‹„””‹™š¤ƒƒ|[TTsresle{||lld]bZrr]JHFttsJHF{zm‚|u””‹JHF:97tsllrilldƒƒ|Šƒ}‹„„ƒƒ|‘Œ…‹’Š””‹Œ‹“‹’Šƒ„„‹’ŠŠƒ}Šƒ}‘Œ…’ŒŒƒ‚uƒ‚ukd\Œ”•‚v{™š¤œ¤¦Œ‹“””‹››”ƒƒ|”“›¦§¨“Œ”Œ”•tt{ƒ}ƒ{u{”“›Œ‹“›”›u{{“Œ”lksƒ||lriš””œ¤¦’ŒŒƒ„„|„…|„…{||llkmttf]c{{ƒ{||“Œ”‹‹„{{t|‚zœ››ƒ„„Œ”•”š”uzt„Š„lek„„Šdc\tt{Œ‹“kk]lekƒ||d\\|‚z|‚z{||ƒ||ƒ||‹‹„kd\VTL{||tll£œ¥sre¨©´¦§¨|„…„Š„ƒ||”š”’…‹UMR†~‘’ŒŒœ››ƒ}ƒ‹„„{ttš””œ››‹’Šƒ||kk]ƒ}ƒ{{ƒ›”›¦§¨‹„‹‹’Š{u{Œ”•{{ƒ|„…{tt‹’Š|‚zƒƒ|„„Š“““Œ‹“„Š„{||{||{{ƒ…‹‹™š¤ƒ„„{||„Š„…‹‹„„Šœ¤¦„Š}ttsuztUTSUTSSKJSKJƒƒ|‹„‹“Œ”…‹’Œ‹“Š}ƒ‚ut£œ¥ultš””sle„Š„lksddcd\\lekƒ||uztddctslƒ}ƒ¦§¨{u{…‹‹\[bƒ}ƒ””‹„„Š„„Š{{ƒf]c]cdJHFultllkŒ”•‹‹‹tslƒ||””‹lddD;9lldbVUuztekd|‚z{ttek]|‚z›¢›Œ”•‹’Š‹‹„|‚z|‚z””‹‹’Š›¢›‹’Š“““‹’Šœ¤¦Œ”•|‚z|‚z‹‹„ƒ„„ƒƒ|‘Œ…ƒƒ|yle‘…„ekd’ŒŒ‘ˆ}ƒ||ƒ||[[TbVU‹’Š‹„„ƒ„„‹‹‹”“›{||‹’Šœ››Œ‹“ƒ||{{t‹…’|„…™š¤dc\…‹‹\[[mtt›”›lld[[TSKJVTLƒ„„„Š}tts‹„„|„…\[b{{tj]\””‹JHF*)({tt|‚z‹‹„‚|uŠŠ}Šƒ}‚|u{zmdc\‹‹„leklld|„…‘…„{{t››”slellk””‹””‹ƒ||‹‹„’ŒŒuzt{||Š}ƒz‚lƒ||ƒ||llkš””{u{|‚z†~‘“Œ””š”{{ƒ‚v{¦§¨Œ‹“mttlekŒ”•ƒ‚u™š¤Œ”•¦§¨œ››‹‹„llk{{ƒldd|„…{{ƒekdœ§²{ttƒ„„”“›|‚z…‹‹ƒ„„‹’Šƒƒ|tts“Œ”ldd{u{|‚z‹…’‚|u|‚z›”›tllztldc\‹’Šœ¤¦‹„„””‹››”b[U[[TddcVZTtlldc\ekdldduztlriƒ||{ttlek‹„„ƒ}ƒ„Š„u{{ekd’ŒŒ{||™š¤¤¤ƒ}ƒzll{{ƒ‹„‹ult¦§¨¦§¨£œ¥’ŒŒ‹‹„›”›mtt{{ƒ¦§¨{{ƒƒ„„{{ƒŒ‹“‹‹‹”››™š¤mttek]lriƒƒ|ƒ„„|‚zœ¤¦…„’|‚z‹‹‹”š”{{t„Š„‹‹„lldultttsUUYŒ‹“dc\“““›”›„„Š‹„„£››‰v|£››··Ä’ŒŒŠ}|‚v{s_qred”“›ƒ}ƒVTL‹„„]cd’ŒŒ¦§¨›¢›tzl‹‹„tzlmtt‹’Š{||‹‹‹f]c[[T|„…lksedk‹„‹\[[ƒ}ƒ‹„‹tt{‚|u{{ƒƒ}ƒb[U{{ƒd\\tt{|„…™š¤mtt{{ƒ”››{{ƒ…‹’™š¤¦§¨£²‹‹‹ŒŒš‹’Š“““Š}ƒšŒ‹„„ƒƒ|œ¤¦”››ƒ||‹‹‹redslej]\ultbVU£œ¥r]Z‹„„cbVkd\sle‹„„lddkd\{tt“Œ”tll‹…’\UZ„Š„VZ[dc\edkŒ”•uzt[[TŒ‹“[TT\UZƒ„„lld[[Tzll‹…’””‹kd\š””‹„„›”›ŒŒšVTLj]\œ¤¦>EC:97ultŒ”•|‚z{{t“““zll ztl”š”‘Œ…VTLƒƒ|„Š}Š}|šŒ£››‹‹„„Š„š””Š}|red”“›{tt”“›{tttll”𔓓“tts‹uŠult™š¤‹…’…„’“Œ”ƒƒ|™š¤¦§¨ƒƒ|ultdc\{u{“““¦§¨’ŒŒŠ}ƒ„Š„‚v‚…‹’edk„„Š{{ƒ{|||„…LKRtslmtt‹‹‹u{{‹‹„ttsd\\ttsuztldduztj]\ƒƒ|tt{llklddkk]tt{‚|uldd|„…›¢›™š¤{zm„Š„™š¤„Š„„„Š|‚zlrid\\‹„„ƒ||ekdlekœ¤¦|‚z|‚z{u{{zm[TT|‚zttsUTS‚|u{{t‹’Š’ŒŒ›”›ƒ||Œ”•œ¤¦™š¤˜Ž£{{ƒ“““{tt“Œ”fkklks{{ƒŒ”•‹…’ŒŒšª³·‹‹‹…‹‹Œ”•Œ‹“|„…”››]cd…‹’tt{fkktt{|„…|„…”››mttulttts”“›™š¤…‹’‹„‹“Œ”“Œ”£œ¥f]c|‚z¦§¨|‚z”››{u{“Œ”‹…’{u{‹’Šult’ŒŒ’…‹“Œ”kd\SKJkd\tllŒ‹“Œ”•’ŒŒ…‹’ƒ}Š{{t{{t„Š}‚uttslSKJJHFb[Uƒƒ|tsl‰ƒvlddƒƒ|]bZ”“›dc\mtt|„…ttsVZTult…‹’|„…{{ƒ‹…’ŒŒšƒ}ƒ{u{‹„‹ƒ}ƒ’ŒŒ··Ä‹…’£œ¥ƒ||bVU“““››”Š~‹ult|‚zŠŠ}dc\ldd|‚ztslUTSSKJ””‹‹‹„lld[TTslej]\\[[MRKŒ”•[[T{{tƒ„„„Š„lksllk{||œ››{||Œ”•mttlrimttddc[TTj]\„Š„Šƒ}kk]lddtsl‹‹„‹‹„£››u{{{u{\[bVZ[ƒ}ƒƒƒ|JHF*)(tll|‚z‚|u””‹‹’Šyle‚utkd\sleƒ||j]\{{t“““‰ƒv¤¤›¢›””‹ddcŠƒ}kk]ztl’…‹’ŒŒ‹„‹ƒ||ƒ}ƒtts‹’ŠŠ}|ƒ„„{tt…‹‹„„Štt{Œ‹“£œ¥™š¤”“›|‚z”š”””‹„„Štts{tttslƒ„„{{t{u{tsllriŒŒš‹uŠVTL\[b[[Tedk‚|u¦§¨ƒ„„|‚zlektt{{{ƒlddttsƒ||leklddlldtllŠƒ}‘Œ……‹‹››”tllƒ||„Š„tsl\[[{||ult{{tMSS|‚z|‚zu{{ƒƒ|„„ЄЄlddu{{|„…”“›{ttƒƒ|sleSKJfkkVTL{ttztltzl‚|uŠƒ}“Œ”{{t„„Š{{ƒ‹‹‹{zmtll‚v{“Œ”ult›”›{{ƒƒ„„”“›ƒ„„¦§¨”››|‚znv‚ultmtt„Š„…‹’£œ¥œ››“““œ¤¦“““”“›ult‹‹‹|‚z…‹‹ª³·²¬µ£œ¥”“›œ››™š¤œ››¦§¨¦§¨¦§¨‘Œ…ttstt{Œ”•ƒƒ|{{tkd\›”›„„Š”“›dc\”“›{{ƒ‹‹„kd\ultŠƒ}‹„„‹’Š{tt’ŒŒŠƒ}šŒ‘…„“Œ”‹‹„kd\iq]|‚zUTSƒƒ|””‹{tt‹’Šllk‹‹‹[TTedklksu{{„„Š]bZVZ[lri]cdlek‹„‹|„…lekllk„„Šllkkk]‹‹„‹‹‹{ttœ¤¦{{tllkƒ||ƒ‚u””‹››”‹‹„‚|ulksllkb[Udc\VTLjcVcbV]bZlddVTLƒ}ƒ”“›dc\\[[uzt{{tlksttslddmtt|‚z™š¤]cd“““‹„„‹‹„lld{u{‹’Š[[TVTL{{tlrillk{{tƒ‚uddc[[TedkmttUMR‹‹„>EC74,ƒ|||‚z„Š„‘Œ…tsl‚|utllkd\{zmldd|‚z]bZ‹‹„‚|uŠƒ}Šƒ}¤¤œ››tt{{zmœ¤¦ƒƒ|ztl{u{lks‹„„”››|‚zŠ}|“Œ”ƒ}ƒ£œ¥‹’Šu{{”“›’…‹ƒ||‹„‹œ››Œ”•Œ”•{ttf]c[[Tsre{|||‚ztsl‹‹„ldd„„Š“Œ”]cdtt{””‹{{ƒlks|„…™š¤œ››lksfkkƒ||ƒ„„tllSKJlddSKJ[[TlekŠƒ}‹‹„ƒ„„‹‹‹ult‹‹„ekdlld\[[ƒƒ|‹„„‚|uMSS\[b\[[lld„Š„Œ”•Œ”•d\\edk„Š„”š”š””f]cœ››kd\|‚z„Š„ultƒ|||‚z¤¤ult‹‹‹ƒ„„’ŒŒ“Œ”ultŠ}|ƒ„„edkf]c{{ƒœ¤¦…‹’›”›„„Šlksƒ„„|„…{{ƒmttmtt|„…{u{…‹‹›¢›œ¤¦Œ‹“|„…tsl{{ƒ{{ƒŒ‹“¨©´™š¤Œ‹“£œ¥¦§¨£œ¥¦§¨µ¶·»ÂǦ§¨Šƒ}sre‹’Š‚ut“Œ”sreŠŠ}”š”{{t{u{‹‹‹¦§¨Œ”•Œ‹“’ŒŒ‹„„{tt›”››”›¦§¨…‹‹|‚z¦§¨š””‰‰w‰ƒv{{tƒ‚ukd\‚|ulldtslŒ”•›¢›{{tœ¤¦…‹‹tt{lek…„’lks‹„‹“Œ”™š¤ultŒ‹“›¢›£œ¥‹…’ƒ}ƒu{{ulttts{ttŠ~‹ultllkƒ||ƒƒ|£œ¥llkœ¤¦Œ”•u{{™š¤ttsƒƒ|‹„„‘Œ…kd\‹„„ƒ||ult|‚zllk’…‹kd\ƒ‚usre„Š}VZTŒ”•ekd„Š„lksJHFUMRlri|„…]cd…„’›¢›‹„‹ƒ„„bVZ|‚zlldUTS‚|ulldƒƒ|ƒƒ|dc\sleVTLJHFJHFJHFztlJHF3+*{u{››”ƒ‚u]bZtsl‚|u{tt‚ut{{tjcVb[Ukd\ttssle£›››¢›ƒ||{u{’…‹{u{’ŒŒrfk‚ut“““fkkƒ}ƒƒ„„llkœ››ult‹„„{||Œ”•ƒ}ƒ›”››”›„„Š’…‹‹’Š|‚z„„Šf]c{u{‹‹‹‹’Š‹„‹zll\[[tt{”››…‹’lekdc\\[bf]cult{{tllk„Š„‹‹„llkƒ„„lddƒ}ƒ‹„‹‹„„ƒ‚u‹„‹f]c‚v{‚|u‹„„“““ultVTL›¢›“““uztttsslef]cƒ||ddc\[[|‚z„Š}œ››u{{Œ”•ldd…‹’…‹‹„Š„ƒ||Œ—£››”ª³·|„…tllrfktts™š¤””‹lek{||{||ƒ„„‹…’tzlƒ„„{{t¦§¨“““|„…{u{|„…Šƒ}lriedkllkƒ}Š{{ƒ¦§¨|„…|„…ƒ„„“““…‹‹Œ”•|‚z””‹‹’Š›¢›‹’Š|„……‹‹„Š„…‹‹”››”“›{{ƒ¦§¨”“›™š¤ƒ||š””bVU¦§¨ª³·redtll£œ¥‹’Š’ŒŒ‹„„ÃÄÆ¨©´¦§¨Œ”•‹„‹“““’ŒŒ‘Œ…‚|uš””dc\ŠŠ}‚|u””‹””‹‚v‚›¢›‰‘~]bZuztkd\lek‰‘~\UZ‹‹„Œ”•ª³·›”›””‹|„…bVZultf]cf]cƒ}Šƒ}ƒƒ}Š‹’Š™š¤fkk{{ƒ{{ƒmttUTStzl‹„‹Œ‹“Š}ƒ‹„‹›”›tllultult”𔣛›‹…’{{tultdc\Œ‹“u{{uztekd[[Tlridc\|‚z„Š„lrisleddctzldc\VZ[lriUTS\[[ddcVZT|„…‹„„fkkƒ}ƒbVU™š¤tt{ƒƒ|tsl‹„„lld{zmlriƒ‚ulldf]c{ttUTS|‚z›¢›JHF*)(lksuztuzt””‹”››zllƒ‚uƒ‚u{tt{tt£››uzt””‹šŒŠƒ}””‹’ŒŒ{u{ƒƒ|bVU‚|uŠƒ}tllƒ}ƒ{||ª³·‹„‹Œ”•¦§¨uzt‹‹„›¢›”“›œ¤¦{u{£œ¥lek‚v‚Œ‹“tts{||’}™‚v{{u{{||{{t{u{SKJlld{{t|„…{u{””‹„„Š…‹šult{u{lld{||{||{tt„Š„ƒ}ƒj]\Š}ƒs_qzllƒ}ƒ‹„„‹„‹tsl‚|ud\\zllcbVtslŒ”•mtt„Š„tsl\[[tll\UZ{zmuzt›¢›”š”u{{ª³·u{{|„…„„Š{{tƒ}ƒ“Œ”œ››š””¦§¨ttslekŠƒ}uzt{{tult‘ˆ}{tt{{ƒŠ~‹‹‹„‹’Š””‹ƒ„„š””ttstt{{{ƒuzt…‹‹”“›‹‹‹™š¤™š¤…„’tt{lddƒ„„™š¤|‚zu{{Œ”•ª³·‹‹„|‚z„Š„|„…”𔛢›tslƒ„„…‹‹tt{tt{ddcddcSKJ{tttll“Œ”™š¤”“›‚v{…‹‹ƒ}ƒ‹„„£œ¥¦§¨£œ¥“Œ”¨©´“Œ”¨©´¦§¨µ¶·ƒ||™š¤ztl“Œ”””‹mw‹‹„{||uztfkkMRKlrilrillk”››ddc…‹‹ŠŠ}{||edk{{ƒf]cleku{{”››u{{mtt{{ƒtslŒ”•ƒƒ|‹’Šmtt”››™š¤„„Š|‚z{||Œ”•™š¤”“›¦§¨œ››tslƒƒ|dc\Œ”•{u{edkƒƒ|JHF„Š„VTLVTLŒ”•iq]VTLu{{]bZ„Š„lekllkuzt\UZ‹„‹ttsJHF]bZ‚v‚JHF]cd]bZSKJ‹„„›”›‚utƒ}ƒŒ‹“ƒ‚ub[UlldcbVzll|„…Šƒ}|„…{{t|‚zmttmttšŒJHF*)(ldd”š”{zm‰ƒvƒ‚u{zmŠŠ}ƒƒ|{{t‚ut‰|vŒ‹“””‹¤¤‚ut‹‹‹‚v{{||tts‘Œ…‚|u’ŒŒ¦§¨™š¤{tttts““““Œ”{zm“Œ”“Œ”ƒ}ƒ‹’ŠŒ‹“{u{tll‘…„tt{ztl|„…{||ƒ}Š‚v‚{||llktlllldlddlri‹’Š˜Ž£Œ‹“ƒ}ƒ{{ƒf]cultƒ||ƒ}ƒŒ”•mtt’ŒŒ‹‹„f]cƒ||ultrfkulttll“Œ”Š~‹ŠŠ}{tt{||{ttddctzluzt‹’ŠŒ”•‹‹‹£››š””ttsuztƒƒ|‹’Šƒƒ|edkttsŒ”•›¢›{||Œ”•œ››ŒŒš²¬µ””‹¦§¨{{ƒ›”›{{tmtt””‹ƒ||’ŒŒ{tt”“›¦§¨¦§¨Šƒ}””‹Œ”•ƒƒ|ttsƒ}ƒd\\lekttstt{‹‹‹|„…„„Šƒ}Š›”›‹„„“Œ”ƒ}ƒ™š¤£œ¥‹„‹’ŒŒƒ„„”“›Œ”•tts{tt¤¤™š¤”››“““ekdŒ‹“Š}|b[Uzll„„Š{tt¦§¨œ››œ¤¦Œ”•ƒ}ƒlksult{u{“Œ”†~‘™š¤™š¤²¬µƒ}ƒ™š¤tll“““Œ‹“¨©´‚v{£œ¥’ŒŒ“Œ”‚v{tll£››‹’Š{{ƒ|‚z|‚z„Š„Œ”•‹‹„””‹‹‹„lld„„Š…„’f]cƒ}Š„„Š”“›{{ƒ…‹‹]cduzt™š¤ª³·›¢›œ¤¦”››¦§¨„Š„‹’Šƒ}ƒ£››{{ƒœ¤¦…‹’„Š„””‹‹’Š‘ˆ}“Œ”‚v{[[Tuzt{||{{tVTLcbVllk|„…tzl[[TuztUTSuzt\UZVZ[‹„‹Œ”•ekdtll\[[uztUMRlri[[Tttsƒ}ƒ’ŒŒ£œ¥|‚zƒ„„‘Œ…kk]ekd{zmƒ„„‹’Šƒƒ||‚ztzl[[Tedk‚v{:973+*|‚ztts‹‹„lld{zm‘ˆ}ƒ||ztl”š”„Š„lddœ¤¦””‹¤¤‚|utslƒ||‹„„Œ‹“‹‹„‹‹„¦§¨‹„‹”“›Œ”•’…‹™š¤››”‹‹„¦§¨£œ¥…‹’¦§¨™š¤“Œ”{tt”›››”›ŒŒšµ¶·™š¤··Ä…‹’‹‹‹{{t“““‹‹‹{u{ƒ||lrif]c{{ƒ\UZ\[b™š¤f]c{{ƒŒ‹“‹‹‹…‹‹™š¤…‹‹Š}ƒ“Œ”ƒ||[TTƒ}ƒ\UZ{u{sle’‘~””‹”“›“Œ”‚ut|‚zƒƒ|‹’Š‹’ŠlriuztSKJ{||ult“Œ”œ››‹„„lksMSS|„…„„ŠŒ”•{{ƒ”𔋋‹ƒ}ƒ‹‹„|‚zlks¦§¨’ŒŒ{||‹„‹ƒ||‹„‹„Š}‹„‹µ¶·œ›››”›ƒƒ|‹„„›”›uztƒ}Š{ttttsŒ”•‹„„„Š„„„ŠŒ‹“Œ‹“ƒ||ultƒ}ƒ„vŒ¦§¨ƒ„„uzt””‹’…‹ƒ„„ª³·tts…‹‹Œ‹““Œ”lddŒ”•lddtsl›¢›‹…’£››¦§¨™š¤µ¶·lksŒ‹“Š}ƒ“““ultlks™š¤ult‹‹‹™š¤„„ŠlddlddŠ~‹‹„‹ƒ||™š¤Š}ƒ…‹’Œ”•”››”“›ultœ¤¦tllŠƒ}“““””‹¤¤™š¤|‚zlridc\“““|‚zekd„Š„lri|„…tslŒ”•f]c™š¤ƒ||{{tŒ”•ƒ„„ƒ„„{{ƒ…‹‹uzt“Œ”„„е¶·¦§¨|‚zƒ„„ƒƒ|lldllduztkk]“““]bZ””‹{tt„„Šllk[[T|„…mttddc‹’Šƒ„„‹’ŠVTL{{ƒ”››ƒ}ƒŒ‹“f]cUTSlkslkslri{||Œ”•lksttsult››”ultlks‹„„£››””‹ŠŠ}ƒƒ|‹‹„{{tdc\]bZ|‚z[[T[[T¦§¨LKR*)({{ƒtll””‹œ››{zm|‚z‘Œ…{{t””‹””‹£››™…””‹‘}zŠ}|””‹{tttt{Œ‹“uzt“Œ”£››ƒ}ƒ“Œ”{||ƒ}ƒŒ‹“Š}|””‹“Œ”œ››Œ‹“ddcƒ„„“““”“›’ŒŒ…‹‹{u{Œ”•™š¤{{ƒ¨©´Œ”•{||ttslek‹„„u{{ttslek\UZlddVZ[£œ¥ƒ}ƒlkstt{{||tll’ŒŒttsrfkŠ}|‰v|lddrg]‚v{„„Š“““„„Š‘Œ…Œ”•‚utldd‹’Šlldekdtzlekd„Š„tlllldŠ~‹{{ƒŒ‹““““}‡’\[[f]cŒŒš|‚z{||’ŒŒllk‹‹„llkƒ„„”››‹‹‹{tt’ŒŒšŒ²««››”“““£œ¥‹…’‹‹„|„…š””lldƒ„„tts{u{‹„‹‹„„{{ƒ“Œ”{{ƒ™š¤…‹‹Œ”•ƒ„„ddc¨©´ttsult™š¤ult{{ƒ¦§¨””‹Œ”•|‚z‹‹„{{ƒ™š¤Š}ƒd\\„„Š{tt‚v{ƒ}Štt{tll”“›œ¤¦…‹‹“Œ”›”›™š¤“Œ”f]c‚ut{{ƒ“Œ”\UZ‹„‹rfk™š¤ultƒƒ|ƒ||“““‘Œ…uzt¦§¨llkŠ}ƒ‹„‹›”›‹„‹ƒ„„sle{u{”“›‹’Šœ››d\\]bZtslŒ”•lrillkmtt{ttmtt‹„‹d\\ƒ|||„…Œ”•”››™š¤…‹‹„„Š…„’“Œ”“Œ”¨©´‚v{…‹‹ultŒ‹“|„…‹’Štsltzl{||ƒƒ|lriuztlks“Œ”””‹ztlƒƒ|‘Œ…|‚z{{t{{t[TTlldekdƒ}ƒd\\{u{d\\[TTJHFVZTuzt{||ekdf]c{{ƒlekƒ||‹„‹…‹‹lrizllztl“““tzl|‚z{{t„Š„]bZ‹’Š]cdu{{²²¬:97*)(kk][TTƒ‚uƒƒ|uzt‘Œ…Šƒ}””‹²²¬””‹‘ˆ}Šƒ}””‹sleŠ}|””‹¦§¨›”›™š¤œ¤¦‘Œ…“Œ”“Œ”ultƒ„„¦§¨¦§¨ƒ„„Š}|››”²««™š¤‹‹‹ƒ„„“Œ”£œ¥œ››“““œ››””‹„„Š“Œ””››£››{||‹‹„‹’ŠŒ‹“edk|‚zŠƒ}{{ƒd\\]cd‹’Š|‚zŒ‹“ƒ}Š”››£››™š¤ƒ}ƒ›”›Š~‹ylemttkd\ddcf]c{u{sreŠ}ƒttskd\“Œ”‹’Šzlldc\llktslttsd\\|„…ultu{{tts‹’Šlrilksddc”“›lksddcƒ||lksŠƒ}¦§¨Šƒ}|„…””‹|‚z{{ƒ…‹‹Œ‹“››”{tt‹‹‹Œ‹“‹„„rfk{zmtsl{{tŒ”•“““‹„‹””‹œ››‚v‚{{ƒ¨©´™š¤ƒ}ƒ‹„‹ttsƒƒ|ƒ„„…‹‹”“›‹„‹{{t¦§¨ƒƒ|™š¤ttsŒ”•Œ‹“„„Š£œ¥”𔦧¨ƒƒ|‹„„{{t“Œ”‘Œ…™š¤‰v|‹‹„‹‹„¦§¨Š}ƒƒ}ŠŒ‹“’}™„„Š„„Š”“›ƒ}ƒ‹…š\[b£²ƒ}ƒddc”š”{{ttllf]cƒ‚ulritsl›”›Š}|{zmƒ||ƒ}ƒ„Š}]cd„„Šu{{u{{[TT{{ƒmtt‚v{”“›|„…ztl…‹‹{{ƒtll{u{¦§¨œ¤¦…‹’…‹‹{{ƒ|‚z‹‹‹™š¤…‹’”“›”“›Œ‹“š””|‚z‹’Š|‚z””‹lrikk]|‚z”š”Šƒ}tzl¤¤“““tllƒ„„llk“Œ”“Œ”{ttŒ‹“ƒƒ|\[[kk]ƒ||tllVZT‹‹‹|„…u{{tt{|‚z‹„‹]bZƒ}ƒ[TTtt{lri{||ultlld|‚zllkekd[TT{||mtttzltll{||²««F=C7-2‚ut‹‹‹„Š„ztlƒ||‹„‹{zmsrekd\{{t¤¤sle›¢›ult””‹‹‹„‘…„‹„‹ƒ„„z‚l’ŒŒ‚utš””{u{‹„‹Šƒ}ƒ}ƒmtt£››Šƒ}™š¤{u{‹’ŠŒ‹“‹…’Œ”•“Œ”“Œ”™š¤uztŒ‹“›”›…‹’‹’Š’ŒŒ|„…„Š„lksmttŒŒš{ttu{{{{tuztŒ”•dc\tt{ult{||ƒ„„›¢›…„’ƒ||tll‹„„[TT{{tddc‚ut{||„Š„\[[Œ‹“{||Œ‹“‹‹„ekdlldƒƒ|{{t{||tts\[blksƒƒ|™š¤‹‹„lrilks}‡’Œ”•™š¤‹‹„›”›llklddllk„„Šllkf]c\[[“Œ”””‹›”›‘Œ…œ››tts‹„‹Œ‹“‚|u’ŒŒƒ„„lldu{{£››™š¤œ¤¦…‹‹”“››”›edk‹…’“Œ”™š¤Š}ƒƒ„„„„Š‹…š‹…’””‹Š}ƒ‘Œ…‚ut‹„‹‘ˆ}‚|u‹’Š{||Š}|tts‹’Šsreƒ„„Šƒ}Š}ƒ£œ¥£››Œ‹“‹’Š„Š}™š¤›”›“Œ”‹u…œ››“Œ”Š}ƒ{{ƒ“Œ”“Œ”‹‹‹„„Šf]c{u{‹„„zllldd‹’Š£››ztl{ttttslksedkFD;kd\””‹z‚l[TTŒ”•“Œ”™š¤}‡’UMR\UZ…‹’|„…„„Šlks…‹šedk…‹‹UTS…„’Œ‹“™š¤u{{u{{™š¤|‚zyl„¦§¨{{tŠƒ}‹‹‹{{tllkd\\ƒ||{{ƒ|„…ult{||]bZ{{t”››””‹lddVTL¦§¨„Š„{||”“›ƒ||“““{{t|„…mttf]cuztultlks‹„‹llktt{{u{edkrfktllƒ}ƒlri{{ƒ{tt‚|u„Š}ztl[[TztlŠ~‹|„…{{tlldlld²««JHF*)(tsld\\|‚z’ŒŒƒ„„ztl‚wl[[TŠŠ}‚v{’ŒŒu{{‘Œ…’ŒŒƒ}ƒ‹‹„‘…„{ttƒ}ƒ„Š„‹’Š“~ˆzll‹‹‹£››„Š}‰‘~„„Š‹‹„„Š„“Œ”™š¤ttstts{u{‹‹‹|‚z¦§¨Œ”•‹’Š™š¤{||™š¤ƒ||tll‹’Šlritt{\[b|„…ƒ}Šœ¤¦ekdldd|„…ƒƒ|‹„„ŒŒšllk{{t|‚z|‚ztslƒ}ƒ‹„‹{{ƒult…‹‹{{tcbV{ttŠ}ƒ“Œ”ƒ||cbV‚|u{||”𔛢›‹’Š„„ŠVTL\UZŒ‹“Œ”•Œ”•ƒƒ|œ¤¦{{ƒŒ‹“ƒ„„”𔋒Г““|„…ƒ||‚|uyle|„…{tt„Š„ƒƒ|ƒ„„ƒ„„‘…„”“›tllŒ‹“llktts|‚ztts‹‹„„„Š”“›ƒ||Š~‹Œ”•„Š„|„…f]c{{ƒŒ‹““Œ”Š~‹ƒƒ|¨©´lld{u{{{ƒ›”›“Œ”lri{{ƒ’…‹Œ”•‘…„£œ¥‹„‹{{ƒŒ”•›”›™š¤‹‹‹ztl‹„„¦§¨‹‹„ƒ„„””‹“““Šƒ}‹„‹tlltsl‹‹‹ƒ}Šf]c{u{tts{||‹‹„Œ‹“[[T¢“d\\zllj]\‹„‹‚v‚“Œ”‘Œ…››”SKJ‚v{sre\[[œ››””‹Šƒ}|„……‹‹{{ƒmtt„„Šf]cŠ}ƒttsƒ}ƒtzlVZTƒ}Š\[[ultdc\lri|„…{{tu{{œ¤¦œ¤¦””‹…‹‹‹‹‹‹„„””‹ƒ„„ultƒ}ƒddc”“›Š}|VZTVTLuztmttJHF|‚z|‚z”››lld›¢›„Š}›¢›‹‹‹lld‹‹‹ƒ}ƒtts|„…ultf]cddc[TTtslf]c”“›‹„‹{{trfkŒ‹“>EC{{tVTLlldllk{ttfkktsl|‚z”š”]bZ›¢›£››:97:97Š}ƒƒ||››”tll‚|u¦§¨{{t|„…ztl{{t¦§¨‚|uŠƒ}“Œ”ƒ‚uŠƒ}¦§¨|„…ult””‹dc\sle“Œ”‹„‹‹…’“Œ”‘…„rfkƒƒ|‚v{“Œ”ƒ„„¦§¨{{t‹„‹‹‹‹“““¨©´ƒ„„|„…{||‚v‚tt{¦§¨{{t]cd…‹’tt{uzt…„’{ttœ¤¦ddclri]bZrfk“Œ”|„…{{tŒ‹“|„…u{{ultlriredu{{ƒƒ|r]g{{tƒ}ƒlddƒ||‹„„lddredred›¢›¦§¨œ¤¦„Š„›¢›mttUMRu{{{tt{||srett{ƒ}ƒŒ”•{{ƒª³·””‹£œ¥›¢›ƒ||””‹rfk{||{||ttslri…‹‹‹‹„œ››”“›{||¦§¨‹‹‹ŠŠ}‹‹‹“““›¢›‹„„”“›Œ”•{tt…‹‹‹‹‹”“›Š~‹f]c‚v‚ƒƒ|œ¤¦\[[‚v‚…‹‹Œ”•tt{„„Š“Œ”llk“Œ”‚|u|‚zœ››„„Š‹‹„|„…–¢‹‹…’”››ƒ||lld”š”tt{ƒ„„‹‹„ztfŠƒ}¨©´’…‹”“›„Š„‹’Š{||dc\f]c‹„‹ƒ}ƒ””‹Š}|””‹Šƒ}kd\‹’ŠlekVZTlrisleredzlltllztlsreVTL{{t‹‹„£››‹…š‹„‹‹‹‹‚v‚{{ƒlks|‚z’ŒŒ„Š„uztsle…‹‹\[b]cdƒ}ƒŠ~‹ƒ„„uztmtt”››Œ”•Œ”•ttsmttddc{|||‚z{||sleJHFƒƒ|\[[‹’Š[TTdc\„Š„„Š}lri”“›|‚z\[[›¢›ƒ„„]cd‹’ЄЄrg]š””ekdtslƒ||ddcuzttt{ƒƒ|Œ‹“„„Šlld‰|vdc\u{{SKJdc\tslVTLlld[TTsreƒ||lriaWMSKJ|‚z£››D;9*)(ƒ„„“Œ”Šƒ}tslƒ‚u’ŒŒ››”‘Œ…’ŒŒ””‹“Œ”Šƒ}£››¦§¨£››{{t¦§¨ƒƒ|‹’Š“““lek‹’ŠaWMª³·‹„‹›”›…‹‹‚ut‹’Š£››Œ”•|„…””‹ŠŠ}£››Œ‹“œ››²¬µµ¶·Œ”•›”›ƒ}ƒŒ”•ƒƒ|[[T’ŒŒ[[T]bZmttd\\ƒ„„{zm’…‹„Š„tsl„„ŠŒ‹“{{t’ŒŒƒ||„Š„ƒ}ƒš””lriztlŠƒ}{ttldd„Š}{u{Œ‹“”“›‹„„‹„‹Š}ƒult…‹‹|„…„Š„|‚z‹‹„‹’Š|‚z””‹„Š„ekd””‹u{{f]cztlƒ„„…‹š”››¦§¨ttsƒ„„„Š}ztfddc‹„„{{tsre‹„‹„Š„ƒ||{tt{||„„ŠŒ”•”𔦧¨…‹‹›¢›””‹‹‹‹lksult™š¤Œ‹“ƒ„„tt{llk{{ƒsle{{ƒŒ‹“‹‹‹|„…¦§¨Œ‹“…‹‹{{t‹„‹ultŠ}ƒ‰ƒvœ¤¦„„Š’ŒŒ…‹‹llk„„ŠtllcbVŒ‹“’…‹|‚zƒƒ|ztltt{‹„„¦§¨{||mwsreƒ„„‹’Šsleult{tt…‹‹‹„„ŠŠ}ƒ„„ƒ‚uzll‚utylelritll£œ¥‹„‹””‹tlltzlkd\b[UddcŠƒ}lek™š¤›”›edk›”›‚utƒ||„Š„|„…u{{‹’Š|‚zllk{{ƒƒƒ|Œ”•tslŒ”•››”‹‹„™š¤u{{ƒ}ƒlldƒ}ƒUTS””‹|‚z[[Tultuzt¦§¨tt{mtt{{t{{tlld]bZbVUultultUMRŠ}ƒ{||‘Œ…‹’Šb[Uztlf]c{{ƒ…‹‹ultult””‹|„…{||{{ƒ{{ƒkd\„„Štt{fkkf]cd\\‹‹‹‚utzll{{tlrilridc\\[[ekduztš””:97*)(tzlsre‹‹„ƒ}ƒ{tttts””‹¤¤£››“““’ŒŒ‘…„“Œ”²««ƒƒ|‘Œ…ƒ„„{ttttsƒƒ||‚z«²«Œ”•{tt¨©´£œ¥¤¤…‹‹‘Œ…ƒ||¦§¨“““›”›¦§¨›”›™š¤‹‹‹¤¤œ››‹’ŠddclddŒ‹“|„…]bZ\[bƒ||tt{‹’Š‚v‚ƒ}ƒb[U‹‹„|‚z‹’ŠŒ‹“ƒƒ|‹‹‹‹„„{||u{{ldd›”›‹‹‹{u{ŠŠ}kd\zllkd\lek”“›‚v{kd\edkŠƒ}{{ƒ“““|„…£››tts„„ЄЄ[[T{{ƒ‹’Šmttdc\]cdSKJlek…‹‹lkskk]‹‹„{||“““tsllldllkslelld[[T{ttƒ}ƒ£œ¥‹„‹››”’ŒŒ|„…£œ¥””‹ddc|‚zlddƒ}ƒŒ”•‚v{¦§¨‹‹‹Œ‹“’ŒŒult“Œ”œ¤¦ŒŒš“Œ”uztttsŒ”•ldd…„’mwƒ„„{tt“Œ”“““‹‹‹“Œ”’ŒŒultŒ‹“”“›”“›‚v{ƒ„„{||™š¤”››ƒƒ|‹„‹tllš””Œ‹“œ››tsl{{tŒ”•””‹{||\UZ{{ƒ‹‹„µ¶·‹‹‹œ¤¦ƒƒ|{tt‹‹„”𔋄‹£œ¥’ŒŒ‘Œ…SKJttsjcVldd]bZƒƒ|‹„‹ƒ„„™š¤Š}|lekf]c‹„‹dc\“““„Š„‹’Šttsœ››„Š„“““¨©´„„Š{{ƒŠƒ}lri…‹‹{{ƒƒ}ƒyl„edkbVZj]\›”›[[T‚|uekdd\\{{ƒ{ttddcttsf]c[[Tek]sleult“““lksFD;zllztlƒ||‹„‹tt{UMRfkkultu{{‚|uJHFƒ„„red“Œ”ƒ}ƒŠƒ}{{ƒ{||\UZztl{||ƒƒ||‚z”š”]bZkk]dc\\[[UTS]bZ¦§¨:97*)({{t{ttlddred’ŒŒƒ}ƒ¤¤{zm„Š}²²¬š…Ž‹’Šztfztl¦§¨ƒƒ|“Œ”„Š„£œ¥µ¶·“““¦§¨¦§¨“Œ”…‹‹”𔦧¨£œ¥›¢›ƒ}ƒ¨©´’ŒŒ‹„„””‹{||””‹‹‹‹„Š„{ttƒ||{||››”ddc{{ƒ‹‹„ƒ||lek”“›Œ”•”“›tlld\\lld‹’Šœ¤¦ƒ}ƒ“Œ”‹„‹sredc\Œ”•“Œ”„Š„u{{{||sleSKJ‹„‹ƒƒ|tlltllzll‹„„r]g“Œ”mtt„„Š“““¤¤Œ”•{||ƒ„„tslƒ}Šœ¤¦|‚z{{tuztd\\ƒ||”››ddc‹’Š–¢‹ƒƒ|ztllritts‹‹‹ztlƒ„„|‚zƒƒ|ƒ||{u{‚ut’ŒŒ‹„„„Š„{{ƒ‹’Šlld‹„‹{{tƒ}ƒ““““Œ”Š}|lek“Œ””“›ultƒ}ƒ™š¤“Œ”tt{tts”š””››œ››{{ƒUTSlksttslriœ››‹‹‹“Œ”tts{u{ƒ||›¢›ƒ}ƒ‹„‹„„Š‚|uek]™š¤‚|u²««{||”“›tsl“““Œ”•{{t””‹ƒ||{||tts|‚z‘Œ…“““ƒ„„š””{{t£œ¥‹‹„”“›\UZ£››ddcztl‹’Šdc\VTLVTLek]tllŒ”•ª³·{ttyfltt{\[[ƒ}Š[TTtt{leku{{VTL]cduzt…‹‹„„Š„„Šu{{lksd\\|‚z››”f]c¦§¨lri{u{j]\edkttsllk]bZllkƒ„„{{ƒ\[[SKJek]tll‰|v””‹VZT“Œ”[TT{||dc\ldd[[T‚v‚lksf]cƒ}ƒttsf]cJHF]cd{{ƒlek“Œ”‹‹„tt{Œ”•fkkƒ}ƒ‚v{|‚zsle\[b‰‘~lrisre]bZ[[TFD;ƒ||“Œ”:97:97rfkkd\‹‹„{tt£œ¥””‹‹’Š›¢›{{t£››ƒƒ|””‹›¢›‹„„²¬µ‹’Š™š¤£œ¥š””‹‹„¤¤”“›²¬µ“““œ››™š¤””‹”š”››”|„…µ¶·‹’Ц§¨¦§¨œ¤¦›”›œ››ƒ„„š””‹‹‹‹„‹¦§¨|‚zultƒ}ƒ‹‹‹”𔤤¦§¨{{ƒlektts{{tllkŒ”•{u{‹‹‹‹‹„…‹‹¤¤™š¤‹‹‹{{ƒ”“›‹„‹{ttb[UbVZtslƒƒ|ult£››ztf”››‚v{œ››{u{llkztl„Š„ƒ„„UTS‹‹„{{ƒsre™š¤ƒƒ|mtt‹„„ƒ||”š”…‹‹mttŠƒ}‹„„‹„„ek]Šƒ}{{ƒ’ŒŒ\[[lrisle{u{ƒ}ƒrfkš””ƒ}ƒ‹’Š£œ¥‹‹„lri‹„‹ƒƒ||„…|„…™š¤””‹““““Œ”ƒ}Й𤋋‹“““tslultmtt…‹‹„Š„ƒ||…‹‹llk‚|uƒ}ƒ{u{‹„‹Š}ƒ”“›ttsllkŠƒ}¦§¨{||š””dc\{||ult|‚z{{ttslultš””ƒ||£›››¢›uzt‹‹„›¢›Œ”•„„Š£œ¥¬¶Ã“Œ”£œ¥›”›‹’⬵ƒƒ|{||{||‹‹„Œ‹“‘Œ…lld‹’ЉƒvŠƒ}‹‹‹ŠŠ}Œ”•ƒ„„ultbVUf]clddƒ}ƒedk[[Tlriult›”›”››™š¤‹„„ultlri”“›ek]{{tdkVmttƒ}Šztlult’ŒŒ„„Štt{llkUMRLKRƒ}ƒ“Œ”{tttts{{ƒ\[[ttsttsŠ}|kk]llk|„…ƒ||£œ¥uztlek™š¤Š}ƒ{{ƒf]cJHF‹‹‹{||VTLlriƒ}ƒ|„…Œ”•mttllk\[b{u{ultllkttssre{{trg]|‚zuztMRK\[[dc\¦§¨:97*)(dc\ztl’ŒŒ‹‹„„Š}””‹‹‹„ƒ||››”¤¤{u{ƒ‚uŠ}|’ŒŒ¨©´œ¤¦{||¦§¨”››‹’Š«²«µ¶·œ¤¦œ¤¦”“›“Œ”œ››„„Ц§¨„„Šƒ}ƒ™š¤“““”››‹‹‹‹’Š‹‹‹ƒ‚u‹’Ц§¨£œ¥²¬µ”››uzt‹‹‹²««{{tœ¤¦‹’ŠŒ”•{{ƒ{u{SKJ[TT|‚z“Œ”kd\‹‹„„Š„‹„„u{{‘Œ…UTSƒ||j]\{zmlddƒ}ƒrfk{{ƒtll’ŒŒ{tt‹„‹{tt“Œ””››™š¤£››{||„Š„JHFtsl‚v{{{tu{{”››„Š„uzt‹„„ttsŒ”•|‚z””‹lldd\\“““¤¤‹‹‹‚v{|‚z„Š}‚|ullkf]cultult‚|u”š”{tt|‚z{||Œ”•œ¤¦”››Œ”•”“›„vŒ|„…yl„“““Œ”•’ŒŒ””‹ult{u{|„…{u{{||ztl‹…’‹‹„ult[TT{tt’ŒŒ‹„‹{{ƒ‹„‹[TT‹‹‹‹„‹‹‹‹tlltsl{u{tlltslred‘ˆ}’ŒŒ›”››”›{||Œ‹“¦§¨”š”ttsœ¤¦¨©´…‹‹‹‹‹“““›”›“Œ”{tt‹„„|„…uzt{u{ƒ||¨©´››”‹’Š‹…’ƒƒ|‹‹‹|‚z“““‹‹‹“““ƒ„„“Œ”Œ‹“{tt{{ƒ[TT]bZb[UlriŒ‹“uztdc\{tt{{tredult|‚z{||{{t{zm{{t{{t“““‹’ŠVTLŒ”•‹…š\UZtts‹„‹d\\ƒ„„œ››ƒ}ƒddcƒ||\UZek]SKJ{{ttt{UMRŒ‹“{{t‹„‹‹„‹„„Šd\\VZTUMRlri{ttddc…‹‹ƒ||„Š}‹…’d\\tsltts[TT|„…„Š„Š}|u{{z‚llriŠƒ}ddcUTS[TTlektslFD;,55‹‹‹››”Šƒ}yleŠƒ}‹‹„’ŒŒ‚ut””‹ƒ||‹‹„Š}ƒ{{ƒƒƒ|ƒ}ƒ‹‹„„„Š…‹‹›¢›¤¤¤¤‹’ŠŠ~‹¤¤‹…’‘Œ…˜Ž£ƒƒ|‹„‹sre›”›|‚zœ››ƒ„„‚|ulri|„…‹‹„“Œ”tll‹„‹™š¤…‹’u{{|‚z‹„‹‹‹‹…‹’ŠŠ}ult‰|v{||dc\£œ¥fkkleklks’ŒŒ†~‘£››ƒƒ|œ››Œ”•{||””‹j]\tllŠ~‹{u{‚ut‚ut“Œ”tts{u{ƒ}ƒ„„Š{||”“›‹‹„uztuztllklld\UZ„Š„Œ”•VTL{{ƒ|‚z|„…›¢›œ¤¦lrikk]‹„„‹„„{{t™š¤ƒ}ƒtllrr]””‹{{ttt{lddf]c’…‹‚v{‹‹‹¦§¨lri™š¤‹‹‹”››¦§¨Œ”•Œ‹“Œ‹“¦§¨£²ƒƒ|”“›Š~‹”››{{ƒ…„’|„…]bZŠ}ƒŠ~‹“““fkkŠ}|llkb[U‘…„{u{£œ¥ƒ||d\\‹’Šƒ||’…‹tzldc\cbV{{ƒdc\””‹‘Œ…j]\ddc‹…’Š}ƒœ››Œ”•œ§²|‚z”“›u{{tslŠŠ}¦§¨‹„‹{||…‹‹™š¤‹’ŠleklekŠƒ}‹„„zll|‚z‹„‹‰ƒv²²¬…‹’sle…‹‹“Œ”ƒ}ƒ‚v{VZ[ultultbVZ‘…„ƒ}Šƒƒ|tll…‹‹SKJVZ[uztUUYUTS|„…‹‹„ddctslllkŒ‹“™š¤‹„‹‹’Ц§¨‹‹„{{ƒƒ}ŠŒ‹“{tt‹„‹lekŒ‹““Œ”u{{lri{{ƒ{{tztltll[TT™š¤{{ƒ{tt‚utƒ}ƒ‹„‹ddcUUYllkœ››lri‹„„tt{ztl‹„‹VTLƒƒ|{{tldd“Œ”tslmtt‹‹„ƒ„„lriztl‹’ŠtslUTSJHF’…‹:97*)(Œ‹“„Š}“““{||””‹Šut„Š}tll¦§¨{{t‹‹„››””š”””‹“““œ¤¦¦§¨ztlµ¶·‹‹„µ¶·””‹Œ‹“”š”ult“““’ŒŒuzt™š¤‹‹‹£œ¥ƒ„„{{t‹‹‹›¢›|„…‹‹‹{||‚|uƒƒ|ƒ}ƒ|‚zŒ”•lksƒ„„{tt‹‹‹…‹‹Œ‹“…‹’ƒƒ|tslœ¤¦{ttŒ”•›”›¦§¨“Œ”‹„„ƒƒ|ƒƒ|‹’Š‚v{””‹ddc‚utJHFƒ}ƒtts„„ŠŠƒ}bVU{u{{{t{u{‹„‹{{ƒ…„’slerfk{{ƒ|„…{{tult\[[]cd[[TmttlriVTLlri|„…œ››ztlƒ||lld””‹ƒƒ|{ttd\\{{ƒ””‹Šƒ}{{ƒtllŠ~‹’…‹“Œ”™š¤ƒ||›”›„Š}‹‹‹’ŒŒ£œ¥ƒ„„‹‹„™š¤ƒ}ƒ…‹’‹„„œ¤¦lri{tt{||ƒ„„llkzll|„…sle‹’Šllk{u{‹„„sletll‚|uƒ||Šƒ}lkstzl“Œ”ƒ||”“›„Š„ƒ‚uŒ‹“lld’ŒŒ””‹‰|v“~ˆ‹„‹™š¤™š¤“““ƒ„„{tt{u{\[[„Š}œ››“““{||uzt[[Trfk‹‹„d\\{u{š…ŽŒ‹“¦§¨œ››ƒ„„“““tsl|‚z‚|uƒ„„ult{u{UUY\[[ldd{{t{u{‚utult{{tƒ}ƒ…‹‹Œ”•ult‹’Šj]\lek„„Štt{ztllriddcŒ”•‹„„{ttb[ULKRVZ[lks…‹šf]cttslddult‹’Šƒ||{u{ult‚ut{{tbVU{||VZT\[[Œ‹“{{t’ŒŒtll¦§¨‹‹„VZ[mtt{ttmtt{{tf]cSKJ{u{ƒƒ|„„Š\UZztldc\SKJ‚v{tsl{{tuztuzt|„…\[[VZTUTS¤¤:97*)(ƒ||kd\›¢›{{t››”¤¤‹‹‹›”›ztl‘Œ…¤¤™‹†ƒ||sretts£››‹‹‹¦§¨”š”’ŒŒtslœ¤¦ª³·µ¶·¦§¨™š¤‹‹‹”𔋄‹”“›”“›””‹¦§¨ª³·¦§¨¦§¨tt{Šƒ}|‚z”“›{u{£œ¥UTSztl|‚z{||…‹‹ƒ„„‹’Šttsƒ„„{||œ¤¦ekd‹„„“““™š¤bVZekdƒ‚u›”›‚|uVTL\UZ{||“Œ”f]cŒŒšult{u{‹‹„“Œ”Š}ƒ|„…lek‚v{{u{›”›leklksf]clldUMR{{ƒcbV…‹‹””‹‹„‹ddcSKJuztddc‚|u‹‹„“Œ”sleœ››{u{››”Š}ƒƒ„„„Š„kd\ult‹„‹Œ”•Š}ƒ”“››¢›™š¤“Œ”¦§¨¦§¨œ¤¦„„Š«²«£››™š¤‹„„ƒ„„“““ƒ}ƒ‹’Š‹„‹“Œ”£œ¥Œ”•{{t{{ƒ‹„‹¨©´{ttdc\‹‹„…„’zllztl‚utƒƒ||‚z››”‹„‹‚v{{tt„Š„tslŒ‹“ƒƒ|‘…„kd\ƒ}ƒ’ŒŒj]\Š~‹£››‹’Š‘Œ…œ››”“›…‹‹œ¤¦‹’Š”“›{{ƒ{tttts[TT”š”mttu{{kk]lekƒ‚u””‹ƒ„„–¢‹‘…„…‹‹{ttuztlekedklrimttd\\\[[ƒ||{{ƒult‚wl{u{Œ”•Œ”•‹’ŠUTSedkd\\ƒƒ|UUYtllf]ctts‹„‹ŠŠ}|‚zƒ||UTS\[[llkœ¤¦UMRrededk{{ƒ‹‹„ƒƒ|lek|„…sreƒ||‚utddclrimtttt{{u{ƒƒ|””‹lri\[b\[b[[Tlri{||lldf]c‹…’™š¤¨©´mtt›”›tll„Š„lekdc\ƒ‚u‹‹‹ƒ‚uttsmtt‚v{[[Tekd£œ¥:97*)(ztlƒ‚u›¢›tsl››”‹’Š‹‹‹”››„Š}£›››¢›””‹”“›ƒ||¸Á¹¨©´£››{tt£››ƒƒ|‹‹„„„Š“““™š¤““““Œ”Œ”•¨©´Œ‹“”“›ƒƒ|{{ƒ›¢›ŠŠ}tsl”››ƒ}ƒ‹‹‹‹„„“Œ”{tt|‚zUTS]cdlritllŒŒš‹„‹|„…lkslldtsl…„’mttŒ”•Œ‹“”“›Œ”•ƒƒ|‚|uult””‹‚wltslrfkƒ}ƒj]\\[[uztleksresre{||{u{‹‹‹£››’…‹“““ƒ||‹‹‹“Œ”{||d\\ƒ}ƒ{tttt{|‚z‚|ulks”“›”››“““››”Šƒ}››”²¬µ›¢››”›‚|u‹…’lld„Š„Šƒ}ª³·¨©´“Œ”š””‹„‹|‚z™š¤’…‹|„…Œ‹“ƒ„„tllu{{’…‹””‹ƒ||ƒƒ|¦§¨œ››u{{”“›”“›…‹‹„„Šƒƒ|sleƒ}ƒ£œ¥{u{‹‹„Šƒ}œ››ldd””‹Œ‹“›”›œ››››”™š¤…‹‹“““¦§¨‹‹„£œ¥›¢›‚v{‚|u“Œ”‹„„‹„‹mwtll{{tŠƒ}Šƒ}ttsfkklri{{t’ŒŒ“Œ”{||‹’Š‹’Š|‚z‹„„ƒ„„tts{u{b[U{||i\V‰ƒv¤¤llkŠƒ}‹‹‹tt{‹‹‹lriSKJb[U]bZ{u{llk{tt‹„‹dc\uztfkk„Š„ddc{u{ƒ||””‹Šƒ}tzl{zmtsl{ttztllldllktt{„„Šƒ||lri{u{slef]c|„…{{t›”›MRK…„’sretzlsretslUUYUTSŠ~‹ttsldd¦§¨{||{u{\[b[TTf]ctslcbVtlltt{ƒ„„b[UUUY{{ƒkd\ultJHFleklld{ttfkkƒ}ƒUTSJHFVTL|‚zŠƒ}JHF*)(„Š}‹‹„‹’Š‚ut„Š„›”›|‚z“““¦§¨‘…„¤¤ƒ||‘ˆ}‹‹‹£››”“›””‹‹’Š››”{ttµ¶·£››Š}ƒ{||‚v{œ¤¦”“›¨©´Œ”•‹‹‹ƒ||›¢›uzt|‚zttsŒ”•|„…lri‚|u”𔋋‹edk]cd]cdf]ctsl{u{|‚z{{ƒtt{ult‹’Šœ¤¦‹’Š‹’ŠŒ‹“‹„„‹„„”“›››”’ŒŒƒƒ|„Š„bVUlriŒ‹“f]cJHFbVZlekƒƒ|ult‚v‚sleƒ„„zll‹„„“““‹„„tt{ƒ}Šfkk„Š„j]\ƒ}ƒ‹„‹{ttultŒ”•‹‹„{zm{||ƒƒ|‹„„ƒƒ|¦§¨ƒ„„Š}|’…‹Š~‹ƒ‚n|‚z””‹™š¤‹„„…‹‹tll’ŒŒ””‹{u{‹„„…‹‹“Œ”‹‹„Œ‹“{{t|‚zœ››Œ‹“ddctll„Š„¨©´“Œ”Œ”•œ››’…‹”š”ztl{{ƒ|‚z’ŒŒ‹’Š‹‹„ƒƒ|Š}ƒ‹…’Œ”•Š}ƒŒ‹“Šƒ}¤¤’…‹’ŒŒ‹„‹Šƒ}{||‹„‹ƒƒ|ƒ||ƒƒ|ƒ||Š~‹ult…‹‹‹‹‹zll‹‹‹„Š„{||llkkd\lek£››Š}ƒsle‹„‹ƒ„„{tt”𔋒Ћ„„‚|ullkllkzll””‹Š~‹[[Ttlltt{[TT\[[ddcSKJ‚utredu{{tt{‹„„|‚z‹’Š|‚zlridc\tt{‹‹‹„Š„Œ”•””‹lrif]c{u{{||{u{Œ‹“lkslektllylezlltsl„„ŠmttsleultJHF{{ƒek]lld…‹‹zlllldekdztl‹’Š‹‹‹‹‹„|‚zŒ”•]cd|„…ekd’ŒŒœ¤¦UTSultJHFVTLkd\Œ‹“‚v{sleƒƒ|tt{tll{{tttsƒ}ƒlek{{tlks]bZ¤¤F=C*)(lld|‚z‹’Š‹‹„£››“Œ”£œ¥š””µ¶·š””””‹’ŒŒ¦§¨‘…„¦§¨|„…tsl””‹””‹’ŒŒ‰ƒv£››tllŒ‹“Š~‹rfk„„Š’ŒŒ{{ƒtts{||”“›ttstllƒ||ƒ„„”š”Œ‹“‹‹„sre‹„‹mttu{{fkk|„…uzt{ttuztmttƒ}ƒ{||‹„‹|„…|‚z‹’ŠŒ‹“{||uztƒ||‘…„š””tts“Œ”ƒ}ƒtt{f]cJHFfkk{||ddc{ttš””ƒ}ƒult‹„‹¨©´‘Œ…ult“Œ”|‚zddcsleƒ„„„„Šƒ„„…‹’Š}ƒ„„ŠlrillkŒ”•”››ƒƒ|£››’…‹£››‹’Š›”›sleƒ||tllƒƒ|‹’Š“Œ”{{ƒƒ||‹„‹šŒlrilks“““¦§¨“Œ”‚|u{||…‹’ƒ„„ƒ||{u{tll‹„‹|‚ztt{”𔍩´ƒ„„Œ‹“¦§¨š””Œ”•“Œ”œ››‚v‚””‹[[T‚|u𔔙𤋋‹™š¤›¢›’ŒŒ|„…ztl‚|u‚wl‹„‹‹’ŠzllsleuztŠut{u{yfdllklld‹‹‹¦§¨{||‹…’{u{cbVƒ}ƒƒ„„”››¤¤ƒ||Œ”•‹’Š‹‹‹””‹‹‹‹’ŒŒttszllb[U‹’ŠŠƒ}’ŒŒtts“Œ”rg]ult“Œ”UMRrfk[TT{||ttslldllkJHFedk{zm]bZredƒ||„Š„cbVlkslksŠ}|ultrfk…‹’ulttts|„…ultƒ„„¦§¨››”ŒŒš[TTztlVTL{{ƒƒƒ|ult[[T‹‹„{zmfkklrilekJHFdc\tsl‰‘~Œ”•lddlldlriƒƒ|{{t‹‹‹“Œ”ztlSKJƒ||mttiWUd\\lritzl„Š}ldd{||ƒ„„“Œ”tzl‹’Šfkk²««LKR*)(u{{”›››¢›£››ƒ||‹„„“Œ””“›²²¬¦§¨²««‹„„‘…„ƒƒ|‹‹„””‹›¢›””‹£››¤¤¦§¨“Œ”‚v{£››£œ¥‹„‹Œ‹“”››‹’Š‹„‹™š¤¦§¨””‹|‚z{|||‚z…‹‹ƒ}ƒ{||²««‹‹‹¨©´™š¤…‹‹››”‹‹„{||‹’Šlks„„ŠlddlrilriŒ”•„Š„{{ƒ‹„„ƒƒ|‚|uƒ||ztlŒ‹““““{||„„Š„„Š‚|uJHFƒƒ|rfk{tt“Œ”{{ƒkd\‹„‹lek’…‹š””lks”››f]cmtt‹‹‹bVUƒ„„ult[TTtts]bZdc\tsl”“›››”‹„„‚v{ztlttsekdƒ||‹„„”š”ƒ‚u‹‹„‹„‹ddc\UZsle‹„„‹‹„”š”{ttu{{‹’Štts„„Š…‹‹‘Œ…š””|‚z{tt²««|‚z{u{ƒ„„™š¤™š¤ttsœ››‹‹‹…‹‹ƒ||‹‹„™š¤‹„„\UZztl‚wlƒƒ|‹‹‹„„Ц§¨™š¤mw””‹ƒƒ|‚|urfkœ››‘Œ…š…Ž””‹Š}|“Œ”f]cult‹‹„slešŒƒ‚u{{ƒƒ„„””‹ƒ}Š{{ƒ£››¦§¨uzt\[[ƒ„„{||››”‹…’‚utƒ}ƒŠ}ƒzllztfVTL‹‹„”››lekddcŠ}ƒ‹„„lddultkd\mtt…„’š””ekd]bZƒ||SKJuzt\UZ„Š„ƒ„„dc\kk]{||zll‹‹‹‚v{Œ‹“‹…’£œ¥|„…tts{{t{{t““““Œ”UTSdc\tt{JHF]cdddcjcVlriyflu{{›¢›Œ‹“{{ƒ[[Tmtt|‚z™š¤lri“Œ”|‚zlks{{tmttVTLredcbV“Œ”lksdc\ttsƒ„„uzt‹’Šƒ||tsl{||ddcfkk]bZ‹’Š››”JHF*)(|„…‹’Š|‚z‚|u””‹Š}|‹‹‹“““š””²²¬›¢›Œ”•Š~‹Š}ƒ“““””‹››”“Œ”š””sre›”›²««›”›“Œ”¨©´£œ¥›”›£››¨©´¦§¨Œ‹“Œ”•„Š}„„Š„„Š…‹’|‚z|„…tslƒ„„ƒ||tt{™š¤œ¤¦¨©´‹’Š|„…u{{mttlekulttsl„Š„tts{||Œ‹“Œ‹“lldslelldultŒ‹“™š¤f]c‹’Šƒ}ƒfkktt{…‹‹f]c‹„‹{{tlritll|„…ldd‹’Šult“““…‹‹ultttslldƒ}ƒ{u{{zmtllultekd›”›ƒƒ|’ŒŒŒ‹“£œ¥‘Œ…{zmƒ„„‚|uultult‹‹„‹‹„£››|„…ttsddc‘Œ…’…‹{{tedkred¦§¨{{ƒƒ„„ƒ}ƒ…‹‹ttsƒ}ƒ¦§¨œ¤¦£œ¥‹‹„“Œ”|„…llkŒ‹“{{ƒ…‹‹£››ƒ}ƒ‹„„‹„„{||ult‹‹‹‹„„“Œ”ƒ„„››”‹„‹ª³·£²š””™š¤‚|u‚|usle„Š„¤¤Šƒ}‹„„sle£œ¥yfl[TT{||‘Œ…ddc{||”››„Š„lri“Œ”¤¤””‹’ŒŒ{tttslŒ‹“‹‹„œ››“““lks“Œ”£››i\V‚|u{u{{tttll{u{‰Š¡{{ƒ‹„‹rg]tllƒ}ƒ‚v{ttsred“““tslztltslVZT\[[ekdu{{ek]ultbVZf]clekƒƒ|ldduztƒ}ƒŒ‹“rfk‹„‹¤¤‹‹‹lksu{{ult|‚z|„…›¢›{||lld[TTf]clriƒƒ|{||]bZddcllduzt”››|„…lld‹’Šuztƒ}ƒbVUtlltlltll‹‹‹ƒ‚u‰ƒv|‚zfkktzltslllkllklek\[b|‚zVTLsle¤¤\[b:97]bZrr]œ››””‹œ››‚ut£œ¥²««¦§¨²²¬¦§¨¦§¨«²«¦§¨‹’е¶·“Œ”œ››«²«‘Œ…²¬µ¨©´„„Šƒ}Š“Œ”Œ”•‹„„œ¤¦Œ”•œ¤¦£œ¥“““ztlƒƒ|\[[{tt|„…kd\lld{{t’…‹ultu{{tt{ultu{{lksmttedk{{ƒƒ||{||„„Štll|‚zf]cƒ„„ƒ||kd\”š”tlllldlldƒ}ƒ“““llkƒ||{{ƒ|‚zultedkekd{u{ƒ||JHFtll”››„Š„UTSmttultuzt\UZŒ‹“Š}ƒ|‚zd\\ultŒ”•]bZ”š”d\\””‹tts{zm’ŒŒtts¤¤š””š””ƒƒ|””‹ƒ||[TT…‹‹ƒƒ|””‹’…‹ƒƒ|ƒ„„lldƒ|||‚z|‚z{{ƒ|‚zƒ||“““œ¤¦“Œ”™š¤“Œ”u{{dc\{u{‹„‹llkƒ}ƒƒ}ƒ™š¤ƒƒ|›”›¦§¨šŒƒ||‚v{›”›ƒ||ƒ||ƒ||lksƒ}ƒ””‹{tt‹„„’ŒŒ”𔋒БŒ…šŒ‚|uult‹‹‹ultleklek„„ŠŠƒ}””‹‹‹„‹‹„¦§¨Œ”•’ŒŒƒ||‚ut‹‹‹‚ut””‹fkk‹‹„ddcŠŠ}‚wlj]\{yfj]\f]c‚|uekdllk‚v{ultd\\i\V[TT‚v{‚v{tts‚ut™š¤ek]lddƒ||\[[ult{{ttllfkk|„…f]c‹„„‹„„”š”™š¤„Š„””‹uztldd{u{uztŠ}ƒŒ”•u{{””‹|„…UTS…‹‹„Š„‹„„ƒ„„ult{{t”𔄄Š]cd“““VZ[„Š}›¢›uztJHFMRK{{t|‚zSKJ\UZlld„„Šƒ}Š{{ƒllduztƒ„„„Š„llk“““tllƒƒ|JHFJHFVTLllk¦§¨\[[&&ek]{||Œ”•¤¤Š}|™š¤¦§¨²««£œ¥‹‹‹£››‹‹‹¦§¨›¢›¤¤””‹“““””‹‹’Šƒ||¦§¨¨©´›”›‹„‹¨©´{{ƒ››”“““’ŒŒ‹’Й𤓓“”š”Œ”•ldd„Š„ƒ„„|„…|‚zŠŠ}{||ƒ}ƒ|„…lriultlksmtt„Š„lriUMR{{ƒsle{{ƒŒ”•lriultŠ}ƒ››”bVZtslfkkƒ}ƒ‹‹‹{u{ddc{tt]cdUTS|„…mw’ŒŒ{||d\\ƒƒ|dc\“Œ”llk£œ¥{||lriƒ||{ttu{{ultlddŠŠ}{ttUTS…‹‹VTL…‹‹rfk„Š„{u{sle››”lritll››”ztllld”š”š””{||ƒ}ƒddc”››{ttƒƒ|tts‰v|b[U„„ŠŒ”•uzt‹‹„|„……‹‹”“›’ŒŒ“Œ”„„Š…‹‹…‹’“Œ”{||…„’œ››‹‹‹“““sle’ŒŒ{{tttsult¨©´™š¤tsl’ŒŒtllultred‚|ulddVTLcbVœ›››¢›Šƒ}ƒ||’…‹’…‹Œ”•ldd‹„‹ƒ||Š}ƒ‚v‚‹‹„Š}|ƒƒ|””‹‹‹„¦§¨¤¤››”ttsttsœ››ddctsl‹‹‹‘Œ…lek‹‹„””‹SKJd\\{{t\[[dc\ƒ}Š‹„‹ult”š”…‹’{||¦§¨llkƒ||‹’Šœ¤¦‚v{‹„„{u{mttlldƒ„„f]cbVZ‹„‹f]cŠ}ƒddcttslekŠ}ƒ\UZ‚v‚›”›‚|uultredUUY{zmmtt«²«|‚z›”›{{tultƒ||ƒ||„Š„~’“lrilriŒ”•™š¤tsltsl|‚z|‚zf]cu{{{tttllƒ„„£œ¥llklddekd|‚ztzlƒƒ|ztlƒ}ƒ\UZlek\[[VTLslemtt¤¤MRK%&‹‹‹tsl–¢‹››”lldƒ„„{tt’ŒŒ‹’Ц§¨¦§¨“““””‹šŒ¦§¨””‹µ¶·œ››””‹¤¤œ¤¦›”›¨©´”“›„„Ц§¨ƒ||ƒ„„Œ‹“ult‹’Š””‹¦§¨œ¤¦š””‹„„uztuzt|‚zƒƒ|›”›‹‹‹UTS|„…{{ƒ|„…[[T\[[]cdlekd\\{ttlek“Œ”lrif]cldd{{ƒŠƒ}sleƒ}ƒ’ŒŒ‹’Š‹„‹mttSKJllklldsleƒ„„{ttddc{ttj]\llk‹„„lritlluzt|„…‹‹‹lld™š¤ƒƒ|™š¤Šƒ}{ttbVU]cdVZTlld’ŒŒ‹‹„ult””‹””‹’ŒŒ£››slef]cdc\ztl‹„„ŒŒšŒ”•ƒ||œ››‹‹„”š”{||ƒ||‹’Šmtt››”…‹‹ƒ„„›”›Œ”•„Š„ƒ„„tsl”››œ¤¦mtt{{ƒtlltt{ƒƒ|tll{{ƒsleztl„„Ф¤{u{ƒ||›”›‚|ukk]‚v{dc\™š¤¦§¨‰v|f]cŒ‹“™š¤ŠŠ}‰|v””‹”“›’ŒŒŒ”•ƒ}ƒf]c‹…’“Œ”Š}ƒƒ||‚|u„„Š‹‹‹¦§¨kd\ƒ||kd\””‹ƒ}ƒ\[[ztlsre“““{tt{{t{||sre[[Tlddkk]””‹{||bVZ{{t{{tzll”š”f]c’ŒŒlek‹„„¦§¨¦§¨“““{tttsltt{ztl‹‹‹‹„„lek“Œ”ultŠ}ƒ{{tf]c’…‹‚|uddc›”›{{ƒj]\{u{f]c\[b™š¤Œ—£…‹‹|‚zlekƒƒ|mttlek„Š„ƒ„„œ¤¦]cdtts|‚zƒ}ƒ[[T{tt„Š„lddlld„Š„lldƒ}ƒ‹‹„ekd\[[dc\lri”››‹‹„ƒ„„u{{{u{ƒ}ƒllkmttf]clddddc››”MRK*)(VZTmttztl””‹™š¤™š¤””‹’ŒŒ””‹‚|uŠ}|‹’Š””‹””‹‹‹„¦§¨š””¦§¨›¢›Šƒ}‹…’¨©´›”›„„Š“““›¢›“““™š¤{{t‹’Š”››¦§¨¦§¨œ››£œ¥›¢›“““‹’Š|‚z“““ƒ„„lek‹’Š…‹‹llkƒ„„tsl|‚z…‹‹ƒ}Š[TTd\\{{ƒ{u{ƒ„„ƒ}Šf]cttstsl‹„„Œ‹“’ŒŒ‹‹„{tttslmttJHFlld‹„‹ƒ„„[[T{{ƒllkj]\VTLƒ||“Œ”“Œ”ldd|‚z{ttllkult¤¤’…‹|‚z‹„„{||ƒ„„MRKƒ‚utll””‹‹„„››”‰|vƒƒ|j]\‹„„ƒ}ƒlldsle‘Œ…ultttsƒ}ƒ””‹ƒƒ|œ¤¦”š”Šƒ}|‚zš””ƒ„„›”›‹‹‹ƒ„„Œ‹“…‹‹‹‹„ƒ}ƒƒ}ƒtt{“Œ”™š¤|‚z‹„‹‹‹„œ››ƒ}ƒ{ttƒ}ƒ‚ut‹‹‹rfkb[Utll“Œ”[[TlksbVZ“Œ”Š}|{tt‘Œ…”š”rg]””‹Šƒ}¤¤›¢›ŠŠ}ult‹„‹tt{tts‹„‹‹„‹‘ˆ}ŠŠ}£››‘…„lksrfkƒƒ|j]\{{tllkllk‹‹„‹‹‹ƒ}ƒ‚ut{u{lri„Š„Šƒ}ddckk]ƒƒ|{u{ttstll|„…lek‹‹‹b[U{tttts{zmuzt“Œ”‹„‹{tt“““uztztl”››lddƒ}Š{{ƒƒ}ƒ£œ¥¦§¨ƒ}ƒƒƒ|tsl[[Tƒ||ƒ}ƒtll“Œ”‹’Šyl„\UZ|„…œ§²„„Šƒ}ƒ[TT„„ŠVZTtlllri|„……„’‹’Štllztlrfkultd\\ult|‚zŒ”•ƒ‚u{tt{{t{{tlldŒ‹“{||]bZtzl‹‹‹‹’Š””‹{{ƒlekmttlldztl‹‹‹¦§¨dc\>EC‹’ЄЄ››”“““’ŒŒ“Œ”ttsœ››“““¤¤“““{u{Š}|‘Œ…£›››”›š””ƒ„„›¢›››”™š¤¦§¨“Œ”¦§¨Œ‹“ƒƒ|¦§¨¦§¨‹‹‹|‚z“Œ”{{ƒ|‚z‹’Š””‹‹„‹”››‹’Šuzt“Œ”ƒ}ƒSKJ|„…]bZVTLkd\lld]cd\[blek{u{{tt{{ƒ‹‹‹ekdlldult‘…„‘Œ…””‹{||Œ‹“›”›{tt{{t{ttSKJlld|„…™š¤‹‹„‹„‹„Š„£››lri‹„‹uzt|„…‹‹„‹‹‹{ttƒ||u{{u{{{{ƒ|„…“Œ”ulttt{lri›¢›‹„„››”‹‹‹²««‘Œ…”“›ƒƒ|zllttstts„Š„œ¤¦tt{…‹‹kk]‹‹‹¤¤£œ¥‹’Š‚utŒ”•Š}ƒ„Š„”››Œ”•”“›{u{…‹‹tllttsƒ}ƒ…‹‹™š¤™š¤„Š„tts„Š}œ¤¦‚v{‚|u…‹‹mtt“Œ”ldd[[Tlldsleztlult¨©´“Œ”’ŒŒ£œ¥llkƒƒ|lddš””ztlŒ‹“{{tœ››““““““mtt{tt{u{›”›‹‹„zll‚utš””„Š}››”{{tƒ||››”‘ˆ}ƒ||tsl››”{||‹‹‹sle‹‹‹“““[[T‹„„lldlriŒ”•{{ƒ‹‹‹{{ƒtt{{u{lks‹„„uzt{||sled\\SKJƒ„„[[Tuzt””‹{||ƒƒ|ƒ}ƒš”””“›{u{ƒ„„‹„„‹‹„‹’Š|„…’ŒŒ“Œ”tsl‹„‹|‚z{||ƒ|||„…lks]bZmttslemttedktsl¦§¨mttldd{{t”“›{||ultttsj]\„„Šllk‹‹‹lld{ttƒ}Šlek{{ƒŒ‹“tts‹‹„tll[[TmttŠ}ƒlek„Š„{||{{tlldlld²¬µ]cd-1+tsl‹„„››”ƒƒ|{||··Ä¤¤£››‹‹‹”𔦧¨ult²¬µ£œ¥ƒƒ|¤¤¦§¨¤¤ƒƒ|Œ”•š””Œ‹“¨©´’ŒŒª³·œ››µ¶·œ››š””¤¤”“›››””š”|‚z…‹’ƒ}ƒƒ}ƒ‹‹„œ¤¦ƒƒ|‹„„lddu{{uztllkŒ‹“”››tt{Œ—£‹‹‹lek{u{…‹š‹„‹‹‹‹ƒƒ|ztl››”ƒ‚u‹‹„{||{||ƒ}ƒ„Š}Šƒ}kd\‹„‹lld‹‹‹…‹‹„Š„{||u{{£››…‹’zll¦§¨lkstzlmtt‘…„‹„„š””tts“Œ”{||ldd{||…‹‹mtt|‚zƒƒ|œ››”“›ŠŠ}ŠŠ}ddcœ››‹‹„’…‹{zm|‚z“““{ttlriddcŠƒ}‹‹„Œ”•™š¤Šƒ}‹’Š›”›‹‹‹ƒ„„tt{{{ƒŒ‹“„„Š“Œ”{{ƒ¦§¨{{ƒ’ŒŒ‹„‹”š”tllttsfkktsl‹‹„…‹‹{||“““{ttƒ„„{u{d\\SKJu{{rfk‚v{™š¤Œ‹“‹‹„””‹zll{{tƒƒ|ƒƒ|{{tƒ‚u{||Œ‹“tts‹„„‹…’kd\tsl‹‹‹¦§¨ƒ||lek‚utƒƒ|ƒ„„‹‹‹””‹u{{ƒ„„ztl”š”””‹’ŒŒ‹’Š‹‹„sre{||]bZtsl{||tlluztuztsle{ttedkzll|‚ztsltllj]\zllslelld‹‹„Œ”•ƒƒ|’ŒŒ{ttƒ||tsldc\tsltt{lrikd\slered{u{lddddc‚|u\[bllk…‹‹mtt¦§¨SKJtsl„„Š…‹’lrib[Uedk{{ƒœ››ƒ„„ultedkƒ}ƒ|‚ztll”š”Šƒ}‹‹‹zll\UZllktt{ttslksmtttt{[[T„„Šultlri{{t„„Šlrisle\[b¦§¨LKR%&£››Œ”•£œ¥£œ¥™š¤£²£››¦§¨””‹„Š„‹‹‹ƒ}ƒ£››››”¦§¨››”¤¤{||ƒ„„‹’Šœ¤¦¤¤··Ä¦§¨¦§¨‹’Š£››…‹’ƒƒ|{{ƒ{tt„Š}{{ƒ{{tŒ”•”š”|„…Œ‹“Œ‹“‚|u››”tll…‹’|‚zVTLlddmttmtt…‹‹lks¦§¨ttsultŒ”•|‚z‹‹‹\[[¦§¨ztl‹‹‹d\\””‹tll‹‹„’ŒŒlld™š¤“““™š¤{{ƒtsl{{ƒsleŒ”•œ››™š¤“Œ”‹…’|„…lldƒ||{tt„„ŠUTSlek„Š„{zm{{ƒLKRekd„Š„‚|ukk]‹‹‹¤¤””‹Œ”•|‚zœ››{ttttsƒ‚u’ŒŒ‹„‹uztƒ}ƒƒ||””‹{{t{||‚|uƒƒ|šŒfkk””‹ƒ„„tts{||„„Š{||Œ‹“„Š„|‚z£››{||ttsu{{Œ”•lddlddd\\‘Œ…ttsŠ~‹™š¤[[T„Š„tsl‹„‹ƒ||’ŒŒŠ}ƒƒ}Š‹’ŠŠƒ}‚|u’ŒŒ{{t\[[¦§¨j]\lriSKJ£œ¥„„Š“““Šƒ}ƒ„„ƒ||Š}||‚ztzlƒ„„Šƒ}’ŒŒ‹‹„{ttŠƒ}lddƒƒ|{{tƒ„„”››tll{||¤¤lddrg]{u{”››lrilri\[[|„…„„Š‹„‹mtt{{t|‚z{{tVTLbVZztl“Œ”{{ttsldc\]bZllk‹„‹ƒƒ|ttsldd‹‹„™š¤{u{ƒƒ|tt{‹u…‹…’‚|u„„Š{||Œ”•[[TŒ”•œ§²{{ƒ\[b¦§¨Œ”•tt{‹’Šb[Umtt{{ƒ{ttrfk’…‹{u{UTSlritlltts”››ƒ}ƒult‹‹„{||ddclri‹„‹{||…‹’tsl|„…b[Utts‹„‹llk‹„‹[TT\[[¦§¨ek]FD;Œ”•””‹¦§¨œ¤¦ƒ}ƒ¨©´‹„„¦§¨µ¶·¦§¨¤¤’‘~£œ¥¦§¨¦§¨²²¬‹’Š“““ª³·œ¤¦™š¤‘…„œ¤¦Œ”•|„…‹‹„š””„Š„™š¤¨©´‹„‹”“›¦§¨““““Œ”››”{{t”“›‹„„ƒ||{tt’ŒŒ|„…lri{u{llklri“““\[[{{ƒ{||{u{dc\›”›‹’Š“Œ”””‹£››{tttslƒ„„zllƒ||{tt£œ¥Šƒ}ƒ}ƒ‹‹‹Œ”•‹„‹ƒ||‘…„sre‚utƒ„„›”›{||ddcƒ}Š…‹‹tts“Œ”›”›‹’Š„„Šƒ„„’ŒŒ‹„„Œ”•lrikk]š””llkllkš””‹„„lld{{t‘…„UMRttstslŒ”•ultŒ”•››”››”››”uzt„„Ф¤„Š}”š”{ttƒ„„ult‹‹‹”“›‹‹„lekekdlriddcu{{ƒ}ƒlldtt{uzttts{{t|„…ƒ}ƒldd‹„„ult›¢›Š~‹|‚zŠ}ƒSKJ{u{‚v{sre‹„„ƒƒ|ztlŠƒ}””‹ƒƒ|ƒƒ|ƒ||mttllk„„Š„Š}{tt‚v{ƒ„„Šƒ}ldd‹…’\[[’ŒŒ’ŒŒ¨©´””‹”𔋋„lldjcV‘ˆ}]bZkk]bVZ{ttƒ„„„Š}ƒ‚u{zm‹’ŠVTL‹‹„\[[|„…\[[f]clddekdƒƒ|sle{tt’ŒŒ‚utf]cVTLƒƒ|UTS“““œ¤¦‹‹‹’ŒŒ]bZztluztlri””‹dc\Œ”•’ŒŒƒ}ƒrfk\UZ“““|‚z„„ŠŒ”•|„…u{{{{ƒttsƒ}ƒ¦§¨¦§¨‹‹„u{{„Š„“Œ”Œ‹“¦§¨tt{u{{|‚zŠ}|lri”“›lddf]cVZT”“›{||UTS“Œ”ttsVTLtslŠ~‹‹„‹dc\ultu{{ultŒ‹“llk¨©´UTS)+2››”ƒ||ƒ„„ƒ„„𔔍©´¦§¨«²«›¢›™‹†››”‹„‹’ŒŒ””‹“““‹‹„™š¤››”ƒƒ|”›››”›”š”œ›››¢›“““™š¤”“›¦§¨Œ”•¨©´”››Œ‹““““”››””‹z‚l¦§¨œ››…„’{{tƒƒ|ƒƒ||‚z{{ƒ“““ƒ„„ddc{||lksƒ}Š‹…’ƒ„„“Œ”‹’Šuzt{{t„Š}œ››“Œ”‹„„{u{{u{‚utlddf]ctllztlƒ‚uVTLultƒƒ|d\\Œ‹“ultVTLƒ}ƒ{{ƒllkllk{tt‘…„£œ¥Œ”•‹‹„{u{u{{Œ”•‹‹‹‹‹‹‹‹„„Š„ztlŒ”•tts¦§¨š””“““‹’Škd\‹„‹JHFlriƒƒ|tll‹’Ц§¨›”›””‹¤¤Œ”•ƒƒ|ƒ||¦§¨œ››lldƒƒ|tll‹’Šsle“““Œ‹“|„…“““…‹’‹„‹ztl\[[””‹ƒ}Šš””{||Œ‹“‹‹„tt{ƒƒ|”𔋅’|„…zll{{tŒ‹“ƒ}ƒllkƒ„„‹„‹ƒ„„dc\‹‹„yleƒ‚u’ŒŒ‹„‹tllttsƒ}ƒ{tt„Š}uzt¤¤Šƒ}{tt{u{“Œ”ttsdc\{||””‹{{tllk‹‹„ztlztflddœ››lrillkddc‹’Šek]|‚zdc\|‚zdc\lddUTSf]clekred…‹‹¤¤[[T{{ƒ“Œ”‚|u{{t„Š}”››„Š„edkŠ}|’ŒŒ„Š„Œ‹“››”œ¤¦‹…šsre”››tt{{u{‹’Šlrimttuztddcekd”“›uzt””‹]bZ™š¤edk|‚ziq]lks{||sletll‚utultµ¶·{||uztu{{ƒ„„dc\tts‹„‹{{ƒŒ”•dc\‹…’tts\[[|‚zddc{ttuzt‹„‹ƒ}ƒ{u{”š”tll¦§¨\[bLKR|‚z…‹‹ª³·Œ‹“’ŒŒ“Œ”››”ƒ‚u–¢‹„Š}¦§¨‰ƒv’ŒŒ‹‹„¤¤|„…¦§¨››”ƒ||‹‹‹”››’ŒŒ£››‹’Ѝ©´£œ¥··Äœ¤¦‹…’¨©´¦§¨¦§¨„„Šª³·š””¤¤¤¤œ¤¦ƒ„„ƒ||š””ƒ||fkkƒ„„{{ƒ‹„‹{||””‹{{ƒ£œ¥“Œ”ƒ}ƒult{u{tslŒ‹“tt{””‹Š}ƒ››”‹„‹tslldd‘Œ…¦§¨’ŒŒdc\rg]llk{ttlldsle‚ut‘…„”››ultŠŠ}llk{||d\\“Œ”‚|u‹‹„›¢›™š¤Œ”•|„…{{ƒllkdc\]bZ‹„„ttslek‚|u‘Œ…ldd«²«Œ‹“{u{ƒ}ƒcbV”š”ƒ„„{||””‹’ŒŒ¤¤‹‹‹š””{ttƒ‚u¦§¨„Š„‹’Ѝ©´{ttŒ”•‹‹‹‹„„£œ¥”“›‹‹‹{||{{ƒ‹‹‹…‹‹ƒƒ|‹‹‹|‚z{u{…‹‹ttsult{||fkk\[[Œ‹“u{{‹‹„Œ”•{u{{ttƒƒ|“Œ”{tt{zm{tt‹‹„‚|u””‹ƒƒ|ldd\UZ‹’Š“Œ”‹’Š“““sle’ŒŒd\\kd\{tt{{tlldmtt]bZekdttsƒ„„šŒƒ}ƒbVZŠ}ƒ…‹‹llklldkd\SKJddc{u{ztlllktzlb[U{u{{tt{{tu{{lriƒ||r]g¦§¨ƒ||¦§¨”š”…‹‹ƒ‚u‹‹‹›”›cbV””‹‹„‹|‚z„„Š‹’Š›¢›œ¤¦‹„„ƒ}ƒ””‹„Š„‹’Š|„…|‚zekdœ§²|‚z|‚z‹‹‹mttuztƒ||d\\UMR›¢›‹’Šƒ||lksf]c››””››{{t›¢›]bZŒ”•‚|u“Œ”uztmtt[[Tttslri|‚zdc\JHFƒ}ƒtllƒ}ƒ[TT{ttultd\\¦§¨MSSLKRœ¤¦›”›”“›£œ¥‚v{ƒ||’…‹””‹¦§¨¦§¨¤¤²¬µ“Œ”¦§¨ƒƒ|“““tzlª³·‹’Ѝ©´‹’Š£œ¥Ÿ±¯¦§¨¦§¨”“›…‹‹¦§¨£œ¥””‹™š¤…‹‹ƒ„„“““‹‹‹™š¤””‹’ŒŒ…‹‹‹…’edk‘Œ…\[bŒ”•ƒ}е¶·lks™š¤œ¤¦„„Š‹„‹‹…’ƒ||œ¤¦ƒ||Œ‹“llkztl’ŒŒ|‚z„Š„{{t“Œ”ƒ||’…‹lld‚|u’ŒŒtsl{||…‹‹Šƒ}‹„„sleu{{’ŒŒ‹‹„|‚z\[[ttsƒ‚u“Œ”ƒ}ƒekd‹‹‹llkœ¤¦tt{ddctzltsljcVƒ||¤¤œ››‘Œ……„’‹‹„‘…„‹‹‹{||›¢›|‚z“““‹’Š‹„„zllŠ}|ƒƒ|{tt’…‹‹’ŠŒ‹“u{{“““‹‹‹zll’ŒŒƒ„„{{tŒ‹“„Š„‹„„”“›ƒ||{tt”“›ƒƒ|tt{tsltts›¢›tllŒ‹“tt{tt{\[[“““ultllkƒ}ƒlks¤¤„Š„‹u…{{tƒƒ|››”Œ‹““Œ”ƒ}ƒtts{u{ƒ||ttsœ››””‹”“›‘Œ…ƒ||Š}|{ttsle{tt[TTkd\tsl{u{ƒ„„{{tŒ‹“kd\””‹{u{‚v{JHFŠ}|ztllri‹‹„{ttultbVUdc\{u{lekŠƒ}ttstts‚utƒƒ|ƒƒ|{{ƒ‚ut«²«›¢›„Š„{||„„Š‹„„‹‹‹ztlƒ„„|‚z£œ¥‹’Ц§¨Œ”•sleƒ„„š””|„…tzlŒ—£…‹‹Œ”•|„…]bZ|„…]bZu{{\[buztJHF\[b{tt]bZyle\UZŒ‹“{||tllredVZTek]fkklddlekedk|„…ttsu{{]bZ]bZ|‚z‚v{ultƒ„„‹‹‹ƒƒ|ƒ||sle\[b¦§¨MRKUTS|„…cbVƒ„„£œ¥“~ˆ‹„„””‹Š}ƒ|‚zƒ‚n’ŒŒš””sle|„…{||“““¦§¨›¢›¦§¨¨©´£›››¢›«²«lld‹‹‹«²«œ¤¦”“›“““œ››Œ”•¡¡’ŒŒª³·”“›llk‹‹„lri‹’Š‚|u{||‚|u{{ƒŒ”•ult‹‹‹{{ƒƒ}Š{{ƒlkslldd\\‚utƒ}ƒƒ}ƒztl‹‹„‚ut‚v{‹‹„lek‚|ured’…‹{u{{u{{ttŠƒ}lddldddc\sle‘…„›”›‹„„ƒƒ|¦§¨|‚z\[[{||‹„„ult‹‹‹{u{\UZllkƒ„„f]cf]ctzlsreSKJƒƒ|tzl[TT‚ut‹…’sle‚|u“Œ”[[Tƒ‚u””‹”“›™š¤››”›”›¦§¨¦§¨{||‘…„tsltsltsluzttts’…‹ƒ}Šš””š””„„ŠŒ”•‚|uƒ}ƒ›”›uzt™š¤š””ƒ„„ldd‹’Š{{tlddŒ”•ƒƒ|ƒƒ|ztlƒ}ƒf]cuztultœ›››”›Œ‹“””‹‚|u|‚ztslœ¤¦ƒ„„ŠŠ}¦§¨ult“Œ”””‹”››ƒ„„”››’ŒŒ‘…„ƒ}ƒŠ}|ult{||d\\“Œ”Šƒ}ultƒƒ|{{tƒƒ|‚|u‘…„yle{||‚|usle{{t¤¤ƒƒ|ƒƒ|tsllldFD;uztllktzllld\[[lldƒ}Šdc\bVZSKJtzlztl‹’Šlriultztl“““kd\””‹¦§¨›”›ª³·{{tkk]ztlŒ”•tsl…‹‹uzt„Š„u{{mtt‚v{u{{{||lksddcllkMSSlldult‹…š„Š}{{tUMRf]clektll”š”{{tlld{||u{{„„Štll\[[dc\]cd]bZlri‹’Š‹„‹„„Š‚utultŠƒ}Š~‹UMRf]c£››JHF?;C„Š„„„Š“Œ”£››‹„‹ƒƒ|‹‹„’ŒŒŠŠ}””‹Šƒ}Œ”•¸Á¹¦§¨¦§¨›¢›”𔦧¨œ¤¦œ¤¦¦§¨‹„„œ¤¦‹’Š‹uŠƒ„„…‹‹“““¨©´¦§¨Œ”•…‹’Œ‹““Œ”ŠŠ}’ŒŒœ››|‚ztsl‹„‹£œ¥‹„„uztUUY¦§¨Š}ƒlksultlksmtt…‹’ƒƒ|ƒ||œ¤¦{u{ƒ}ƒ{{tƒ||“Œ”|‚z”››“““‹„‹‹„‹‹‹‹Šƒ}ldd†~‘{u{™š¤‹‹‹“Œ”””‹cbV{{tƒ‚uƒ‚u{zm‹„„j]\‹’Šƒ||¦§¨ttstts|‚ztllf]cƒ}ƒƒƒ|lrilriƒ‚ulri„Š„{tt{||zll‚ut‹„‹““““““ƒƒ|›”›™š¤’ŒŒ‘…„¦§¨ƒ||””‹ƒ|||‚z{u{{{ƒ”š”ult‹„„’ŒŒƒ„„tll„„Š‹’Š’ŒŒ{u{’ŒŒu{{“Œ”ƒ„„tsl{{t…‹‹ƒƒ|ƒ„„tllf]cƒ„„”“›“““{{ƒƒ||{tt{{ƒzll\[[ƒ||‹„„{||ƒ‚uu{{b[Usle‘…„jV[‚|u‹‹‹ƒ„„””‹ƒ„„ztlŠƒ}œ¤¦š””tts““““Œ”Œ”•‚v{ƒ}ƒj]\‰|v‘…„””‹¤¤‘…„{tt{tt‹‹‹[TT‚|u£œ¥Š}|ylett{sreƒ||tll‹‹‹‘Œ…lddiq]{u{‹…’|„…ƒ||kd\{{ttsl„„Šf]ctll{u{b[Ulksztl|„…™š¤uzt{{t‹„‹mtt{||\[b|„…lks…‹‹UTS“Œ”{||\[[|„…lkssle\[bllk\[bUMRttsuzt\[b{{ƒlekdc\tt{ƒ‚u‹‹„\[[{{tƒƒ|[[T”š”{{t|„…{{tultlddƒ}ƒtll™š¤”“›››”lddbVZldd¦§¨\UZJHFlks|„…‹„‹£œ¥™š¤‚|uŠƒ}”š”””‹””‹””‹«²«¤¤¤¤””‹œ¤¦¦§¨‹’Ѝ©´«²«µ¶·›¢›{{t””‹¨©´œ¤¦Œ”•”››Œ”•’ŒŒ‹‹‹Œ‹“™š¤¦§¨|‚zœ¤¦‚|u‹’ЄЄyleult¦§¨]cd{{tlekultŒ‹“edklksu{{|„…”š”dc\„„Šlek”“›{||¤¤‹„‹{{tlri{ttŒ‹“’ŒŒ¨©´ultlddUTS¦§¨ƒƒ|ƒ„„ƒ||”››sleddc\[[lriƒƒ|lek[[T{tttll‚|u„Š„ƒ„„|„…uztJHFlkscbV|‚zllk””‹|‚z„Š}””‹””‹Š}|kd\ƒ„„Œ”•|‚z‹‹„tll„Š}‹„‹›”›²««“Œ”¤¤tll„Š}Œ‹“š””‹’Š{{ƒ‹‹„ƒ||{tt“““’ŒŒƒƒ|“Œ”’…‹‹„‹ddcult“““‹„„””‹‹’Š„„Štll[TT“Œ”„Š„{u{ƒ„„ƒ}ƒœ››ƒ}ƒ²²¬’ŒŒ|‚z„Š„ƒ‚n„„Š”š”{||{{t‹‹„lddmwŠ}|‹‹‹|„…“Œ”ƒ„„Šƒ}ylebVZŠ}|œ››ekdƒ}ƒ{ttkd\zll{ttš””‹„„’ŒŒ‹„„‘…„››”’ŒŒ{u{ult“Œ”‘…„[TTƒ}ƒ[TT„Š„lri{u{{ttŠƒ}mtttt{‹‹‹ultllkztlUTS£››tll…‹‹›”›‹„„“Œ”{tt{tt[[Tllkš””\[[››”‹„„ttsLKR[TTtzl\[[SKJmtt|„…mttœ¤¦ddcu{{lekœ¤¦dc\ult’ŒŒ“““‹„„lks{u{ult[[Tœ›››¢›‹’Štzl{{tƒ}ƒfkkfkkƒƒ|{||uztƒ„„uzt{tt{{tŠ}ƒult£›››”›kd\tll£››JHF*)(”››“““‹„„‘…„‹‹„”“››”›””‹|‚zz‚l£››œ››œ››“““›¢›··Ä«²«ª³·¦§¨µ¶·«²«œ››²²¬Œ”•‹’Šœ¤¦£œ¥œ¤¦‹’Š”š”œ¤¦”“›Š}|¦§¨œ¤¦œ¤¦Š}ƒŒ”•‹‹„lldƒ}Šult„„Š””‹Œ‹““Œ”{u{„„Šllk|„…›¢›‘…„“““lri{tt“Œ”””‹‹„„š””””‹“Œ”ƒ||‚ut£››œ››””‹‹„‹ddc„Š„ƒ||„„Š’ŒŒ‹„‹{u{f]c[TTlldcbVŠ}ƒUTSšŒ‹„„’ŒŒƒ‚n[[Tlrikd\{{ƒlri{{t‹‹„lri{zm{tt›¢›ƒƒ|“““zll{{t‹‹‹‹‹‹“““Šƒ}|‚zƒ||ƒ„„‘…„¦§¨’ŒŒ{{t‹…’ƒƒ|œ¤¦Šƒ}””‹”“›‹„„‹„„fkk‚ut“““tslult‹‹‹œ››u{{ƒ}ƒ”š”‹’Šƒ}ƒddcŒ‹“tt{ƒ||lddlddƒ„„{{ƒd\\ult‹‹„‚v{{tt››”lri‚ut|‚z„Š}uztztlzllƒ||tlltts𔔦§¨‹’Šuzt‚|u›”››”›lddztl„„Šttsƒ||lek‚|uttsek]ƒ||Šƒ}“Œ”‘ˆ}£››š””ŠŠ}“““lekƒ||ztlsle‚wl‹„„dc\uztztl{ttuzt„Š„‹’Š„„Š“““‹‹„|‚z¤¤Œ‹“ƒ„„llkldd„„Š“““‹‹„œ››u{{ƒƒ|{{t]bZ{u{SKJUMRmttSKJ]cd]bZ|‚zŒ”•mtt‹’ŠŒ”•lri„„ŠMRKƒ}ƒf]clldJHFdc\UTSd\\mtt|„…tll‹„„‹‹„lriekdlriƒƒ|\[[tlltt{dc\lridc\{u{{{ƒlddlektllƒ}ƒd\\ldd¦§¨JHF$›¢›ƒƒ|”“›’ŒŒ”š”£œ¥™š¤‘Œ…””‹¦§¨””‹¦§¨¦§¨š””¦§¨œ¤¦ª³·¨©´¦§¨µ¶·‹’Šœ››£››‹’ŠŒ”•”››Œ‹“”››œ››lek‹’Й𤋋‹¦§¨ª³·…‹‹’ŒŒ„Š„tsl{{t£œ¥‹…’\UZUTSƒƒ|{ttlri|„…lri|„…z‚l’ŒŒ””‹„Š„„„Š‹‹‹tll“Œ”‹„„›”›‚utŒ‹“‰ƒv£››Œ”•””‹ƒ„„{||tts‹„‹sle¦§¨ƒ„„bVU‹’Šldd|‚zdc\ƒƒ|j]\dc\redzlluzt”š”ttsJHFlek{{ƒsretsl{||Œ”•œ››››”{zm{||Šƒ}sleultƒƒ|uztŠŠ}tts”››ƒ||ult¤¤œ››tzl{||‹’Š”š”„Š„”š””š”‹‹‹››”tt{ƒƒ|lri…‹‹‚v{{u{ƒ|||‚zmtt‹„„ult‹…’ek]š””{u{tts‹‹„“Œ”zll’ŒŒ“Œ”‚v{‹‹‹lekƒ‚utslcbV|‚zuztkd\ƒ„„„Š}zll’ŒŒ£œ¥Šƒ}tsl|‚z„Š„“““‚|u‚v{’ŒŒ‘…„red„„Š{{ƒ“““r]glrilld{u{{u{Š}|[[Tkd\‘ˆ}‚|u‹‹„|‚zj]\lddf]ckd\{u{Œ‹“Šƒ}[TT‹‹„dc\|„…‹‹‹ek][TTlld{{t{||¦§¨“““{u{ult¦§¨¦§¨›”›{||›¢›|„…mtt{{tUTSddc|‚zŒ‹“\[blri””‹‹’Šmtt™š¤uztŒŒšlriu{{leku{{lksŒ‹“mttlri{{ƒ{||{{t{{ƒ|„…zllddcttsuztllk„„Šuzt|‚zlekdc\ztl{u{ultƒ„„ƒ}ƒŠ}ƒ{tt“Œ”{||ttsult¦§¨VZT*)(”››“Œ”””‹‚|utsl’ŒŒ‚wlŠŠ}””‹¤¤µ¶·””‹£››››”£››ƒ„„””‹¦§¨£››¤¤»ÂǤ¤¤¤œ¤¦|‚z‹’Š··Äœ¤¦„„Šƒ||Œ”•œ¤¦…‹‹››””››tzl””‹œ¤¦“““|‚z“Œ”‹„‹|„…|‚z™š¤[TTVTL[TTlriu{{‚ut‚v{tllŒ”•”“›””‹’…‹ƒ||‚v{Šƒ}Š}ƒzll£››Š}ƒƒ„„lld{{tlld”“›lekyfd†~‘ƒ}ƒkd\tsl{tt’…‹””‹{{t{ttƒ||‰v|uztllklddŒ”•cbV{u{SKJlri|‚z‹‹‹tzldc\””‹‹‹„“Œ”‘Œ…‘…„{u{{zm‹’Š{tt„„Š””‹{ttŠƒ}tsltsl|‚z›”›|‚z””‹‹’Šƒ‚uŒ‹“tsl‚|uttsƒ||‹‹‹ŠŠ}ultult|„…ttsuzt{{tƒ}ƒ‚|utsl‹’Š{{ƒtlltts{{t™š¤²««‹„‹ult|‚zdc\tslƒ„„‚v{ƒ||{{t”š”œ¤¦‚|u£››“Œ”‹„„‚ut{{tuzttzl{zmŠ}|‚|u‚|u’ŒŒš””„Š„uztƒ||“Œ”‹„‹Š}ƒ|‚ztllztfb[Uekdttsj]\ƒ‚u|‚zllkŒ‹“{u{Š~‹{u{{||ƒ||[[T”š”ƒƒ|]cdUTS‚|uf]cbVU‘Œ…b[U{{tj]\Œ”•llk{||Š}ƒ‹‹‹‹‹„{tt[[T[[Td\\llk“Œ”|‚z{tt{{ƒ|„…Œ”•lksŒ”•ª³·œ¤¦{{ƒ‹’ŠMSSlriVTLbVUf]cUMR>B9ƒ||ª³·“Œ”|„…]cdtts]cd|„…ek]™š¤„Š„Šƒ}…‹‹{{t|‚z{tt’ŒŒb[U‹„‹{u{ult{tt’ŒŒr]Z‹„‹{ttœ››MRK*)(””‹²¬µ£œ¥””‹ultmw””‹Ä¿¤¤””‹›¢›£››²««””‹£œ¥¦§¨¦§¨£››£››¦§¨²²¬‚wl‹‹„””‹›¢›{||£œ¥œ¤¦‹„„¦§¨‹„‹{ttllk¦§¨“““Œ‹“ƒ‚u„Š„’ŒŒ|‚z¤¤‹‹‹…‹’FD;„Š„ultu{{u{{fkkUTS{ttzll‹„‹…‹‹ƒ}ƒ‹‹„š””d\\{u{lld‹„„Š}|ƒ||‹‹„ƒ}ƒuzt{ttkk]ƒ„„UMRrfk‚utttsSKJztlrfk””‹tsl\UZ“““‹’Š‘Œ…‚wlllkttsb[Uldd{||{||¦§¨kk]ƒ}ƒek]|„…””‹‹„„‹‹„š””ult“““‹‹‹lld”š”llk{ttƒ}ƒslesle{tttsl{u{”𔫲«¤¤”š”ƒ„„Šƒ}Š}|‚ut‹‹„“““ƒƒ|’ŒŒuztƒ„„u{{{{ƒ{{tƒ}ƒlri‹’Š“““ƒ||ttslriƒ„„”“›Œ‹“ult{tt{{tkk]{{tultttsllddc\{{t{zm{{tj]\zll‚v{‹„„{u{tllƒƒ|tzlb[U{{tŠ}|š””tllŠ}|œ¤¦ƒ}ƒult“Œ”£››Š}ƒlrilri“Œ”VTL{zm‚|u‚|u“““›¢›ultlddzll‘…„ztlf]ctts|‚z{tt{||uztlldtsl{||fkkek]tts{zmddctllš””VTLultuztbVUlriuztekdŒ”•””‹¦§¨Œ‹“f]c‹’Š…‹‹…‹’”››œ¤¦ttstt{u{{UUYJHF]bZƒ}Š{{ƒ[[Ttsl{{ƒŒ”•‹’ŠmttŒ”•‰ƒv{{tldduztttslriuztuzt{zmƒ„„llkf]ctllkd\ldd‚v{rfkztl‚v{leklek«²«JHF,55llklksƒ}ƒ””‹š””£››¤¤››”|‚z¤¤’‘~µ¶·²²¬²««š””¦§¨¤¤‚v{uzt„Š}¤¤£››¦§¨‹‹„|‚zœ››œ¤¦”“›{ttœ››ƒ||ztl‹‹„‰|v\[[lritlllld{{t{{tƒ„„Š~‹…„’tyguzttll‹‹„|‚zŠ}ƒ{||rg]‹‹‹kk]‹‹‹‹‹‹ƒ}ƒƒƒ|ult‹„‹ƒƒ|›”›‘Œ…“““œ››Œ‹“tsllekŠƒ}‚v{zll[[Tb[Uultrfkƒƒ|‚|u{u{„Š}£››”“›{{ƒŠ}|{u{…‹‹ƒ}ƒ‹‹„‹„„ƒ„„tt{jcVi\Vƒ‚uƒ||ƒƒ|›¢›¦§¨“““””‹‹‹‹{u{ƒƒ|sreztf{u{‚|u|‚z‘…„{zm|„…tsl‹‹‹‹’Š|‚z…‹‹›”›|‚z“Œ”ƒƒ|ƒ}ƒ”“›œ¤¦ƒƒ|tll{{tŒ”•Œ”•Š}ƒŒ”•Š~‹{u{‹’Š’…‹ƒ}ƒfkku{{tll’…‹ult{ttš””\[b{{tƒƒ|sleƒƒ|lektll|‚zƒ‚u{u{‚|u£››£œ¥‹‹‹ƒ}ƒ‹’Š”››{||tsltslrg]ƒƒ|sle’ŒŒ“““{{tƒƒ|“Œ”tsl’…‹››”kk]ult‹„„ƒƒ|ƒ||lld‹‹‹ƒ}ƒ‚ut{||bVUrg]kd\lek£››ƒ||tslƒ„„uzttts{u{z‚lmtt{zmztlj]\tts{{ƒ‘…„ŒŒšz‚lekdtll|„…„Š„„Š„yl„]bZ‹’Š‚|u{||‹’Š‹‹‹Œ‹“Œ‹“‹‹„¨©´fkk|„…\[b„„ŠUTSD;9lksmtt‚|u{{ƒlks”š”mtt{{ƒŠ}ƒ’ŒŒ“Œ”‹’Š‹‹‹{||tts‚uttsltt{|‚ztlllekredf]cf]cƒ}ƒ{ttŠƒ}tlltll¦§¨MRK*)(ƒ„„ƒ||¦§¨¦§¨£››²²¬¦§¨‰ƒv¦§¨µ¶·ÃÄÆ¤¤µ¶·“Œ”””‹”š”£œ¥¦§¨µ¶·››”””‹‹„„‹‹‹œ››“Œ”tts¦§¨™š¤²²¬””‹¤¤‹’Š”››Šƒ}ttsVTLtts”𔋋‹uzt{ttttsƒ„„]bZƒƒ|¦§¨uztllk„Š„{{tztlƒƒ|‹‹‹Œ”•uztd\\lddƒ||‚|uztlŠ}ƒ””‹‚utedk„Š„tts“Œ”lld’ŒŒldd™š¤Šƒ}„Š}‹‹„Šƒ}f]c‹‹‹{{tldd„„Š‹‹„™š¤‚uttts[TTSKJŒ‹“lriekdƒ‚uŠƒ}tts‰v|“Œ”²¬µ¤¤¤¤£››‹‹‹ƒ}ƒ™š¤ƒ‚ukk]‹„‹””‹ƒ||‹‹‹››”‹’Šztlultƒƒ|‹’Š””‹‹„„“Œ”ƒ}ƒŠƒ}{||ƒƒ|Œ”•{ttlrikk]{u{…‹‹¨©´ƒƒ|tll{||Œ”•‹‹„ƒ}ƒ{||u{{‹„„{{tult‚|uƒ}ƒ”š”””‹tsl””‹œ¤¦‚v{›”›{{trg]{{t‘Œ…ƒ||›”›‚ut“Œ”“Œ”››”{{t’ŒŒ’…‹d\\ttskk]’ŒŒ”“›‰‘~¦§¨ttsŒ”•œ››‰|vsre››”‚|u{{tdc\kk]ƒ||ƒƒ|d\\{u{slered{tt{tttll\[[{u{lld{||VTL{tt|„…ttslldztl’ŒŒŒ”•lks{||‹„‹lritts‹„‹Œ”•uzt™š¤lddtll|‚z”››llk{||ƒ„„‹’Š’ŒŒ‹’ŠVZT\UZlrislef]cu{{{{ƒ‹…štlldc\UTSlri‹’Šlks…‹‹ƒƒ|‹„‹{|||„…œ¤¦{|||‚zddctslƒ}ƒekd{tt[TTƒƒ|{tt{u{Šƒ}{tt››”Šƒ}dc\µ¶·JHF*)(„Š}“Œ”œ¤¦‘ˆ}””‹£œ¥‘Œ…£››””‹»ÂǦ§¨²²¬²««²««¦§¨¦§¨œ››¨©´›”›£››“““ƒƒ|ƒ||tzl™š¤…‹‹ƒ}ƒ‹’Ф¤¦§¨£œ¥ŠŠ}ƒ‚u¦§¨uztuzt“Œ”››”ƒ}ƒ‹‹‹tslttsŠƒ}ddc‹’Š|‚z„Š}|‚zlridc\ƒ||ttsuzt„Š„ƒ||ldd{u{d\\zll£››š””œ¤¦¦§¨¦§¨¦§¨ƒƒ|‹‹‹”š”{{ƒ²¬µ’ŒŒ£››‘Œ…‹‹„tllƒ}ƒtts…‹‹„Š„‹„‹yleš””tllƒƒ|mttVTL’ŒŒtt{”“›ƒƒ|kd\ƒ„„ƒ‚uVTL’ŒŒ‚|u‚wlš””tt{‚|ullkdc\tslult‹„„ƒ||‘Œ…‘Œ…‹‹‹jcVmw{zm¦§¨£œ¥‹…’™š¤‹’Š›”›{u{{||‹‹„“““{u{‹‹‹Œ”•Œ‹“{||‹‹‹ƒ„„{{t‹‹‹tslƒ|||„……‹‹{||‹„„›”›ƒ}ƒ‹„‹tts‹‹„|‚z{zm¤¤tll{u{ƒƒ|{{t›¢›{{t””‹ƒ||ƒ||{{t‹’Š|„…‚|uŠ}ƒyleƒ||red„Š„””‹ƒ||’ŒŒ‘Œ…””‹ƒ„„dc\uzt””‹‹’Šƒ||slekd\mtttzl\[[ultƒ||’…‹‘…„sle“Œ”ƒ||‹‹‹ƒ„„|‚z„„Š{{tb[UtllŒ”•„Š„lld…‹‹”“›ƒ||””‹„„Šœ››|„…ztlœ››„Š„Œ”•’…‹lddŒ”•tts„Š}|‚zmtt™š¤”“››¢›{tt{{ƒmtt””‹|„…Œ”•tt{ƒ}ƒred‚v{lksŒ”•ekdleklksztllek„„Šuzt„Š„dc\[[Tekdlekƒ}ƒlld{||[TTtlllddlek{tt‚ut„Š}Š}|]bZ··ÄJHFF=C‹„„Š~‹””‹²««²««£œ¥””‹ƒƒ|‰‘~¢—£››ƒƒ|šŒ‘…„‘Œ…š””²««››”²¬µ··Ä“Œ”œ››Œ”•›¢›llk“““‹‹‹{tt››”£››Š}ƒ‹„„¦§¨ŠŠ}‹‹‹„„Š…‹‹lritts‘Œ…‹‹„tsldc\ttsƒƒ|\[[[[Tkd\VTL[[Tr]g‹‹‹‹’Šek]“Œ”{ttlldllk‚ut”𔋄„ƒƒ|‹’Štts„Š„‹‹‹zlldc\{||“Œ”rfk¤¤”“›››”„„Štsl‹’Šƒƒ|‹’Š“““‹‹„ƒ||tllllktzlƒ||‚wlŒ‹“{||redsleSKJ{{tƒƒ|zllsletsl{zmlekf]c„Š„rg]„‰vttsŠ}ƒ{||š””””‹¦§¨‹‹„””‹sle|‚z””‹“Œ”“Œ”‹’Šƒ}Šu{{{tt¤¤‹„„‚utƒ}Štt{ƒ}ƒllkllkƒƒ|“Œ”lld‹‹‹{tt”“›”››‹‹„{ttult‹‹„‹„„f]c›¢›ƒƒ|ƒ‚u‹‹„ƒ„„‹„‹›”›‹„„¤¤ŠŠ}sre£œ¥{||‹‹„„Š„‚|u{tt‹„„llk{tt””‹JHFtts{zmrg]{{tŒ”•ƒ„„{{t‹„„¦§¨£››jcVdc\sre]cd{{t¤¤¦§¨“Œ”š””‚uttts‚utœ››Œ‹“‹’Š[TTddcsref]clldult‹’ЄЄ™š¤u{{›”›kk]“Œ””“›ª³·ztl„Š}‹’Šult“Œ”Œ‹“u{{š””„„Š‹‹„|„…‹’Š“““lri]bZlldfkkVZT]cdllk{ttŒ‹“‚|u‹„„VZ[mttŠƒ}‹…’llkŒ”•{ttmtt]bZedkdc\{||fkk{u{lddzll{{ƒtllultyfdred››”ldd‹’Šƒ||ƒƒ|¤¤JHF*)(tsl’ŒŒ”𔲲¬¢—š””””‹’‘~‚wl””‹¦§¨‘Œ…£››¤¤“Œ”²¬µ¨©´²¬µ“““œ¤¦¦§¨£œ¥«²«‹‹„“““™š¤‹‹‹„Š„¦§¨‘Œ…£œ¥¦§¨‰|v¤¤™š¤u{{‹‹‹››”Šƒ}¦§¨{||dc\uzt„Š„]bZ{||ƒƒ|‹’Štzllriƒ}ƒŒ”•‹‹„Œ‹“‚|u{tt{ttƒƒ|‘Œ…Šƒ}kd\r]gztl¦§¨tsl{||llkVTLtt{‹„„‹„„Šƒ}uzt’ŒŒ„Š„‹„„{||sre{{tƒ„„‹‹‹sle’ŒŒtslƒƒ|“““lddtt{{{ƒkd\sre‹„‹|‚z‹‹‹tllƒ||{zm„Š}f]cVTLztl‰|v’ŒŒŒ‹“sle„„Šœ¤¦ƒ‚u‹’Šƒƒ|£››‹’ŠŠŠ}“““Œ‹“”“›…‹‹’ŒŒmtttsl››”›”›‹„‹Œ”•ultd\\lks‹„‹“““ldd|‚z‹„„™š¤™š¤tts‹‹„‹„„Š}ƒtsl[TTƒƒ|{zmdc\ztl‹‹„‹„‹{tt‚|u¦§¨ŠŠ}””‹{{tult{ttlri„Š}”“›zllult‹‹‹tll‚|u””‹f]cultŠŠ}Œ”•sreŒ”•””‹«²«’…‹“““ƒƒ|lddredSKJtslcbVtllƒ||ƒ||sle£œ¥‹„‹VTLb[Uddc‹‹‹|„…tll‹„‹{{tllkuzt|‚zSKJlri{||‹„„£œ¥“““‹‹„¦§¨{tt›¢››”›‹„‹’ŒŒlriŒ”•{{ƒkd\¨©´Œ”•™š¤uzt„Š„ŠŠ}JHF|„…lriƒ}ƒf]c\UZ]bZult|„…ƒ}ƒƒ}ƒ’…‹lkslrimtt|‚zttsSKJlriuztedklksƒ||ƒƒ|tts‹‹‹ttsrfkd\\{u{Š}ƒ‹‹„Š}ƒ{||£››:97*)(œ¤¦’ŒŒŠƒ}²««²««²««š””¦§¨””‹‘ˆ}µ¶·²««“Œ”²««²¬µ²¬µ¦§¨™š¤‹‹‹¤¤ƒ}ƒ¦§¨“Œ”“““œ¤¦”“›Œ‹“››”¦§¨””‹£››“Œ”llk²²¬{{tuzt£œ¥ƒ„„tll£œ¥¦§¨Œ”•|„…‹’Š|‚ztzl‹’Š‹…’lri””‹ƒ„„”“›{zmŒ”•””‹{tt{ttƒƒ|Šutztltsl››”Šƒ}“““‘Œ…{||{zm{||„„Š{{ƒ{u{ƒƒ|uzt{{tVTLf]c|‚z‹‹‹{||ƒ„„d\\£››£››{zmdkV[[Tddc‹’Šƒ}Š‚|u[[Tƒ„„{{ƒ„„Š{ttsleƒƒ|ƒƒ|f]c{u{ƒ„„”››š””Š}ƒ’ŒŒ{ttŒ”•‘Œ…””‹£››¤¤¤¤‹‹‹’ŒŒ“Œ”ƒƒ|‹‹„œ››tsl“““‹„„‹‹‹tt{ult‹…’zllddc’ŒŒ{ttƒ||{{tu{{‹’Š”“›‚ut‚|u“Œ”Œ‹“tll{zm„Š„ƒ||ƒƒ|‚wl“““‚v{šŒyl„›”›””‹‘Œ…Š}ƒ{ttsleŠƒ}{{t{tt›”›ƒ„„{ttlddekd‹‹‹‚ut„Š}””‹””‹{{tµ¶·“““¦§¨’ŒŒ”››„Š„redkd\VTLsleldd{||‚|u{ttŠŠ}|‚z{tt‘…„ƒ„„lldlriztl››”‹„„{{tVZ[‹’Štts]bZ{||Š}ƒ‹„‹tllŠƒ}{zm{tt{||””‹‹‹‹‹„„‹„„ztlfkk“Œ”rg]Œ”•™š¤tt{mtttsl”“›ddc…‹‹MRKlkslriƒ}ƒtlltts{{ƒ“Œ”{{ƒŠ}|Œ”•{||ekduztttsedk””‹lrilksŒ‹“ƒƒ|lri[TT{{ƒ{u{ƒ||kd\{tttlltts{{t‹’Š””‹:97*)(£››¦§¨””‹’…‹£››ƒ||£››ŠŠ}‘ˆ}››”””‹£››²¬µ²¬µ²««£œ¥²¬µ™š¤£››”››ƒ||““““““µ¶·„„Д𔦧¨››”››”Š}ƒš””ƒ}ƒ”š”„Š}¦§¨ƒ}ƒ£››‹‹„Š}ƒ‚|u‹‹‹|‚z‹’Š[[Tkk]|‚z¦§¨“Œ”|‚z„Š}¨©´”š”{zm|„…›¢›£››‹„‹‚|uztl‹‹„‹„„””‹””‹Œ‹“ƒ‚u|‚z‹‹‹{||f]cttstll{{t‹’Škd\ƒ„„“Œ”’ŒŒtzl„„Šf]c\UZ‘Œ…{{t‚ut{tt|‚zekdƒ}ƒttsz‚lrg]‹…’’…‹ƒ‚uƒ||››”‹’Š””‹ƒ}ƒ‹„„‹„„{||‚utf]c‹„„{||lddkd\tll¦§¨sle‹’Š|‚zƒ||{||„„Šƒ„„{ttttsŠŠ}š””ƒ||„„Š‹‹‹£²’ŒŒŒ”•œ››ƒƒ|{u{|‚z|‚z]cdtts{{ƒ‹„„„„Šƒƒ|ƒ„„ƒ||tts’ŒŒ‹„„””‹‹’Štts”“›ult{||””‹ztl‚wl””‹zll„Š}{{t‹‹„œ¤¦£››ƒ„„\UZ””‹‹’Š{{t{{tš””››”ƒ‚n{||…‹‹‚wl“Œ”ldd‘Œ…{zm{u{mwzllbVUkd\lddslef]c[[Tredtlluzt{zm\[b‹„‹””‹j]\ƒ„„VTL|‚z{{tVTLlri{tt‘…„\UZek]…‹‹lld{{ƒ‹’Štt{ddclddUMRlld…„’ztl“““tt{ddcleklddf]c‚v{lksVZTf]ccbV{{ƒlldddc{{ƒult‚v‚‹‹‹lksfkk…‹‹|‚zuztœ¤¦lld\[[mtt{||ldd|‚ztt{ƒ}ƒllklddztf‹„„ttsƒƒ|lriVTL’ŒŒ:97*)(›”›¨©´«²«²««’…‹Š}|²²¬²¬µ‹‹„‘Œ…””‹¦§¨£œ¥²««²««£œ¥µ¶·¨©´‹‹‹Šƒ}„Š„‹‹„’…‹™š¤„Š„”››“Œ”››”ŠŠ}µ¶·›”›Š~‹‹’Ц§¨¨©´‹„‹‹„‹ŠŠ}””‹ƒ‚uƒ||dc\llkƒ||{{tiq]…„’|‚zuzt‹‹„tzlŒ‹“{{t‹‹‹‚|u‹„‹„Š}‘…„’…‹sleŠƒ}¤¤²²¬““““Œ”“““‹’Šttstlltsluzttzl”››d\\{ttlddrfkkd\{{tdc\{tt‚ut‹„„u{{tllrg]UTStll„Š„sleš””ult„„Šred‚|uš””‹’Š‹’Š{{tœ››|„…[[Trg]j]\tllldd{{ttsl{ttzll‚|u›¢›„Š„“Œ”‹‹‹ddclld‘Œ…“““’ŒŒƒ„„¦§¨{{ƒŒ‹“…„’{||{||””‹lekŒ”•‹’Š{{ƒlldultmtt{ttdc\„Š„‘Œ…{ttŠƒ}{ttuzt””‹œ¤¦£››‘…„‘Œ…{u{ƒ}ƒztl’ŒŒ””‹£››“““ŠŠ}“Œ”tsl„Š„ulttts|‚z„Š„ult‚utrg]{{t‚|uVTLSKJkd\|„…ƒ||{{tztlttsd\\ztltll””‹zllkd\f]clld[TT\UZultVTLsrelri]bZ{ttd\\:97{ttekdƒ‚ntt{ztljV[{u{VTL[[Tdc\‹‹‹ƒƒ|lek|„…”››{ttultŒ‹“lddŒ‹“{||lldŠ}|UMRbVUƒ}ƒmttFD;llkuztf]clri{{ƒult{tt[[TVZ[nv‚\[b]cd‹’Štsllkstsluztf]clddd\\lkstsllekƒ}ƒbVUzllƒ||tllƒƒ|ddcb[U‘Œ…:97*)(£››¦§¨‹‹„£››£œ¥¤¤»ÂÇœ¤¦–¢‹¤¤¤¤¤¤²««‘Œ…šŒ“““œ¤¦¦§¨”š”ƒ‚u{zmzllƒ}ƒ‹„‹ƒƒ|{||VZTœ›››¢›¨©´ŒŒš“““””‹£››‹‹‹ƒƒ|“Œ”‘Œ…sle‹‹„ult”š”tzl‚utƒƒ|u{{‹‹‹|„…]bZ[TT{{ƒƒ‚ukd\Œ”•””‹sletsl‘…„“““{zmŠŠ}”š”””‹‹‹„””‹„Š„{{tttsƒ}ƒœ››Œ”•{||ƒƒ|ddc{||SKJzllslesreUUY‹„‹‚|uƒƒ|UTS{ttVTLJHFƒƒ|{u{{{taWMmtttsl{u{Š}|œ››””‹‹‹‹…„’tzldc\uzt‚ut{||ƒ}ƒ“Œ”‘Œ…š””‹‹‹‹„‹{tt“““¦§¨ƒ}Šult‚ut„Š„ƒ}ƒ|„…‹„„™š¤””‹|„…lek”“›‹„‹Œ”•ƒ||’ŒŒ“““{{ƒllk‹‹„\[[uzttlllldlks‚|u’ŒŒ‹’Š””‹|‚z‹’Šƒ||“““”“›ƒ}ƒŠ}ƒƒƒ|‚|u””‹‹‹„tllƒ}ƒƒ‚u””‹ƒƒ||‚zƒ}ƒVTL‹‹„„‰vek]tll{zmaWMlldVTLkk]rg]\[[‹’Š‹‹‹‹„„{tttts{u{‚|u{{tultƒ||[TTultbVUSKJŠ}ƒdc\dc\‹„‹{||ldd[TTlrildddc\‚|u‹‹„ƒ||‚v{™š¤‹‹‹tzl{{t{{tƒ‚utllƒ„„{{t¦§¨{ttŒ‹“Šƒ}‚v{„Š„™š¤‹’Š‹„„Š~‹ƒ}ƒedkVZ[\UZVZTfkklldUUY{|||‚z]cdekd|„…|„…mttlekVZTlksuzt|„…u{{lek‹‹„ƒ„„f]clddultsleultƒ||ztl‹‹„{ttsre‹„„JHF74,ƒ}ƒ£››””‹£››£››£››››”››”››”£››‘ˆ}™‹†››”‘Œ…²««š””›”›‹’Š‹‹‹””‹””‹‹‹„ƒ||”››ƒ„„¦§¨„„е¶·¦§¨‚v{œ¤¦{{ƒ™š¤””‹¨©´{{t¨©´‹‹‹tsl¦§¨ƒ||‹‹„™š¤ƒƒ|{tttslddcMRKuztsre\UZ‹’Š‹„„‹’Šƒ||‹„„ƒƒ|‘…„‘…„Š}ƒ””‹‘Œ…ztl”“›ƒ‚uƒ„„lldVTLƒ||{u{ƒ}Š‹‹„lddf]c{{ƒrfkŠ~‹rr]››”ƒ}ƒ‚v{ƒ||Šƒ}ƒ||£››tzl‹’Š‹‹‹’ŒŒ”“›‹„„…‹‹…‹‹“Œ”””‹’ŒŒ|‚z{||“Œ”lksƒƒ|{{ƒ‚|uƒ„„ƒ||”“›‘}z‘Œ…š””ƒƒ|””‹{{tƒƒ|“Œ”tt{›”›‹‹„‚ut“““{tt’ŒŒ¦§¨›”›{{ƒ…„’|‚z…‹‹“Œ”’ŒŒ‹„‹|‚zƒ||‹‹„tt{mttƒƒ|””‹Œ‹“‚|u‹‹„{{tztlƒƒ|””‹‹’Šƒƒ|“Œ”lekƒ}ƒlri”š”rg]|‚z{ttddc‹„„‚wl|‚z”“›œ¤¦{ttŠŠ}dc\‚|uŠŠ}‚wlcbVkd\ztld\\tzl{{t‹‹„lldkd\tllllk››”£œ¥‹„„{ttsred\\””‹llklekŠ}ƒredkd\SKJekd\[[dc\\[[UTSsre\[b{{ƒdc\rfkult›¢›„Š„›¢›Œ”•””‹ultƒ}ƒllkƒ}ƒUMR\[[lldddc{||{u{ƒƒ|{{t{ttulttll›”›ƒ}Š|„…£œ¥|‚z|„…tt{ƒ}ƒ™š¤„Š„MRK{{ƒmtt{||tsl{||mtt|„…ttsƒ}ƒŒ‹“{{ƒUMRSKJred‹„„‹‹‹ƒƒ|lddd\\ttsƒ‚u””‹>B9:97‹„„Š}|‘ˆ}‘ˆ}Š}|£œ¥¤¤‚|u–¢‹£››²²¬£œ¥‹’Š£››£››“““œ¤¦ƒ„„‹‹‹”𔋒ВŒŒ””‹”š”””‹¦§¨£œ¥£œ¥”“›””‹ƒ||“““ƒ‚u””‹“““sre¦§¨‚|u{||Šƒ}tlllri‹‹„‘…„lritslult„„Šmtt|‚z„„Š‚|u‹„‹tsltslrfkƒ„„””‹{tt„Š}‹„‹ƒƒ|„Š}¦§¨kd\[[T|‚zkk]””‹„„ŠŠŠ}‹‹„redUMRbVUrfkƒ||VTL‹‹‹ldd{tt‹„‹‹„„‚ut‚|u‚ut[[TVTLb[Uztl£››f]clks‹„„‚utŠƒ}“““|‚z„„Šred‚|ulri””‹tsllekƒ„„Œ‹“zll”“›‹’Š‹„„ƒƒ||‚z{ttƒ}ƒ…‹‹‹„„ƒ||Œ‹“‹„„‹„„‹’Š™š¤|„…Œ”•›¢›ekd“““Š}|tts|„…”š”|„…tslŠ~‹Œ‹“œ¤¦{u{sle{{ƒyle’ŒŒƒ„„‚utŠ}|f]ctts‹„‹‹„‹lri››”‹„„–¢‹š””‹‹„‹‹„‹„„›¢›UTSd\\lldtsltzl””‹llk¢—{yfsle‚wltsltllƒƒ|ƒ„„lek‚|u‹uŠiWUslettsƒ„„sleƒ„„lekƒ||ult‹…’ult|„…VTLztlkk]Š}ƒ{||]bZƒ‚ulddtt{tts{zmbVUƒ}ƒf]c„„Šœ››|„…””‹Œ”•ttstslƒ„„{u{‹’Š„„ŠŠ}ƒlektll|‚zaWM£››lks{{ƒ{||‹…’¦§¨Œ‹“š””…‹‹ƒ}ƒfkk|„…\[[VZ[ult\[bttsekdf]c“““{{ƒ{||‹„‹„Š„ƒ„„srett{j]\‚|uj]\lddlddddc‹‹‹lri””‹JHF-1+“Œ”™‹†sle£››››”‘…„‰ƒv‚|u¢—‘ˆ}¤¤¤¤””‹{zm¨©´²¬µ£œ¥””‹¦§¨ƒƒ|””‹ztf„Š}{tt”›››¢›„Š„£››‹’Šš””¨©´“Œ”””‹Œ‹“[TT“~ˆ“Œ”‹’Š‹„„‚|utll[[Tr]Zrfkult{||œ¤¦„„Šllk”𔦧¨ƒ||UMR“Œ”ƒ}ƒŠƒ}ŠŠ}tllbVZ›”›{zm„Š}šŒtsl‹‹„kk]uzttslš””UTSmw¤¤\UZ{{ƒSKJ’ŒŒkd\ztfdc\‹‹‹{u{‚|u‚utƒ||Šƒ}“Œ”lld{tt|‚zŠ}|’ŒŒzll{{tƒ||’ŒŒ‘…„‘Œ…ekd\UZ{{ƒrg]{zmjcVlldultƒ||œ››››”ƒƒ|‹‹„‹‹‹„Š„lri“““›”›‹‹‹£œ¥‹„‹ƒ||{zmu{{tsltt{llkmttUUY…‹‹“Œ”redu{{llk|‚z…‹‹“““uzt›”›‹’Š“Œ”{||Š}|dc\ƒ}ƒ’…‹£››ƒ||lksf]credult””‹{{tsle¦§¨{ttœ¤¦“““’ŒŒrr]tt{‹…’ƒ„„‘Œ…ƒƒ|””‹ƒ||ƒƒ|{zm{{t‘Œ…‚wltllztlƒƒ|j]\VTLƒƒ|Šƒ}‰ƒvd\\ult‹‹„‹‹„ƒ„„tllultf]cuztlri{||[[Tztlf]c‹„‹‚utek]ekduzt{{ƒztltllult„„Ц§¨ƒƒ|lri””‹›¢›tt{ztl”“›lek{{t|‚z‹„„”››{tt“““Šƒ}“Œ”{{ƒŒ‹“”“›{{ƒ\[[|„…“Œ”ƒƒ|lks…‹’|„……‹‹u{{{{ƒVZTllkztlult{{t{{ƒƒ„„{{ƒttsƒƒ|tslƒ}ƒlddbVUbVU‹„„tts{{tuzttsl‰ƒvMRK*)(‚wl‘…„{tt£››››”””‹¤¤š””¢—’ŒŒ‹‹‹Šƒ}µ¶·¦§¨¦§¨²««²««“““œ››‘Œ…””‹””‹Šƒ}Œ”•‹‹„ƒ„„‹„„ƒ||ƒ||{{ƒ””‹››”“Œ”¦§¨ƒ}ƒ£œ¥ƒƒ|‹’Šlj¦§¨“Œ”sle‚utyflƒ||…‹’‹„‹{{ƒ„Š„¦§¨…‹‹‹„‹ŠŠ}Šƒ}‹„„Šƒ}|„…Š}ƒ‹‹‹²««››”¤¤ultuztztl\[[‚v‚””‹“Œ”””‹¦§¨„Š„‹„„lldddc{tt‚utƒ}Šttsƒ„„b[U£››lkstts£››bVUUMRj]\zllztfiWUƒ}ƒd\\Š}|‚utult››”ƒƒ|ƒ„„ldd‹’ŠtslSKJlddredƒ||ƒ„„œ››””‹i\VŠƒ}|‚z‹‹‹‚v{‹‹‹ƒ„„ƒ}ƒ“Œ”œ¤¦‹„„“““ƒ„„ƒ„„lldedktslƒ„„‚|uzllddclksztl‹…’›¢›‹’Šƒƒ|Šƒ}{u{“Œ”llk„Š„¦§¨kd\“~ˆllktslttsƒ}ƒd\\{{tlld‘Œ…llkƒ||‹‹‹ƒ||‚v{‚|u¦§¨”𔣛›£››{{ƒ‹„‹¤¤‹’Šƒƒ|‹‹‹sre””‹œ¤¦kd\‹’Š{u{¦§¨”“›lekƒ||uzt‹’Š{{tddcttsfkk‚v{ƒ}ƒƒ„„UTS{{tƒ||‘Œ…Š~‹”“›…‹‹„Š„‹‹„uzt{||‘ˆ}kd\“Œ”kd\›”›rg]lritzl“““„Š„uztŒ‹“›”›”“›z‚l””‹›¢›tts”“›‹„„{tttllŒ”•|„…{{ƒƒ||f]cddc‚utŒ‹“ƒ„„…‹’|„…lrif]cŒ”•ƒ}ƒ„„Šddcuztu{{tts[TTllk“Œ”{tt{u{bVU’ŒŒlek{ttldd””‹‹‹„{{t¦§¨JHF*)(zll‚wl‹„„’ŒŒ’ŒŒÃ¼¿¤¤””‹Ä¿’ŒŒ‚wlŠ}|‘…„¦§¨£››‹„‹£››¦§¨””‹””‹‹‹„‘Œ…Šƒ}‹‹‹››”‹’ЄЄ“Œ”œ››¦§¨¨©´£œ¥¨©´¦§¨‹…’ƒ}ƒ›”›““““Œ”””‹‘…„i\Vtslzll””‹llkƒ||tllekdlri‹’Šƒ}ƒœ››”››“Œ”ƒ‚u‹„„‹„„‹„„«²«¦§¨{{tslelldlrilldaWM[[Tj]\›”›ŠŠ}|‚zƒ„„dc\ult“Œ”‚utSKJ\[[VTLtllztl‚v{‹‹‹lekUMR{||\UZzllƒ‚usledc\{{ƒ{u{‚ut{tt‚|uƒ„„llkd\\ƒƒ|{ttŠƒ}{tt‹„„ƒ||’ŒŒƒƒ|‘…„””‹‹„„””‹tts‹„„‹„‹ƒ„„fkk‚v{ƒ„„›”›tll‹„‹leklks„„Š|‚z|„…ƒ||’ŒŒult{{ƒult{||ƒ„„Œ”•{ttlldƒ}ŠlddUTStsl‹„„Šƒ}ƒ}ƒ{ttztff]cUTSd\\lriƒƒ|tsllldVTL[[Tsre{u{lldtslddc{ttŠƒ}slekd\llkƒ‚u‹’Š””‹„Š}{ttœ¤¦{{t“““ƒ}ƒtsl„Š}‰|vkk]‹‹‹llkuztultƒ}ƒultldd“Œ”{ttttstts{zmtslƒ||’ŒŒœ¤¦ƒ„„ƒƒ|lkstzllks‹‹‹lekdc\‚utsleVTLlekƒƒ|{||b[U{u{ƒ}ƒ|„…‹’Šsle{||tll{{ƒƒƒ|‰|vtll{{ƒ†~‘“““tslldd{tt‹‹‹{{ƒ\[[mtt|„…lks“Œ”„Š„›”›™š¤„„Š|‚z{{ƒ\[[‹„‹…‹‹‘Œ…“Œ”š””slered{u{‹‹„ƒ„„„Š„„Š„ƒƒ|£››:97*)(’ŒŒšŒšŒš””£››¤¤‹‹„¼À¯¤¤²²¬œ››£››²««£››²¬µ¨©´²²¬µ¶·›¢›””‹š””Š}ƒŠŠ}“““¦§¨¦§¨ƒ}ƒ£››£››£œ¥Š}ƒ£››‹„‹””‹ult{ttƒ}ƒ{{tzll‹‹„›”›‘ˆ}slezllUTSVTLtsltts{||‹‹„‹’Šœ››{u{ƒ„„¦§¨‘Œ…Œ”•{tt¦§¨¦§¨„Š}””‹‚uttsl{||‚|u‚|uUTSredrfkuztdc\VTLƒ}ƒ{tt£œ¥””‹VTLƒ}ƒd\\›”›uztyfd‚|udc\Šutƒ||Š}|f]c{ttƒƒ|ttsUTS’ŒŒƒ‚u{||kd\Œ‹“ƒƒ|ƒ„„‹„„sleŠƒ}‹‹‹{tt‹„‹œ››Šƒ}šŒ’ŒŒƒ||‹‹„‹’Šƒ||’ŒŒ…‹‹Šƒ}ƒ}ƒlektsldc\{zmtt{{{ƒtt{ƒƒ|{{ƒƒ||“““™š¤bVZƒ„„”››{||‹‹‹{tttts”“›d\\[TT[[T‹„„‹‹„ulttllŠ~‹tll{u{ƒ||Šƒ}VTLƒƒ|››”ztl…‹‹{||aWMbVUVTLSKJcbVlek[[TaWMMRKrg]››”{||””‹ŠŠ}‹„„d\\‚v{Šƒ}‹„„{tt{{tVTLƒ‚u„Š„¦§¨b[U{tt\UZ{{tUTSkd\{||ult{{ttslb[Uult‹„‹{{t™š¤|„…{{tbVUŠƒ}lek\UZ‹„‹zll›¢›£œ¥ƒƒ|tll]bZ‹„‹‹‹‹{{tŒ”•š””Œ‹“ƒ„„Œ‹“””‹ƒ„„¦§¨„„Š{u{tts|‚zƒ}ƒttsf]c{{ƒ\[[\[b]cd]cd\[b…‹‹{u{{{ƒ{{ƒuzt|„…tslu{{‹‹‹{{ƒ’ŒŒ“Œ”‚utztlkd\ztllld‹‹„‹‹„[[T¦§¨D;9:97””‹£››‚wl™…‹„„””‹¦§¨””‹¤¤“““¦§¨¤¤²««£››²««£››¦§¨¦§¨””‹””‹™‹†’ŒŒ„„Šƒƒ|””‹¦§¨Œ”•£œ¥²««¨©´£››¦§¨£››’ŒŒ‚utult{tt‹’Š£››‘ˆ}›”›‚|u››”››”Œ”•lld‚|ubVZuzt„Š}{yfŠƒ}lri£››ƒ}ƒŠƒ}ƒ„„ttsƒ‚uš””ƒƒ|‘Œ…ƒƒ|ztl¦§¨‹‹„‚|usre“Œ”lddkk]kd\[[T[[T{tt‚|ub[Uredƒ}ƒult‚v{|„…Š}|ƒ||Œ”•f]cr]Zult’ŒŒcbVjcV{||‹‹„ultred‹‹‹{{tlldrfklrillk|‚z‹„„‹‹‹“Œ”rfkƒ„„„Š}Š}|¦§¨ƒ||ƒƒ|„Š}tll‹‹‹u{{’ŒŒ‹„„edkœ››|‚zlld|„…‚utddcmtt…‹‹ƒ||Š~‹jV[edkzll“Œ”lri…‹‹‹’Šu{{tt{‹‹„sleuzt¤¤‚|uultš””{u{‹‹‹’ŒŒrg]¤¤mtt|‚zƒ‚u{tt[TTbVUb[U[TT3+*kd\kd\ek]cbVlld‘ˆ}ztl‹„„‘ˆ}{ttƒƒ|‚utŒ‹“tsl””‹“Œ”VTLtsl‚|u|‚zŒ”•{tt‚v{“““\[[‹„‹dc\b[Uddcb[Ub[U””‹lld\[[{u{£››lldultllddc\tsllekllkŠ~‹sleuztlritsl””‹u{{ultlddƒ„„„‰vŠƒ}Š}|Š}|Œ”•››”£œ¥{u{‹„‹f]cllk›¢›ƒ}ƒlddlekmttmttdc\tt{mttedktll“Œ”|„…ƒ}ƒlri\[[{{tuztŒ‹“‚utslezll‹„„’ŒŒkd\red{ttdc\uztlldµ¶·UMR:97‘ˆ}ljljŠƒ}Šƒ}sle‹„„‘ˆ}›¢›‘Œ…””‹£››£››²¬µµ¶·šŒ¦§¨¦§¨””‹””‹›¢›d\\|‚ztsltzl‹‹‹”“›““““““‹„„£œ¥£››””‹‚|u‰v|””‹¦§¨ƒƒ|”š”‘Œ…„„Šztl‹‹„tts‚v{“““””‹{{ƒ”“›ƒ„„uzt{{ƒlld{tt²¬µ””‹dc\{{t²««“Œ”””‹ƒƒ|”š”››”lldrfk{||ƒ||Š}|ƒ„„‚|ulldlldbVU{tt‚v{yleek]{ttddcƒ||]bZtsl‹‹„‹„‹“Œ”{zmldd‚utdc\aWMddcttsredš””tll››”{{tzll{{tldd‚ut‘Œ…‹‹„£››b[U„Š}ƒ„„‹‹„‹‹‹uzt‘ˆ}„Š„{ttsle\[[ƒ||llktts‹„„{||‹’Šlri…„’ƒ„„fkk|„…rg]ult‚|ullk{||llkƒ„„|„…‹‹‹|‚ztll„Š„kd\llk¤¤””‹£œ¥’ŒŒuzt‘…„Œ”•f]c{{ttsl‹’Šsle|‚ztllultVTLj]\{ttrfk‚|u“““‹’Šb[U‰ƒv“““šŒVTL‚|ulld{{t‹„„dc\‹‹‹ƒƒ|uzttslsledkV‹‹„ƒ‚uƒƒ|llk{tt‚v{tsl’ŒŒrg]lldVTLlri‚v‚tts¦§¨””‹‹‹„llkb[Ullkttsrfk{u{›”›£››llk‹‹„”››|‚zƒƒ|{{ƒd\\ldd”š”‚|u’ŒŒ‘…„”“›lriƒ‚u‹‹‹ultf]cldd|„…tt{ddctt{{{ƒedklri\[bu{{ultd\\lksek]lkslri\[[{ttƒ„„ƒ}ƒ‹„‹Š}|tlllddi\Vlri‚wlj]\ƒƒ|ƒƒ|tzl¤¤VTLJHF‚wl‰ƒv“~ˆŠ}|‘…„””‹µ¶·£œ¥š””¦§¨²²¬²««›”›£œ¥Â¾Æ²««²««²¬µ‘…„‹„„””‹tts„Š}›¢›‹‹„›¢›‹‹‹¦§¨¦§¨£œ¥¦§¨£››””‹œ¤¦¢—Šƒ}’ŒŒ›¢›››”‹„„ttsldd‘Œ…„Š„tll{{ƒ‚ut“““ult…‹‹„Š„‹„„lrilekƒ‚u£››{{tƒ||’ŒŒš””””‹ttslriultttsŠƒ}£œ¥””‹’ŒŒ‹„„ƒ‚u›¢›kk]SKJ“““j]\‘Œ…ldd„„Š[TTƒ}ƒ|‚ztt{ƒ||zllbVUVTLbVZ{tt{tt“““{{t]bZyleš””“Œ”ƒ||„„Šd\\|„…{{t‹‹‹‚|u‘Œ…Š}ƒ””‹‹’Š‹„„sletsl‹„„„Š„tll””‹tll|„…ztllek{u{{tt{{tœ¤¦Œ‹“ttsttsu{{ult›”›ttstllulttt{ddc…‹‹llkulttlltt{ƒƒ|””‹ulttsl[TTtllœ››tslƒ||›”›š””‹‹„ultztlkd\‚|ullk‘Œ…‘Œ…kk]”››‘…„UMR„Š„„Š}”š”srezll‚|uyleŠ}ƒSKJllk{ttsreVTLƒ‚uuzt{{t£››ztl”š”ƒ„„„Š„‹‹‹\[[{tt{ttŠ}|j]\{ttƒƒ|sletllzllƒ}ƒ‹„„„Š}LKRuzt‚utŒ‹“ljedk‚v{‚|uttslridc\””‹‚|u”“›{tt‚|utsl‹’Š”“›¦§¨‹„‹tslŠ~‹lksttsf]cztl]cd[TTtzl{||mtt{{ƒu{{‹’ŠUUY]cdkd\uztƒƒ|””‹lriUTS{||d\\{tt{u{‹„„yleyleyleJHFkd\red{{t{{tŠƒ}¤¤JHF*)( ””‹£››‚wl’ŒŒ“““¦§¨›¢›¢—²««Ã¼¿²¬µ²««£œ¥£œ¥Ã¼¿²¬µ””‹ƒ||“Œ””š”””‹¦§¨¤¤””‹›¢›“Œ”””‹›¢›ƒƒ|Œ”•Š}|¤¤ult“Œ”š””””‹‹‹„œ››ƒƒ|rfk””‹²««‹„„jcV{{t“Œ”‹‹‹ldd””‹”š”ƒ„„{||ƒ„„|‚z’ŒŒƒ„„ult‹‹‹j]\””‹lldldd{{tcbV{tt„„ЄЄ‚wl‹„„””‹{{tcbVSKJš””‚|ukd\j]\lld’ŒŒ{ttœ››tllƒ}ƒ™…kd\tsl‚ut¤¤tyg””‹|‚zdc\‚uttllƒ}ƒšŒtll{{t‹’Šœ¤¦ƒ„„’ŒŒŠƒ}f]csle‹„„uztŠƒ}ƒƒ|ƒƒ|rg]b[U{u{{u{lld{tt{tttts{||ƒƒ|„Š„„Š„ƒ}Š‹‹‹ƒƒ|“““ldd›”›{u{u{{””‹“““„Š„Œ”•tlllekŒ”•œ››””‹{{ƒ„Š„”“›{tt‘…„ƒƒ|š””‚v{Š}|ƒ||ztl{{tsleVTL[[Tzll””‹ŠŠ}¦§¨£œ¥‘}z“Œ”›¢›¦§¨ƒƒ|’ŒŒŠ}|’ŒŒredtsldc\‹‹„]bZldd¤¤ƒ„„{||”››ek]mtt“““|„…rfkzllultƒ}ƒ“Œ”‹„„kd\tslcbV„Š}edktll’ŒŒš””{ttuzt{{ƒd\\VTLbVUlrib[Uldddc\dc\„Š}ŠŠ}¨©´¨©´‚|uztl””‹“Œ”¤¤”“›ƒ„„{tt{{tf]ctsl{tt|‚zmttVTLdc\|„…{{ƒ{{ƒœ¤¦tt{ekdddcƒ„„{{t{||ƒƒ|d\\uztlldtlltllƒ||tllztlllkr]Zƒ}ƒŠ}ƒŠƒ}kk]{{t²²¬FD;74,¤¤“~ˆ’‘~‘ˆ}£››¦§¨š””£››£››¤¤£››¤¤¦§¨²¬µš””››”›”›œ››¦§¨£œ¥‹’Š£œ¥‹‹‹œ¤¦µ¶·””‹ƒ||‹‹„‚|u‹„„“““œ››{{t‹‹„›”›tsl‘ˆ}sre‹’Š‹‹„tts“Œ”‘ˆ}Œ‹“bVUddc™š¤Š}ƒlek„„Š‘Œ…‹‹‹|„…ƒ||””‹‚|u„„Šƒ„„››”™š¤””‹“Œ”‹„„{{ttsl£››ƒ}ƒ|‚z‚|u‹…’¢“‹‹‹[[Tj]\\[[tts‚|uƒƒ|¦§¨mtt“Œ”ult‹’ŠbVUŠƒ}VTLcbV[TTŠƒ}rfkekd\[[uzt‹‹‹j]\MRKultrg]sle{{t‹’Šƒ„„{tt{||’ŒŒtllƒ||tts‹„„ƒ||‹‹„|‚zj]\yle“Œ”“““‹„‹ƒ||Œ”•“““ƒ„„|‚z¨©´™š¤|„…llk”›››”›“““|‚z{u{””‹¦§¨d\\“““ƒƒ|ult{||ƒ„„|‚z…‹‹„Š„ƒ}ƒŠ}|‹‹„[TTƒ||‹‹„››”ƒ„„ztl{zmrg]d\\ekdztl‚wltslƒ}ƒŒ‹“ƒ||’ŒŒ‹‹„™‹†Šƒ}‚ut‹„‹™‹†Šƒ}”“›‚utdc\£››kk]¤¤„Š}””‹{{tƒ||ƒƒ|ultlekkk]{ttsleŠ}|yleƒ||[[Tek]tzltllultult‚utb[UŒ‹“lri\[[bVZ‚wld\\””‹sleultƒ„„ztl‹’Š’ŒŒ™š¤{u{ƒ}ƒ{zm‚uttll‘ˆ}¦§¨”“›™š¤„Š„ƒ„„‚|uƒƒ|tsl{{tMRK‹‹‹ƒ„„‹‹„{||{||lri{||””‹lddekd“Œ”d\\f]cddc‹‹„{tt‘…„‘ˆ}{ttcbV‹‹‹‚|u{{tšŒ‚|u‚|u‹’Ц§¨VTL-1+””‹‹„„‘ˆ}’…‹£œ¥¦§¨›¢›£››œ››Šƒ}¢—£››£››²««£œ¥²««””‹£œ¥¦§¨¢—‹„‹ƒ„„uzt{{t››”µ¶·Œ”•‘ˆ}“Œ”Œ‹“”››“Œ”¦§¨„Š}‹‹‹‘Œ…llkdc\ƒ‚uztfsre’ŒŒrg]Œ‹“lddttsultƒ‚urfkŠ}ƒ{{t{ttƒ„„‘Œ…‹„„››”{||‹„„ƒ‚u¨©´š””{{ƒšŒ‹‹„tzllddultsleŠƒ}‹„‹Š}ƒttsVTLrfkf]c‚v{ƒƒ|lri“Œ”{||{||lld‚|u’ŒŒztlkd\ƒ„„ztl‚|u[TTdc\‚|utsltllbVZƒ||Š}|tslsre|‚z¦§¨ƒƒ|cbVkk]{||{tt›¢›{||tslƒ„„‹‹„¤¤‚|u“““ŒŒštts{||{ttuzt\[[ŒŒš›¢›‹’Šƒƒ|Œ”•lks™š¤£œ¥“Œ”ztl“Œ”“““‚|uekd‹„„{ttƒ||f]cŠ}ƒdc\{||lldmttrfkldd{ttŠ}ƒ‹‹„ƒƒ|zllŠ}|ztltllƒ||‹„„{{t{tt{{tƒƒ|“““‚|uš””kd\kk]™š¤™š¤tsl‰v|red””‹ƒ}ƒ‚|u””‹tll¦§¨ztlddclri|‚zŒŒš{||uztŠƒ}{ttzll“““‹‹„ztlddcllduzt{{ttll{ttŠ}|zllultldd{u{lldr]g{{ƒsleztl{{ƒuzt£››tsl‚|uœ¤¦™š¤{||‰|vƒƒ|¨©´²««{u{”“›“Œ”{u{{u{rfklri|‚zult‹’Š››”Œ”•“““ttsƒ}ƒVZ[ƒ„„‹„‹|‚zlritts{|||‚z]bZtslsleš””ztlŠ}|‰|vdc\llkŠ}|‚ut››”{tt|‚z¦§¨[[T*)(tll‚wl‘…„ƒ}ƒ’ŒŒ››”“Œ”›”›¦§¨£››£››£››“Œ”ü¿²««¦§¨£œ¥£››£œ¥”››£››Š}ƒŠŠ}š””‹’ŠŒ‹“Š}ƒª³·’…‹‹„„””‹ƒƒ|””‹ƒ„„{ttŠ}ƒztf„Š„””‹¤¤{zm“““ƒ‚uultb[UlldVTLrg]ultzlltsltllult£››””‹slef]cƒ}ƒ|‚z‹„„””‹œ››llkƒ„„‘…„{{t£œ¥ztlbVUŠ}ƒtll\UZJHF[TTtllllk[TTldd{u{f]c{tt{||sleulti\VVTLVTLkd\ztlekdcbVcbVƒ„„Œ‹“ttstlllddtll’ŒŒ‚ut‹’Š‹’ŠŠƒ}lddŠƒ}ƒ}ƒ‹„‹tts””‹š””šŒ‘Œ…ultƒ||{ttƒƒ|f]c{{t{{ƒŠƒ}{{ƒ|‚znv‚{u{‹‹‹‹’Š…„’›”›”“›„„ŠŒ‹“››”„Š„…‹‹ƒ||ult¨©´Œ”•{u{‹‹„ƒƒ|„Š}tts‹„‹ƒƒ|rg]{ttƒƒ|jcVSKJjcV{{tf]c£››{zmtslƒ„„tzltll\UZzllƒ||‘Œ…ŠŠ}ult‚v{‚|ušŒŠ}|‹‹„“““ƒ||ƒ}ƒ{||zllf]cdc\tsl{{ƒ‚|uƒƒ|[[T‹‹„Š}ƒ’…‹…‹‹{||Š}|ek]‰‘~|„…slef]cmttzlltllbVZSKJ{||ƒ||{{ƒ“Œ”{{t‹„„{||„Š„”𔛢›‹„„\UZ‚v{{tt¨©´””‹‹„„””‹lek‚utztlƒ„„„„Š{ttŠƒ}VTLŠƒ}‹’ЄЄ‘…„{{t„„Šu{{ultult{ttŒ‹“„Š„“Œ”„Š„‹’Šuzt|‚zƒ}ƒ‘…„{ttb[U‚|utllyle{tt‚ut‰ƒvŠŠ}sre¦§¨D;9*)(Š}|š””“Œ”‰|v¦§¨ŠŠ}²¬µ¤¤²²¬£››””‹¤¤›”›¦§¨šŒšŒ“~ˆ£››œ››…‹‹sre‹‹„Šƒ}‘…„¦§¨›¢›šŒ”š”Š}ƒƒ||ƒƒ|‹‹„‹„„ƒ}ƒ”“›„Š„‹‹‹ƒƒ|z‚ltslŠƒ}‹„„””‹tt{‚v{‹‹„Šƒ}VTLultult‘Œ…‹„„”››“““›”›‹„„tt{“““ƒƒ|›¢›‹’Šf]c‹‹„{||‹‹„kd\ƒ}ƒsrebVUbVUult{u{\[[sleultlldƒ||b[U”“›“““Œ‹“ƒ„„tslbVUSKJFD;]bZSKJsrekd\[[Tlddd\\‹„„ztltzlƒ„„”š”ttskk]sle‚ut‚|u{tt™š¤”››œ››“Œ”‘…„¦§¨‚v‚ƒ„„£››‹„‹‹„‹ztl‹„‹Œ”•™š¤ƒ|||‚z|‚zlksf]ctt{fkklksUMRŒ”•‹‹„Š}ƒ”››tslœ››œ¤¦£››“Œ”{{ƒ‹‹‹”“›lldŒ”•›”›lekƒ‚uƒ||ƒ||lldsletslb[Uztfldd{tt‘Œ…Œ”•{{t{{tlldultcbV‚ut‚|u‚|ušŒ£››ultŠ}ƒj]\{tttts‰|vrg]tll{ttd\\„Š„uzt””‹{{tuztrg]bVZlddlddtts‚|u’…‹ƒ}ƒMRK|„…tslƒ„„rfk‚v{UMRbVZƒ„„‹‹„ƒ}ŠŠ}ƒƒƒ|{{ƒtll{tt„Š}œ››sre‹„„tts‹‹‹Œ‹““““Šƒ}f]cŠutŠ}|{{t𔔙𤓓“dc\‹‹‹dc\ƒ}ƒƒ||ƒƒ|ƒƒ|„„Šddcf]cf]c‹‹‹{||“Œ”‘Œ…{{ƒŒ”•‚utƒ„„ŠŠ}‹‹‹zlltllredj]\‚|utslj]\redƒ||‹‹„ztl›¢›JHF*)(™š¤’‘~²««‚ut‹„‹£››²²¬£››””‹””‹£››Ã¼¿””‹“““ü¿””‹²««›”›‹‹‹”“››¢›£››¦§¨š””””‹¤¤tslšŒ‹‹„“““ƒ||ztl‘Œ…uztš””Œ‹“””‹“““ztl‚utkd\rfk””‹ldd‹‹‹‹„‹’ŒŒ‹‹‹’ŒŒ£››‚utJHFuzt{||””‹£››‹„„›”›””‹{||uztŒ‹“”››tzl£œ¥{{t{{ƒlrizllrg]{||lddlrijcVtts‚v{””‹ultf]cSKJ”“›tll{||Š}|{{t{tt[[TUTSVTLj]\llklddlkstts‚v‚š””Š}ƒƒ„„{||r]Zekdddc‹‹„””‹ƒ„„ƒƒ|‹„‹ƒ||ztl’…‹{||ƒ||Š}ƒj]\{tt™š¤llkuzt{{ƒ’ŒŒ„„Š|„…u{{{||{{ƒlksedk{u{”š”ƒ„„ŒŒštsl|‚z|‚ztts“Œ”¦§¨“Œ”lks{{tkd\lksttsedk{tt{u{{{tultllddc\redred‚ut{tt””‹tts¦§¨ƒ||ttstllkd\yfd””‹zll£››‚|uŒ‹“ultdc\d\\””‹‹„„‹„„{tt{u{Š}ƒ„Š„ldd{{ttts‹„‹”››‰v|lddllk{ttŠ}ƒ‹‹„‚|usre{||tsllddlek‚|uUMRultbVZtts[[T{u{ƒ||tslƒƒ|tllƒ„„“Œ”‹‹„’ŒŒ‹„„ultƒ„„ƒ||š””ultbVU™š¤{{t‹„‹Œ”•d\\[TT|„…tzlšŒ”š”fkkŠƒ}sre™š¤Œ‹“{||““““““lri‚|uldd…‹‹{||‹‹‹{||ƒ||Š}|{u{‚wl{zmtlld\\‚ut‚wl‰v|rg]rg]¤¤FD;74,””‹‘}z£››j]\’ŒŒ¤¤Ã¼¿£œ¥²««™‹†²¬µ‹„„£œ¥œ››””‹£››šŒ|‚z‹„„””‹‰ƒvŠƒ}””‹¤¤¦§¨µ¶·››”’ŒŒƒ||{{tsle””‹››”š””’ŒŒllk‹‹„{{t›¢›ƒƒ|ƒƒ|{tt‹‹„tt{{tttts{zmztlƒ||£œ¥tllƒ||‹„„”“›œ››‹’Šƒ}ƒƒ||‹‹‹’ŒŒ|‚zlddtts[[T‹‹‹{{tƒ„„tzlkd\{tt{u{[TTd\\[TT‹„‹ƒ}Š{tt{{tŒ‹“ddc™š¤ƒ„„[TTd\\ekdrg]kk]bVZllkldd[TTtzllritllš””‹‹„“Œ”[[Td\\b[U{{t{tt›¢›{{t‹‹„‹„‹ttsŠ}|Š}ƒƒ}ƒ‹„„ƒƒ|‹„„{u{‹’Šƒ||“Œ”ƒ„„u{{{{tƒ„„llkƒ„„tt{{{ƒ…‹‹|„…“Œ””››„Š„ƒ}ƒtts„Š„„Š}ƒƒ|ƒ„„‚v‚””‹tt{Š}|{u{tll{u{{u{ƒ}ƒƒ||›”›››”llkdc\red‘}zf]cƒ}ƒ’ŒŒ{||‹’Š‚ut{{tUTS‚|utllsre‹‹‹‘Œ…ylettsŠƒ}‘Œ…ƒƒ|yfd{{tƒ||sleyflƒ}ƒŒ‹“{{tŒ”•‚ut‹‹„ƒ}ƒ{{ƒƒ||‚v{{u{Šƒ}“Œ”‚v{„Š„‹‹‹VTL‚v‚{{ƒ””‹edktllf]c‹‹„[[T‹„‹››”slelddllk””‹››”{zm‹„„“Œ”””‹u{{¦§¨””‹ultztlrg]{zm{{t|„…„„Štll{{t|„…²««…‹‹]bZ‹‹‹…‹‹tt{”“›|‚zlek|„…Œ”•ŠŠ}ddclekd\\kd\llkddc{tt‹„„Š}|uztldd\UZf]cŠ}|‘Œ…‰ƒv‹„„””‹>B93+*ƒ||‘…„£››£››”“›µ¶·Ã¼¿š””””‹‘ˆ}¤¤¦§¨£››”“›²««š””ª³·Š}||‚z¤¤›¢›£››¦§¨‹‹„”“›””‹¦§¨¦§¨œ¤¦tt{ƒ‚u‹„„‰‘~’ŒŒ‘…„’ŒŒ‘Œ…‹‹‹››”””‹lld{ttkd\tts‘…„{ttlldj]\tll’ŒŒ£››ƒ„„‚v{f]c‹„„tsl{tt‹„„ƒ„„{ttrg]ddctllƒƒ|šŒ”“›ƒ„„”š”Š}|’ŒŒ›”›llkiWU]bZtlluztœ¤¦tsl{{t{||ultlekdc\Š}|JHF{||ƒƒ|ttsƒ„„rfktllJHF{||‹‹‹‚v{srellkddckd\b[Utslslekk]d\\{||ƒƒ|lekyleztl’…‹Šƒ}ddctts›”›„Š}Œ”•‹‹‹‹„„u{{uzt|‚zƒ„„Œ”•‹„‹œ¤¦…„’…‹’™š¤uztddc\[[|‚zƒƒ|„Š„‹„„ƒ}ƒ\[bf]clks“Œ”lddƒ||ƒ}ƒœ¤¦ƒ}ŠŒ‹“…‹‹œ¤¦“Œ”‘Œ…„Š}œ››ƒƒ|j]\‹‹‹lld””‹i\V{{tzllkd\ldd„Š}ƒƒ|i\Vƒ||llktlllld{||llkŠ}|b[UbVU‚utbVZ‹„‹{ttsre‹’Šttszllƒ}ƒult‹„‹ƒ||{ttŠŠ}lek{{tƒ}ƒ[[Tddcttstlledktll{{ƒƒƒ|¦§¨Œ‹“Š}ƒsrecbV{{tsre™š¤u{{kk]‘Œ…ƒ„„Œ”•£››£œ¥tll‰|vzll‚|uƒ||ƒ||ult{ttƒƒ|‹‹‹‹’ЄЄ‹’е¶·{||{||Œ‹“Œ”•“““ƒ‚n{u{Šƒ}ultƒƒ|tsld\\rfk„Š„Š}|{zm‹„„tll{zmŠ}|zllyleztlkd\kd\””‹:97*)(ƒ„„‹„„Šƒ}¦§¨¤¤²¬µ£››£œ¥š””²¬µ ¦§¨¦§¨£œ¥£››’…‹šŒ›¢›ƒ‚uƒƒ|””‹››”””‹£››«²«¦§¨£››ƒ„„’ŒŒ‹‹„ƒ||’ŒŒztf{u{yfd‚ut”𔄄Ћ‹„£››{zm‹„„ƒ‚ulddšŒ‹‹‹tsl‚v{ƒ}ƒœ››Šƒ}…‹‹Š}ƒ’ŒŒllksle{{ƒ…‹‹„Š„ƒƒ|ƒ‚uldd„Š„ŠŠ}››”Œ”•‹‹„tzl‚|uddcƒ„„lriƒƒ|FD;d\\u{{]bZllkd\\rfklddlddsrezllSKJŠ}ƒtsl|‚zsleVTLtsldc\ƒƒ|lddsleVTLzll‹‹„lld’…‹››”rg]sre‹‹‹ldd‹„„ultd\\{u{ƒ||‹„„{ttŒ‹“‚|uztlƒ||‹„‹‹„‹mttllk|„…{{ƒœ¤¦|„……‹’ƒ}ƒŒ”•Œ‹“ƒ||œ¤¦ddcŒ‹“lriuzt‹‹„{ttlkslekUUY‹„‹ƒ}Šƒ||‹„‹‹„„kk]ldddc\‹’Šƒ}ƒ‹„„š””‘Œ…š””’…‹tllsrekd\bVZultlld‚v{bVZbVZœ››lddlriŠ~‹kd\‚v‚Šƒ}{{ƒƒƒ|Š}|f]c›”›lddultœ››ldd{||llkd\\kk]‹„„{u{‹‹„‚v{ƒ||ƒ||ƒƒ|{||tsl{u{‹‹‹VTL{zmbVUddctts„„Š™š¤lriztltllUTSš”””“›””‹››”ulttsl…‹‹š…ަ§¨Œ‹“‰|vttsrg]ƒ||tsl‚v‚ƒ||›¢›kd\[[T„„Š‹’Ц§¨£››£››œ¤¦Œ”•“Œ”‹‹‹{{ƒ’ŒŒtllƒ„„ƒ„„ƒƒ|lekƒ||{tt‰|v‚utztfzllsle‹„„ƒ||kd\‚wl‹‹„¤¤:97*)(ldd‹„‹Šutš””œ›››”›š””£››‘ˆ}¢“‘ˆ}£››™š¤¦§¨£››µ¶·£››¦§¨{{tƒ‚u¦§¨””‹‘Œ…‚ut¤¤”š”œ››‚|uƒ||ƒ}Ф¤””‹š””tts‚wl‚v{{{t“““‚|u‹‹„›¢›“Œ”‚|u‹„„’ŒŒ„Є𔔔”‹“Œ”Š}|sle{||f]crfk“““{{tƒ||ƒ}ƒ«²«‹‹‹zll‘Œ…{||‹’Ц§¨›¢›Œ”•d\\rg]redldd…‹‹ztlllkf]cŠ}ƒrfk[[Ttll‘ˆ}tt{j]\VTLkk]lldslettslridc\ƒ||tll„Š}dc\‹„‹tyg|„…ztllddj]\mtt{zm‚ut””‹{{t‹’Šš””ƒ||f]c‚v{tlllddd\\’ŒŒ‹„„ƒ}ƒŒ‹“ƒ„„›”›ƒ„„ƒ}ƒ„Š„ekdŒŒš|„……‹‹{{ƒtt{“““„„Š|‚z{u{””‹‹’Š‹‹‹„Š„tlllek{||Š~‹{{ƒ“Œ”‹„‹™š¤{{tllkleksle›¢›””‹|‚z‹„„sle‚|u{ttllklriredkk]VZTzllredbVZ[[T{{t{ttƒ}ƒultddc{ttƒƒ|””‹Šutredrfk‘…„{u{ƒ„„{{ƒ{||ŠŠ}lriztl]bZ\[[‚ut‘Œ…“Œ”VTLƒƒ|lld“Œ”lriddctsl{zm[[Tf]c„„Štsl{ttƒ}ƒš””””‹‹„„‚v{“Œ”„„Š£››‘…„lek{||bVZ‹„‹‘Œ…™š¤Šƒ}{u{ztl‹„„{{tš””kd\‹‹„uztuzt|‚zƒƒ|š””{{ƒ“Œ”|„…|‚z…‹‹œ››tt{‚ut{||{{t{zm‹„‹lldlldd\\sletll‚|u‘…„zllldd‘…„Š}|yleƒƒ|Šƒ}>B9&&‹‹‹£œ¥“Œ”‹‹‹›”››”›››”£œ¥¢“¦§¨Š~‹{tt“Œ”¦§¨£œ¥²««£›››¢›ŠŠ}‘Œ…š””ƒ‚u£››œ¤¦«²«{{tœ››ƒƒ|ƒ||¦§¨‚ut¤¤””‹’ŒŒrr]redtsl{u{tsl£œ¥ŠŠ}ztl¤¤Œ”•’ŒŒ‹’ŠŠ}|’ŒŒ{{tŠƒ}{{t{||‹‹„zllš””sle“““‹„„Œ”•ƒƒ|tllŠƒ}‹‹‹Šƒ}ultƒ„„{tttllsle’ŒŒultllksretts‹‹‹„„Škd\\[[tllf]c‹„‹sreztl‹„„d\\tts”𔋄‹””‹tllŠƒ}{{tVTLUTS[[Tlldztlkd\b[U{||ŠŠ}kk]ekduztƒ||kd\lddlkszllƒ||“““{ttkd\‘Œ…‹’Šu{{“Œ”{{ƒ””‹ddcek]lks|„…”››…‹’mtt‹„‹Œ‹“|„…edkƒ}ƒ‹‹‹|„…ƒƒ|‹‹‹š””{u{„„Š““““Œ”ƒ}ƒ£œ¥ddc{||‘Œ…ƒ||“Œ”””‹“~ˆcbVkk]tllkd\“Œ”f]clrib[U‹‹‹ƒ||”››j]\ztf{||{u{{zmƒ||ldd{ttƒƒ|‹‹‹ƒ‚ud\\Š}ƒƒ||rfkŠƒ}‚|utslttsœ››‹’Š{||tslkk]ƒ}ƒ‚ut‹‹„{ttredsrej]\‹‹„ttsUTS”š”tts’ŒŒ{u{{||£œ¥“Œ”‹„„¤¤{tt›”›’ŒŒ””‹Š~‹ultŠ}|uzttts™š¤zll{||‚|u“~ˆ{zmztlƒƒ|£œ¥zll””‹srelriƒ}ƒ‹„„Œ”•¨©´¦§¨|‚zekd“““‹’Šekdslellkldd‚|u‚|uƒƒ|tzl“Œ”‚|u{zmƒƒ|‘Œ…{tt‘ˆ}‰|vredkk]i\V””‹D;9*)(››”œ¤¦””‹{{t“““œ››¦§¨“Œ”‰|v£œ¥””‹‘…„£››£œ¥£œ¥“Œ”£››|„…‹‹„ƒƒ|¦§¨š””Šƒ}ƒ„„ƒ‚u››”‹„„œ››‚|u‹„‹‚utztl‘ˆ}‹‹„„Š}yleb[U[[Tzllf]czllŠ~‹{ttult‹‹„””‹š””tsl{u{kd\{tt|‚zš””kd\”“›‹„„š””ƒ||Œ”•£œ¥zllƒƒ|›”›‹‹‹‹‹‹ƒ„„ultlldzll‰|vŠ}|sledkV‚v{dc\Œ”•dc\{ttƒ||ƒ}ƒ“““lridc\kk]mttSKJ‹’Š{{trfk“““FD;sre{{ttll{{t|„…[TTb[UsleŠƒ}b[U{{tsreƒ||tll{||‹’ŠtllŠ}ƒŠ~‹‚v{‹„‹ƒ||𔔔𔋋„“““tt{lldultuztmtt{{ƒ{{ƒ{{ƒlrilksŒ”•‹’Š|‚zŒ‹“{u{‹’Šuztultƒ||ƒ}ƒœ¤¦ttsldd‹„„lks”“›{u{‹‹„Œ‹“{{t‹„„‰ƒvu{{{u{ƒƒ|Š}ƒ’…‹Œ”•‹’Šyle{||tsl{{ƒztlkd\d\\f]cuztŠƒ}tzl{||””‹›¢›œ¤¦””‹bVUrg]ƒ}ƒ‹‹„‰|v{tttslkd\ŠŠ}‹‹‹ƒƒ|ƒ||“Œ”{u{{ttrg]kd\[[Tlldtsl]bZult””‹››”{tt{{ƒ‹’Šsle›”›ztlztfš””ƒ„„š””””‹‹„„ztl‚utƒ}ƒ…‹‹ƒ||²²¬”“›‚|u“Œ”ztlsle“““Š}ƒ‹‹„lekœ››|‚z‚wlŠŠ}tll‹‹‹„Š}ek]{||™š¤„Š„{||‹‹„ƒ„„tsl‘Œ…ƒ||{||{ttƒ||JHFŠƒ}i\V‹„„ŠutztlŠ}|‹„„‚wlred²²¬FD;*)(„‰v““““““£››£››¦§¨£››£››šŒ‘…„²¬µ£››¤¤››”²««²¬µ²¬µ¦§¨ƒƒ|‘ˆ}‚ut¢—’ŒŒ’ŒŒ‹‹‹“~ˆ‚v‚”𔣛›‹„„ldd£››››”“Œ”‹‹„{ttƒ‚ubVUš””{||tsltll{{t{||‹‹„„Š„‹‹„‹’ŠŒ‹“ult››”uztttsƒ‚u’ŒŒŠ}|{tt’ŒŒƒ„„{||‹‹„‚|u’ŒŒ„Š}”š”””‹lri‹‹‹Š}ƒsleldd›”›Šƒ}FD;{||ult|‚zƒ}ƒlri{ttttsllkekdu{{lldb[Ulri‚utUTStygtll„Š„sreuztŠƒ}„Š„ztlsre[TTaWM|‚zztl‹‹„rfklldƒ||ŠŠ}tllƒ}ƒ£››‹„‹tllš””ƒ|||‚zƒ„„‹„‹lks„„Šlrilek]cd|„…”“›|„……‹’lkstt{Œ”•Œ”•Œ‹“ƒ}ƒfkkllk{ttultlek“Œ”„„Šƒ„„sle£››{{ƒ“Œ”›”›£œ¥{{t{{t|‚z„Š}{u{‘Œ…ultrfktsltt{rg]lld‹‹‹‚utUTSzllyleslekk]{{t{||lddƒ„„ƒ„„““““““’ŒŒ‚utlekf]c{u{{u{r]gƒ||ƒ||{||ƒƒ|Šƒ}‹…’tllredtzlsleVTL|‚z{{ttllŒ”•‹‹„‹‹„ƒ„„ttsllk{tt‚v{œ››ƒ||””‹‹„„¦§¨‹„„£››£››¦§¨ƒ„„]bZ{{ƒ„‰v™š¤¤¤™š¤£››ulttslƒ||Šƒ}tsl{{t‹‹„Šƒ}ŠŠ}mttmtt“Œ”£››“““u{{‹’Š›”›””‹{{t‹‹‹lddlldtzlllk{ttj]\‹„„lddsleƒ||‚|uztlsletslrg]¦§¨JHF*)(’‘~{{t‘ˆ}²¬µ£œ¥²««¦§¨“““£››šŒ£››£œ¥¤¤‘…„²¬µ£››šŒ‹‹‹ŠŠ}‘Œ…‹‹„‚|uzll›”›››”£››Šƒ}‘Œ…‹‹„{{t™š¤‹‹„Šƒ}ƒ„„‰|v’…‹|‚zŠƒ}‹„„’ŒŒ„Š„{||srelri‹’Š‹’Š””‹„Š}„Š}ƒ}ƒ‚|u…‹‹‹‹„’ŒŒ‹‹„|‚z{{ƒŠƒ}{{t™š¤yfl””‹Šƒ}sle„„Š””‹llkŒ‹“””‹r]ZbVZ“““““““Œ”“““ƒ„„ƒ„„Œ”•llkred{ttddc[[Tlld‹‹„Šƒ}lldlldƒ||tzltll[[Tddc{||rg]dc\b[Usreslesleƒ‚nsreŠŠ}{{ttllƒƒ|lritzl””‹²¬µ‹„„zlltllƒ}ƒŒ”•tts{{ƒult„„Š]cd|‚z{{ƒ|„…Œ”•|„…u{{Œ”•…‹‹|„…mttlriultuzt{{ƒultf]clks\[bmtt›”›’ŒŒultŒŒš‹‹‹ƒ„„lddztldc\kk]‹‹‹{tt‚utƒ}ƒ‹„‹llkddcƒƒ|””‹Œ‹“sre{tt‚utzllztl{{ƒ{u{kd\d\\ƒ„„¦§¨‚ut{u{¤¤š””‚utred{tt{||ztltllkk]\[[¤¤lriŠƒ}ultŠƒ}uzt‚wl|‚zmttŒ”•Š}ƒtt{’…‹””‹£œ¥mtt]bZ„Š„Š}ƒttsŠƒ}‘…„‘Œ…š””sre™š¤””‹µ¶·tts{u{{||¦§¨œ¤¦š””››”“Œ”“““„Š„‹„‹””‹‚v{ztl››”[[T‹‹‹‹„„‹‹‹‘ˆ}z‚l”››ƒ„„…‹’‹„„„Š}lldttscbVlldttssrerg]sle{{t‚utztl‚|ui\V‘…„zllƒ‚utll””‹JHF!””‹”š”›”›œ››²²¬¦§¨²¬µ£››‘Œ…””‹š””‹„„£››’…‹Â¾Æ£œ¥£››“Œ”ƒ‚u£››œ¤¦’ŒŒŠƒ}£œ¥{{t‘ˆ}{tt{{t„„Š‹’Š””‹’ŒŒœ››””‹””‹’ŒŒttsztl””‹‚|uƒ„„{||‹„„™š¤ƒƒ|lldŠƒ}tsldc\dc\kk]tsl›¢›ƒƒ|‚ut£››ƒ||ƒƒ|„Š„‹„‹Šƒ}””‹zllllk‹„‹œ››{u{{tt‹„„b[Uš””ƒ}Š{{ttsl{{ƒ„„ŠlribVZlritlllriVZTUTStlluztf]c„Š}ƒ„„‹‹‹mtttslkd\ƒ||‹‹‹‰ƒvuztyle››”‹„„šŒ{zm{u{JHFƒ||‹‹„|„…ƒƒ|“““{zm“Œ”¦§¨œ››|„…”››„Š}„Š„{{ƒ“““|„…|„…‹‹„…‹’lkslksekd“Œ”}‡’™š¤|„…„„Š„†™‹„‹fkk„Š„dc\ult‹‹‹tt{ƒƒ|lddd\\tsl”“›{u{œ¤¦tts‚|uVTLƒ‚nƒ}ƒ‹‹„ult£››f]cult|‚z‘Œ…ƒ„„lks{{ƒƒ||ztl‚|u{{t„Š„lekttsldd”š”Œ”•{||‹„„‘Œ…lddrfkbVZdc\{{t››”””‹u{{tll{{t{ttƒƒ|ŠutŠ}||‚zŠ}|ƒ‚uŒ‹“{zmkd\u{{ztlrg]ƒ||llk›¢›ƒ‚uƒ}ƒ‘Œ…’ŒŒŠ}|ƒ||Šƒ}¤¤£››š””“Œ”{ttlri’…‹””‹‹„‹””‹{ttŠ}|²««“““‹‹‹‹„„Š}ƒ„Š„{||‘Œ…sre“Œ”{{t‹‹‹|‚z””‹{{tƒƒ|ƒƒ|sletslŠƒ}{{t{{tztl[[Tƒ‚u[TTsleultb[UztlŠƒ}ƒƒ|{ttŠŠ}‚v{ult>B9*)(””‹¦§¨””‹ƒ||‹‹‹²««²««£››¦§¨¦§¨”𔦧¨¤¤›¢›¤¤¦§¨¦§¨¤¤””‹””‹”››¤¤‚v{‹‹‹‚v{zll‹„„tts’…‹“Œ”“““””‹£››“Œ”’‘~‹„„dc\lekyle‚v{’ŒŒ{{ƒ‹‹‹{{ƒldd{||’ŒŒ{{td\\[[Tuztllkƒ‚n””‹£››‘Œ…ƒ}ƒƒ‚uldd“Œ”œ››¢—sle|‚z£œ¥ƒ„„ztlƒ„„ƒ‚u‚|uƒ||tts|‚ztts‹‹‹œ¤¦{tt„Š„‹‹‹‚|uƒ„„{{t[[T””‹\[[ƒ||‹‹„ƒƒ|ldd‹‹„Š}|ttsƒ||ƒƒ|Š}|slesle””‹jcVƒ||kd\‹‹„tzlttsƒƒ|ƒ„„ƒ‚u£››‰|v’…‹“Œ”ƒ}ƒ‹’Š{tt{||‹‹„{{ƒ„Š„ƒ„„{{ƒ…‹‹ƒ}ƒŒ”•{{ƒtslmttmttŒ”•mttmttuztŒ‹“\[b\[[{||lddƒ„„lekultult’ŒŒ„„Š|„…rfkœ¤¦‹„„{ttlddƒ„„”š”œ››dc\ƒ}ƒ“Œ”tsllldttsldddc\[[Tlld‘Œ…‹„„lld{{t{{ƒ[[TbVUkd\tts„„Šldd‹’Šedkzll\UZd\\tll‹„„{||uzt””‹“““‹’Šlriultzll\UZ{{ttyg[TTMRK\[[llk\UZŒ‹“{ttult‹’Ц§¨¦§¨‹„„‹‹„ƒ}ƒ‚wlkk]››”‘…„µ¶·’…‹™š¤‹…’ƒ||‹„„‹‹‹£››’ŒŒ’ŒŒ£››™š¤ttsztl‘Œ…‹’Šdc\{{tƒ‚ulld››”ƒ||tzl|‚zŒ”•{zmkd\ƒƒ|lriiq]lldtllsrebVU{zmztl‹‹„ztlŠƒ}‚|u””‹tllyleŠƒ}“““”š”D;9*)(‘Œ…‹‹„£››’ŒŒ›”›“Œ”²««£››£››‘Œ…”“›ŠŠ}‚wl¦§¨µ¶·£››£››ƒƒ|«²«””‹‹‹„‚wlƒ||””‹kd\„Š„{{t{||{tt{{t£››¤¤ƒ‚u„Š„››”{||{{trfkrg]ƒ}ƒ””‹Š}ƒ{{t{u{‹’Š‹’Š‚wlƒƒ|{tt{u{„Š„d\\ƒƒ|¤¤š””˜Ž£µ¶·’ŒŒƒ‚u‹’Šztlƒ‚uƒƒ|ƒ„„ztlƒƒ|SKJttssle“Œ”Šƒ}bVU[[Tultllkult„„Šlksƒƒ|ƒ„„llk‚|u[[Td\\tts|„…ƒ‚u{{t‚|u‚|u“Œ”„Š„‹‹‹‹’Š‚|u{{tf]c””‹’ŒŒ‘…„sleƒ||{{tsleztl””‹lld‚v{ztl“Œ”””‹tsl”š”tll‹‹‹™š¤edklld{{ƒ{{ƒ|‚z…„’›¢›tt{…„’|„…mtt{{ƒmttu{{{||‹„‹{{ƒllduztd\\\UZlks[[Tf]clld{u{llkŒŒš{{tldd››”cbV”𔋄„ultlddultƒ||ƒ}ƒdc\{{t{tt[TTUMR{ttb[UmwVTLrfk{u{VTLSKJ{tt{{t‚v{‚v‚red„Š„ldd[TTtsldc\|„…‹‹„„Š„””‹šŒƒ„„‚utsle‘}z„Š}ekdllkllk„„Šldd{||’ŒŒ£››ƒ„„{{ƒuzt””‹‹‹„Šƒ}sre‹„‹Š}ƒ²««²²¬£››£››‰|vlekllk’ŒŒ‹‹‹‹‹‹‹‹„Š}|zll‹„‹ƒ}ƒ’ŒŒ‹„„ƒ||‹„„ttsƒƒ|£››Œ”•›¢›{{t„Š}„Š„|„…ztl‹„‹b[Uƒƒ|{tt‘Œ…{||{{tlddtts‹‹‹‚|u‚utztlƒ||’ŒŒ‚ut””‹ƒ||‚wlŠƒ}:97*)(››”¤¤²««£œ¥µ¶·š””””‹‘Œ…š””µ¶·µ¶·š””«²«²²¬£››¦§¨¢“ƒƒ||‚zƒ‚u‹‹„¦§¨£›››”›‹‹„tll””‹‹‹„œ¤¦{||¢“’ŒŒ¤¤tts‹‹„ƒ||‘Œ…f]cultttssleb[U’ŒŒ‚v‚ƒ‚u‹’Š“Œ”››”]bZ[TT|‚zddcb[U|‚z›”›‚|u‹„„‹„‹ƒƒ|tslŠƒ}kd\{zm‹‹‹‚v{ª³·ƒ||llk’ŒŒ›”›lddsleŠƒ}‹„„›¢›ult”“››”›ttsb[Uƒ}ƒcbV„Š}‘Œ…Œ”•ƒ||‹‹„tlli\VVTLSKJkd\‹‹‹tll{{t‚|uyletll‚|u‘ˆ}‚|u‹„„tslsle{||b[U’…‹””‹{tt‘…„‹„„tsltsldc\{u{{ttlks‹‹„{{ƒ{||uzt{{ƒ›¢›mtt„„Š|„…Œ—£mtt|‚z|„…|‚z›”›|„…{||llk{ttlek{||{{ƒd\\bVZbVZ{u{£››|‚zƒ}ƒ””‹‚|uƒ„„ƒ„„z‚lult‹‹‹‹‹‹tlluztdc\redUTSztf›”›kk]SKJƒƒ|‹„‹lekkd\f]ctllVTLmttd\\tslƒƒ|”“›ƒƒ|‚|u\[[””‹“Œ”‹’Š“““£››‹‹‹kd\{||‹„„{tt‹„„sle‹„‹ƒ}ƒldd„„Š{{ƒ‚v{ƒ}ŠlksmtttllsleultztlultUMRldd””‹’…‹“““‚utllkuzt™š¤tts“Œ”£œ¥’ŒŒ¤¤£œ¥ƒ„„‹„‹šŒzllsre‹‹‹ƒƒ|››”””‹Šƒ}‚|uŠƒ}„Š„ŠŠ}“““lddztfsre‘Œ…ƒƒ|ƒƒ|]bZredƒ||ƒ‚u{{t‹„„‹„„‚wlztlztlšŒƒ||tsl‚wlJHF*)(£››¦§¨ÃÄÆµ¶·¦§¨‹„„£››šŒ‘…„£››²²¬¸Á¹””‹µ¶·£œ¥š””Šƒ}¦§¨””‹ƒ‚u‹‹„‰|v“Œ”“““›”›£››’ŒŒ‚|uƒ}ƒ›”›‹„„yleŠŠ}ƒ„„’ŒŒ“““’…‹“Œ”£››„Š„ƒƒ|‚|uuzt‹„‹’ŒŒ””‹””‹››”mtt{{td\\ƒƒ|‚|uŒ‹“£››Šƒ}{zm‚|u‹‹‹ƒƒ|‚|uŠƒ}ƒƒ|„„Š”š”{||f]csresre‘Œ…Š}ƒultllksle{||ultultuztlldd\\{u{VTL]bZ{{tsre“Œ”‘Œ…{zmƒ}ƒJHFSKJdc\dc\‚|uztf[[Ttllkd\‚|u””‹ƒ||Šƒ}Šƒ}lldkd\ztlj]\‹„‹‘…„{tt‘Œ…tsl{{t{ttttstllddclddlekmttu{{mttœ¤¦|„…tt{{{ƒŒŒš{{ƒttslks“““²¬µtt{Œ”•|„…”“›Š}ƒ‹…’“Œ”ƒ||ttsf]cƒ}ƒbVZylelri¤¤|‚zsre{||kk]’ŒŒ{||‚|uldd„Š„|‚zkd\rg]‘Œ…œ¤¦‰|vsreztl‹„‹rfkƒƒ|Šƒ}‹„‹rfk“““ztlkk]b[U‚|uƒ}ƒzlltlltllf]c”š”{{t‹‹‹„„Šrfkrg]rfk””‹uzt|‚z„Š}{u{leklektlllekƒ||ttsmtt£››‹’Š‚utŠ}|‚v‚zll’ŒŒƒ‚nllkŠ}|‹„„‹„‹ult™š¤f]c‹‹„””‹Š}|‘Œ…‹„‹lddšŒ‹‹‹£››tsl{u{‹’ŠŠƒ}””‹‹‹„Šƒ}tll„Š„{||Šƒ}‹„‹¤¤‚wlŠƒ}{{t[[Tdc\tll””‹tslŠƒ}‚|uƒ||‚|u‘ˆ}{tt“~ˆ’ŒŒ‹„„ztlD;9*)(£›››¢›²¬µ¦§¨²««¦§¨²««²««£››’…‹µ¶·²²¬‹’Š””‹››”£œ¥šŒ‹’Ф¤«²«››”ƒ‚u£››‹‹‹‚ut››”‹„„‹’ŠŠŠ}lld’ŒŒ’ŒŒ¦§¨‚wl{tt{u{zll’ŒŒ{{t‹’ŠttsŠ}ƒMRK‹‹‹sre|‚zŠ}ƒ‚|udc\‹‹‹¦§¨‹‹„››”‹’Šƒ||{{tlriƒ‚u‹’Š‹’Š‚utŠŠ}‚|utsl‹‹„››”Š}|“““ƒ||zllƒ||ƒ||ztld\\ddcsre„Š„\UZ{{tƒƒ|Š}|‹‹‹ƒ‚u{{t‘Œ…””‹‹‹„dc\j]\f]cVTLsleƒ„„lddttsuztŠƒ}ŠŠ}b[Utll‰|vyleztlkd\kd\‚wlf]ctsl‘Œ…Šƒ}Šƒ}d\\ƒ||Š}ƒƒ„„{ttllk“““ƒ„„„„Štts{{ƒn…{{ƒƒ„„mttŒ”•lkslksultlek„„Š™š¤|„…mtt’ŒŒtt{ult]cd‚v{bVZ{tttt{tsllld{{tz‚l{{t‹‹„ƒ‚utsl’…‹f]cj]\llk{{tŒ”•””‹{{t‚ut{{t‹„„‘Œ…ƒ‚u{{tlek{zm‚|urfklks…‹‹„Š„ƒ||kd\Šƒ}ƒƒ|SKJf]ccbVƒ||sre›¢›lddƒ}ƒƒ„„slesletsl‘Œ…‚|uzllttsult””‹‹…’“““lriekd”››œ››|„…„„Š{tt“Œ”ƒ||£››¤¤‹‹„š””{tt{||{ttƒ„„rfkƒ||‹„„Š}ƒ{u{Šƒ}‹„‹tll‚|ud\\‚|u[[Ttsl‚|usrekd\lldŠƒ}œ››‹’Š››”lldrg]ƒ‚u‹‹„‹’Š‹’Šƒƒ|‚v{””‹kd\ƒ||r]Zš””sle‚|uredredVTLcbV£››FD;*)(¢—¦§¨£œ¥’ŒŒš””šŒ£œ¥¼À¯µ¶·¦§¨¦§¨¦§¨¤¤²²¬‰|v£››¦§¨››”›¢›{zm{{t‘ˆ}Šƒ}››”{{tƒ‚u‹„„‚|u{u{¦§¨£œ¥››”‹’Šƒ||‹„„{{taWM’ŒŒœ››llkƒƒ|ƒ„„{{t‹„„”𔋋„redllk{||„„Š‹’Š‚ut¦§¨›¢›{ttŠƒ}tzlSKJJHFVTLš””{tt››”{zm””‹‹‹‹b[U|„…£››ult{tt‚utldd[TT””‹ult{ttd\\slej]\kd\|‚zƒ‚udc\slelddkd\f]ctslb[UJHFƒƒ|tts{u{””‹dc\{tt‚|u‘ˆ}llk‰ƒv‹„„‹‹„””‹ttsƒƒ|lddƒ„„””‹tts{{ttslcbV‹„‹””‹ƒ||{{tƒ}ƒtts…‹‹…‹‹lks|„…|„…{{ƒ{{ƒŒ”•VZ[]bZfkklksleklkslrimttƒƒ|\[[\UZUUY{ttldd{u{‹‹‹›”›„Š„{{t””‹cbV‘…„‹’Š[[Ttllultldd{||sretsl‹‹„tts‹„‹{zmkk]lldƒ}ƒƒ||{||ƒ‚ušŒd\\‹„„tll|‚z‚v{kd\b[Utzlu{{tsl|‚ztslƒ||‹‹„tll„Š}{{tkd\‰|vVTLlldslelri{tt{u{ƒ„„‹‹‹lksmtttt{|‚z¨©´œ¤¦”š”ƒƒ|›¢›Šƒ}ƒ||{||tsl{tt‘Œ…›”›ultƒ}ƒ{||uzt“Œ”kd\ƒ||Š}|Šƒ}‹‹‹bVU{ttd\\ttstslƒ‚uuzttslƒƒ|{||{{tuztf]cult{zmzll‘Œ…””‹uztŠƒ}ztl””‹rg]d\\j]\tllrg]rg]Š}|ƒ||{{tztl¦§¨UTS*)(¤¤¤¤£››šŒ“Œ”¦§¨²««¤¤¦§¨¤¤¤¤¸Á¹””‹›¢›šŒ²¬µ™š¤””‹›¢›‘ˆ}‚|u{ttrfk{{tœ››’ŒŒ£››ztl‹‹‹‘Œ…“Œ”tll{{t‹„„‹‹‹{||rg]{{t{||zll|‚zƒ||ƒ„„tts{||š””‹„„{{t\[[llk‚|u”“›š””””‹›”››”›ƒ„„Š}||‚ztyg‚v{ttsj]\“Œ”¦§¨‘Œ…Š}|Œ‹“‚|u{u{bVUztlŠƒ}VTL]bZldd„„Šllk\[[UMRtll[[Ttsl{||›”›dc\{zmlrij]\tll{zmtsltlldc\{{tztlŠ}ƒ{ttkd\VTLlldbVUb[U{{tŠ}|Šƒ}rfkŠ}ƒƒƒ|‹„„”𔋄„››”‹„‹ƒ„„VTLsre{{ƒ|„…tt{Œ‹“|„…Œ”•„Š„{{ƒllk…‹’nv‚{||mttd\\{{ƒfkk|„…ttsf]cUTSlks\[[bVZƒ}ƒ‚v‚‚|u’…‹”š”Šƒ}‰‘~sreƒƒ|llk{{tttsllkd\\ztllri[[Tƒƒ||‚z‹„‹„Š„„Š}sreŠ}ƒƒ}ƒƒ„„dc\tllf]c{ttŠ}ƒƒƒ|tts‹„‹{{ƒ{u{„Š„”“›sle{{t|‚zŠƒ}{{t{{ƒ{{t[TTtllVZT[[Tƒ||{||ƒƒ|bVU{u{llk‹„‹…‹‹”››‹’Š‹‹‹œ››¦§¨|‚zu{{ƒ||£››’ŒŒ‹‹„¦§¨{||\UZ{{ƒlri‹„„”š”zll””‹zll¦§¨““““““sle‹‹„“Œ”tts››”{tt‹‹‹‹‹„‰ƒv|‚z{{tlddj]\ztl{zmslesleƒƒ|ƒ}ƒ‹„„’ŒŒztltsl{ttSKJlldek]‰ƒvƒ||sle‚utsle²««SKJ*)(‘ˆ}“Œ”²««›”›ÃÄÆ¨©´£››™‹†””‹””‹””‹›¢›¤¤””‹£œ¥¦§¨”››‹‹„Šƒ}{zm{zmtllŠ}ƒƒ||ƒƒ|›”›„Š„‹‹„tll‹‹„‹„„Œ”•’ŒŒ“““{u{„„Šlld[TTlrisleƒ„„‹‹„‹‹„Š}|{{t¤¤¦§¨|‚z‹‹‹’…‹ek]{tt››”‹‹„ƒ}ƒ‚|u„„Š‹„„sle{{tldd‘Œ…¦§¨¦§¨£››zllš””‹‹„{tt‹„„ƒ||{ttkd\{u{{{tttsttsƒ}ƒlldSKJ]bZuztkd\tslŠ}ƒ{{ttllVTLd\\[TTD;9{{tlld‚v{sre{||‹„‹kd\ztldkVkd\‹„„ƒƒ|b[U{{t””‹ƒ}ƒ‹’Š””‹¦§¨‹„„ztlƒƒ|’ŒŒ{{tlrisle‹‹‹ƒ„„Œ”•œ¤¦lksmttmtt{{ƒVZ[{{ƒ…‹‹fkkmtt…‹‹{u{ulttsllksƒ„„d\\d\\„„Š£››“Œ”š””llkƒ„„¤¤‚|u””‹kk]sreuztttskd\tt{\[[lldredztl{{t””‹Š}ƒllksle‚|utll“““‹„‹\UZƒ||’…‹ult{u{{tt{||dc\jcVtslult{{t’ŒŒ‚|u{zm{{ttts{tt{u{j]\d\\edkekdƒƒ|{{ƒ{||tts{{ƒ˜Ž£Œ‹“ŠŠ}u{{…‹‹‹‹„{{tš””‹’ŠŒ‹“tts››”‹‹„””‹“Œ”‹‹„ƒ„„ƒ}ƒ“““uztƒƒ|{tt¦§¨£››‚v{ƒƒ|{||›”›{{tŠŠ}ttslld‹„„ttsult››”{{t…‹‹›¢›Šƒ}lridc\b[UcbVƒƒ|‘Œ…llkkk]‚|utsl{tt‚ut‹„„ztlrg]ddcƒ„„ƒ||red¤¤D;9:97£››£››¦§¨²¬µ¤¤¦§¨£œ¥””‹¤¤’ŒŒµ¶·¤¤¦§¨«²«¦§¨“Œ”£››”š”””‹‚wlŠƒ}ƒ||“Œ”“““„Š}¦§¨ƒ}ƒ’ŒŒ{tt¤¤ƒ||²««ƒ||ƒ„„{ttŒ”•‹„„‚|uuzt‹’Š””‹rg]llktts{zmš””ultb[U\[[‹‹‹[TT{||kd\{||{ttsled\\ƒƒ|‹‹‹‹‹„œ››””‹£››ƒ„„‚|u‘Œ…‚v{tsl”š”j]\‹’Šdc\sled\\ƒ||kd\lek{{ƒddcldd\[[dc\[[Td\\“Œ”f]cslesle{ttb[U[TT]bZrfkldd‚utƒƒ|bVZj]\ztlztlŠ}|kd\|‚z{zm‹‹„“““ztf|‚zŠŠ}„Š„ŠŠ}rfktsl{||’ŒŒ|‚zkd\tt{‹‹‹{{ƒlri‹„‹{ttlri\[[|„…„„Š”››…‹‹mtt…‹‹{{ƒ…‹‹]cd\[bttsf]c{u{lks{{ƒf]cddc\UZ{||ƒƒ|lld{{tƒƒ|kk]kk]{{tlri„„Šldd{{ttllddcult]bZŠ~‹uzt{{tb[Uƒ}ƒf]cf]c{ttj]\’ŒŒ{tt‹„‹sresle‚|u‹‹‹lddult{{tttsƒƒ|››”‚|u‹„‹‹’Š{||‚|u|‚zult„Š„UTS{ttttsttsf]c{{ƒ{u{’ŒŒ„Š„„Š„ztl”𔋄‹„Š}Œ”•‚ut{{ƒ{||’ŒŒ’ŒŒƒ}ƒ‹„„ƒ„„{||…‹‹lrizllŠƒ}‘Œ…”“›””‹‹„„ƒ‚u‹‹„ƒ‚u{||‚|uuztttsƒ||{{ttsluzt‹‹„ƒ||“““‹‹„ƒƒ|sre{{t‚wl{{ttslztf‹‹‹kd\ztlŠ}|sre’ŒŒƒ||{{ttsl{||¦§¨FD;*)(‰ƒv£œ¥¦§¨””‹£œ¥²¬µ¦§¨šŒ››”¤¤¤¤””‹””‹””‹“““µ¶·£œ¥‹’Љƒvƒ‚uƒ||redredƒ‚u””‹‹‹‹{u{œ››ƒ„„””‹ƒ||‹„„Š}ƒ‹’Šƒ„„{ttztlŠƒ}{||Šƒ}””‹š””””‹œ¤¦lld{{tred[TTldd{ttslelekrg]sledc\tslƒ||“Œ”ƒƒ|‹‹‹š””‘Œ…””‹ƒ}ƒ‘…„‹„„tll‚v{[[Td\\ƒ„„‚|uztltll{||”“›ƒ}Š”“›uztf]c]bZlddb[Ulddd\\{u{{{t‚ut‹„„ƒ‚uldd„‰vredVTLkk]lddbVZ‚|uslelddŠ}|ldd{ttllkƒƒ|‚|u‚|u{{tŠƒ}{||sle‚utztl’ŒŒƒ||lriƒ„„|„…{{ƒŒŒš{{ƒtt{]cdult{{ƒmtt{{ƒ|„…tt{edkf]clksllkekdmtt{{t‹„‹ƒ„„lks{u{lek\[[d\\ek]lldllkkd\ƒƒ|‹„„tslsreldd\[[d\\sleƒ}ƒllkŒ‹“tsl‹„‹“““‹‹„sleŒ‹“ddclddtt{‚ut‚v{{ttultldd‚|u‘Œ…‹‹‹VTLkd\UTSƒ‚uœ¤¦ƒƒ|Šƒ}{tt{||uzt‘…„ldd…‹‹]bZtsllksœ››{{ƒ{u{lksult[[Tlektsl””‹œ¤¦‹’Šllkuzt|‚z‹‹„‹’Štzl“Œ”Š}ƒ¦§¨lekŠƒ}|‚zlld{u{ƒƒ|ƒƒ|’ŒŒ‹‹‹‹‹‹ƒ„„b[USKJd\\mwFD;[TTllkƒƒ|ttsƒ‚udc\{tt››”{zmŒ”•ek]llkcbV[[TŠƒ}{{t]bZtllsre{ttjcVyle‹„„’…‹Šƒ}sle£››SKJ*)(Šƒ}œ¤¦£œ¥“““£›››”››”›¤¤£œ¥µ¶·“Œ”ƒƒ|„Š}«²«ƒ„„”“›‹’Š””‹””‹‹‹„””‹ƒ„„{ttlld„Š„‹’Š{ttlldƒ||‹‹„š””Šƒ}|‚z’ŒŒ›”›{||“Œ”{{t‹‹‹„Š„‘Œ…“Œ”ƒ„„|‚z{{ttts{||‹„„ƒ„„ult‚|uŠ}ƒ‰|v{zmtyg’…‹rfk‘…„{{t„Š}ƒƒ|{tt›”›tsl’ŒŒƒ||zllƒ||ztlƒ}ƒ{ttldd[TTƒ}ƒ„Š„{{tddc{||tsltlltsl{u{ek]lektllrfkztl{ttlddkk]kd\ddcf]ckd\b[Uekdd\\zllaWMMRKƒ||{||‹‹„lri{ttj]\{zmŠŠ}{yf|‚zkk]ŠŠ}{tt”“›””‹‹„„‹‹‹¦§¨ƒ}ƒ‹…’uztddc|„…|‚zlksmtt…‹’uztllkmttf]c\[bultekdlksultƒ||iq]b[U{u{ƒ}ƒ{u{\[[ldd{{t{{t[TT{{tlldtsl{zmlldƒ}ƒdc\sleddcd\\aWMlriƒ„„ƒƒ|{{tVTLlldtllr]gtt{Š}ƒ‘…„lddd\\tsl‚utddcztlddcb[U{||[[Tlld‹„„”››{{t]bZƒƒ|ƒ||u{{”››{||””‹““““Œ”™š¤\UZ\UZSKJkd\ekdtll{tt|‚zf]c{||lksfkktslttsb[Uf]c{||‚v{{u{{ttllktsltllaWM|‚z{tt{||ztl{tt’ŒŒj]\tsl‹‹„ƒ||dc\dc\lri{zm{{ƒ[[Tredƒ„„””‹‚|uƒƒ|ƒƒ|lldtslsre{zmtsltllcbV{ttkd\ztl{{t{ttmttldd™…D;9:97ƒƒ|𔔍©´›”›‘Œ…²««£œ¥¦§¨µ¶·‹„„šŒ””‹ƒƒ|¤¤œ››¦§¨uzt›¢››¢›‘Œ…’…‹‘Œ…{tt’ŒŒ‚v{ƒƒ|{u{””‹™š¤‹‹„™š¤‹‹„‚|uƒ„„‹‹‹“““{zm„Š„”š”|‚zƒ||{ttultlri|‚zƒƒ|¦§¨|‚zŠƒ}‘Œ…ƒƒ|ƒƒ|{zmtsldc\red{{tƒ||{||„Š„|„…sle‹„‹red{u{{ttredlldslelddlekj]\dc\SKJslelritslƒ„„b[U{||ddcƒ„„uzt{{t{{tldd{{t[TT{tt{zmSKJ|„…‚utsle{{ttll{ttztl‰ƒv[TTsle“““lrilld{ttj]\Š}|kd\tslllkztlbVZttsƒ}ƒ‹‹„{{tdc\lkslksddc{{ƒ{{ƒƒ„„llkmttƒ„„u{{ddc\[[UUYUMR{{ƒ{{ƒuztmttlddlek‹‹„dc\ddclekllkultŠŠ}lrilddlriƒ‚u””‹{ttd\\lek{{t{||ztlldd|‚zƒ„„kk]VTL{u{j]\b[U\[bd\\[TT‚|ub[Ured{||[TTllkVTLb[Uredb[Uj]\]cd{||ƒ„„j]\tlltts”››ekd{u{{||{ttVTLlri{u{ƒ||…„’tllŒ”•{||tllkd\‹’Š{||“““]cd|‚zdc\lksƒ||ddcbVUSKJztlVTL[TTlrittscbV{||sletygtts|‚zrg]‹‹‹ƒ||ƒ||{u{lddztllriƒ„„Šƒ}|‚z„Š}dc\ldd[[T|‚zttskd\[[Td\\tslb[Utzl[[T[TTkd\{||„Š}redƒƒ|ƒ||tslj]\£››SKJ*)(‹‹„””‹£œ¥£›››”›£œ¥›”›””‹”››’ŒŒ›”›¤¤››”›¢›ƒ„„‹‹„”››””‹ultŠƒ}{tt‹„‹‚|u””‹‹‹„ztlƒ||‹„‹Œ‹“{zmƒƒ|‚wl“Œ”ƒ}ƒ{{tlksŠŠ}{{t{|||‚zztlsredc\„„Šsre“““ŒŒš{ttšŒ’ŒŒŠƒ}ƒƒ|‚utŠƒ}{{tzllekd’ŒŒttslddllktll{||kk]{{t‚|uultult‹‹‹“Œ”tll\[b]bZbVU[TTtslf]c{||tsltlltllƒ}ƒlldkk]tlld\\kd\j]\ƒƒ|ƒ‚uFD;tll{ttsleVTLb[UlddVTLztlƒ||tts“Œ”ultkd\cbVdc\{zmƒ‚usletts„Š}tll‹„‹…‹‹“““‹‹„[[T]cdslelks{{ƒ{{ƒedkddc{||u{{mtt\UZ\[bJHFVZ[lkstt{ddc„„Šlksƒ}Šlks[[Td\\lekllkf]ctts“““‹‹„‘ˆ}VTLtslttsbVZ[[T[TTzllkk]ƒ||mttz‚ldc\lks‹’Šƒ||VTL\UZSKJd\\lekkd\zlllddlldddcSKJVTL[TTtslƒ}ƒ\[[dc\tslVTLVTLŒ‹“lrildd\UZlldd\\{u{llkllk{tt„„Štts„„ŠtllbVZlkslridc\uztŒ”•mttƒ}ƒlektlluztlekj]\b[Uu{{d\\{tttts[TTVTLtslVTLkk]ddc‚|uddcŠƒ}{{t’ŒŒŠƒ}tllƒ||ekdƒƒ|[TTdc\lld‚|uultttsf]cƒ„„{||kk]sre‹‹‹dc\kd\lddztlddcb[U‚utlld{ttƒ||sle£››JHF*)(Šƒ}‚|u“““𔔍©´“Œ”“Œ”’ŒŒ¦§¨£››²««”››“““›¢›Œ”•ƒ‚uŒ‹“„Š„ƒ„„ƒƒ|…‹‹‹„„{tttsl{{ƒ””‹››”tt{‹‹‹””‹{ttsle‹‹„Œ‹“tsl{{tzllztl‹‹„llk‘Œ…ƒ||UTSkk]dc\ekd{ttlddtslulttsltslkd\|‚z|‚zkk]{||d\\{||lddlri‚|uttsŠƒ}ttsSKJddctllƒ„„Œ‹“ult[[TVTLSKJllkJHFSKJ\UZdc\ldd‹„‹|„…tsllldtslb[UUTS[TT]bZVTLj]\b[UVTL{tttslVTLzllztlztfldd{u{lrilddJHFb[UVTLkd\redtslttsƒ||{ttllk{{ƒtsllldUTSttsekd{{ƒ]cdf]cllkƒ„„tts{{ƒ…„’\[bfkkVZ[ƒ}Šu{{lksddc|„…{u{“Œ”ŒŒš{tttlledkuztlek‚utuzttsltslVTLtt{\[[d\\[TTekdj]\{{tlddkk]„Š„tzl[TT\[[d\\b[Umttllkllkldddc\\UZlekbVZlldtllzllŠ}ƒtslj]\[[Tdc\lldttslldllkuztkd\edk\UZVTLb[UJHFf]cUTS…‹‹u{{Œ‹“ddcb[Ukd\…„’UTSlriuzt]bZttslddMRK„Š„„„Š{ttUMR[TT{tt„„Šllk[[TlddcbV\[[{ttlldj]\[[Ttslsreƒ||kd\ddcb[Uddctll]bZkd\ƒƒ|lldtlltslƒ||{||ultŠƒ}d\\dc\ztldc\kd\tsl{u{sle‰|vsleddc{{tlld²««[TTD;9ztl’…‹¤¤‘Œ…‘Œ…ƒ||“““‹‹‹{||››””“›…‹‹…‹‹Œ”•„Š„“““ƒƒ|„Š„{{t|‚zllk‹„„””‹|‚zƒƒ|tts{||llkd\\kd\{u{’ŒŒƒ}ƒ‹„„lrilldlldztlkk]lldtsl””‹tslu{{sleedk[[TVTLrfkf]credkd\kd\]cd|‚zsleƒ}ƒlldtts{||ekdf]ctlllld|‚zslelld‹„„tts{tt{||tllcbVzll[TTdc\d\\{u{]bZbVU{tt\[[VTL[[Tkd\\[bb[U[TTtllslekd\|‚z[TT‚utztl\[[b[Usletsl{||tts[TT[TTlld|‚z‘Œ…d\\tsl{{t{{t{||lldtllttsd\\[[Td\\{{ƒlrif]cfkklkslks|‚z{||mtttt{VZ[LKRVZ[mttmtt]cd\[[\[bd\\d\\lddlekmttedk\[[r]guztekdekdd\\lridc\{{t[TTlldd\\FD;[TTd\\kd\tslUTSlld\[[[TTkk]f]cj]\f]cf]c[TTtllf]cbVZUTSllkkd\ttslksllkd\\SKJmttUTSUMRd\\tllSKJ[TT\[br]gf]cUMRUTSztlddcslelkszlltll\UZtllVTL{||llddc\lldtt{VZTtt{„Š}‹„‹ultd\\d\\tt{mttekdlkssleVTLkd\{{tdc\dc\{{tldd[TTztl\[[dc\d\\b[Uddcd\\f]cb[UcbVlldlld{{ttslcbV[TTztlVTLkd\dc\lldtllb[Urg][TTUTSredkd\””‹[TT:97{||››”’ŒŒ²²¬“Œ”“““ƒ„„Š}|”››“““ttsllk„Š„ƒƒ|tt{mttƒƒ|…‹‹‹„„ŠŠ}{{ƒ{u{ztl‹„‹‹„„tts{u{{u{ƒ„„llk{{ƒƒ}ƒ{tt{ttkd\kd\dc\{u{tsldc\slelldƒƒ|{{ƒ{||{||ƒƒ|tllttstlldc\{ttkd\{||…‹‹{u{|‚zlld|‚zVZTSKJkd\lek|‚ztts\[[JHFf]clrildd{||sledc\ttsttsllddc\\[[JHFd\\UTSdc\ztfkd\\UZsleVTLd\\tslaWM[[Tllk{ttkd\lldlritslƒ||uztƒ„„tts{||{{tlld{u{kk]ztf„Š}{{tlridc\lddultekd]bZdc\llkSKJtlllksmttlksVZ[f]cllkUTSlks\[b\[btt{\[bult\[bVTL\[bJHFUUY[TTdc\UMR\[bd\\UTS[[T[[TVTLMRK\[[|‚ztllttsekdd\\b[USKJUTSSKJ\[[dc\lldttsllkj]\d\\leklddUMR[TT{tt\UZleklldtsld\\VTLkd\[TTuzt[[Tƒ„„ddcu{{ƒ„„{ttd\\JHFmtt[TTldddc\\UZtts{u{u{{SKJ\UZ[TTVTLUTSekdlldedkddc[TTllkddcddclridc\JHFedkttsult\[[[[Tllktslf]ccbV[TTkk][[TlldSKJSKJtlltlld\\fkkd\\sretslllkVTL{||{{t[[TVTLUTSd\\ldd[[Tdc\tllrg]]bZttskd\ldddc\d\\[TTztl²««JHF*)(‹„„ƒ||‹‹„’ŒŒ‹„„‹„„{{t„„Šƒ„„‹„„tzl{||tll|„…llkƒ„„|‚zttstllƒƒ|tt{lddƒ}ƒ„„Šb[Uƒ„„{||ddcllk[[Tultlksultu{{{ttd\\JHFdc\VTLek]lld{{t{{tlddldd…‹’ƒ||sre|„…ƒ||„„Šlriƒ||ddc{||{{t|„…u{{ddcddcedk{u{{u{tsl[[TJHF[[T\[[ddc{u{lddultkd\f]c[TTddcd\\dc\cbVlddultuztkk]b[U[TT[[TVTL\UZtllVTLb[Udc\kd\redlldVTLb[Ulldtzl{||tllekddc\lldtll{{tlddztltsl]bZlrilldlddttslld{||\[[UUY]cdedktt{mtt\[b]cd\[bUUY\[bmttlkslksUUYfkkUTS]bZUMRJHFUMR:97JHF:97UTSUTSJHFllkllkVTLSKJllk]cdcbVLKRb[Ub[U[[T\[[SKJVTL\[[dc\lriddcVTLdc\llkf]cllklddlldlddUMRUTStts\[bkd\VTLllkJHFtllbVZuztttslddddcbVU[TT[TTUTSJHFJHFddcUUYUMR\[bJHFJHF[TTdc\d\\ekd[TTUTSJHFVTL\[[]cdD;9f]clld]bZd\\VTLSKJVTLJHFllktt{‚|uekdUTS]bZdc\JHFkd\[TT[TTtll[[TVTL]cdb[U[[TSKJVTLdc\lldFD;[TTUTSSKJJHF[TT[TTdc\dc\b[Ulddd\\VTL\[[bVUd\\jcVkd\ŠŠ}JHF-1+{tt‚|u„Š„ƒ}ƒ{tttts{||{tttts„„Šdc\“Œ”uzt„„Šllkttsu{{tts|‚zJHFedkleksle\[[sleek]llk\UZf]c{{tf]cedkSKJtts{ttlddlrillddc\\[[]bZ{{ttslUTSldd{u{llklksfkkllkultkd\[[TUTS]bZ[[Td\\tllUTSddctts\[[\[[dc\VZTJHFJHFJHFFD;UTSVZTVZTtllredd\\VTLVTLdc\kd\UTSd\\kk]dc\ddcUTS[TTdc\bVUcbVJHF[[T]bZtllb[UJHFd\\tllb[Umtt[TTUTS\[[VTLb[U[TTdc\VTLb[U[[Tddc[TTUTS\[[cbVVTLddcf]cf]cUTSlksllkVZ[]cdultmtt\[[edk\UZJHFLKRUMRJHFLKRUTSJHFJHF)+2:97F=CF=CJHF:97D;9d\\d\\VTLdc\VZTLKRJHFUTSJHFFD;JHFFD;UTSMSStllMRKUTS\[[UTS\[[\[[[TTf]cSKJSKJD;9JHFUTSUMRlddVZTUTSlekdc\lks\[[[TTddcF=CSKJFD;UMR:97JHF:97:97MSS:97\[[UUY\[bllkult{||JHFJHFFD;>B9>ECJHF:97JHFLKRUTS\UZ[TTUMRMRKd\\VTLJHFekdlldlddJHFF=CFD;MRKSKJSKJlldlddSKJllkUTS[[TJHFJHFD;9D;9:97:97>B9:97>EC:97D;9:97JHF[[TSKJSKJlddJHFFD;\UZJHFJHFSKJSKJ¦§¨SKJ*)(ztl{{tƒ||{{t{tt{ttllkdc\lldldddc\[[TJHFedkdc\ddcmttlkstts]bZllklddtllultVTLMRKJHFUTS]bZ[[TUTSJHF\[[UTS\[[tslbVZllktsl[TT]bZ]bZFD;JHF>ECJHFJHFJHFVZ[UTSddc[[Td\\UTSVTLd\\SKJ\[[\[[UTSVZ[JHFJHFD;9dc\JHFJHFUTSSKJUTSJHFJHFd\\JHFJHFJHF:97UTSJHF:97FD;JHFVTLJHFJHFJHFdc\[[Tkd\JHFD;9JHFJHFJHFFD;FD;SKJ[TT[[Tldd\[[JHFddc\[[lldd\\[[Tddcllddc\VTLFD;JHF]cdllkddcldd\[[[TTd\\]cd\[[]cdJHFLKRJHF]cd*)($:97*)(*)(?;C:97:97*)()+2:97:97:97:97UUY3+**)(74,!*)(*)(*)(*)(*)(74,*)(*)(*)(JHF*)(:97*)(:97*)(74,3+**)(*)(3+**)(*)(7-2*)(:97*)(*)(*)(:97*)(,55*)(*)(*)(*)(*)(*)(*)(:97&&%&*)(>EC-1+%&FD;)+2LKRLKRUTS?;CJHF*)($*)(*)(,55*)(*)(F=C*)(*)(*)(*)(*)(74,:97-1+*)(*)(*)(:97:97JHF*)(74,-1+*)(*)(*)(74,3+**)(*)(&&*)(*)(*)(!*)(*)(*)(*)(*)(*)(*)(*)(:97*)(*)(:97*)(*)(D;9:97*)(-1+VTLSKJFD;\UZ[[TJHFSKJJHFLKRJHFSKJSKJ3+*:97:97JHFJHF74,:97LKRUTSMRKMRKJHF:97*)(:97*)(:973+*:97*)(:97:97JHFLKR>ECJHF,55:977-2*)(-1+74,:9774,-1+3+**)(*)()+2*)(*)(*)()+2:97JHF:97,55*)(*)(*)()+2*)(*)(?;C*)(74,:97*)(:977-2*)(JHF*)(&&*)(*)(3+*:97*)(3+**)(*)(*)(*)(74,3+*&&&&3+**)(*)(&&-1+*)(*)(*)(SKJ*)(*)(:97*)(D;9:97:9774,74,*)(*)(>EC*)(:97*)(*)(*)(*)(*)(*)(74,*)(-1+,55,55:97)+2*)(,55:97:97:97LKRJHF?;CUUYf]c\[b\[b\[[[TTSKJUMRJHFllkUTSllkJHFMRKVTLUTSJHFF=CVTLJHFFD;JHFJHFUTSJHFJHF>ECJHF>ECJHFJHFJHF:97LKR:97F=CJHF:97D;9:97:97:97:97FD;:97:97:97JHFF=CLKRJHF\[b\[[MRKMRKdc\]cdLKRek]UTS\[bMSSMRKJHF\UZJHFJHFVZTMRKJHFMRKJHFJHFJHF:97:97:97:97JHF>B9JHFMRKJHF:97D;9UMRVTLJHFFD;VTL[[TD;9JHFFD;>B9:97:97>B9D;9FD;JHFJHF>B9D;9:97JHFD;9FD;UTSSKJD;9FD;SKJD;9SKJJHF[TT[TTJHFJHFVTLVTL:97[[Tdc\VTLllkbVZf]cek]>B9VZ[\UZ>EC\[[VZ[UUY\[[\[bLKRVZTfkk]cd\[[[TTUTS>B9MRKMSSJHFSKJddc[TTVTLVZ[UUY\UZUMR\[[MRKllkVTLJHF:97SKJ[[TVZTJHFJHFVTL\[bJHFMSS[TTLKRJHF:97JHFD;9:97JHF:97JHF\[bf]cJHF:97VTLJHFJHF>EC:97>B9JHFSKJ:97:97SKJJHFJHFJHFJHFFD;SKJD;9MRKJHF74,JHF:97:97JHFFD;UMRD;9SKJbVUFD;MRKb[UJHF:97UMRMRKMSSLKRFD;:97FD;JHFekd:97JHFUMR]bZJHFUTS:97JHF\[[LKR\[bLKRMSSJHFLKRMSSOS`OS`JHF¦§¨¦§¨“Œ”¦§¨¦§¨™š¤¦§¨¨©´…‹‹¦§¨›”›¦§¨›¢›¦§¨«²«››”²««¦§¨›¢›µ¶·µ¶·²««²««””‹¤¤¤¤£œ¥”“›¦§¨²««””‹””‹œ¤¦ƒƒ|‹‹„ztl›¢›šŒ‚v{¦§¨²²¬²««²««£››£››š””¦§¨“Œ”¦§¨tsl’…‹¤¤£œ¥Šƒ}¤¤²««››”¤¤¦§¨¤¤››”¦§¨²¬µ¦§¨¦§¨¨©´¦§¨¦§¨¦§¨£››¦§¨£››¦§¨¦§¨œ››«²«¦§¨µ¶···Ä¤¤£››””‹’ŒŒ‘Œ…‹„„””‹””‹‰ƒv¦§¨£››¦§¨µ¶·¤¤¤¤²²¬¦§¨¦§¨¦§¨›¢›¤¤””‹””‹¤¤Šƒ}””‹²²¬¦§¨””‹ult”š”Šƒ}‚wlztl£››¦§¨²««¤¤¦§¨£››™…£››£››²««””‹²««ŠŠ}²²¬[[T\UZ²²¬²²¬¦§¨¢—𔔣››¤¤¦§¨ª³·²²¬¦§¨µ¶·Ä¿¾Ƶ¶·µ¶·µ¶·¦§¨¦§¨µ¶·¦§¨¦§¨£››‘ˆ}µ¶·µ¶·ÃÄÆ¦§¨µ¶·²««‹‹‹¤¤µ¶·¤¤›”›µ¶·²««²««²²¬µ¶·¦§¨Ã¼¿¦§¨¦§¨’ŒŒ«²«””‹¦§¨¦§¨¦§¨²¬µ”𔤤‹‹‹””‹ƒ„„£œ¥£œ¥£››¦§¨²²¬µ¶·””‹¤¤¦§¨›¢›¤¤“““‹’Š”š”’ŒŒ‹„„‹‹‹£››››”²««””‹£››£››¢—””‹””‹””‹ƒ||¤¤²««£››””‹£››²²¬¦§¨²««¦§¨””‹¦§¨¦§¨£››‘ˆ}¦§¨²««¤¤ƒ„„£››””‹””‹ƒ||””‹š””””‹µ¶·¦§¨²²¬¦§¨²²¬¦§¨¤¤¦§¨¦§¨¦§¨œ¤¦¦§¨¦§¨¦§¨¦§¨µ¶·œ¤¦¨©´lks)+2?;CLKRdc\ultd\\7-2>/Att{\[[f]c]bZ!:97%lrilridc\ddc:97SKJlddlldSKJƒƒ|:97*)(JHF[[TLKRJHF\[[JHFSKJVTLldd{u{f]ckd\]cdddcred{zmSKJVTL3+*:97%JHF\UZlld7-274,%&$VZTuzttll[[TUTSMSSVZTVTLVTLtlldc\tll[[Tddc[[TJHFJHFUMRekdddcUTS74,@/7	74,73FD;VTLRP:tslredbVUVTLD;9MRKFD;FD;D;9C8.]bZ&&&&3+*FD;D;93+*3)D;9dc\VTL3)FD;%&&0FD;SKJD;9D;9VTL²²¬dc\[[TVTLjcVƒ||SKJ>R.VTLJHFGSu]cd’ˆ|‚z|‚zlrityglldsreD;9SKJsre{{t‹‹‹‚|u{tt‹„„lddf]cMRKƒ}ƒ{tttllek]f]c[[T]cdUMRD;9UUY"%VTLFD;JHF\[bf]cMRKfkktsllri[[T ,55-1+>B9VTLUMRD;9VTLVTLlldSKJ\[[sre{||VTLd\\{ttSKJfkkJHFD;9SKJsleVTLcbV>B9VTLVTLyledc\3+*"FD;FD;d\\D;9Q?@SKJ	>B9*)(:97*)(]bZ7-2SKJ3+*dc\zllUTScbVJHFlldtslJHFlldf]cJHF\[[LKR%&-1+,55{{ƒVZ[llkUMRlks]bZJHFF=CLKRf]clddlek\UZf]cMSSSKJf]c>ECf]c74,[[T]bZVTLttstllƒƒ|]bZedk{u{[TT{ttUTSLKR\[bUMRJHFVZTUTSJHFJHFVTLdc\lldultVTLtlldc\uzt{ttSKJSKJSKJ74,UTSf]cf]cJHFkk]JHFD;974,*)(>B9*)(JHF3+*fkkultUTSJHF\UZUMRVZ[[TTd\\lrio€wd\\uzt]bZtsl\UZLKRultuzttts\[[lddFD;-1+FD;>B9%)*)("*)(FD;SKJFD;j]\UMR[[TFD;SKJ:97C8.D;9D;9SKJFD;JHFFD;JHFtllUMR:97SKJb[UVTLFD;JHFVTLD;9F=CPF=JHFD;9D;9SKJJHF¦§¨VTLJHF‰ƒvƒ‚u‚|u‰|v‹„„lri’ˆcbVJHFtsl‹’Š\[bSKJ7-2[TTuzt|„…lldllk…‹‹lrib[UJHFb[Uult‹‹‹„„Šult[[Tlek{{tlldSKJ\[b{{ƒ{{tj]\tllultekdSKJSKJ\UZD;9ldd\[[[[TekdF=CVZ[JHFdc\uztultlri:97]cdfkkMRKJHFttsddc\[bJHF[[Tdc\]bZlriUTSddcVTLSKJUTSf]clri[TTztlb[UVTLVTLlldVTLVTLlddd\\cbVSKJMRKVTLkd\{ttb[UUMR\UZFD;*)(:97[[TFD;[TT:97>EC:97[[TJHFFD;sle[[TMRKVZTSKJVZT\[[>EC\[[UUYUUY>EC>ECJHFJHFUUY]cdJHF\UZ]cdlksddc>ECedkJHFddcj]\UTS\UZ\[[edkbVZf]c\[b[TT:97D;9[[TMRKb[Uek]VZTUUYJHFUUYVTL]cdd\\f]c\[b\[bD;9lriMSSSKJd\\[[T[TTsle\UZ\[[UTSb[Ullk\[bSKJtll\[[SKJSKJ*)(UMRUMRSKJJHF&&3+*:97JHF74,:97JHFLKRSKJf]c]cdf]c]cdedkVTLb[UVZTmtt[[T[[T]bZ[[TUTSu{{ddc{{t{u{lksf]c]bZ]bZVTLlri&&&&SKJaWM[TT[[TVTL[TTb[UFD;3+*FD;FD;VTL74,D;9VTLSKJ[TTd\\[TTD;9SKJJHFdc\JHFJHF[[T[TTJHFbVUUTSaWM[TTVTLtll¢—llkSKJtsl{{t{zm’…‹{u{kk]]bZ|‚zMRKdc\VTLJHF%UMR{||ttsttsŒ”•\[[|„…tzlrfklddult„Š„{||ekdlddldddc\…‹‹ddcb[Umtttt{ldddc\{ttultlriUMRUUY|„…dc\lekmttVTL\[[F=CMRKVTLfkk{u{{ttMSSMRK\[b:97ekdb[Udc\ult\[[:97dc\JHF[TTMRKddcu{{dc\j]\d\\[TTllkSKJkd\j]\d\\tll[[TlddmttVTLlldVTLJHFFD;D;9SKJJHF[TTddcD;9D;9*)(FD;b[U:97SKJsle:97SKJVTLddcVTLlld{||VZTddc{||llkF=CultlrimttJHF]cd>ECLKR:97MSS\[bMSS]cdVTL\[bddc>ECSKJ\[b\[[{||ƒ}ƒ„„ŠJHFddcbVUulttts\[[FD;:97VTL3+*JHFVTL:97d\\:97]bZdc\ekdddcUMRLKRD;9[[T[[TJHFf]cbVZkk]tlldc\zllSKJb[Ukk]edkf]c{u{lek]bZUTStt{f]clddUMRUTSSKJJHFVZTFD;VTL:97FD;FD;lddJHF‚v{fkkVZ[VZ[\[[sleƒ„„lldlkslriJHF[[Tkk]\UZdc\VZTƒ„„{ttVTLlks]bZ[[TJHFJHF&&
&&3)[TTSKJbVUkd\f]csleSKJ:97FD;&&FD;PF=FD;VTL[[T[TT[TTb[Ured:97[TT[[TVTLFD;VTLJHF[TTVTLf]cVTLSKJVTLD;9lldš””bVZJHF{zmŠŠ}’ŒŒ{ttlddMRKmttiq]z‚l‹’Š|‚zUMRVZTJHFSKJƒƒ|„Š„tt{d\\lkstts[TTJHF„Š„…‹’{{tlrid\\[TT[TT]bZ[TTddclldlddlldSKJJHFedkUUYJHFlekJHFUMR[TT\[[{zmUTS\[bMSSVTL]cd{{ƒ…‹‹UTSekdSKJLKRddcSKJllkJHF[[TFD;]bZlek]bZek]\UZVZ[UMRkd\lddztluzt[TTb[Ulekd\\{u{FD;VTLmttmttllkSKJMRK74,D;9VTLVTLb[USKJbVZ[TT&&PF=VTLVTL\UZek]>B9D;9tsl\[[ekdkk]mttdc\llk{ttllkSKJ\UZ{{ƒllk\[b]cd>ECLKR:97LKR{{ƒ|‚z\[bf]ctt{MSS\[bVZ[LKRttslldj]\iWUUUYldd[TTf]cf]cJHFJHFJHFFD;JHF[TTtlldc\FD;JHFbVZlldlldddcJHFUMRSKJSKJSKJJHFSKJ{ttSKJkd\ulttll[TTSKJ{zm\[[ult{ttj]\cbV]cd\[bJHFf]c‚v‚\UZkk]jcVVTLMRKVTLsreUMRFD;UTSlek‹„„llkUMRUTS]cd{u{{{tddcu{{]bZuzt[TTsred\\b[UVTLVTL{ttVTLf]cFD;74,VTLVTL>B9	:97*)([[TD;9SKJVTLkd\d\\VTLredb[UPF=FD;sreVTLjcVek]UMRldd[TTUMRlddSKJkd\b[UFD;D;9SKJdc\JHFtll[[TSKJ74,SKJlld£››f]cLKR‘Œ…ƒ‚usle‚v{JHFVTLsreFD;ZbN‹’Šlldf]cmttUMRŒŒš{{ƒŒ”•‹’Šekd””‹ttsttstll„Š„{||‹‹„|„…{||ultsleek]llkdc\ddctlltllddcd\\\[[mtttt{\UZUTSJHFb[U\[[{{ƒJHFUMRVZ[UTStslu{{{||\UZ\[b[TT]cd>B9FD;f]ctt{:97\[[VTLdc\[[TlritslMRKFD;[TT[[Tredtts{zmdc\UTSd\\SKJSKJD;9VTL]bZrfkttsFD;!D;9VTLJHF\[[SKJUMRVTLJHFSKJj]\d\\D;9i\VJHFD;9ztlUTSlek[[TekdVZTekdlddtsllekd\\]cd{{tbVZJHF\[b>ECLKR]cdlkstsl{{ƒmtt{{ƒf]cJHFUTSultlddVTLUMRf]c\UZf]c‚v{lekUTS]cd>B9MRKVTLVZT{{t‹‹‹lek¦§¨fkktlltts{||]bZF=C74,SKJddc|„…lldlekf]cdc\zlltll‹„„‚|ubVUb[Ulekd\\tllultddcSKJSKJf]cUMRldd\UZSKJD;9JHF[[TVTLSKJVTLVTLJHFƒ}ƒŠ}ƒ{{ƒllk]cd[TTd\\sleultleku{{œ¤¦ƒƒ|tslf]cVTLFD;[[Td\\UMRD;974,MSSVTLFD;%>B974,MRKJHFj]\kd\FD;UMRcbVjcVkd\ztfcbVC8.VTLFD;VTLek]VTL[TTkd\PF=JHFVTLjcV{zmd\\PF=FD;SKJ[TTSKJbVUVTLcbV]bZtsl¤¤ek]JHF‘Œ…‘Œ…ƒ„„’ŒŒzllf]clri]bZšŒztlƒƒ|g\rq^„¬¶Ã¨©´œ¤¦µ¶·”››|„…¨©´‹‹„”“›Š~‹tllultuztddcf]c{u{{ttƒ„„“““{{tuztœ››ƒ‚utllultfkk‹‹„f]cSKJ‚v{dc\{u{ddcƒ}ŠJHF{{ƒlrid\\„Š„|‚z\[[UTSUUYlksJHFddcD;9edk…‹’VTL:97lldƒ||{||ttslldldd[TTUTSj]\b[UVTLSKJ:97{u{lddSKJrg]b[Ullkllk{{t{{ƒD;9JHFMRKVTLUTSuzt[TTddcD;9:97sle[TTdc\SKJHR>SKJrfktslmttJHFdc\ttslrilriƒ„„|‚z“Œ”ƒƒ|lek{{t†~‘MSSmtt^fsfkkŒ”•Œ‹“tt{mtt„„Š{{ƒ\[b{||[[T\[bultkd\\[bVZTmttlek“~ˆmtt{{ƒmtt{u{JHF[[Tdc\’ŒŒƒƒ|llktlltsluzt{u{ultllkJHFUMR]cdcbVVZTddcF=Cb[Uƒ||tlltlllddlld{{tdc\mtttllƒ}ƒzlldc\d\\SKJ[TTlekrfkbVZ‚wlaWM74,JHFlriD;9ddctllekdŒ‹“ttszll”“›u{{u{{VTL{zmb[U{{ƒu{{‹’Štllƒ‚utll]bZ]bZztlcbVultUMRF=CSKJiq]MRK3+**)(	*)(JHFredsleb[Ub[Ukk]cbVtslVTLFD;ZbNdc\jcVztfFD;]bZbVUtslb[UVTL[TTtslŠƒ}VTLZbNkd\rg]j]\{tt‰|vcbVFD;tll|‚z¦§¨>B9SKJ‘ˆ}›”›‹‹‹Šƒ}]cdjcVmttkk]ekd‹’Šš””ult„Š„‹’Ѝ©´”“›»ÂÇœ¤¦›¢›¬¶Ã‹’Š”š”{{ƒ””‹’ŒŒ{u{{||›”›ƒ}ƒztlª³·››””š”{{ƒ›”›‚|u‹„„ttsllk\[[b[U\[b]cd|‚z“Œ”{u{””‹\UZ]bZlkslld„Š}{||llkVZTMRKF=C>ECrfk[TTMRKttsJHFlddllk|„…“““mtttllj]\redUMRJHFSKJcbVVTLFD;ek]‹„„dc\j]\lldJHFlekttsuzt]bZSKJ]bZ‹„„ult‚|u[TTUTS]cdVTL[[TsleVTLD;9aWMVTLtll{{tuzttsl›¢›{||lriŒ”•“““œ¤¦™š¤‹„„¨©´|‚zzlllksOS`]bZlks]cdtts…‹‹\[b‹‹‹†~‘\[bddcUTS{||‹’Šƒ||{ttddcedkzllf]c{{ƒfkkUMRttsJHFllkVTLlddztl{ttttsdc\lri]bZddcttsVZ[JHFrfkf]cllk[[TSKJ‹„„””‹ƒ}ƒlddrfkjcVslekk]lld‹…’ƒ||‹„„|„…SKJ{{ƒUTS‚v{\[b[TTb[Uuzt[[T\UZkjVJHFD;9VTLllk‹‹‹bVZ{{ƒddc\[[\[[ƒƒ|›¢›lldddcrfktzl{||”š”…‹‹b[UFD;d\\VTL{ttd\\UTSFD;\[[FD;&&%74,>B9uzt{tt{yfztl{zmb[UaWMSKJVTLJHFVTLVTLVTL|‚zkk]VTLkd\lldbVUSKJ[TTkk]sleaWMVTLkd\SKJj]\tll‚utd\\ƒ‚ulektslª³·VZ[SKJzll£››„‰v’ŒŒŠƒ}aWMtts]bZUTSƒƒ|Šƒ}Š}ƒ]bZdc\›”›ª³·¦§¨Œ”•|„…™š¤d\\‹‹„ztlƒƒ|tts{zm“““j]\f]c“““¦§¨””‹«²«¦§¨‹„‹{ttƒ}ƒ\[[‹‹‹Œ‹“\[bf]cf]cŠŠ}ƒƒ|ŒŒšƒ||™š¤mtt“Œ”„Š„tyg””‹{||UUYtt{ttsllkUMRUMRnv‚„„Š\[[ŠŠ}ddctt{{{tƒ„„{{t\[[lddUMRredkd\lldaWMb[Urfklddsletllldddc\lld‚v‚ƒ„„UTSJHFuzt‚v{tllkd\ƒ||LKRJHF]bZb[Uƒ‚uMRKUTSkk]JHFbVU””‹dc\{{ƒsleult|‚ztts{{t{{tult…‹‹…‹‹„Š„tts]cdMSS>ECMSSldd„†™mttf]c}‡’ult{{t]bZdc\f]cSKJf]c[TTleklrif]c’ŒŒ‹„‹tts]cdD;9MRKFD;[[TSKJbVU[[T{ttlldƒƒ|\[bekd„„ŠlritslUMRlld™š¤ttsbVUttsŠƒ}›”›ƒ||‹„„‚|ulldiq]…‹‹ƒ„„{tt‹‹„‹‹‹ƒ||lkslek“Œ”tll™š¤‰|vƒ„„FD;JHF\[[dc\ultlriƒ„„ƒ}ƒllk{||tts{{ƒ{{ƒb[UztflldddcUUYiq]zllƒ‚uddctsl]bZf]cultf]ckk]\[bC8.D;9]bZJHF!FD;	74,VZTtllš””‚wlldd‚wl[TTSKJrg]C8.dc\sreaWMaWMPF=JHFFD;{ttSKJSKJ[TTVTLek]i\VSKJVTLVTLSKJ‚|ukd\VTLsrellktsl²²¬\UZ3+*Š}||‚zrr]‘Œ…tzlrg]ekd|‚zlld‹’Љƒv‚ut!VTL{yf¦§¨ª³·›¢›u{{¦§¨|„…rfk[TTlri™š¤ƒ„„™š¤¦§¨””‹””‹›¢›¦§¨„Š„ƒ„„‹„„‚|uj]\”“›|‚zLKR‹‹„{||tt{|„…FD;ƒ}Šƒ||…‹‹lksƒ}ƒultlri{||lrif]cuztedklksf]ctllttsllkUUY„Š„VTLdc\dc\…‹‹SKJ[TTd\\llk{||ƒ||ƒ„„SKJsle\UZf]cylemwrg]”“›ekdddcƒ}ƒVZ[JHFVTL{{tslekk]tll\[[ekdd\\VTLb[U{ttSKJkk]kd\{u{‚|uldd{zm’ŒŒ{ttƒ‚uŒ”•|‚z{ttlldultyl„tzlddcMSS\[bMSSUUYddc\[bMSSlks{{ƒƒ„„mtt\UZlld{{ƒtsl{ttƒ||f]c]bZŒ‹““~ˆultfkkztfMRKMRKtt{SKJr]ZVTLj]\sle‹‹„{{tlkskk]ttsdc\JHF]cdlri‹„‹Œ”•tll{tt””‹“Œ”ƒ||’…‹””‹ztllldttsŠŠ}’ŒŒœ››”“›|„…f]cf]cultƒ„„‹„„i\Vfkk]bZultkk]SKJ>B9VTLƒƒ|tsl‹„‹{{ƒ…‹’Œ”•mtt]bZdc\{zm…‹‹\[b|‚ztllƒƒ|tt{f]clri‹„„Š}|tllek]JHFsleJHFaWMJHF*)(:97!JHFbVZd\\j]\sle‚|ubVUVTLsleaWMztfztfHI/VTLFD;jcVVTLVTLSKJSKJJHFkjVŠƒ}VTLd\\d\\bVUSKJztl[TTkd\VTLult{tt¦§¨>EC:97{||„‰v„‰v²««™š¤ƒ‚uƒƒ|››”‚v{{||’ŒŒƒ}ƒ*)(&&ƒ‚n¨©´‹’Šddc|„…Š}ƒƒ||VTLD;9‹„„‹‹‹tll“““…‹‹‹„„””‹‚|u””‹”š”{{ƒƒ||””‹SKJ…‹‹tzl{zm„Š„™š¤“““\[[ztfƒ}ƒ{||ƒ„„VTL[TTb[U{{t‹‹‹ztl[TTSKJUTSMRKf]cUMRllklddultlekddcztld\\VTL‚wl\[[rfkkd\Š}|{||b[Ukd\red‹„‹{u{iq]‚|u[TT|„…tslekd[TTJHFD;9[[Td\\‚|u’ŒŒsle{||JHFVZTdc\kk]VTLVTLVTLjcVd\\{{t]bZ{{t{zmƒƒ||‚z”𔛢›Šƒ}ƒ||lek{{ƒtsl{u{{u{>EC>EC]cd\[[\[bmtt\[b{{ƒ”“›ultFD;d\\lkslld[TTlekUMR|„…¦§¨{u{ultŠ~‹mtt[[TVTLllkSKJztlredlld[[TtsluztVZTJHFFD;lriƒ}ƒf]cbVZztftzlš””’ŒŒ’…‹redƒ„„Š~‹{zmsleFD;sletsl“Œ”š””{u{ddcJHFUTSSKJf]c„Š„rfk\[[‹’Šd\\JHFJHFlldMRKƒƒ|ult{{ƒtll{u{{{ƒekdsletsl›¢›mttŠ}|‹’Šƒ||ŠŠ}„„Š|‚z|‚zz‚lƒ||lksƒ}ƒUMR\UZlekb[U\UZJHFVZT?;C3+*:97SKJ‚|uŠƒ}ztl‹‹‹rg]r]ZcbVd\\SKJi\VjcVcbVcbVVTLVTLaWMztl[TT[TTsre‘Œ…jcVredb[Utllred{ttredrg]cbV[[Tƒƒ|µ¶·\[[:97œ››””‹£››£››{u{š””ÃÄÆ””‹…‹’]bZ£››{{ƒ|„…lks’ŒŒ””‹…‹‹…‹‹‹‹‹“Œ”Š}|dc\iWUredƒ||tsl‹„‹“Œ”red””‹‹‹„’…‹cbV‹‹‹£››‹„‹f]cŒ”•fkklri››”Œ‹“Š}|lri]bZldd‹„‹…‹‹\UZj]\lddlldƒ‚uttslekSKJUTS\[[{u{rfkŒ”•bVZJHF[[TŒ‹“llduzt‹„„‚wld\\[[T\[[tll‚|uƒ||{{tlld„Š„f]c‚utb[UUMRztlŒ‹“bVZ„Š}JHF[TT\[[uztdc\‚|uŠƒ}…‹‹\[[“““‹‹„srelddkjVƒ‚nVTLaWMj]\VZTllk››”‹„‹d\\ekd‹’Š„Š}{u{{u{[[T„Š}{u{“““f]cMSSn…{{ƒ~’“…‹štts”š”tt{\UZJHF\[[|‚z|‚zœ››ultlekf]cŒ‹“‚v‚›”›ddcekdJHFmtt…‹’{ttŠ}|{tt{||SKJkd\››”|‚ztzluztkd\j]\F=C\UZSKJ{||{u{kd\‚uttlltllult{u{ztl‚wl\[[{zm‹u…ztl”“›[TT\[b\[[\[[llklriƒ}ƒUTS\[[tllŠ}|mttiq]FD;]bZ‚utƒ}ƒddcVTLddcŒ‹“kd\{tt\UZ‹‹‹ƒ„„tslš””ƒ||›¢›‹’Štyg|„…‹„„f]cUMR\[bd\\ƒƒ|VTLUTS>B9JHFUUY3)JHF‹„‹j]\‚|u‘Œ…‚|uslecbVdc\jcVŠƒ}aWMSKJb[Udc\rg]ƒ‚nrg]d\\rg]lldb[U‹„„ztfaWMSKJlldd\\‘…„ƒ||VTLdc\j]\“““Ä¿VZ[JHF£œ¥²¬µ””‹››”‘…„¢—””‹tslu{{]bZƒ}ƒ†~‘^~Y3+*’ŒŒœ¤¦Œ”•¦§¨™š¤ƒ}ƒ|‚zVTLiWUyle¦§¨£››‹„„|‚zŠ}|slesle‹‹„”š”|„…Š}ƒ“““\UZ]bZ›¢›|‚z„Š„¦§¨‹’Štzl{{ƒllkš””„Š„mttj]\dc\{{t›”›tsltts‹„‹\UZttsJHFSKJd\\lriult{u{{tt‹’Š””‹ƒ||Œ‹“UMRd\\‚ut{ttŠƒ}lddldd[TT””‹‚utš””Šƒ}ultkd\lddttstllUTSSKJUTSddc›”›’ŒŒb[Ulri|‚zƒ}ƒlriœ››””‹sresreJHFlddƒƒ|“““ƒ„„£œ¥”“›„Š„›¢›”š”œ››‹„‹{zm\[b{u{f]clrilri{||uzt{{ƒ…„’{{ƒuzt}‡’ƒ„„\[bJHFVTLfkk|‚z…‹‹{{tultƒ}Šlri‚wl{u{tsltyg›¢›mttlriVTLmw“~ˆsle|‚zŒ”•bVU{zmVTLf]cŒ”•bVZlddŠ}|‚v{zllf]cSKJ‚utultŠ}ƒzllllkcbVkd\{||b[Uƒ}ƒŠƒ}SKJSKJ“Œ”llkŒ‹“…‹‹…‹‹‹„‹]bZekdd\\f]cFD;VTLaWMcbVj]\ddc{u{\[bƒ„„Œ”•‰‘~d\\ekd„Š„„Š„‹‹„‹„„œ››„„ŠŒŒšFD;|‚zŠ}|ƒ}Šƒ}ƒtt{D;9lksJHF:C+MSSJHF	MRK’ŒŒttsi\Vlld{{tkd\f]crr]‹’Šrr]ultzllkd\VTLrg]VTLrg]j]\‚|uj]\FD;sletllƒ‚u\[[{yf[TTUMRaWMŠ}|VTL‚|u‹’Š‚|u¾ÆUUYJHF£œ¥£œ¥£››“Œ”ƒ‚n£››¤¤VTLƒ}ƒJHF‹‹‹{{ƒLKRr]gšŒ‹‹„|‚zª³·”š”œ››‹„„kk]Œ‹“›¢››”››¢›Œ‹“”𔋄„‹„„š””kk]…‹‹Œ”•ƒƒ|{||d\\lld”š”™š¤¦§¨{||{tttsl“Œ””“›ƒ}ƒ{||]bZ{{ƒred‹’Šttsƒƒ|ldd{{ƒlek]bZbVZlksƒ„„ƒƒ|{{tllk£››””‹¦§¨¦§¨”“›ƒ|||‚z‚|u{tt‹‹„i\Vredd\\ƒƒ|‹„„’ŒŒj]\\[[tslŒ”•ŠŠ}[[Tƒ||lks\UZtt{sle‚v‚ƒ}ƒ|‚z‚|uf]cuztek]ztlkk]tslSKJ\[[{zm…‹‹ztl””‹Š}ƒ{zmuzt››””››fkktt{{{ƒ‹„‹tts[TTUTSlld[TTtts”››|„…„Š„mtt]bZtt{ekdtslllk‹‹‹ŠŠ}mttd\\UMRekdtlltllleku{{MRK]bZ|„…kd\|‚zkd\‚wlcbV|‚ztslekdlddttslldyleultzll…‹‹{tt‚utSKJzll£››“Œ”‹„„¦§¨‘Œ…‹‹„ttssle{tttslldd|„…{ttultlriuzt…‹‹VTLJHF[[TUTS‹„„FD;JHFkk]rg]|‚zœ››‹„‹tsl|‚z|‚z›¢›{tt{{t”𔄄Ћ‹„£œ¥‹‹‹d\\tt{fkkVTLredtts[TT\UZ:97SKJVTLFD;:97%:97\[[dc\llk””‹ztlb[UjcV‘Œ…d\\kjVd\\aWMdc\VTLPF=SKJylelddVTLSKJVTLdc\{zmrg]{yfrg]bVZjV[zll‚wl{{t‚|uƒ||‹‹„µ¶·\[[74,¦§¨£››””‹£œ¥ldd‘ˆ}rr]b[Uƒ}ƒj]\ljƒ}Š:97SKJztl”“››¢›»ÂÇŒ”•‚wlƒ||llk‹„„£œ¥“~ˆ{||¦§¨¤¤‚v{‘…„kk]””‹›”›{{ƒƒ||œ¤¦’ŒŒ‹‹„””‹’ŒŒ{zm‘…„£œ¥“Œ”‹„„ƒ}ƒ{ttmtt[[Tf]clddƒ}ƒ‹„„{u{tllmttllkŠ}ƒtts{{ƒtsl‹’Š|„…VTL¦§¨››””››‚ut|‚z{||”š”rg]ƒ}ƒ{||sleVZTFD;red‰|vztfsle\[btslŒ‹“‹’Štts{ttldd‹…’[[Ttll””‹ƒ||œ¤¦ƒ‚u\UZultlldkd\cbVztlj]\bVU¤¤‹‹„lri‹„‹ƒ„„uzttslƒƒ|”››ƒ}ƒ‹…’{tt…‹‹‹„‹{{ƒJHFiq]llk[[T{u{{{ƒ|„…mtt{{ƒttsekdVTLddc‹‹„ƒƒ|ttsj]\Š~‹ddc{ttf]c{||]bZMRKmttu{{|‚zŠƒ}{||tsl”š”llk‚|u…‹‹tsltts{tt\UZŒ”•{tt|„…bVUllkredrg]ƒ}ƒ£œ¥‚utƒ„„‰|v¦§¨””‹{tt‚utbVUd\\VTLtllttslksƒ}ƒƒ}ƒÂ¾Æœ¤¦œ¤¦|„…f]c{ttdkVkk]jV[‹’Šllkf]c{zmfkkVTLz‚ldkVœ››œ¤¦”š”„„ŠŠƒ}|„…UTSekd:97r]gUTS:97ultedkJHFD;9dc\,553+*[[TD;9JHF[TTUTS‚|uŠŠ}{{tƒ||zll{zm‚utrg]rg]kd\SKJVTLVTL[[TVTLVTLldd[TTVTLsreƒ‚usreiq]VTLsle‚utredƒ||lld‚wlztlƒƒ|µ¶·\[b:97“““£œ¥‘Œ…‚wl{ttŠ}|‘ˆ}z‚lJHFœ¤¦š””jcV.1SKJ“Œ”µ¶·‹’ŠªÁŲ¬µ’…‹ultf]clld‚v{ƒ||‚v{™š¤ƒƒ|tll‚|u¤¤|‚z¦§¨Œ”•“““™š¤››”ƒƒ|‚wl‘…„›¢›{ttrfk}‡’ult“““œ››lritslƒ}ƒ””‹‹’Štzllrilks‹’ŠŒ‹“SKJf]c{tt””‹ŠŠ}UTS‹‹„‹„‹|‚zred{||‚v{‹„„tsl‚utb[Uztl{||[[Tzllkd\i\VlddŠŠ}ultuztƒ||”š”tllb[USKJ[[Tllk‚v{‹‹„yleldd’‘~[[TMRKkk]d\\SKJkk]j]\ŠŠ}””‹„Š„{{tultŠ}|tslu{{uzt{||¦§¨‚v{„„Š{u{{{ƒ|„…LKR\UZlddllk{{ƒ{{ƒlksnv‚mtt‹’ŠUTSVTL]bZtt{llktllƒ}ƒŒŒšŒ”•Š}|tslMRK]bZ]bZiq]]cdtzl[[Tsre{zm‹’Š{{t|„…|‚zttsƒ||rg]ƒ„„f]cƒƒ|‚v{dc\llkSKJ‚v{{tt£››ƒ}ƒllkztl|‚ztslztfƒ}ƒj]\rfkŠŠ}sle\[[ultekd„Š„Œ”•{{ƒ{{ƒlri…‹’z‚lJHFtzltslyle‹„‹ƒƒ|b[Uuztlrilrilld|‚zŒ”•„„Štt{™š¤„„Š]cdlrisreztlf]c{{ƒ“Œ”tll*)(SKJkd\VTL3+**)(D;93+*JHFJHF{{tztl‘Œ…Šƒ}ztfVTLSKJjcVVTLSKJb[UVTLkk]jcV‚wlj]\kd\i\V[[Tkk]ƒ‚u{{ttslZbNzllr]Zzllyle””‹[TTkd\{{tµ¶·LKRLKR›”›‹‹‹›¢›£œ¥f]c‘ˆ}¢—„Š}tt{““““Œ”j]\JHFUTS’…‹Œ‹“„Š„¦§¨¨©´²««™‹†ldd]bZ‚|u‹’Š|‚z{{tred[TTsle£››mttmttuztš””{{t|‚z‹‹„{{t’ŒŒ|„…¤¤›”››”›{{ƒ{{t„Š}{||{||ult¤¤‹‹‹lld\UZllk{||lddb[Ud\\‚v{uzt‚ut„„Šlri{||dc\jcV{{ƒllkƒ||ƒ„„{tt\[[kd\{ttb[Uƒƒ|tslƒƒ|ƒƒ|sleSKJ‹‹„›”›””‹r]glldf]c\UZVTLŠ}ƒƒƒ|ƒ„„{{tVTL{ttlksSKJtsl[[TJHFš””‹…’‹’Š{{tlriƒ„„…‹‹mttuztuzt|‚z|„…ultllk{{ƒ“Œ”{{ƒlks{{ƒƒ}ƒ|„…edk{{ƒœ¤¦|„…Œ”•‹„„{||sleddcddclldƒƒ|f]cŒ‹“…„’¤¤{tttslVTLVZ[tzl‹…’ƒ„„tsl“““‹‹„{ttddc…‹‹|„…|‚z””‹„Š}‚utƒƒ|‹‹‹mwUTS{{tslelek‚v{Š}ƒŠ}ƒtts‚utsre\[[b[U{ttŠƒ}‹…’“““{{tsleƒ„„‹‹‹lksd\\ldduzt„„ŠŒ”•mtt‹„‹œ¤¦„Š}[TT|‚zttsŒ‹“”š”JHFz}››”llk|„…™š¤Œ”•“Œ”{{ƒ\UZek][[Tƒ||š””tlllksƒƒ|mttSKJzllekd\[b?;CFD;"[TTƒ„„slei\Vsle‚utVTLrr]bVUPF=VTLjcVd\\lldVTLsrelddi\VVTLSKJ‚wlz‚lŠ}|lrirg]b[U{ttbVU‚ut‰|v’ŒŒ‚|ukk]|‚z¦§¨VZTUTSultƒ„„””‹‘}zrg]‘Œ…ƒ‚u–¢‹„Š„j]\j]\bVUMRKSKJ{tt¨©´œ¤¦›¢›”“›µ¶·£››‚ut””‹ztl‹„„{{t··Ä|‚zŠƒ}‚|usle‹‹‹u{{‹’Š{||{ttƒ‚u{zm{tt‹„‹””‹ƒƒ|š””{||Š}ƒ™š¤‹‹‹{ttlri¦§¨’ŒŒ™š¤‚|u‚v{d\\lek\[[]bZ[TTf]c„Š}uztƒ„„bVZ“Œ”ƒ||‚wldc\lddd\\‹’Š{zmtlltsl‹„„{ttj]\ztf„Š„kk]SKJŠ}ƒ|„…£››››”{tt{ttJHF[TTd\\ult’…‹ekdJHF[[TSKJ\UZdc\dc\SKJVTLultult‚|uµ¶·u{{{u{…‹‹|„…‹’Š››”|‚z„„Š{ttŒŒš„„Š£²‹…’\[b\UZult™š¤lksu{{ŒŒš{u{Œ”•kjVu{{\UZJHFj]\]bZ]cd\UZ{tt‹„‹‹„‹„Š}””‹…‹‹tzldc\Œ”•™š¤‹‹„››”{{t’ŒŒ{||sre|‚z‚|uredf]cSKJœ¤¦llkf]cVTLJHFSKJbVUŠ~‹yleš””bVZFD;kd\{yf””‹d\\{zmzll‹‹‹ƒƒ|rfku{{d\\r]g{{tf]cJHFultf]c„Š„]bZ]bZek]{{t‹„‹\[[{{ƒ{{ƒllkf]csleƒ„„„Š„‹‹‹tt{ŒŒš„Š„edk{{t“““ldd‚|u‹„‹|„…jcV{||ekd\[[VZT[TTF=CFD;74,lldf]ctll‚wlƒƒ|‚utVTL[[TVTLb[UVTLb[Ulrikk]bVZddcƒ„„SKJsle{ttVTL{zmƒ‚u|‚ztsllldlddtll‚v{rr]‚wlztf{{t‚wl¦§¨fkkMRKtts£››Š}|‹„„tzl’…‹‹’Š””‹ƒ}ƒjcVVTL|‚zF=C?;C¤¤›¢›„Š„…‹‹ƒ}ƒ›¢›tslsleƒƒ|ƒ„„šŒ|‚z”š”””‹Š}ƒ¦§¨‹‹„ƒ‚u]bZ‹’Š…‹‹”››ƒƒ|{{tƒ||“Œ”rfk²¬µ¤¤{u{tsl¦§¨™š¤lddekd£œ¥ƒ||Œ‹“››””“›d\\ƒ}ŠlldllkbVUzll¤¤|‚z[[Tsreultƒ‚uldd‹„„tsl‚wl‚|u{{t…‹‹tslf]cekdPF=bVUŠŠ}j]\[[T’ŒŒƒ}Šlddtt{f]c{tt:97lldUMRultekd]cdVTLbVUbVZfkk|„…ztltslSKJ{tttsllri‹‹„‚|u{{ƒlri‹‹„„Š„‹‹„œ››‹‹‹ƒ„„fkklkstt{JHFVZ[›¢›g\rmtt\[b{{ƒtt{ƒ„„œ¤¦d\\[[TVTLVTL{zmcbVtts{u{bVU{u{‹‹‹››”“““uztVZTttsuztuzt„Š„ldd””‹››”f]c„Š}„Š„[TTtsl‹’ŠMRK[[T{{ƒ‚v{d\\ƒ||tsl‘…„’ŒŒ’ŒŒf]c››”‚utrg]VTLkd\’…‹{{tlek[[TŠ}ƒtygllk””‹ljVTL[TT\[[|‚zlddƒƒ|dc\lri”››‹‹‹ƒ„„edkekd]cd{{ƒ\UZ[[TŠ}|uzt“““Œ”•{{tmttttsŒ”•lriVTLsle…‹‹lldr]ZD;93+*|‚zkd\{yfFD;JHFSKJjcVMRK‚|uƒƒ|dc\‚utkk]SKJtsl]bZbVUkjVsre[[TtllD;9aWMslesreultj]\sre””‹ƒ‚usreredtts‚ut£››ult‚wlƒ‚u{{t‘…„µ¶·]cdMRK‹„„“Œ”’ŒŒ£››£››™š¤ª³·š…Ž\[[{ttldd]bZ]bZzll‚wlƒƒ|‹„‹„Š„Š}ƒ””‹ƒ||SKJFD;š””‹‹„Šƒ}„Š„ƒ‚u“Œ”š””{tt”››tll‹’ŠŒ”•‹„„{{tŠŠ}ƒƒ|tllƒ||£››|‚zƒ„„¤¤red{||cbV]bZ{u{£œ¥›¢›¦§¨ztl\UZƒ}Ѝ©´|‚zŠ}ƒ‹…’{||tslƒ„„dc\𔔤¤{tt“Œ”‹‹‹ƒ||Šƒ}‹‹„“““slekd\ultsleztlult‰|vtll{ttllktllredUMRtslVTLtts{tt…‹‹{ttekd]bZaWMred‹„„llkƒƒ|‹‹‹””‹kd\Œ”•ƒ‚uœ››¤¤”“›‚|uƒ„„”“›‹’ЄЄ{||ultlek„Š„{{ƒddc]cdf]ctslŒ”•{{ƒ“Œ”lks{{ƒ…‹’j]\VTLFD;[[Tlddƒƒ|‹‹‹ultllk{||„„Šlriƒƒ|{{t{{t{|||‚zd\\‘Œ…‹‹„tzl””‹{{t|‚zƒ‚u‹‹„Šƒ}[[T3+*lektllyfltsld\\lddŠ}|‚ut{tt‚wl{u{VTLcbVŠ}ƒƒ||‹„‹‹‹„[TTVTLVZT‚utƒ„„tsl…‹‹{u{{yfmtt\[[{u{kjVŠ}|ƒ„„“Œ”¦§¨“““™š¤tzl|„…lkslldkd\„„Šllku{{‹‹„‹‹„|‚ztt{””‹VTLƒ‚usleJHFbVUUTS:97UTSD;9VTLiq]JHF%PF=b[Ulekrg]„Š}|‚zƒ||‚|utslkk]kjVVTLdc\llkdc\JHFb[Ukd\[[Tb[U{tt‚wl‚wl‰ƒvtsl{zmš…Žred²««‰|v¤¤sleŠŠ}‘ˆ}‹‹‹¦§¨\[[JHFŒ”•¦§¨“Œ”‹„„ŠŠ}‹’Š‹’Šultdc\dc\‹„„kd\VTL’}™£›››¢›””‹«²«…‹’{{ƒ[[Tdc\b[U¦§¨””‹kd\›¢›lri’ŒŒƒ||””‹Šƒ}tzluzt|‚z™š¤sre›¢›””‹tllr]gz‚l‹‹„lri””‹¤¤››”‚|u”“›Š}ƒš””””‹ŠŠ}ƒ„„‹‹„|‚zttsVZTŠ}|{{ƒtsl[[T‚|u‘Œ…ŠŠ}‹‹„ƒ||llk“Œ”tllƒƒ|‘Œ…tslŠƒ}Šƒ}lddred‹„„aWMtllƒ„„cbVJHF[TTult{u{j]\UTSllk„Š„Œ‹“ztl|„…››”tzlkd\ultƒ„„{{tŒ”•’ŒŒ‘…„›¢›ztltslkk]‚|u‹„‹{||lkscbV””‹mttŠŠ}›”›‹…’lksJHFuztmtt|„…ulttt{ŒŒš…‹š„Š„{||mtt\[[{zmSKJMRKlek‘…„ult„Š„„„Šult[TTlritsl|‚ztsllri…‹’{tt””‹µ¶·ƒ„„Œ‹““““‹‹„ƒƒ|š””|‚zdc\b[Uedkrfkred‹‹„[TTƒ}ƒŠ}ƒ‹„„Œ‹“””‹‚v{[TTkk]‚|u‚ut‰‰w‚v{lldƒ||SKJd\\tll{||j]\mtt„Š}ƒ„„tsl{zmztl|‚zª³·¤¤“““ƒ}ƒf]c]bZu{{{ttƒ||ztlred…‹’‹‹‹u{{Œ”•Œ‹“””‹tsl‹‹„ƒ‚u|‚zƒƒ|UMR7-2SKJFD;MRKLKRtt{3+*73JHF[[T‚utsledkV[TTPF=VTLFD;bVZƒ‚u‚|u{zmtsl]bZ{||i\VztlSKJ‹‹‹edk„Š„¤¤‚wl|‚zr]Zljzll‰|vlj‚|uŠƒ}ƒƒ|‚v{¦§¨[TT:97ƒ„„tsl’ŒŒƒ‚uuzt£››Œ”•””‹„Š„\[[Š}|lld]cd“~ˆ””‹›¢›””‹””‹f]c[TTb[Uyletzl{{ƒztl„Š„””‹[TT“Œ”bVUƒƒ|’ŒŒ{{tddc”𔋄‹lrisreVTLtllult‹‹„kd\Œ”•”š”ƒ‚uš””‹„‹|‚z™š¤””‹{zmŠƒ}›¢›lritzl{tt‹’Ф¤‹‹‹ƒ„„{{ttslkk]ŠŠ}red‘Œ…“Œ”tsl‚ut’ŒŒztllri{zmaWMƒ‚ujcVd\\SKJVTLkd\{u{\[[lri{{tf]cSKJ{{ƒ[TTrfkttsƒ||lri’ŒŒ’ŒŒyfllek‹‹„{{tult{ttsresre{zmŠŠ}sretll‹„„{||lri‹„„kk]{||{{t“Œ”ultf]cVTLVZ[|‚z]cdmtt‹…’llk„„Šƒ}Šttsdc\MRKjcVtslztl””‹ultf]ctslult£››Š}ƒ„Š„dc\|‚zVTLttsultƒ||’…‹‹‹„››”›¢›„Š„Œ‹“‚|uztliq]lriSKJu{{UMR|‚zSKJf]cŠ}ƒ’ŒŒ‹‹‹‹…’{||ƒ}ƒf]csre{u{lddŠƒ}ultuzt\UZVTLlrilld‹‹‹{u{ddcek]lddkk]b[Usle„Š„ƒ}ƒ’…‹‹…’’ŒŒœ¤¦‹…’\[b””‹{zm…„’ztl{||‹‹‹|‚zƒ„„„Š„„Š}]bZƒ‚uƒ}ƒ|‚zttsmttlks[[TVTLFD;74,UTS3):97iq]dc\|‚z{{tVTL‘…„‚|uƒ„„cbV[TTVTL|‚zsle\[[VTL‚|uztlŠƒ}ƒƒ|edktll‚wl‚|utsllldd\\d\\Š}|ztlƒ||ƒ‚u{zmƒ‚u‚v{£››UTS*)(‹‹‹“““‘Œ…ztfVTL‰|vlriVTL”š”llkr]Zb[U:973+*‹’Šœ››¦§¨rfkyfl‚|ubVUVTLFD;redƒƒ|””‹››”ultult‹„‹”“›Œ”•‹’Š¡¡¨©´Œ‹“{{ttsl£œ¥‚v{lri¦§¨‹‹„…‹‹‹‹‹““““Œ”‹‹‹lks™š¤™š¤‹„„””‹”š”„Š„uzt›¢›”š”””‹tt{‘}zedkaWMek]‚|uztfzll‹„„ƒƒ|tll{tt‚wlkd\rg]sleŠ}|ztllrir]gSKJf]cb[Uekd‚|u{ttŒ‹“d\\UTSult‹‹‹ƒ„„‹„„tslsleƒƒ|kd\uzt‹…’„Š„lkskd\SKJlld””‹|‚zlld…‹’‹„„„Š„Œ”•{{ƒtzllldlldŠ}ƒddcf]clksJHF]bZmtt\[[tt{ƒ}Š{{ƒu{{…‹‹bVZFD;tslddclld‚|uu{{lks{{tƒ„„ƒƒ|’ŒŒ{{tuztekdUTSŠ~‹ztlŒŒštt{‹‹„£››‹„„uztŒ‹“{{tztlŠƒ}kjVuztŒ‹“ultjV[””‹‰|vjV[‚v‚ƒ||„„Š‚utf]c{{tcbVƒƒ|{||‘Œ…“Œ”ztfultb[Uttstll””‹ddcƒ„„MRKlriVTLFD;lld|„…llk{u{llkš””’ŒŒ™š¤“Œ”mttœ¤¦ƒ„„‹‹„‹…’™š¤llkŒ”•tt{ŠŠ}”𔦧¨“Œ”lriekd]cdf]cbVUVTL>B9FD;:97FD;&&C8.{{t„Š}‹‹„kk]ultsleulttslJHFVTLVTLsre]bZVTLbVZlldlddcbVlld’ŒŒ„Š}‚wlttskk]ƒ||ƒ||Š}|‚wlbVU‚|usrei\V‚|u‘ˆ}>B9:97››”ƒ„„‘Œ…””‹jV[bVZu{{i\Vekdllkkd\aWMVTLJHF¤¤™š¤™š¤|„…tts{u{sle\[[tzlr]gtslldd|‚z’ŒŒƒ||“““£œ¥ƒ||lri|‚zƒƒ|™š¤‹‹„SKJ„Š}™š¤{|||‚zkk]tsl|„…“““ƒ„„Šƒ}VZ[™š¤‹„‹›”›’ŒŒ‹‹„‹’Š|„…{zmƒ}ƒ””‹„Š„ztflld{zm{||„Š}SKJb[Uƒ„„ƒƒ|[TTredzllztllddƒ‚uylelj{u{tllƒ||llktllƒ„„””‹ƒ„„ultb[U{{ƒJHFtsl{||lriƒ‚u‚v{]bZƒ}ƒ|„…Šƒ}u{{tts‚wlsle‚|ulld‹’Ц§¨‹„„ƒ}ƒ„Š„ztlŠ}|ƒ‚udc\ekd’…‹rfk{{ƒmttF=C>EC]bZf]c”“›…‹’…‹šƒ„„”››dc\\[bVTLVTLUTS‚|ui\VF=Clld‹„‹‹‹„ª³·‹’Šiq]dc\[[Tƒ„„ƒ||{||šŒƒ‚u›¢›„„Šuztuzttsl””‹›¢›Œ”•]bZ™š¤redultƒƒ|rg]f]c[TT|„…‚v{Œ”•ƒ}ƒ|‚z‚|u‚v{Š}|{zmƒ||ƒ„„redbVUUTS{u{lldƒ|||„…lri|‚z‹‹‹kd\d\\kk]u{{ult\UZšŒtts\UZtt{…‹’¨©´’ŒŒ™š¤”››‹„„u{{{||‹‹‹”››ƒ„„¤¤‹„„lrilld>EC%FD;74,FD;SKJVZT3+*&&C8.yle|‚zƒƒ|ƒƒ||‚z‘Œ…Šƒ}JHFJHFlri]bZVTL:97VTL{u{tzlŠ}ƒlddrfkllk{zmlriƒƒ|VTL‘Œ…rfkŠƒ}‰|v{u{””‹Šƒ}‚utztfµ¶·MRK*)(‹’Š‚ut|‚z‘ˆ}{zmJHF|‚zllkuztlekttsi\VD;9D;9‹‹„«²«ŠŠ}Œ‹“””‹{{ƒcbV[TT‹’Šedk‹‹„ƒ||¤¤’ŒŒ™‹†‹‹‹’…‹b[Uƒ„„lri¦§¨ª³·””‹kk]Œ”•”“›ddclldVTLekdSKJj]\F=Cj]\{{ƒ„„Šƒ„„››”’ŒŒsle]bZlld{zm‹‹‹””‹‹’Šrg]ddcf]cj]\‹‹‹š””“Œ”j]\ddclddŠƒ}š””tzlztlsleƒ}ƒ‚ut{||Š~‹“Œ”fkkŠ}ƒ|„…tslmttf]ctslUMRSKJ‹„‹lksslef]clddddc{{ƒŒ”•‹„‹tslƒ„„tts’ŒŒlriuzttslz‚l{||‚utsreƒ||’ŒŒ…‹‹uztVTLtllultddcedkekdLKRu{{lkstts…‹’œ››Œ‹“”“›{tt{{ƒj]\MRKVZTrfklektsluztƒ}ƒ“Œ”“““ttstsllks‹„„…‹’„Š„ttsƒƒ|lldŒŒšŒ”•‹‹‹{||ldd“Œ”‰‘~„Š}mtt{{ƒ“Œ”£œ¥‹’Š‹„„lek‹‹‹ƒ||tts”“›‹„„ƒƒ|ƒƒ|‘Œ…‚wl››”£››b[U\UZtllrfkldd‚v{”››”››|‚zƒ}ƒ„Š„j]\‚|uSKJ{{ƒJHFddcredult„„Štt{ult‹„‹{zmµ¶·”››ultldd‹‹‹…‹‹”››‹„„¤¤‚utlldllk]bZ:97aWM3+*C8.Q?@F=C%&&&tlllri{zm‘Œ…VTLƒ||VTLƒƒ|ztl{u{JHFVTLlldJHF\UZ[TTtsllddtlld\\tts[[Tsre[[TVTLkd\kd\ŠŠ}£››£››rg]Šƒ}sle‚utµ¶·MSS:97tslƒƒ|“““‚wlekdJHF|‚ztt{uztdc\|„…rg]74,bVU…‹‹”››””‹“““UTS{||ddcekdlritsl‹‹‹’ŒŒ‹‹‹‹‹‹Šƒ}sleƒ„„””‹llkVZ[‹’Šœ››‹’Š{tt\UZ„Š„{||ƒƒ|VTLSKJ]bZ’ŒŒœ›››”›FD;[TT“Œ”¤¤¤¤‹„‹‹‹„œ¤¦””‹|‚z¤¤mttrg]tts‘…„‹‹‹d\\rg]Š}|{ttƒ„„‹„„kk]tsllldtsl‚v{{zmkd\ldd’ŒŒƒ„„mtt„Š}ƒ}Š‹„„ƒ„„{u{f]cultUMRztlult’ŒŒj]\Š}ƒkd\llkƒ||lri„„Š{||ttsf]c[[Tsreƒ„„‹‹„‹‹„{tt””‹{||ttstsl{tt{||‹‹„Šƒ}lek{ttuztMSSmtt“Œ”{u{ek]{u{{u{f]ckd\lddd\\SKJtsl’ŒŒf]cdc\{{t[[Ttllf]c\[[u{{mtt{||ekd‰|vŒ”•kd\””‹‚|u›¢›²¬µƒ„„Œ‹“‹‹„{ttVTL[[TVZTlri‚|uœ¤¦Šƒ}“Œ””››ƒƒ|{u{tsl{u{{tt‹‹„‹„„‚|u|‚zllkultlddslej]\{u{j]\‹‹‹ƒ}ƒƒ„„tzl“““‹‹„Šƒ}UMR[[Tj]\{tt‹„„ultf]c\UZ‹‹‹slerg]‹‹‹f]c{tt„‰v‹’Šfkk””‹f]ctsl\UZŠ}ƒ{u{{{ƒ:97lldmttF=CFD;>B9FD;|‚zj]\|‚z|‚z‚wlsletzlaWMrfk[[T[TTlri{zm\UZ‹’ŠlddcbVtsllldSKJttsttsVTL[[Ttllsre[[Td\\{zmrg]lldrg]ƒƒ|‰|v{zmÃÄÆJHF3+*{{t””‹”𔢗rr][TT”“›|„…ƒƒ|llk{{t‚|uC8.JHF{{t“““uztœ››{{t”“›ƒ}ƒlksdkVŒ‹“lld‹’Š‹‹„ƒƒ|‹‹„¦§¨œ¤¦\[[|„…ƒ„„‹„„£œ¥ztl‹‹‹“““tzl””‹|‚z“Œ”lri£œ¥ƒ}ƒ{u{‚utultª³·{{t’ŒŒ‹„„‹’Š‹‹‹tslkd\””‹jcVš””‘Œ…ƒƒ|‚|usleƒ„„‘…„r]gyledc\d\\‚|ulld{{tsletllrfklddllkyleœ¤¦ekd{u{edktzl{zmlekf]c{{ƒVTLrfk‹…’””‹]bZ|‚z[TTŒ”•{u{ƒ„„tzl”š”fkk{{t””‹redlri””‹‚v{lld[[Ttslzll’ŒŒ|‚z{{tƒ}ƒ’ŒŒ…‹’lek{||Œ—££››‹…’Œ‹“{{ƒ{{ƒ{u{ttsttsfkkd\\\[[‹’Š™š¤zll{u{››”ƒ||ƒ||¤¤]cd|„……‹‹“Œ”|„…››”Œ”•‚utƒƒ|tsl“Œ”””‹Œ”•œ››””‹ƒ„„JHFmtt{{t…„’‹’Šœ¤¦«²«‘Œ…ƒ‚uult””‹“Œ”tt{kd\{zm’ŒŒ‘Œ…sre{u{\UZlekult’ŒŒ“Œ”š””‹„„|„…lrirg]””‹iq]ƒ||“““ttsldd‹„‹[TT“Œ”ultƒ||lldredlld‚v{“Œ”Œ”•ƒ||“Œ”ƒ„„¤¤kk]u{{“Œ”VTLb[U…‹‹\[bSKJ{{ƒr]gUMRƒ‚uVTL]bZJHF\[b{||‚|u“Œ”dc\kk]ultrg]\UZtsl„Š„tzlddclddu{{tts{{tVTLredUTSUTS]bZdc\]bZrg]SKJrg]{yfkd\i\VSKJsreldd¦§¨SKJ:97””‹‹„„{zm‘Œ…]bZttslri„Š„ƒ‚ukd\dc\rg]PF=bVU‚v{œ››”š”œ¤¦ztl”“›Š}ƒtsl„Š„”››ƒ||“““¦§¨‹…’‚ut{||ddc‹‹‹b[Utts””‹Œ‹“lddkd\lrilritzlŒ”•ƒ‚u„„Š‹„‹µ¶·„„Š“Œ”tts¨©´Š~‹£››d\\dc\ldd…‹‹jcVVTL{{t{ttztltslƒƒ|ztl{{t’ŒŒŠ}|Šƒ}rg]mw{zm{zmredrg]‚v{lddred”“›ult‚v{fkkd\\‹„‹kk]ƒƒ|‹‹„‹„‹lek\[[kd\ƒ}ƒtllƒ„„|‚zek]uztŠ}ƒuztlri‚|ufkkƒƒ|”š”{tttslƒƒ|{tt“““‹’Š“““lddƒƒ|”𔋒Йš¤ulttllb[Ukk]|„…œ¤¦™š¤Œ”•£œ¥fkk|‚z‹‹‹{tt[[Tslelri„„Š|‚zŒ”•¦§¨‹’Š{||‹…’{{tVZTdc\\UZ|„…|„…llkŒ‹“ƒ„„“Œ”‹‹„£œ¥ƒ}ƒ›¢›ƒ||ekdttstts”“›{u{””‹{{tttsztluzt£››‹„‹‚v{tlld\\sre‹’Š’ŒŒ‘Œ…{tt‹„„d\\Š}ƒ{{tldd[TT…‹‹lldbVU’ŒŒ›”›tll‚utllktzl‚|ubVZlekllkSKJlri[TTttsd\\{zm’ŒŒ¨©´„„Šƒ||ƒ„„“““›”›‹‹„tllbVZkd\„Š}]cdu{{:97{{ƒJHFD;9”š”|„…]bZ:97dc\{||rg]‚wlekdtslztlllkultsrettsŠ}|mtt{{ƒ{tt|‚zš””{||ƒ||d\\slesrett{ŠŠ}b[Ub[UcbVrg]””‹cbVjcV‚wlrg]µ¶·ddc*)(‹’Šœ››„Š„zll›¢›u{{lld„„ŠsleUTScbV{zmHI/ultult¤¤‹’Š‹’Šred™š¤f]c{zm‹‹‹tts{{t”››‹„„£››ult¦§¨ult…‹’dc\{||tts¨©´”š”„Š„„Š}…‹‹Œ”•ƒ||cbVtt{{{ƒ£œ¥tts‚ut‚v‚ddc”“›š””ƒ||f]c‹‹‹UTSkk]lldVTL{{tƒƒ|‚|ud\\ztlsreƒ||‘Œ…‰ƒvbVU‚utlrilldVTLVTLd\\kd\b[U]bZ’…‹{{ƒJHFd\\ultek]tslƒ||ƒ}ƒlri]bZdc\lek]cduzt{{ƒkd\b[UUTSult„Š}slelek””‹ek]‹„„tsl{{tred{{t{zmj]\lkscbV{{t|‚zult’…‹kd\lekUTS{{ƒekd{{ƒ”“›“Œ”{||ƒ„„œ¤¦‹‹‹‹„„›”›„Š„‹’Š{||tllƒ„„ek]tt{ƒ}ƒ{||‹’Šlldlek{{ƒŒ”•tslŒ”•‹’Š’ŒŒ›¢›“““”“›”š”ƒƒ||‚zmttf]c]cd…‹šddcztl|„…ƒ‚u|‚zuzt„„Š‹„‹{{ƒf]clksƒƒ|¤¤«²«››””𔄄Š{u{zllult‹‹‹fkk“Œ”’ŒŒ‹„‹‹„„tlllldsle‚|u£››{{ƒƒ||lrildd‚|ubVUttsultztfŠƒ}tll…‹‹rfk{{t…‹‹‹„„cbV{||mttƒƒ|UTS]bZUMRD;9\[bekdzllVTL{ttedkSKJ>B9f]c{zmredVTL„Š}Š}ƒb[U\[[{{ƒfkk‹‹‹{||lks{{ƒ[[Tllkdc\dc\‹‹‹u{{Šƒ}‹„„„Š„dc\lri‹‹„{zm””‹›¢›ljsle‰‘~²««[TT:97››”””‹¦§¨’ŒŒuztttsj]\f]cVTLbVU{{t{ttFD;JHFyfl‘Œ…zllmtttsldc\d\\kk]”𔓓“‹„„”››””‹…‹‹šŒŒ‹“lks‹’ŠŠƒ}llk„Š„µ¶·œ¤¦…‹’{|||‚z|„…{||ƒ„„uzt‹„‹”“›ultšŒlrittsœ¤¦’ŒŒ{tt„Š„ult{||sleŠŠ}£››{zmslesreVTLtllsre’…‹i\V‚wlultš””lldztllldtllkd\VTLSKJƒƒ|ƒ}ƒlektslzlllriVTLd\\{ttultuzt\[[VTLrfkttsttsuztkd\b[Ulriƒ}ƒ{zmrfkJHFJHF74,b[U{{tVTLllktslsrelriƒ‚utsl|‚z‹„„ult‹…’bVU{u{ekdmttfkk£œ¥ƒ}ŠŒ‹“¦§¨{{ƒu{{f]cƒ}ƒJHFcbVllk‹’Š„Š}{||‹„„…‹‹£››{||lldŠƒ}|„…Œ”•Œ”•|‚z…‹’ƒ„„‘…„‹’ŠŠ}|{{ƒu{{JHF]bZredyl„lksllksreztf|‚z’ŒŒ’ŒŒ¤¤{{t{u{‹…šf]cd\\lldsle‹‹„|‚z„Š„Œ‹“\[[tllztlred“““{ttŠ}ƒtll…‹‹ek]bVUtsl‹‹‹²««š””‚v‚{{ƒŠ}|ultekdlek‹„„yle‹„„œ››œ››lld‹‹‹“Œ”tzl{||slemttuztMRKVTLJHFFD;FD;tzlD;9lldsre]cdJHFJHFddcaWMrg]VTLtslƒƒ|edklddlek{{ƒllkUTSddc{tttzlult{||llkultŠ}|ƒ„„‹‹„{{tSKJi\V””‹{zm””‹£››¤¤{||ŠŠ}‹‹‹VTL:97‘Œ…„Š„‹„„‰ƒv‹‹„ƒ„„‹‹‹[TTjcVkk]kk]VTLbVU%UTStslƒƒ|…‹’{{tlrid\\lksuztœ¤¦ldd””‹“Œ”{||¤¤“Œ”“““””‹ƒ}ƒ”››››”£œ¥z‚l¦§¨‹„‹ekddc\ƒ||…‹‹ƒ„„\UZultkd\‚v{VTLddc”š”lek›”›“““œ››lld›¢›ult‹„„kd\rg]‚|u{{tlddlrid\\ŠŠ}›”›‚wlred\[[sref]c‚|uVTLSKJVTL‚|uultredfkkd\\|„…dc\lldlektlllld[[T‚v{f]c{ttlri„Š„d\\zlllriultztl\[buztddclldrfkuztcbVllk‹‹„„Š„Šƒ}{||lddƒ}ƒ|‚zƒ||Š}ƒmttŒ‹“lks|„…”››tsl]bZ|„…ttsƒ}Štts\UZtts]bZultlldlks‚|uƒ||tllldd£œ¥ƒ„„llk…‹‹‰Š¡ƒ}ŠfkkŒ”•„Š„‹‹‹lld››”“Œ”‹’Š‹‹„›¢›\[b„Š„lldtt{d\\dc\„Š}ƒ„„‰|v‚|u‹’Š„„Šƒ„„‹„‹edk{||[[T‹‹„{{tƒƒ|‹„„‹’Š™š¤’ŒŒr]gŠ}|‹„‹‹„„œ››{{ƒ|‚zrg]llk‹‹„‚|uƒ}ƒƒ„„ƒ„„ƒ||rfk“Œ”‹‹‹tt{{u{zllkd\Š}|tt{sre‹’Štllƒƒ|\UZddcek]…‹‹‹„„|‚z\[b>B9\[[ddc\UZVTLJHFC8.JHFFD;ddcylecbVztllriztlllkddclek{ttttsllkllktts””‹‹„„ddclek{tt|„…tsl’ŒŒsrerfkcbV‰ƒv‰|v£››””‹‰|v“Œ”‚|u¤¤VZ[JHF‚|u{{tœ››Š}|ƒƒ|{{ƒ™š¤†~‘lldtllkk]‰ƒvsleD;9UMRultsle{{t‹‹„“““uztu{{Œ”•“““››””š”™š¤‘…„ult‚utldd[[T’ŒŒddcŒ‹“‹‹„“““Œ”•š””tts”››‹‹„Œ‹“”››œ¤¦“Œ”Š}ƒ¦§¨b[UllkŒ”•£œ¥›”›|‚ztslœ¤¦llklldlldrg]cbV‚|uVTLj]\{{tztlztl‹‹„red“Œ”d\\ƒ‚u‹’Š{ttFD;cbV{{t¤¤’ŒŒultztlSKJ]bZMRKkk]ƒ}ƒ“Œ”u{{tsl››”“Œ”‹’Š|‚zu{{Šƒ}‹‹‹ttsƒ}ƒylef]c›¢›]cdlridc\”››‹’Š{ttœ¤¦{zmultlld{||tllllk{u{ƒ„„[[Tdc\]cdlks…‹’lks‹’Š{{ƒtt{lks‹uŠbVZldd\[[{tt\[[]cd‚utƒ}Štllƒ}ƒ“““‹’Šƒƒ|Œ”•‹…’lks··Ä‹’Š‹’Š“Œ”’ŒŒkk]“Œ”›”›ttsuztllk{{t{||edkJHF“““‘Œ…”“›‚utuzt””‹›”›lek‚v{Š~‹tlltsl’ŒŒlriƒƒ|‹„„”“›ƒ||ultj]\‚|utts{ttlddƒ||b[Usleš””lri””‹“““{||Œ‹“ƒƒ|”“›“Œ”ƒƒ|‹„‹“Œ”ƒ||š””“““{{tslemttjV[tsl‹’ŠŒŒšllkmttSKJMRK]cdJHFD;9JHFSKJD;9fkkaWMedk‚v{ddcrg]{zm››”lld{zm„Š„tts„„Š{u{bVU|‚ztllƒ}ƒ“““|„…‹„‹lddttsŠƒ}lldŒ‹“tslrg]b[Uƒƒ|ztlƒƒ|‰|v‘ˆ}rg]››”µ¶·UUYLKR‰ƒv¤¤Š}ƒ™‹†ƒƒ|[TT{ttuzt‚|uƒ„„i\Vrg]FD;VTL[TT{||dc\|‚zƒ||tts]bZ\UZ››”’ŒŒŠ}ƒœ¤¦ƒ„„‹„‹‹’Š’…‹‹’Š|„…tt{dc\ƒ}ƒƒ„„„Š}jcVzll…‹‹lri¦§¨‹„‹„Š„ƒ„„lks“““›”›ekd‹…’‹‹„¦§¨¦§¨”š”d\\lks›¢›tslŠŠ}srerfksre{{t‘Œ…””‹‚ut‹„„›”›jV[Š}ƒ{||ƒ‚uƒ||tzlek]cbVmtt[[T‹„„lekSKJlld|‚z››”’ŒŒ’…‹‚ut|‚z[TT””‹…‹‹tsl|„…‹‹‹slelldFD;sreƒ||“Œ”|‚zƒ„„{{t‚|uƒ„„ƒƒ|”“›‹‹„‹‹„‹„‹£œ¥“Œ”‚v{‹’ŠŠƒ}{ttultuzt|„…MSSmttu{{ttsllklkstt{{||Š}ƒlekuztƒ‚uddcultttsƒ„„{{ƒ™š¤ldd”“›”š”™š¤··Ä„„Š|‚zfkk“““‹…’”š”tslztlƒƒ|uzt‹’ŠŒ‹“‹„‹‹…’tlllekdc\‹„„‹’Š“Œ”‘…„‹’Š›”›’…‹¨©´ƒ||VTL„Š}ƒ||ƒƒ|Œ”•{ttŒ‹“”“›””‹tts“Œ”u{{ƒ||ƒ„„’…‹‘Œ…‚wllks|‚zkk]ƒ}ƒsle“Œ”Š~‹‚v{œ¤¦redrfknƒ’…‹£››“Œ”tslŒ”•cbVztlƒ‚u{||ŒŒšƒ||UTSFD;ZbN:97:97SKJ[TTcbVsreSKJVTL[[T{u{[TTsleult‚wlcbVŒ”•dc\{ttlekƒ„„ztlnv‚mttƒ}ƒ‹‹„ƒ„„tllf]clddcbVdc\‹„‹kk]‘ˆ}ƒ||ƒ‚u””‹””‹‚wl‚|u£››“““¤¤\UZ>ECztf›¢›‹„„rg]iq][[TŠ}ƒllkztlkd\tts””‹redFD;{tt{tt‘…„|„…|‚zŒ”•ekd{{ƒ‹„„ƒƒ|ƒ||¦§¨¨©´²¬µ£››“Œ”‹’Šmttƒ„„tll{{tekd››”kk]Œ‹“‹‹„ƒ„„™š¤tt{”››‹„„Œ‹“‚ut“Œ””š”ekd’ŒŒŒ‹“‘Œ…{{t””‹tt{ƒ„„”𔋋„””‹Š}|‹„„{{tjcVƒƒ|ƒ||””‹‚wl{{t\[[d\\lld{||iq]rfk„‰vdc\d\\[TT\[[tts””‹llk|„…š””’ŒŒ‚v{ƒ„„f]csle{u{ƒƒ|…‹’lldSKJd\\tll‹‹‹‚|u£œ¥ztflld‹‹„””‹uzt{{t“Œ”Œ”•‹„„|„…‹„„œ››ƒ„„Œ”•ztlbVZddctsllld}‡’|‚z{{ƒddcŒ”•ƒ„„lksƒ}ƒddc“““\[[{||tt{{{ƒ””‹‹„‹„„ŠšŒ{tt“““ƒ||¨©´™š¤›¢›lkstt{ƒ„„…„’””‹{{t{u{œ››”“›Œ”•„„Š…‹‹‹„‹™š¤lriztlrfkf]czllztltsl›¢›ƒ}ƒƒ„„ultldd|‚zƒ||‹‹‹dc\‹‹„£œ¥š””b[Ukd\{zmtslŠ}|Œ‹“‹„„””‹ƒ||ƒ}ƒlriSKJrfkultf]cƒ}ƒ“““lks‚|u™š¤ƒ}ƒš””Š}|ƒ||Šƒ}‹‹„„Š„””‹{zmƒ}Š|‚z’ŒŒttsb[Ullk\[bFD;%UMR[TTtzlJHFVTL’ˆVTLlriŠ}|kd\Šƒ}ƒƒ|llkttsllkddcllkƒƒ|ult{{ƒ{u{„Š„Œ‹“u{{lksult‹‹‹‹„‹{||ƒ‚u{tt››”¤¤””‹‚|u‚v{¦§¨‰|v‹’Š›”›UMRJHF{{t””‹j]\‚|uttsb[Ub[Ured‰|v‚|u{ttztlD;9FD;{{ƒ“Œ”sle|‚z‹‹„œ¤¦llk[TT|‚z“Œ”‹„‹„Š„‚v‚µ¶·››”|„…œ¤¦mtt…‹‹|‚z”š”|„…{{tƒ„„{||”“›{||ƒ„„lkskd\f]c{u{‘Œ…{tt‹„„ƒ}ƒ¨©´{ttrg]‚|uldd{u{Š}|tllkk]tsl’…‹[[TVTLš””|‚z“Œ”‘Œ…‰‘~‰‰wtlllritsld\\JHF’ŒŒƒƒ|tslƒ||{tttts\[bekdllktsl‘Œ…‚|u‹„„lritlllek‹„‹|‚zdc\‹‹„lldttsd\\‹„„bVUtlltts[[T[TT{{ƒttsVTL{u{›¢›lridc\Š}ƒƒ||ƒ||‹‹„lddf]c{{t”š”{{ƒmttfkklldmttuzttt{lksVZ[{||ztlVZTƒƒ|llkultŒ”•’ŒŒ\[b‚v{‹’Š«²«ƒ||™š¤¦§¨¦§¨Œ‹“{{ƒu{{™š¤”“›ƒƒ|›”›ƒƒ|‹„‹|„…µ¶·›¢›™š¤„„Й𤋒Šf]csre‹„‹tllllkkd\‹„‹‹„‹{||d\\llkult””‹tts‹‹„]bZ‹„„lld[[TSKJult‚v{{||’ŒŒ“““{||“Œ”tzli\V{tt„Š„Š}ƒ‹„„š””fkk\UZ{u{tllƒ||redƒ„„””‹ƒ„„„‰vuztdc\{||ekdj]\tlllddVTLMRK[[T>B9\[[kd\tsl\[[MRK*)(u{{{||redj]\‹‹„œ››ttsekd[TT[TTddc‹„„edk\[[tts|‚ztts|„…„„Šlek„Š„lddƒ}ƒ‰‘~‰ƒv‹‹„››”””‹””‹ ™‹†tll””‹µ¶·\[[,55‹‹„ƒƒ|‹’ŠjcVz‚l]bZttsztlƒƒ|‚utFD;sref]cVTL‹„‹“Œ”d\\œ¤¦››”œ¤¦„„Š™š¤lek”“›‘…„”“›tts“Œ”ª³·ª³·¨©´ÂÅÓ›¢›ª³·”››ƒ„„””‹|‚z“““{{tf]cultŒ‹“ƒƒ|{ttd\\Š}ƒŒ‹“tzl„„Š”“›ƒ}ƒtllƒƒ|redu{{zllkd\‚wlƒƒ|‹„„„Š}›”›i\V‰‰w‹„„Šƒ}{zmƒƒ|ƒ||lldbVUttsb[Uƒƒ|tygredzll‚v{\UZ[[Tkk]{{ƒlks››”kd\rr]lld‹„‹uztmwœ››ƒ||„Š„d\\ddcultzllŠ}|yle’ŒŒsle‚|ubVU{||SKJŠ}|[[TultŠƒ}ƒ||zllllktts‚utƒ„„uzt\UZMSSMSS|„…UTSUTS\[[ult\[b|„…“Œ”{||{||››”ƒ„„ultedkddc‹„„‚v{{{t”š”{||œ¤¦ŒŒš‹…š{||mttª³·Œ‹“¦§¨ª³·“Œ”‹‹‹Œ”•”š”ƒ‚u‹’Štt{llk{|||‚zf]ccbVtllmtt“““|‚z\UZ‚v{jV[sle[[Tkd\{||ttstts{tt‚|u””‹ztlkd\š””tts“Œ”„„Škd\‹‹„r]g‹‹‹tsl‹‹‹‹„‹Œ‹“sle‚ut|„…ƒ|||‚z“Œ”‚ut|‚ztts£››ƒƒ|£››¤¤“Œ”lrimtt‚utœ››|„…{ttek]JHFJHFFD;JHF{||MSSMRKƒ}ƒJHF|‚zƒ„„‹‹„‘Œ…dc\ƒ„„UTSyfllekf]c“““mttred‹…’llkŒ”•tts‹„„{tt‹’Štllœ¤¦ƒƒ|‰ƒv{zmŠƒ}››”›¢›¢—“Œ”{ttŠƒ}²««MRK:97£››{tt‚|usreSKJsrezll{{t‚|u‚|ubVZsrekk]SKJrfk’…‹Š}ƒ‹’ŠŠƒ}lks„„Š|‚zedkUTSƒ||”››™š¤š””Œ”•‘…„¦§¨œ¤¦œ¤¦››”|„…lri‘Œ…’…‹tllddcrfkf]cult𔔣››{u{‹‹„{{t|‚zddc‹„‹f]c‚|u”“›…‹‹lri|‚zrfk{{t‹„„’ŒŒ„Š„{tt’ŒŒtslzllƒ‚uzll‘Œ…ƒƒ|ttsb[Ullkdc\ƒ‚uVTLd\\‹„‹f]cddcekdf]cf]c|„…£››Š}ƒtsl’ŒŒ{tt‚v‚{tt‹’Š„Š}lldSKJtllbVZztf“Œ”Š}|ultdkVƒƒ|zllƒ„„œ››‚v{{{t‰ƒv{ttred{{tƒ}ƒult{|||„…ultllk>ECMSSUTSllkddc…‹‹{{ƒmttfkkƒ„„{tt{||ekd{||f]clksddctlltll{{tœ››”››„„Š”“›ult”››ultŒ”•ƒ}ƒ›¢›ÌÖЦ§¨¦§¨™š¤”››‚|uuzt“Œ”Œ”•”“›sreœ››ƒ„„ƒ||‘Œ…{{tƒ„„ƒ„„ƒ||‹…’{{t{{t²««{tt„Š„{||ttsztl„Š„{ttkd\ƒƒ|ultƒ„„{||lld…‹‹›”›’ŒŒƒ||ƒ}ƒ{{ƒ…‹‹‚|ulddult|‚ztzlƒ„„œ››Œ‹“’ŒŒ“Œ”ztlƒ‚uztl{ttyfl…‹‹lddtll{u{VTL\[[FD;F=CUMRd\\ƒ„„[[TZbNedkUTS™š¤Œ”•µ¶·‚|u{{t{||rfkƒƒ|‹‹„|‚zƒƒ|ttstslŠ}ƒlriu{{]cd„„Й𤓓“{{t“““{{t‹„„‘Œ…kk]‘Œ…{{t‚ut£››tll{zm²««llk7-2ŠŠ}””‹ƒ„„””‹cbVkd\‚wlƒƒ|tzlœ››yfd{||SKJPF=ƒ„„„Š„‹„‹‹’Škd\Œ”•|‚z{{ƒ]bZztld\\|‚zŒ‹“‹„‹tsl“Œ”ƒ}ƒ„Š„…‹‹„‰vœ¤¦„„Šd\\››”’ŒŒlldf]cŒ‹“{{ƒ‘Œ…rfktlllks›”›‹’Štts¦§¨{{ƒƒ}ƒtsl‹‹„MRKlks‹‹‹{tt{zmtll{||ƒƒ|””‹[TTredkd\Š}ƒƒ‚uddcƒ||ƒ||u{{lldbVZ[[Tek]\[[{u{leklekŠ}ƒ|‚zultsleekdtllkd\redllksleuztcbVlldFD;lekj]\ztl‰|v{tt‹„„ƒ||ƒƒ|“Œ””››ƒ}ƒult“““ƒ||i\Vredrfkult{ttultlrifkklld|‚z]cdmttultuzt„Š„ult^^qf]cƒ||ƒ}ƒfkk„Š}ƒ||”››uztf]c‹„„‹„„{||‹’Š“““|„…f]ctlltslddc¨©´„Š„¨©´¦§¨“Œ”˜Ž£lri„Š}ƒ}ƒ{||{tttt{ultlddzlluzt£››‹’Štzl‹‹‹{u{‰v|ƒ}ƒddc‹‹„›”›lldlldƒƒ|™š¤‚utƒƒ|‚ut‹„‹slekd\ult¦§¨ƒƒ|kd\{{t‚wl‹…’£››ƒ„„ƒ„„‚|u’…‹…‹‹lriztllekƒƒ|ƒ}ƒ£œ¥”››tll„Š}‹’Š‹„„“Œ”lld“Œ”Š}|Œ”•kd\VZTVTL:97UMR{zmekdUTSFD;MRK]bZ|‚z””‹””‹sle{{t|‚z{{t‹„„Œ‹“ztl{{tllkd\\sle|„…ttskk]llkldd‹‹„lektsl‹’Šztl{tt‹‹„{zm‹’Š‚v{Šƒ}ƒ||ŠŠ}²²¬VTL*)(œ››tzlœ››ljcbV|‚zzll””‹tzlkd\sreŠ}|74,D;9{{t”š”ƒ„„œ››tll„Š}{||ƒ}ƒ„Š„ƒ„„ultœ¤¦“““¤¤‘…„jV[yfd|‚z”››””‹ƒƒ|„Š}Š~‹ƒ||‹„‹tslƒ}ƒƒ}е¶·””‹šŒµ¶·¦§¨{{ƒƒƒ|tt{œ››¨©´’ŒŒ[[Tddcek]slettsƒƒ|ª³·‹‹‹{zmultsle\[[kd\tslVTLƒƒ|{{tlddlddulttll‹‹‹JHFultred’ŒŒtsl{{ƒbVZmttlri‰v|mttkd\kd\dc\‹’Š›”›|‚z„Š}{{ttslUTS{{t{ttljtlltll{u{’…‹‹„‹tts‹‹„’ŒŒ„Š„ultredlddkd\{ttult{||edkultJHFmtt\[bfkk{tt|‚z„„Š…„’ult|„…{||‚v‚UTSdc\“““Œ‹“llkŒ”•‰|v‚v{Œ”•‹‹‹u{{mtt{{ƒ“Œ”Œ”•‹‹‹ƒƒ|‹’Š{{ƒ””‹‘…„£››‹’ŠŒ”•ƒ}ƒ‚v{{tt[[T‚|uƒƒ|¤¤ƒ||’}™„Š}|‚z“Œ”‹„‹Š}|”“›››”{zmƒ||{{tmttttsƒ„„zllƒƒ|›¢›uzt‹„„’ŒŒd\\{{ttslztf|‚ztslƒ}Šƒ}ƒtslsle””‹ƒ}ƒ{u{kd\d\\””‹››”„„ЄЄƒ}ЄЄekd”š”“Œ”rfkJHFƒ||bVUlekb[USKJJHFFD;MRKSKJVTLJHFƒƒ|\UZ|„…f]cƒƒ|‚|uŠ}|llk…‹‹ekdƒ||lri{||kd\MRKred{|||‚ztts‹‹„ƒ||ultu{{{||…‹‹{||kd\‚|u«²«„Š}ŠŠ}{{tsle‚|uŠŠ}µ¶·JHF-1+|‚z“““‘Œ…rg]kk]jcV‰ƒv”š”b[U‹‹„ƒ„„b[UVTL3+*‘Œ…„Š„‹…’ttsVTLƒ}ƒtts|‚zmtt£œ¥””‹tt{‹‹‹›”›¦§¨œ››ƒ}ƒ”“›llktt{¦§¨¨©´£››‹„‹{tttslf]clkstsl“Œ”‹…’{{ƒƒ||‚v‚”𔦧¨„„Š‹„‹Œ‹“‹‹‹ultttsdc\f]c‚ut„„Šƒ||‹‹‹redi\Vkd\zllVTLldd{||[[Tllkƒ||ttssredc\ƒ„„bVUttsSKJƒ}ƒultllklriœ››redztltsl„Š}d\\ztlƒ„„{tt’ŒŒdc\‹’Šd\\”š”‚|uztlŠ}|cbVkk]kd\“Œ”ƒ||ƒ„„Š}|””‹’ŒŒ‚wl“Œ”kd\ult{{ƒultƒ„„lldfkk|„…JHF\[btlluzt‹„„„„Š{{ƒ}|’Œ‹“{{t{u{”š”’ŒŒƒ„„ddcƒ„„tll„„Š‹…šœ››Œ”•{||”››’ŒŒlriŒ‹“”››{tt|„…|‚zƒ||›”›””‹ƒ}ƒ”“›edk…‹‹|‚z“““‹‹„sle…‹‹lek¦§¨{||tslƒ„„ƒ}ƒŠ}ƒ{{t{{t“““{{t|‚zdc\‹‹‹rfkœ¤¦””‹’ŒŒ‹„„Š}ƒ‹„„{||‹’Š‘Œ…llkƒ„„’…‹ult|„…‹„„‹„‹›”›Œ”•{{tslett{”𔋄‹“““{{ƒƒƒ|””‹‹‹„Š}|bVZlldlekztluztkd\D;9VTLFD;[TTsleUTSf]c&&\[b„Š„‹‹‹‹„‹‚|u‹‹‹‹’Š…‹‹Š}ƒŠ~‹””‹sleƒƒ|ƒ}ƒ‹„‹ƒ}Šlld‹‹„ztlttstts‹‹„“““‹’Š”š”‚ut‹‹„lld‹‹‹ƒƒ|‚v{yletslƒƒ|¦§¨:9774,ƒƒ|ƒ‚u{{t‚|urr]rg]‘Œ…tslyle{u{ƒƒ|ƒƒ|VTLSKJŠŠ}œ››ƒ}Ц§¨ƒƒ|ƒ„„„Š}tt{lri‹’Š£œ¥uzt…‹‹“““””‹£››‹„„ult|‚z«²«|„…ƒ||‘Œ…™š¤›¢›…‹‹dc\Œ”•ƒ„„d\\[[TUTSrfkldd‹‹‹|„…ƒ}ƒ“Œ”Œ‹“™š¤“““„Š„j]\“Œ”b[U“Œ”{{t‹„„š””‹’Škk]{ttƒƒ|kk]uzt|‚ztts“Œ”f]c{{tsletslƒ}ƒd\\‚v{|‚z{{ƒultƒ„„’ŒŒ‹‹„{||Šƒ}Œ”•uzt‹‹„‹‹‹¦§¨{||jcV\[bƒ||{u{”𔋄„š…Žult‚ut{{t‹‹‹‹‹‹tllŠ}|Šƒ}‹„„{u{ƒ„„Œ”•”“›f]cƒ}ƒ‹’Šlri|„…lri]cd\[[ekd…‹‹‹„‹tt{{{ƒ…„’‹‹‹tsl{u{{||ƒ||„„Šƒ„„ekdtllŒŒš†~‘llk„„Š…‹’“Œ”“Œ”„„ЄЄŒ‹“’ŒŒ“““‚wlult‹„„µ¶·Œ‹“…„’‚wlult|‚z„Š}ƒƒ|ult“““ult{tt{{t{ttƒ„„“Œ”£››ƒ||sle’ŒŒtsldc\{||œ››lek{{t{{tŠƒ}‹„„“Œ”£œ¥¦§¨“““¦§¨ƒ„„ƒƒ|“““tll‹‹‹‹„„„„Šmwmttd\\mttztl‹‹„{u{š””’…‹{{t‹’Š|„…‹„„redlldtllŠ}|‘Œ…rg]uzttygC8.dc\[TT‹‹‹ldd\[bmtt„Š„”“›\[bkd\rfk…‹’{{t[[T‹„‹|„…š””‹‹„ttsŒ”•‚v{’ŒŒ{{tslellk”“›””‹‹„‹¦§¨‹’Š£››››”ƒƒ|‹’Ф¤‹„‹ztl››”‚utü¿SKJ:97kd\kjVŠƒ}ztlkd\ŠŠ}d\\tsl|‚zuztƒ}ƒ{zm[TT‹„„{zmuzt”“›£œ¥ƒ‚u£œ¥ƒƒ|b[U£œ¥{||{u{Œ‹““Œ”{{ƒ{{t’ŒŒ‘Œ…››”Œ”•{||‹’Š”“›””‹£››tts\[[ek]|„…u{{ƒ‚ulksult{{t{{ƒƒ‚uu{{”“›’ŒŒ“““„„Š‚ut‹‹‹Œ”•ƒ}ƒ‘Œ…”“›“Œ”ª³·ƒ||b[Usreƒ||sreŠƒ}tt{ƒ||‚|u“““ult{ttsretzlŒ”•d\\lrir]Z|‚z‚ut“Œ”‘…„‹‹„œ¤¦tts{{t‹„‹{{ƒ{ttek]tslkd\d\\tll‹‹‹£››‹„„¦§¨››”tlllddf]cƒƒ|llkŠ}|„Š„ƒ||ldd£››sreƒ}ƒ{{ƒ“““ƒƒ|]bZ…‹‹„Š„{||…‹’{u{|‚z|„…ƒ}ƒmtt{||…‹‹|‚z‹„„ttstt{ƒ}ƒtllultƒ„„ldd£œ¥™š¤¨©´œ¤¦“Œ”“Œ”𔔦§¨«²«‹‹‹ƒ„„ƒ‚u¦§¨‹‹„‹’Š‹„‹‹…’f]c„„Štts››”””‹››”µ¶·‹…’tzl‹‹‹””‹|‚zŠ}ƒ‚ut{||ldd’ŒŒ””‹|„…{tt{{t„Š„{zmuzt””‹›”›“““£œ¥”“›œ››””‹{u{ƒ||{tt›”›ttsƒ}ƒlddldd{{t[TTllk‚|u¦§¨ƒƒ|”“›ƒ}ƒu{{‹’Šƒ„„’ŒŒ‹„‹‹„‹Š~‹ztf{{tsleŒ‹“kk]D;9ult{{ƒ|‚z…‹’mttUUYƒ„„d\\fkkzll‚|u›¢›ƒ„„uztƒ}ƒ{u{’ŒŒ‹‹‹\[[‹„„Š~‹ddc]bZ[[Tddctsl‹’ŠŒ”•Œ”•tslb[Uƒƒ|{||””‹¤¤“Œ”£››‚v{ztl¦§¨[[T74,››”„Š„{zmŠƒ}Šƒ}|‚z{zm|‚zllduztœ››‹‹„ƒ|||‚z‹„„Œ”•Œ”•“““ztlldd[TTddc|„…{u{{u{’ŒŒ‹„‹”››Šƒ}Šƒ}„„Šƒ„„VZ[u{{…‹‹¦§¨‹„„ƒƒ|ldduztdc\lksŒ”•lriŒ”•ult‘…„{tttsluzt”“›Œ‹“{{ƒd\\œ››‹’Š‹„‹ƒ}ƒ‘ˆ}ultŠ}ƒzll{ttœ››lddœ››››”Šƒ}{{t{{ƒlddtsl{||ƒ‚uƒ||kd\‚|uultj]\tllllkrfk‹‹„ƒ||{{tœ››ƒƒ|›”›{ttlld|‚zrfkj]\‚v{mttƒ}ƒlekrg]Š}ƒ‘…„‘…„ztl“Œ”›¢›‘Œ…tsllddƒ„„{tt{{ƒƒ}ƒredƒ„„„„Šuztkd\b[Utts{||{{ƒ„„Šƒ„„|„…{u{~’“mttlks[[T{||llkdc\rfkmtttt{|„…””‹ƒ}ƒ“Œ”f]c‹…’™š¤£››››”Š~‹tsl‹’Š{{ƒtt{‹‹‹{zm””‹£››ƒ„„¦§¨ƒ}ƒŒ”•‹‹‹‹’Š””‹œ››™š¤Œ‹“‚|uœ¤¦‘Œ…{||“““‚v{ƒ}ƒ‚|uŠƒ}lldƒƒ|lld‚ut¤¤‹‹„”š”‚ut‹„„›”››”›‹„„tts›”›š””‚utƒ„„“Œ”Š~‹mw„„Š{ttƒƒ|ddc“““ƒƒ|››”lks”š”{u{…‹‹|‚z”››“Œ”‹„„ƒ}ƒ‹„‹ƒ||d\\sred\\|‚z‰|v™š¤ttsŒ”•\[b>B9f]cJHFtll{||uztkd\tsl{{ƒŠ}ƒ“Œ”„„Šš””|‚z””‹„Š}›¢›{||lld{{t\UZmttƒƒ|‹„‹llktslSKJVTLkk]kk]{{tš””Š}|’ŒŒtll¦§¨VZT-1+‹‹„””‹ƒ||‘…„‚|ukd\tzlVTL[TTllkŠƒ}ƒ‚ulrilks{{t|‚zlksƒƒ|sre‹‹‹[[TUTSUUYƒ}Šzllœ››£œ¥”š”››”ƒ||‹‹‹lri|„…cbVŒ”•…‹‹‹…’slettslrikk]lddlkstts|„…”“›‚|u[[TŒ”•„Š„ttsekdldd„Š„tt{„Š„„„Š‹‹‹[TTztltts{u{‚ut|‚z”š”””‹ƒ‚uƒ‚u‘Œ…‹‹‹tll‹„„{u{lddkk]‰ƒvlddredbVUtlllldƒ}ƒtt{ƒ||ƒƒ||‚zƒƒ|b[Utts{{t{u{Œ‹“sleSKJd\\d\\„Š}sleldd[TTddc’…‹ek]‹‹‹„Š„“““‚ut‹‹„llk{u{{{t””‹„„Š[TTkd\|„…slelrimttlek|„…ƒ||‹’ŠŒ‹“{{ƒ…‹’{{ƒ{||llk{|||‚z’…‹‹…’|„…{||ƒ||{u{ƒ}ƒ‹‹‹{{ƒƒ}ƒ¦§¨›”›ƒ„„|‚z„Š„ult¦§¨”››’ŒŒ“““{||”››{{ƒ‹‹‹|‚zlld„Š„ŠŠ}‹’Š{||›”›“““„Š„¤¤“““Š}|{u{{u{ƒƒ|””‹ƒƒ|tslœ››¤¤ƒ||ƒƒ|””‹{zm””‹d\\f]c‹‹‹„Š„sle{||Š}ƒ››”“Œ”{u{”“›£œ¥””‹uztbVU|‚z‹‹‹kd\‹‹‹tsl…‹‹“““|‚z”››œ››’ŒŒ]bZ‹„„š””tll„Š}Šƒ}sletzl{{ƒlddtzltt{SKJJHFFD;llk|‚z››”tsl|‚ztt{sle“Œ”ztl{u{kd\Œ”•‹„‹ekd{u{[[TbVUtts|‚ztsltt{lldlrib[UaWMcbVdc\tslŒ‹“ƒ}ƒtsl‰|v’ŒŒJHF3+*ƒ}ƒ””‹‚|u‚wl””‹tsltslsletll„Š„lriƒƒ|u{{sle“““{||ddclri‘Œ…\[[ttsf]cUTSzll“~ˆ{u{’ŒŒ¦§¨sreƒ||’ŒŒŒ”•mtt|‚zf]cttssle¦§¨ddctsl:97ek]VTL[[T‹‹‹ttslri{||ƒƒ|{||“““”››”“›„vŒƒ|||‚z‹…’{u{zll‚v{‹„‹„Š}ult„Š„‹„„‚|u‹„„ztlœ››‹‹‹ƒ„„ult”“›‘Œ…sreyfd‹„‹sleredd\\kd\bVUtts‹‹„sreƒƒ|’ŒŒ‘Œ…]cddc\{||ttsredredUMRd\\…‹‹‚|ud\\yleŠ~‹‚|uƒ„„‹„„‹’Š{tt‹„„„Š}{u{ttsreduztƒ}ƒtll‹’Šƒ„„{u{\[b]cdyl„lksƒ„„|„…”››|„…Œ”•ƒ}ƒ’…‹llkƒ„„{{ƒ„Š„“Œ”ƒƒ|ƒ„„ƒ}ƒ›”››”›“““”“›Œ‹“››”›”›Š}|‹’Ц§¨”››|‚ztsllld‚|uƒ„„„„Šult’ŒŒ‹‹‹|‚zš””›¢›‹‹„\[bƒ}ƒ{tt|‚zsleœ››ult‚|u‚v{Šƒ}š””tslƒ„„ŠŠ}{zmsle‹‹„ƒƒ|‚|u’ŒŒ£œ¥‹„„{u{ƒ„„‚utlldŒ”•{{t¦§¨ultƒ||ƒ}ƒ‹„‹ƒ„„ƒ||¤¤tts‚|u‹„„”š”dc\tt{”››¦§¨œ››£››Œ‹“Œ”•’ŒŒzll|‚zj]\[[TŠ}|SKJ‹„„ŠŠ}SKJVTL[TTlrimttddc‚wl{{tu{{Œ‹“tt{ƒ||{u{‚v{b[Utsl„Š„{{ƒŒ”•Šƒ}lldlekƒƒ|‹’Šultttstsl‚v{{zm¤¤tsl””‹››”‹‹‹“““{tt«²«JHF*)(ƒ}ƒuztƒ||f]c‚|udc\‚|ulritllUTS‚|ulri”𔓓““Œ””š”Œ”•‘ˆ}SKJ‰ƒvlldekd\[[UMR{tt£››‹„„£›››¢›œ››Šƒ}™š¤‹’ŠlksŠƒ}ƒ„„‹’Š{{tred„Š„lldSKJ{||tslŠ~‹uztlri™š¤ƒƒ||‚z™š¤…‹’”“›”“›ƒ||¦§¨œ››ultƒ||zllztlŠŠ}£››dc\ƒƒ|Šƒ}’ŒŒrg]£œ¥ƒ„„|‚z”“›d\\tlltsl{ttƒ„„rg]ultSKJ{||ƒƒ|{{tsre{{t‹‹‹‘ˆ}ƒ||tsld\\mttƒ„„{ttƒ„„‹‹„ƒ„„slešŒldddkVbVU{||”“›{||mtt‹’Š‹„„uztllk{{ƒ‘Œ…ƒ}ƒŒ‹“lld{||[[TbVU\[bd\\\[bedkƒƒ|]bZ…‹’u{{Œ”•„„Š‹’Š|‚ztts‚|u{u{¦§¨ƒƒ|ƒ}Š{{ƒ¨©´¦§¨ƒ„„¨©´„„Šzll{u{„Š„|‚z‹‹‹”“›leklld””‹[[TlldŒŒš{{ƒ|„…„Š„|‚zztlœ¤¦‚utVZTƒ}ƒ””‹ŠŠ}››”“““£œ¥š…Ž{tt[TTkd\ek]‹’Šƒ„„‹‹„Šƒ}‹‹„‹‹„Š}|‘Œ…‹„‹ƒ}ƒŠ}|ƒ„„Œ‹“„Š„ttstslš””ƒ||„Š„››”“““‹’Š{u{‹’ŠŠ}ƒƒ||ƒ||„Š„ƒ}Šƒ||‹’Šƒ||”š”‚|uƒ„„”“›bVUƒ||rg]ztl|„…ult[TT{{tƒ„„slelrif]c{{ƒldd{|||‚z“““{{t‹‹„{||d\\f]ckd\VZTtts{u{¦§¨{tt‚v{‹’Š“““lksƒ„„”››‹’Šƒ„„šŒ¤¤›¢››¢›«²«£œ¥›¢›¦§¨‘Œ…””‹VTL*)(sreƒƒ|lriztl‚|uVTL””‹{{t‘Œ…„Š„ƒ}ƒ”𔋋‹{tt[[T|‚z„Š„‹‹„b[U£œ¥{tt]cd…‹‹£››’ŒŒœ¤¦‚ut“Œ”ƒ||ƒ}ƒƒƒ|ƒ}ƒ…‹‹z‚lŠ}ƒ„‰vsle[TTUTScbV‚|udc\‹„‹ŒŒš™š¤{||ƒ‚uƒ}ƒ›¢›u{{‹‹‹“““”››‚v{ƒ}ƒtsl£œ¥ƒ}ƒtll‹‹‹‚ut|‚z‹’Šek]zll{zm››”‰ƒv{{tuzttll‰|v„„Šƒ}ƒbVUztl›”›sleredƒ}ƒlddŠ}ƒsle””‹ƒƒ|llddc\””‹{ttllkd\\{ttkd\tll|‚zj]\”››Šƒ}ƒ}ƒ‘Œ…{ttŠƒ}šŒllk‹’Šllkƒ||‚v{ƒ}Š””‹tllŒ”•{{ƒ“Œ”tts„Š„tslmttf]c{{ƒmtt“““uzt{{ƒ|‚z|„…Œ‹““““{ttVZ[{ttŠƒ}uztŒ”•‚v{Š~‹…„’ƒ||tll“““”“›””‹‹„„’ŒŒœ››Œ”•{||ddc‚v{‹‹„Šƒ}”››‹‹„“Œ”™š¤Œ”•‹‹„”𔤤››”dc\{||£››’ŒŒ””‹’ŒŒrfkŠ}ƒš””Šƒ}ztlŠŠ}tsl„Š„œ››ztf{{t{ttkd\sle‹„„”“›‚|u|‚zultŠŠ}‹„‹‹„„‹„„··Ä‹‹„£œ¥Œ”•ƒƒ|‹„„j]\ƒ}ƒŒ‹“red„Š„™š¤¦§¨Œ‹“”“›‚|utsl¤¤{||‚utlldtzl…‹‹{{tSKJ‚utVTL{{t’‘~f]cJHFlrittsŒ”•ŠŠ}“““‹‹‹”š”ultj]\ƒ}ƒ’ŒŒllktsllksƒƒ|“““’ŒŒ”š”{zm„Š„{{tƒ}ƒƒ„„tsl››”‹’Š””‹›¢›’‘~²¬µµ¶·µ¶·¤¤¦§¨\[b)+2Šƒ}””‹ƒƒ|››”‘ˆ}dkV‹’Š‚|u‹‹„‹‹‹Š}ƒsreVTLsle‚|uŒ”•lrimttztl‹‹‹|„…\[[lrizll’ŒŒ‚|uuztVTL¤¤“Œ”šŒ“Œ”‹„‹lld“““”š”“Œ”Šƒ}‹„„lri‹‹‹f]ctsllri{{ƒ™š¤¨©´‹‹‹”š”…„’{{ƒ{u{‹„‹™š¤tllsleŠƒ}{u{‹‹‹‹’Šƒ}ƒsle{ttj]\„Š}ldd{zm‚|u””‹ƒ||‹‹‹sle‹„„„„Šdc\‰|vj]\‹‹„“““‹„‹]bZŒ‹“”››tll{{t‹’Š{zm‹„‹{u{‚|u“““Œ‹“kd\’…‹ttsedktlllddsleztf{u{ƒ||‰ƒv{tttsldc\‚v{‚|u{u{ƒ‚u›”›””‹edk{u{ƒ„„ttslldult{{t{||™š¤|‚zuzt|„…Œ”•|„…|„…|‚zlksu{{{zmƒ„„lekŠ}ƒtt{ƒ}ƒ““““““Œ‹“Œ”•‹‹‹£››ultlksƒƒ|ƒ„„„„Š{||‘Œ…”š”š””‹’Šƒ„„„„Š|„…ttsŠ}ƒ‘Œ…‹‹„‹„„{{ƒultœ››”“›¦§¨›”››”›yfl‚|u””‹‘Œ…””‹sre””‹ŠŠ}„Š„‹‹‹yfdztl‚|u‚|uƒ„„‹’Š‹‹‹‹‹‹‹„„{ttœ››’ŒŒ‹„„|‚z|‚zrfklri{ttult“Œ”¦§¨¦§¨›”›‹„‹ƒ„„|„…›¢›‹‹‹{tt‹‹„{{tš””uzt„Š}lldztfVTLSKJsleuzt[TT:97f]cmtt\[[lri”š”™š¤{{tmttƒ}ƒ“Œ”{u{¦§¨„Š„ƒƒ|“Œ”‹’Šƒƒ|‹„‹„Š}ek]tlltt{[TTƒ„„“““””‹ƒ‚uŠŠ}”𔦧¨™š¤£œ¥››”¦§¨¦§¨JHF*)(‹‹„‹‹„lri‘Œ…ztliq]‹’Š‹‹„‹‹„lld{u{VTLtsld\\ƒƒ|ƒ„„uzt™š¤ƒ||uzt‹’Šu{{u{{tll‹„„œ¤¦ulttts{||£››¤¤œ››Œ‹“‘Œ…rfk“Œ”š””œ››‹„„ƒ„„ldd\[[{{t„Š„{ttƒ„„“Œ”tt{ƒ„„u{{|‚zultœ››red‹‹„²««ƒ||{{ƒ“““tll‹„„b[U’ŒŒ{||tts{zmslei\VŠƒ}{tt‹„„‚utddcddckd\‚|ud\\„Š}tllƒ||zll‘…„UTStll|‚z””‹ƒ‚usle“Œ”{u{ttsŠŠ}Šƒ}{||{ttƒ„„f]ctll‚wlš””lldsleƒ|||‚z‹‹‹”š”›”›‹‹„“““{u{ultttstts{ttƒ||ƒ||‹‹‹lksƒ||lriu{{|„…„„Š„„Š|„…VZT]cdu{{{{ƒ]bZ‹’ŠŠƒ}™š¤’ŒŒ{u{tll“Œ”lri‹’Š„„Й𤦧¨Š}|sleƒƒ|ulttts‹‹‹£œ¥””‹‘Œ…«²«””‹Œ‹““““{{tJHFztl{{tŠƒ}ultŠ~‹tll‹„„£›››”›£››Š}|‘ˆ}lj²««lri‹‹„{zm‹’Š””‹ƒ„„Š}|zllkd\šŒ‹„„‹‹‹|‚zƒ||UTS{tt{||š””’ŒŒ‹‹„‹„„tll\[[Š}|{tt{u{’ŒŒŒ‹“‹’Šƒ„„‹„‹Œ”•œ¤¦‹’Š“““¦§¨ƒ„„œ››“Œ”|‚z]cdztlVTLSKJŠƒ}…‹‹Œ‹“MRKSKJuztd\\mtt‘Œ…„„Š‹„‹“Œ””“›“Œ”›”›œ››‹‹‹ƒƒ|tt{|„……‹’ƒ}ƒ‹’Šƒ}ƒ‹‹„ttslkstllƒ„„š””tsl›¢›{{t‚|ullkƒ||ttsƒƒ|¦§¨MSS*)(cbV„Š}Œ”•{{tƒƒ|cbV’ŒŒdc\‹‹„sreŒŒšztlekdldd‚|u‹’Š‹’Ц§¨¦§¨¦§¨|‚zJHF¦§¨ƒƒ|[TTred[[T‹’ŠŠ}ƒœ››‹’в««Š~‹{zm””‹llk’ŒŒ{{t‚ut…‹‹„Š}|„…›¢›”››{{ƒlksƒ}Š|‚z„Š„…‹‹‹„„™š¤ƒ}Š‚wl””‹‚v{Œ”•yflf]clld{||‹’Š‚|uddcdc\uztb[U‹‹‹ƒ||{||²««Š}|ƒ„„tllkd\„Š„lek‚ut{ttƒ}ƒtt{ƒƒ|lektll„„ЄЄztlrg]”š”tts{u{lld‚v{{{tddcVTLƒ||ƒ„„‹’Šultƒƒ|sleiq]]bZlri’ŒŒ›¢›Šƒ}Œ‹“\[[‰v|sleƒ||’…‹{ttœ¤¦”“›“Œ”{{tu{{u{{fkk“Œ”ƒ}ƒmtt{{ƒ\[bŒ”•tsl„Š„{{tkd\lekultddc{u{UMRuzt‹‹„uzt›”›¦§¨ƒ‚u”š”Œ‹“…‹‹{{tllk¦§¨‘Œ…“““µ¶·ƒ„„{u{’ŒŒiq]‹‹„tllŠŠ}‹‹„‹„‹ƒ„„šŒ{{ƒ‹„„’ŒŒš””’ŒŒ²««Šƒ}{tttslƒƒ|ttsuztŠ}|ƒ||b[Utsl››”š””Œ”•„Š„uzt“Œ”„„Š{u{ƒ||ultƒ}ƒ‹„„{ttedk’ŒŒSKJsle¦§¨tt{ƒ‚u“““œ››“Œ”„Š„‹‹‹¤¤š””””‹Š}ƒ¦§¨…‹‹sle‹‹„cbVrr]SKJdkVŒ‹“Œ‹“MRKf]ctzlmwekdŠƒ}ƒ„„›”›‹’ŠŒ‹“”“›“Œ”ldd”››„Š}tts‘ˆ}…‹‹£œ¥‹‹‹ƒ„„{||Œ‹“ƒ„„‹‹‹“““tll|‚z{{ttslztlƒ„„Š}ƒƒ„„ult²¬µ[TT*)({{t¤¤„Š„’ŒŒšŒlks{zm{ttƒ||{{t„„Šuzt‹’Štslyle””‹{{t‹„‹””‹”››Œ”•|‚z¨©´²««ult‹’Šuzt{||f]c””‹{tt››”‹‹‹¦§¨›”›mtttlltzlttssle]bZ„Š„ƒ„„„Š}lri\[[™š¤\[[uzttt{tts{ttƒ„„£››ƒƒ|uzt¦§¨ttslddb[U‹‹„|‚zƒ„„ddc{{tlriztl“Œ”ŠŠ}‹‹„š””ztlttsztllddb[U‹„‹‚|uslekd\{{tŠƒ}’ŒŒ“Œ”|‚z””‹{||›¢›„Š„{{ƒ””‹‹‹„j]\ƒƒ|VTLtll“““|‚z¦§¨{u{“““š””””‹ttsllk{{tŒ‹““““œ››tllztl|‚z’ŒŒ£››ƒ}ƒ¦§¨tlledku{{ddc|‚z|„…”“›ekdmttmtt|„…ƒƒ|tll“““ztlztlultult…‹‹ttsƒ}ƒ‹‹‹‹„„Œ”•£››¦§¨‚v{ƒƒ|”“›œ››Œ”•ŠŠ}¨©´¦§¨›¢›¦§¨›¢›¦§¨‹„‹ƒƒ|ƒ„„{{t‹‹„{zmœ¤¦{{ƒlddƒ||‹„„”“›“~ˆš””œ››‹„‹‚|u‚|udc\›¢›””‹ƒ||‚|uƒ||£››Šƒ}„Š}ƒ„„‹‹‹””‹ª³·„Š„u{{ƒ}ƒš””ƒ}Š{||““““““…‹‹ƒ||tll‹„„tts£››ƒƒ|lddedklld‹‹‹””‹ztlkd\“““£œ¥¤¤ƒ„„‚|ukk]b[U{tt‘Œ…”››†~‘mttƒ}Štts{||llk‹‹„VZ[{ttƒ||“Œ”“Œ”‹…’mwmttuzt{||¦§¨ƒ„„ƒ||Œ”•Šƒ}‹’Šœ››„„Š‹’Šddcƒ||””‹[[T{u{{zm£œ¥{{ƒƒ}ƒŠ}|”š”LKR)+2ƒ‚u‹’Š“““d\\Œ”•Š}ƒ‚|usleuzt””‹tt{‹„‹VZ[VTL‹„„„Š}\UZ‚|uƒƒ|…‹‹u{{|‚z…‹‹”“›£››‹‹‹lriuztcbV‚|u’ŒŒ‹„„„Š„››”„Š„„„Š‹’Šƒƒ|ƒ}ƒƒƒ|tsl\[[|‚zu{{‚|ulks£²u{{”š”œ››tzlŒ‹“|‚z“““’ŒŒƒƒ|‹‹„ztl{u{{{tœ››lritts‰ƒvtslsleylelrirg]¤¤ztl‚|uƒ„„ultƒ}ƒztlcbVf]cš””d\\‚|u{zmŠ}|{u{lldtslddcƒ„„|‚zƒ‚u””‹ƒƒ|tsl{||d\\sle‚|u{||sre‚|u‹„‹‘Œ…d\\‰|v‹’Škk]tlltsl‹‹‹uztŠƒ}sreŠŠ}ƒƒ|‹„‹„Š„ƒ||{u{„Š„Œ”•{{ƒ”››„„Š|„…ttsŒ”•|„…‹„„‹‹‹„Š„ztlƒ„„Š}ƒƒ„„{||‹’Ц§¨”š”œ¤¦¦§¨¦§¨£››µ¶·²««‹’Š“““‹„„Š}ƒ¤¤µ¶·ª³·””‹¨©´‹’Štt{sreŠ}ƒ’ŒŒš””ddctslult›”›{{ƒ‹‹‹ƒ}ƒ›”›‘…„‹‹„tll››”|‚z|‚z¦§¨™š¤‚|u„Š}‘ˆ}››”””‹yle‹‹‹‹‹‹{||¦§¨‹’Šllk„„Šƒ}ƒ“Œ”‹„‹£œ¥‹’Š‹’Šf]cred…‹’ldd”››ldd|‚z’ŒŒ”››¤¤ƒ‚uultdc\£››ztl”𔋋„|‚z‹‹„VTL𔔔𔋒Š{u{Œ”•lek{{t‚v{llk‹’Šu{{‚v{lekƒ}ƒ‚v{‹„‹ƒƒ|{tt|„…llk¦§¨Š}ƒ’ŒŒƒ„„¦§¨‹‹‹™š¤‹’ŠŒ”•‹„‹ƒ„„Šƒ}kk]ult‘…„“Œ”›”›f]c[TT¤¤JHF:97sreƒƒ|‹„‹”𔋋„{ttƒƒ|[[Tb[Uƒ||‹„„Œ”•lldtlllrilld[[T|‚zƒ}ƒtzl{||mttƒ„„{{t››”‰‘~ultƒƒ|‚|u‘Œ…’ŒŒƒ||ƒ}ƒtslœ¤¦|„…‹„„dc\\UZ\[[{{ƒddcztlVZ[ztlƒ}ƒŒ‹“}‡’„Š„|‚z“Œ”ƒ}ƒlriddcŠŠ}{{tœ››sreƒ}ƒ{||‹’Š|‚z{ttdc\ttsƒƒ|lldkk]ztlSKJi\V[[T{{ƒek]ƒ||‹’Š{ttzll{ttj]\ƒƒ|zll“Œ”‚utztlœ¤¦llk{tt{||ƒƒ|ztlŠƒ}zllllkdc\lldultUTS‚|ub[UsleŠƒ}sre››”‹‹‹ƒ||””‹{{t“Œ”|‚zŠƒ}‘Œ…“““{{t“Œ”{||\[[{u{{|||„…]cd|„…‹„‹{||ƒƒ|¨©´‹‹‹{{t{u{{zmŠƒ}‘…„zllƒ„„red‹‹‹‹‹„”š”Œ”•|„…“““‹‹‹£››””‹„Š„¦§¨¦§¨›¢›¤¤²««‹‹„”š”{{t‹„‹‹’Š‹„„¨©´ƒƒ|µ¶·tzl{||{{ƒŒ”•¦§¨¦§¨‹„‹£››ƒ||’ŒŒ{tt‘Œ…‚wllriŒ”•“““ƒ||‚|u‰ƒv””‹Šut“““”“›œ¤¦lri‹„‹£œ¥”››‹’Šš””{u{{tt{||{||{||ult‹„„‹„‹ƒ}ƒ„„Šƒƒ|ƒ||{tt‹‹‹‹‹„{zmyleƒƒ|‹‹„‹„‹”“›‹’Šuzt””‹]bZ“““¤¤|‚z£œ¥u{{ult]cdf]c„Š„ƒƒ|“““„Š„„„Šult“Œ”‘Œ…››”dc\ƒƒ|‹„‹ƒ„„lekredsre‚v‚{||‹„„{|||‚zbVUrfk¢—{{tlld‚|uldd{ttzll‚ut‹‹‹:97JHF‹‹„{{t|„…sleƒ||„„Šƒ||‚|uƒƒ|‹‹„‹„‹ekdlri””‹tslƒƒ|Œ”•ƒ||tllŒ”•|„…VZT‹’Š{{t””‹„Š„ƒ„„«²«‹‹„š””ƒ||ŠŠ}…‹‹’ŒŒ”“›{||b[U|„…sreŠŠ}lekttslri„„Š\[[lkssleVZ[{u{…‹‹£œ¥ƒ„„{tt{{tƒ||lri‹’Š{tttllVZ[ƒ||ƒƒ|f]cƒƒ|{||sretsllddsre{{tsre{{td\\{||ƒ„„lld””‹d\\‰|vƒ||b[Ukd\‹‹‹ldd’…‹œ¤¦‹’ŠtslŒ”•lldb[UUMRtll‹‹„‹‹‹red’ŒŒ„„Š[TTtsl{||Šƒ}‹‹„{||¦§¨¦§¨{tt‹„„œ››”𔋋„‚ut‚|ukd\tt{uzt›”›„„Š‹‹‹ldd{tttt{fkkmtt{ttu{{{{ƒ”“›’…‹‹’Šƒ‚uldd“Œ””“›tt{™š¤ª³·“““«²«£œ¥›”›¦§¨£››‹‹„‹‹‹{||›¢›£œ¥£››‚|utsl«²«“““‚v‚rfk“Œ”™š¤”››››”‹‹‹{||{u{“““ƒ„„tts“Œ”“Œ”{||‰|v‰ƒv””‹””‹”š”œ››‚v{‘Œ…{{t‹’Š‘Œ…š””“““{{ƒ{{t{{t“Œ”™š¤“““””‹¨©´“Œ”¦§¨¤¤Œ”•tzl“Œ”zll‹„„ƒ||lldŠŠ}“““”››”››‹‹„µ¶·²²¬‹‹‹Œ”•ƒ||„Š„\[[ƒ||ttsMRKztl“““|„…Œ”•lkslksƒ}ƒbVZ…‹‹¦§¨„Š„›”›‹’Šult›”›Œ”•‹’Š„Š}„Š}ƒ„„‚ut{u{{u{‹’Š‹„‹„„Šƒ„„SKJlrifkkred‚|u“““ƒƒ|Šƒ}‹‹‹ƒ||‚utldd””‹JHF:97rg]|‚zƒƒ|tzllri‹„‹¦§¨‘Œ…ƒ}ƒtllƒ}ƒ{{t]bZVTLƒ||‹‹„œ§²›¢›llk‹’ŠŒ”•tts|„…“““d\\“““tt{‹‹„d\\\[[£œ¥yle{tttlllks‹‹„ttslldVTL‹‹„leku{{edk‹’Šd\\UTSultŒ‹“ƒ„„{u{‹’Šslelrilldƒ‚uƒ||‹’ŠŠƒ}ƒ„„{ttztlldd|‚z‹„„tts‚v{lldŠŠ}j]\jcVkd\VTLtzlŠ~‹ult{zm‚|u[TTšŒ‘Œ…jcV¤¤ult””‹‹‹„›¢››¢›{u{{{tdc\Šƒ}bVUldddc\{{ƒ””‹“Œ”ƒ„„ztl‚|utsl‹„„rg]„Š}Œ‹“„Š„ƒ||ƒ}ƒ„Š„{{tlddztlkd\sle{|||‚zult|„…ƒƒ|”š”{u{Œ‹“…‹‹tts„„ŠlriedkUMRtll“““{{t‹‹„ƒ„„{u{ƒ„„£››¦§¨”š”œ¤¦µ¶·››”„Š„š””œ››”𔛢›“Œ”ƒ}ƒšŒ‹’Š‹‹„„Š„“Œ”ƒƒ|¦§¨£œ¥rfkƒ„„¤¤„Š}{{t„„Šœ››ƒ}ƒœ››‹„‹ultiWUzllrg]‚utztf””‹„Š„Š}|ztl‚|ukd\‚|uŠƒ}‹’Šu{{tts‹‹‹œ››š””mttllk{||ult“Œ”tsl›¢›uzt¨©´ƒ„„“Œ”ƒ}ƒ„Š„|‚z›”›”š”œ¤¦“Œ”‹’Š‹’ŠŒ‹“ult£œ¥uztzlllddttsVTL[[Tsreœ¤¦f]cJHFultultzll{tttll””‹‹‹„‹„„Œ”•’ŒŒŒ‹“{u{|‚zƒ||Œ‹“{{tsledc\|‚z‰‰w{{ƒddcƒ||tsl{||ztltllƒƒ|‰ƒv£››lddultlddƒ‚uƒ„„D;9,55ƒƒ|UTS{||lld\[[{u{tll“““|‚z‹„„‹„„uztult‚|u{tt‹’Š…‹‹’ŒŒ‚v{lkslks]cdddc{{t‹‹‹cbVŠ~‹‹‹„d\\‚wlf]c‘Œ…ƒ||‘Œ…£œ¥ƒ‚utzl[[Tmttlld\[bttstt{lri‹‹„tts‹‹„tslŒ”•ƒƒ|ztl‹‹‹|„…zlldc\{||”››sleVZTuztlriƒƒ|”“›tts{ttŠ}ƒƒƒ|MRK£››‚wl{{tsle“““‹„„tllkd\tslsle£››{u{lri‚wltt{Šƒ}tll„Š„”š”tll…‹‹lld‹„‹‚utb[Uredllkƒ||Š}ƒ{tt“““{{tŠƒ}‘Œ…Š}|ulttzlf]c‹‹‹‹‹„‹’Š{{tsled\\‹„„‚|u{u{\[[]cdƒ}ƒŒ”•ttsƒ„„‹…’ƒ}Š‹„„{||edk{u{kd\„„Šƒ„„|‚z„Š„š””ƒ}ƒƒ}ƒkk]ª³·tts£œ¥š””‘Œ…””‹£›››¢›œ››“Œ”¨©´“Œ”‚ut²²¬²««œ¤¦œ¤¦„„Š›”›¦§¨[[Tztl”››œ››ƒƒ|ƒ}ƒƒ„„{u{{{t‹„‹š””Š}|b[Uztl‘Œ…‚|uek]¦§¨£œ¥ŠŠ}‰‘~‚utztf¤¤””‹“Œ”Œ‹“{||‹‹‹’ŒŒ{||tll£œ¥ulttt{tsl”š”™š¤ŒŒš£››””‹„Š„“Œ”‹‹„ƒƒ|™š¤œ¤¦‚|u¦§¨‹‹‹sreƒ‚u‹„„u{{lld|„…JHFdc\tsl‘Œ…[[TUMRMSSUMRultlks{{t{{t“Œ”{ttlddŒ‹“{||llkuzt{{tƒ„„ttsŒ”•››”{tt‹’Šlld[TT‚v{ƒ„„„Š„‚ut‹„„‹‹„””‹Šƒ}››”lldldd‹‹„“~ˆ£œ¥:97*)(ƒƒ|ƒ„„ƒ}ƒztlu{{ƒƒ|d\\Šƒ}‚|u|„…tts{{tUTS£››…„’”››ttsredldd{u{llkekdtt{¤¤‹‹„{{tlld{||ttstll“““‹„‹‚v{‹„„mttdc\ƒ||ekdlrikd\{ttŒ”•™š¤lriƒ„„|„…Œ”•tts„Š}|‚ztllŒ‹“‹’ŠŠŠ}tzl„Š„Š}ƒ{u{LKRd\\rr]f]cd\\ddcf]c‚utdc\kk]ztl›¢›¤¤””‹ƒ„„tt{srekd\[TT[TTj]\ultsleŠƒ}ƒ„„‚utŠ}|Œ”•tslult{{ƒƒ„„ƒ||‘…„‚|uult“““tslŠ}ƒ””‹{yf‚|u‘Œ…‘Œ…‹‹„z‚l‹‹‹uzttllrg]|„…tsl›”›{u{’ŒŒ{tt‚v‚dc\{ttƒ„„‹’Š‹‹‹„Š„{{ƒ‹‹‹‹„„{u{{{ƒ{tt‹„„red‘…„‹‹„¦§¨‹„‹”“›ƒ}ƒ‹„„”𔛢›„Š„£›››”›¤¤ztl‚|u‹’Š{u{‚|u’…‹šŒ¤¤››”ƒƒ|‹‹„Œ”•rfk™š¤llk‚|uƒƒ|¨©´‹’Š‹‹‹ƒ„„tts‹„‹¨©´“““‚utzllrg]Šƒ}jcVsreŒ”•‚v{‹’Š””‹redŠŠ}ztlkd\„Š}VTLtsl””‹‚v{’ŒŒƒ„„››”‹„‹kk]››”lri‹’Šedktll›”›{{t™š¤¦§¨‹‹„œ››™š¤¨©´«²«”››‹„‹„Š„…‹’{{ƒmttd\\VZTƒƒ|ƒ||”š”ƒƒ|[TTJHFf]c{{ƒf]ctsl‹‹„”“›‹‹‹‚ut“Œ”lri|„…{||uzt¦§¨™š¤ƒ}ƒ””‹‚|uƒƒ|‚wlƒ„„ult{||‹‹‹““““Œ”“Œ”’…‹‚ut‹‹„‹„„Œ”•‹„„Šƒ}£œ¥JHF*)(‹‹„‹„‹ƒƒ|ƒ||mtt””‹ztl‚|u‚ut›”›¤¤{{tlri{||d\\ldd‹’Š]bZƒ}ƒƒ}Š|‚z|‚z„Š„‹‹‹‹‹„”››¦§¨™š¤‚|u””‹Œ‹“¦§¨‹„„””‹”š”uztlrillddc\{{tztl‹„‹rfk‹…’’ŒŒkk]™š¤|„…”š”[TT{||tts{||{ttlldllkmw’ŒŒ\UZƒ„„{zm‹„„{u{ƒ||‹‹‹‚v{tslsreztf‚wlkk]ddcdc\ultzll‹„‹{tt‚v{{{tkd\dc\’ŒŒƒ„„d\\›”›d\\[[Tkd\rfktslVTL‚ut£››„Š„tslb[U“Œ”{ttulttllztltll‚ut|‚zlriŒ‹“f]cŠƒ}“““{zm‹„„››”Š}ƒd\\f]clri‹„„{||‹’Š|‚zlldtt{‹„‹‹„„‹„‹{{ƒ|„…ƒ||Š}|ƒ„„ƒ„„Œ‹“‹„„’…‹ttsŠŠ}œ¤¦uztsleŠ}ƒ’…‹£››¦§¨£››‹‹„ultŠ}ƒ‚v{“““Šƒ}¦§¨„Š}ƒƒ|…‹‹zll‹‹‹“““‹‹‹dc\‘Œ…dc\{||ƒ||mtt””‹tll‚v{’ŒŒ{ttŠ}|Š}|kk]sle‹‹„‚v{‚utztfƒ}ƒ››”””‹|‚zsreSKJllk{||kk]›¢›…‹‹›¢›“Œ”‹‹‹ldd|„…Œ”•„„Ц§¨‹‹„’…‹ƒ}ƒ””‹”š”œ››ƒ„„£œ¥|‚z{{ƒ“““‹‹‹lekttsƒ„„lrilddlri’ŒŒ„‰v{ttf]clriƒ}ƒ“Œ”‹„„›¢›ƒƒ|{u{Š}|‹„„…‹‹‹’Š|„…ƒ„„ƒ„„‘Œ…Š~‹¦§¨ztlŠŠ}‹’Š{{tŒ”•‹„‹tts|‚z{u{{u{Š}|£››™‹†¦§¨¦§¨ƒ||“““ŠŠ}£››:97*)(Šƒ}Œ”•‘…„{ttŠ}|ƒ}Š‘Œ…ƒ||{||ƒ„„Œ‹“›¢›llkkd\{u{…‹‹”“›’ŒŒ‹‹‹tts“““\[[z‚l{||‹‹‹µ¶·“““¦§¨‚|u›¢›”“›Œ‹“{{tslerfk„Š„‹‹„‹‹„›¢›{{tdc\ƒ}ƒ‹„„›¢›‹‹„ek]f]c|„…ƒƒ|‹‹„‚v{„Š„‹„‹“““zll{tt{u{[TT{{tllkzll{ttllklribVUultf]cdc\{{tVTLƒ||ƒƒ|lri{zmkk]ƒƒ|lddtllŠŠ}‹„‹VTLredƒ}ƒ“““›”›„„Š‹‹‹ƒ„„f]c|‚zsle‹„„ƒ||tllddc””‹š””‹‹‹ƒ„„‹’Š{zmbVUƒ‚u“““dc\ƒ„„[[T‹‹‹{{t‹’Š“““‘Œ…ƒ||Š}ƒztlttsultttsfkkllk|‚z\[bttsƒ„„“Œ”mttlri‹‹‹tts‹‹‹””‹ult‚ut›”›ult‚|u{{t„Š„ttstll“Œ”£››š””£››{{tƒ„„redf]cŠ}ƒ””‹‹‹„””‹¦§¨›¢›ƒƒ|\UZ”š”|‚z››”tsldc\{||‹’Šult‹‹‹{{t‚v{ztlƒ}ƒzll¦§¨b[Utzlƒ„„œ››Šƒ}dc\‘…„Šƒ}‚wl{zm{{tuzt‹‹„œ››{tttzl{ttƒ}ƒ››”{{t¤¤uzt”𔋋‹‹„„‹‹„“““u{{‹„„Œ”•”“›„Š}“““tsl{ttfkkŠ}|‹‹‹ƒ„„{||sle]cdtts‚|u|‚zƒƒ|Œ—£edkf]cultƒ}Š„Š}ƒƒ|¨©´š””””‹|„…ƒ‚u‹‹‹ƒ„„ƒƒ|‰|v›”›™š¤µ¶·¤¤››”›¢›“Œ”“““”š”ƒ„„lddultultred𔔣››£››“Œ”’…‹‚wl¦§¨JHF)+2››”ŠŠ}ult‹„‹”“››”›£œ¥‚v{sle‹„‹‹„‹lldlek[TTlks‚v{Œ”•ƒƒ|ƒ}ƒ„„Š”››uztu{{{u{‹‹‹¦§¨„Š}¦§¨¤¤ƒƒ|¦§¨£›››”›‹’Š‚|u£œ¥”š”ƒ„„mtt[TT|‚zlek{||ƒ„„{||lldultddctsl„Š„sle™š¤’ŒŒjV[{{trfk‹„‹lek‚v{ƒ„„f]cƒ||lddd\\d\\b[Ullk””‹rg]{{tkd\|„…‹‹„Š}|ttsttsƒ||sle‘Œ…””‹ƒ‚n‚|u„„Šš””œ››””‹ƒ„„ƒ}ƒlddlddtllkd\‚utrg]f]cztlƒƒ|’…‹‹‹„ƒ‚uƒ}ƒb[Ullddc\ƒ||ƒ}ƒ{u{llk{||tsl‚|u””‹{tt‹„„ddcŠŠ}{u{ddcƒ„„‹„„“““tt{{{ttt{„„Š™š¤ƒ„„UTS‚v{lek|‚zddcd\\‹‹‹kd\ztl…‹‹“Œ”“Œ”¦§¨Â¾Æ£››””‹¤¤«²«””‹Š}ƒult‰|v“Œ”uzt„Š}‹’Šƒ„„œ››‹„‹‹‹‹ŠŠ}„Š„{||™š¤¦§¨“Œ”{ttd\\œ››š””ƒ||‹„‹“Œ”š””””‹ƒ„„‹’Š“Œ”‹’Š‹‹„²¬µsre‹‹„sretsl¦§¨Œ”•›¢›‚v{Šƒ}{{tƒ||“““‹’Š‹‹„lld|‚zƒƒ|ldd“““‹‹„“““ƒ}ƒuztƒ||{u{„„Š‹‹„ƒ„„‹„„tts£œ¥ƒƒ|…‹‹‹„„]bZ‹„„‚|u|‚zœ››‚|u\[b\[bbVU‹„‹kk]ƒ„„“““›¢›ƒƒ|ƒ„„“Œ”tsllld{u{Š}|£œ¥¦§¨dc\””‹¤¤{zm”“›œ››Œ‹“œ››„Š„“Œ”‹„„‹„„zll¦§¨‹„„£œ¥‘Œ…‹‹„²²¬\[b*)(zll[[T{tt‚|uddc{tt„Š„œ¤¦ƒ||ult{{t‚|u„Š„š””ƒ}ƒedk{||“Œ”tt{‚|uztl|‚z„Š„ult“Œ”tzl”𔋋„„Š„‹‹‹“Œ”ƒ||ƒ„„ztltts]cd””‹|‚z‹’Š””‹|„…u{{‹„‹…‹‹llklddtllmttƒƒ|š””ŠŠ}tts‹„„{u{ƒ}ƒ™š¤tllUMRllkttstll{ttmwSKJ[[Td\\“““’…‹cbV‚|uyle‹‹„ƒ„„š””‚|ulldŠƒ}tts‹‹„sleŠŠ}””‹£œ¥{u{™š¤“Œ”zllrfkf]ctsl{tt{tt{zmŠ}ƒ…‹‹ƒ||‹„„™š¤”››ƒƒ|‹„‹‹‹‹kd\llkƒƒ||‚z‹„‹zlltsl{zmƒƒ|’ŒŒ{ttš””„Š„‹’Štlltsl|„…{{t{||“Œ”{u{Œ”•‹‹‹‹…’”“›lri‚v{ult{||¦§¨“““ƒ||‹„„ƒƒ|£››””‹“Œ”“Œ”£²Ã¼¿¦§¨{zm¦§¨Œ‹“œ››²¬µ{{t‘…„f]c“““›¢›¦§¨ƒ||„„Š‹„‹ŠŠ}{{tœ››lri””‹ƒƒ|‹„‹‚v{lekf]c‚wl{||“Œ”šŒ””‹ƒƒ|“““›”›œ››{{t“Œ”sre””‹¦§¨‹’Š|‚z–¢‹‹‹‹ddc‹„„{{t‹„„šŒtslŠƒ}llk\[[ƒ}ƒztlƒ}ƒƒ}ƒfkk¦§¨“““Œ‹“””‹“Œ”Œ”•ultllksle‹‹‹“““|‚z{||„Š„VTL\UZ„Š}£œ¥lddedkUMRŒŒšf]c‹‹‹{{tult{||‚ut‹‹‹ttslddllk””‹Š~‹›”›’…‹uzt‘Œ…tsl””‹‹‹‹Š~‹„„Š|‚z‹‹„ƒ„„‹‹‹Š}ƒj]\‘Œ…ƒƒ|‹‹„tt{š””µ¶·f]c*)(tll‚|uš””‹…’mtt{u{Š}|{zmtslf]c|‚zlrikd\[TTtt{‚|ulri™š¤ƒ}ƒdc\„„Š„Š}ƒ„„‹„„{tt¤¤œ››Œ‹“›”›tts²««‹‹‹‹„‹‹‹„{{tƒ||”››ƒƒ|„Š„ƒ‚uŒ”•”“›tt{“Œ”Š~‹‹‹„‹’Š{{ƒVTL‚v{|‚z™š¤‹‹‹’…‹|„…ƒ}Š‹„‹‹‹‹ƒ}ƒŒ”•‚utdc\kd\\[[‚utƒ||{{t‹‹„‚|ulri‰v|ttsttsllkƒ„„|‚z’…‹j]\‹’Š{u{i\Vsreš””›”›Šƒ}ƒ||VTL‹„„ylellkztfmwlddtsl{zmƒƒ|„Š}{u{‹„„‰ƒv‚utœ››ƒ‚ullk„Š„sreƒ}ƒd\\kk]Šƒ}‚ut{tt‹„„‚ut{||ekdƒ„„”š”tslƒ}ƒƒƒ|{||{{t{{ƒ››”ŒŒš™š¤{u{‹„‹¦§¨{{t¦§¨µ¶·‹’Š‹‹‹“““£œ¥Œ”•‘Œ…£œ¥‹„„‘…„’ŒŒ™š¤ƒƒ|¨©´tll‚v‚““““Œ”{u{œ››””‹“Œ”ekdŒ‹“ƒ}ƒ‘Œ…ƒƒ|‹„„kk]ttsrfk‹‹„‚v{ƒ||zll‹„„lri›”›‘Œ…‹‹‹¦§¨”››£››‹’Š‘Œ…‚utŠƒ}{{t‹’Š‹‹„‹’Š”š”{u{tsl{{t‹‹‹u{{ddcttsƒ‚u…‹‹{||ƒ„„{{t„Š„‹’Ц§¨{u{“““tll›¢›‹„„‹‹‹‹„„‹„‹””‹…‹‹”››lek{{ƒ|„…d\\ult{zm¤¤ultlkslks{u{rfkdc\ƒ„„ƒ}ƒlri{{t”“›ƒ}ƒ„Š„{{t‚ut{tt›”›Œ‹“‹’Šƒƒ|llk{zmƒ}ƒƒ||tts{zm{{ttllrfkŠƒ}{ttsreƒ||{yf‹’Šztl””‹JHF?;C‘Œ…‘Œ…”››‹„„ƒ}ƒtzlulttll[[T›”›‹‹„\[[ultƒ||tllƒ||Œ”•|‚zƒ||’…‹‘…„lri“Œ”‹‹„”“›“““ekdlld‹„„u{{ult‚|ukk][TT{ttkd\ddc‚|uƒ„„{{t„„Šƒ||“Œ”“Œ”tllek]‹„„ddc‰‰w„Š„[[Tllkd\\…‹‹f]c{u{llk‚utlrittstllultsle{ttj]\{||ddcsleztl[TTred‹’Šlddzllƒ||\[[‚v{{||{{t™š¤{ttlld’ŒŒ‹‹„u{{{||lek“Œ”£››tslƒ||ztl…‹’tsl„Š„”š”|‚z£œ¥š””””‹|„…{{ƒƒ‚ulriƒƒ|lld‹„„dc\{ttƒƒ|ztfultƒ||‹„„lks{{t“Œ”|„…‹‹‹›”›””‹{u{tll™š¤llk£››£œ¥‹‹‹dc\|‚z””‹œ››‹„‹¤¤’ŒŒult””‹”››tllƒ}ƒultƒƒ|‹‹„lld”š””››lriŒ”•tllƒ||””‹kk]‚ut¨©´›”›„„Š‹„„‹„„››”tts{||››”…‹‹rg]ƒ||šŒ£œ¥‹„‹ƒ„„ƒ}ƒŠ}|ƒ||‹„‹{||²¬µŒ”•Šƒ}ƒ‚ukk]‰ƒv›¢›‹’Š”š”ƒƒ|’ŒŒ‹„„¦§¨œ››ƒ„„ldd|„…|„…‰‘~]bZult‹…’ƒƒ|››”sleƒ„„llkƒ}ƒ””‹‹„‹|‚zƒ}ƒ{u{„Š„ƒ„„„„Š‹‹‹„„Š|‚z]bZŒ‹“›¢›„Š}|„…JHFlksult›”›‹’Šƒƒ|’…‹ƒƒ|tllŠ}ƒ{{ƒª³·“Œ”‚wl‘…„„vŒ‹‹‹¨©´””‹sletts””‹‚ut’ŒŒ{||ttsœ››ztl“Œ”‘…„‚|uztl‹‹‹{{tek]¤¤:97*)(‘Œ…tlltslekdult‹„„Š}|ultkd\mttƒƒ||„…u{{kd\{u{lddekd{{ƒlekVTL™š¤œ¤¦œ¤¦”𔓓“ƒ„„œ¤¦{{ƒ{|||„…’ŒŒ››”¨©´lldtll|‚z›”›ƒ||tslƒ„„¦§¨”“›ult”š”|„…‹’Šƒ„„ddcƒ||ƒ}ƒ{{t\UZllk„„Š‹‹‹{u{ƒ}ƒultj]\“Œ”r]g{||ƒ||{u{j]\›”›Šƒ}tsl‰|v”››Šƒ}ª³·ult{yfšŒtzl‚utbVUllkzll’ŒŒf]cƒ||‚uttts\UZ{{tztlƒ||ƒƒ|‹‹„šŒlld{{tz‚lŒ”•tts”››””‹{{t’ŒŒtts‚ut{||‹‹„ƒ„„“““d\\‹„‹ztf’ŒŒzll‹„„’ŒŒƒ„„››”ult…‹‹ƒ||š””Œ”•{u{›”›lks‹„„”››llk“““Œ‹“””‹ztl™š¤œ››²¬µ£››{{t{{tllk‘Œ…‚v{š””””‹œ¤¦‹‹‹›¢›œ¤¦“Œ””“›{{ƒ‚utkd\lld”𔋄‹’ŒŒ¨©´‹„„ƒ„„{{tƒ„„tzl›¢›‹‹‹‘…„¦§¨››”£œ¥¦§¨£››“Œ”£››‚|u{{tƒ„„‹„„”š”{u{“Œ”dc\‚ut{{tjcVœ››“““{u{lek›¢›””‹„Š„mtt‹’Šuzttzllrimtt\UZmtt”š”œ››{tt‹’Š‹„‹›”›¦§¨œ››ztltt{Œ”•¦§¨”“›„„Š›”›”“›‹’ŠtllŒ”•œ¤¦ƒƒ|UUYUMR\[bult‹’Š”››…‹‹uzttll“““ƒ}Š{||lks””‹ulttt{lddƒ„„“Œ”sretslƒ||‹„„tllƒ„„‹‹„{u{“Œ”‚ut‚v{ŠŠ}{{t|‚zƒ||lld¦§¨VTL74,‹’Šš””‹’Štt{“Œ”ƒ||‚v{[[T]bZlek‹„„”š”ztllri{{ƒult{||llkultkd\sle¦§¨Œ”•‹’Ц§¨Œ‹“¦§¨‚utš””ƒ„„“““”››{{tƒ||””‹Šƒ}{||“““b[U›¢›œ§²£œ¥Œ‹“mttŒ”•‹„‹ultf]c‹„‹ldd‹„„tts‹„‹uztSKJ[TTultult„„Šllki\Vƒ}ƒ{tt‹„„””‹j]\£››ƒ||¤¤Œ”•‹„„dc\‹‹„ŠŠ}{{tVTL‚utSKJtzlb[U{ttSKJ{ttkd\ƒ„„bVU[TTŠƒ}{ttuzt‹„„zllkk]tll{||‘…„‹’Š“““lddbVU‚utkk]lri‹‹‹ttsŠŠ}…‹‹|‚z“Œ”¤¤‹„„{ttrfk‹‹„{ttŠƒ}‹…’‹‹‹”š”tts”“›tllš””{{ƒƒ„„„„Š“Œ””“›{tt›¢›kd\”››“Œ”‘…„ultttslld‹„„sle›”›ƒ}ƒ£››‹’Š“““”𔓓““Œ”|„…‹…’Œ”•‹„„””‹£››“Œ”Šƒ}“Œ”“Œ”¦§¨›¢›’…‹u{{tzlƒ}ƒedk“““¦§¨‰v|red¦§¨“Œ”‚ut|„…Šƒ}‹‹„{||”“›‘Œ…£››‹’Š{zmŠƒ}„Š„¦§¨š””œ››™š¤››”‹„‹Šƒ}Œ”•{{tƒƒ||‚z|‚z’ˆllk”š”|‚zddcƒ„„…‹‹ƒ||{u{‹u…„Š}tt{‹„‹”››”š”Œ”•µ¶·œ››lri‹’ŠŒŒš¨©´‹’Šƒ}Š[TTf]clek¦§¨{||lld|‚zmtttt{{{tƒ||tt{{u{redd\\ƒ}ƒ™š¤””‹{u{‹‹„tslztlulttll‚ut„Š}‹„„Šƒ}šŒ{tt‹„„…‹‹tzlmtt{zm›¢›JHF:97{{t‘ˆ}dc\…‹‹Œ‹“š””ztlztlllk‹’Šdc\ƒƒ|cbVz‚l„„Šult››”llk{||ultŠƒ}„‰v|„…ƒƒ|ƒ}ƒ“““‹’Štt{¦§¨¦§¨{tt”››tt{‹‹„lriztl{||tllƒƒ|VZT|‚z™š¤tt{fkkllkƒ||[TTJHFf]c\[[lldultf]cf]c\UZllk‹„„ult‹‹‹lekyfllek¤¤ƒ}ƒ{zmŠŠ}‚wlSKJšŒd\\JHF{{t|‚zsre’ŒŒ{{tƒ||red{{t‚|usre{||Š}|cbVtllzll‹’Š{tt‹‹„‹„„ztl‚uttllllkƒ||‹‹„{tttzlVTLtll]bZkd\ƒ‚uƒƒ|”››‹‹„™š¤lld{ttƒƒ|‹’Š“Œ”‚v{’ŒŒŠ}|››”{|||„…„Š„tt{Œ”•“Œ”‹„„„„Š‹‹‹{ttmttultzllƒ„„¤¤ƒ}ƒlddldd£››“Œ”ddcƒƒ|ƒƒ|‘…„¤¤””‹Œ”•”››tts”š”””‹£œ¥ƒ„„Š}ƒ¦§¨ƒ‚u››”£œ¥’ŒŒ“Œ”£²‚|uredu{{ztl’‘~Š}|ƒƒ|𔔣œ¥{tt‹„„b[U£››kd\Š}ƒkd\‹’Š‹„‹ƒƒ|£››£››””‹Š}|{{ttts””‹””‹£œ¥{{tlri‹’ŠŒ‹“tsllriz}‹’ŠŒ”•tsl“““ult””‹ztlzllœ¤¦Š}ƒƒ||{ttŒ”•„Š„ztl”š”…‹‹”››‹’Š”“›ƒƒ||‚z\[[›¢›lldŒ”•‹‹„’ŒŒ{u{‹…’’ŒŒŒ”•ƒ„„œ¤¦™š¤‹…’‹„‹uzt‹„‹¤¤‹„„{tttll¦§¨ƒƒ|{zm„„ŠŠ}|ulttll”››{zm{{t’ŒŒš””tll‹‹„‹‹‹”𔓓“””‹¤¤JHF*)(ultcbV|‚zttsƒ„„]bZŒ”•red{ttj]\‹’Štslƒƒ|kk]ult¤¤”“›Œ”•f]ckd\bVU‹’Š…‹‹dc\d\\¤¤‹’Š|‚zŠ}|ƒ}ƒŒ‹“ƒƒ|“Œ”zll£œ¥{{t{{ƒllkuzto€wlkstt{™š¤u{{Œ”•UMRd\\ldd‚v{UMRj]\ultmwtsledkUTSƒ||ƒƒ|ƒƒ|tt{‘Œ…tll‹‹„‹‹„{{t[[T{ttredztllldlriƒ}ƒtzl{{td\\ƒ‚u‚|uƒ||ƒ‚u{||£››ldd{tt[TTd\\FD;rr]{tt{tt“““š””tll‹„‹ƒ„„‹‹‹tsllldd\\ztl{{t””‹ztltzl{{t|‚z’…‹‹‹‹…‹‹‹„„ztlƒ„„rfk”“›‹‹„{u{‹‹‹{{ƒztllddj]\mtt‹„‹{ttlek“““„Š„tt{\[bllk|‚z””‹™š¤ƒƒ|ƒ||tll{||„Š„’ŒŒ„Š„¦§¨œ››£œ¥{||”š”ª³·œ¤¦ƒ‚uŒ”•Š}ƒ··Ä£œ¥¦§¨«²«œ››f]cŒ‹“‹„„{{tƒ„„f]c‹’Š‹„„“““ldd{ttŠ}ƒtllŠ}ƒcbVddc{u{š””ƒ||ztlttsƒƒ|Šƒ}–¢‹››”””‹ƒƒ|ƒ„„𔔣œ¥„„Šztl{{t‹‹„…‹‹u{{lddlriŒ”•mtt]cd]cdŠ}ƒedkj]\‚|u‹‹„¦§¨redult”š”™š¤’ŒŒ™š¤š””¦§¨uztƒ}Š|„…dc\tlllri|„…|‚ztt{u{{™š¤{{tƒ||„Š„ƒƒ|œ¤¦ƒ}ƒtslƒ}ƒ|‚zƒ}ƒ‹„„‚|umtt{u{{zm„Š„ztlddcztlult‹‹‹{ttztlƒ||kd\‚|uultf]c{{ƒƒ||”𔣛›“““>EC:97tslSKJ{{tŒ‹“‹’ŠVTL‚wlŠ}|{u{d\\rg]|‚z„Š}mtt‹’Šš””™š¤{{tbVZ{u{sre|„…‹‹‹ƒƒ|{||zll|‚z{u{””‹”š”uzt”››ulttll{{tlddƒ}Š{tt|‚z‹’ŠUTSŒ‹“ult\[blrilldf]ctll£œ¥mwtsllek‹„‹””‹…‹‹JHFuzt¦§¨{tt[[T›”›{||kk]’ŒŒ‚utSKJred‚v{‹’Šllk|‚z‹’Љƒv‹„„d\\tslultedkƒ}ƒ“““ƒƒ||„…b[Uztl‘Œ…„Š}kjV‚|utllƒ„„{{t{tt›”›dc\ƒƒ|ƒƒ|{||lldƒ‚u””‹‘Œ…””‹‹„„‹„‹”š”ƒ}ƒƒ}ƒtts{tt‹‹„{{t‹„„ƒ}ƒƒƒ|{||Œ”•‹„‹”“›|„…{||Œ”•ttslektt{{tt{||Œ”•‹„„œ››‹‹‹¦§¨ƒ}ƒ{{t’ŒŒ‚v{tslŒ”•š””‘Œ…“Œ”¦§¨››”’ŒŒµ¶·œ¤¦‹’Štslœ››{tt…‹‹¦§¨›¢›¦§¨“““‹…’ƒ}ƒš””¤¤¦§¨£››š””›¢›¦§¨ª³·œ››‹„‹‹„„{tttts{zm‹„„£››{tt{{t{ttŒ‹“\UZred‹’Š{u{uztš””Šƒ}œ››‹„‹{ttbVU{|||„…]bZŒ”•‹’Š›¢›Œ”•…‹‹‹‹„ult””‹‹’Š“““„„Šult“““š””‹„‹“““|‚zultdc\llkkd\tlledkttsultfkklks\[blekllk{{ƒkk]‹’Šœ¤¦¤¤Œ”•œ››¦§¨ekdttsƒ}Š{||‹‹„“Œ”{u{uzt{{tdc\|‚z‘Œ…“Œ”ƒ„„Œ”•{{tztf‘…„ƒ„„›”›llkšŒ””‹“““’…‹‹’Š:977-2”››‹‹„ŠŠ}”š”llk{u{ƒƒ|‹„„„„Š{u{tzllld|‚zlldu{{ttstt{lriultŠŠ}]bZkd\{ttƒ||tll””‹lld’ŒŒŠƒ}‘Œ…|‚zƒ}ƒ”“›rfk¤¤‹’Š“““|‚zƒƒ|{||™š¤llktt{„Š„lksf]c{u{SKJƒ}Š{ttlldŒ‹“tll{tt‚v{…‹‹|‚z|‚zuzt[TTƒ||llk‚wlrfkVTLsleƒ||slettslld‹‹„tts|‚zsleƒ||aWMSKJFD;ztlultu{{“Œ”[TT””‹slelldkd\‚|utsltts„Š„‹„‹uzttllb[Utyg{{ƒ””‹ztlsrekk]‹„‹{{t™š¤¦§¨››”“Œ”ddc””‹‹„„sle‹…’ƒ„„”𔋋‹|‚ztts…‹‹ƒ}Š{tttt{{||“““ddc‹…’{||{{ƒtts„„Š‹„‹¤¤Š~‹“““‘…„ƒ}ƒ›¢›‹’Š››”{{t£œ¥™š¤’ŒŒµ¶·œ¤¦œ¤¦¤¤””‹¨©´µ¶·™š¤œ››µ¶·¦§¨“Œ”£œ¥“Œ”f]cƒ„„mw‹„‹‚wl‚|u””‹””‹””‹„Š„„„Š“Œ”uztbVU››”“Œ”lld‹‹„ddctsl‹„‹{ttsle‚|uƒ„„ult“Œ”{||“Œ”rg]ƒƒ|Šƒ}ƒ„„lri{||œ››mtt|‚z„„Štt{ddc’…‹“““›¢›{||rfk››”£œ¥‹‹‹„Š}ztlŒ”•zll‹’Šƒ||lddŒ”•ƒƒ|‚v{uztVTLultSKJtslŒ‹“[[Ttzl‹’Š‹‹„{||{||„Š„{tt””‹„Š„““““““Œ”•{{ƒ‹’Šultƒƒ|ƒ„„{{t‹„„{u{“““”𔋄„Š}|ƒ||tsl{u{‚|u{tt|„…uzt”š”>B9*)(zllƒ|||„…“Œ”{{tllklddbVUd\\lddek]UTSlri[[T{{ƒtslult{{td\\„Š}u{{cbVbVZ››”ƒ}ƒsleb[U{||zll‹„„{||”“›ƒ}ƒtsl{ttƒ‚u|‚z„„Šuzt|„…|„…{{ƒ\[bJHFJHF\[[f]cd\\\UZb[Ud\\ƒ„„ttsd\\VTLƒ}ƒ‹„‹{zmtsl{||‚|u{{tƒƒ|„„Šf]c]bZsleldd£››ddclld|‚ztzl‚|utllaWMsre{{ƒ{zmŒ‹“j]\tllƒ||‹„„tslztlf]cb[U|‚z{||Šƒ}Œ‹“dc\|„…zll‹‹„Œ”•ek]tsl‚ut‘Œ…{ttƒƒ|lri‚v‚‹‹„ƒ}ƒ¤¤tlliq]tsld\\{||{{t‹„‹|‚z›”›{{ƒƒ}ƒš””Œ‹“›”›ƒ}ƒ{{ƒ{||ƒ}ƒ”š”{u{ƒ||‹„„Œ”•Š}ƒ‹„„¦§¨’ŒŒ‹’Š”“›”››“Œ”™š¤‹‹‹””‹¦§¨‹’Ѝ©´{{ƒ”“›ƒ}ƒŠ}ƒ“Œ”¤¤œ¤¦sle“““Š~‹£œ¥’ŒŒ“““œ›››¢›‹’Šƒ||‚|u{{tƒ|||‚z“Œ”ŒŒš\[[‚v{„Š}ztl{||“““‹„‹tsllldj]\ttstzl{||‚wl“Œ”ƒ}ƒƒ„„lldƒ||››”„Š„„„Šlldmttlks|„…lksuzt„„Š“Œ”››”‹‹‹{{ttts“Œ”ƒ}ƒ‹‹‹“““””‹Œ”•{{tƒƒ|ƒƒ|’ŒŒ‹‹‹lriƒ„„œ¤¦”“›Œ”•r]glldƒ„„mtt|‚z„Š„lddœ§²‚v{‹’Š’ŒŒƒ„„‹‹‹‘…„‘Œ…tt{{{ƒƒƒ|‹„‹š””Š~‹’ŒŒ‹‹‹‹„‹‹’Š{{t…‹‹{{t’ŒŒ“Œ”dc\VTLtllVTL]bZ’ŒŒJHFJHF“““‹‹‹|‚z|„…]bZSKJd\\ultddcd\\b[U|„…|‚zlekttssleultuzt‹‹‹‹„„{{t{{ƒ‹„‹“““ƒƒ|‘Œ…‹’Š|‚zllkldd|‚ztts{u{lddƒ}ƒ|‚z|‚zMRKddcult]bZlddultf]cmtt„„Štsl[TTultd\\lddu{{Š}ƒtllj]\„„Šf]c‚|ukd\{||{u{[TTŠ}|{u{sreztl‹„„{zmcbVƒ||„Š„tzltzlultkd\{||’ŒŒllk…‹‹zll‚utult‹‹„¦§¨kd\VTLsle””‹|‚zdc\“Œ”ƒ||ztl’ŒŒsresre”š”kk]tsl‚utsleldd‹‹‹‹…’ulttlllddllkSKJiq]tsl‹„„ƒ}ƒ‹‹‹Œ”•{tt{{ƒ{||llk‹’Š{{ƒ™š¤’ŒŒ™š¤|‚zŒ‹“™š¤ƒ||tts“““{{tkd\””‹ƒ||¦§¨Œ”•{||ƒ}ƒ””‹£œ¥‹„‹”𔛢›”››™š¤ult‹‹‹|‚z™š¤£œ¥uzt‹’Šœ››¨©´Œ‹““Œ”tsl|„…{{tœ››‚|u¦§¨“““œ¤¦Šƒ}™š¤ldd¦§¨Œ”•“Œ”‹„„’ŒŒ‹„„£œ¥Œ‹“ƒ„„dc\ldd‹„‹””‹‹‹„‹„‹‚|utt{ƒ„„›”›‹‹‹…‹‹tt{œ¤¦tsl|„…|„…{{t¨©´”š”„„ŠŒ”•{{ƒ|„…tts’ŒŒ””‹‚utŠƒ}Œ‹“sle™š¤””‹”››‚ut{||ª³·Œ”•£œ¥ekdœ¤¦£››…‹’Œ”•œ§²|‚z‹‹‹”››”𔦧¨™š¤œ›››¢›tsl”š”ƒ}ƒztl{u{llkƒ||¦§¨‘…„ƒ}ƒ‘Œ…‚v{ƒ„„””‹{{t{||{ttj]\ttsŠ}ƒ|‚zttsddc„Š„‹„„SKJ*)({||dc\lddtllVTLf]c‹‹‹{u{uztttstslu{{””‹lriu{{f]c‹‹‹ƒ„„u{{lld‹‹„Œ‹“‹„„ƒ„„…‹‹’ŒŒƒ||ƒ||²¬µdc\b[U¦§¨‹„„„„Šllk“““‹„„uzttzlddcu{{d\\ddcJHFVZTSKJ“““’ŒŒ‚v{tt{[TTlksƒ||tsld\\[TTddc””‹‚|utts’…‹{||red{ttd\\sle””‹d\\ƒ}ƒ\[[z‚lŒ”•ƒ„„bVZŠ}|’ŒŒƒ||ƒ||{||‚v{rg]rfkkd\‹„‹ƒƒ|kd\{{tslesrelld‹„„red|‚zsletslztl…‹‹{tt‚|uš…ŽŠ}|“Œ”‹’ŠŠ}ƒ{{t‚|u{tttslƒƒ|sleƒƒ|‚v{tsl{tt”››ƒ„„£››tts|„…ƒƒ|{u{ttstt{ƒ„„mtt“Œ”™š¤‚v{llk{ttŠŠ}™š¤ztl£œ¥‹„„‹‹‹¨©´’ŒŒ™š¤“Œ”“Œ”„Š}‹‹‹|‚z¦§¨ƒ„„„Š}¦§¨“Œ”‹„„„Š„µ¶·Â¾Æ£››£››Š~‹›¢›”𔄄Л¢›Šƒ}¦§¨‹‹‹{tt¦§¨””‹‹’Š›”›{||“Œ”tts‚ut£››’ŒŒ‹„„‘Œ…{||Š}ƒŠƒ}ƒ}Š”š”‘Œ…‘Œ…”“›ultœ››››”|„…lriš”””››|„…’ˆŒ‹“…‹’|„…|‚z”“›ult|„…dc\“““²¬µ’ŒŒœ››{u{ƒ}ƒ”“›‚|u{zm{tt‹‹„™š¤Œ‹“‹„‹„Š„Œ‹“ƒ}ƒ{ttttsu{{ª³·¦§¨ƒ„„Œ”•Œ‹“j]\””‹””‹uzt‹„„tsl‚v{ƒ}ƒuzt‹‹‹‹‹‹bVUƒ||ztl‹„‹Œ‹“{{t{tt{{t‚ut{ttllk‚|u{{t|‚z\[[dc\‹‹‹:97&&UTSd\\d\\u{{ztl|„…š””™š¤{{tƒ„„œ¤¦””‹|‚z|„…“““”š”“Œ”mtt‹‹„„Š„sle”››£œ¥‹’Š‹’Š‹‹„{{tlld›”›sletts‹‹„£œ¥ª³·{tt“““ekd…‹’ekdsrelrif]c‹„‹{{ƒmttsle{zmzllƒ||Œ‹“¦§¨ldd››”lektlledkult{{t\[[|„…£œ¥f]cttslddtslkd\sleSKJ‹‹‹\[[leklldtts{u{tll””‹{{tƒ}ƒš””ztlrfkttssle””‹VTLtllsleztf{u{uztŠ}ƒf]csredc\Šƒ}sre{u{{zm{||£››Š}|‹‹„“““lldkd\‹„‹{tttlld\\„Š„sreœ››„Š„{{t™š¤Œ‹“ƒ||ttstll{u{mtt””‹{tt”“›‹‹‹{{ƒ{{ƒ{tt{{ƒf]c”››”“›‹‹„Š~‹£œ¥ttsŒ—£››”tts’…‹ƒ}ŠŒ”•‹’ŠŒ”•ƒƒ|tsllri…‹’¦§¨‹‹‹“““»ÂÇ”š”“Œ”²¬µ›”›””‹tsltsl›¢›š””Š}|ult”š”””‹‹„‹‚|u{u{{{t{u{š””›”›ƒ„„tts‹‹‹ƒ}ƒ{{ƒ“Œ”llk›”›‹’Šƒ||š””|‚z‹„‹{{ƒ‹‹„|„…mtt\[[‹„„ƒ„„|„…|„…Œ‹“mttŒ”•f]cd\\|‚zƒƒ|‚ut‹…’‹…’‹„‹„Š„tllmtt‹„‹tll”š”ƒƒ|›¢›…‹‹™š¤mtt™š¤¨©´ztl{ttŒ”•Ž¡›”››u{{œ¤¦ttsƒ}ƒ¦§¨‹‹„Œ”•”››ƒƒ|lrilekttsŠ}|{||{tt{{tƒƒ|‹‹„š””ƒ‚uuzt‹„„‚ut‚v{lks‘…„‹„„{||{{ƒJHF£››:97*)([[TSKJJHF\[[lri“Œ”{||‹„‹tsl{ttlri‹’Š|‚zŠŠ}ƒ„„u{{™š¤kd\„Š„ƒ„„£››…‹’‚v‚›¢›Œ”•|‚z‹„‹œ¤¦“Œ”¦§¨„Š„Œ”•¦§¨“Œ””𔦧¨f]cf]cVTLek]kk]Œ”•ultd\\VTLŠ}ƒ{||„Š„f]ctt{Œ”•edkš””lddedk„„ŠuztVTLmtt…‹’ldd„Š„‹‹‹ƒ||kd\lddzlllksƒ||š””|„…{||{u{ƒ||lddtlld\\u{{ƒƒ|f]c[TTtllƒ||‚|u{zmj]\zllj]\{{t”“›tllŒ‹“{{tSKJ…‹‹¤¤|‚z„„ŠŠ}|ldd‹„„‹‹„ƒ}ƒ{ttƒ‚u‹‹‹„Š„“““ldd‹‹„‹’Š“““|‚z…‹‹{{ƒ{tt{{t{{ƒ‹‹„sle{||„Š„uzttts{u{ƒ||{{ƒ{tt{u{‹’ŠtslŒ‹“‹„„Œ‹“£œ¥tslŒ”•llktt{“Œ”lek„Š„”š”|„…›¢›œ››„‰vŒ”•œ››¨©´ª³·…‹’œ¤¦tt{‚v{²¬µ””‹œ¤¦Š}|‹‹„‹‹„ƒƒ|Œ”•””‹œ››ƒ}ƒ‘Œ…™š¤ƒƒ|‹„‹{||£››’…‹Œ‹“””‹›”›£››£››{{ƒ›”››¢›¦§¨œ››ƒƒ|Œ‹“{tt‚v{ƒ}ƒƒ„„‹„„zllmtt™š¤|„…ŒŒšJHFlldlks{ttsleldd“““™š¤‹„„‘…„‹’Šš””™š¤‹‹„‹‹„””‹Œ”•œ¤¦”››Œ‹“dc\…„’ƒ}ƒttsƒ„„{u{lld’…‹„„Ц§¨llk“Œ”“““{||tts|‚z“Œ”lek{{ƒult‚|uztl‚v{‚|u‹‹„š””‹„„„„Štzlœ››‰|vtlluzt”š”ttsllklld{{t››”SKJ*)(lkslldVTLUTSsref]ctllbVZtzllldmtt|‚z{{tƒƒ||‚zƒ„„Œ”•‹’Š‹’Šlld›¢›Œ”•šŒ¦§¨{||\[[‹’Š‹‹„””‹ƒ}Š{||…‹‹tll››”|‚z›¢›ŒŒšult”››lld{||mtt£››dc\MSS“““…‹‹”››’…‹{{ƒ„Š}lriztlsrezllŒ”•ttslddztl{||‹„„llkf]cllkultVTLsre{zmzllƒƒ|f]ctsl{||{u{dc\SKJ‹„‹ultlldƒ„„nƒf]c{||ŠŠ}””‹‰ƒvŠƒ}ult{||ƒƒ|‹„‹tts{zm{tt””‹‹‹‹“““{||{tt{tt‘…„tslŠ}ƒ£››ƒƒ|‹‹‹kd\sleulttllƒƒ|£››{{tŠƒ}ƒ„„”››‚ut…‹‹“Œ”llkllkttsllk™š¤{u{ddc…‹’Œ‹““““‚|uƒ||”››”š”’ŒŒ¦§¨œ¤¦|‚z‹’Š{{ƒ{u{ƒ}ŠŒ”•‹‹„|‚z‹„‹¦§¨›¢›«²«™š¤”“›„„Šš””‹‹‹ƒ}ƒ‹„„]cdƒ„„|„…š””uztkd\’ŒŒ{tttsl”š”Œ‹“{tt›”›ƒƒ|‹„„lek›”›¦§¨Œ”•{tt¤¤‹„„’ŒŒ£œ¥ŠŠ}tzlš””ƒƒ|”𔋋‹tllƒ}ƒ|„…redUMRtt{…‹‹UTS„„Š…„’ƒ„„…‹‹ƒ}ƒ“Œ”‹‹„ŠŠ}Š}|¦§¨µ¶·“Œ”‹‹‹“““tll“Œ”””‹››”›¢›Œ”•…‹‹lri„Š„{u{¨©´ŒŒš…‹‹u{{’ŒŒŒ”•”𔋋‹tt{™š¤uzt™š¤tts„„Š›”›¦§¨ƒ„„ƒƒ|tslš”””“›‰v|ƒƒ|Š}ƒkk]|„…ldd¦§¨š””’ŒŒ”𔋋„””‹{u{“““{||²««JHF3+*”››ƒƒ||„…UTSdc\Š}|‚ut[TT{||lkstsl|‚zƒƒ||‚z|‚zƒ}ƒ“Œ”lri’ŒŒ{{ƒ””‹|‚z›”›{||‹’Šƒ||ekd…‹‹rfkkd\ƒ‚uttsƒ||“Œ”‹‹‹›¢›ª³·‹„„mtt>B9JHFlksƒƒ|tsl””‹\UZ{{ƒ…‹’Œ‹“\UZfkk››”VTLult‚|u‹„‹¦§¨…‹‹d\\\[[ult‹‹„ek]llkbVUj]\tzlztlslekd\ult¦§¨‹’ŠŠƒ}ldd{tt{u{tt{b[USKJiWU{u{”“›ƒ„„{zmVTLrg]sreedkƒ||{ttttsƒ„„„Š„‹„„Š}|‹‹‹zlltllƒ||rg]ztlƒ||ztlbVUlddu{{Šƒ}kd\lldtsl‹’Štllsle{{t‹‹„{ttllkedk{ttttslldedk{u{tt{llklks|„…sre„Š}Œ”•Œ”•¦§¨ÂÅÓ”“›¦§¨…‹’”š”œ¤¦”“›“Œ”‹‹„|‚z¦§¨ƒ„„ƒ‚u›¢›œ¤¦™š¤£››{u{{{ƒ””‹‚v{lrif]cdc\”“›œ¤¦ƒƒ|ƒ‚u“““„„Š‹‹„‰‰wsretts{tt””‹£œ¥„Є𔔋„‹”“›‹‹‹„Š„ult‚v‚tllult|‚z„Š„{{tœ¤¦‹„‹’ŒŒ‚v{ƒ„„ldd{tt{||œ¤¦…‹’…‹‹{{ƒ›¢›lkslek‹„„‹„„ƒƒ|‹‹„‹u…’…‹‹„‹‹‹„’ŒŒ{{ƒ››”{{t¦§¨ŠŠ}¦§¨™š¤…„’{{tult„„Š|‚zŒ”•llktslmtt£œ¥|„…llklddlek{{ƒ{{tƒ„„‹„„ƒƒ|‚v{’ŒŒ¨©´¦§¨š””ƒ||””‹“Œ”‹„‹œ››‰ƒvkd\redulttsldc\sleƒ}ƒlekƒ„„””‹JHF{{tlldkd\UMRUTSlksSKJUTS]bZƒ||lritslkk]tslllk{tt{||ƒ||Š}|‚ut|‚z¦§¨‚v‚œ¤¦|‚z‹‹„|‚ztsl‹‹‹‹‹„…‹‹llkj]\Œ‹“|‚z£œ¥{u{tt{\[[|‚zlldŒŒš“Œ”uztkk]ƒ||tt{lek{u{“““dc\f]cuzt‚|ucbVu{{tzlddcƒƒ|dc\sleƒƒ|””‹‹‹„VTLb[Ulri{zm‚v‚ek]lldsle{||’ŒŒllkd\\›”›JHFttsb[UbVUztl{zmtzlŠŠ}SKJ]bZfkk|‚z‹„‹tll“Œ”[[TtslultŠ}|ƒ}ƒllkyle‚|u’…‹tllƒ||‚v{ztld\\{||yletlllri‚wlj]\‹„‹uzt‹‹‹ldduztult“Œ”‹„„{{ƒ{u{{{ƒŒ‹“lekmttddc„„Š™š¤{||¦§¨Œ”•{||··Ä¨©´œ¤¦Œ”•|‚z™š¤‹‹„u{{”“›ƒ„„ª³·¨©´ª³·Œ‹“¦§¨Œ”•‹„‹tsl™š¤œ››’ŒŒ‹„‹’ŒŒ¤¤”››“Œ”“““‹’Šƒ||‹‹‹¦§¨tsl“Œ”‹‹„ƒ}ƒtll£œ¥ƒ„„£››‹„‹‹„‹ƒ„„‹’Š‹‹‹Š}ƒttsš””‹‹‹{{tƒƒ|ƒƒ|[[T“““{|||‚ztllƒ}ƒƒ„„œ¤¦mtt|„…fkk£œ¥”“›“Œ”‚v{‹„‹„Š„|‚z“Œ”‹„„tlllri‹‹‹‹„‹£œ¥ldd‹‹„‰‰w”š”|„…{{ƒu{{¨©´Œ‹“lri„„Šllk{{tlks‹’ŠŒ”•‹’Šylelks{{ƒtslƒƒ|‹„„lks‚v{‹‹‹{{ƒŠ}ƒ‹„‹ztlztlbVZƒ}ƒ™š¤ztld\\Šƒ}{u{„Š„ƒ}ƒsrelekedkƒ„„£››JHF:97llklldj]\lek[[T„„Štslldd{||lekdc\dc\{ttb[UŒ‹“lkstsl‚|uŠƒ}ŠŠ}ƒƒ|Œ”•{{ƒœ¤¦””‹“““‹‹‹sleœ››{u{ttsŠ}ƒ›”›‹’Šlldƒ}ƒlddmtt|„…mtttll{{ƒ¨©´“““sle‹‹‹ƒ„„f]cJHFlks|„…b[UJHF{{tD;9u{{ƒƒ|‹‹‹œ››tts{||b[U]bZ[TTƒ||‹’Šƒ„„dc\ƒ||ttstsllldllkztl{{ƒ‹’ŠlekbVZf]cƒ||‚v{Š}|ƒ||ztfrg]VTLd\\lldllkttsf]cƒ„„ƒ‚u|‚z‚|uŠ}ƒlld‚|utll‘ˆ}zll’ŒŒrg]j]\{{td\\|‚z‹„„ztltt{‹‹‹uzt‚v{„Š„lldlldƒ„„mtt…‹’ƒ}ƒ„„Š{u{Œ”•|„…mttllk\[[›”›‹’Š{{ƒŒ”•|‚zƒ„„£²”››|„…œ§²›¢›Œ”•„„Š£œ¥“““Œ”•‹„‹{{ƒª³·››”lks™š¤£››ƒ||{{t¨©´“““œ››Œ‹“„Š„”››¨©´‹’Ц§¨¦§¨„Š„uzt¦§¨“Œ”{u{›”›‹„„’ŒŒƒ||””‹ultddc“““slerfk{u{{tt‹‹‹œ¤¦{{ttzl]bZmttƒ„„Œ‹“lri{ttŒŒš{tt\[[mttŒ”•{{ƒƒ}ŠŒ”•tt{‹‹„fkk{{tƒ„„ƒ}Šztlœ››uzt’ŒŒ“Œ”{{ƒ‘Œ…‘Œ…ƒ‚u„„Šedkƒ}ƒ‹‹‹¨©´{u{lriultnƒ|„…{{ƒ”“›lri‚utš””“““‹‹‹{{ƒ››”¦§¨”“›ƒ„„‹’Š£œ¥fkk‹„„‚|u””‹{tttzl£›››”›{{t‚v{{u{tsllddcbVSKJlddf]c£››JHF*)(\[[[TTSKJ‹’Šdc\ƒ}ƒ[TT‹’Š{{tlddSKJtsliq]b[U{{tek]‹‹‹sle””‹lldlrittsultlld]bZ”š”ddc£››ttsf]cttsu{{ultUMR‚|ulddultŒ‹“}‡’|‚z{tt”“›yfl{||‚|utsltt{edkSKJlksuzt{{tJHFtll\[[‹’Škk]›¢›ƒ„„‹‹‹ƒ||lldœ››Šƒ}{zm{ttddcb[U{||z‚l‹’Š”“›{||b[Ud\\VTLf]c\[[b[UUMRj]\‚|u{tt‘Œ…‚|uredsreƒƒ|…„’„Š„{||„Š„uzt”š”kd\kd\ƒ„„™š¤Šƒ}{{tƒƒ|tsl{u{‘Œ…lritlllld{ttzllyleƒƒ|tslttsŒ”•lldekd‹‹„{{ƒŒ‹“yl„]cdultuztult{{ƒ{||tt{¦§¨…‹‹”››uzt…‹‹¦§¨Œ‹“¨©´œ¤¦lrimtt…‹’Œ‹“‹‹‹ƒ„„‹‹‹|„…“Œ””››|„…£œ¥¨©´¤¤‹„„œ¤¦“““¦§¨··Ä‹…’ŠŠ}{{ƒ{u{{{ƒƒƒ|…‹‹”››“““µ¶·Š}ƒ{ttƒ}ƒƒ||“Œ”ƒ}ƒ{ttƒ}ƒ„„Š“Œ”‹‹„‹‹‹“Œ”‹…’…‹‹|‚zœ¤¦mttddctzl{{ƒultf]cƒ||UUYlddœ¤¦|„……‹‹rfk‹…’mttf]cd\\edk£››”››{u{ƒ||ƒ||››”“““lld“Œ”’ŒŒµ¶·’ŒŒƒ„„™š¤‚|u£œ¥Œ‹“‹„„”››„„Šmtt„Š„f]c‹…’Œ‹“’ŒŒ’…‹„Š}„„Š‹‹„‹‹„²¬µ‹„„ttslri„„Šƒ||llkƒƒ|ttsred{{tŠ}ƒ{{tƒƒ|tll‹„„\[[{{tkd\‹„‹ek]fkk¢—FD;3+*Œ”•VTLb[Ulrisrelddƒ||[TTJHFd\\\[[ƒ||sre{zmƒƒ|ztl‚utztlztllld””‹…‹‹“Œ””››ult|„…uzt‹‹„{u{uztultƒ||tt{llk„Š„lektlld\\[TT\[[[[TŒ”•œ››„„ŠbVUztlb[Uttsf]cf]c{||Šƒ}[[TVZTŒ”•|‚z…‹‹tzl|‚z{tt{u{{zmrg]“Œ”ztfkd\dc\{{tultlrikk][TT„Š„’ŒŒttsƒƒ|„„Šdc\ek]\[[mwiWUzlltsl’ŒŒlldldd|„…Œ”•lri””‹|„…tsl‹’Š‚utŠ}|‹„‹£››srekk]kd\ekd‚v{bVZdc\ƒ}ƒtygb[Uƒ||redlldlekult|‚ztts{{t{{tƒ}ƒ„„Š”“›{{ƒ{{ƒ]cd{{ƒ”“›tt{{||™š¤|‚z{{ƒ›¢›Œ”•tt{‹…’£œ¥…‹‹{{ƒª³·…‹š‹‹„‹‹„”››Œ‹“Š}|“Œ”¨©´…‹‹™š¤‹„‹š””‹‹‹{||‹’ŠedkUUY{{ƒ¦§¨tt{š””ultŒ”•‹‹‹¦§¨£œ¥¤¤uzt’ŒŒult£œ¥‹…’’ŒŒ{||{{tldd„Š}{{tred’…‹ztl”››”š”…‹‹š””tsltts{tt{u{ƒ}Štslu{{ƒ„„‹’Šlksƒ„„mttƒ}Š]cdtts‚ut{{ƒƒ„„|‚z”“›£››rfk‹‹‹’…‹œ››‚|u’ŒŒ“““¤¤™š¤„„Š‹’Š™š¤tt{‹„‹“““{u{„„ŠŒ”•lks‹…’Œ‹“£››”š”ƒ„„‹‹„Œ‹“’ŒŒ£œ¥ttstllulttts’…‹f]cz‚llri{u{‹„„œ››‹‹„‚uttts’ŒŒ|„…]cd‹‹‹{u{{{tllk””‹SKJ*)(|‚zd\\\UZ[[TJHFƒ„„ultddc|‚zsle‚ut‹’Š|‚z””‹“““‚v{ultlldzll|‚z“““kd\ƒ„„™š¤‹‹‹œ››Œ”•{{t‚v{ƒ}ƒ…„’kk]f]czll¦§¨ddcnƒult…‹’›¢›ult“Œ”£œ¥”š”tt{kd\{{ƒf]cult\[b{||\[[„Š„llk“““œ¤¦tt{dkV]bZ{u{|‚zslesleztl‘Œ…ekdlri{||[TT{zmsle‚wlƒ}ƒŠ}|”“›{||“Œ”‚wlƒ||dc\Š~‹‚wlŠŠ}ƒ‚nŠŠ}kk]›¢›tslƒ„„lri‰ƒv…‹’|‚ztsl‘ˆ}Šƒ}ztlcbV|‚zd\\‚utultŠ}ƒedk{{ttlltslb[Utlltllƒ||mtt{{tuztkk]lld{{tlks{{ƒ‹‹‹ƒ}Š…‹‹{{ƒ{{ƒtt{ƒ„„ƒ||Œ‹“™š¤™š¤„„ŠŒ”•‹‹‹‹‹‹¨©´™š¤Œ”•…‹’¨©´¨©´¦§¨›¢›…‹štll‹‹„™š¤£œ¥¦§¨£œ¥¦§¨Œ”•ƒ„„{{tš”””“›{{ƒ«²«mttƒƒ|¨©´{{ƒƒ}ƒ™š¤”š”ztl{u{‹„„£œ¥¦§¨›”›µ¶·£››Šƒ}‹„„„„Šttstsl{ttƒ||…„’ƒ„„|‚z‹„„{||Œ‹“ztlult„„Š‹‹‹nv‚{||lri‹„‹„„Š[[T{||{{ƒŒŒšf]c„Š„[[Tƒ„„{{t²¬µlritsl‹‹‹tt{”“›‚|uš””‹‹„“Œ”ƒ}Š›¢›””‹…‹‹™š¤„„Š”“›‹‹‹|‚z“““™š¤{{ƒ“Œ”ƒ||{||{||sle{u{{u{j]\j]\¨©´Œ‹“œ››‚v{{{t””‹‹„‹”“›¤¤Šƒ}’ŒŒ“Œ”tllƒƒ|uztuzt‹„‹„Š„{||””‹D;9*)(f]cVTLlriu{{sre{u{ztlVTLttsddc[TTuztlri‹’Štzl‹„‹£œ¥uzt””‹lriult|‚z{tt¦§¨“Œ”ƒ„„”š”{{t’ŒŒ”››{||d\\llklriƒƒ|tts‚v{{tt‹…’Œ”•‹‹„ƒ||›”›ultultŠƒ}„Š„uzt”“›JHF[[T‚utlritlldc\”“›tt{]bZkd\tsl{u{red‹„„slelddtslŠƒ}sle\[[{{t‹’ŠbVU{{tztfŒ‹“‘…„rfkldd‹‹„sreŠ~‹r]g{||ƒƒ|{u{lri›¢›ƒ„„|„…lek[TTb[Utsl[[Tsle‘…„dc\tllrg]|‚z‚|u{tt{u{kd\{zm[TTƒƒ|ƒƒ|‹„„’ŒŒztltt{uztƒ„„lri“Œ”ƒ„„ƒ}ƒtt{‹„‹}‡’“““…‹’Œ”•{{ƒ…„’|„…”“›|„…edkƒ„„Œ—£œ¤¦{{ƒ{{ƒ„„Š|„……‹’‹‹‹œ¤¦“““…‹’‹’Д𔦧¨¨©´ƒ}Š£œ¥·¶Ñœ¤¦Œ”•„„Š”››ƒ}ƒtzl„„Š{{ƒlks{u{Œ”•Š}ƒ¦§¨‹‹‹tts„Š„{u{llk‹„‹‚v{µ¶·¦§¨{u{tll{u{tllƒƒ|{ttultllkttsu{{‹’Ц§¨””‹¨©´|„…{u{lks†~‘edk›”›„Š„“““„„Š„„Šlks{{ƒlksb[Uyle’ŒŒ””‹“““››”ƒƒ|››”¦§¨“““{tt’ŒŒ‚ut„Š„Œ‹“ƒ|||‚z“““‹‹‹ª³·…‹‹ƒ„„tt{|„…”“›‹„‹™š¤tll‹„„tts{{ttsl‹„„‹’Š‹„„“““Œ”•œ››š…Žƒ‚u’ŒŒŠƒ}ƒ}ƒ|„…ƒƒ|’ŒŒ{tt’ŒŒƒ||ttsƒ„„{||{tttslfkk””‹MRK*)(leksre]bZ{tt„Š„lddkd\d\\UTSUMR{{tuztmttdc\{zm‚v‚tll“““ldd|„…SKJu{{|„…|„…‚|uª³·Œ”•ƒ‚u‹‹„™š¤‹„‹Œ‹“ƒ„„¦§¨kk]\[blksŒ”•edkldd…‹’bVU„„Š””‹{tt‹‹„{zm{{ƒ{u{{u{tllƒƒ|tzl””‹|„…””‹[[TbVUlri“Œ”£››FD;ttsredkd\b[Ud\\{zmVTL›¢›ƒƒ|[TTllkƒ||{||b[U{ttŠ}|sle’ŒŒƒ||kd\lldƒ‚n{{tlld‹‹„{||Œ‹“|„…“““ƒ}ƒlriƒƒ|‹„‹’ŒŒttsb[U‹’Šek]ztlrg]‹„„ƒ‚uztf[TTtts‹‹„‚v‚zllkd\Œ”•llkuztddc‚|u{tttt{tsl™š¤œ››“““™š¤™š¤…‹š|„…Œ”•ŒŒšttsfkkƒ}ƒ{u{{{ƒ›”›{{ƒ}‡’Œ”•|„…|„……‹’}‡’mtt|„…¨©´tts··Ä™š¤…‹’›¢›‹„„‹‹‹‹„‹“““œ››¨©´ttsrfk£œ¥£››‹„„“Œ”“Œ””𔋋„‹‹„{u{zll{||‹’Š‚wlœ¤¦|‚zƒ„„uztlkslri|‚zttsf]clekekd„Š„|‚zŒ”•™š¤|„…lkslriultlksdc\tsl|„…‹‹„Š}ƒUUY{{ƒƒ}Š›”›š””kd\””‹›”›œ››‹„‹‹„„¦§¨“Œ”sle””‹ult{{t{{ƒƒ||‹‹„””‹‹‹‹{u{{{ƒ™š¤„„Š{||Œ”•“Œ”f]crfkŠ}|lriztl‹„„‹„‹›¢›‹‹„tt{Š~‹ƒƒ|ddcŠŠ}””‹ƒ||{u{ttsŒ”•‹„‹”𔋄„ultddcƒ„„{ttultsre\[[ƒ||JHF*)(llklldkd\lldƒ‚u‹„‹ddcd\\UTS{u{ddcttszllddc{zmtll{||tts‚|u„Š„„Š„”š”œ¤¦‹’Šƒ}ƒlkssretsl’ŒŒlri“Œ”j]\j]\¤¤”š”{||lekƒ}ŠŠŠ}{||[[Tf]c“Œ”|‚zzllkd\ttstslƒ„„‹‹‹lri’ŒŒ>EC|‚zŒ”•{u{uztztlŠ}ƒ’ŒŒ{{t{{tsle‹„„bVZu{{ldd{{tlld|‚zlriVTL£œ¥VTLultkd\ƒ||j]\ƒ||]cd‚v{VTLdc\dc\ƒ„„tzl{ttuzt’ŒŒ…‹’‹„‹yle{{tllk‚utƒ||ŠŠ}llktsl‹‹‹tllztl“Œ”{{tek]sleƒƒ|‚utƒ}ƒldd‹„„‹’Šƒƒ|‹‹‹lldƒ}ƒ“““‹„‹{||“Œ”mtt{{ƒ{{ƒlks…‹’|„…tt{”“›{||„„Š{{ƒ™š¤Œ”•ŒŒš|„…}‡’}‡’|‚z…‹’Œ”•tts™š¤“““œ¤¦Œ”•”››lksnv‚mtt“““|‚z{{ƒ™š¤ƒ}ƒƒƒ|ƒ}ƒ‹‹‹mttztl’ŒŒult“Œ”Œ”•{u{ƒƒ|¨©´“““ƒ||{{t“Œ”ƒ||llkddcttsƒƒ|Œ”•’ŒŒ‚v{lks{u{{{tƒ„„Œ”•{u{{{ƒ…‹’ultlksUMR™š¤”››‹’Š|„…lri|‚z]bZUMRd\\b[U‹‹‹llk‹„„”š”|‚z{zm‹„„›”›ƒ}ƒldd’ŒŒŠ}|ƒ„„{tt£œ¥›¢›sre›”›“Œ”¦§¨‚v{Œ—£‹‹„“““ƒ||llkd\\{ttsreƒƒ|›”›œ››“““‹„„ƒ}ƒ{{ƒkd\lddƒ„„›¢›ƒ||›”›“Œ”‰|vŠƒ}œ››ƒƒ|ddc\[[d\\[TT\UZ[[Tƒ}ƒ¤¤74,74,lddVTLb[U‹‹„uztdc\ddc{u{u{{dc\d\\tsl]bZddcredlritllsleƒƒ|ekd™š¤ƒƒ|lekª³·”“›lek„„в²¬ultu{{b[U¦§¨tlllri‹‹„{{ƒtt{Œ”•‹‹„SKJUTS{u{{tt””‹’ŒŒtsllldtt{yl„ttsztltllƒƒ|kk]\[[ddc„Š}¦§¨ƒ}ŠultttsŠƒ}|‚zj]\‚|uztlu{{tllƒƒ|ttsƒ„„d\\fkk{tt“Œ”ult{||Œ‹“ƒ„„ƒƒ|“Œ”{zm|„…lksdc\Š}|Œ”•ztf{u{“Œ”“Œ”¦§¨tts‚utult[TTek]ƒ||ztl{ttkd\ztlƒ„„”š”››”{tt{zm‚|uultldduztŒ”•{{ƒƒƒ|{{t‹„‹uztllk‹‹‹…„’ultf]c|„…nv‚fkk{||Œ—£ŒŒš{{ƒ£œ¥“Œ”œ¤¦u{{Œ‹“Œ”•…‹‹|„…|„…|„…ƒ}Š”››tts„„Й𤋄‹ƒ||{{ƒŒ—£mtt””‹„Š„™š¤”››™š¤dc\{{ƒƒƒ|{tt¤¤“““„„е¶·ult¨©´œ››£œ¥zlltllllk”“›ttsu{{‹‹‹”“›”››ekd”“›ƒ}ƒtzlƒ}ƒlldtts…‹‹f]crfkŒ‹“\UZd\\\UZ‹…’|‚ztsl‹’Š‹„„uzt]cd|„…lks[[Tš””{u{‹„„„Š„¦§¨µ¶·”“›‹„„ƒƒ|uzt²²¬{tttts{||{tt‹‹„Šƒ}¦§¨Œ‹“”››‹„„Œ”•”››„„Š›”›{u{bVUƒƒ|”š”‰ƒv{||™š¤“““‚|u”“›ult¦§¨ŠŠ}„Š„|‚z…‹‹ult”“›{||ƒ}ƒkd\‚|uƒ„„|„…Œ”•lrif]c|„…tt{²««JHF3+*bVZllkj]\tll]cdlld]cdult{{tUTS“““[[TlriVTL‚|u„„Šlksd\\j]\ttsœ¤¦‹‹„›¢›™š¤lddldd”››‹‹‹ldd…‹‹‚ut””‹“Œ”››”d\\uztttsedk‘Œ…lekƒ„„“Œ”{u{ƒƒ|‚v{‹’Š|„…{{tslellkVZTlri|‚zz‚lddc™š¤ttstll|„…š””u{{‘Œ…sreb[U{ttŠ}ƒsled\\tts„Š„{ttldd\[b››”ldd{zmtt{„vŒ™š¤tzl‹„‹f]cdc\lri‚|ukk]{yfd\\llkf]c{{tŠƒ}‹’Štlltll{u{‹‹„…‹‹‘Œ…””‹‚utj]\zll|„…‹’Šsle{{t””‹›”›‚v{œ››{{ƒƒ„„‹„„tsl„Š„‹‹‹‹„„”š”{{ƒƒ„„“Œ”¨©´Œ”•Œ—£Œ‹“‹„‹”“›‹‹‹¨©´™š¤ª³·”“›ŒŒš|„…œ¤¦|„…Œ‹“|‚zŒ—£¦§¨…‹‹£œ¥™š¤ƒ||œ››„„Šlks™š¤››”„Š„œ§²{||redƒ}Š‹„‹ƒ„„‹‹‹{tt”››‹‹‹ultŒ‹“··Äƒƒ|ldd‹„„Œ‹“tt{sleuzt‹„‹ƒƒ|fkkƒ}ƒ…‹‹ƒ}ƒlld{||{{ƒ‹’Š…‹‹ƒ„„{u{MSSf]cUTS”“›f]cmtt{{ƒƒƒ|™š¤Œ”•‹‹‹u{{edkedktslƒ||ƒ}ƒ“Œ”””‹ŠŠ}‚wl“““›”›{||”𔋄„‹‹„„Š„ultƒ}ƒbVU[[Tƒ}ƒtts]bZŒ‹“ƒ„„Š}|{||“Œ”‚v{{tt¦§¨«²«‹’Štsl¨©´…‹‹“Œ”Œ”•Œ‹“{tt[[Ttsl‹‹‹„„ŠŠ}|sle‰ƒvƒ||ultuztŒ”•uztƒƒ|tllUUYddc\[[£››:97&&red{zmJHFVTLMRKƒ‚u\[[[TTVTLJHFVTLtslsle[TTllddc\””‹i\Vtsltts“““ƒ„„lriœ¤¦£››\[bddcƒ||ultœ››{ttƒ||“““ƒƒ|Š}ƒ™š¤{{ƒlksSKJedk{{ƒƒ}Šlld‹‹‹sleƒ„„]cd‹’ŠbVZUTSVTLdkVfkkFD;„Š„aWM]bZVTLSKJƒ||uzt‹„„lri’ŒŒldd’ŒŒ“Œ”lddƒ}ƒtts{ttddctllƒ||redf]cŠ}ƒzlld\\tzlƒ„„{ttuztdkVVTLŠŠ}JHFredf]cult{||tll“Œ”{u{’…‹lekƒ„„{tt{||‚|u‹„„tllƒ||ldd|‚zŠƒ}tts‚ut{ttf]c‚|u‹’Š››”{|||‚zŠƒ}ƒƒ||„…‚v{™š¤…„’‹…’…„’}‡’lks{u{ŒŒš™š¤™š¤|„…Œ‹“›²¦§¨…„’tt{œ¤¦}‡’ª³·…‹’‹„‹{||œ¤¦›²›²œ¤¦›¢›¨©´Œ”•Œ”•£››«²«…‹‹‹‹‹‹…š{{ƒ‚v{‹‹‹ult«²«œ¤¦™š¤“Œ”ƒƒ|¨©´£œ¥rfk”“›£œ¥„„Šƒ}Š„„Š…‹’‚|u{||{{ƒƒ}ƒ{tt{{ƒ››”£œ¥›¢›œ¤¦”››¨©´|„…|‚zd\\“““{{ƒ]bZƒ}ƒlldƒ}ƒœ¤¦ƒƒ|{{ƒJHFult”𔋋‹tt{…„’‹„‹””‹tzl{||{tt¦§¨”š”’…‹ƒƒ|„„ŠŒ”•“Œ”|„…lldldd|„…›”›ƒ||Œ”•|‚z„„Š‹„‹™š¤š””sreƒƒ|{yff]c‹’ŠŒ”•|„…ƒ}ƒ{{ƒ‹„„lriVTLek]ƒ}ƒ‹„‹llkcbVldd[[Ttlledk\[buztztl[TTUTSedk””‹:97&&\[[SKJVTLz‚lVZTek]FD;ultd\\|‚z‹‹‹lldsre’ŒŒsle…‹‹kd\jcV‹’Šƒƒ|llk‹’Šlld\[[„Š}uztƒ„„„Š„“Œ””𔋅’‹…’ª³·£››{tttsl{||›”›tllf]ctlllldŒ”•Œ‹“‚ut”š””››\[[ultSKJ{{ƒ{zm[[TVZTlddJHFu{{lddVTLtlllldd\\tsltsl‚v{‹’Šztllrillkttsj]\lriUTSb[UlddŠƒ}lddƒ}ƒultzllf]ckd\lritzluzt››”‚wllddttsƒƒ|‚utreddc\‚uttts{{ƒ“““Œ”•‹’Šƒ||Šƒ}‚wl{{t{{tddctlllriŠŠ}redddc{{tztltsluzt|„…‹„‹”š”u{{„Š„ƒ}ЄЄ’ŒŒ…„’{{ƒ{{ƒ‹…’™š¤u{{ŒŒš{{ƒ”››…‹’Œ—£{{ƒ{{ƒŒ”•…‹’“Œ”Œ”•¨©´™š¤…‹‹Œ”•™š¤£››‹‹‹™š¤edkœ¤¦›¢›¦§¨™š¤”››‹„„›”›”››œ›››¢›¦§¨‰‘~ŒŒš£œ¥µ¶·¨©´‹„„¦§¨¦§¨™š¤‹…’„Š„|„…ƒ||“Œ”tt{Œ‹“‘Œ…“Œ”Œ”•‹‹„‹…’”››lrimttŒ”•‹’Šekd{u{rfklks\[buzt’ŒŒ“Œ”u{{Œ”•…‹‹f]c[TT„Š}“Œ”ult”“›œ¤¦‹’Š‹’Š‘…„{|||‚ztts“Œ”ult‹’Š“Œ”ƒ}ƒ‹„‹|‚zb[Utts£œ¥‹„„{||{tt‹‹‹ƒ}ƒƒ}ƒ”“›‚|u|‚z„Š„Œ”•‹„‹«²«“Œ”ldd\[[‚|u]bZkk]sleŠ}ƒldd{||„Š„{{t{tt››”‹‹‹|„…|‚ztlllek{||JHF£››JHF3+*edkek]lldb[Udc\lld\UZVTLVTL[TTlddlld{{ttlllddƒƒ|Šƒ}yle¤¤‹‹‹{||{{t„„Š|„…{u{‹’Š”“›ƒ„„‹„‹›¢›”››{u{{{ƒšŒ›¢›fkkr]Z{{ƒs_q‹…’rfklek™š¤lld”››‹‹„uzt‚v{ƒ‚uldd‹’Šƒƒ|MRK]bZVZ[llklld‚utekd‹„„ddcztl]bZUMRztfdc\Šƒ}JHF\[[f]cƒƒ|Š}ƒ{||j]\tllkd\d\\…‹’ƒ||{ttttslks„„Šƒƒ|œ¤¦Šƒ}£œ¥Š}|lldllkultlddlld””‹{tt‚v{››”‹‹„“““rg]’…‹’ŒŒ{tt{ttlldf]c{{ttllllklddredƒƒ|{{t›¢›¤¤œ¤¦“““”š”””‹™š¤u{{…‹‹Œ”•…‹’„„Š…‹’™š¤œ¤¦Œ—£mtt™š¤‹…’”“›{{ƒlks›²œ§²œ§²œ¤¦”››£²{{ƒ{||lri‹‹„sre…‹’u{{…‹‹|„…|‚z|‚zŒ”•””‹‹…’ultœ¤¦“““ª³·”››ŒŒštts“Œ”™š¤„Š}„„Šƒ}ƒ‹„‹“Œ”Š}ƒu{{ztl{{t”“›ttsj]\š””uzt‚|ubVZmttŒ”•VZ[|‚z…‹‹tts{{ƒ‚|uf]c‹…’”“›””‹ŒŒštllekdUTSlks†~‘[[T{{tlks{{t¦§¨””‹¦§¨’ŒŒtllƒƒ|£››‘…„ldd„Š„tt{Œ”•‹‹‹£²‹„‹ƒ}ƒ›”›ult…‹‹“Œ”edk›”›tt{{{t‚|uƒƒ|„Š„|„…‹„„{||lldlksultb[Ulld{{t[[Trfkult’…‹ƒƒ|lld””‹”š”„Š„‹‹‹ekd‹‹„[TTtslddc²²¬FD;*)(ultddcSKJD;9JHFcbVf]cSKJ[TTldd\[[tslŒ”•[[Trfk„Š„Š}|lld{zm‹’Šuzt{{tlri„Š„ƒ„„’ŒŒŒ‹“„Š„{tt’ŒŒ\[[‹„„{{ƒf]c«²«„Š„…‹‹{||Š}ƒƒ„„‹‹‹ultŠ}ƒbVZ„„ŠbVU…‹’š””””‹{{t›¢›Ž¡›ult]bZultldd[[Tlddlld“““[TT‚|ub[Ulld‚|u{ttek]ddcddcVTLSKJFD;kk]ult{{tddcuztVTLtllbVZ{||[TTtslldd¦§¨lritllŠ}|ƒ„„{{tƒ||bVUttsredredzll‹‹‹{{t|‚z{{tztl|„…|‚z‚utœ¤¦kd\…‹‹ztl‹„‹edk|‚z…‹‹lld‹„„‹„‹‹„„”››Œ‹“uzt|„…{{ƒŒ”•}‡’¨©´œ¤¦™š¤›²œ¤¦™š¤ƒ}Š‹„‹„†™}|’{{ƒ{{ƒŒ—£œ¤¦|„……‹šf]ctt{ultŒ”•…‹’‹‹„‹’Š„„Š{||¨©´«²«‹’Š…‹‹mttŠ~‹…„’{{ƒŠƒ}””‹œ¤¦|„…Œ‹““Œ”‹„„Œ”•„Š}ƒ||„Š„…‹’{tt‹’Š{{ƒŒ‹“d\\{||f]c‚v{r]g{{ƒ‚wl{|||‚z]cd|‚z|‚z„Š„{{ƒ|‚z{||f]c™š¤tslƒƒ||„…lld‹‹„†~‘‹’Š£œ¥„Š„ƒ||{{ƒlld…‹‹‹„‹‹‹„ƒ||“““Šƒ}ƒ||Œ‹“tsl‹‹‹™š¤ldd„„Š’ŒŒrfk“Œ”ƒ}ƒldd…‹‹{u{|„…›”›ƒ„„tt{ƒ||«²«lriƒ}Š™š¤Œ”•{||{||Œ‹“d\\kd\tsl\UZlddultu{{uzt|‚z’…‹’…‹‹’Šƒ„„‹’ŠŠ}|f]cVZT\UZ¦§¨UMRlddVTLFD;FD;‹‹„[[T‚ut[TTfkkƒ}ƒ[TT[[T‹‹„lek[[Tƒ„„ztfVTLcbVdc\‹‹„tslfkk“““|‚zmttek]’…‹ƒ||tzl“““{{tttsœ››¤¤’…‹tt{ddc‹‹„ƒ}ƒš””’…‹‹„„Œ”•¦§¨VTL\UZ””‹”š”|„…‹‹‹”š”ª³·lriedkdc\|‚zztlttstllekd‹„„SKJ‹‹„ttskk]ƒƒ|uztlldSKJ‚|utsltlld\\f]ckjVƒƒ|SKJb[Uztluztulttsl‘Œ…‹’Š|‚zsle{tt‹‹‹‹‹„Š}ƒlks[[Tkd\red‹„„ƒƒ|kk]u{{‘Œ…lddllk{{ƒsledc\f]cƒ„„š””Š}ƒult”››‹’Štllztlƒ||llk{||{{ƒƒ„„ƒ}Šmtt™š¤}|’{{ƒŒŒš™š¤‹…’nv‚˜Ž£}‡’ult{{ƒ™š¤›²}|’{{ƒ}‡’Œ”•|„…Œ‹“Œ‹“™š¤|„…ŒŒš¦§¨”š”…‹‹Œ—£”š”|„…tzl|„…Œ”•|‚zultƒ||‹’Š””‹“Œ”„Š„¦§¨lks{tt…‹‹„Š„{||›”›Œ‹““Œ”o€w|„…{ttsle|„…‹’Š‹‹‹ult¦§¨‹’Šredekd…‹‹œ¤¦|‚z]cd|„…mtttslmttedkŒ‹“‹‹„uztcbV\[[››”œ§²|„…™š¤‹„„ƒ||f]cŠ}|œ››œ¤¦š””‚v{š””[TT{{ƒ””‹”››Œ”•tllŠƒ}{{ƒd\\ƒ}ƒŠƒ}{{t{||ddcddc…‹’“Œ”rfktsluztddcult¦§¨llk‹‹‹”š””“›‹‹‹dc\››”‚|uUMRƒ}ƒtsl{||tsld\\ttsddcu{{{u{{ttlekVZTddc²««D;9*)(dc\VTLFD;D;9ek]kk]bVUult{{tlksd\\lrilriVTLlks‚|uj]\cbVlldVZTuztMRKƒ„„u{{{ttŒ”•lriœ¤¦u{{ƒ‚u{tt“““‹‹‹mtt²²¬ttsƒƒ|mttf]c™š¤tsl‹„„ult„Š„Œ”•ŠŠ}”“›ƒƒ|ulttts]bZ„„Šƒ„„{ttultztl{{tztl]bZ“Œ”{zmlri\UZ„Š}{u{Š}|d\\uztƒ}Šƒƒ|Š}|sreœ››‘ˆ}f]c‚v‚{{tlddSKJ‹„„ddc‚v‚ek]VTL[TTdc\llkddc\[bƒ„„ƒ||”š”tsllldredUTSlldkd\ƒ„„redVTL{||[[TFD;llklddtsltsl{{ƒf]cfkktsl‹„‹ƒ||llkultlrifkk„„Šmtt|„…‹’Š|„…{{ƒ…„’Œ”•”“›œ§²¡¡mk…}|’Œ—£{{ƒlks{tt‹…š|„…¨©´Œ”•…‹‹”“›™š¤Œ—£¨©´‹„‹Œ”•‹„‹Œ‹“¦§¨|‚z‹‹‹lri|„…Œ‹“{u{}‡’’ŒŒ{{tƒƒ||‚z™š¤]cdlks…‹‹Šƒ}œ››{tt™š¤Œ‹“ŒŒš…‹‹lek››”…„’ª³·‹’Ф¤{{ƒ{u{ƒ„„›¢›mtt™š¤{||VTL|‚z]bZtsl„„Šult‹’Šdc\‹‹„”š”™š¤™š¤|„…‹…’”š”’ŒŒ‚v‚{{ƒult¦§¨‹’Šœ››{u{ƒ||tsllek¦§¨Šƒ}ƒ„„“Œ”{u{{ttƒ}ƒ„„Š{u{sle“Œ”‚v{f]c{{tƒ}ƒƒ„„ƒ||lriztledk{{ƒ|„…››”™š¤“““¦§¨sle‘Œ…{u{d\\{||‹‹„mtttslultdc\|‚z{{ƒkd\ldd\[[tt{\[[¦§¨SKJ&&j]\Šƒ}f]cVTLJHF]bZzlltll]bZllklld››”tzlsleuztultVTLtll]bZ[[Tu{{tzl”š”llk|‚z‹’Š|‚zŒ”•{{td\\²²¬{||Œ”•ekd‹’Šlld{{ƒf]cedkš””lldbVU“Œ”lddult[[Ttt{SKJ{ttlddu{{lriUTSdc\rfkƒƒ|tsl{{ttslzll|‚zƒ||{ttttslldddcMRKf]clkstsl‘Œ…ekdƒƒ|‘…„{{ƒldddc\{u{FD;Q?@ultƒ}Šdc\ƒƒ||‚z{{t†~‘„Š„mttlldultŠƒ}|‚z{zmf]cuztŠŠ}{||UTSylerfk{ttdc\sle{||VTLtzlbVUlddllkdc\lddƒ||ztfllklddƒ}ƒu{{mtttt{uzt…‹’nv‚ŒŒšedklkstt{¨©´œ¤¦Œ”•›²œ§²“Œ”¨©´lks}‡’}‡’|„…u{{¦§¨„„Š£œ¥™š¤™š¤£œ¥œ››|„…|„…œ››œ››œ¤¦›¢›{{ƒu{{ultyl„ttsµ¶·‹„‹Œ”•\[[lkstsl…‹‹llk‹‹‹lri…‹‹{{ƒ””‹{||›”›„Š„„„Š{{ƒ¦§¨“Œ”£œ¥„Š„ldd|‚zlksƒ}ƒmttlrirfk\UZd\\\[b‹’Š{{ƒ‹‹„››”tslmttlkslksƒ„„{tt{tt|„…¦§¨’ŒŒ’ŒŒœ¤¦Šƒ}Œ‹“””‹ƒ||™š¤£››””‹{||’…‹{{ƒultult{{ƒ|‚z‹„„œ››|‚z™š¤{{t{{ƒƒ||””‹|‚zƒ||{||œ››‹’Šœ¤¦‹’Šƒ}Š„„Š’ŒŒ{{tddc{tt{{ƒkd\lriƒƒ|lld{ttƒ„„ttsƒ„„ztlfkk]cdllk””‹bVU-1+ldd{{tF=CsletllSKJ{zmzllldd\UZslelldddcd\\ƒ„„‹„„r]ZŠƒ}„Š}|„…JHF{zmfkku{{‹’Š„Š}lriuztƒ}ƒƒƒ|“““”š”tt{kd\{||VZTlksllk“““‹’Š›¢›[TTƒƒ|uzt„Š„Šƒ}›”›lddtlllriUUYVZTVZTUTS‹‹„‹‹‹{{tslettskd\ƒ„„VTLkd\tsl‹’Š…‹‹[[T\UZ‹’Љ|vkd\ƒƒ|{{tsleƒ||SKJ””‹f]csre{tt{{ƒultƒƒ|rg]‹’Š„Š}lddtslbVUlri‹„„‚v{d\\UTSslekk]ƒ||”𔋋‹{{tŠ}|{ttttsek]{||ztlttslddjV[\[[\UZ{ttult‹‹‹ƒƒ|{{ƒ{||fkk“““£²„„Š…‹’{{ƒnv‚{||u{{{{ƒ„†™Œ—£œ¤¦}‡’Œ—£{{ƒ{{ƒyl„{{ƒ…‹’Œ”•™š¤™š¤ttsŠ~‹œ§²ŒŒšª³·™š¤£››‹’Štzl›¢›lldª³·ª³·lrimtt™š¤tll¦§¨ztlŒ‹“Œ”•ƒ}ƒ‹‹‹zllƒƒ|‹‹‹“Œ”™š¤{{ƒ””‹”“›‹‹‹bVZ|„…‹‹„‹„„{tt{{ƒ[[Ttll…‹’|‚zŒŒš„Š„[[Tƒ„„„„Š‹‹„ttsŒ”•|‚z]cduzt{{t{{ƒUMR|„…d\\{zmƒ}ƒ‹„„…‹‹ƒƒ|‹„„ƒ„„sleldd‹„„”“››”›””‹¦§¨ƒ}ƒ“Œ”¦§¨{u{{u{…‹‹Œ”•””‹ƒ}ƒ„Š„|‚z‹‹‹”“›‹„„ddc{||„Š„{{ƒult‹’Š’ŒŒ|‚z“““kd\“““››”„„Šš””redŠ}|tzl“““sle[[T|‚z]bZb[U[TT\[[UTSf]c¦§¨FD;*)(f]c‚|uSKJ]bZlddJHFddclldddc\[[“~ˆtzlekd{||ult“Œ”“Œ”tzlu{{Œ‹“llklldtt{ekd›¢›lkszlltt{uztƒ‚u‹’Š}|’””‹‹’ŠtsltllVTL{tt‹’Šztl…‹‹uztVTLlri‹‹„ƒƒ|‹‹‹‹„‹{tt]bZJHFb[U]cd]bZmtt{tt{zm‹‹‹[[Tlld{u{sreult{||]bZttslld[TTcbVVTLb[U””‹[TT{zmi\VbVZtllƒ}ƒsletlledkUMRek]kk]””‹VTLlddUTS“Œ”‹„‹‚utultkd\{||“Œ”cbV{tt|‚z‹‹‹””‹tllbVZuzttsl{||ƒƒ|lld‰ƒvtsllksbVZ{||ulttll{{ƒultmttfkk„Š„™š¤‹‹‹“““Œ—£{{ƒlksŽ¡›mtt‹…š…„’Œ”•…‹šŒ—£|„…„„Š…„’…‹š~’“ekdŒ”•ƒ}Š›”›ŒŒš…„’£››‹„‹™š¤›¢›“““›”›”š”ƒ||””‹ª³·ª³·‹‹‹{{ƒ‹’Š‹‹‹‘…„™š¤Œ”•{{ƒš””¦§¨“Œ”››”ldd‹‹‹£œ¥ŒŒš{{ƒ™š¤Šƒ}|‚zŒ”•ztlƒ„„{u{{||’…‹{{ƒŒ”•›”›‹’Š‚utf]c™š¤“Œ”ƒ„„lriUUYmttUTSdc\]cdtts{{ƒekdlek‹„‹lekŒ”•››”ttstzl‚wlŠ~‹›”›‹‹‹”“›lksœ§²|„…£œ¥{{ƒtsl{{ƒ™š¤‹‹„¦§¨Š~‹‹‹„u{{‹‹„ƒ}ƒƒ}ƒ‹‹‹ƒƒ|‚|u{||tt{fkk„Š„Š}|ultlri{{t‚|uƒ}ƒƒ„„ƒ}ƒƒƒ|ƒƒ|””‹‘Œ…ztlƒ„„tslVTL{ttultfkkUTS¦§¨MRK*)({tti\Vkd\FD;bVUPF=dc\UMRdc\sle„Š}tsl{u{ttstll›¢›jcV‚|utygƒ„„ƒƒ|u{{d\\mttekd„Š„ƒ}ƒŠƒ}|„…ƒ}Šuzt|„…|‚z””‹b[UddctllŠ}ƒŠŠ}\[[‹…’{zmj]\„Š„’ŒŒ‹„„[TT’ŒŒtlltts…‹‹Œ”•u{{lrillk›”›tllztld\\‚v{|„…ztlVTLttstzl{{ƒ{||„„Š[[Tb[U{{tŠŠ}\[[VTLJHFlddiq]d\\VTLlld]bZSKJJHFƒƒ|ƒƒ|ƒ||f]c„Š}ƒ}ƒddcd\\tll‚|u”“›“““lld£››‹’Š{u{’ŒŒŒ‹“ƒƒ|mtttsl{||Œ”•mttƒƒ|mwtts‹„‹[TTtll|‚z„Š„ƒƒ|ddcMSSlek™š¤Œ‹“lks|„…}‡’…„’|„…{{ƒ‹‹‹Œ”•Œ”•™š¤ƒ„„…‹’¨©´{{ƒŒ—£nv‚Œ”•…‹‹“““£²”››ŒŒš””‹{u{{{ƒ¦§¨ƒ}ƒ‹„„‹‹‹|‚zœ¤¦œ¤¦»ÂÇ‹„‹lks\[b›”›{tt„„ŠŒ”•Œ”•]bZ‹„‹‹„„””‹ult’ŒŒ„†™{{tœ¤¦””‹Œ”•„Š}tts„„Šultœ¤¦‹„„{||¦§¨”š”ª³·„„Šƒ„„£œ¥{{ƒ{{tŒ‹“JHF\[[LKRMRKVTL\[bJHFu{{u{{red£œ¥Š~‹|‚z“Œ”tts¦§¨›”›¨©´²««”“›””‹”“›Œ”•Œ”•‰v|ƒƒ|ª³·ttstt{…‹‹‹…’ultœ››“““ƒ}ƒ“““™š¤ƒ||ekd…‹‹ddcedk‹„‹ldd{zmmttultdc\ƒƒ|llk‹„‹‹„‹‹„„{{ƒ››”‹„„sle‹’Šdc\ƒ„„{tt]bZ]bZVZT£››b[U*)(f]ckk]Š}|FD;UMR{tt[[TVTLSKJVTLj]\VTL{u{ƒ||tlllldkk]ztl‹‹„‹‹‹”š”tslmtt\UZ„Š„Œ”•{u{‹‹‹™š¤{{ƒ«²«›¢›{||‹‹„{{tƒ„„‚utekdbVZUMR™š¤‹‹„{u{{||‚|u‹‹„lek‘Œ…””‹{{ƒuzt{{tekdJHFUMRldd|‚z‰|vf]c‹‹„{||ztl{ttVZ[‰‘~”››{{ttll{tt[[Tkd\ƒ}ƒFD;VZTd\\lddb[UtlllldlddJHFultekdƒ‚u””‹ƒ„„dc\tslƒ||dc\“Œ”¦§¨{{tkk]{ttƒƒ|‘Œ…››”ultredtt{|‚ztsl‹‹„Œ‹“š””{{tzllLKRmttƒ}ƒbVU{{ƒlri“““uztmtt{{ƒtt{}|’{||Œ”•{{ƒ|„……‹šŒ—£™š¤{{ƒ|„……‹’œ§²·¶Ñ¨©´”“›{{ƒœ¤¦œ¤¦|„…}‡’“““¦§¨œ¤¦Œ‹“¦§¨‹‹‹¨©´£›››¢›Œ”•™š¤””‹‹‹‹|‚zfkkf]clksŒ—£zll‹„‹‚v‚¬¶Ãš””lldredƒƒ|ƒ||„„Šœ››Œ‹“Œ”•Œ”•œ››Œ”•¦§¨lld|„…{tt”››‹’Š{u{„„ЄЄ{||uzt|‚z{tttt{JHF„„І~‘ƒ}ŠŒ”•…‹’zlluztlriVZTlrillkŠ}|llk„„Š{u{›”›‚|uztlƒ}ƒultƒƒ|™š¤¦§¨¦§¨‘Œ…”››™š¤”“›ƒ}Šf]clldƒ}ƒ{{ƒ‹„„‹‹‹„Š„ldd|„…llktts…‹’ekd£œ¥‚v‚tll‹„„ƒ||{ttleksletll‹„„‹„„ƒ||JHF{||zllkd\JHFUTSlek‚utfkk\[[ddc‘ˆ}JHFSKJbVZkk]b[UPF=3+*FD;[TTD;9JHFlddtsldc\{ttdc\‚ut{u{{||ƒƒ|¤¤ƒƒ|ttslddddcult[TT|„…™š¤“Œ”¬¶Ã¨©´œ¤¦Œ”•‰‘~iq]„Š„tllb[UddcUUYf]c{tt|‚zddc{u{dc\‚v{tslultƒ„„rg]Œ”•|‚zekd[TTlks‘…„{||lek”“›ƒ||b[Uš””›”›[[TŒ”•UTS{ttrfksresle”››j]\ttsUUYuzttllVTLleksre‚ut‚wl\[bƒƒ|“““ddcultlld‹‹„ƒ||\[[{{ƒ£œ¥””‹‹‹„‹„‹{{tš””{{tlksredultœ››Œ”•£››{||tllmttrg]ttstt{{u{ult{u{””‹…‹‹{{ƒ…‹‹…‹‹Œ—£Œ”•u{{{{ƒŒ”•Œ—£Œ‹“…‹šŒŒšŒ”•…‹šŒ”•™š¤Œ—£»ÂÇ”››™š¤œ¤¦…‹‹Œ”•‹„‹™š¤¦§¨š””™š¤¦§¨™š¤›¢››”›‹„‹tzlŒ”•”›››¢›Œ”•u{{yl„MSSuzt{{t”“›“““Œ”•„Š„ƒ}ƒƒ}ƒ‹’Š„Š}”“›™š¤tts™š¤”“››¢›|„…‹„‹|‚z\[b›”›u{{{{t“Œ”Œ—£|„…[TT„„Šmtt\[[{{ƒUTSultŒ”•“Œ”™š¤|‚zlddllk{{ƒŒ”•llk‚|u‚v{Œ”•ttstt{ultztl‚v{“Œ”ƒ„„›”›”››ª³·¦§¨‹…’›¢›ƒ„„|„…\UZƒ}Šrfk’ŒŒ‹„„ldd’ŒŒŒ”•„Š„‹„‹ƒ||”››llkmttƒ}ƒ„„Šmttu{{ultttsŒŒš‰|v{{ƒ‹„‹zllSKJd\\lriu{{ek]„Š„|‚zsleztl[TTVZTllk¦§¨:97*)(u{{SKJJHFSKJ3+*SKJD;9F=Cf]crfkVTLƒƒ|{tt‹„‹“~ˆddcsrejcVlldlld”››edk[TTƒ„„mttƒ„„‹u…‹„‹lriƒ„„ek]lri”𔫲«ƒƒ|ƒ„„ztl‹„„{ttƒ}ƒƒƒ|u{{[TTd\\VTL{{tult››”‹„„Œ‹“u{{u{{ttsfkkUMRb[Ulld{tt\UZŠŠ}VTL’ŒŒ‚v{„Š„‹‹„ultƒ||redlks”𔋒Ši\V[[T‹’Štyg‹’Šlddult‚|uƒ‚uƒ„„f]c|‚ztlltslVZ[„Š„tzl[[T{u{ult‹„‹“““‚|u¦§¨ƒƒ|tts””‹£œ¥£œ¥”››””‹”››{{t{u{VTLlri“Œ”{u{“Œ”…‹‹›”›ddc’ŒŒultkd\u{{Œ”•™š¤ŒŒš‹‹‹…‹š…‹šmtt{{ƒ|„…„„Š|„…ŒŒš{{ƒŒ”•™š¤œ§²…‹‹‹‹‹|„…¨©´™š¤™š¤Œ‹“{{tŠ}ƒ†~‘“Œ”‹‹‹|„…’ŒŒª³·š””œ¤¦œ¤¦‹‹‹‹’Š”››\[[tt{{||ƒ}Šƒƒ|Œ”•‹’ŠŒ”•Œ”•œ››™š¤‹‹‹‹„‹ddcƒ}Š›¢›}‡’™š¤Œ”•ƒ}ƒ„Š„‹’Š„„ŠUTSVTLb[UŒ”•lriuzttt{lri[TTultultult{{ƒ™š¤Œ”•tlllrilks|‚zlks“Œ”‚utf]c{{ƒultŠŠ}tts{||{ttŠ~‹ƒ||‚v{£››tzllkssreUTSddcnƒVZ[lksŒ‹“ƒ||lddƒ„„ƒ||ƒƒ|uztƒ„„›”›{{ƒ{u{Œ”•ƒ„„…„’”››ƒ„„ƒ}ƒ{||œ››‹’Š‹‹„‹‹‹sle[TT\[b]bZsletslVTLekdztl‹u…[TTu{{llk²««UMR*)(\[[rg]bVUVTLVTLkd\ttsƒƒ|rfkŠ~‹ƒ„„tzlƒƒ|ƒ||[TTtt{‹‹‹kd\VTL{{ƒ„Š„tsl‚|uƒ„„f]c[[T{{ƒ”“›ttsmttek]{{tuztlriVTLlek‹„„ttssle‹„‹„„Šttsuztkk]r]Z“Œ”¦§¨Š}|kd\f]cJHFddcfkkf]cUMR{u{lldult[TT””‹[TTrfk{{td\\‹‹‹ƒƒ|™‹†ult¨©´”š”lks‚|u“““|„…tlllldkd\{u{|‚z‚ut‹‹„‹…štslb[Uddctsluzt”š”‚|uƒ}Š‚v‚{{ƒš””tllœ››‹„„””‹tts“Œ”’ŒŒª³·››”{||‹„„tts‚ut‹’Šzllƒ}Š{{ƒldd{u{‹„‹‹‹‹ƒ}Šllk‚|u|„…Œ—£œ¤¦Œ”•™š¤}‡’{{ƒ{{ƒ}‡’|„…mtt…„’Œ”•}‡’™š¤ƒ„„”“›„„Š|„…Œ”•Œ”•Œ”•™š¤ddcŒ”•ttsŒ‹“ult¦§¨œ››‹…’‹‹‹|‚z””‹ƒƒ|”“›Œ”•£œ¥™š¤lkslks”››Œ”•‹’ŠŒ”•{{ƒ‹‹‹‹u…uzttll‹‹‹…„’Œ”•mtt\[b„„Šmttmtttt{ultlks‹’Š[TTuztVTLddcƒ„„fkk{tt†~‘™š¤„„Šlddyl„{{ƒttslri{{ƒ‹‹‹|„…œ¤¦ztlš””ult|‚zŠ}|£œ¥”š”{{t{u{{u{‹‹„Œ”•tts{||lriƒ„„tt{ddcu{{\UZ‹„‹tsl{ttŠŠ}ultƒ}ƒ¨©´ƒ}ƒ{ttŒ”•{{ƒtt{…‹‹llk{||ddcf]crfkƒ||’ŒŒ››”Š}|tslbVUf]c‚|u\UZ{zmƒƒ|tts[[Ttsld\\|„…{||¤¤MRK:97{ttdc\D;9SKJVTLVTLf]c\UZbVZ‚v{uzt{||slekd\ekdlkstzlŠƒ}uztlrifkkƒ„„ƒ||ttsƒ||\[[ekdtll\[[\[[mtt‰ƒv{ttVTLdc\rfklddtll‹„„{u{|„…ttsƒƒ|UTS{{t‚v{¤¤tllbVUVTL\[bttsult\[bllkŠ}ƒ{{ttllddc“““ƒƒ|UTS|‚zVTL|‚zultrfkult¦§¨„Š}¦§¨i\VŒ”•|„…{{ttt{‚utlriztllriu{{lddœ¤¦lj|„…‹„‹„Š„{||{ttƒ„„‹„‹{u{‹‹‹Šƒ}„Š}lddŠƒ}{{t‹…’ƒ}ƒƒ„„‚|uttskd\tts‹„‹Œ”•‹‹‹ƒ}ƒtts|‚z‹‹‹lks…‹‹{{ƒ|‚zƒƒ|edklri|„…„Š„…‹’|„……„’ŒŒš}‡’ŒŒš|„…Œ—£|„…”››œ¤¦”“›¬¶Ã¦§¨…‹š¦§¨œ§²œ§²›”›µ¶·¦§¨Œ”•œ¤¦“Œ”™š¤ƒ}Š£œ¥’ŒŒ›¢›”š”œ››“““lri“““ultttsd\\{||„„Š‹’Šœ¤¦¤¤f]c’ŒŒ|„…tt{¨©´ƒ}ƒœ¤¦Œ”•u{{Œ”•…‹’œ¤¦lks|„…mttlld[TTekd|„…”››ƒ||{{ƒ“““‹’Š“““{{tekd£›››”›„„Š‹‹„…‹šek]ddckd\ult›”›{u{ttsldd›”›¦§¨ƒƒ|“Œ”tlllek|‚zuzt|„…sre‹„‹{u{[TTtslultult{{tƒ|||‚z’ŒŒ“Œ”Œ”•ƒ}ƒ‹‹‹tt{lksmtt{{ƒ{{ƒ„„Šllk{{ƒtts‹‹„œ››””‹tsl{{tŠ}ƒrfkVTLtllVTL]bZ{||ƒ||tllf]c[[Tddcƒ„„MSS*)(tslb[U[[TaWMJHFSKJuztVTL[TTultddcdc\{zmlld„„ŠŒ”•cbVUTScbVŠ}|\UZ{ttultš””œ¤¦„Š}u{{tll|„…tts„Š„ztl{{tdc\tt{{tt{{tekd““““Œ”Œ‹“\[[srekd\ƒƒ|‰|v’ŒŒšŒ{u{r]g|‚zddc„„Šlks‹„‹‹„„lldyl„d\\tts„Š„tlltll[[T[[TŠ}|{ttlri|‚zVTLrfk‘Œ…tllŒ‹“sreldd{ttUTSkd\…‹‹UTS]bZ›¢›’ŒŒu{{‹„‹uzttlllld{{ƒsle\[[ƒƒ|„Š„‹’Šuzt””‹”𔋋‹f]c|„…ttsddclekœ››”››|„…‹„„{u{ttsttskd\edklldŒ‹“‹‹‹{||{{ƒ\[b|„……‹‹…‹’{{ƒtt{Œ—£Œ”•œ¤¦›²{{ƒŒ”•{{ƒŒ—£Œ—£™š¤lksœ§²…‹‹£œ¥›¢›Œ”•œ››ƒ„„Œ”•„Š„”“›Œ”•œ››ƒ}ƒ…‹‹Œ”•…‹‹¦§¨œ››™š¤“Œ”\UZ]cdldd|‚zŒ‹“ƒƒ|”š”tt{‹…’¦§¨ƒ||™š¤‹’Š›²¦§¨lriedk\UZ‹‹‹ttsttsmtt]bZlriƒƒ|u{{\[[›”›“Œ”|‚zkd\lddƒ‚u”š”ƒ||SKJtt{Œ”•u{{‹„‹“Œ”ult“““£œ¥ulttt{Œ”•ƒƒ|‹„„“““¦§¨¦§¨¤¤š””{|||„…ult]bZƒ}ƒUUY]cdldd{{ƒœ››{{t|‚z‹‹‹””‹‹…’”››„„Šlek…‹‹{{ƒ|„…lks|‚zuztulttt{ttsƒ}ƒ‚utƒ||dc\‚|urfk‚v{{||{tt|‚z]bZUTSsle[TTllkUTStt{£››LKRD;9lldkd\[TTVTLPF=VTLVTLf]cultf]cddc{{tdc\{u{kd\‹’Šlrilldtslkd\VZTred“Œ”{u{«²«uztu{{ƒƒ|lddŒ”•ldd{tt…‹‹]bZMSSlddkd\‹‹„ƒƒ|{u{…‹’lks|‚zdc\Šƒ}lddŠƒ}‹„‹Šƒ}lriUUY|‚z{{ƒ:97lksult|‚zultƒ„„››”{{td\\mtt{{tllk“Œ”rfk[[Tdc\Š}|‹„„Š}|‹‹‹{||ƒ„„‹‹„ƒ‚u{{tsle|„…|„…lek›¢›”š”””‹œ¤¦¦§¨ƒ||Œ”•ƒ}ƒtll{{t|‚z‚|u‹‹‹{{tlld|‚zuztlddŒ‹“„Š}‹‹„‹„„¨©´’ŒŒŒ”•‹‹„lks|„…]bZUTS{u{{||ttsƒ„„{||mtt\[b|„……‹’…‹‹|„……‹’Œ—£Œ—£™š¤¬¶Ã™š¤|„…~’“„†™|„…{u{{{ƒŒ—£”››¨©´|„…™š¤Œ”•™š¤¨©´|„…™š¤u{{‹…’’ŒŒekd|„…œ¤¦‹‹‹tllmttd\\lksŒ”•‹‹„£²rfk„Š„Œ”•ƒ„„‹„„“Œ”ƒ„„œ¤¦ƒ}ƒ…‹‹Œ”•{{ƒrfku{{llkekdldd‹‹‹¦§¨””‹ztltt{ekd„„Š{{tŠ}|tll|‚z|‚zmttrfkƒƒ||„…fkk{||ddcultult‹‹‹™š¤rfk™š¤{{ƒŠ}ƒƒ„„”š”””‹“Œ”„Š„Œ”•œ››‹’ŠŒ‹“ƒ„„”“›{{ƒƒ}Š[[T…‹’‹„„{u{ƒ‚u{||””‹edktzlult{tt|„…{{ƒtts{{ƒu{{|„…‹’Š“Œ”lldŠ}|{{tddc‚|uJHFJHFlddttsult‹‹„{{tlritsl[TTllkdc\ddc””‹FD;:97UTS]bZd\\VTLSKJrg]lriyle{{tekdlrilldkk]]bZ‹„„edktsl””‹uzt{||edkŠ}ƒ{u{ƒƒ|{tttslŒ”•ƒƒ|lld…‹‹‹‹‹{ttƒƒ|mtt{{t{||[[T››”tts‹‹‹\[[Œ”•|‚z£››‹’Š“““š”””››{{ƒœ››\[[”“›ekdUTSf]cUTS”š”|„…‚v‚[[Tlks{ttlks[[Tƒ}ŠSKJr]gSKJUMRkd\ŠŠ}b[Uultekdllk”š”aWMŠƒ}ƒ||›¢›…‹‹{{ƒŠƒ}¨©´œ¤¦¦§¨‹’Šœ››“Œ”{u{zll‹„„uztƒ}ƒ|‚zldd‹‹„tsl“““lddlekƒ||‹‹‹{ttuztƒ||uztƒ„„llktt{|‚z{{ƒ”“›ƒ„„…‹’{{t‹„‹mtt|„…œ§²”››œ§²Œ”•lks|„…œ§²™š¤··Äª³·…„’{{ƒŒ”•…‹’{{ƒ{{ƒ‰Š¡tts“Œ”{{ƒŠ~‹…‹’¦§¨Œ”•··Ä‹‹„\[[”“›tllf]cekd|„…››”|„…™š¤‹…’ƒ}Šu{{tt{{u{{{ƒtts{u{lritts“Œ”tt{mtt{{ƒmtt‹‹„™š¤lekrfk“““u{{\[[ƒƒ|ŒŒšztl‹’Šdc\lldkd\ƒƒ|lldu{{‹‹„d\\ƒ||“Œ”ult{{ƒŒ”•tllF=CŠ}ƒ‹…’’…‹‘}zŠ~‹ƒ}ƒ{tt‹‹‹‘Œ…ƒƒ|Šƒ}œ››„Š„{{ƒllk|‚zŒ‹“uzt{u{‹„‹œ¤¦‹‹„|„……‹‹‹„‹mtt…‹‹|„…”“›”››ƒ}Šllk{{ƒŒ‹“œ¤¦”››™š¤…‹’…‹‹ƒƒ|”››’ŒŒ“““rg]VTLFD;[TTUTSekdlddztlllkllkdc\[[TUMRztlUTS””‹:97:97sreb[UlddSKJsreD;9lddSKJldd{||lld‹‹„srezllf]cŒ”•sle‚utƒ‚uultlld{tt‹„„””‹ƒ||]bZlriƒ||tsl|„…Œ”•’ŒŒ‚ut‹’Š[[T[[T[[Ttsltsl™š¤Œ”•‹’Šœ››{{tlddƒ}ƒttsttsŠ~‹uzt|„…‹‹„MSS\[[[TT‹„‹]bZ[TTi\Vƒƒ|{u{{{tƒ„„ƒ||{ttsrej]\leklddcbV‹’Šrg]{{t{tttllƒ„„tyg‚|uttslldƒ„„mttdc\UTS‹‹‹›¢›²²¬‘Œ…£œ¥œ¤¦‹„‹‹’Š‹’Š””‹“““f]c‚ut|‚zƒ„„{tt‚|u„„Š“““{||{||ddcƒ„„ultedk{{ƒ|‚zlksŒŒš‹‹‹œ››|„…}‡’œ¤¦|„…™š¤|„…|„…Œ”•…„’œ§²^fs…„’·¶Ñ…‹’Œ‹“œ§²”“›„Š„ƒ„„{{ƒ{{ƒŒ”•”››{{ƒŒ”•›¢›™š¤£››¨©´ƒƒ|ultŠ}ƒ“Œ”™š¤tsllks…‹’”š”‹’ŠŒŒš„„Šu{{mttmttlksŒ”•Œ‹“ddc{||ƒ}ƒmttlks…‹’™š¤Œ”•‹‹‹lrimttŠ}|lritsl‹‹„lriƒƒ|‹„‹”“›Œ”•{{t›”›“““ƒ„„ƒ„„sre¦§¨{{tred„Š„lld]bZ\[bUMR{{ƒ{{ƒred‚v{“Œ”™š¤Šƒ}{u{‘Œ…ƒ||‹„‹uzt‹‹‹™š¤tsl|„…]bZŒ‹“ƒ||…‹‹tll¨©´‹’Š™š¤tt{‹’Šmtt‚v{uztƒ„„ƒ}ƒ›¢›lksƒ„„mttuztekd…‹‹llk‹‹„tlltzlek][[Tlldsletts„Š„‚v{ƒƒ|ddcekdtslztlultdc\,55ƒ||FD;74,{{tlrif]c{zmlriFD;\[[VTL{||‹„‹|‚zsle|‚zttsjV[tslrg]tslslej]\sleƒ||lekllk{{ttzl“““llddc\|„…{||“““ek]”››b[U{ttlri‰ƒvlri\[[¦§¨Œ”•ekd…‹‹uzt‚|u‹‹„tt{{{ƒƒ„„lri|„…kd\UTS\UZdc\[TTlldbVU{{t\[[„„ŠlldVZTultyle‹„„ƒ}ƒ„„ŠcbVkk]lri{zm‹„„zll[TTsreztlf]c]bZ|„…UTSlri„Š„]bZ‹„„‹‹„ztl{||«²«“Œ”““““““‹’Štslƒ||‹‹„d\\‹‹‹{ttmtt{u{””‹’…‹tt{‹‹‹œ››‹„‹ƒ}Š]cdtts{{ƒlksƒ||ƒ}ƒ{tt™š¤‰Š¡…‹‹Œ”•}‡’|„…}‡’Œ—£{{ƒ|„…Œ”•}‡’¨©´™š¤Œ—£›²‹‹‹‹„‹ƒ}Š…‹š­À¶œ¤¦™š¤Œ‹“™š¤µ¶·{{ƒ›”›|‚zŒŒš“Œ”ult”š”mtttts“““uzt„Š„}‡’edk|‚zmttUTS\[b]bZŒ”•dc\tsl{{ƒnv‚]cdŒ—£“““…‹’‹„„d\\\[[|‚z“““‹‹„„„Š{u{tllj]\”“›|„…£››ldddc\|„…mtt|‚zƒ}ƒ‚v{£œ¥lks™š¤Š}ƒ‚v‚{{ƒ‚wltt{‹‹‹yl„“Œ”‚v{ŠŠ}‚utŠƒ}ƒ„„œ¤¦‹’ЄЄ™š¤Œ”•™š¤””‹llktll…„’ulttt{‹‹„…‹’“~ˆtzlŠƒ}™š¤„Š„|„…ƒ}Šnv‚œ§²„Š„“Œ”ddcmttlksd\\lrilddd\\ekd{tt{{t‹„„ddc{||Š}ƒ{tttzltts{zmj]\\UZUTSUTS””‹JHF74,lridkVSKJVTLJHFbVZVTLbVUtllŒ‹“u{{d\\srelksztlƒ„„kk]tslztlddclri{ttƒ||””‹‹‹‹”š”Œ‹“ztlfkk{||tzlƒ}ƒ]bZmtt{u{llk|‚z‹’ŠFD;MSSlriœ››lri]bZ{{ƒtll‹„‹”››lkslddllkƒ„„ddctll\[bultuzt\[bƒ}ƒtslŠƒ}‹’Šlks]bZ„„ŠUMRƒ„„ƒ||ƒ„„b[Uƒ„„ult£››rg]LKR{ttkk]UTSlddVTL[TTUMR‹„‹lriœ››œ››ƒ‚u{u{”“›lld‹„‹Œ”•„Š„‹’Š‘Œ…{||{tt‹„„ª³·š””™š¤ƒƒ|‘Œ…‹„„kd\tzl…‹‹ƒ„„…„’\[bek]tt{“Œ”Œ‹“{{ƒu{{™š¤|„…ŒŒšmttŒ—£…‹’¬¶Ã™š¤Œ—£Œ—£Œ”•…‹‹™š¤ƒ}ŠŒ—£”“›ª³·”››ƒ}ƒ™š¤™š¤™š¤Œ‹“Œ‹“ª³·“Œ”“Œ”{{ƒ|‚z£œ¥‹…’ulttt{tt{Œ”•ƒ„„‹„„UTSultlksu{{}‡’|„…lksekd]bZ]bZtslƒ}ƒ””‹|„…mk…Œ”•”“›”“›\[b\[[kk]|‚zultztl‘…„tlllri|‚zddcultttsek]]cdMRK‹‹‹ƒ}ŠUMR‚v{œ¤¦Œ”•‹‹‹Š~‹{{ƒ‹„‹ult””‹£²‚v{llk‹„„£œ¥š””œ››„„Ц§¨‹‹‹¦§¨Œ”•Œ”•Œ”•|‚zmttmttf]c|„…ek]\[bultllktts£œ¥‹‹‹|„…{{ƒ…‹‹}‡’ƒ„„Œ”•{{ƒlksVZTJHF{ttultUTSu{{tlllld{{tedkŒ‹“ƒ||sletsl{||kk]SKJSKJaWM|„…š””ekd*)(kd\kk]bVUVTL:97D;9\UZbVU‹„„llk]bZtsl„Š}f]ckd\mttcbV‹„‹ldd\[[‹’Šztlztllldmtt’ŒŒŒ”•‹‹„cbVƒƒ|dc\„„Šb[Ulld‹‹„‹„„|„…]bZ]cdekdJHFu{{MRKVZ[llkkd\edk{||{{ƒŒ”•|„…„Š„lddldd{{ƒlks|‚zllk‘Œ…tslztl‚utUMRjcVƒ„„j]\lddbVZ{|||‚z‹‹„‹‹‹››”‚|uf]crfkrg]\[[ldddc\{||mtt”“›|‚z{{t‹„„[TT\[[\[btslttsƒƒ|ƒ||{||”š”lekƒƒ|‹„„™š¤red¦§¨‹„„lld£››mttu{{uzt{u{{{ƒlkstslƒ}Š{{ƒ”››u{{{{ƒfkkmttu{{|„…mttmtt}‡’†~‘œ§²Œ—£›²{||“Œ”†~‘†~‘‹’Š”››µ¶·{u{|„…nv‚{u{|„…“““{|||„…¨©´š””u{{²¬µ£œ¥›”›|„…Œ”•ttsult{u{mtt}|’mttfkkŒ”•|„…mtt|‚z|„…Œ”•“““ult”››œ¤¦mtt…‹‹„„ŠŒŒšleklldllk{||VTLŠƒ}UTS[TTlldVTL{||‚utJHFtllJHFtslkd\¦§¨lks¦§¨›¢›tslƒ‚uƒ}ŠJHFleksleŒ”•™š¤ƒ}ŠŒŒš“Œ”’…‹‹„‹‘Œ…“““”𔋄‹Œ”•¨©´ttsuztŒ”•lri\[blksu{{tsl\[bƒ}ƒf]cƒ||Š~‹tt{{||˜Ž£|„…”“›tts{tt{||mtt|„…uztlldf]clri‹’Šlld{{tztl]cd\[[redVTL[[T|‚zrg]FD;[[Tdc\SKJ””‹:97*)(UTSVTLaWMVTLSKJJHFf]ckk]‹„‹‹„‹llkSKJlrikd\zllrfkd\\lrilriVTLƒ}Šyle‚|ubVUmtt{zmŒ”•{{tkd\tts{{t{ttƒƒ||‚zƒ||ldd‹’Š‹‹‹„Š„lrilksekdmtttzlultƒ||{{ƒlri‹„‹mtt›”›…‹’ƒ„„‹‹‹ƒ}ƒtt{|‚z„Š„redrg]››”lrifkk{{t„„Šlddsle‚|utsllriŒ”•Š}|ƒ„„Š}|D;9ƒ||…‹‹lldulttt{[[TŒ‹“lddttslrid\\b[UJHFd\\lldtt{ƒ„„“““ƒ„„ƒ„„”››{tt”“›uztkd\{{ƒf]ctsl”“›{{t{u{{ttult{{ƒmttƒ||{{ƒtt{]bZ]cd{{ƒmttmttŒ”•mtt{{ƒnv‚…‹’…„’œ§²™š¤™š¤™š¤mtt{{ƒŒ—£|„…”››¨©´lksƒ„„{{ƒ”“›“Œ”¨©´„„Š”“›œ¤¦ƒ}ƒlrif]c‹„‹{u{[TT¨©´edklekuzt…‹‹lks]bZlrimttmttmtt~’“‹’ŠŒ”•Œ‹“u{{„„Šmtt„„ŠŒŒš{{ƒ{u{„„Šƒƒ||‚z‹’Štllkk]lddb[Uƒ||”š”{{tultlekdc\MRKllkrfkf]c’ŒŒ‹’Š“““‹‹‹œ››’ŒŒf]cUMRtll{{ƒ”“›™š¤¦§¨„Š„ƒ||‹„„Œ”•‹„„‹‹„‘…„¨©´”“›ultuztŒ”•ƒ||””‹ƒ}ƒmtt‹’ŠlksVTL\[[u{{tslultttsult{{ƒ{{ƒedkƒ}ƒmttVZ[„„Štts‹‹‹™š¤{{ƒuzt\[[tlltsl\[btts[TTztlVZTkd\VTLb[UyleUTS[TTµ¶·JHF>ECSKJVTLJHF74,[TTrfkŠƒ}b[Uƒ}ƒf]cllklld{||UMR\[[VZTi\V]bZlriekdVTL””‹|‚ztll|‚z‹’Šfkk‹‹„tzl‹‹„‹’Ц§¨””‹fkk[[Trg]ekd{{ƒ™š¤tll…‹’‹’Ц§¨ƒ„„ƒ||{u{g\rUTSedkkd\u{{Œ”•Œ”•‹‹„mttŒ‹“‹’ŠmttSKJult|‚z{u{£››ddcd\\{u{lddsleldd|‚z]cdred|„…cbVd\\f]c”“›Œ”•š””„Š„|‚zmttd\\\[[ƒ„„‚utttsu{{uztuzt“Œ”‹‹„‹’Ц§¨”š”Œ”•””‹Œ‹“ƒ„„Œ‹“ttsult|‚z{{t„„Šƒ||ƒƒ|lriƒ}ƒmtt|‚z“Œ”lkskd\{{ƒ‹„‹¨©´Œ”•Œ—£¬¶Ã…‹’|„…{{ƒœ§²Œ—£lks…„’„Š„™š¤¦§¨Œ”•|„…™š¤”“›ƒ}Š‹…’{{ƒœ§²™š¤”“›‹’Š{{ƒuztš””“““™š¤”“›£››tsl|„…Œ‹“llktt{„„Š|‚z[[Tmttu{{|„…Œ—£|„…Œ”•|„…‹‹„”“›…‹’Œ”•u{{lek|„…lkslrimttu{{lld‹„‹|‚z¨©´„Š}lrib[Uekdr]g\[[VTLf]cŠƒ}{||f]cmttult“““ƒƒ|{u{f]c™š¤Œ‹“ƒ||tyg{tt’…‹„Š}”š”lekrfk“Œ”’ŒŒœ››¦§¨{ttƒ}ƒ„„Š|‚zŒ”•„Š„¨©´“““|‚z„Š„”››{||llkllk{u{”“›tts{{ƒ{{ƒlksŒ”•ttstllŒ”•}‡’uzt{{ƒ’ŒŒ…‹‹\[[d\\ek]d\\edkllklddtsllri[[TVTLb[Uultlddu{{¦§¨UMR*)(aWMVTLd\\VTL[[TD;9[TTb[U{u{]bZ{{tttsztlSKJlld’ŒŒƒ||tsltsluztddc‚|u{zm‹‹‹ekdkd\ddc‹‹„\[[lldtts‹„„tygŒ”•b[UŠŠ}sle\[[|‚z”“›™š¤…‹‹¸Á¹lri››”Œ‹“|„…uzt]cdlri{{ƒ|‚z]bZf]c{{ƒlrimttŒ‹“b[Ud\\\[[ƒ||lldlld{{ƒlldtslsleekd|‚zldddc\tslj]\VTL‚v{u{{ƒ„„‘Œ……‹‹MRKVZTƒƒ|uztsreŠƒ}ƒ„„|‚z¦§¨‹’ŠŒ‹“‹„„¦§¨Œ”•ƒ„„|‚z””‹£œ¥{||ƒ||{{t‹„„tslƒƒ|œ››{{ƒ››”‹…’ultmttVZTtt{{{ƒ|„…™š¤ƒ}Š…‹‹}‡’™š¤Œ”•}‡’œ¤¦Œ—£‹…š}‡’†~‘|„…lri‹‹‹Œ—£¨©´‹‹‹œ§²|‚z“Œ”Œ”•ŒŒšƒ}Šƒ„„Œ‹“¤¤‹‹‹ª³·™š¤ultult|„…‹…’{{ƒ‹…’…‹‹‹„‹Œ”•lldu{{uzttsl}‡’|„…œ››™š¤œ¤¦nv‚Œ”•‹‹‹œ¤¦œ¤¦{{ƒ„„Šmtt{u{„Š„ttsekdƒ„„Šƒ}ldd„„Š“““””‹‹‹„ddckd\Œ”•uzt{{ƒSKJttsUMRdc\D;9{ttMRKsle{{ƒƒ}Š{{ƒtll{{tƒ}ƒ™š¤”š”lrid\\kd\ƒ„„{ttƒƒ|œ››…‹‹ƒ}Šƒ}ƒ‹„‹{{t“““¨©´™š¤{u{ª³·ƒ}Šƒƒ|u{{mttu{{tll…‹‹lks|„…ŒŒš{{ƒf]c{||{tt{{ƒ{{ƒlrilksƒ„„tsl{ttlld{{tmttultkd\rfk{{ƒ]bZkk]tllVTLUTS]bZ²²¬]bZ:97Šƒ}VTLtzli\VJHFi\VUMRVTL‹…’\[[\[[mttnƒ‰v|uzttll“Œ”Š}|bVU„Š„‹‹„¤¤ultlld]bZedk|„…sre{ttkd\bVUf]cŠƒ}œ¤¦”š”|‚z[TTtll‹„„œ¤¦‹’Š[[Tllkd\\ƒ||ƒ}ƒœ¤¦”š”u{{edk„Š„‹’ŠVTL\[b\[bVTLdc\{||ƒ||ztlttsred]bZek]cbV…‹’››”’ŒŒllk]cdedkd\\lld]bZkk]tslUTS[[Tedk{||lriddcu{{mttsrei\Vƒ„„„„ŠŒ‹“Œ‹“”››²²¬¦§¨{||uzt„„Š{||{{ƒ{{ƒ‹‹„‹’ŠŒ‹“UTSƒ||‹‹‹|„…|„…ttstt{tt{œ››…‹’ƒ}ƒtllŒ—£|„…u{{}‡’{{ƒ™š¤œ§²Œ—£Œ—£¨©´¬¶Ãœ§²…‹š‹„„mtt“Œ”Œ”•‹‹‹œ§²]cdœ¤¦‹…’|„…Š~‹‹‹‹{||™š¤„Š„™š¤µ¶·™š¤™š¤™š¤„„Šœ¤¦™š¤…‹š‹…’‹’Š”“›ŒŒšlriª³·]cdu{{]cd…‹š~’“|„…‹‹„„Š„u{{mttƒ}ƒ…„’mtt{u{“““cbV]cdf]cSKJtts‹’Š‹’Štllztlddcƒ„„ttsekdlrilksSKJ]cd|„…[TTlriddc[[T{u{lksyl„‹‹‹Œ”•Œ”•tts“““ƒ„„‹„„zll‹„‹“Œ”›¢›{||””‹|‚z™š¤¦§¨„Š„tslœ¤¦›¢›{{ƒ‹‹‹{{ƒ„Š„|„…‹„„ŒŒš{tt…‹‹}‡’“Œ”tt{ŒŒš‹‹‹›”›lri|„…]bZmtttt{tllƒ„„ddcuztbVU\[[…‹‹tsl|‚z‹‹‹srecbVyfdlddred[[T¦§¨JHF*)(kd\VTLek]VTLMRKD;9{{t[TTlddJHFVTL\[[tt{{u{{||zll‹‹„Šƒ}›”›”››ekd‹’Šƒƒ|“““””‹ttsƒ}ƒtsllekkd\VZT\[[{ttSKJ{{tzll’ŒŒ‚|u|‚ztsltlluzt{tt„Š}ƒ‚uƒ||Œ”•””‹Œ”•\[bcbVn…fkkbVZSKJz‚l„„Šttstllkd\Š}ƒVTL|‚zƒ„„lek[TTtsld\\]bZ‹’Ѝ©´ult¤¤”“›[TT„„ŠUMRultrfklri]bZUMR|„…lriVZT{tt‹‹‹‹‹‹{{ƒ|‚z™š¤›¢›‘Œ…Œ‹“|‚ztsl’ŒŒult…‹‹ƒ||[[Tfkkuztƒ}Štts„Š„‹„„ƒ„„{||Œ‹“”š”Œ‹“’ŒŒ‹‹‹…‹’{{ƒmtt{{ƒŒ‹“nv‚Œ”•…‹’…‹šœ§²|„…›²{{ƒ“““™š¤¦§¨u{{f]cŒ—£‹‹‹{u{”“›…‹‹£œ¥‹„„ƒ}Š‹„‹™š¤uzt™š¤edkŒ”•™š¤œ¤¦¦§¨…„’œ¤¦µ¶·Œ”•’ŒŒ…‹‹]cd|‚zVZ[mtt]cdœ§²‹’ŠŒ”•ddcuztŒ”•fkklksŒ”•Œ”•lksUTSSKJtsl‹’Š{{t]cd{{tuztŒ‹“’…‹|‚z’ŒŒŒ‹“Œ”•ttsƒ||fkktt{lrif]cttsƒ„„[TT[[TVTL{u{ttsmttœ¤¦Œ”•”š”tzl{ttƒ||‹„„Šƒ}”››„Š„‹‹‹Œ”•‹‹‹¦§¨“““‹’Š™š¤„Š„‹‹‹‹„‹‹„„™š¤Œ”•‹„‹{u{{u{{||u{{{{ƒlkslksttsf]c]cdlks|„…\[b|„…ttstsl{ttƒƒ|tll{||uztlld|‚z[[TVTLJHFlld[[T]bZult²²¬UTS*)(dc\[[TJHFaWMD;9D;9jV[FD;JHF\[[b[Uf]cult‹‹„d\\lekƒ}ƒtt{ultiq][[TŠŠ}z‚lŒ”•ƒƒ|ek]‹‹„u{{ƒ}ƒ‚uttzlƒƒ|Šƒ}rg]j]\Š}ƒ‘…„zlllddek]mtt{{t‹‹„ttslri{u{œ¤¦ƒƒ|tll{{ƒƒ||lldMRKSKJF=C„Š„{{trfk””‹r]Z’ŒŒtllbVU]bZekdsle{tttllƒ‚uekdtlltll››”…‹‹‚v{ult{u{\[[ultfkk>B9tll|„…‹’ŠcbVekd””‹u{{‹„„ƒ||{{ƒœ››ƒƒ|„Š„™š¤ttszlllddmtttslttstt{ƒ„„œ››››”{{t…‹‹tts|„…{tt™š¤mttlriuzt|„…\[b}‡’…‹’…„’…„’Œ”•Œ”•}‡’Œ—£…‹šœ¤¦™š¤{{ƒ¦§¨Œ—£…‹‹ƒ„„Œ”•ª³·‹‹‹™š¤Œ”•Œ‹““Œ”™š¤™š¤”››”››“Œ”™š¤›”›™š¤†~‘™š¤u{{lks“Œ”…‹‹‹’Škd\f]c|‚z|„…mttVZTnv‚|„……‹’llkƒ„„u{{…‹‹Œ”•ult…‹šƒ}ƒf]c¤¤{|||‚zllk|‚z{{t]bZsleƒ||ƒ„„””‹”“›dc\ƒ||\[[{tt\[b[TTŠ}ƒtzl|„…VTLek]JHF{u{”››Œ”•Œ”•¨©´{{ƒ¦§¨ƒ„„š””{ttœ››‹’Šuzt‹‹‹tslŠ}ƒŠ~‹tll|„…ztl|„…]bZ{||„„Š|„…‹’ŠŒ”•u{{‹„‹{{ƒŒ”•…‹’ŒŒš…„’“““{ttu{{mtt]cd…‹‹{{ƒƒ||‹’Šb[Uekd{ttfkkZbN|‚z\UZekdSKJVTLldd[[Tdc\VTL¦§¨:97*)(slejcVD;93+*JHF74,JHF[TTultƒ}ƒ‚|ulldttsŒ”•ult“Œ”ƒ||ult[[TttsUTS[[Tek]””‹„Š„„Š„Œ‹“„„Š“““š””ddc{{ƒ…‹‹|‚z‚|uult‹„‹‹„‹ultƒ„„”››ultlks“Œ”uzt\UZlritslek]{u{tsllri]cd?;C{tt[[T‹’Šsle{tt‚|ulriJHFddcdc\ddcd\\tllƒ‚uVTL[TTttsd\\ultttsb[Uult[TTUMR[TT‹’Šlri{||ttsekdfkk›¢›Š}|ƒ}ƒ““““““ƒ}ƒtll›¢›llk··Ä“““„„Š“Œ”mtt”š”uzt¦§¨‹‹‹ztl{|||‚zƒ‚uŒ”•{{ƒ‹„„…‹‹tslœ››™š¤mtt{{ƒ|„……‹’Œ—£™š¤ª³·Œ”•}‡’|„…œ§²ª³·¡¡ƒ}ƒƒ}ƒ‹…’™š¤„„Ь¶Ã£œ¥¦§¨ª³·œ¤¦œ§²›¢›™š¤Œ‹“œ§²|„…£œ¥‚v‚¦§¨™š¤™š¤lks…„’œ¤¦]cduztmttu{{{{ƒtts|„…Œ”•fkkmtt|„…Œ”•{{ƒ‹‹‹edk]bZlks}|’‹‹„ƒ}Šrfk{{t…‹’’ˆtsl‹’Š]bZ[[TUTSŠ~‹u{{‚|u„„Šekd[[Tdc\u{{VZ[lrilekuztuzttsllrilriultd\\|„…‹’Štt{”“›”››¦§¨Œ”•¦§¨mw””‹‹‹„tslVTL{{ƒ™š¤{||”››‹‹‹ƒ„„”“›ƒ}ƒtslllk„Š„“““”“›ƒ„„lriult™š¤{{ƒ‹„‹ƒ}ƒtt{ƒ„„lks]bZ{{ƒ{u{{||‹‹„f]cdc\SKJ„„Štslƒƒ|llk[TT[[TztlVTLsrett{d\\¤¤JHF*)(j]\cbVJHFSKJF=CF=C[[T[[TbVUƒ}ƒ{{tƒ||²««’ŒŒ{u{tlllekllktll{zmdc\kd\{{t{{tlri]bZ”“›‹‹‹™š¤ƒ„„“““‚wl””‹…‹’ƒ}ƒƒ||red|„…ƒ}Šsle‹’Š„„Š£œ¥…„’Œ”•œ¤¦”››SKJlektllŠ~‹‹’ŠŠƒ}\[bultleklritsld\\’ŒŒ{ttddc‚v{mttƒ„„“““tllb[U“Œ”d\\‹‹‹kd\b[UbVZdc\lddF=Cf]clekŒ”•mttf]cmttttsu{{…‹‹lri“Œ”Šƒ}ƒƒ|ƒ„„lldtsl…‹‹“Œ”„Š„Œ”•‹…š{u{²²¬fkkŒ‹“uzt››”ƒ„„‹’Š”š””š”f]cƒƒ|{ttlld”››„Š„…‹’{{ƒ|„…{{ƒ…‹šœ¤¦œ§²œ§²}‡’}‡’|„…Œ—£œ§²tt{™š¤{{t“““„Š„…‹‹¬¶Ãœ››‹‹„…„’£œ¥¨©´“Œ”lks„„Š…‹’lek£››™š¤Œ‹“Š~‹„„Šmttœ§²Œ”•“Œ”lddmttUTS”š”|„…mtt”“›|‚zœ¤¦Œ—£tt{{||…‹‹…‹‹{{ƒlks{{t‹…’tll‹‹‹“““¤¤kk]uztVZTddclekbVZtslkd\lksŒ”•VTL]bZtlluzt[TTtll‹’Š]bZekdu{{{{ƒ{{ƒ“““|‚zlri{{ƒ{u{lld››”{u{‚v{’ŒŒekd{{tzll„Š„ƒ||Š}|{{ƒœ››„Š„ttsŒ‹“}‡’f]cmttŒ”•f]clri{{ƒmtt]bZedk„†™ŒŒš‹…’mtt‹‹„tt{dc\]cdu{{tts‹’Š‹’Šllk{tt|‚zztl]cdlek[[T{{trg]VTL[[TSKJldd¦§¨\[[*)(sleJHFbVZJHFJHFVTLVTLkd\[TT’ŒŒ{{t„Š„ƒ||ttsrfk{{ƒ’…‹{{ttslllklri“““””‹llkttsu{{f]cŠŠ}ƒ}ƒ{{t””‹ek]lksfkkŠ}ƒƒ„„ttstzlƒ„„d\\uzt”“›]cdultttsœ››Œ”•d\\…‹‹UUYƒ|||‚zddcdc\UMRdc\mtt‹‹‹rg]lek““““Œ”lddlri{ttjcV¦§¨‹‹„[TTj]\ek][TT{ttƒ}Š|„…llk{tt‚v{ƒ}Š|‚ztt{\[[]cd\[[…‹’™š¤„„Šƒ||”“›{||Œ‹“{||tsl|‚ztt{{||ekd“Œ”ƒ}ƒœ››|‚z”››sle”“›“““ƒ„„„Š„›¢›|„…ekd]bZ|‚zƒ„„dc\…‹‹…‹š…‹’„†™™š¤œ¤¦™š¤Œ—£…‹šŒ—£Œ—£}|’|„…Œ”•{{ƒœ››{{ƒ{||‹‹‹{{ƒƒ„„œ››Œ”•Œ”•Œ”•™š¤œ§²œ¤¦|„…™š¤‹…š‹„„ultŒŒš··ÄŒ—£™š¤œ¤¦œ¤¦lks]cdlksmttlri\[b…‹šmttŒ”•mttƒ„„ult…‹‹œ§²{{t{{ƒ{{tƒ}ƒ‹„‹“Œ”tts{{t]bZ[[T|‚zuzt“Œ”“Œ”llk””‹f]c{{ƒ]bZek]tsl\[[JHFmttmtt”››|„…{||ddcztl[[T\[[’ŒŒ™š¤”“›Œ‹“¦§¨ƒ}ƒlld’ŒŒ„Š„¦§¨{{tlld‘…„›”›”››uztŠŠ}lkslld\[[tsl}‡’uzt|„…{{ƒlks{||VZ[{{ƒƒ||lekŒ‹“lddlri{{ƒ[[T{{ƒƒ„„tsl…‹‹{{t]bZƒƒ|{u{‹‹‹{zmedkddc[[Tdc\VTLztl\UZldd¦§¨LKR*)(ztf{{t{ttUMRVTLj]\|‚zrg]‚v{f]ckd\tts{u{fkk‚v{„„Štt{slekd\dc\ttsuzt””‹lks”š”{u{tt{’…‹‹‹‹‹„‹{||’ŒŒ”š”Œ”•{ttƒ„„\UZ‚|uf]ckk]{{t””‹{{ƒ\[buztœ¤¦”š”tslmttlkstsl‹’Š{||SKJ\[[[TT|„…[[Tdc\’ŒŒtllkd\lkskd\‚uttzl‚|u{zm¦§¨tsld\\š””kk]lld{{ƒultf]cƒ||ult]cdlkslks{||lek›¢›‘Œ……‹’ƒ}Šœ¤¦ƒ‚u··Ä‹‹‹¦§¨ekd‘…„{||ult£œ¥’ŒŒ””‹Œ”•‹‹‹””‹{{ƒƒ„„”››„„Š“Œ”|‚ztts‹‹‹™š¤{||{||Œ”•{tt„„Šlksœ¤¦}|’„„Š…‹’|„…Œ”•}|’…‹šŒ—£{{ƒ‹’ŠŒ”•™š¤ŒŒš|„…£œ¥{u{\[b“““·¶Ñ£œ¥¨©´Œ”•¦§¨ªÁř𤍩´{||‹…’¨©´œ¤¦œ§²Œ—£œ¤¦Œ”•u{{|„…mtt\[[tts}‡’|„…mtt]cdfkkddcŒ”•ƒ„„|„…‹‹„ultlri‚v‚{||d\\[TT”š”kd\kd\fkksre\UZJHFmtttts{{ƒ„„ŠVTLb[U‚utmtt\[b\[b|„…{||u{{ƒƒ|[[Tlldƒ}ƒ}‡’{{ƒŒ‹“”“›‹„‹‚|u{ttœ››{u{|„…‹‹„{tt’ŒŒœ››{ttmtt“Œ”ƒ‚u”š”ŒŒšnv‚mttmtttsl‚v‚Œ”•ultmtttt{…‹‹”“›‹„‹ƒ||uztu{{ultmttUUYult{{t{||œ››]bZsle\[[UTS[[Tllkdc\VTLVTLVTLd\\jV[SKJ¦§¨\[b74,red]bZlddekd[TTSKJ]bZSKJf]cb[Utslddcztl{{ƒrfk‚v‚ult‹’Šdc\kk]{{tkk]dc\ult„Š„{{t‚|ud\\ƒ}Š[TTtzllri[[Tekdtsl¦§¨tll„„Štts|‚z|‚zŒ”•fkkƒ}ƒu{{{||uzt]cdJHFlksdc\[[TtllSKJ“Œ”tsl|‚zmtt‘Œ…tll‹„‹VTLsretllƒƒ|{zmf]cllk{{t{ttUTS‹„„ztl{ttllkf]ctllf]cSKJJHFult„„Šu{{JHFtt{„Š}”››Œ‹“œ¤¦{tt{u{’…‹›”›mtt‚v‚ª³·dc\lek„Š„””‹lldkk]{||edk{{t|„…„Š„™š¤|„…ª³·ult{{ƒmtttts|‚ztt{uzt{{ƒª³·™š¤Œ”•mk…{{ƒ{{ƒ™š¤™š¤ƒ}Šœ¤¦lekƒ„„d\\‹’Š|„…ƒ}ƒ‹„„f]clksª³·‹…’‹„‹|‚zŒ”•”“›»ÂÇ|‚z{{t“Œ”„„Šœ››Œ”•¨©´ª³·œ¤¦Œ”•fkkVZ[„„Š|„…{{ƒ^fs]cdmtt\[b”“›Œ”•”š”ultœ¤¦{{ƒ™š¤f]cƒ||tsl‹’Šddc’…‹JHF|„…ƒ‚u‚utf]cult\[[lkstt{{ttult‹‹‹™š¤Œ—£nv‚\[[]bZekd]bZJHFddcult‹„‹™š¤…‹’…‹‹¨©´„Š„“Œ”‹„‹kk]|„…{||tllƒ||tslult\[[Œ‹“ƒƒ|SKJf]cŒ—£|„…Œ”•{||tslŒ”•”š”…‹‹mttlks{{ƒ“Œ”“““mtttslult”š”yl„\UZtsluztultuztƒ||ddcd\\kd\UTStslVTL[TTlld]bZrg]d\\œ¤¦LKR*)(bVUVTL74,JHFJHFf]clldUMR{tt|‚zƒƒ|uztb[Uƒ}Š“Œ”‹„‹{u{ztl{{tkk]b[U„Š„[[T{{tdc\‚v{Œ”•‚ut{{ƒ{tt{{tlricbV|‚zlekƒ||tts{tttslultƒ„„…‹‹{u{{u{tts|‚zmttUTS\[bUMRd\\ekdVTL[[TbVZult‹‹„{{ƒsrered[TTbVUf]cSKJ‘Œ…””‹sletsl{zm¦§¨u{{ƒ}ƒ[TTSKJƒ||bVZlddllk{u{SKJf]clkstt{MSS“““‹‹‹‹‹‹{u{„„Šƒƒ|”“›™š¤‚|u‹’Šddc”››lksƒ„„‹…’¦§¨tslult{{t£œ¥‹’Š“““…‹‹›¢›Œ‹“{||{{ƒ{{ƒ\[btt{Œ”•{{ƒ‹„‹™š¤™š¤™š¤Œ‹“mtt}‡’}‡’lksmk…†~‘tts„„Š{{tƒ}ƒttsu{{“Œ”‹…’™š¤œ¤¦|„…tsl‹„„]cdu{{œ¤¦…‹’{tt‹‹‹lks‹„‹™š¤…‹‹œ§²Œ”•‹…šœ¤¦]cdUTSƒ}Šnv‚mttVZ[\[b\[b|„…ƒ}ƒ\[[|„…ƒ}ŠŒ”•|„…‹…’{{ƒ{u{””‹MRK{{ƒ™š¤f]cllkkd\{{ƒlksŒ‹“ƒ„„lksmtt|‚z…‹’‹…’^fs\[[mttu{{{{t|‚zVTLtsltslVTLfkk…‹‹{{ƒœ››‹…’›”›ult‹‹„ƒ‚u¤¤‹’Š“Œ”„„Š‹„„j]\…‹‹u{{ƒƒ|Œ”•f]cultLKRƒ„„…‹‹ƒ}ƒlddttsŒ”•ƒ}ŠŒ‹“…‹’™š¤…‹‹lekuzt{u{|„…lksmttlri|„…lriuztlekultd\\dc\UMRek]sle[TT]bZSKJ\[b[TT¦§¨MSS-1+VTL[TTPF=UTSddc\[[lld‚utred|‚z|‚zƒ„„ƒ||u{{{ttbVZlek{zmj]\VTLmttdc\tzl|„…‹‹„{||lekƒ}ƒ‹…’{{t’ŒŒ{{t\[[Šƒ}UMRƒ}ƒtt{|‚z{{ƒfkkš””ƒ„„™š¤‹…’{{ƒ™š¤|‚z“““ŒŒš‚wlVTLtsl[TTlks„vŒSKJ|‚z„„Šddc{||ƒ}ƒlddj]\tts‰|vJHF[TT‹‹„‚|urfk{{tult’ŒŒsleƒ„„ttstll{tt…„’MSSf]cult„„Š\[bldd{ttŒ‹“ultf]clekœ¤¦Œ‹“‹’Š|‚z™š¤”››‹…’{||Œ‹“‹‹„„Š„ƒ||™š¤ƒ}ƒŒ”•…‹‹lld|„……„’uzt{||mttedk|‚zœ§²™š¤œ¤¦™š¤™š¤¦§¨¦§¨›²‰Š¡|„…‰Š¡{{ƒmttŒ”•‹„„uztŒ”•“““›”›œ››£œ¥Œ—£‹‹„llk‹‹„”š”ult|„…™š¤œ¤¦|‚zf]cf]c{{ƒ™š¤}‡’¨©´”››ŒŒšmtt]cd\[[ldd|„…Œ”•mtt{{ƒVZ[lks{{ƒlksmtt{{ƒlek\[blks{u{Œ‹“{ttSKJ{u{tll{u{VZ[‹‹„tt{llkddclddrfk|„…ƒ„„{{ƒtt{edk|„……‹šmtt‹‹‹]cd]cdlld{||{ttultŒ”•„„ЄЄ{{ƒ]cd{{t{tt¤¤ƒ„„‹‹„œ››u{{u{{‹„‹Œ‹“|‚z[TTtt{{{ƒ|„…u{{‹‹‹ekd{{t{||tllfkk{u{VZT|„…‹…š{||ddc|„…ult…‹‹ldd{tt|‚zekdddcUMRztlfkk‘Œ…‹„„SKJVTLdc\D;9JHFlldVTLldd¦§¨JHF,55sled\\:97JHFredbVUlri{u{tllUTSVTLlriultf]cult‹„‹ult‹‹„“Œ”]bZ{{ƒ„Š„tsl]bZ„Š„‚|uf]clekultdc\””‹llk…‹‹VTLVZTlek{{ƒ¦§¨›”›UTSd\\…‹‹{||tt{ƒ}Š™š¤”š”‹„„Œ”•ult‘Œ…‹‹„{{tJHFƒ„„f]c„Š„ult{tt›”›sleztl‹„„rfk£››redrr]slettsšŒ›¢›“Œ”™š¤{||‘Œ…{{ƒrfk{zm\UZJHFddc{{ƒ\UZLKRŠ}ƒƒ„„£œ¥‹„‹{u{ldd’…‹Œ”•‹’Š|‚zmtt‹‹‹ƒ||™š¤lks”››‹‹‹‚ut‚|u‹„„{||{ttŒ”•‹’ŠŒ”•“““[[Tmk…uzt“Œ”lks{{ƒ…‹šœ§²··ÄŒ—£¨©´™š¤™š¤™š¤}‡’†~‘mtt‹„‹{{t{{tŒ”•{{ƒ“““¨©´¨©´™š¤µ¶·ƒ}Šš””™š¤]cd{||Œ”•{{ƒ„„Šult{{ƒ‹…’Œ”•…‹‹{{ƒttstt{{||]cd…‹‹tts]cd|‚zŒ”•n…mttlkslks™š¤”››ŒŒšultu{{ƒ}ƒƒ}ŠŠ}ƒ‹‹„‹„‹uztg\rŒ”•Œ”•š””ƒ}ƒ”“›edkƒ||f]c|„…{{ƒ|„…lks\[blksŒ—£nv‚›¢›|‚z{{ƒ“Œ”‹„‹Š}|tll…‹’“Œ””“›”“›…„’tsl‘…„tslult…‹‹œ¤¦’ŒŒtt{ƒ}ŠŒ”•mtt„Š„…‹’“~ˆ™š¤mttfkk‹„‹ƒ}ƒ‹…’ttsfkkttsu{{{{ƒ{{ƒ\[[mttmttUMRllkƒ}ŠmttuztUTSfkkUTSSKJ|‚ztsl[TTSKJ[[Trg]aWMlrilddcbVult¦§¨LKR,55‚wl[TT\UZddcJHFtll[[Tultllk]bZtzl{ttult[TT”“›tsl„„Š‹’Šƒ||SKJmttŒ”•|‚zttsek]Œ”•lddœ››llkd\\{||d\\mttJHFVZTbVZlks’…‹mtt|„…„Š}Œ‹“„„Šƒ}Š{{ƒ‹’Šu{{lks™š¤{ttsle[[TUMR?;Cf]cSKJ„Š}lekttstt{„„Šf]cƒƒ|UMRkk]ztlŠ}|VTLuzt…„’”š”f]cƒ||VTL‹„„…‹‹lddldd[[Tekdd\\mttlks\[b{|||„…lksldd{{ƒ‹„‹ttsŠ}ƒ|‚zu{{{{ƒ‹’Š‹„‹ƒ||…‹‹››”|„…ƒƒ|ƒ}ƒtll‹‹„Šƒ}Œ”•‹’Šƒ||„Š„tll{{ƒ‹„‹”“›{{ƒœ¤¦…‹‹Œ‹“…„’œ§²¨©´Œ—£·¶Ñ™š¤…„’‰Š¡„†™u{{b[Ulld{{ƒƒ||£››£œ¥”››‹„‹¦§¨ultŠ~‹¦§¨|‚z|„…™š¤¦§¨œ¤¦ƒ„„¨©´£²mtt™š¤lks”“›lddŒ”•mttœ¤¦“““Œ—£|„…{{ƒnv‚œ¤¦]cd|„…\[b|‚zlek\UZlks‹„‹ŒŒšlek‹’Šƒ„„’‘~ƒ}ƒƒ„„…‹‹Š}ƒlks„„Š„„ŠŠ}ƒ…„’lks{||{{ƒLKR…‹š{{ƒ\[b~’“|„…Œ”•mtt„„Šd\\…‹‹£œ¥Œ”•”“›”𔋅’Œ”•lriŠŠ}‹‹„”“›’ŒŒ¦§¨š””{{t‹…’|„…|„…lks{u{™š¤œ¤¦Œ—£|„…tllf]cfkk“Œ”lriu{{ultu{{{{ƒƒ|||„…mttlksŒ‹“lks…‹’ƒ„„…‹‹lks]cddc\\[[dc\[TTultddcsre{ttlrikd\ztlVTL¦§¨MSS:97tzlŠŠ}ultSKJVTLVZTVTL[TT[[Tf]c‚utllkŒ‹“dc\lekb[Uttsƒ}ƒtt{ƒ|||„…mtt|‚zuztlldƒƒ|f]clksult‹„„ultœ››œ¤¦|‚zddc“Œ”Œ”•{ttJHFtsl‚|u|„…u{{ƒ„„|„…ttstt{…‹’ƒ}ƒtlld\\iq]lriUMR|„…d\\llktlllri\UZ[TTsleŠƒ}\[[ultŠƒ}’ŒŒztl¦§¨‹„„”š”\[[ƒ||]cdJHF[TTVZTVTL\[[ekdSKJ^fsmttSKJdc\ldd„„Š“Œ”„„Š™š¤ult‹‹‹“Œ””š”ƒ}ƒƒƒ|ƒ}ƒ„„Šƒ„„{||’ŒŒ…‹‹uztllklldtll›¢›{||{{tzlltts\[bƒ}ƒult˜Ž£u{{Œ”•ulttt{™š¤„†™„„Š‹…š…‹’ŒŒš™š¤Œ—£“Œ”lek{u{›”›ƒ}ƒ“Œ”{u{µ¶·›¢›‹„„“Œ”™š¤¨©´ª³·œ§²›¢›|„…œ¤¦‚v{£œ¥ƒ}ƒŒ—£Œ”•…„’…‹‹”“›|„…œ¤¦lri¨©´{{ƒ|„…Œ—£œ¤¦}‡’mttlektt{‹’Š‚v‚”››ŒŒš„„Š„„Š[TT„Š„{{t‹‹‹{{t{{t„Š„ztl]bZ‹…’{{ƒƒ||ŒŒštts{||JHFVZ[lksn…MSSmttmtt{||fkk\[[™š¤œ¤¦Œ‹“‹‹‹›”›|„…“Œ”‹’Šlddƒ„„‹‹‹‹…’Œ”•””‹“““Š}|‹„‹nv‚ultdc\™š¤tt{edkUUY{||ƒ„„ŒŒš{{ƒmtt]cd\[b^fs‹’Š…„’mttmttmttf]cmtttsl„Š„ekduztUTSƒƒ|‚utleklrid\\f]ccbVlddSKJlldUMRr]ZVTLµ¶·OS`)+2‹’Šƒƒ|llkFD;[[TSKJFD;SKJVZTUMRJHFJHFtsllldredSKJ{||‹„‹UTS\[b¨©´ekd›¢›|‚z|„…tts{||ƒ„„mtt‹…’{||lri™š¤œ››]cd‚v‚uzt‹’Šztl[TTztltts™š¤\[btsl{{ƒ…‹‹{u{UTS‹‹„ƒ„„|„…]bZ{{ƒJHFddcultŠ}|\[[d\\srelri{ttŠ}|rfksrebVZdc\edksleddcu{{\[[ekdf]c\UZ|„…d\\|‚z[[T\[[\[b™š¤d\\{{td\\£œ¥‹„‹¨©´Œ”•¦§¨ƒ||lritts‹„‹…‹‹ƒ}ƒ‹‹‹ƒ„„{tt¦§¨œ¤¦ƒ||ƒƒ||„…””‹›¢›‹‹‹…‹’’ŒŒttsUUY{{ƒŒŒš™š¤œ¤¦Œ”•}‡’ŒŒš¬¶Ã†~‘„„ŠŒ—£œ››¨©´…„’Œ—£uzt¦§¨…‹’›”›tt{†~‘‹„‹{tt{||‹„‹™š¤™š¤{tt…‹‹}‡’Œ”•ƒ„„’ŒŒ“““‹…’™š¤˜Ž£Œ”•lksœ¤¦Œ”•…‹‹]cdlriddcult|„…uztŒ”•|„…¬¶ÃŒ‹“™š¤ƒ„„“““‹„‹ddcultult[TTtllekdiq]]bZ„Š„ekdkd\{{ƒ\[[ekdf]c™š¤ƒ„„{u{lksmtttt{|„…|„…n…Ž¡›ek]|„…„Š„lksuzt“Œ””››“Œ”mtt{{ƒlks{{ƒš””œ››†~‘‘Œ…“““‹‹„“““tllŒ”•„„Š’ŒŒƒ}Š|„…{{ƒlksŒ”•ddc{u{{{tult|„…mtt|„…{{ƒlksfkk\[b]cd\[b]cdfkkddcuzt]cdlri|‚z{||[TTb[Ukd\sleb[UyleyfdllkJHFaWMlriœ¤¦OS`*)(ttsƒ}ƒ{ttd\\sre{{tb[UVTL74,JHFFD;UTSVZTkd\redjV[{u{ekdmtt{{tult{{t‹’Š|‚zu{{lkslri\UZuztƒ}ƒ[TTƒ„„Œ‹“lri]cdddc{||UTStt{„„Š›¢›|„…tts{u{|„…››”uztultUTSlddztl|‚zek]{{ƒ:97f]c\[[{ttlld”“›{u{|‚z“Œ”{ttƒ„„rfk{tt‹„„sref]cUMR[[TlriJHFƒ||\[b{{ƒƒ„„™š¤Œ”•ult]bZultƒ}ƒƒ||mtt’ŒŒ„„ŠŒŒšekdtt{£œ¥”“›ª³·“Œ”„Š„{||{||œ¤¦‹„„ŠŠ}{{tª³·‹„‹”š”ƒ}ƒu{{„„Š|„…’ŒŒ{{ƒultmk…ƒ}Šœ§²œ¤¦~’“œ¤¦ult›²œ¤¦Œ—£Œ—£…‹šŒ—£„„Š|„…“Œ”tllœ¤¦œ››ŒŒš}‡’š””µ¶·“Œ”“““›”›‹…’›”›œ¤¦|„…«²«Œ—£Œ‹“¦§¨™š¤lks™š¤™š¤Œ—£Œ”•…‹’¨©´¡¡…‹‹“““{ttŸ±¯VZ[{{ƒ]cdmttUUY…‹‹„Š„ult”“›yl„Œ‹“f]cf]c‚wlddcJHF[[Tƒƒ|edk’ŒŒ„Š„ulttt{š””edkmttŠƒ}]cdMRK{{ƒ|„…OS`lriŒ”•]bZLKR{{ƒlksuztyl„™š¤“Œ”“Œ”™š¤…‹‹…‹‹‘Œ…‹‹‹ƒ}ƒ‹’Šš””››”‹„„Œ‹“…‹’edkttslekmttfkkƒ„„Œ‹“{||…‹’|„…ƒ„„\[[f]c\[b]cd{{ƒlks|„…Œ”•}‡’‹„„…‹‹ƒƒ||„…lksVZT…‹‹‹’Šf]ckd\b[Uf]c[[Trg]red{{tekd]bZtsl¨©´JHF,55mttlldbVUFD;b[Uz‚lekd[[Tekdlri›¢›SKJlld„Š„ƒ}ƒ{u{{u{d\\UTS…„’lks|‚zlrimttu{{mttllk\[[llk\[[ldd{tt{||lri{{ƒ„„Šulttsl{{ƒmttƒƒ|{||ƒ}ƒƒ}ƒult„„Š{{ƒttsdc\{{t{{t„Š„[[TlksJHFJHFd\\„„Š|‚z{{ƒ‚|uŒ‹“tsl[TTrfkVTLrfkdc\FD;sleekd[TTkk]|„…lldƒ}ƒ{u{JHF{{ƒ\[[UUY]bZ{u{SKJllk„Š„zlllek{||„„Š‹‹‹ƒƒ||„……‹‹…„’‹’Šƒ}ƒ‹„„Œ”•lld›”›‹‹„“Œ”lriŠƒ}ldd|‚z{{ƒŒ”•llk“Œ”lks‹’Šlekmtt“Œ”œ¤¦Œ‹“{{ƒ|„…Œ—£Œ”•œ§²‰Š¡™š¤{{ƒ™š¤ode-0.16/drawstuff/textures/sky.ppm0000664000175200017520000014005313403272463014361 00000000000000P6
# Created by Paint Shop Pro
128 128
255
¾çýÃéþËîÿÎïÿÆéÿÂçÿºçÿ·åÿ²àÿ°Ýþµàÿ¹åþÃëÿÍðÿÏðÿÐíûÑîüÏïþÇìÿ½æü´àù´âü¹åÿºæÿ¹åÿµâÿ±Þý«Ùú¦×ø§ÙüªÜÿ¶âýÉîÿÐñÿÚõüâúþëýýíýüïÿþìþÿìþÿãüÿÛøÿÊíÿÄéÿ­Ûÿ£Ôü£Øÿ¤Úþ§Üü±ãþ°ãÿ¤Ûÿ ÕýŸÔþ ÕÿŸÔþŸÕÿ›ÔÿšÕÿ™×þ˜×ÿ”Ñý™ÒÿšÓþ›Õý¡Ùþ¥Úü­Þü°ßù»åû½èû½æü»çÿ¸åÿ®Þÿ§ÛÿÓÿšÓÿ•Ðü•Ðü—Òþ“Òþ‘Ðû›Óø§Ùú¾èÿÄêÿÌðÿÆîÿºæÿ¦×ø Öú“Óÿ‹Íý„Çü€Äÿ}Ãÿ}Ãÿ~ÄÿÆþ€ÇýƒÉýƒÈÿÆÿƒÈÿÆÿ€ÄÿÅÿÅÿÆÿ€Åþ~Äÿ}ÄÿÆÿ…ÈÿŒËÿÌÿ„Çü…ÊÿˆÍÿ‹ÌÿŽÍÿ‘ÐÿÎÿ™Ôÿ ×þ±âÿ´áþ¸äÿÂêÿÃèÿ»ãý·àü®Üý©Ùý¥Ö÷©Ö÷¯ÛøÂëÿÊðÿÇëÿÆéýËîÿÉîÿÌðÿÆïÿ¿éÿºæÿ»çÿ¼èÿ»çÿ¹åÿµäÿ²àÿ¨Ùú£Õø Ôù¢Öý²ßüÄêÿËðÿØöÿÞùÿéþÿêþýìþþíÿÿêþÿ×õÿÎðü½ãö·áù®Ûú¬Ùú³àÿ½çÿÂëÿÐôÿÏôÿ¼éÿ³àÿ­Ûü®Üþ¨Úÿ£ØÿŸÕÿ‘ÎúŽÍùÏû‘Îû•Ïý–Ñý˜Óý×ý ØýªÜý¬Ýû¸æÿ»çÿ¶âý²áÿ¬Ýþ ÔûÒü˜Ðÿ•ÏýÍú‘Îû”Ñþ‘Ñÿ‘Ñý˜Òø Ôù·äÿÀéÿÇïÿÀìÿ¸æÿ¥ÙþŸÖý‘ÑÿŠÌþ…Èÿ}Áþy¿ý{Àÿ}Ãÿ€ÆÿÈÿÆý‚ÉÿÇÿ}ÃÿzÀüÅÿÅÿÅÿ~Äÿ|ÂýzÀûzÂýÆÿ…ÈÿŠÉþŠÉþ…Æþ†ÉÿŒÏÿÎÿÍþÍþÍþ”Ïû˜Òú¨Ýÿ°Þÿ²àÿ·ãÿ¸áý±Ýú®Ûú¤Öù Òõ¤Ö÷­Ûü³ßüÃéÿÆìÿ¼âùºà÷ÃéÿÅíÿÈðÿÃíÿ¼æÿºäý½çÿ½çÿ¼æÿ·ãþ³âÿ®ßÿ¨Úý¢ÖûŸÕûŸÔü±ÞýÀèÿÇíÿÔôÿÛøÿåýÿèþüìÿÿíÿÿëÿþ×øÿÍóÿ¾ä÷¹ãùµáüµáüÁëÿÍòÿÒóÿÚ÷ýØöÿÆïÿÁéÿ¸âû³ßü®Üþ¥Ùÿ ×ÿ‘ÎûËúŽÎþÎý”Ñÿ•Òÿ–Óÿ›ÖÿœÖü¥Ûÿ¨Ýý³äÿ·æÿ³âÿªÛü¦ØûŸÔü˜Ñü•Ïý’ÏþŽÌû‘Ïþ”Òÿ‘Ñÿ’Òÿ˜ÒúÓù²àÿºçÿ½éÿ¸æÿ³ãÿ¥Ùÿ ×ÿŽÎþ‰Ëý…Èÿ~ÂÿzÀþz¿ÿ|ÂÿÅÿÆþ€Åþ€Çÿ~Äÿ{Áÿy¿ý~Äÿ~Äÿ~Äÿ~Äÿ|Âý{ÁüxÀûÆÿ…Èÿ‰ÈýŠÉþŠËÿŠÍÿŒÏÿÎÿÌûÍü‘Îý“Îú—Ðû¤Úÿ£Øÿ¥Úÿ®àÿ±ßÿªÚÿ¥ÙþšÑø—Îõ¢Öû´âÿ»çÿÉíÿÈîÿ¹áû³Üø³àý·äÿºçÿ·ãÿ²Þû¹ãü»ãý¼æÿ½çÿ¶ãÿ®ßÿªÜÿ¡×ýÔûšÔü›Õý«Ýÿ¸åÿÀêÿÍòÿÓõÿÚ÷ýßûþéÿÿçÿýéÿýáÿÿØúÿÉíûÆëûÉîÿÊïÿÔõÿÚ÷ÿÙõùàõöß÷÷Úöÿ×õÿÏðÿÉìÿ¹âþªÜÿ¡Öÿ’ÐÿÎÿ‹ÌÿŽÍÿÏÿÏÿÐþ”Óÿ‘Ðû›ÖþžØþ¨Þÿªßÿ¥Ùþ¡×ýŸÖý˜Óÿ“ÐýÍþŽÍÿŽÍÿÎÿÎÿÏÿÏÿ’Ïü–Ïú£×þ¨Úÿ¨Øü¤Øý¥ÙÿžÕþ—Òþ‹Êý†ÈüƒÅÿÃÿ|Âÿy¾ÿz¿ÿ}Ãÿ~Äÿ‚ÇÿÇÿx¿ýv½ýu¼üw¾þzÁÿzÁÿzÁÿzÂýyÁüw¿ù€Åþ„ÇüˆÇüŠËÿŒÏÿŠÍÿˆÊþ‘Îû•Îù”Íø–Ïú“Éõ“ÊóÔý›ÑÿžÔÿ©Ýÿ¬Ýÿ£×ÿ Õý˜Ñü•ÐúŸÕû±âÿ¼éÿÌðÿËðÿ¼åÿ´àý°ßý±ßÿ´âÿ´ßÿ±Ýúºäý¹áû»åþºæÿ´ãÿ¬Þÿ¨ÜÿžÕü˜Òú˜Ñü›Ôÿ¥Ùþ²áÿ¸åÿÆìÿËïÿÕóýÜùÿçÿÿäþýæÿüæÿÿßþÿÐñúÎîùÐòþÒóÿÚúÿÝøÿÝöúåûùæûüßøýÚõüÚøÿÕöÿÂêÿ¯ßÿ£Øÿ‘Ïÿ‹Íÿ…Èý‹ÍÿŽÍÿÌÿÍýÐþÍü—ÔÿšÕý¡Ûÿ¤ÜÿžÕü¡Øÿ×ÿ“Ðý‘ÏþÏÿÏÿÏÿÎÿŽÍÿŒÎÿŒÎÿÍü”ÏûžÓý Õý¡ÕüŸÔü¡Öÿ™Òý”ÏûŒËÿ…Æü‚Äþ~Âÿ{Áÿz¿ÿz¿ÿ}ÃÿÅÿ‚ÈÿƒÉÿw¾üu¼üt»ût»ûyÀÿzÁÿyÀÿx¿ýw¿ú{Ãý‚Çþ„Çü†ÅúˆÉÿŒÏÿ‰Ìÿ‡Éû•ÐúœÓúÒúŸÔü™Îö™Îö¡Øÿ”Ìû–ÏüšÐüžÓý™Òý“Îú“Óÿ”ÒÿšÕÿªÞÿ²ãÿÃèÿÅíÿ¾êÿ¸äÿ®Üý¬Úû®Üý²Þû±Ýú³Üø·ßù¸äÿ´áþ®ßÿ£Ùÿ ×ÿœÕÿ›Ôÿ›ÖÿÖÿŸÔü¨Úý­Þÿµáü½åþËïÿÐòþÚ÷ýÛ÷ûàúûíÿÿíÿÿæûüåýÿãþÿßüÿÛùÿÛøþßûÿäÿÿäþÿãøûàøüÞùÿÚøÿÍóÿ±âÿ¡ÕüÎýÎÿ†Éÿ‡ÉýŒÎÿŠÌÿ‰ËÿŠÌÿ‹ÍÿÏÿ‘Ïþ“Ðü’Ïû•Ðü”Ïû’ÏüÏýÏÿŒÎÿŒÎÿŒÎÿŒÎÿŽÍÿÏÿÏÿÏÿ‘Ïÿ”Îü•Îû–Ïü•Îû—Ðý˜Óÿ•ÒÿŽÍÿŠËÿ‚Äþ~Âÿ~ÄÿzÀþy¿ý~Äÿ|Âÿ|ÀýÅÿ{Âÿx¿ÿw¾þv½ýw¾þv½ýw¾üzÂýÇÿÈÿ†Éþ…Èý…Äù„ÅûŠÍÿŠÍÿÐÿ¢Ùÿªßÿµãÿ¸çÿ²ãÿ¬Þÿ Ôû•Îû•Îû–Ìø™Ïû—Òþ‘ÎûÒÿ’Òÿ–Óÿ£Øÿ©Ûþ¸âû¿èÿ»çÿµáþ®Ûú±Þû³àý³ßú²Þùµáü´Ýùµáþ²ßþªÜÿÔû×ÿ™Ôÿ›ÖÿŸØÿž×ÿÔû¢Øü§Üþ¯Þü¶âýÈìÿÌïÿ×õÿÛøÿÝùüêýûîþûëþüêÿÿèÿÿãÿÿÞûÿÚ÷ýÞûÿæÿÿåÿÿãøýß÷ûÜ÷ÿÚøÿÎôÿ³äÿ¢ÖýÍüŽÍÿ†ÉþˆÊþ‰Ëÿ‡Êþ†Éý„ÇûŠÍÿÏÿŽÎþÍüÍüÍúÍúÍüÏÿÎÿ‹Íÿ‰Ìÿ‰Ëÿ‹ÌÿÎÿÏÿÏÿÏÿÎÿ‘Îý“Íý’Ìú‘Ëù”ÎüšÔÿš×ÿÎÿ‹ÌÿƒÅÿÄÿ~Äÿ|Âþ{Áý~Äÿ}Ãÿ}ÁþÅÿ~Äÿ|ÂÿzÀþw½ûy¿ýx¾üx¾ü|ÂþÇÿÈþˆËÿ†Éþ‚Ãù„Åý‹ÎÿŠÍÿ‘Ïþ¨Þÿ´çÿÁíÿÄðÿ¾ëÿµäÿ¤Öû§Ýÿ¦ÝÿœÑû˜Ïø”ÑþÐÿŠÐÿŒÏÿÌÿ“Ìù˜Íõ¬Ýý¸çÿ½éÿ¼æÿ¼äý¿åüÂêÿ½çÿ½çÿ¸äÿ¸äÿ°Þÿ«Üý¢ØþšÓþ–Ñý•Ðü˜ÓÿŸØÿŸÕÿ×ÿ ×þ¤Úÿ©Ûþ¯Ýÿ¾çÿÃèÿÒóÿÙöÿÝøÿãøûçûúéþÿéþÿäýÿáúþÝùýÞúþàüÿáýÿßøÿÚõþÛöÿÛùÿÕöÿÅîÿµäÿ«ßÿ“ÐýŒÌüŒÍÿÎÿ‰ËýŠÍÿ‰Ìÿ„ÇüƒÆû†Çý…Çû‡ÆùŠÉüÍÿÎÿÎÿÏÿŒÎÿ…Çù†Èú‰ËÿÌÿŽËÿÌÿÍÿÎÿÎÿ‘Ïÿ‘Ïÿ‘Ïÿ“Ðÿ–Ðÿ™Ñÿ™ÓÿÎÿŒÎÿ…ÈýÆÿ€Çÿ~Äÿ~ÄÿÇÿÅÿ‚Çÿ‚ÈÿÅÿ|Âþ{Áý|Âÿ|ÂÿzÀüzÀü~ÄÿƒÊÿ†ÍÿŽÑÿÐÿ‹ÌÿŒÍÿÐÿÎÿ’Ïü«Ýÿ¸çÿÌñÿÒøÿÏøÿÈðÿµâÿ©Þÿ¨Þÿ›Ðø—Î÷“ÐýÐÿˆÍÿ†ÍÿˆÉÿÌþ•Îû£Ùû¬ßþºæÿ¿èþÇêýËïÿÌïÿÃìÿÅïÿºèÿ¹æÿ«Üý§ÛÿÔý”ÏûÍú”Ïû–ÑýÓÿžÓýœÖþ×ÿ¢Ùÿ¤Øÿ§×ÿ®ÙûµÞüÇêÿÎíÿ×óÿÛöÿÞùÿÜ÷þÛ÷ûÛ÷ûÛ÷ûßøüäüþéþÿåúýÝôú×ôÿÖóÿÒóÿËïÿ»æù«Üú¥Úü•ÐüÎý‘ÐÿÎÿŽÍÿÏÿÏÿŒÏÿ‡Êÿ†Éþ‡ÊÿŠÌÿŒËÿÍÿÏÿÏÿÏÿŒÎÿ‹Íÿ‹ÍÿŽÍÿÌÿÌÿÌÿÌþÍÿÎÿÎÿÎÿ‘Ïÿ“Ïÿ”Îþ—Ïþ˜ÒÿÏÿŽÐÿˆËÿ‚ÇþÈþ~Åý~Äÿ}Ãþy¿ú}Âý‚ÇÿÆÿÆÿÆÿ€Äÿ~ÂÿÃÿÄÿÆÿ‚Çþ„Ëÿ‡ÊþˆËÿ‰Êÿ‡Èÿ†Èÿ‡Èþ“Îú©Úú´àùÆèòÍîõÒôÿÌñÿ¼äþªàÿ©ßÿ›Òù–Íö‘ÎýŽÎþ†Ëÿ…Êÿ†ÇýËý•Îû£ØúªÝü¹åþÀéýÈìüËïÿÉìÿ¿èþÂìÿ¹çÿ¸çÿ«Ýÿ©ÝÿœÕÿ‘ÎúÌù”Îü–Ñý›ÑýžÓý×ýžØÿ¤Ûÿ¤Ùÿ¦×ÿªÖù±ÜüÄèÿÊêÿÖóÿÛ÷ÿÝùÿÙ÷ÿØöþÛøÿÛøþÛ÷ûâúþçüÿåúûÞöúÓòÿÐñÿÉîÿÄêýµâù¨ÙùŸÔö•Îù”Îü’ÏþÍüÍþŽÍÿÏÿÐÿ…Èý…Èý‡ÊÿŽÏÿÏÿŒËþÎÿÏÿÏÿŒÎÿÒÿÑÿŽÍÿÍÿ‘ÎÿÎÿÎÿŽÍÿŽÍÿŽÍÿŽÍÿÎÿÌþ’Ìü™Ñÿ›ÕÿÏÿŽÐÿˆËÿƒÈÿ‚Éÿ€Æÿ€Æÿ}Ãþz¿ú{Àù€ÅþƒÈÿ„Éÿ…ÇÿƒÅÿÃÿ‚ÄþÆÿÆÿÆý…Ëÿ†ÉýˆËÿŒÏÿŠÌÿ„Æÿ…ÈýÌù¡ÖøªÛù½ãðÆèòÍòÿÌòÿ¿çÿ°äÿ©Þÿ˜Ñü”ÎüŽÍÿÌÿ‡ÉýŠÉü‹Éú–ÐÿžÔÿ°Þÿ´áÿºäú¿êûÇîÿÄíÿÃëÿ¾èÿ¾èÿ»éÿ³äÿ¥Ùþ¢Øþ—Òü“Òþ’Ñý™Öÿ›ÖÿœÒþÔý¡×ý¤Úÿ¤Üÿ£Ùý£×üªÛü°ßý¼äþÀåÿÉìÿÔôÿÓóþÐòþÎïþÍîÿÍîýÔôÿÜùÿßúÿäüþÞúþÍóÿÅîÿ¸âû²ßü¬Üÿ¥ÖþÑùžÓû¡Öþ¢×ÿœÒÿ•Íü’Ïþ‘ÏÿÌÿ‰Èû‡Éý‰Ëý‹ÏÿŠÍÿŽÎþÏÿÏÿÏÿÎÿÌÿŽÍÿÎÿÎÿÎÿŽÐÿŽÐÿÑÿ‘Ðÿ‘ÎÿÍÿ•Îÿ•Íþ–Ïü›Ôÿ™ÔÿŽÍÿŠÉþˆËÿÆÿ€ÄÿÇÿ‚Çÿ€ÂüÂù‚Åü„Éÿ‡Éÿ…Æþ…ÆüŠÉþŠÉþ…ÆüƒÆý‚ÇÿƒÈÿ„Åû‡Èþ…Èý‡Ìÿ‡Îÿ€Çý„ÊþÏÿ–Õÿ›Øÿ©Ûü°ßýµäÿ´ãÿ·æÿªßÿ¤Ùÿ•Ðü“ÐýÌÿˆÊþ‰ËÿŒËÿŽÌý˜ÒÿžÔÿ²àÿ¶ãÿ¹æû¿êûÂëýÆïÿÆîÿ¿éÿ»çÿ»éÿ´âÿ¦Øý¢Öý™Óû—Ôÿ•Òþœ×ÿž×ÿžÕü Öü¤Øý§Ûÿ¦Üÿ¤Øý¤Øý®ßÿ³àÿ¼äþ¿äþÆéÿÑñÿÑñþÍîÿÌíÿÈëþÈëþÑñÿÚöÿÜ÷ÿàùþÜùÿËñÿ¿èü³Ýö¯Üù¬Üÿ©Úÿ¤Øÿ¥Ùÿ¦Úÿ¦Ûÿ Öÿ—Ïþ”Îþ“ÐÿÍþËü‹ÊýÍýÏÿŽÍÿÍüŽÎüŽÎüŽÎþ‹ÍÿŽÍÿŽÍÿÎÿ‘ÏÿÎÿÌÿŽÍÿ‘Ðÿ’Ðÿ‘Íÿ‘Íÿ”Îþ–Ìú™ÏûŸÖýœÖþÍþŽÌÿÎÿ„ÆÿÆÿ‚Çÿ‚ÇÿÃýÄûƒÆý†Ëÿ†Èÿ„Åý†ÇýŽÍÿŽÍÿ‰Êÿ†ÉÿƒÈÿ„Éÿ…Æü†ÈüƒÆúˆËÿ‡Íÿ‚Èü†ÉýÍý’Ïû–Ñý¢Øü¤Ùû¥Úü¥Úü«àÿ•Îû•Ïý‘ÎýŒÊû‡Éý‡Êÿ‡Êÿ‹ÍÿÎÿ–Óÿ›Ôÿ­Ýÿ±âÿºêÿ¾ìÿ¼éÿ¼èÿ¾êÿ¶âý³ßø³ßø·äÿªØü¦ÖüŸÓúŸÖýžÕü¢Øþ£Ùý§Ùú¨Ûú¨ÙúªÛüªÛü«Üý­Þÿ±ßÿµâÿ¿èÿÂêÿÃèÿÈëÿÇêþÅèþÅçÿÃçÿÃçÿÉéÿÑðÿÒïÿÕñýÕõÿÄêý¹âø²Üõ±Þû¯Ýÿ­ßÿ¯áÿ­ßÿ¬Þÿ«ßÿ Õÿ™Íü›ÑÿžÔÿ Öÿ ÖÿŸÕÿŸÕÿ›Ñý˜Îú“Íû‘Ïþ‘ÏþÐÿŽÐÿ‹Íÿ‹ÍÿŽÍÿÍþÌþÎÿÎý‘ÎýÍü™ÑÿžÔÿ Õÿ¤ØÿªÜÿ«Üý¥×úœÓü—Ðû”ÎþÊÿŒËÿ…Èÿ…Èÿ…Èÿ…Èý„Çü†Éþ‡Êÿ†Çý‡ÉýÌÿÌÿÎÿŒÍÿ„Æÿ‚ÄþƒÄúŠÉþŠÉþˆÊþ‰ÈýŒËþŽÌý‘Îý”Íú•Îù™Ôÿ—Ôÿ”Ñý’Ïû’ÏûÉùÍüÍþŠÉü†Éþ‰Ìÿ‡ÊÿŒÎÿÎÿ“Ðÿ—Ñÿ¦×ÿ¬Þÿ·éÿ¼ìÿ¸æþ¶âý·ãÿ´àû²Þ÷³ßø¹äÿ®Úý«Ùý¤Öù£×ü£×ü§Ùú¨Ûú«Üú®Ýù°Ýü±Þý±Þý²ßÿ´áÿ²ßþµáþ¾çÿÁèÿÁæÿÇëÿÇêÿÆèÿÅéÿÅéÿÅéÿÅèþÎïÿÏîÿÑîþÑòÿÅëÿ»äú²Üõ¯Ûø«Ùû®Þÿ®Þÿ¬Üÿ«Ýÿ«Ýÿ¦ÚÿŸÒý¢Öþ¥Ùÿ¦Úÿ«Üÿ¬ÝÿªÞÿ¥Ùÿ¡Òú“Ì÷‘ÎûÎýÏÿŒÎÿ‹Íÿ‹ÍÿŽÍÿÍþÌþ‘Îý’Ïþ’Ìú’ÌúÓÿ£Øÿ§Øÿ®ßÿ³áÿ³àý­Üú£×üŸÓú—ÍûËýÎÿŠËÿ‰Êÿ‰Ìÿ‰Ìÿ†ÉþˆËÿŠÍÿŠÌÿ‰ËÿÌÿŒËÿÎÿ‹ÌÿƒÅÿƒÄþ‚Ãù‹ÊÿÌÿÎÿŽÍÿŽÌýÍþ‘Îý”Íú•Îû‘ÏþÐÿ‘ÑÿÐÿŽÎþ‡Æû†Åú…Æü†Çý…Èý…Èý‹ÎÿÑÿÏÿŒÊùÊ÷™Îø Öü®ãÿ±æÿ¬Ýý­Ûý®Üþ¶âÿ¹åÿ»çÿ½æÿ¶ßÿ´ßÿ±Þý°ßýµäÿ¶äþ¸æþ½êÿ½êÿÁëÿÁéÿ¿çÿ½äÿ¿æÿ¿çÿ½çÿ¼äþ½äÿ¿çÿÃéþÄèþÄèþÅéÿÆêÿÇëÿÆêÿÍðÿÏóÿÎïþÎòÿÅîÿÀèÿ³ßú²Þû´áÿµãÿ±ßÿ¯Ýþ°ßý°ßý±ßÿ¯Üûµáþ¸äÿ»åý¼æþÁëÿÃíÿ½çÿ¶àøŸÕûšÕÿ–Óÿ‘ÑÿÏÿŒÎÿŒÎÿÎÿÎÿ‘Îý”Îü—ÒþœÒþœÓü¦×ÿ«Ûÿµâÿ½çÿÂèÿÈìÿÆìÿ¹åþ´àý¨ÙúÒü›ÔÿÍþŽÌÿŽÍÿ‹Íÿ†ÈúŠÎÿ‰ÍþˆÊþˆÊþ‹ÍÿŒÍÿ‹Ìÿ‡ÈÿƒÄüŠËÿ†Éÿ‰Ìÿ‰ÌÿÏÿÏÿ‘Ïÿ’Ðÿ’ÎÿÍþÎÿÏÿŒÏÿŒÏÿŒÏÿ‰Ìÿ†Çý‡Èþ…Èÿ„Çþ‰ÌÿÐÿŒÎÿÌÿÍþŠÈ÷ˆÅò˜ÎúžÕþ¦Üÿ¦Üþ¤Ùû¦ÖúªØü¹æÿ»éÿ¾êÿ¿èÿ¹âÿ¶ßý³ßü·ãþ¼èÿÀíÿ¼éþÄïÿÆñÿÃìÿÂçÿÀåÿÀåÿÅêÿÂçÿ¿çÿ¾æÿ¾æÿ¿çÿÉïÿÈîÿÇíÿÈíÿÉíÿÈíÿÉîÿËðÿÍòÿÎòÿÌòÿÃìÿÀèÿ´àû²Þû´áÿ±Þÿ±Þÿ¶ãÿ¹æÿ»éÿ»éÿ¼éÿ¼åû¾çûÊïÿÉîÿÏôÿÐõÿÇìüÁèù«àÿ›Öÿ˜Õÿ‘ÑÿŠÌþŒÏÿŒÏÿÏÿ’Ðÿ’Ïþ–ÎýœÕÿžÕþŸÕû«Ûÿ¯Ýþ¹ãüÈîÿÎñÿÎïÿÊíÿÆìÿÂëÿ²Þû£ÕúŸÔü“ÍûŽÌýŽÍÿÌÿŽÐÿ‹ÍÿŠÎÿˆÌý‡Ëü†Èü‡Èþ‹Êÿ‰Èþ‡ÆüŒÍÿŠÍÿŒÏÿÐÿÏÿÎÿÌþ’Îÿ‘ÏÿŽÍÿÏÿÏÿ‹Íÿ‹ÍÿŽÐÿÎÿˆÍÿ„Éÿ‚Çÿ‰ÌÿŽÏÿŒÍÿÎÿ‘Ïÿ“ÐÿÍúÌù‘Îû•Ðü˜ÓûšÔúœÓú Ôü§×ÿµâÿ¸åÿÁîÿ¾æÿÁéÿÂêÿÄìÿÇðÿÉïÿËñÿÆìÿÉðÿÊïÿÇìÿÄèþÅèüÈëÿÉìÿÍðÿÉîÿÁåûÁåûÆìÿÆíþÆíüÇîýÊïÿÊíÿÈìüÊîüËñþËóÿÆîøÄìøÃìÿÃíÿºæÿ¶âý³àÿ´áÿ²Þû¶âý»åþ¼åûÅïÿÎóÿÑóýÐòûÕôùØõûÝüÿÞýÿÕöýÎðù²ãÿ™Óû•ÐúÍýŒËþ†Éþ‡Êþ‹Íÿ‘Ïÿ”Îþ˜ÑþšÓþ Õý¥Ùþ·äÿ¹åþÄêýÖöÿÙ÷ÿÜ÷ÿÝøÿÛøÿ×÷ÿÇìÿ±Þû«ÜýšÐü“ÍûÍþÍýÏÿŽÐÿŠÌþˆËÿ‰Ìÿ‹Îÿ†ÇýˆÇü‰ÈýÎÿ’Ðÿ‘ÓÿÎÿŽÌý’Ìú–Ïü•Îû”ÎüÎÿ‹Íÿ‹ÎÿÏÿ‹Êý‡ÆùˆÇüŠÉþ‚ÈÿÇÿƒÈÿ†Éÿ‹ÌÿŽÍÿ‘Ïþ”Ñÿ˜Óÿ—Òü•ÒþÏÿÍüŽÍù‘Îú–ÑýÓÿ¢Õÿ®Üþ°ÝúºçüÁêÿÄíÿÃìÿÄêýÊïÿÍòÿÊïÿÉìÿÉìÿÇìþÉîÿÈëþÊîþÏðÿÏïþÍíüÍîýËïýÉíýÆëýÆìÿÆíþÊïÿÌïÿÍîÿËìýËïÿÎóÿÎõÿÅïýÂìü¿èþ½çÿµáü¶âý¼èÿµáþ´Ýùºâû¿èþÃéüÈìüÖöÿßüÿàûÿåþÿäýÿæÿÿäÿÿÛùÿÒóü°ßý˜Ïö’ËöŠÊú†Èú…Èý‡ÊÿŽÍÿ‘Îý”Îþ›Ôÿ›Ôÿ¤Øÿ¬ÞÿºèÿÀêÿÎòÿÝúÿàùÿâúþæûþéÿýçÿÿØøÿÀæýµáþ¡Õü˜ÏøÍüÍûŠÌü‰ËýŠÌÿŠÍÿŠÍÿ‰ÌÿŒÎÿŠÉþŒËþ˜Õÿ™Ôÿ˜ÑüÔû Öú¦Öú¦×ø£Ó÷ Ò÷–ÏúÎÿÏÿŽÐÿŠÍÿƒÆúƒÄú…Æü€Æÿ‚Èÿ„Éÿ…Çÿ‹ÊÿÎÿ’Ñý–Óÿ™Ôþ™Ôþ—ÔÿÏÿŽÎþŽÌûÏû–ÓÿžÔÿ¢Õÿ«Ûÿ®Ýù·äù¿èüÄíÿÃìþÅëþÍòÿÍòÿÊíÿÊíÿËîÿÉîÿÉîÿËïÿÌðþÐòþÑñþÖöÿÖöÿÐòþÌíüËïÿÆìÿÆìÿÉîÿËîÿÌíÿËìÿÌíÿÌñÿÌñÿÃìþÀéû¿çÿ¾èÿ·ãþµáü¶âÿ·ãþ¸âû½æüÁêþÉîÿÌíþØõÿÞùÿâûÿèÿÿàøüßøýÞùÿÚøÿÔòü·äÿÒú•ÎùŠÊú…Çù†Ìÿ‰ÏÿÏÿÍü•Íü™Òÿ™Òÿ¦Úÿ­ßÿ¹çÿÀëþÑóÿßúÿãüÿéþÿìÿÿíÿüìÿÿàüÿÇëÿ¼æÿ£×üšÑú“ÐýÏý‹ÍýˆÊü‹Íÿ‹ÎÿŠÍÿ‡ÊÿÏÿŠÉüËüšÔÿžÕþžÔú¬Þÿ³äÿ¹åÿ·ãÿ¯ÛøªØùœÑù’ÏüÏÿÐÿ‰Ïÿ„Êþ„Çü‚Åü~ÄÿÅÿ€ÅÿÃý„ÅûˆÇü•Óÿš×ÿœ×ÿÖÿØÿÏÿŒÎÿŽÎþ‘Ñÿ™ÖÿŸÕÿ¡Ôÿ¯Ýÿ²ßü¸âøºã÷ÅîÿÉïÿÅêúÊîþÊîþÆéüÉìÿÐñÿÎïÿÑóÿÔöÿÖöÿ×õÿÙ÷ÿÞûÿáþÿàþÿ×÷ÿÇëùÈìÿÅëÿÅéÿÇêÿÉéþÉéþÌïÿËîÿÉîÿÁçú¾äù½çÿ»åþ¶ßûµáü½éÿÁëÿÄìÿÇíÿÈîÿÒöÿÖöÿ×ôÿÔðüÖñüàøÿáøÿÝõÿÛöÿÚöÿÕòÿ»èÿžÒù–ÍôÎúÐÿÓÿ’Õÿ•Ôÿ‘Îý“Íý‘Éø”Íú¦Ûÿ­ßÿ¸äýÂëÿÒôÿÞúþäýÿëÿÿìÿýîÿùìÿýåþÿÎïÿÃéÿ«Üü¡Õúš×ÿ–ÕÿÏÿÎÿŽÍÿ‹Íÿ‹Íÿ‹ÎÿÐÿŒËþŽÌûœÖþ¨Üÿ©Øô½çýÊðÿÔõÿÓóÿÏðÿÆêÿ°ßýŸÖÿ–ÓÿŠÍÿ‰Ïÿ‡Ìÿ„Éÿ|Ãû|Äÿ}ÅÿÅÿ}Ãþ~Ãü€ÅüÐÿ—Öÿ™×ÿ™Óÿ’ÏþŠÎÿŠÎÿŽÎþŽÎü™Óÿ£Øÿ¨Ùÿ´àýºäý¼åû½åþÄêÿÆëþÊëúÎïÿÍñÿÄéüÇêþÑðÿÓðÿÚõþÜ÷þØõûÛøþÜùýçÿÿçÿÿàýÿÛùÿÉíýÃçÿÄèÿÁçþÀäúÇìÿÌñÿÍòÿËïÿÊîüËìûÆéü¾åÿ¾åÿºâüºäýÁëÿÈñÿÆïÿÆíþÊñÿÎòÿÖ÷ÿÏïúÐñÿÏóÿ×÷ÿàüÿÞùÿÞùÿÚöÿÖôþ¹åÿ£Õú™Íô’Í÷‘Îú’ÒÿŽÐÿ‘ÑÿŽÌýŽÌý’Ìü”Îü¡Øÿ¥Ùþ¶ãÿÂìÿÔõÿßúÿåýÿìÿÿéüúðÿüðÿÿèýÿØôÿÑòÿ»äÿ«Üü›Õýš×ÿÐÿÎÿÍþÎÿÏÿŽÑÿŠÐÿ‹ÍÿÏûŸÕû·æÿ¶âûÇîÿÓ÷ÿâýÿãüÿÝøÿÓðþ·áù¦ÜÿšÕÿŒÌü‹ÍÿˆËÿ„Çü~Ãü|Äÿ|Äÿ|Äÿ|ÃÿyÁüw¿ùÄýƒÆý†Åû‹Èþ‹Éü‰ÍüŒÎþÐÿÎý—Ðý¥Ùÿ­Þÿ¶âý»åýÅëÿÉïÿÈëÿËìýÒðûÒòÿÎïÿËîÿÌïÿÓòÿ×ôÿÞõûåýÿãÿÿåÿÿæÿÿèÿÿçÿÿäýÿÞûÿÎïÿ¿äþ½äÿ¾èÿ¿éÿ¿éÿ¾èþÄíÿÃéüÅêüÌðþËðÿÅêÿÄéÿÁçþÂèÿÉïÿÆìÿÂèûÃìþÈòÿÉðÿÐòþËïÿÃìÿÁêÿÊïÿÎïÿ×óþÛöÿÛøþÙöþÊóÿµâÿªÛûŸÕùœÔù‘ÏøŽÍø‘ÏþÍþËýÍü’ÏüœÕÿ¡Öþ²áÿ»çÿÎòÿÖóûÝöûéþÿëÿþíÿÿíÿÿéüÿÞöÿØõÿÇíÿ¹åÿ£Ùý×ÿŽÍù“Ðÿ‘Ëù–Ðþ—ÑÿŽÎüÌÿ‘Ñÿ”ÑýŸÓø»çÿÇíÿØúÿàþÿæÿÿèÿÿäýÿÛ÷ÿÄêÿ¬Þÿ¢Øþ“ÑÿÏÿ‡Éý†ÉþƒÈÿ|Äÿ{Ãþ{Ãþ|Ãÿw¿út¼÷zÀû}ÂûÂúˆÇý‰ÈýˆÌûŠÌüŽÎþÍü˜Ñþ§Ûÿ°áÿ»äÿ¿çÿÊðÿÊðÿÍîÿÐðýÙõÿ×õÿÎîýÎïÿËïÿÏïþÔñÿãúÿèÿÿæÿÿâÿÿâþÿêÿÿêÿÿæþÿßúÿÐðÿ¾æÿ¹åÿ¹åÿ¼èÿ»çÿ·ãþ¼æÿ¿èüÄêýËðÿÊïÿÇëÿÇëÿÃèûÃéüÉïÿÅëþÀæùÂëýÈñÿÅïÿÈíýÇíÿ¾èÿ»åþÆêÿËìÿÖòýÜ÷ÿßúÿÝøÿÎóÿ¾èÿ¶äþ«Þý¥ÚúœÖü™Ôü—Ôÿ‘ÍÿŽÊüËýÌû™ÒýžÓû¯Ýþ¹åÿÊïÿÔòüÙôûæþÿêÿÿìÿÿíÿÿèýÿß÷ÿÛ÷ÿÊïÿ¾èÿ©Þþ¢Úý”Ïù”Ñþ“ÎúÓÿŸÕÿ•Ðü‘Îû—Ôÿ™ÔþžÒ÷½éÿËðÿÝûÿàýÿâûÿäýÿÜøÿÕõÿÄìÿ²ãÿªÞÿ˜ÖÿÑÿ‡ÉýˆËÿ…Êÿ|Àý|Âþ~Äÿ~Äÿv½ûsºøu¼úzÀþ€ÄÿÃÿ„ÇþŠÌü‹ËûËúÌùžÔÿ©Ûþ±ßÿ½åÿÃéÿÌïÿËïÿÚöÿáüÿèÿÿâûÿÞúÿÖöÿÐòþÎîûÔòýàùþæÿÿåÿÿÝùüßøüìÿÿëÿþêþÿäûÿÕñýÀéýµãû­Ú÷°Ýü°Üÿ­Ùü¶áÿÂìÿÈñÿÍôÿÌòÿÔôÿÕõÿÐñÿÌðÿÌñÿÆìÿ¾çû¼åû¿éÿ½çÿ·ãþ³àÿ®ßÿ¯Ýþ½åÿÃçýÓïûÛöÿáúÿÜøüÏí÷ÎðüÌòÿÄïÿ»èÿ¯àþ§ÜþŸÖÿ•Ïý‘ËûŽÍÿŒÌü“ÐüšÔüªÜÿ´ãÿÀéýÒôÿØöÿßûÿåþÿèÿÿêÿÿæþÿßøýÚ÷ÿÊîüÅëþ»éÿ²äÿ¦ÜþŸÙÿ Õý«Ýÿ®ÞÿªÜÿ¥Ùþ¤Ûÿ¡ØÿŸÓø½éÿÑòÿÙ÷ÿÓñüÐðýÏðÿÆìÿÀéÿµâÿ¯ßÿ«Ýÿ”ÒÿŒÍÿƒÄú„Çþ€Åþ}¿û€ÂþƒÇÿÅÿx¿ÿw¾þv½ýw¾ü}Ãÿ~ÄÿƒÈÿŽÎþÏý”Ñþ–ÑýŸÖÿ­Þÿ³àÿÄêÿÉîÿÏðÿÖôþäýÿèÿÿìÿÿìÿÿëÿÿÚöÿÓñûÓñûØöþÚóøàùþáýÿÛ÷úàøüêþýìÿýìÿÿëþÿß÷ÿÎóÿÅîÿ½åþ¼åÿ¹âÿ¶ßÿ»âÿÅéÿÊîþÓõÿÓôýÚ÷ÿÛùÿÕõÿÐòþÊîþÇíÿÁçþ³Ýö´Þ÷²ßü¯Ýÿ Ôû¡Õü£×ü±Þý¿äþÑíûÙôÿâûÿàùþÛ÷ûÚ÷ûÚùþÔöÿÍñÿ¾èþ³áû¥×üšÐþ”Ìû“ÓÿÐÿ“Ðý—Òü¤Ùû­ÞþºäüÌðÿÑóÿÚøÿâÿÿæÿÿèÿÿæþÿÝöúÚóøÔòüÐòþÉïÿ¾èþ³âþ¬àÿ®Þÿ²Þû³ßúµáþ´âÿ©Ûÿ¡ÕüœÒø¸æÿÆìÿÅèþºà÷µãû²áýªßÿ¢Øü›Óø¡ØÿžÕþÊÿˆÉÿ„Åý„Æÿ‚Çÿ…Æÿ„Æÿ€Åÿ~ÄÿzÁÿx¿ýw¾üzÁÿÅÿÅÿƒÈÿ‘Ïþ”Òÿ•Òÿ—Òþ¡Öþ°Þÿ¶áÿÄêÿÊïÿÖøÿÖôüæþÿéþÿîÿÿëÿÿçüÿÛöÿÖóûÕòø×ôúßøüÛôùÜøüäÿÿçÿÿëÿþìÿýìÿÿìÿÿàøÿÎðüËïÿÆëþÄèÿÂåÿÁäÿÆèÿËìÿÑñþÖôüÑï÷ÙöüÛùÿÑñüÏñýÊîþÇíÿÅëÿ¹ãüµÞú±ÞýªÚþ¡ÕüŸÔü Ôû°Ýþ½âýÒïÿ×óÿÛöýÝøÿÝöúâþÿßûÿÙ÷ÿÖöÿÉïÿÁëÿ¬ÝþÓÿ–Îý‘Ïÿ“Óÿ˜Õÿ˜Óû¢×ù©ÚúºäüÉíýÎïþØöÿÜùÿäÿÿèÿÿèÿÿáùûÝöúÚ÷ÿÓóþÈíýÆìÿ²àø¨Úû®Üþ¼åÿ¹ãü¶ßû¼éÿ¥×üžÒùÓù¯áÿ½æÿ¹âþ±Þû¨Ýý¡ÙüžÙÿšØÿ’Ïû•Òÿ—Ñÿ‰Èþ†Çÿ‰ÊÿˆËÿ†Éÿ„Åý„Åý‚ÄþÄý}Ãþ}Ãþ€Æÿ‚Èÿ…ÊÿƒÈÿ‰Êÿ’Ïþ•Òÿ˜Òÿ™Òý Ôû¯Üý¶ßûÃèûÉíýÔõþÛúÿëÿÿíÿÿóÿýîüýìûÿâùÿßøýáúþäþÿçÿÿåþÿáýÿàüÿäýÿéýüêþýëÿÿåüÿÙõÿ×õÿ×õÿÖóÿÔôÿÔóÿÔôÿÖóÿÚôÿÝõÿßöþÜõüÔòüÔòüÊê÷ÈéøÄçúÇíÿÅîÿÀéÿºæÿ¶ãÿ¶äÿ«Ýÿ£×þ¢Öý°Ýþ¿çÿÑòÿÙöÿÛùÿÜúÿÞùÿáúÿàùþàûÿÝúÿÒóÿÉïÿ´ãÿ¢×ÿ›Ôÿ‘Îû”Ñý˜Óû›Òù¨Úû°ßû½æüÉíýÎðüØöÿÜùÿàüýãýþæþþêÿÿèÿÿäÿÿàýÿÔöÿÌðÿºàõ±Ýø¯Ûö·ßø¸àú¶ãÿ®ßÿ ÕýŸÖýŸÔüÑø¡Õü¢Ùÿž×ÿ•Ôÿ‘ÑÿŒÐÿÓÿŽÑÿ‹Íÿ‹Êÿ„Åý…Æÿ‹ÌÿŠÍÿ„Çü†Çý†ÇýƒÆý‚Åü€ÅþÆþÈÿƒÊÿ†Ëÿ‡Êÿ‹Ìÿ“Ðÿ–ÓÿšÓÿ›Ñý Ôû°Ýü·áúÅèûËìûÖôþÝúÿëÿÿîÿÿôÿþòüýïýÿéüÿåýÿçÿÿéÿÿèÿÿçÿÿâþÿÝúþáýÿéþÿëÿþèýÿàùþÕòÿÚöÿÚöÿÚöÿØöÿ×õÿ×õÿÚöÿÜ÷ÿßöþáõþÝôüÔôÿÓóÿÊëúÆêúÅêýÃìÿÂìÿ½éÿ»çÿºæÿ¹æÿ¯àÿªÜÿªÜÿµâÿ¿çÿÐñÿÖõÿ×÷ÿ×÷ÿÜøÿÜ÷þßøÿàûÿÞùÿÒóÿËðÿ¶ãÿ¢×ÿ›Ôÿ™ÔÿšÕÿ›ÕûžÔø«Üü²áû¾çûËìýÎîûØôÿÛøþàüýáûüãûûèýþéþÿåþÿàûÿÕõÿÏðÿÁæù¹ãû¶àù¸âú¸âû³áÿ¨ÜÿœÖþ×ÿŸÖý˜Íõ™Ïû™Óÿ•ÒÿÏÿÏÿ‡Íÿ‹ÑÿŠÐÿ‡Êÿ†Çý…Æþ…Æþ‹ÌÿŠÍÿ„ÇüÏÿÏÿˆÊþ„ÇüƒÉý…ËÿƒÉý†ÉþŠÌÿÌÿ‘Ïÿ•Ïý˜ÒÿÓÿŸÔÿ§Øÿ·ãÿ½åÿÈìüÎðüÙ÷ÿÛøþêÿÿíÿÿ÷ÿÿøÿÿöÿÿòÿÿïÿÿìÿÿìÿþèýþæþÿàüÿÛøüàüÿèÿÿçÿÿßøý×ôüÍîÿÓðÿÕñÿÙ÷ÿÛùÿÝüÿÝüþÜúüÞúþàùÿã÷ÿÝôÿÒöÿÑòÿÊíÿÄéûÂèûÃìÿÀêÿ¹åþºæÿ¾ëÿ½çý¸äý²áÿ­Þü´áþ»ãýÄçûÉêýÊíÿÉîÿÐðÿÓñüØôÿÚõþØóüÒòÿËîÿ´áþ¢×ÿž×ÿœÖþžÕü¡×û§Ùú¶ãÿ»çÿÇìÿÐðýÔðüÛöýáúÿäþÿåýÿçüýéýþêþÿäûÿßøÿ×õÿÒòÿÐóÿÈîÿÄíÿºæÿµâÿ¢ØüŸÙÿ–Õÿ”Óÿ ×ÿœÓü“Ñÿ‹Êÿ‰Èý†Èú‰ËýŒÎÿŒÎÿ‡ÊþˆËÿ†Éÿ‡Èÿ†ÇÿˆËÿ‰ÌÿˆÌýÏÿÏÿˆÊþ„Çû†ÉýŠÍÿˆËÿŠÌÿÍýÍþ“Ðÿ–Ðþ™ÑÿÓÿ Õÿ¬Üÿ¸äÿ¿çÿÉíýÏñýÙ÷ÿÚùþèÿÿíÿÿ÷ÿÿøÿÿöÿÿóÿÿïÿÿíÿÿëþúêþÿåýÿßûþÛøüßûþçÿÿäüþÚõüÕóýÌïÿÏîÿÓðÿÙ÷ÿÛùÿÛýþÜþýÚúùÜøüáùÿâøÿÛõÿÎóÿÍðÿÈíÿÁçú¾äùÁêÿ¿éÿ¸åü¸åü¼æü½æø»åû¶åÿ²áý¶âý¸âû¿âøÁäøÄéüÅêýËìÿÒïÿØôÿÖñüÕðûÒïýÉìÿ±Þû ÖüÖÿ¡Øÿ£Ùÿ§Üþ¬ßþ¼èÿÁëÿÌïÿÕóþ×óþàùÿåüÿéÿÿëÿÿéýþåùúäøùÞõûÜõüÙ÷ÿÕõÿ×úÿÌñÿÈîÿ¸äý±àþšÔú—Ôÿ“ÓÿÐþœÖþžÕþ—ÕÿŠËÿ‰Ëÿ‰Èû‹ËûÏÿŽÎþˆÊüÏÿ‰Êÿ„Çþ„ÇþŠÍÿŒÏÿŠÎÿ‘ÏÿÎÿŽÎþŽÍÿŒÎÿŒÎÿÏÿŒÎÿŽÍÿÏÿ‘Ïÿ•Ðú˜ÑüŸÖý Öü«Üý¾çÿÇíÿÒñÿÕòÿÛöÿáúÿëÿÿïÿÿ÷ÿÿöÿüôÿûñÿÿîÿÿèÿÿçÿÿâþÿÞúûÜøùßùúãûýâúþÞ÷üØôÿÒñÿÉìÿÐñÿÑóÿÒôÿÕ÷ÿØúÿÕ÷ÿÕöÿ×õÿØöþÜùÿÛùÿÎóÿÈïÿÁçú¼åùÁëÿ¼èÿºæÿ·äÿµâÿ°ßý«Þû¶éÿ´åÿ²áý´àûºãÿºâüºâü»åþ»äÿÈìÿÍðÿÐóÿÎõÿÉòÿÀïÿ¹éÿªÜý¡Öþ¤Ùÿ©ÝÿªÝü°ßû·ãüÇíÿÌðÿØöÿÜõüßøýèÿÿéþÿèýþéþÿêÿÿæûþáùýÝöýÛöÿÛ÷ÿÚöÿÒòÿÏñýÃêû¶âý¯ÝþŸÔþšÐþ”Îü•ÏýžÕþžÕü™Òÿ•Ïý’ÏþÎÿÌÿÌÿÌÿÌÿÎÿ‘ÍÿŠÊú‰ËûÏÿŽÐÿÏÿ’Îÿ‘ÍÿÍþÍý‹Íÿ‹ÍÿÏÿŒÎÿÌÿÎÿÎÿ”Ïù—ÐûžÓû Ôù°Þÿ¼æÿÆêÿÐïÿÕòÿÞöÿåýÿìþþïÿþöÿÿøÿüõÿüñÿÿíÿþæþþäýÿáÿÿßûüÝúøâúúçüýåýÿàùÿ×ôÿÑðÿÆéÿÊëúÍïûÑòÿÔõÿÑòÿÉíýËïÿÎðüÒòýÖ÷ÿÕ÷ÿËòÿÆìÿ¾çû»åû½éÿºçÿ¸åÿµáÿ´àÿ®ßÿ©ßÿ¬âÿ¬ßþ¬Ýý´àýµÞü¶ßý¸áý¹åÿ»çÿÅéÿËîÿËñÿÃðÿÀïÿ¸êÿ±äÿ¥Úü¢×ÿ¤ÙÿªÜÿ«Þýµãý½çÿÊïÿÏðÿÚõþÝöúáùûêÿÿéþÿêþÿêþÿêÿÿæþÿäýÿÙôýØóüÙõÿØöÿÒòÿÎòþÄêý¶ãÿ±ßÿ£Öÿ›Ïþ”Ìû•ÎûžÕþ ÖüŸÔüšÐü–Ïü’ÎÿÌÿÎÿÎÿÍÿ‘Îý“ÍûÌøÎú’Òÿ‘ÑÿÎÿ’Îÿ’ÎÿÎÿÎÿÏÿŽÐÿÏÿŒÎÿÌÿÌÿÎÿ•Ðü™ÒÿŸÔþ¢ÖýµãÿÀêÿÈìÿÒòÿ×õÿãüÿìÿÿîþþïýýôþýøÿþ÷ÿýôÿÿïÿþçüýãûÿàüÿßûüâüýçÿÿéþÿãûÿÞ÷üÕóþÏïþÆéýÐñÿÏñýÉíýÈíÿÇíÿÃéÿ»äú¿åüÃéþÈîÿÆïÿ¾èÿ¸äý³ßú¯Ý÷¯Þü¯àÿ¬ÝþªÚþ©Ùý£×üžÔøÕú£Ùÿ¥Ùÿ¤Öû£Ó÷¬Ùú±Üüºãÿ½çÿÊëþÎïÿÈíÿ»åû¹åþ¯àþ¥×øœÐõ£×ÿ¤×ÿ¦Ûý«Ýþ»èÿÁíÿÍòÿÒóÿÛöÿäüþèýÿëÿþêþýíÿÿìþÿëÿÿåþÿáüÿÕñýÐíûÍîÿÎïÿÇìÿÁêþ¶âý­ÞÿªÜÿ ÕÿžÔÿšÐüÒú©Þÿ¯áÿ¬Ýþ¤Øý ÕýšÓÿ–ÐÿËýËýÍü•Îû˜Ñþ›Õý×ÿØÿšÕÿ“Ðÿ”Îÿ”Îÿ’Îÿ’Ðÿ“Óÿ”ÔÿŽÐÿÎÿÎÿ’Ðÿ“Ñÿ˜ÒÿÕÿ¨Ýÿ©Ýÿ³áÿ¿éÿÈíÿÑñüÖôüãüÿêýÿñÿÿõÿÿöÿÿöÿü÷ÿÿõÿÿñÿÿìÿÿêÿÿâûÿßøüáúþçÿÿéþÿäüÿßøýÖóûÒðûÊëúÍïûÍîýÈíÿÄíÿºæÿ³àÿ¬Úü©Úû«Üý¯Ýþ¯Ýþ¬ÝþªÛü­ÞÿªÜý¨Úýªßÿ©Þÿ§Ýÿ¥ÛÿžÖûÔû•Ï÷—ÒþšÔÿœÖÿÓÿ«Ýÿ³áÿ¾èÿÅêÿÏðÿÍðÿÇíÿ·ãÿ´áÿ¦×ÿÑùšÏùŸÖÿœÓú Öú¥Úü´ãÿºæÿÌñÿÔõÿÜ÷ÿèýÿëÿÿëþüíÿþïÿþîÿÿëÿÿÜ÷ÿ×óþÍîÿÄçû½åþ»åþ°Üù®Üý£×ü¡Öþ ×ÿÓÿ Öÿ¢Öý¨Úý¸çÿ½ëÿºæÿ´áþ®ßÿ¨Üÿ¤ÙÿÖÿÖÿÓÿžÓû£Øÿ«Ýÿ¬Üÿ¨Üÿ¤ÙÿœÒþ”Îþ”Îþ’Ïþ‘Ïÿ‘Ñÿ’ÒÿÏÿŽÍÿÎÿ“Ñÿ“Ñÿ–Ðþ™Ñÿ§ÜÿªÞÿ³áÿ½çÿÆëþÒòýØöþåþÿêþÿñÿÿõÿÿöÿÿ÷ÿÿ÷ÿÿõÿÿòÿÿìÿÿêÿÿäüÿàøüáùýéþÿéþÿåýÿàùþØõýÕóûÎðúÐòþÐñÿÇíÿÃíÿ¶åÿ®ßÿ¤Õý Öü¡×ý£×þ£×þ¢Öý¢ÖýªÞÿ«ßÿ©Ýÿ©ßÿªàÿ¨àÿ¥ÝÿÔûžÕþ—Ðý“Ðÿ”Ðÿ•Óÿ—Ñÿ§Üÿ±áÿ¾èÿÆìÿÎòÿÊðÿÄìÿ¶âÿ±ÞÿŸÒÿ˜Îü˜ÑþšÕÿ—ÒúœÔù¢×ù±âÿ¸æÿÊïÿÒóÿÜ÷ÿèýÿëÿÿëþüîÿÿïÿþíÿÿêÿÿÛ÷ÿ×ôÿÊíÿÁçþ¹åÿ¶ãÿ©Úû¤ØýÔûžÔÿž×ÿžÔÿ ×ÿ§Ùü­Þþ¿ìÿÄïÿÄíÿ½çÿ¶äþ®ßÿªÜÿ Õÿ ×ÿŸÔü£×ü¨Üÿ´âÿ³àÿ­Þÿ«Ýÿ Õý–Ðÿ•Ïÿ‘ÎýÍüÏÿÏÿŽÎþÍýŽÌÿÎÿ‘Ïÿ“Íý—ÏþŸÔþ¥Ùÿ²àÿºäúÃèúÑòûÙøýëÿÿîÿÿôÿÿôÿÿöÿÿ÷ÿÿ÷ÿÿòÿÿðÿÿëÿÿêþÿãøýãøýåúÿèýÿçüÿåýÿãüÿÜøüÙöüÚøÿÔöÿÎòÿÀéý¹åþªÜÿ¤Øÿž×ÿ˜Òÿ—Ñÿ”Ïû‘Ìø˜Ñþ›Ôÿ£Úÿ¨Ýÿ­ãÿ¦Üÿ¡Øÿ¡Ûÿ¡Ýÿ“ÎöÓÿÓÿÌÿÊÿÏÿÍÿšÓþ¥Ùÿ´áþ½åÿ¿éÿ¶ãÿ³áÿ§Ûÿ Ôÿ–Ðÿ“Ïÿ’Ðÿ•Ôÿ”ÓþœÔù¡Öø²àÿ¹åÿÈíÿÎïÿÜ÷ÿèýÿéüÿîÿÿðÿÿíÿÿíÿÿãüÿÚ÷ÿÔõÿÁéÿ¹åÿ±ãÿªÞÿ—Íù”Ìû•Ïÿ—Ñÿ™Óÿ¡Øÿ¥Ûÿ¬Û÷³áùÈïþÌðüÎðüÊîþÄêý´àû¯Þü¤Öù Ôù¥×ü«Ýÿ²âÿºæÿ¼èÿ´áÿ°Þÿ¨Üÿ•Ïÿ•Ïÿ‘ÎýÍüÎÿÏÿŽÎþŽÎþÍÿÎÿ‘Íÿ“Íû–ÏüÒü¢Öý®Ýû¹ãùÂçùÐñúØ÷üéÿÿíÿÿôÿÿôÿÿõÿÿôÿÿõÿÿñÿÿïÿÿëÿÿêÿÿäùüäùþåúýçüÿæûþäýÿäýÿßûÿÜùÿÛøÿØøÿÑõÿÀéÿ·ãþ¦ØýžÓý”Ñþ’Ïþ“ÐÿÍúÊ÷”Îü—Ðý Öÿ¢Ùÿ¦Ûÿ¥Ûÿ¢Ùÿ×ýœØý”Ï÷šÐüžÔÿ”ÐÿÎÿÏÿÍÿšÓÿ£Øÿ¯Ýþµáþµãý±ßÿ­Ýÿ£ØÿÓÿšÓÿ—Óÿ“Ñÿ“Óÿ“ÒýžÔú¥×ú³âÿºæÿÈíÿÎïÿÛöÿâùÿçüÿìÿÿíÿÿìÿÿêýÿßøÿÔôÿÌñÿºæÿ²àÿ©Þÿ¤Ûÿ“ËúÍü’Îÿ”Ñÿ–Óÿ ×þ§Ýÿ°ßùºäúÌòÿÒóüÑòûÎïþÉîþ½çÿ¶äþ§Øù¤Öù§Ùü¬Þÿ±âÿ¼èÿ½éÿµâÿ°Þÿ§Ùþ”Ìý”Ìý’ÌüÍüÍüÍüŽÎþÍþÍþÌþÍü–Ñû™Òý Õý¤Øý¯Þü½çýÆëýÑñü×õýåþÿëýýñÿÿòÿÿñÿÿîüüïýþëýýêþýêÿþêÿþíÿÿìÿÿíÿÿíÿÿêÿÿçÿÿçÿÿäÿÿãþÿÝúÿØõÿÑòÿÀåÿ¶âÿ¢ØþšÓþ’Ïþ–Ôÿ˜Öÿ—Ôÿ”ÑþÍú’ÍùÔý¡ÖþŸÓú ÖüŸÔü˜Òú˜Óû—Òü˜ÏøÓÿ™Ñÿ–Ðþ“Íý“Íû–ÏüœÓüžÒùžÒ÷¦Öú¦Öú¥×üžÓý™ÏûšÕÿ™Ôÿ—Òþ˜Óÿ˜Óý¡Õú§Øù³àý»äÿÈíÿÎïÿÚöÿÞ÷þâùÿèýÿèýÿçüÿÞöúÓïúÈëþ¿èþ¯Ýþ¥×ü›Ôÿ™ÓÿÌÿ‘Ïÿ’Ðÿ”Ñÿ˜Óÿ¡Ùþ©Þþ¹æûÇîÿØøÿÛøþÜ÷þ×õÿÓõÿÇíÿ¼æÿ­Úû«Ùû­Ýÿ¯àÿ¯àÿµâÿ¶ãÿ³áÿ®Þÿ¤Øÿ”Ìû”Ìû“ÍýÍüÍüŽÌûŽÎüÍþÎÿ’Îÿ’Ïþ—Òü›Ôÿ£Ùÿ¨Üÿ³âÿ¾èþÇìÿÑñüÖôüãüÿëýýðÿÿñÿÿïÿþìüüíýýëýýêþýêÿþëÿÿëÿþëýýëÿþìÿÿéÿÿåþÿãüÿßøýÞùÿÝøÿ×ôÿÏðÿÀåÿ¶âÿ£Ùÿ›Ôÿ“Ðý–Õÿ™Öÿ—Òü”ÏùÍú“ÎúŸÖÿ£Øÿ£Õú ÔùžÒù›ÕýØÿ™ÔüŸÖýŸÖýÓÿšÓþ™Òÿ•Îû—ÍùšÐü™Ðù™Ðù£Óù¦Öú¥×úžÒ÷›ÏöžÕüžÕüœÓúÒúžÓû§×û¬Úû¶âý½åÿÊíÿÏðÿÚöÿßøÿßøÿæýÿèÿÿãûÿÝöýÒðûÇëÿ¾èÿªÚþ Ôû–Ðþ“ÏÿÍÿÎÿ‘Ïÿ“Ðý—Òü¢Øü¬ßþ¾èþÊïÿÚøÿÜøüßøýØöþÕõÿÉíÿ½åÿ®Ûü¬Úü®Þÿ®Þÿ¯ßÿ²àÿ±ßÿ¯ßÿ«Ýÿ¡×ýšÒÿšÒÿ˜Òÿ•Òÿ‘ÏþÎýÍüÍþ‘Íÿ–Òÿ˜Õÿ™ÔüžØÿ¨Þÿ¬áÿ·æÿÀêÿÈíÿÏïüÔòüÞ÷üêþýìÿûíÿüíÿþíÿÿëýýêþýéÿýèÿþéÿÿïÿÿíÿþìÿýéþÿçüÿâûÿÞ÷üÛôûÞ÷þâûÿÚöÿÒñÿÁæÿ¶âÿ£×þœÓü˜Õÿ™×ÿØÿ™Óø•Ñö—Òþ›Ôÿ¥Úÿ§ÛÿªÚþ¨Úÿ¨Ùÿ¢×ÿ ÚÿÖÿ¢Úÿ¡×û Öü¢Öý¢Öý¤ØÿœÒþ›Ôÿ—Ôÿ—Ôÿ¨Øÿ²Þÿ³áÿ®ßý¬Þù°âý±ãþ´ãÿ±Þÿ²Ýÿ¸åÿ¹æÿ¾èÿ¿çÿÇêþËìýÑïú×ôüÚõþÞùÿßúÿßúÿÞùÿÓóÿÆìÿ¼èÿ¦ØýÒü“ÍÿÌÿŽËÿ‘Ïÿ‘Îý”Ïû˜Òú£Øú³äÿÄíÿÎòÿÚ÷ÿß÷ûàøüÞùÿÛùÿÌñÿÃëÿ¶ãÿ±ßÿªÚÿ¨ØþªÚþ¬Üÿ¨Úÿ¤Øÿ¢Öý›ÒùŸÔüÔûœÖþÖÿ–Ñý‘ÎúÍùÍù•ÐüšÕÿœÕÿ ×ÿ¥Úÿ­ßÿ±ßÿ¿èÿÈîÿËðÿÐñÿÕõÿÙ÷ÿåþÿéþÿéþÿêÿþéÿýèþüêþüëÿýëÿýëÿýðÿÿíÿÿéýþàøüÜøüÔòüÒðúÍíúÏïüÐðÿÍðÿÉîÿ½çÿ·ãþªÝü¥Úü¡×ýŸ×ü£Ùÿ¡×ûžÔøŸ×ú¢Úý©ßÿ©ßÿ¨Üÿ¦Úÿ¤Øÿ£×ü£Ùý¥Úú©Ûü²áÿ³áû´àû»çÿµáüªÛû¦Øû£Ûÿ¤Þÿ³áÿÄìÿÈîÿÊîþÊëüÅêúÆëûÉîþÍîýËëøÉðÿÆïÿÆïÿÅîÿ¿èþ¿åüÃçýÍîÿÒòÿØöÿØöÿÓõÿÓóÿÑðÿÁéÿ¸åÿ¡Ýÿ™ØÿÏÿÍþ“Íý’Ïü•ÐüšÑøŸÕû¯Þü¹åÿÉîÿÏðÿÚ÷ÿÚöúÝøÿÚöÿÙ÷ÿÑòÿÈíÿ½æÿ¶áÿ¦Öü¡Ôÿ£ÖÿŸÕÿ ÖÿŸÕÿÓÿšÓþ Öü ÖüŸÖý×ÿ–Ñû”ÏùÍù“Îø–ÑûœÖþ×ÿ¡Øÿ¦Úÿ­Ýÿ°Ýþ½çÿÅëþÉìÿÎïþÒóÿ×÷ÿßûÿäüÿåýÿçÿÿèÿþæÿüéÿýêþýëÿþìþþïÿÿíÿÿéüÿÞ÷üÛöýÖöÿÓóþÎïþÌðÿÍîÿÌñÿÈîÿ½çý·ãü­Þü©Üû©Ûü¦ÛýªÜÿ©Ûþ¤Ùûž×õ¢Øú¨Þÿ©Þÿ¨Ýÿ¤Øÿ£×þ¤Øý¥ÚüªÝü¯Þüµãýºäü½æüÂëÿ½æü°Þø«Úø¥Ûý¨àÿµâÿÈîÿÌïÿÕóþÕóþÏïüÍïûÐòüÔòúÒï÷ÎðúÊðûÈïÿÉïÿÁêÿ¾æÿ½æüÆëþÊîþÏñýÏñýÍóÿÐñÿÍìÿ»âÿ±ßÿ›Ùÿ“ÖÿŽÎþÍþ•Íþ”Îü•ÐúœÓú¢Öû²ßþ»åþÉìÿÏðÿÚùþÚõüÜøÿÛ÷ÿÙ÷ÿÏðÿÈëþ¾æÿ¶âÿ¨Øþ¡Ôÿ¡Õÿ¡×ÿŸØÿ›Ôÿ›ÑÿœÒÿ¢Øþ¢Øþ ×þžØÿšÕÿ™Ôþ–Óÿ™Ôþ›Öÿ×ÿ×ÿ¥Úÿ§Ûÿ­Þÿ±Þý¾èÿÇíÿÉìÿÉêûÌíüÏïüÖóûÚõüÝùýáýÿãÿÿçÿÿæÿÿåÿÿçÿÿèÿÿåøþéüÿçûÿÞùÿÚøÿÕ÷ÿÓõÿÎïþËïÿÍîÿËîÿÆëý¾äùºãù¶ãúµáú¸æÿ½éÿ¾êÿºãÿ´âü¬ÞÿªÜÿ¨Üÿ¨Ûÿ¤×ÿ¡Ôÿ¡Ôÿ¥Öþ©Ûÿ¯àÿ¶âÿ¼æþÈîÿÌñÿÎñÿËðÿÀéÿºäý°áÿ°áÿ¼èÿÍòÿÓôÿÛùÿÜøÿÛùÿ×÷ÿ×ùÿßýÿÞùÿÞúþÛ÷û×õÿÖöÿÎñÿÉíÿ¿èþÁêÿÄíÿÆïÿÆðÿÄëüÆëýÃçÿ°Ûû§Ùú™×ÿ‘ÔÿÍýŽÌý’Ìü•ÏýšÔü¢Øþ¨Üÿ·äÿ¼æÿÊíÿÐðÿÚ÷ýÛ÷ûÚõþÜøÿÙõÿÎîûÌíþÁçþ¹ãüªØú ÔüžÑþšÏû›Ðü›ÐúœÑû¡Öÿ¡Öþ¡Öþ ×ÿÖÿœ×ÿœ×ÿš×ÿ›Öÿ›ÖÿœÖþœÖþ¤Ùÿ§Ûÿ®ßÿ²ßþ¿éÿÉïÿËîÿÊëüÌíþÏïüÔòýØõýÚ÷ÿÞûÿßüÿåÿÿâþÿáýÿâýÿåþÿÞõûáøÿàùÿØôÿÕóýÔöÿÒôÿËïýÉíýÊíÿÍñÿËîÿÄéüÃèûÀéýÀéÿÂëÿÌòÿÍóÿÄèþ½åþ±âÿ­Ýÿ©Úÿ¨Ùÿ¡Ôÿ¡Ôÿ¢Óþ¦Öþ©Ùÿ±ßÿ»äÿÃéþÏòÿÓôÿÔôÿÐñÿÉîÿÂëÿ¸æÿµâÿºäüÌïÿÒóÿÜøÿÛöÿÚøÿÖöÿ×ùÿàþÿáüÿäüÿâúüÛöýÚöÿÑòÿËîÿÃéþ¿èþ¿èþ¾éü¾éü¾çù¿èü»ãý­Ûü¥Úü—Öÿ“ÔþÏÿÍþ”Îÿ—ÒþœÖþ¥Ûÿ¬Þÿ¸äÿ¿éÿÌïÿÑñþÚ÷ýÚöúÙôýÛøÿÙõÿÑñüÐñÿÊîÿÀèÿ¬Úû¤Øÿ¢Õÿ˜ËöšÍøžÒúŸÓû¢ÖþŸÔü ÕýžÕþšÓþœ×ÿžÙÿ™Öÿ™Ôÿ—Òü›Ôÿ×ÿ¡×ý¦Úÿ­Þþ¯Üù¹ãûÅëÿÉîÿÉìÿËîÿÊîþÌíþÏðÿÑòÿÖöÿØùÿÚøÿÓóþÑñüÒòÿÓôÿÙöÿÚ÷ÿØõÿÒòÿÑñþÒóÿÑòÿÉíýÆéüÈëþÏðÿÎïþÍîýÎïþÏðÿÏðÿÕõÿÝûÿÝùÿ×óÿÒòÿ½æÿ³ßüªÚþ¨Ùÿ ÓÿŸÒÿ¡Òý§×ý¯Ýÿ¹åÿÁêÿÏóÿÙöÿÛ÷ÿÝøÿÛöÿØõÿÒóÿÇíÿÃéþ¾äùÉêûÎîûÛöÿÛöÿ×óÿ×ôÿÕõÿØöÿÜ÷ÿß÷ûàøüÝöûØóüÔòýÒòÿÍñÿÇìÿÆëþÅëÿÃìÿ½êÿ¹æý­Úù£Õú Öü”Òù’Ñú‘Ïþ“Ñÿ–Òÿ–Ñý ×þªÞÿ±âÿ»çÿÁéÿÍñÿÒòÿÝúÿßûÿàùÿÝöýÛöýÚ÷ÿÙ÷ÿÏóÿÆíþ³ßúªÜý¥ÙþÒúÔýžÕþÒüœÑûŸÔü ÕýÔý™ÒýšÕÿœ×ÿ–Óÿ–Ñý•Ðú›ÔÿŸÖÿ¤ØýªÜÿ°Þÿ¯Üù·áùÆìÿÉíÿÈëþÉìÿÆéüÆëþÉîÿÍñÿÔöÿÖøÿÓóÿÍïûÉíûÊîþÌïÿÎïÿÏðÿÏðÿÎïþÎïþÎïþÎïþÉíýÇêýÌïÿÔôÿÔôÿÔôÿÖöÿÙ÷ÿØöÿÚöÿÝøÿÞ÷þÜõüÙõÿÄíÿºäý®ÜþªÚÿŸÒýŸÒý¡Òû«Ùû±ßÿ¼èÿÂèûÒóÿÙõÿÚõþÞ÷þàùÿÚöÿ×õÿÌðþÈíÿÅëþËìýÏìúÙôÿÚõþÖôÿÕõÿÕõÿÕóþÙõÿÜõüÞ÷þÜ÷þØóüÕóý×õÿÎîýÊëüÊíÿÎñÿÌóÿÂïÿ¼èÿªØúŸÓúžÖû—Óø“Ñø’Ïû’Ïþ–Ðÿ–Ïú¡×ý­ßÿ²ãÿ½éÿÀèÿÎïÿÒòÿßüÿâþÿãüÿÞ÷üÝöûÝùýÛøþÕõÿÌðÿ¼æþ²ãÿ¬ÞÿÔûÔýœÓü›ÒûÔýœÑù›ÐøœÓü›ÔÿšÕÿ™Ôÿ•Òÿ–Ñý•ÐüšÓþ¡Øÿªßÿ­ßÿ±àþ¶ãÿ»åýÄêÿÇëÿËîÿÉìÿÂæü¾äûÀæýÂèýÉîÿÍñÿÍñÿÇìþÂèû¼åû¼äþ¾æÿ¿èþÀéýÅêüÇìþËïÿËïÿËïÿËîÿÎñÿÐñÿÓóÿÕõÿØôÿÙôýÙôûåþÿèÿÿèýÿæûþâûÿÍñýÄëü´âü¬ÝýžÔú¦Üÿ©Ýÿ³äÿ½ëÿÃîÿÊïÿÏïüÔñùÙò÷ãøýäùþáøþßøÿÖôþÑñüÊïÿÎïÿÑñþÚõÿÚõÿÖóÿÐñÿÌíþÑñÿÕòÿÑñþÑóÿÕõÿÖöÿØöÿÙ÷ÿ×óþÖòþÔðüÒîüÒòÿÄîÿ»çÿ¬Üÿ¤Ùÿ¤ÚÿŸÕ÷Óõ™Ð÷—Ðû—ÐýÔû¤Øý­Þÿ²àÿ½æÿÂèÿÎïÿÓóÿÜùÿçÿÿçÿÿéþÿêýÿéþÿçÿÿÝøÿØöÿÉïÿºèÿ²áÿ¦Üÿ¥ßÿ¡ÛÿœÕÿ—Òü˜Í÷›ÐúžÔÿ›Ôÿ—Ñÿ–Ðþ”Ñþ•Ïý”Ïû™ÒýŸÖÿªßÿ­ßÿ³âÿ¸åÿ¼æþÄêÿÆêÿÈìÿÇëÿÀæý½åþ½åþ¾çýÄêýÉîþÍòÿÅëÿÀéÿ·ãüµáþ²Þûµßø·áù¿èüÄêýÈíÿÊïÿÌïÿÌïÿÌïÿÍîÿÏñýÓóþ×óþÙôýÜõüèÿÿêÿÿèýÿçÿÿæÿÿÔöÿËðÿ¶äü¬ÝûÓù£Ûÿ§Ýÿ²äÿ»éÿÅîÿÉîþÐðýÒï÷ØñöæûþéüÿæþÿäýÿÚ÷ÿÕóýÊïÿÐñÿÔôÿÚöÿØôÿÑñÿÍîÿÆéüÍìþÏïþÍñÿÎòÿÒóÿÕõÿÙ÷ÿÚøÿÚõþØóþÕðûÑëøÒïýÅîÿ¼èÿ®àÿ©ßÿ©ßÿ¥Úù¦Ùø ÔùÒú™ÏûŸÔü©Ýÿ¬Ýþ°ßýÁéÿÂèÿÍîýÑñüÚ÷ýçÿÿêÿÿëþÿìþÿìþþëÿÿåýÿßúÿÎòÿ¾èÿ³àý¦Üÿ§Þÿ¥Üÿ¢ÙÿœÖþÒüŸÔþÓÿ˜Ñþ”Îü•Ïý‘Îû’Ìú“Îú™Òÿ ×ÿ«Ýþ­Þþ¶ãÿ»éÿ¼æþÃéÿÄèþÅéÿÅéÿÀåÿ½æÿ¼åÿ½åÿÃéþÉîÿÊïÿÅëÿÀêÿ¸åÿ±ßÿ©ÛüªÛû¯Þú»èÿÁêþÇìþÊïÿÏòÿÍðÿÊíÿÌïÿÍñÿÔôÿØöÿÞùÿàüÿãüÿâûÿáúþæÿÿåÿÿÙúÿÎòÿ´àû©Úû›ÔÿœÕÿ ×þªÝü²áûÂíÿÌóÿÒôÿÓðøÖòöçÿÿêÿÿéÿÿçÿÿÚ÷ýÕòúÄéûÌïÿÔôÿØöÿÕòÿÎïÿÊíÿÃçýÆéýËëÿÕöÿÔõÿÖôÿØöÿÚ÷ÿÙöü×ôüÖôÿÒòÿÍîÿÏðÿÆìÿ¼æÿ¨Úÿ¬àÿ²äÿ¾ìÿÀìÿ¶ãÿ­Þÿ£×ÿ§ÛÿªÚþ°Þÿ´áþ¾æÿÃéþÌíüÏïúÙöúèÿÿíÿÿòÿÿòÿÿôÿþôÿþìþÿçüÿÔñÿ¿åüµßø­Ûü¬Ýý¬Ýþ¨ÚûŸÔö§Üÿ¥ÚÿŸÕÿ›Ôÿ–Ðþ”Îü’Ïü“Íû“Îú˜ÑþŸÖÿ¨Ûú­Þþ´áþ¸æÿ½çÿÂèÿÁçþÅéÿÅéÿÃèÿ¼èÿ½æÿ½çÿÁçüÃèûÂæüÀèÿ½æÿ±ßÿ®Üþ¦Üÿ¨Ýÿ®áÿ»éÿ¾èÿÄéüÈíÿÌïÿÈëÿÅèþÉîÿÊïÿÏñýÑñüØõýÚ÷ýÙõùÙõùÙõùÞûÿßüÿÔñÿÊëþ´áÿªÜÿ•Íþ–Ðÿ˜Ðÿ£Õú©×ø½çÿÆïÿÏóÿØöÿÝøÿæþÿêÿÿèÿÿäýÿØõûÓðøÅêüÉîÿÐñÿÕòÿÑñÿÎñÿÌðÿÂêÿÅéÿËîÿÕñÿÕðûÚõüÞùÿáýÿÞûÿÚøÿÏóÿÈîÿ¿éÿÂêÿÅèû»ãü¨Øü®ÞÿµãÿÁêÿÅëþ¼æÿ´áþ¬Þÿ­ßÿªÛü´áÿºæÿ¾æÿÄèþÎïþÑñüÛøüéÿÿïþÿõÿÿ÷ÿÿøÿü÷ÿûñÿÿìþÿÛõÿÇêþÀåÿ¸âû¹ãû½çÿ»çÿµáþªÞÿ¦Ûÿ¡×ÿž×ÿ–Ðþ‘Îû”Ñþ’Ïþ“Íû—ÐýÔý§Ùú­Þþ³àý¶äþ½çÿÂèÿÁçþÄêÿÅëÿÅêÿÀéÿÀêÿÀèÿÁçþÁçüÀæýÀêÿ¼èÿ±Þÿ­Ûý¨Ýÿ©Þþ°ãÿ½ëÿ¿éÿÁçúÆëþÈíÿÅèþÃæüÈîÿÉðÿËðÿÍñÿÔôÿØöÿÙöþÛøþÚ÷ýàýÿàÿÿÐñÿÃçý­Ýÿ¦Ûÿ˜Òÿ—Ñÿ™Ñÿ£Õú¦×ø»çÿÄïÿÏóÿÜúÿáüÿêÿÿëÿÿèÿÿäýÿØõûÒðøÅêüÇìþÍîÿÏïþÎîýÌïÿÊîÿÀèÿÂçÿÇíÿÒîüÓîùÞ÷þåüÿéÿÿæÿÿÛùÿËðÿÂëÿµäÿ·äÿ·ßù°Ûû¡Òú¥ÖþªÛü¸äý¿èþ¹ãü³ßü¯Ýÿ®Þÿ®Üþ´áÿºæÿÃéÿÆéýÐðýÕóýÝùýìÿÿðþÿõÿþøÿÿøÿü÷ÿûõÿÿðÿÿàøÿÍîÿÇêþÆìÿÇíÿÆïÿÄìÿ¹ãü²äÿ«ÝÿŸÔüÔý–Ðþ”Ñþ“Ñÿ’ÐÿÍü”Îü˜Ñþ£Ôü¨Øþ²àÿ³àý¹æý¾çý¿èüÁêÿÂëÿÂëÿÆìÿÃéþÂèýÀéÿ¾èÿ¾êÿ»éÿ¹çÿ±ßù®Ýù¨Ù÷´ãÿ»éÿ¾èÿ¿çÿÀæýÂèÿÀæýÀæýÁæÿÃîÿÃîÿÅîÿÄíÿÉíÿÎñÿÑòÿÖôþÛøþßûüÚùþ¸åú«Ýøœ×ÿ•ÓÿÌÿ–Îÿ™Íü¡Óø§ÙúµäÿÀêÿÌïÿÞùÿâùÿëÿþíÿþëÿÿåþÿÜúÿÔôÿÁåûÉìÿËîÿÈëÿÇêþÉìÿÉîÿÁêÿ·ãü»çÿÍîÿÕòÿçýÿíÿÿîþþíýýà÷ýÎñÿÃíÿ¥ÙþŸÖÿ—Ñÿ–Ðÿ•Ïý—Ðû—Ñù­ãÿ²æÿ²âÿ°Þÿ°Ýþ°Ýþ´ßÿ»äÿ¿çÿÅêýÌíþÓðøÛôùèýþïÿþôþýöüü÷ýýøÿþøÿÿöÿÿïÿÿèýÿÜõüØóüÏïüÐñÿËïÿÊíÿÈîÿ¶èÿ­ßÿŸÔüžÕþ–Ðþ’Ïü‘Ïÿ‘ÏÿÍü•Ïý˜Ñþ Ôû¦Øý²àÿ³àýºçþ¾çý¿èüÅëÿÆìÿÇíÿÅëÿÅëÿÄêÿ¿èþ¿éÿÀìÿ¹çÿ¶äþ²áý±àþ¬Û÷¶ãÿ»éÿ½çÿ¿çÿÃéÿÃéþÃçýÄêÿÄêÿÀéû¿èúÃéüÂèûÇìÿÍðÿÎïÿÑòûÖôüÙöúÒóú²àø§Øø—Òþ‘ÏÿÌÿ–ÐÿšÐþŸÓú¤Ùû³âÿÀêÿÉìÿØôÿÞ÷üëÿþíÿþíÿÿçÿÿÝúÿÖôÿÄéüÉíÿÊîÿÆêÿÃçýÅéÿÆìÿ½åþ²Þù¹åÿÈëþÓðþåýÿìÿÿðÿÿïÿÿâùÿÍðÿÂêÿ¤ØýžÕþ”Îÿ‘ÍÿÍú“Îø–Ðø§Þÿ¬ãÿ¬àÿ«Ýÿ«Ûÿ¬Úü±Þÿ¹åÿ¾èÿÅéÿÊëüÕñüÞ÷þëÿÿðÿÿóÿýôýüõþýøÿÿøÿÿôÿÿïÿÿéþÿàùÿÜ÷þÕñÿÖóÿÍîÿÊëþËðÿ³åÿ¯áÿ§Üÿ¢Ùÿ”Îü‘ÎûÍþÍþ’Ïþ—Ñÿ™Òÿ Õý¥Ùÿ°áÿ³âÿ¼éÿÀéÿÃéþÆìÿÆìÿÇíÿÃéþÆìÿÅëÿÀéÿÂìÿ»çÿ¶ãÿ´ãÿ²ãÿ¯àþµäÿÂîÿÆòÿÁêÿÃéþÈíÿÉìÿÉíýÌðÿÊïÿÅèûÀãöÄèøÊîüÉë÷ÇéõÔôÿÔõþÕöÿÏïúÆêúªÜý Öü’ÒÿŒÐÿŽÑÿÎý•Îû›Ðú Õý¬Þÿ¹åÿÈíÿ×õÿÛ÷ûêþýëþüîÿÿëÿÿâùÿÛóýÈíÿÃéÿÁçþÀæýÁçþ¼äþ¸áý¬Øõ®Üý´âÿÁåûÌìûßúÿåýÿìþþîÿÿæýÿÏóÿÃìÿªÛûŸÕû“Ïÿ’ÎÿŽÌýËúÌø’Ïü–Ñý•Îù•ÎùŸÔþ¥Öþ«ÛÿµäÿºçÿÅëÿÈëþÚöÿäýÿîÿÿðÿýòÿÿóÿÿóÿÿôÿÿôÿÿñÿÿïÿÿéüÿâúþÝõùØòÿÖòÿÐíýÏîÿËîÿ¯áÿ­ßÿ¦Ûÿ¡Øÿ”Îü’ÏüÍþÍþ“Ðÿ—Ñÿ—ÒþžÕþ¢×ÿ­ßÿ±àþºæÿÀéÿÃéþÅëÿÅëÿÅëÿÅëÿÆìÿÅëÿ¿çÿ»çÿ¹åÿ·æÿ·æÿ³äÿ°áÿ³àýÀìÿÆðÿÃéþÄêýÊîþËïýËïûÏñýÍñýÍîÿÉèúÍíüÓóÿÎïøÊëôÙúÿÙúÿÙùÿÐðýÄéü¦ÚÿœÓúŽÐÿŠÐÿŠÐÿŽÍù’Íù™ÏûÒþ§Ûÿ³áûÅìý×õÿÙõùèüûëþüñÿÿíÿÿæûÿÞõýÉîÿÀæý½ãú¾æÿÀèÿ¹âþ²Þû©Ö÷«Ûÿ¯ßÿ¿åúÊëúÜùÿâùÿéýþìÿÿåþÿÐôÿÅîÿ¬Ýû Ôù’ÐÿÎÿÍýŠÊúˆÈøÍûÎýŽËøÌùšÓÿ¡Öþ¨Úÿ²ãÿ¹æÿÃéÿÈëÿÛ÷ÿåþÿîÿÿðÿýñÿÿðþþïÿþðÿÿðþþîþýìþþêþÿéþÿâúüÖñüÔðþÑîþÒñÿÉìÿ®àÿ¦Øû›Ðø›Òû•Ïý’ÏüÍþŽÌý“Ðÿ—Ñÿ–Ñý ×ÿ¤Ùÿ­ßÿ¯àÿ¹çÿ½çý¿èüÄêýÄêýÅëÿÁçþ½æü¾çý¿çÿ¹ãü¹åÿºèÿ·æÿ²áý²áýÀêÿÇíÿÈîÿÄèøËìûØöÿÚøÿÙøýØ÷üÜûÿÜøÿÛ÷ÿÜøÿÚ÷ÿØõùÚùüØúüÙùÿØøÿÌíÿÁåÿ¢Öþ–ÌøŒÎþ‰Ïÿ†ÍûÏû‘Îú•ÎûšÐþ¡Öÿ¯ÞüÁêþÒòý×ôúêÿÿíÿÿõÿÿõÿÿðÿÿèùÿÌíþ¾çû½æü¿çÿ¾èÿµâÿ´áÿ­Ûÿ¦Öþ¨Ùÿ¾æÿÈíýÙúÿÞùÿçüÿéþÿâûÿÒóÿÈîÿ¯ÞøŸÔô“ÑÿÍþ‘ÐÿŠÌÿ„ÇûˆËÿŽÐÿŽÐÿŒÎÿ“ÑÿšÓþ¢Øþ­ßÿ³áÿ½åþÃèûÙõÿãüÿðÿÿóÿÿîÿÿìþþëÿþëÿþêþýéýþêÿÿêÿÿìÿÿçüýÓïúÒòÿÐôÿÏòÿÇíÿ­ßÿ§ÙüœÑùšÑú’ÌúÍú‘Ïÿ‘Ïÿ’Ïþ•Ïý–Ïü ×ÿ¥Úÿ­ßÿ°áÿ·åý»åû¾çýÀéÿÁêÿÂêÿ¿çÿ¼æþ»åý¸âú·áùºäü¹ãû¹ãû½çÿÀêÿËðÿÒóÿÍïûÍëõÖóûæÿÿåþÿáûüãýþãýþâûÿâúÿãüÿäýÿßûüÞúûØõùÚøÿÚ÷ÿËêþÄæÿ§ÙþžÓûÐþŒÐÿŠÐÿÏýÏû”Îü—ÏþŸÔÿ®ßÿÁëÿÌíüÖôþåýÿëÿÿñÿÿóÿÿðÿÿìûÿØõÿÈíÿÂèû¿èþÀêÿºæÿ´áÿ®ÜþªÚþ­Ýÿ¾èÿÆìÿÓõÿ×õÿàùþãüÿÝøÿÓôÿÎôÿºæÿ«Üü–Óÿ“Ðý‘ÏÿÌÿ‹ÍÿÏÿŽÐÿŒÎÿŽÍÿ–Ôÿ×ÿ¢ØþªÛü°ßýºäúÁæùØóþâùÿïÿÿñÿýìþþèýþéþÿçÿÿåýÿÞöúßùúèÿÿçÿÿãûÿÕ÷ÿÍõÿÅïÿ¾éúµâù®àÿ¨ÚýžÓû›Òû’ÌúÌùÎÿÎÿ‘Îý”Îü•Îû¡Öÿ¦Úÿ®àÿ±âÿ¸æþ¹æý¼æþ¾èÿ¾èÿ¿éÿ¿éÿ»åþ¹ãü¸âú¹áú¼äý½æü¼åû¿èþÆìÿÕöÿ×ôÿÓñûÕð÷Þ÷üçÿÿçÿÿçüýæþþåýýâúþâùÿäûÿåýÿãüÿßûþÙöúÙ÷ÿÚøÿÏìüÉéþ¬Úû£Õú‘ÐüÏÿ‹ÏÿÏý‘Ðü“Îú”Ïû›ÑýªÛü¼æÿÊíÿÓóÿÞ÷üçüÿíÿÿñÿÿîþþìûþÜøÿÍîÿÆéüÂèýÀêÿ¾êÿ¸åÿ°Þÿ®Üþ±ßÿÀêÿÄíÿÎòÿÓóþÞùÿáýÿÜùÿÒóÿÏôÿÁëÿµäÿšÕÿ–Ñý‘ÏþÎÿ‘ÐÿÎÿÎÿŽÎþ‘Ïþš×ÿÔû¡Õú§Øø¬Û÷ºãùÄçûÙôÿãúÿïÿÿñÿýíÿÿçüýèýþèÿÿäüÿÜõúÛ÷úãüÿäýÿáúÿÕùÿÌöÿÀëû·ä÷°Þõ¨Úý¥×úžÓûœÓü–Ðþ–ÓÿÎÿÎÿ‘Îý”Îü•Îû¥Öþ©Ûÿ¯àÿ³âÿ¸æÿ»çÿ¹åþ¶âûµãýµãý·åÿµáüµáú¼æþÃéÿÃéþÈëþÇêýËìýÒòÿÜøÿßøÿâùÿèýÿêþÿíýýïÿþîþýïÿþìÿýéýüèýþéþÿçÿÿáøþÞ÷þÜ÷ÿÞùÿàûÿÚõþÒðûÀéÿ²ßü—Î÷ÌûÎÿ‘Ïÿ“Ðÿ—Òþ˜ÓýŸÖý¨Øü·àþÌðÿÔõÿÛöýãúÿëÿÿíÿÿíÿÿíÿÿäüÿÓñüÎîûÃæù¿åøÆðÿÅïÿ½éÿ·ãü¶âûµáú»åýÈïÿÑòÿÛ÷ÿÜùÿÚöÿÎïÿÊíÿÀèÿ¶ãÿ¡ÛÿžØþšÕÿ•Ïÿ“Ðÿ‘Îý•Ïÿ˜ÑþšÓþ Õý¢Öû¬Þÿ´ãÿ·åÿÃéþÏðÿÞùÿæýÿïÿÿðþþíÿÿëÿÿêÿÿâûÿÞùÿ×ôü×ôüÚ÷ÿÝøÿÛöÿÏóÿÇðÿ¿êý¸åú°Þö¨Úý¤ÖùÒú›Òû—Ñÿ˜ÕÿÎÿÎÿ’Ïþ•Ïý—Ðý¤Öû©Ùý±ßÿ³âþ¸æÿ»çÿ¸äý²àú²àú³àý²ßü´àûµáú¼æþÇíÿÉîÿÎïÿÏïþÓðþ×óÿáúÿåüÿéþÿîÿÿîÿÿñÿÿóÿÿòÿÿòÿÿòÿÿëÿýéÿýéþÿæþÿßöþÜòýÞöÿÜ÷ÿàûÿÞùÿØõýËðÿ¼æþœÑù“ÍûÍÿ’Îÿ•Ïÿ—ÒþšÕý¢Úÿ¬Üÿ¸áÿÊîÿÐñÿÙöþáúÿéþÿìÿÿîÿÿíÿÿæÿÿ×óþÕóþÅéùÂçùÇðÿÆðÿÀêÿ»åû¸âø±Ýø´àùÅëþÌðÿ×õÿÙõÿÙ÷ÿÏðÿÊíÿÀåÿ´àý¢Úÿ ØýœÕÿ–Îý•Ïý—Ïþ™Ñÿ Õÿ¡Öÿ£×ü§Ùú±âÿµãý¶âûÀæûÍîÿÝøÿåüÿðÿÿòÿÿìþþëÿÿæþÿÝùýÜ÷ÿÖôþÖôþÙõÿÛ÷ÿÚõÿÎñÿÇíÿÀéÿ½çÿ²Þùºçÿ³âÿ§Ùü Ôû›ÔÿžØÿ’Îÿ’Îÿ–ÐÿšÒÿÓÿ¥Õû¨Øü®ßÿ²áÿ¶åÿ¶åÿ´áþ¯Þü°ßý±âÿ°ßû»éÿ¼èÿÃéþÑôÿØ÷ÿÚöÿÛ÷ÿÞùÿß÷ÿéþÿêþÿëýÿíýýïýþôÿÿöÿÿõÿþôþÿ÷ÿÿòÿýïÿýïÿÿíÿÿãùÿàöÿÝõÿÔïøÙôûäÿÿàýÿÔöÿÊðÿ¬ÞÿžÔÿÌÿÍÿ‘Íÿ’Ïû•ÓüŸÙþ¨Úÿ°Ûý¿çÿÅêýÖöÿÙöþáúÿåýÿêÿÿêÿÿâûÿÙôýÚöÿÍíúÈéøÌïÿÌñÿÃéüÁêüÂëý±Ýö²Þù»äúÂèûÐñÿÕóþÚöÿÒòÿÍîÿ½âü°Ü÷¡×ûŸÕû¡Öþ Õÿ¡Öÿ¤Øÿ¤Õý¨ØüªÛü°ßýµâÿ½éÿ¾èÿÀéÿÎòÿÕõÿåüÿëþÿðÿÿñÿÿïÿÿáùûÞõûÛöÿ×óÿ×õÿ×õÿØùÿ×÷ÿÖóÿÇêþ¾âú¼âùÂçÿ¿çÿÍòÿÇíÿ³Üø«Øù¤Õÿ¢ÕÿšÏÿ›ÐÿœÔÿžÔÿÒþ£Ôü¥Öþ©Ûþ¬Ýþ°áÿ±âÿ³áÿ¬Ýþ«Ûÿ°Þÿ³àýÀêÿÅîÿÍñÿÔòýÜøÿÜôþÞ÷þäýÿäýÿçüÿëýÿìþÿðÿÿòÿÿõÿÿõÿÿöÿÿöÿÿõýÿöÿþòÿüðÿÿïÿÿçûÿáøÿÖñüÏëöÐîöÚûÿàÿÿ×õÿÊïÿ¬ÞÿÖÿŽÍÿŽÍÿÍÿÍüÏûØÿ£×þ­Ûý¸äýÀêÿÍóÿÕ÷ÿßüÿâýÿçþÿçÿÿÞúþÝúÿÝúÿ×õÿÓñüÍíüËìýÃèûÄíÿÀëþ¶àöµß÷µâù»åýÌñÿÖøÿÚõüÙöþÕõÿ¼åû­Ûõ¡×ý£Ùÿ£×ü¨Úý¬Ýþ²áÿ¶ãÿ²àú°ÞøµáúÁçþÄêÿÊðÿÍòÿÕóýßúÿêüþðþÿòÿÿñÿÿæþþÛöýÖðýÓîÿÕðÿ×õýÙøûØûýÓõÿÍñÿ½ãú»äúÀæûÂèûÈíýÙ÷ÿÒòýÉìÿÈîÿ¹äÿ²Þÿ©Úÿ¦×ÿ¢Öþ¢Öþ¢Öþ ÕýŸÔü¡Õü£×ü¦Ûû­ßÿ®ßÿ§×û§×û²àÿ¼èÿÈñÿÐõÿ×÷ÿÜ÷ÿàùþàøüâúþéÿÿèÿÿèýÿêþÿêþÿíÿÿïÿÿòþþóÿÿõÿÿ÷ÿÿ÷ÿÿ÷ÿýõÿúôÿÿóÿÿìýÿéüÿÜóûÓîõÔïøÚ÷ýÜùÿÔòúÉíýªÜý›ÕýŠÉü†Èü‹Êÿ‘ÏÿÍü“ÐüžÕþ¢Öû­Üú³áû¿êýÇîÿÒôÿÕõÿØôÿÙôÿÚøÿÚ÷ýÜùÿáüÿáüÿÙ÷ÿÒòýÂæöÃìþÃîÿ¾èÿ·àü±Þû¸åÿÈñÿÏòÿÞùÿÖòþÎíÿ»åþ²áÿ¬Þÿ®àÿ±ßÿ¹åÿ¾èÿÄíÿÅîÿÃìÿÂëÿÂèûÈéüÊíÿÐóÿÕöÿÝúÿåýÿïýýóÿýôÿÿîÿÿäþûØõýÓîÿÐêÿÐìÿÙ÷ÿÚùüØüüÏóÿËîÿÆëþÇìþÍñÿÒôÿÛùÿßüÿÚøÿÐòþÎòÿÆïÿÁíÿ´âÿ­Þÿ¦Øû¤Öû¢ÖýŸÔþžÓýžÓûŸÕû¤ÙûªÜÿªÜý¤Ôø§Õù´áÿ¿éÿÌòÿÒ÷ÿÛùÿßøÿäüÿãûÿäüþçÿÿæÿÿéþÿêþÿëÿÿíÿÿïÿÿðþþòþþõÿÿ÷ÿÿ÷ÿÿöÿüöÿüöÿÿöÿÿðÿÿìþÿèûÿà÷ýà÷ýâûÿãüÿ×õýÉíý¨Úû™ÓûŠÉü†Èü‹Êÿ‘ÏÿÎý“ÐýœÕÿ Õý¨Ùú®Ýû¹æý¿èüÉîþÍñÿÐðýÒïý×õÿÚ÷ÿÝúÿäÿÿäÿÿÜùÿÖôþÃç÷ÅëÿÃìÿ¼åÿ´ßÿ±Þÿ¶ãÿÃëÿÊîÿÚ÷ÿÔñÿÈëÿ¸äÿ²áÿ°áÿ³áÿµâÿ¿éÿÄíÿÉïÿÊïÿËðÿÊïÿÇëûËìýÍîÿÐôÿÕ÷ÿÞúþéþÿñÿÿôÿþòÿÿíÿÿæÿýÚ÷ÿÕñÿÐêÿÏëÿ×õÿØ÷üÙûýÓõÿÎñÿÏðÿÐñÿÔôÿÙ÷ÿàûÿáùýäýÿäÿÿßþÿÖøÿÓùÿÅðÿ¾éü°Þö¬Ùø©ÚûžÔÿ›Ñý—Ðû™Óû ×þ Öü¡Õú¦Ôö«ØùºãÿÁçüÎòÿÖøÿÝúÿâúüäùúæûüèýþçÿÿçÿÿæþþéþÿêÿÿìÿÿîÿÿïÿþñÿÿôÿþõÿþôþýöÿüöÿü÷ÿÿ÷ÿÿöÿÿöÿÿõÿÿòÿÿñÿÿîþýêþÿÜúÿÌïÿ§Ùú›ÒûŽÍÿŒËÿŒÊýÍþÍþ“Ñÿ”Ñÿ™ÒÿžÓý¡ÕüªÛû¯Þú¹ãü½åþÃéþÇëÿÑîÿÙõÿÞúÿäÿÿâþÿÚøú×öûÉíûÄêÿ¿äÿ¯Úý®Úÿ²àÿ²àÿ¶âÿ½åÿÇëÿÅéÿ½äÿ´áÿ±ßÿ·ãü¼æÿ¿èþÈíÿÌðþÓóÿÕõÿ×øÿÖ÷ÿÔõþ×õÿÔôÿÔöÿÖöÿÜøüêÿÿðÿýòÿüðÿÿêÿÿèÿÿÝúÿØôÿÑíÿÐíÿÔôÿÕöÿ×øÿÒôÿÏðÿÐíûÒîùÙôûÞ÷þèýÿéýÿæûÿàøüßùúÚùû×ùûÎóûÈîû½æüºáþµâÿž×ÿ™Òý‘Îú’Ïû˜ÓÿžÕþŸÕû­Ûýµàÿ¿çÿÆêúÖ÷ÿÞüÿçÿÿêÿÿèüûêÿþêÿþæþþäþýâüýãýþåýÿéþÿêÿÿëýýëþüñÿýòÿþõÿýõÿþ÷ÿÿ÷ÿÿøþþøþþùÿÿûÿÿùÿÿùÿÿ÷ÿþñÿÿÖöÿËðÿ­ßÿ¡Øÿ‘ÏÿŽÍÿŽÌÿ’ÐÿÏÿÏÿÍÿ”Ðÿ™Óÿ›Ôÿ Õý¦Úÿ­Ûý­Üú³àý¸äÿËëÿÒïÿØôÿÞûÿàüÿÜúüÙøýËïýÄéÿ¼ãÿ²Þÿ«Ùý¬Úü±Þÿµáþ¶âý¶âû±Ýú°Ýü²ãÿ³âÿÃéþÇíÿÌðÿÒòÿÖôþÜùÿàýÿÝúÿÚ÷ýÛøþÖôüÓôýÓôýÖôüÜõùèýþíÿþîÿÿìÿÿæÿÿãÿÿÚ÷ýÔòüÍìþÌëÿÌìûÍíúÑñüÑñÿÐïÿØõÿÙõÿÚõþÝöýà÷ýáõþáõþßöüÞ÷ûÛ÷úÙöúÔõüÏñýÅéÿÁæÿ½æÿ¡Øÿ—Ðû‘ÎúÌùš×ÿ™ÒýŸÔü¯Üý·âÿÉïÿÊëüÙúÿßþÿèÿÿèýþêþýêÿþêÿþåýýâüýÜøûßûþãýþçÿÿêÿÿêþýíÿþñÿÿðÿýñÿýôþÿôþÿ÷ÿÿúÿÿüÿÿüÿÿüÿýûÿýûÿýõþùðþþÏïüÀåø¨Úû ×ÿÎÿÍÿÍÿŽÍÿŽÍÿÌÿŽÌÿ‘ÏÿšÔÿœÔÿÓÿŸÔþ¥×ü«Üý°Þÿ´áÿÁåÿÌëÿÒòÿÛúÿÜùýØ÷úÓôûÉíýÁæÿºáÿ¯Ýÿ­Ýÿ°ßý²ßü³áû³áû°Þø®Ýù°ßý´åÿ¸çÿÄêÿÉîÿËïÿÔôÿÚøÿÜ÷þÞùÿÞúþÝùýÜùýÙøýÕöÿÔõþ×õýÝöûçüÿîÿÿíÿÿéÿÿâþÿÛùûÚøÿ×õÿÌíþËìÿÊëþÍîÿÔõÿ×÷ÿ×öÿÚúÿÛùÿÚøÿÙõÿÜôþÜóÿÝõÿÞöÿÞöÿÞ÷þÜ÷þÛ÷ÿÛ÷ÿÕôÿÐðÿÊïÿ®àÿ¢Øþ–ÑýÍú”Òÿ–Ñý™Ðù°Ýþ½æÿÍðÿÏðÿÛùÿÝúÿäýÿçüýéþÿéþÿçÿÿáýÿßûþÛøþÛøþÛøüáúþâûÿæûþèýþìÿþíÿþíÿþñÿÿóÿÿõÿÿ÷ÿÿûÿþûÿþûÿüûÿýøÿþôÿûîþýÓôÿÆëþªÜÿ ×ÿ“ÏÿÍÿ‘ÏÿŒËÿ‹ÊÿŒÎÿÎÿ’Îÿ–Ðÿ—Ñÿ™ÒÿžÔÿ£×ÿ¦ÚÿªÜý¬Þÿ¸áýÂæþÇìÿÐôÿÒôÿÏóÿÌñÿÃìÿ»æÿ·ãÿ²ãÿ²ãÿ·äÿ¸äý·åü¶æý¬âþªßþ«àÿ´åÿ¹çÿÁçþÄêÿËîÿÑñþÓñü×ôüÙöþÚ÷ýÚ÷ýÛøþØöþÔõþÓóþÖôÿÚõþáøþëÿÿêÿÿßüÿÓõþÕöÿÒòÿÒóÿÍòÿÉíÿÅéÿÆêÿÌïÿÑòÿÒòÿÏóÿÎòÿÓôÿÒóÿÔñÿÕñýÖòþÚõÿÛöÿÞöÿÞöÿÜ÷ÿÜøÿÙöÿÒñÿÌðÿ±âÿ¨Úý˜Ñü”Îü“Ñÿ˜ÒÿšÑú°Ýþ¼åÿÉìÿÏðÿÛ÷ÿÜùÿåþÿêÿÿéþÿçÿÿåþÿßüÿÝúþÚ÷ÿÙöþÙöüÜøüßøýâúþæûþëÿþìþþìÿýðÿÿñÿÿôÿÿõÿÿùÿÿùÿýùÿûøÿþöÿýðÿüìþþ×øÿÉïÿ©ÛþÔýÌþÍÿ‘ÏÿŠÉþ‡ÉýŠÌÿŽÎþ’Îÿ”Îþ•Ïÿ™ÒÿŸÕÿ£×ÿ¦Úÿ¨ÚýªÜý¶âý¾æÿÂëÿÊðÿÊïÿÈíÿÅëþ½çÿµâÿ³áÿ±áÿ²ãÿ¸äÿºäý¸åü¶åÿ¬ãÿ¨Þÿ©àÿ²ãÿ¸åÿ¾æÿÁêÿÊïÿÏðÿÐðýÔòü×óþ×ôü×õýØöþÖôüÒôþÒòÿÓóÿ×óþßøÿéÿÿæÿÿ×øÿËïûÎðüÎïþÍñÿÈîÿÄêÿÀèÿÃéÿÈìÿÏðÿÐðýÍñÿËðÿÏóÿÑòÿÐðÿÑóýÑóýÕõÿÙ÷ÿÛ÷ÿÜ÷ÿÝøÿÞùÿÝúÿ×ôüÑóÿ·ãþ¬ÛùšÏ÷•Ðü”ÒÿšÔÿŸÕÿµâÿÀéÿÌïÿÒóÿÛ÷ÿÚöÿàùÿãûÿåýÿâûÿÞùÿÙ÷ÿØöÿÕóþÖôÿ×õÿÙöþÛöÿÞ÷üáùýéþÿëþÿìþÿíÿÿîÿÿðÿÿñÿÿôþýõþýôÿûòÿÿñÿÿëÿþçÿÿÏóÿÂèý§×ûŸÔþ–ÐÿÌÿŽÊþŠÇý†Èü‡ÉýŽÌû–Ðþ–Ðþ–ÐþžÔÿ Õÿ£×ÿ¥Ùþ¥Úú©Üû°âýµãý¹åÿ¿èÿ¾èÿºãÿ·ãÿ²ßþ©Ûü©Ûþ¬Üÿ°Ýÿ¸áÿºáþ¹âþµäÿ¨àÿ Úÿ¡Ùþ­Ûý°Ýü·ãÿ»äÿÂêÿÊïÿÌïÿÏïþÐðÿÐðýÑñþÓóÿÕõÿÓôÿÓôÿÓôÿØôÿÛöÿáüÿÜøÿÉïüÁçúÂåùÈíÿÇíÿ½çýºæÿ¹åÿºãÿ¿èþÌðþÏñûÍñÿËïÿÏðÿÐñÿÏîÿÑöþÒ÷ÿÔöÿÕõÿØôÿØôÿÜ÷ÿÞùÿßûÿÚøúÕöý¾èÿ°Ýú™Îö•Îù’Ðÿ—Ôÿ Öÿ´áÿ½æÿÉìÿÏðÿÙõÿØôÿÞ÷þà÷ýáøþÞ÷þÚõüÕóýÔòüÐðýÕòÿ×õÿÛøÿÜ÷ÿÝöûàùýçÿÿêÿÿëÿÿìÿÿìÿÿðÿÿñÿÿôþýôþýòþüñÿÿîÿÿêÿÿæÿÿÌðÿ½ãø¦Öú Õÿ™ÓÿËÿ‹ÇûŒÉÿŠÌÿ‰ËÿÎú™Òÿ™Òÿ˜ÑþžÔÿ Õÿ£×ÿ¥Ùþ§Ùú©Üû©Ü÷­ßú²áýºæÿºåÿ´ßÿ²ßÿ­Ûý¢×ù£Øú¦×ÿ«ØÿµÞþ·Þý·àÿ³áÿ¤Ûÿ›ÔÿœÓü§ÕùªÖù²ßþµáþ¼äþÆêÿËîÿÎïÿÏðÿÎïþÎïþÑòÿÒôÿÑòÿÏòÿÑòÿÖñÿÙóÿÞøÿÕóþÂéø½æú¾âøÂæüÂèÿ½çýºæÿµâÿµáþ¼åûËïýÏñûÎðüËìûÍíüÐðÿÓðÿÌíþÏðÿÒóÿÐñÿÊíÿÊîþÐñÿÕõÿÛùÿÚ÷ÿÙ÷ÿÅëÿ³ßøžÓõ˜ÒøÒý”Ôÿ—Öÿ©Þþ±âÿ¾èÿÂëÿÎñÿÕöÿÛùÿÛöýÝõÿÓïúÑïúËïýÉîþÍðÿÐñÿÒóÿÙõÿÜ÷ÿÝöýâùÿëÿÿëþÿìÿÿìÿÿìÿÿíÿÿíÿÿïÿÿðþþïýýñÿÿòÿÿïýýéýþÐñÿ¿åú¥×ú¡Øÿ–ÔÿËþŠÈûˆÇúŠÉþŽÐÿ’Ðÿ–Óÿ—Ôÿ˜Õÿœ×ÿ›Õû¤Úþ¨Ýÿ­Þÿ¬Ýþ§Ûÿ¥Ùÿ¥ÙÿªÜÿªÜÿªÚþ¨Úÿ¢ÖýÒúšÏù™Òý™Òý¢Öý©Ûÿ§Ûÿ¤Ùÿ˜Õÿ”Ñÿ–ÐþŸÔÿ¢Õÿ¦×ÿ¨Øü±Þý¿éÿÂëÿÌñÿÍñÿÎïþÎðüÏðÿÎïÿÌïÿÌðÿÎïÿÐíûÖôÿÐðÿÈëÿ´áþ­Þÿ¯Üû·ãÿ¸äÿµãý¶ãÿ°Ýú°Þø·ãüºçþ½çýÄçûÇçüÎïÿÎïÿÎïÿÂäýÁåýÁçþÂçÿ¾æÿ½åþºãùÁçüÐóÿÑòÿÌïÿ¾çÿ±Þý¡ÕúŸÖý™×ÿ—ÕþšÕý¥Úü¬ÝýµâÿÀêÿÅëÿÈíÿÒòÿÙõÿÓïûÏìúËìûÅêýÁçüÄéüÎïÿÓóÿÚöÿÚõþáøþæûÿìÿÿìþÿíÿÿìÿÿìÿÿíÿÿíÿÿïÿÿïÿÿðÿÿòÿÿóÿÿñÿÿíÿÿÝûÿÌñÿ¦×ø›Òù’ÐÿÎÿŽÌÿŠÉþŠÉþ‰ËÿÌÿÎÿÎýÏú•Ðø›Õû£Ùý§Üþ®Þÿ°Þÿ§Ûÿ ÕÿŸÔü£×ü¥Ùþ«ßÿªÞÿ£ØÿœÒþšÐþ“Ðý’Ïû˜ÒúžÓûŸÖÿœÕÿš×ÿ–Óÿ™ÒÿœÑûžÒú§×ÿªÚÿ³àÿÀèÿÂèÿÇìþÊíÿÌðÿËïÿÇêýÈëÿÉìÿÊïÿÌïÿÏñýÑñþÌíÿÄèÿ®Üþ£Ùÿ¦Øû­Ûý®ßÿ³áÿ²àÿ±àþ¯Þü±àü²áýµäÿ½æÿ»åþ¾èÿ¾èÿ»åþºßú·ßù¸áý»äÿ¹åÿ¸äÿ°ÜõµßøÃìÿÇíÿÄéÿ¶ãÿ®Üþ¢Öý Õý×ÿžØÿ£ØÿªÜÿ­Þÿ²ßü¹åþ¿èþÅëÿÐñÿØôÿÖòÿÎîýÊëüÂèý¾çýÅèûÏïüÖôÿÜ÷ÿÞ÷þåúÿèûÿíÿÿìþÿìþÿìþþëÿþìþþìþþîþþîþþðÿÿòÿÿóÿÿòÿÿîÿÿÝùÿÍðÿ©ÚúŸÕû“Ðÿ‘ÏÿÎÿŒËÿ‰ËÿˆÊþÌÿÎÿÎý‘Ðü—Òü›Õý£Ùÿ©Ûÿ°Þÿ±Ýÿ©Ýÿ ÕýŸÓú£×ü¥Úü¦Úÿ¦Úÿ ×þ›Ôÿ›Ôÿ‘ÎûÍú’Ìô—Ìô˜Ïö—Î÷›ÖÿšÕÿÓÿŸÓú¡Òú«Ùý¯ÛÿµáþÂçÿÁçþÆëþÈëÿÊíÿÊíÿÅéÿÅèþÅéÿÈìÿÉîÿÎïþÏðÿÉìÿÁçþªÛü Õý¡Õú¦Øû©Ûþ¯ßÿ­Þÿ¯àÿ­Þþ¯àÿ¯àÿ²àÿ¶åÿ³âÿ´ãÿ¶åÿ±àþ¬Úü¬Úü¬Üÿ­Ýÿ«ÝÿªÜÿ¤Öù£Õø¨Ùú¬Ýþ¬Üÿ£Öÿ¢Õÿ¥Öÿ¦×ÿªÚþ²àÿµáÿ·äÿ´áÿ¯Üû­Ùö»ãýÄêÿÍðÿÐðÿ×ôÿÌíÿÄçû¾äû¿çÿÏïü×ôüÜ÷þåýÿéþÿìþÿìþÿïÿÿïÿÿîþþìþþìþþìþþìþþîþþîþþïÿÿðÿÿïÿÿðÿÿïÿÿåýÿÔôÿµâÿ©Ýÿ‘ÎûÍþÍÿ‹Íÿ‹Íÿ‰Ëÿ‹ÊýÍþ‘Ïþ”Óÿœ×ÿ Öÿ¥Ùÿ©Úÿ¯Üÿ±ÝÿªÚÿ¥×ü¤Öù¨Úû©Ûþ¨Úý¦ÚÿžÕü˜Ñü™ÔÿžÛÿÚÿŸÖÿ Öü¡Õú¡×ýŸÖý£Ûþ§Üþ²áÿµáþ¼ãÿ¿äÿÁåÿÇëÿÇêÿÉìÿÅéÿÆêÿÆìÿÁéÿÀåÿ¾æÿ¾èÿÀéÿÅëþÉîÿÃéÿºäý£×ü™ÒýšÑú›ÒûÔý¢×ÿ¢×ÿ¢Øþ¢Öý¨Üÿ¥Ùþ¥×ü£ÛÿžØýŸÙÿŸÙÿœÖü Ò÷£Õú¦Úÿ§Ûÿ¦Ûÿ¦Ûÿ ÕýŸÔüŸÕû¡×ý¢×ÿÓÿŸÕÿ¨Ùÿ¬Üÿ´áÿ½æÿ¾çÿ»çÿ¸äÿ´àý¬Øó¹áûÂèÿÊíÿÍîÿÐïÿÊëþÄçûÀæýÁéÿÐðûÛ÷ûâûÿêÿÿëÿÿîÿÿïÿÿðþÿðþÿïýþìÿýìÿýìþþìþþìþþìþþìþÿíÿÿìþÿíÿÿîÿÿæýÿØõÿ¶ãÿ¨Ýÿ‘ÎûÍþŽÍÿ‹ÍÿŠËÿˆËÿ‹ÊýÍü‘Ïþ“Òþœ×ÿ¡×ÿ¦ÚÿªÛÿ°Üÿ±Ûÿ­ÛÿªÛü«Üý®ßÿ®ßÿ¬Þÿªßÿ ×þ˜Ñü™Ôÿ—Ôÿ—ÔÿœÓúžÒ÷ ÒõŸÔö¤Úþ©Þþ°áÿ»çÿ¿éÿÈêÿÇéÿÇêþÌïÿÌïÿÊíÿÇìÿÇíÿÄìÿ½çÿ½åÿ»åþ¹åþºæÿ¿èþÅëÿ¾æÿ¶âÿ¡Õü–Ñý•Îû–Ïü–ÏüšÐüÓÿŸÖÿŸÔþ£Øÿ Öü Ôû×ýšÖû›Öþ™Ôü–ÑùŸÔþŸÔþ ×ÿ¡ØÿŸÕÿÓÿšÓÿ™Òÿ—Ñÿ‘Îý’Ïþš×ÿ¡Ûÿ«Ýÿ´áÿÀæýÆëþÆëþÀæû¼åùºäü¾èÿÀéÿÅëÿÌïÿÍîÿÎíÿÍîÿÊíÿÈìÿÊîÿÖôüáúþåÿÿëÿÿìþþïÿþïÿþðþÿïýþîýÿìþþëÿþêþýëÿÿëÿÿêÿÿëÿÿëÿÿèýÿèüÿëÿÿàùÿ×ôÿ¹æÿ¦Úÿ‘ÎûÍÿŽÍÿ‰Êÿ†Éþ‰ÌÿŒÎÿÎý—Õÿ™×ÿ›Ôÿ¢ØÿªÛÿ­Ýÿ®Úý³Þÿµàÿ·ãÿ¹åÿºæÿºæÿ´áþ³âÿ®àÿ£ÙÿÔû™ÓûŸÖý­ßÿ³áÿ±àü°ßû²ãÿ¶åÿ»èÿÊðÿÎóÿÔôÿÖôÿ×õÿÔôÿÒôþÊðýËðÿÄîÿ½êÿ´âü´àý±àþ®ßý®ßý±Þû¸äÿ³àý¯ÝþžÕþ’ÏüËý‘Íÿ‘ÍÿÌû‘Îý›ÕÿœÕÿœÕÿÔýŸÕÿœ×ÿœ×ÿšÕý™ÔüšÕý Õý Õý¢Ùÿ¤Ùÿ¡Øÿ Öÿ™Òÿ—Òþ•ÒÿÎÿ’Ðÿ™ÖÿžÙÿ©Ûü³àýÃéþÇëûÈìüÅêüÃêûÂëÿÁêÿÆêÿÉîÿÑòÿÐðÿÑñÿÐïÿÎïÿËîÿÌïÿÛøÿãüÿæÿÿêÿÿêþÿðÿÿðÿÿðÿÿñÿÿðÿÿìÿÿìÿÿìÿÿíÿÿëÿÿèÿÿæýÿãüÿáúÿáùÿãüÿÜõüÓóÿ»èÿ©Ýÿ”ÑÿÍÿŽÍÿ‡Èþ…Èý†ÉþŒÎÿÎý–Ôÿ˜Öÿ›ÔÿžÔÿ¨Ùÿ¯Ýÿ±Üü¶ßÿ»äÿ¾æÿ¿çÿ¿çÿ¾èÿºæÿ¹çÿ³äÿ«Ýÿ¦Úÿ¢Øü¦Ûý¶åÿºçÿ»çÿ¹åþ¸æÿ¹çþ¿êýÌñÿÒôÿÙ÷ÿØöþÙ÷ÿÖ÷þÓõþÏõÿÍôÿÃíÿ»éÿ²áû±Þý®ßÿ¬Þÿ­ßÿ°ßý´ãÿ°ßý«ÜýÔý‘ÏþŽÌÿÎÿÍÿÍþ‘Íÿ–Ðÿ–Ðþ—Ðý—ÐûšÐüœÖþœÖþ›Õý™ÓûœÓü©Ûþ©Ûþ¬Þÿ­ßÿªÞÿ©ÝÿžÕþšÓþ•ÒÿÎÿ‘Ïÿ˜ÓýœÖþ§Ùú³âÿÆïÿÎóÿÐôÿÌòÿËñþÌñÿÌðÿÑñÿÔôÿÙöÿÚöÿÛ÷ÿÙõÿ×õÿÖôÿØõÿØôÿÞùÿáýÿçÿÿéþÿìÿÿìÿÿìÿÿíÿÿìÿÿêÿÿêÿÿéÿÿêÿÿäýÿàûÿ×ôüÑïúÔòýÖóÿÕóþÓïûÊíÿµæÿ¤Üÿ’ÐÿŠÉüŠÉþ‡Êÿ‡Êÿ‰ÌÿŒÎÿÎÿ”Òÿ–ÓÿšÓÿÔý§Ùü°ßý¸âû½åþÃéÿÄèþÆéýÆéüÆéüÆëþÅêý½æüµáü´àû¶äþºæÿÄíÿÉîÿÉîÿÇíÿÅîÿÅîÿÊïÿÔôÿØöÿÚ÷ýÚ÷ýØ÷üÓôûÐòûÊñÿÃìþµáú®Ý÷¦×÷¥Ö÷£×ü¢Úÿ£Ûÿ¦Ûý¨Úû§Ùü£×ü™ÒÿÎÿ‹Íÿ‹Íÿ‹ÍÿŽÍÿÎÿ”Ñÿ•Òÿ™ÔÿšÓþœÕÿÔýÔûŸÔüžÓû£×þ®ßÿ®ßÿ°áÿ±âÿ¯àÿ®Þÿ¤Øÿ Õý—ÒþÍü‘Îý™ÒýŸÖÿ©Ûþ³áÿÁëÿËñÿÍòÿËðÿÊïÿÌðþÐòþÖôÿØöÿÛ÷ÿÝøÿÜ÷ÿÜ÷ÿÚ÷ÿÙöþÛ÷ÿØôÿÛøÿßúÿäýÿæþÿêÿÿêÿÿêÿÿëÿÿêÿÿéÿÿèÿÿèÿÿèÿÿàûÿÝúÿÑïúËëøÏïüÓôÿÓõÿÌìùÄéü­ßÿ×ýÏÿˆÊþ‡Éý‡Êÿ‰Ìÿ‹ÎÿŒÎÿÐÿ“Ñÿ•ÒÿšÓþžÕü¨Ùú¯Þúºäú¿èüÈëÿÈëþËìýÍîÿÎïþÏðÿÍîÿÅêý¿åü¾ãý¼çúÀéûÉîþÎïþÏðÿÍñÿÊðÿÊïÿÌïÿÖóÿ×õÿØöþØöþ×õýÑñüÎðüÆíþÀéÿ²ßü­Üú§Øù¤Öù Öü×ýŸÙÿ£Ûÿ¢Øü¢Öû Öü—ÑÿÎÿ‹ÍÿŠÍÿŠÍÿŒÎÿÏÿ‘Ïþ“Òþ–Óÿ™ÔþœÖþÔýŸÔþ¡Öÿ£×ÿªÛÿ¶âý¶âý¹åÿºæÿ¸äÿµâÿ«Üý¤Øý›Òû“Îú”ÎüœÒÿ¡Õÿ¥ÖÿªÚÿ²ßÿ¼åÿÂçÿÉíÿËðÿÓôÿÕóýÜ÷þÞùÿàùþãûÿáøþäûÿâûÿßøýßöü×õÿ×õÿ×õÿÛöýÞ÷üÞ÷ûßùúâüýåýÿçÿÿæÿÿåþÿàüÿßúÿÚ÷ÿ×õÿÌìùÄèøÇëûÏôÿÒõÿÎïÿÄíÿ«áÿœ×ÿ‹Íÿ‡Êÿ†Çý†ÉþˆËÿ‰ÌÿŒÎÿÐÿ‘Îý’Ïü›Ñý Öü­Þü¹çÿÆñÿÊñÿÏðÿÐïÿÒïÿÔòýÖòý×óþÖôþÔñÿÏïþÍîÿÌðþÍòû×õýÚ÷ÿÜùÿÛùÿÎòÿÌðÿÍîÿÒïýÓïûÔñÿÒòÿÒòÿÍîÿÈëÿ¼äý¹âþ°Üÿ­Úÿ¨Ùÿ§ÛÿÔû–Ñû–ÔûŸÙÿŸ×ü ÕýžÕþ•ÒÿÏÿŒÍÿˆËÿ‰ÌÿÏÿŽÎþÎý’Ñý—ÕþšÕýœÖþžÔÿŸÕÿ£Øÿ¤ÙÿªÞÿ´áø¶ãú½çÿ¾æÿ¾æÿ½çÿµãý¬Ýý›Òû‘Ïÿ‘Íÿ™Òÿ›ÓÿšÓÿ›Ôÿ¢Ùÿ¨Úû¯ÞúºäúÃìþÍïû×ôúÝöúßøüäüþçùùëþüæøøåúýÞúÿÕõÿÅëþÆïÿÈñÿÈñÿÉïÿÊïÿËïÿÒòýØöÿÛøÿÕ÷ÿÒ÷ÿÍôÿÊñÿÈîÿÈîÿÅëÿÆéÿÇêþÏðÿÕòÿãüÿáýÿÆïÿµãý—ÏôÎúŽÌûŒËþÌÿŽÍÿÏÿÎÿ”Ñÿ•ÐüŸÕû­Þÿ¿çÿÌïÿÝùÿáúÿæýÿæþÿæþÿèýÿèýÿçüÿæûÿâùÿàùÿÞùÿÞúþâþÿÝùýÚõü×÷ÿÔöÿËðÿÁêÿ¼æþ½çÿÀêÿÉïÿÉïÿÉíÿÂæÿ¾äû¾äù¼åû»åþ¸äÿ±ßÿ¬ÞÿœÔù’ÍùŽËø—Öÿ˜×ÿ™×ÿ—Õþ“Îú‘Ëû’ÐÿÎÿÌÿŒËþÌÿÍþÍü•Ðü™ÒýœÒþœÑûžÓý¡Õü£×þ®Þÿµâù·äû½çÿ¾æÿ¾æÿ¾èÿ¸æþ°âýŸÖý’Ðÿ‘Ïÿ•Îû—Ïþ—Ñÿ–ÓÿžØÿ¢Øú§Ú÷²ßö¾çùÍïûØõûÞ÷üáúþäüþçúøîþûèúúæûÿÚúÿÏòÿ»åý¼èÿ¼êÿ½éÿ¼èÿ¿éÿÁêþËïÿÒôÿÖôÿÍòÿÉòÿÃîÿÀêÿÀêÿÂëÿÄêÿÆéÿÊêÿÑðÿÖòÿæûþæÿÿÔøÿÅîÿ¥Ø÷–Ñù’ÏûŽÌýŽÌÿÎÿÏÿÎÿ”Ñþ–Ñý¡×ý®ßÿÃéÿÏðÿâúÿèûÿéþÿéÿýéÿýêþýêþýìÿÿìÿÿéþÿæþÿæýÿäüþçÿÿâûÿÝøÿÖöÿÒóÿÉîÿ½çÿ·ãþµâÿ¶äþ½çÿ½çÿÁèÿ¿çÿ½åþ»äø»äø¼æþ¹åþ´áÿ­àÿœÔù“ÍûËü’Òÿ–Öÿ™Øÿ˜×ÿ—Òþ•Ïÿ‘ÏÿÎÿÌÿŒËþŽÍÿŽÌÿÍþ”Îü—ÐýšÐüÒüžÓûŸÓú¤Öû¬Ýþµäÿ·äÿºæÿ¼åÿ¾æÿ¿çÿ¸æýµåü¦Üþ—Òþ”Îü–Ìú–Ïü˜ÑþšÓþžÕþ¦Ûý°áÿ¼éÿÃìÿÌðÿ×õÿÝúÿßüÿßûÿáùûéýþåúÿàøÿËîÿ¿äþ¦Õñ§ØöªÛù¯Þü±àü³ßø¹ãûÈîÿÍðÿÍîýÄçúÂçú¼âõ»áôÂçúÅêýÇêýÍîýÑñÿÙõÿÜôþçüýèÿÿãÿÿÙúÿµáú©Þÿ¡Øÿ’ÏþÎÿÎÿÎÿÎý”Ñþ˜Óÿ¥Ûÿ«Üý¾æÿÇêþÖòþàøÿêÿÿëÿÿìÿÿíÿÿíÿÿìþþìþþêþÿéþÿéþÿêÿÿèýþáùýßøýÕóýÐðûÅéù¾äû¼äýºäý·ãü³áû±Þû³Þþ¶áÿ¶âý·äû·äû·åÿµäÿ®àÿ«àÿšÔü’ÎÿŽÍÿ†Èü‡ÉûÐý‘Ñÿ“Ðÿ“ÏÿŽÍÿ‹ÍÿŠÌÿ‰ËÿŒÎÿŽÍÿŽÍÿ‘Îý•Îû—ÍûŸÕÿ ×ÿŸÔü¢Öý­Ýÿ²ãÿ³äÿ·äÿ¸ãÿ¾æÿ¿çÿ»èý¹çþ­âÿ¡ØÿœÕÿšÐþ›ÑÿÓÿÓÿÔû¨Ýÿ±âÿ¿éÿÂëÿÍñÿÖöÿÝûÿÞüÿÜúÿßûÿåýÿàùÿÚöÿÃéþ¶ßû£Ôõ£Õø¥×ú©ÚûªÛû²ßü¸äýÉïÿÌñÿÉìÿÄåöÁä÷¿äöÀå÷ÉìÿÌðÿÎïþÔòýÙõÿÞùÿàùþéþÿçÿÿäÿÿÞüÿÁçü²ãÿ¨Üÿ“ÐýÏÿÏÿ‘Ïÿ‘Îý˜Òÿ™Ôþ¦Üÿ¬Þÿ½çÿÅéÿÒïýÚöÿæþÿêÿÿìÿÿíÿÿîÿÿðÿÿîÿÿîÿÿìÿÿìÿÿìÿÿçüýß÷ùßöüØõýÖôþÊëúÃèûÃéþ¾æÿ¼æÿ´ãý±àü°Ýþ³àÿ´áþ´âú´âú²áý®ßÿ¥Ùþ¦Üÿ™Òý‘ÏÿÎÿ†ÇýƒÆúŠÎýŽÐÿ‘Ïÿ‘ÎÿŠËÿ‰Ìÿ‡ÊÿˆËÿŠÍÿÏÿÎÿ’Ïþ•Ðü–ÏüÓÿŸÖÿ Õý£×ÿ®àÿ«àÿ«àÿ±ßÿ³àÿ¼äþ¿èþ½èù½èùµäþªÜý¥Ùþ¢×ÿ¡Öÿ£Øÿ¢×ÿ Ôû©Úû®Ûú´Þ÷·àöËîÿÑòÿÔõÿÑõÿÐôÿÙûÿÙùÿÐñÿÈëþ³àýªÛüŸÖÿÔýÔýŸÕû¢Öû­Ûü´áÿÆîÿÉïÿÆêÿÈéúËëúÑñÿÓóÿÙ÷ÿÛùÿßüÿàùþäýÿéÿÿèÿÿèÿÿèÿÿçÿÿåþÿÒòÿÀêÿ¯àÿ•ÐúŽÎüÏÿÎý–ÐþœÕÿœÕÿ¥Ùÿ«ÝÿµáþºäüÇêþÍîÿÜ÷þäüþèýþìÿÿíÿÿíýüîþýïÿþïÿÿîþþðÿÿìÿýëÿÿçüÿÞ÷þÞùÿÚøÿÓôÿÍðÿÇìÿÅëÿ¸æý¶âû¶âÿ½æÿ¼èÿ·åü¸æý¶åÿ¯àÿ¢ÖûžÕü˜ÒÿÊÿŽÍÿ‰Êÿ…ÈýˆËÿˆËÿ‡ÈþˆÉÿ…ÈÿƒÈÿ‚Çþ„Éÿ‰ÌÿÏÿÏÿ‘Ïÿ”Ñþ–Ðþ™ÒÿœÕÿ¡Öÿ¤Øÿ¬Ýÿ¨ÞÿªÞÿ°Þÿ²ßÿ¼äþ¾çûÁëûÁëûºçþ®ßý«Ûÿ¥Ùÿ¤×ÿ§Ûÿ¦Úÿ¤Öû­Ûü³ßüºâü»áøÉîÿËïÿÍñÿÊïÿÉðÿÓøÿÒöÿÈíÿÀæý«Üü¤ØýšÕÿ™ÔÿšÓþ¡Øÿ¤ÚÿªÛü³àÿÅïÿÉîÿÇëÿÍîÿÑñÿ×÷ÿÛøÿÞúÿßüÿãþÿâûÿæþÿêÿÿéÿÿæÿÿçÿÿåüÿáúÿÎîûÁëÿ²áÿ•ÐúŽÎüŒÐÿ‘Îý—ÑÿÖÿžÕþ¤Øÿ¬Þÿ´áþ»åþÉíÿÌïÿÙöþáúþåýÿëÿÿíÿÿîþýîþýñÿÿðÿÿðþÿîþýîþýðÿÿëÿÿÝôúÞ÷þÝùÿØøÿÓôÿÏðÿÍòÿ¾éü»åý¼ãÿÁéÿÁëÿ½êÿ¿ìÿ½ëÿ·æÿ¨ÚÿÔû™ÓÿŒÉÿŒËÿ‰Êÿ‹ÌÿŒÏÿ‹ÎÿˆËÿ‰Êÿ„Çþ‚ÇþÆýƒÈÿˆËÿŒÎÿÏÿÐÿ“Ðÿ–Ðþ›Ôÿž×ÿ£Øÿ¦Úÿ¬Ýÿ¡Öö¤Ùù°ÞÿµàÿÃéÿÇìþÑõÿÓ÷ÿÅïÿ»åþµàÿ§Ùþ¥×ü§Ùþ­Ýÿ·åÿ·ãÿ»äÿÁçþ¿åüÄéüÉìÿÅëþ¾çû¿éÿÁëÿ¿éÿ´àù°Ýú£ÙÿšÓþ‘ÏÿÎÿ”Ñþ ×ÿªÞÿ¶äÿ¶ãÿÁéÿÆìÿÇëÿÒòÿÙöÿÚøÿÛ÷ÿãþÿãÿÿáúþæþÿëÿÿåúûãûýÚ÷ýÚ÷ÿÕñüÐîùÄçú½éÿ²ãÿ‘Ìø‡Çõ‹ÍÿÍü—ÐýŸÖÿ Õý¨Úÿ¯àÿ¼èÿ»åþÅëÿËïÿÓóÿÛøÿÜ÷þæþÿëþÿðÿÿïÿþïýýòþþóÿÿïýýïÿþðÿÿíÿÿäùþßöüÛöÿÚöÿØöÿÓóÿÒóÿÌñÿÊïÿÅéÿÊîÿÉîÿÊðÿÉïÿÁëÿ¹åÿ«Ùû¡×ý—Ðý“Íÿ’ÎÿÏÿ‘ÐÿÏÿŒÐÿ…Èÿ†ÈÿƒÆý…Êÿ‚Çþ‚Çþ…Èý‰Ëÿ‹Íÿ‘Ïÿ’Ïü•ÏýšÐüšÑú Õý¤Øÿ§Ùþ°âý±ãþ·ãþ¼äþÊëþÎîûÖ÷ÿÖ÷ÿÏóÿÇëÿÀçÿ­Þþ«Üü³áÿ¸åÿ¸äÿ¿éÿÁéÿÃéþÃéþÆëþÉìÿÁçþ»åýµãû²áû²àúªÛû¥ÚüšÕÿ”ÑÿŽÍÿŽÌý”Ñÿ¤Ùÿ­ßÿ»çÿ¾èÿÄêÿÆëþÈëþÐòþÔôÿÚøÿÙ÷ÿÝùýàùþàøüäüþåýÿáùýÝøÿÑòÿÌíþ¿ä÷»áø³àý¬áÿ£Úÿ‘ÎûÍýŽÎþ”Ñÿ˜Ñþ¡Öÿ£×þ®Þÿ³áÿ¾çÿ¿çÿÇíÿÊîÿÎòÿÕõÿÕóýÛöýäüÿìþÿîþþðþþóÿÿôÿÿõÿÿóÿÿíÿÿêüþáöûÝõùÝöýÜ÷ÿÜøÿÙ÷ÿÖöÿÍñýÌðþËîÿËîÿÉîÿÅìýÃêûºäü´àû¬Úû¦Øû ÕýœÒÿšÒÿ™Óÿ—Ôÿ’ÑýÏý„Æú…ÆþŠËÿˆËÿ†Éþ…Èý‡ÊÿÏÿÎÿÍü”Ïû™ÒÿÒúžÔú¥Ùþ«Ýÿ±âÿ¹éÿ¹çÿ»åý¿åüÎíÿÔòýØöþ×õýÒóÿÊìÿÆëÿ²áÿ®Ýû³àý¶âý·áùÂëÿÆìÿÆêÿÆëþÇìÿÉìÿÁçþ¼æþµäþ¯áü¬Û÷¥×øŸÕù“ÐýÍþÎÿÍþ•ÏýŸÓú§×û»äÿÀèÿÉîÿÊîþÊëúÎðüÐòüÖ÷ÿ×õýÚöúÜøüàùýäýÿáúþßøýÛøÿËðÿÅéÿµßø°ÜùªÜÿ¥Üÿœ×ÿÎýÍþÏÿ”Ñÿ˜Ñþ Õÿ¢Öý­Þÿ³àÿ½çÿÀèÿÈìÿËîÿËïÿÒóÿÑñþÙôýâùÿêüÿíüÿñÿÿóÿÿôÿÿõÿÿòÿÿìþÿéûÿâ÷üß÷ûáúÿÞùÿÜøÿ×õÿÓóþÊðûÈîûËðÿÌðÿÍòÿÅëþÁêü¶âû±Þû«Ùû¨Úû§Ûÿ¥Øÿ¡ÖÿÓÿ×ÿ–Ñû‘ÎúˆÈøŠËÿŒÎÿ‹ÍÿŠÌÿˆÊþŠÌÿÏÿÏÿÍü–ÏüœÒÿ Öü£×üªÜÿ®ßÿ¶äÿ¼éü½êýÄêýÉìÿØõÿÝùÿÚ÷ûÙöüÏïþÅçÿÆëÿºéÿµãý°Üõ³à÷¼åûÄêýÊïÿÊïÿËðÿÆëýÈëÿÁçþÀêÿºéÿ³äÿ°áÿ§ÙüŸÕû‘ÏþÏÿŽÍÿ•Òÿ˜ÓÿœÎó¥Óô¼äýÇíÿÕöÿÔöÿÓóþÏôýÎôýÔ÷ýÓôûÖó÷Ú÷ûãÿÿâþÿáüÿÛöÿÓðþÁéÿ¸áý¥Ö÷ŸÓú˜Õÿ“Óÿ‘ÑÿŠÉüŠÉüŽÌûÍü—Ðý¡Öþ¤Øý±àþ¹åÿ¿çÿÅëÿÉìÿÊêÿÄëüËðÿÍñÿÙ÷ÿÞùÿåøþéûýðþÿñýýóÿÿóÿÿðÿÿëýÿêýÿêÿÿéÿÿâûÿÜ÷ÿÛ÷ÿÔòüÎîùÄîúÅìýÉïÿÂêÿÁëÿ¼éþºèÿ°ßû©Úú¥×ú«Üü°áÿ®ÞÿªÛÿ¥Ùÿ¢ØþœÖûšÖû‘Îû‘Ïÿ‘ÐÿÎÿÏÿ‰Èû‰ÈûÍÿÎÿ“Íû™Òÿ Öÿ§ÛÿªÜý¬Ýý¯Ýþµâÿ¿éùÃêûÊîüÏðÿÙõÿÜùÿÚ÷ÿØôÿËêüÀâûÂçÿ¾ìÿ¼èÿ·äû¹ãù¾çûÄêýÉïÿËðÿËñÿÆëþÆêÿ¾çýÁëÿ¼ëÿ·æÿ°áÿ¦ØûÓùÍúŽÎþŒËþ—ÔÿœÕÿŸÑô¨×õÀæýËîÿØøÿÙ÷ÿÚ÷ÿÖ÷þÓöüÕöýÓôûÕòøÚ÷ýàüÿÞúþâýÿÜøÿÏïþ¼åÿ³àÿ¢ÖûžÕþ™ØÿŽÐÿÏÿˆÇú‡ÆùËþÍü˜Ñþ¥ÚÿªÜÿ¶ãÿ¾çÿÃèÿÈìÿÉìÿÉêýÃéüÊïÿÍñÿÛùÿÞùÿãøûçûüïÿÿîþþðÿÿóÿÿñÿÿëýÿêüþêýÿêÿÿÞ÷þØôÿØôÿÒðûËíùÃíýÁêþÄîÿ¸äý¶âûµâùµãû¬Ýû§Ùú¤Øý«Üü±ßÿ­Ýÿ«Ûÿ«Ûÿ¯ßÿ«àÿªÞÿœÒþ–Ðÿ“ÑÿÐÿÏÿˆÇú„ÆúÌÿÍþ”ÎüšÓþ¡×ÿªÞÿ¬Þÿ­Þþ¯Þü¶âýÎêöÏëöÖó÷ÚöúÜ÷þÚ÷ÿÔóÿÍíÿÂçÿ½çÿ»èÿÂìÿÂêÿ½æü½æüÂëÿÆìÿÆïÿÃëÿÆîÿ¾èÿ·ãü·ãü¸æþ¹çÿ¶ãÿ´âÿ©Ýÿ£Ùÿ•Ðú’Íù‘Ëû—Ïþ™Ðù­Ûü¹åÿÏòÿÕõÿãûÿäûÿâõûàøüÞ÷ûÔïøÑëøÑíùÔðüÛøþÛøþÜùÿÖòþËìý²ãÿ«ÛÿŸÔþ›Ôÿ”ÓþŽÏù‹ÎùŒÌüÌÿÍÿ’Îÿ™Òÿ¤ØÿªÜÿ·ãÿ¿æÿÈìÿÌïÿÎïÿÌíþÆìÿËïÿÐòþÛøþáúþãù÷äú÷çýûæÿÿäÿÿëÿþìÿýìþþìþþçûüäùüßøÿÙ÷ÿØõÿÍîÿÇìÿ¿éÿ½æÿ´áÿ²áÿ³àý¶âý¸äÿ©Úú£Øø¦Üÿ­Þÿ±ßÿ¯Ýþ³àÿ¶Ýú¾áýÌðÿÇìÿ²Ýý¤ØýžÕþ‘ÎûÍþ†Éý„ÇþŠÍÿ‹Îÿ‘Ïþ™ÓûŸÖýªàÿªßÿ±âÿ¶ãÿÀåÿÒðûÓñûÙøûÝúþÝúÿÜøÿÑðÿÅèþ¾æÿ»éÿ¹çÿÀêÿÁëÿ¿èþ¾çýÀæûÄêÿÅëÿ¿çÿÂêÿ»åþ±ßù±Þû²áý´ãÿ²àÿ°áÿ§Ûÿ¡Øÿ—Òü”Ïû’ÍùÔýŸÕû³àý¾èÿÎòÿÕõÿåþÿçþÿåøþäýÿàûÿÖòýÓïýÒïýÔòýÙ÷ÿÙ÷ÿÙ÷ÿÑîüÇèû°áÿ¨Øü›Ðü—Ðý‘ÐüŽÎúÍùŽÌûÍÿ‘Íÿ•ÏÿœÒþ§Øÿ­ÝÿºæÿÁéÿÊïÿÏòÿÐñÿÏïþÅêüÊîüÐòüÝúþäþÿåûùæüùéÿýåÿÿâþÿéÿÿêÿÿëÿÿìÿÿèýÿäüÿÝøÿ×õÿÔñÿÌíþÇìþ¼æÿ¹âþ²ßþ³àÿµáþºäý¼æÿ¯Þü¨Ûú©Þÿ¯Ýþ´ãÿ²ßþµâÿ½åþÄèþÐóÿÎòÿ¿éÿ­Þÿ¡Øÿ‘ÎûÎýˆËÿ„Çþ‡ÊÿˆËÿÎÿšÓþŸÖÿªàÿªßÿ´ãÿ¹åÿÄèÿÙ÷ÿÚøÿâÿÿäÿÿàÿÿÞüÿÊíÿ¿åü±Ýø³âü´ãý²Þù¸áýÀèÿÁêÿÁçüÆëþÃéþ½âüºßù¯Ûø©Úû¥×ü¥×ü§Ùþ¥ÙþŸÕû›ÕýšÕÿ™Öÿ™Öÿ©ßÿ´åÿ¶åÿ¾èþÄëüÌîøÒóúâþÿäÿÿåþÿÝûÿÙùÿÓóÿÑðÿÓòÿÓóÿ×øÿØùÿÖöÿÍìþÄçûªÜ÷¢ÔõšÏû™Ñÿ™Öÿ”Óÿ•Òþ—Òü—Òü›ÑýŸÔü¤Øý¯Ýþ´áþÁêÿËïÿÓôÿ×÷ÿÖôÿÓñüÌìùÍíøÓñûãüÿçÿÿêÿþêÿþçÿÿáúþÛ÷ûÛøÿÚ÷ÿÚ÷ÿÛöýÚõüÙôýÙõÿÔòýÏïüÌíüËïÿÀéÿºäý´àû·áú·áùÂèÿÅëÿºæÿ´áþ¯àÿ°ßû´ãýµãý¹æýÊïÿÒóÿØöÿÕõÿÏõÿ½êÿ­áÿ“ÎúŽÍùŒÎÿŠÍÿ„Çþ†ÉþÎÿ™Ôÿž×ÿ§Ýÿ©Ûüµâÿ½çÿÎîÿÙöþÚ÷ýâþÿåÿÿäÿÿáÿÿÍîÿÄèþ²Þ÷²âù´ãý±Ýú¶ßûÀèÿÅëÿÆëþÈíÿÆêÿ¾äûºßù®Ú÷©Ùÿ¡Õý Ôû ÔûŸÔüžÕü›ÖÿšÕÿ—Ôÿ—Öÿ­âÿºéÿ¼êÿÄíÿÊïÿÒôýÕöýÞûÿÞûÿÝúÿÕõÿÓóÿÐïÿÑðÿÒñÿÒòÿ×÷ÿØùÿÖöÿÎíÿÅêý¬Þ÷¤×öœÑýÓÿœÖÿšÔÿ›ÖÿžØþ ×þ¢Øþ¥Úü¬Ýý³àýºäýÄéüËîÿÔôÿÙ÷ÿÚøÿÙõÿÔòýÓïúÖóûäýÿèÿÿéÿýçÿÿæÿÿàüÿÞùÿ×õÿÔôÿÓóþÕóýÔòüÔðûÖòýÓñüÑñþÐñÿÐñÿÆìÿ¾æÿ¹ãü¹ãû¹âøÆëþÊíÿÁéÿ¸äý±àþ°ßû±àüµãý¹æýËðÿÖöÿÛøÿÚ÷ÿÖøÿÅðÿ³åÿ”ÏùÊ÷ŠÌÿ‹Ìÿ„Çþ†ÉþÍý–Óÿœ×ÿ¥Ûÿ§Ùú´áþ¾æÿÐðÿçÿÿçÿÿêÿþëÿþçÿýåÿÿ×õÿÏîÿÄêÿ¼éüºéý¹åÿ¹ãüÃéþÉîÿÐñÿÔõÿÔõÿÎñÿÇëÿ¼åÿ²âÿ¥Úÿ¢×ÿžÓý›ÒûŸÖÿ Úÿœ×ÿ—Òú›Ùÿ²áÿ¿çÿÀéÿÊîþÐñÿÕõÿÔôÿÎïþËìýÉìÿËïÿÊîþÍíÿÏïÿÐìÿÏìü×õÿØöÿ×ôÿÑðÿÊïÿ¶êÿ­àýÒþšÎþ“ËþŸÕÿ¢Ùÿ«àÿ°ãÿ¶åÿ¸æþÀêÿÆìÿÉìÿÎîùÔòýÙôýÚõüÜøüÞ÷üåþÿßøýáùýèÿÿëÿÿèÿÿæÿÿàüÿÛøÿÚöÿÏôÿÍôÿËðÿÌðÿÌîúÌì÷ÏíøÓñüÖöÿØøÿÕõÿÊíÿÄéüÁçþÀæû¿ä÷ÌíÿÏðÿÇëÿ¾æÿ±Þû°ßýªØù´áþ¸äýÊîþÕóþàùÿáúÿÚ÷ÿÈíÿ¸çÿ—ÑùÊö†Åø„Åû‚ÇþƒÈÿ‡ÉûÍü•Òÿ¡×ý¤Öù±Þû½åþÒñÿèüýìÿÿíÿüíÿúìÿüêþüâûÿÚöÿÍîýÉðÿÈòÿ½çÿ½åþÈëþÎïþÖôÿÙ÷ÿÚ÷ÿÔóÿÍîÿ¿äþ±Ýÿ§Ùþ¦Øý¨Ùÿ¨Üÿ§Ûÿ¥Ûÿ£Ùý¡Öø¢×ù´ÜöÆéÿÈëÿÐïÿÒòÿÔóÿÐñÿÃèÿ½äÿ±Þÿ´Þö¸á÷ÄêÿÉíÿÏîÿÏîÿÔòýÖôÿÕòÿÍìÿËïÿ¶êÿ©ÞýœÑû˜ÌûšÎþ¥Ùÿ¬Þÿ¶äüºçþÅîÿËñÿÍñÿÒòÿ×õÿÜ÷þÝöûäüÿåýÿæþÿêÿÿêÿÿéþÿéþÿçÿÿèÿÿâûÿâþÿØöþÏïüÌìûÄêýÁìÿÆíþÈíÿÍïûÎîùÒðúÕóû×óþÚöÿÚøÿÓóÿÍîÿÆëýÎñÿÑõÿÓóÿÒñÿÊíÿÁçþ°ÝüªÚþ§×ÿ°Þÿ¶áÿÊíÿÓðÿÝõÿß÷ÿÚöÿÆëþ²áýœÓú–ÑûŽÎþŒÎÿƒÈÿ„ÉÿŠÍÿÐÿ’ÐÿœÓü Ôù´áÿ¾èÿÐñÿèûÿëÿÿëÿûëþøìÿûêþüåüÿÝøÿÐðÿÌðþÊñÿ½çÿÁçüÍîýÓóþÛøÿÞùÿßúÿÙöÿÒòÿÄèþ´Ýû¬Úû¬Úû¯àÿ²ãÿ¯àÿ¯àÿ®ßÿ®Ýû®Ýû½áùÏïÿÔóÿØõÿØõÿÔóÿÎñÿ¿èÿ¶ãÿ§Øÿ©Øö­ÛõºãÿÀçÿËíÿÌïÿÏïþÎïþÍîÿÆéÿÅêÿ±äÿ©ÞþœÑû˜ÍùÐýªÜÿ°Þÿºäü¿èüËðÿÍñÿÑñüØôÿÛöýáùýãûÿèýÿéþÿéþÿëÿÿíÿÿéýþæûüæþÿèÿÿÝøÿÝúÿÑñüÇëûÅèûÁçü¾çûÂéúÈíÿÐòþÑñüØõýØõûÙôýÜ÷ÿÜùÿØöÿÓóÿÍñÿÑõÿÓ÷ÿÓóÿÒñÿÈìÿÀèÿ¯Þü¬Þÿ¥Öÿ­ÝÿµâÿÇëÿÐïÿÛóÿÝõÿÚöÿÃèû¯ÞúÓù™ÓûÐþŽÐÿ„Éÿ…ÊÿŠÍÿÏÿ’Ðÿ—ÐûžÔúµãÿ¼èÿÎñÿÛöÿàûÿåÿÿåýýêÿÿéÿÿáùÿÜöÿÑðÿËïÿÊïÿÆìÿÉîÿØöÿÝúÿåýÿêÿÿëÿÿáüÿÚ÷ÿÎîûÅèû¿åü¼åû¾æÿ¾èÿÁéÿÃëÿÇíÿÊîÿÈìÿËìýÖóÿ×ôÿØôÿÖôÿÍðÿÅëÿ¯Ýþ¦Úÿ™Óÿ–Ñù—Óø¡Öþ¨Ùÿ¶ãÿºæÿ½çÿ½êÿ»çÿ´áÿ°Þÿ§Üü§Ûÿ¤×ÿ¢Õÿ«Ýÿ²áý·äûÃéüÈëÿÏîÿØôÿÝøÿåüÿéþÿìÿÿëÿÿìþþìþþìþþìþÿîÿÿêþÿçüýáúþÝùýØöÿÔôÿÈíý½ãø¼âùÀæûÀåøÆéüÎïþÚøÿÜøÿÜ÷þàùýàùþÝöûÛôùÜ÷þÚøÿÔöÿÏðÿÎïþÏïþÊëü½ãú·ãü¬Ýþ¨Üÿ¥Úÿ¨Úÿ¬ÝýÄêÿÈëþÕóþÙ÷ÿÖöÿÀæù³áû¤ØýŸÖýÎý‹ÍÿÆÿ‚Çÿ…Èÿ‰ËÿŒËþ”ÎüšÓþ±ãÿ·æÿÈîÿÖôÿÜúÿáþÿáýÿåþÿåþÿÝ÷ÿÙôÿÐñÿËîÿÉîÿËðÿÏóÿÝûÿãÿÿêÿþëÿþëÿÿãüÿÜ÷þÔòýÐðÿÈëþÆëýÆëþÅëÿÉíÿÍðÿÎñÿÏðÿÏîÿÑñþ×õÿÖôþ×óþÔòüÈìü½æú§Øù¡×ý–ÓÿÐüÐü•ÒþÓÿªÛÿ­Þÿ®Ýù°âý°áÿ­ßÿ©Ûÿ¥Úü¥Ùÿ¥Ùÿ¤Øÿ¬Ýþ³áùºäúÅêüËìÿÐíÿÚõÿáúÿéþÿìÿÿíÿÿíÿÿíýýíýýïÿÿíÿÿíÿÿìÿÿéþÿàùýÚõüÕõÿÒôÿÈïÿ¼åûºâûÂæüÃèúËìýÐðýÛ÷ÿÞùÿâûÿæÿÿæÿÿáúþßøüÜøüÛøÿÔôÿÌíüÊëúÍîÿÈéü¸àù·ãþ«Ýþ¦Úÿ¦Ûÿ¥Úü©Úú¿èþÆêúÕõÿØùÿÕ÷ÿÀêú´âü¥Úü Øý‘ÏþÏÿÆÿ€ÅþÆý‡Èþ‹Êÿ‘Îý–Ñý§Ûÿ­Þþ¿éÿÇêýÏóÿÖøÿÔõþÑòûÑñüÑðÿÎïÿÈìÿÄêÿÄêýÊîúÐòüàüÿçÿÿìÿüíÿüìÿþéþÿçÿÿãÿÿÚ÷ýÖôþÔôÿÔöÿÔõÿÍîÿÖöÿ×÷ÿØôÿÛõÿÜùÿßüÿÞûÿÛùÿÖôþ¾ãõ´Þô¢×÷×ý‘Ñÿ‡Íÿ‡Íÿ‹ÍÿÎÿ˜Òÿ›ÔÿšÒ÷˜Ðõ™Ð÷Öÿ›Ôÿ ÔûŸÓú©Ýÿ®àÿµäÿ½çý¾çùÊëüÏîÿØóÿÜ÷ÿäüÿíÿÿîÿÿïÿþñÿÿîüýïýþòÿÿòÿÿñÿÿíÿÿêþÿâùÿÝøÿÑñüÎïþÍòÿÄêÿÀéÿÊíÿÐñÿ×÷ÿØöÿÞùÿâþÿãüÿåÿÿçÿÿéþÿéþÿÝöûÛöýÔôÿÌíþÊëüËïÿÊíÿ¾æÿ»çÿªÛü§Üþ¡×û§ÜüªÝúµàóÁæöØùÿÛüÿÕ÷ÿÅïý¼éÿ­ßÿ£Ûÿ‘ÑÿŽÐÿƒÈÿ‚Çÿ„ÇþˆÊþŒËÿ’ÐÿÍú˜ÏöŸÔö²àúÃèûËðÿÐôÿÍñÿÎòþËñüÅêúÅêüÂèû¿èüÆìÿÑñü×õÿãÿÿéÿÿêþýîÿÿîÿÿìÿÿêÿÿåÿþÞ÷ûÚõüØõýÔôÿÔõÿÔõÿÕõÿÖöÿÙ÷ÿÛøÿàûÿßúÿÝúÿÚøÿÒóÿ·ßø®Ûø¢Øþ›ÔÿÌÿ‡ÉýˆÊþÎÿ’Ðÿ”Îþ”Îü–Ïú–Ïú–Ïú™ÔÿœÕÿ Öü¡×ý©Þÿ¯âÿºèÿÁçüÅêüÎîûÑîüØôÿÛöýçÿÿíÿÿñÿÿñÿýõÿÿîüüïýýóÿÿðÿÿðÿÿíÿÿëÿÿäøÿßõÿÚôÿÖòÿÎïþÅéùÆìùÎðüÔòýÜùÿÞúýàúûÞúûåÿÿâþÿæÿÿíÿÿêþÿÜ÷þÛ÷ÿ×ôÿÈéüÂãöÌðÿÊïÿÃìÿÁëÿ¶âÿ¯Ýÿ«Ýÿ§ÙüªÛü´ÞöÀåøØöÿßûÿÝûÿÌîúÄêÿ«ÜüÓ÷ÏÿŒÏÿ…Êÿ‚Çþ…ÇûÎÿÎÿËý”Ìý›ÒûŸÓú­Þþ¼áü¼äý¿èþÃéþÁêü½æø¹âô·àô½æü¾æÿÁçþÎðüÑóÿÒîùÔïøà÷ýçüÿèýÿæþþçÿÿâþÿÝùý×óþÔòýÑòÿÑôÿÊíÿÍîÿÐðÿ×õÿÛøÿßøýÛöýØõýÑñþÉêûÀêÿ²ßÿ™Ðù•ÏýŠÌÿ‡Èþ‰ËÿÌÿÌÿ’Îÿ•Òÿ—Ñÿ”Íú”Íø˜Ñü›Õý Öú¤Øý®àÿ²ãÿ¼æÿÂçúÅèûÎîûÏïúÙõÿÞùÿçÿÿíÿÿðÿÿñÿÿðÿüïýýïýýïþÿíÿÿëÿþëÿþêþÿèûÿæúÿá÷ÿÜ÷ÿØöÿÐòüÎòþ×÷ÿÚøÿÛ÷úÝ÷øàúûßûüáþÿãÿÿæÿÿëýýæúûàûÿÞùÿØóÿÌëýÈéúÌðþÌòÿÉðÿÉïÿÀèÿ¶ãÿ®ßÿ¥Ö÷¨×õ·á÷ÈíÿÝúÿâþÿãÿÿØöÿÎóÿ®ÜýÓù‹ÍÿˆÍÿ…Êÿ‚ÇþƒÅùŒËþŽÍÿ‘Ïÿ“Ñÿ™Ôþ›Õý¦Üÿ¬×ù¯Úüµàÿ¶ßý·àüºãÿ¹ãü·ßù¾åÿÄéÿÂçÿÁçúÅêýËîÿÏðÿÏïü×õÿÙõÿÝúÿáþÿâÿÿ×÷ÿÍñÿÈëþÂèýÃéÿÈîÿÊíÿÌíÿÓðþÖòýÞ÷þÜ÷þÙöþÓóþÌíþ»åþ³áÿ›ÒûÌù†ÉþƒÈÿ†Éÿ…Èý†ÈüŽÍÿ“Ñÿ•Ïý›ÔÿžÔÿŸÖÿ¡×ý§Ùú«Ýþµäÿ¸åÿ¼æþÄêýÇêýÏðÿÐòþÛùÿàûÿåýÿíÿÿîÿÿðÿÿðÿüðÿÿðÿÿìþÿìþÿêýÿéþÿéþÿèýþèýþçÿÿäýÿÙöüÖöÿ×ùÿØöÿÜùÿãüÿäüþâüýàüÿÙøýßüÿäýÿåùúäøùÞ÷ûÝöý×ñþÔðþÓñüÒôþÐõþËðÿÊïÿ¾æÿ·åÿ«Üú©Úø¯ÞøÉòÿÑõÿâþÿæÿÿçÿÿÛùÿÍóÿ¥×ü—Î÷„Åû‚Äþ‚ÄþƒÆý‹ÊÿÎÿÏÿÑÿ‘Ôÿ”Õÿ”Óü×ý¦Òõ©Õø°Ûý¯Úü³Üü¸áÿ½æÿ½äÿ½äÿÄèÿÄéÿ¾çý½æüÄêÿÉíÿÍðÿÒóÿÓóÿÔôÿ×÷ÿØøÿÕöÿËðÿÅëÿ¾æÿ½åþÀèÿÆêÿÉìÿÒòÿÖôÿØóúÛöýÛöýÖöÿÐñÿ¼äþ·äÿœÖþÍú†Éþ„ÉÿƒÈÿƒÆý†ÇýŽÍÿÐÿ“ÐýÖÿ ×ÿ£Øÿ¥Ùþ¬Ýý¯àÿ¸åÿºæÿ¾æÿÅëþÇìÿÏðÿÐñÿÛùÿßúÿäüÿìÿÿìÿÿñÿÿñÿýðÿÿðÿÿìÿÿëþÿëÿÿêÿÿéþÿêÿþêÿþèÿÿåÿþÙõùÚøÿÙùÿØôÿÜ÷þåþÿæþÿáûüÝùüØöþÛùÿßûÿáôøáõöß÷ùßöüÛóÿØôÿØöÿÖøÿÕ÷ÿÌòÿÊïÿ½åþ°Ýú¨Ûø¯àþ´ãýÈòÿ×ùÿæÿÿéÿÿçÿÿ×øÿÄìÿžÒù“Ì÷„ÅûÃýÃýƒÆýŒËÿÏÿÏÿÒÿÔÿ”Õÿ”Óü›Õý±ßÿ®Üý³áÿ¸åÿºæÿ¼èÿÂìÿÅíÿ»àúÁæÿÂêÿ»çÿ½éÿºæÿ¸äÿ»çÿÁëÿÃèÿÄèþÇìÿÊïÿÈîÿÂêÿ½çÿ·ãÿµáþ¹âÿÀèÿÆìÿÐñÿÓóÿÔñùÛöýÞùÿâþÿÛûÿËðÿÁíÿŸÖý“Ðý‰Ìÿ‡ÌÿƒÈÿ‚Èü‰ÌÿÎÿŽÎþ–ÓÿœÓüžÓû§Ûÿ­ßÿµâÿ¶ãÿºæÿ¾èÿÀéÿÅëþÆëýÍîÿÍîÿÖöÿÝøÿáùýëÿÿêþýñÿÿòÿÿíýýìþÿëÿÿèýÿÞöÿÞ÷þÞ÷ûâûøãüøåÿûæÿýÞúýÞúÿÚøÿÙõÿÝøÿãüÿâùÿÜõúØóúÍíøÓóþÚöÿà÷ýåúýäùúâúþÞöÿÚöÿÚøÿ×ùÿÓøÿËðÿÇíÿºãÿ²àÿžÐó¨Úû°ÞÿÅîÿÎòÿáüÿâýÿÛöÿÄèø³ßü–Ëõ“ÍûŠÍÿ†Ëÿ‡ÉÿˆÉÿˆÇü‹ÉüŽÍÿ”Óÿ•Õÿ˜Õÿ˜ÓÿŸÔü¹æÿºçÿºèÿ¼èÿÁëÿÃíÿÀèÿÀæýÁåûÇìÿÈîÿ¾èÿ»çÿ¹åÿ¶ãÿ±Þý¶ãÿ¼åÿ»ãü»äúÃéþÁêÿ¾èÿ¹åÿ±Þý¯Üû´ßÿÂêÿÅêÿÏðÿÐïÿÏìôÚõüÝøÿÞúÿÛøÿÒöÿÇðÿ£Ùÿ“Îú‰Ëÿ†Éÿ†ÉþˆËÿ‹Îÿ‘Ðÿ‘Ñÿ–ÓÿÔý Öü«Ýÿ®ßÿ¶âý¸äÿ¾èÿ½çÿÁêÿÉîÿËîÿÌíþÌíþÏïúÙôýãûÿëÿÿìÿÿñÿÿñÿÿìüüîÿÿçüÿâöýÜ÷ÿØóüÙõùÞø÷ãþùæÿüæÿýàüÿÜøÿÖôÿÑíøÖñúâûÿãúÿ×òûÒîùÍïûÏñý×õÿßøÿß÷ûæûüãûÿß÷ÿ×óþÕóýÔöÿÒ÷ÿÇîÿÀéÿ¸ãÿ«Ûÿ¤Øÿ¥×üªÚþ»ãýÅèþÖòÿÛ÷ÿÖóÿÂæü°Ýþ—Íû‘Íÿ‹Íÿ„Éÿ…Çÿ‡ÈÿÊÿÎÿÎÿ’Îÿ–Ïÿ™ÑÿœÒþªÜÿÅðÿÈóÿÉòÿÅîÿÄêýÅëþÈíÿÇìüÆêøÈìøÉíûÅëÿ¿èþ¶âý³âÿ¬Þÿ©Ûþ«Üý®Ûø±Ýø¼æþ½åþ¾èÿ¼èÿµâÿ®Üý°Ýüºãÿ½åÿÆêÿÊíÿÖôþÛøÿÛøÿÜ÷ÿÙõÿÍîÿÄèÿ©ÙýŸÔþ‘ÏÿÏÿŽÎþÌÿÎÿÐÿÏÿšÕÿŸÖý£×ü­Þÿ¯Þü´àû¸âû¾æÿ¾æÿÅëÿÉîÿÊíÿÍìþÎîýÔòýÚõüäüþêþÿêþýîþýñÿÿìþÿëþÿäøÿßöþÓóÿÏïüÏðùÓðô×õ÷âþÿåÿÿßüÿÕòúÑïùÒðúÖóûßúÿßúÿÕñÿÎîýÇìÿÉîÿÎòÿÚøÿÛøÿàùþß÷ÿÙõÿÔôÿÒôÿÊðýÅïý¿éÿ¸äÿ«Øÿ¥Øÿ¡×ÿ Õÿ£×ÿ±Üþ¸ßüÄæÿÇéÿÁæÿ®Ûü¥Öþ•Ïý‘ÏÿŠÌÿ‡ÌÿŠËÿŠËÿŽÌýŽÌýŽÎþ–ËÿšÌÿ¢Òÿ©ÖÿºåÿÊòþÍõÿÏôÿÊïÿÇêýÈëþËïÿÊîüÌîúÍïùÍïùÈíÿÁçú´àù°ßýªÜÿ£×ü¥×ú©Øö®Ûø¹åþ½æü¾æÿ½çÿ·äÿ¯Ýþ±Þý¶âÿºäýÄêÿÉîÿÓóþÛøÿÚ÷ÿÛöÿØóþÌëýÃæü¬Ùú¤Õý˜Òÿ‘ÎýÍúÍü‘Ïþ“Ñÿ“Ñÿ™Ôÿ Õý£×ü¯Ýÿ¯Þü¶âýºãÿ¿çÿ¿èþÆìÿÊíÿÍîÿÎîýÏïüÖôþÚöúåúýêþÿëÿþïÿþðÿÿëÿÿéüÿà÷ýÞ÷þÒóÿÌðþÎðüÑïùÖôüàýÿâÿÿÝúÿÖóûÒðúÑïùÔòüÞùÿÞùÿÔñÿÎïÿÄêÿÄêÿÊïÿÖöÿÙ÷ÿÛöÿÚõÿÕòÿÏðÿÌðÿÄîþÀëüºæÿµâÿ¥Ôþ ÕÿÕÿŸÕÿ¡Öÿ®Úý´Ýý¼áü¿äÿ·âÿ§ÙüžÒú”ÎþÍÿ†Èÿ†ËÿŒÍÿŽÍÿŽÌûÍüŽÎü–ÊúÍý©Öÿ°Üÿ¿èÿÏïúÑñüÓóþÒòÿÏîÿÏîÿÏîÿÎîýÑñþÕõÿ×øÿÖôþÎðü¿èþ¶äþ©Þÿ£Ùÿ¢Öû§Ùú­Þþ»çÿÁêþÀæû¾çý»çÿ´áÿ±Þý³ßü¶âû¾çûÅëÿÎðüÛùÿÞûÿáúÿÞöÿÔðþÌëý¶Ýú®Úý¤×ÿ ÕÿÓÿ—Ðý–Ñý”Ñþ”Ñý™Ôþ¡×ý¦Úÿ±ßÿ¯Þü³àýµáü»åþ½æüÆëþÎïÿÑñÿÔòýÖôþÛöÿÝöûçüÿìÿÿìÿÿðÿÿìþþêýÿæûþâùÿàøÿÊðýÅìûÅìýÆéüËìý×ôÿ×ôÿÖôþÛùÿÙ÷ÿÏïúÑñüÚöÿÚöÿÒñÿÍðÿ¿éÿ¹åþ¼æüÊïÿÎòÿ×ôÿÖóÿÏðÿÄêýÀéý¸åú²âù«Ûÿ§ØÿœÐÿ•Îû•Ðü™ÒýŸÖÿªÜÿ¯Ýþ±Þû²áÿ«ßÿ Úÿ™Òý’ÏþÌÿÆÿ…ÊÿŒÍÿÌÿŽËø‘Ðü’Òþ Ôû¦Öú´âÿ»çÿÁéÿÔòüÔòüÖôÿ×ôÿÕòÿÓðÿÒïÿÑîþÑñþ×÷ÿÛùÿÙöþÓóþÄíÿ»çÿªßÿ¥Ûÿ£ÙýªÜý°áÿ¼èÿÃìÿÃéþÂëÿ¾êÿµâÿ²ßþ³ßü·ãü¼çúÂëÿÎòþÛùÿÝúÿâûÿáøÿÙóÿÔñÿÀåÿ´ßÿ¨Ùÿ¥Ùÿ¢×ÿœÒþšÓþ—Ôÿ–Óÿœ×ÿ£Ùÿ¨Ýÿ±ßÿ®Ýû°Ýú³ßú»åþ½æüÈíÿÎïÿÒòÿØôÿÙõÿÜ÷þáúÿéþÿìÿÿìÿÿïÿÿìþþêýÿçüÿçþÿãûÿÌòÿÄîþÅëþÄçûÈèýÏîÿÑðÿÔñÿÙ÷ÿÚøÿÑñüÓóþÙ÷ÿØõÿÏïÿÊîÿ½éÿ¶âý¸âúÄêýÉîþÐðÿÑðÿËîÿÁçü¼åû³áø¯Þø¤Õý Óþ›Ñÿ‘ÌöÎ÷•ÐúšÔú§Üþ­Þþ¯Þü¬Ýý¤Üÿ™×ÿ˜ÑüÍþ‰Ëÿ‚Çþ…ÊÿŽÐÿÏÿ‘Îú–Õÿ™Úÿ§Ýÿ­Þþ·æÿ½éÿÄíÿÚõÿÙôÿØóüÙôýÛöýÚ÷ýÚ÷ÿÚøÿÕõÿÖøÿÚúÿÜ÷ÿÚøÿËðÿÂëÿ°ßý¨Øþ¦Øý®ßÿ¶åÿÁîÿÆëþÈíÿÇíÿ¼èÿ¸æÿ³áûºæÿ½çÿÂèýÈíÿÖöÿÜ÷ÿáúÿéþÿéþÿäüÿßúÿÎïÿÂèý²Þû¬Üÿ¦ØýžÒùŸÔþŸÕÿ›Ôÿ¥Üÿ¨Þÿ§Ûÿ«Þý­àý¬Û÷¯Þú·ãü½çýÉîÿÓóÿØöÿÞùÿâûÿçÿÿçÿÿêÿÿìþÿîýÿïýþðþÿðþÿïþÿëÿÿëÿÿßüÿÙ÷ÿÑñüÍîýÎïÿÊîþÌíþÓðþÙöþÛöÿÞ÷üßøýÞùÿÚöÿÌðÿÉïÿµáú¬Û÷«Úøµäÿ½ëÿÆìÿÂèý¾èÿ·ãþ¯Þü¤ÙûœÓú’ÏüÎÿ‹ÊÿŠËÿ‘Ðÿ‘Îû–Ñû§ßÿ«áÿ©ßÿ¥Ûÿ›Ñÿ—ÑÿÌþÎÿˆÊþƒÈÿƒÊÿŒÏÿÏÿ’Ðù¡Ùü§Ýÿ±àþ´áþ»åþ¾æÿÊðÿÕñÿÔñÿÙõÿÝùÿàýÿàýÿÜùÿÛùÿÓóþÑóÿÓóþÚ÷ÿÜøÿÎòÿÇîÿ¸æÿ¯Ýÿ«Ûÿ°Þÿ´ãÿ»èÿÅëÿÆìÿÂêÿ¹åþ¶äþµãý»åý¿èþÇìÿÊíÿÏìúßúÿäýÿåúûçûüéÿÿçÿÿÚøÿÐñÿ½æü°ÝþªÛü§Ùþ¦Úÿ§Üÿ¦Ûÿ¤Ùÿ¨Üÿ§Üü¬ßü¯áü²ßü´âü»åýÀéýËïÿÕóýÙöþàùýãûýçÿÿçÿÿêÿÿíÿÿðÿÿôÿÿôþÿïýþîþþëÿÿëÿÿìÿÿçÿÿáýÿÜúÿÙùÿÒôÿÐòþÕóþàûÿåýÿëÿÿçÿÿáýÿÞûÿÑõÿËòÿµáúªÙ÷¦×÷©Ûþ°áÿ½æú½çý¹åþ´ãÿ­ßÿÔû“ÎúˆÇú†Èü€Åþ|ÁüƒÆý‹ÊýÍü™ÔþØÿž×ÿ›Öÿ•ÏÿÌþÍÿŠÉþ„Çû…Ëÿ‡ÍÿˆÌýŠÊø—Ñù®ãÿµæÿ¸åÿ¸åÿ»åþ½åþÅëÿÍìþÎîýÔñÿØöÿÝúÿÝúÿÝúÿÛùÿÖôÿÑñþÒòýØõýÚøÿÎòÿÈïÿ»éÿ®ÜÿªÚÿ°Þÿ´ãÿ¹çÿ¼æþ½åþ»åþ´âü´âü¶äþ¼æþÀéýÊíÿÍîÿÐíûßúÿãÿÿçüýéýþêÿÿçÿÿßüÿ×÷ÿÅêý³àý°ÞÿªÜÿ«Üÿ©Ýÿ§Üÿ¥Ùÿ«Ýÿ«Þý²áý´ãý¶âý¸äý¾çýÃéþÎïþÙõÿÝøÿãûýçüýéþÿèýþëÿÿðÿÿòÿÿõÿÿõÿÿòþþîüýìþÿìþÿëÿÿéÿÿåþÿàýÿÛùÿÒòýÑñüÖòýÞùÿãüÿéþÿäüüÝùýÜùÿÏóÿÉïÿ¶âûªØù¥Ö÷¦Øý¬Ýþ¼æü¿éÿ¹åÿ³áÿ®àÿÔý•Ðü‹Êÿ†ÉþÄý{ÀûÄý‡Éý‹ËûÎú“Ðý”Ñþ”Ñþ‘ÎýŽÌý‘ÏÿˆÊþ…ÇûˆÎÿŠÐÿŒÎÿŒÌúšÔú²äÿ¸çÿ¹æÿ¸åÿ·ãþ¹ãüÀéÿÃçÿÃçýÇêýÌíþÓóþÖôþ×ôü×óþÕóþÓðþÓïûÔðûÖôþÎòþÊñÿ»çÿ°Þÿ¬Üÿ¬Üÿ­Þþ­ßú¯Þú°ßý¯Þü¯Þü²áý·ãþÀèÿÆìÿÎïÿÐðÿØöÿÛøÿàüÿéÿÿëÿÿêÿþéþÿçÿÿäÿÿ×÷ÿÀèÿºçÿ°Þÿ«Ûÿ¨Úÿ§Ûÿ«Ýÿ±ßÿµâÿ»åý¼æþÁéÿÂëÿÈíÿËîÿ×ôÿÝøÿãúÿçûüçûúéüúëýýíÿþòÿþõÿÿ÷ÿÿöÿÿôÿþóÿýðþþðþÿíýüìÿýêþýçÿÿáúÿÖñúÖòýÙõÿÜ÷ÿÝöýèÿÿçÿýßûþÜùÿÊîþÄêÿ´áþ§×û£Õú¦×ÿ¬Üÿ¸äý»çÿµâÿ¬Þÿ§Ûÿ˜Ñþ’ÏþŠËÿ…Êÿ{Ãý}ÆýÊÿ€ÇÿÄýÃý‚ÃýƒÄú†ÈüŒÎþÏÿŽÍÿ‰Ëÿ†ÈüŠÍÿŒÏÿÍü‘Îú¡×ý¶åÿºæÿ¶åÿ´ãÿ°Þø²àúºäüÀåÿ¿äþÂæüÇêýÒòÿÖôÿ×óþ×óþ×óþÕñýÔðüÔðüÔòýÏóÿÌóÿ¹åþ°Þÿ­Ýÿ«Ýÿ¬Þÿ«Þý­Þþ¬Ýþ«Üý«Üü±àü¶âýÃìÿÈîÿÎïÿÐðÿÖöÿÛøÿÝøÿäüþéþÿëÿþéÿýèÿÿèÿÿÜùÿÆìÿÀêÿ±Þý¬Úü¨Úÿ©Ûÿ­Ýÿ³àÿ·ãþ½æü¾çýÂèÿÃéþÈëþÍîÿÖôÿßøýãûÿéýþêüüêýùìÿýïÿþòÿþõÿÿ÷ÿþöÿý÷ÿÿöÿÿñÿÿðþþïþûïÿüìÿýëÿÿäüÿÙôûØóüÚõþÜ÷ÿÛöÿäüüäýúßüÿÛùÿÉîÿÂëÿ±Þý¤Ôú Ñù¤Øÿ¬Ýÿ·äÿ¹æÿ´âÿ«ßÿ§Ýÿ–ÐþŽÌý†ÉÿƒÈÿ|Äþ}Æý€Ëÿ|ÄÿzÀü|ÀýÃÿÁû‚Åü‰ÍþÏÿŒËþÌÿˆÊþŠÌÿÏÿŽÍù“Îø¤Øýµäÿ¸äÿµäÿ°âý®Ý÷²àú¹åþ½æÿ¼åÿ½ãúÀäúÏðÿÕõÿÛ÷ÿÜ÷ÿÜ÷ÿÚõÿÙóÿÖóÿÕóþÍñýÈðü¼éÿ¯Ýþ­Ýÿ«Ýÿ©Þÿ©ßÿ§Ýÿ¢Øþ¢Öý©Ûþ°ßý»èÿÂëÿÇìÿÎïþÎîýÒôþÜúÿÜùÿÜõùâúþêÿÿèýÿêÿÿêÿÿãüÿÑòÿÈìÿ·ßù°Üù¬Ýþ­Ýÿ¯àÿ¸äÿ½çÿÃéþÄéüÄèþÆéýÑòÿÐñÿÖòýÞ÷üåúÿéýþéýüìÿýëýýìÿýðÿýóÿÿõÿÿôÿþõÿÿóÿÿñÿÿïýþòÿþïÿþìÿýêÿÿçüÿÞ÷üÛôûÖñúÜ÷ÿÝøÿâþÿÞûùÙ÷ÿÕ÷ÿÆìÿ½æÿ«ÙýÐûÐû¡Öÿ£ØÿªÜÿªÜÿ¨Üÿ¢ÙÿŸØÿ“ÑÿÎÿƒÈÿÇÿ‚Êÿ~Éÿ|ÇÿwÁþu¿þu¼þx¿ÿ{Áÿ{ÁüƒÉýŽÒÿŒÎÿÌÿÌÿÎÿ’Ðÿ˜Õÿ›Ôÿ¨Úÿ´áÿ¶áÿ²ãÿ¯âÿ¯áüµäÿºæÿ»çÿ¼åÿ½ãú¿ãùËìûÐðûÚ÷ÿÞùÿßúÿÚõÿØóþ×ôÿÔôÿÌðüÆîú¹æû¬ÚûªÚþ¥Ùþ¢Øü Øû¦Ýÿ¢×ÿ Õý¦Úÿ³âÿ¸åÿÀéÿÅëþÌðÿÎïþÑóýÚøÿÚøÿÚöúßøýèýÿæûÿåúýåýÿãüÿÔôÿÌïÿ½ãú¶àù¯Ýþ¬Ýþ°áÿ¹æÿ¾èÿÄêÿÆëþÅéÿÆéÿÎïÿÏðÿÖôÿàùÿäüÿéþÿëÿþìÿÿíÿÿìþþíÿþðÿýóÿÿðÿÿñÿÿòÿÿðÿÿîþþðÿÿïÿþíÿÿìÿÿèÿÿßøýÜõüÖñúÜ÷ÿÝøÿàüÿÜúüÔõþÐôÿÁéÿ¸ãÿªÚÿ Õÿ Õÿ Öÿ Öÿ Õý¡ÖþŸÖÿ›Ôÿ™Ôÿ‘ÏÿŒËÿƒÈÿ‚ÈÿÉÿ~ÇþzÅþxÂÿvÀÿu¿ÿw¾ÿ|Âÿ|Âþ‚Éÿ‹ÏÿŒÎÿŽÍÿŽÍÿÐÿ’Ðÿ˜ÒÿšÓþ¦Úÿ±ßÿ°Ýþ­ÞþªÝü®ßý¶åÿ¾êÿÀèÿÁéÿÇëÿÉìÿÐðûÔòüßúÿèÿÿèÿÿÞ÷þÚõÿØõÿÓóÿÌîúÅëøºåø°ßý«Ûÿ¢×ÿ ×þ›Õû›Ôÿ ÖÿŸÕÿ¢Öý°áÿ³àý¼æþÀéÿÈíÿËðÿÑóÿÕõÿÙ÷ÿÛ÷ÿÛöÿß÷ÿÝöýÛôùÞõûáúÿÚ÷ÿ×õÿÌïÿÂëÿ°Ýü¨ÙúªÜÿ¶åÿ¹åÿ¿èþÃéÿÆìÿÅëÿÉîÿÌïÿÓóÿÛ÷ÿßúÿäüÿåýÿèÿÿéþÿéþÿéþÿéþÿêÿþëÿÿìÿÿìÿÿêýÿêýÿéþÿæþÿåýÿâúþáøþÞ÷þÚõüÔñùØôÿÚöÿÜúÿÖ÷þÊîþÄêÿµàÿ¬Üÿ¡Öÿ›Óÿ™Óÿ•Ïý‘Îû‘Îý’Ïþ’Ïþ‘ÎýÍþ‰ÈýƒÄúƒÆý‚Çÿ}Ãþ}Ãþ}Ãþ|Äÿ|ÃÿyÃÿv½û|Âþ|ÂýƒÈÿŠÍÿŽÍÿ‘Ïÿ’Ðÿ“Ñÿ“Ðÿ“Íû–Ïü Õÿ¤Øÿ¦ØýªÜÿªÜý¯àÿ´ãÿ¸äÿÀæýÃéþÎñÿÓôÿÚøÿÜùÿâþÿåþÿåþÿàùþÜ÷ÿÒïÿÏïþÎðúÊðûÂíþ³âÿªÚþŸÔüžÕþšÓþ—ÑÿœÔÿÖÿ£×þ¬Ýþ±Þý¸äý¼æþÀéýÅëÿÏðÿÓóÿÕõÿÙõÿØòÿÙóÿÚôÿÜ÷ÿÜ÷ÿÛöÿßøýßøÿÕõÿËðÿ±àü©Úû¥×ü­Þþ³âÿ»åþ¼æþ¾èÿÂêÿÅëÿÇíÿËïÿÔôÿØöÿÛøþÞúþãüÿâûÿåþÿæÿÿãÿÿáýþäýÿãüÿãûÿáøþáøþÜ÷þÛøÿÚ÷ýÙôûÚõþÝøÿÜùÿÚöÿØöÿÙ÷ÿÕ÷ÿÎòþÀæû¸âû«Øÿ¦×ÿ™ÑÿÍüÍüÎýŽÎþ‹ÎÿŠÍÿ‹ÍÿŒËÿŒËÿŒËÿ‡Èþ‡Èÿ†ÉÿÆÿ„Æÿ„ÆÿÆÿÆþ~ÇþzÃú|Ãû|Áú„ÆÿÎÿÍÿ‘Ïþ’Ðÿ’Ðÿ’Ïþ“Íû•Ïý™ÒÿžÔÿ¡×ÿ¬Þÿ­ßÿ²àÿµâÿ¹åÿÂæüÆëþÏóÿÓõÿØöþÚ÷ýàùýàùýäüÿàùþÛöÿÑîÿÎîýÎðúÌòýÆñÿ¸çÿ°àÿ¥Úÿ¡Øÿ˜Óÿ˜Òÿ˜Ðÿ™Òý¡ÕüªÛü¯Üû·ãü¹æý¾éüÃìÿÏðÿÓóÿÔôÿÖóÿ×òÿ×òÿØôÿÚöÿÚöÿÚ÷ÿâúþáøþÖöÿÍòÿ´ãÿ¬Ýþ£×üªÛü±ßÿ·ãþ¶âû¹åþ½çÿ¾çýÄêÿÉíýÑñþÓóþØõýÚ÷ýßúÿÞùÿÝøÿÜøüÛøüÜúüÜøüÛ÷ûÝöûÝöýÞ÷þØõýØöÿ×õýÖóû×óþÛ÷ÿÛ÷ÿÚøÿØöÿÕõÿÒôÿËïýºãù±Ýú¦Öþ¡Ôÿ–ÎÿÍþÍþÏýŒÎþˆÍÿ‡ÌÿˆËÿˆÉÿˆÊþ‹ÊÿŠÉÿ†Çý…Èý…Çÿ…Åÿ„ÆÿÆÿ€Çý€Çý|ÃùÄû~Ãú…ÆÿËÿÍÿ’Ïþ’Ïþ’Ïþ‘Îý‘Îý“Ðÿ™Óÿ›ÔÿÖÿ¨ÙÿªÚþ¯Ýÿ²ßÿ¹åÿÆìÿËïÿÐñÿÑîþÔòýÓñûÙ÷ÿØùÿÛøüÝ÷øÝöûÐíûÏíøÖôþÙ÷ÿÔöÿÉïÿÁëÿªÚþ Ôü™Òÿ•Óÿ”Ðÿ•ÏýšÐüžÓû¨Ýÿ©Ýÿ­ßÿºæÿÁêÿÌïÿÓóÿ×óÿÙñûÚòüÙôÿØôÿØöÿÚöÿÜ÷ÿáúþãüÿÛûÿÑöÿ·äÿ­Þþ ÖüŸÖý ×þ¤Ûÿªàÿ¬ßþ­àý°ßû³áù¾éüÈïÿÌñÿÏóÿÎòÿÌðþËðÿÊïÿÊðÿÇíÿÈîÿÊïÿÍñÿÍñÿÏïüÏïüÑñþÍîýÏðÿÌíþÌíþÎïÿÐñÿÒóÿÍîÿÊëüÀéý¹æý«Üý¤Úÿ–ÐþÌû’ÎÿŽÌûÍû‹Òÿ‰Ïÿ‹ÌÿˆÉÿ‡ÊÿƒÈÿ‚Çÿ~Äÿ|Âþ‚Çÿ€ÅÿÆÿÆÿ‚Çÿ‚ÇÿÆÿÆý€ÅþƒÅÿ‚ÄþƒÅÿŠÍÿÐÿŠÎÿŒÐÿÏÿŽÍÿŽÌÿÎÿ—Ôÿœ×ÿœ×ÿŸÔþ¡ÔÿªÜÿ¯ÝÿµàÿÂçÿÇíÿÎïÿÐíýÒðûÒðûÓõÿÖøÿÛúÿÝ÷øÜõùÔòýÓñûÙöþÛøÿ×õÿËîÿÃëÿ°Þÿ¥Öþ–Ïü’Ðÿ’Îÿ•Ïÿ™ÒýŸÕÿ Ùÿ¤Ùÿ¨Üÿ¸äÿ¿çÿÊîÿÓóÿÙõÿÝôüÝôúÜ÷þÛøÿÚöÿÚöÿÝöýãüÿàüÿØøÿÎóÿ·åÿ®ßÿ¡Ùþ›Õý™Ôþ™Ôþ×ÿ¥Ûÿ§Üþ«Üü¯Þú¸åüÁêÿÄíÿÉïÿÈïÿÅëþÀéý¿èþÁëÿ¼èÿ¿éÿ¼æÿÁêÿÅëÿÉíýÌðÿÐñÿÍîÿÌðÿÈëþÈëÿÉìÿÉîÿÌñÿÊïÿÇìþ¾èÿ¸æÿ©Ýÿ Úÿ“ÐÿÌû’ÏþŽÍùŽÎü‹Òÿ‰ÏÿŒËÿˆÉÿ‡ÉÿƒÉÿÇÿ{ÃþyÀþ~Äÿ}ÃÿÅÿÅÿÆÿ‚ÇÿÆÿÆÿ€ÅþƒÅÿƒÅÿ„ÆÿŠÍÿ‰Ïÿ‡ÍþˆÎÿˆËÿŠÌÿŽÍÿÎÿ“Ðÿ™Ôÿ›ÖÿŸÕÿ Õÿ¨Üÿ­Ýÿ³àÿºãùÀéýÌðÿÏïþÒïýÎîýÌðþÎòÿÖöÿÜ÷þÜ÷þÚøÿÙ÷ÿÚ÷ÿÙöþÓñüÍðÿÅíÿ¶äÿ«Üÿ–Ìú’Ïþ•Ïý—Ðý›ÒûÔýšÔüŸÖý¤Øý²áýºãÿÃéÿÍìþÔñÿÞ÷üÞõûÞúþÞùÿßúÿâûÿæûÿåýÿÞúþÏïúÇìþ¸æÿ³äÿžÕü˜Òú™Ôþ—Òü—ÒüœÒþÔý£×þ¨Úý±Þÿ¶âÿ»äÿ¾çÿ½çÿºãÿ´àý³àÿ¶ãÿ²àÿ²Þÿ°Üÿ³Þþ·àü½åþÃéÿËðÿËïÿÉîÿÄèþÁçüÁæÿ¾æÿ¿çÿÁëÿ½çÿ­Úù®Üþ§Ûÿ ×ÿšÓþšÔüœÓü—Ñù“ÎúŽÎþŠÌþˆÇü†ÇýˆÊÿƒÉÿ€Æÿ}ÅÿzÁÿ{Áý|ÂþÅÿÅÿ€Åþ€Åþ€ÅþÄý€ÅþƒÅÿƒÅÿ†ÈÿŠÍÿˆÎÿ‡Íÿ‡Íÿ„ÇüˆÉÿÎÿŽÍÿËý“Ðý—ÑÿšÓÿœÒÿ£Øÿ§Øÿ¬Úü¸âøÀéýÌðÿÏïþÏïþÍîýÊïÿÉîþÑòÿÚöÿÛøÿÙ÷ÿÚøÿÛøÿÙöþÓñüÌïÿÃëÿ³áÿ©Ûÿ—Íù”Îü—Ðý›ÑýžÓûžÕüœÖþŸÖý¢Øþ­Þü´àýÀéÿËìýÐðýÜøüßøýáýÿáýÿâþÿåþÿêþÿåýÿÝùýÍíøÆëý¹çÿ³äÿ£ÚÿšÓþ˜ÓÿÍùÌø•Ïý—ÐýŸÔþ¤ØÿªÚþ³àÿµâÿ¸ãÿ¸ãÿ´áÿ±Þÿ¯Ýÿ°Ýÿ«Ûÿ¬Ùÿ­Úÿ°Üÿ²Ýý¹âþ¾æÿÈíÿÉîÿÈíÿÃéÿ¾æÿ»äÿ¹âþ¸äÿ¸åÿ³âþ¨Öø¨Øþ¤ÙÿŸÖýœÖü Øý¤ÚþŸÕûšÑúÍüŒÊý‡Æû„Åû†ÈÿÇÿ~Äÿ~Æÿ|Ãÿy¿ûzÀü}Ãþ€ÆÿÆÿ€ÅþÄý~ÃüÆÿƒÅÿ„Æÿ‡Éÿ‰Ìÿ†Ìÿ†Ìÿ…ÊÿƒÆý‡ÈþŽÍÿŽÍÿÍþ’Ïü“Ðý–Ðþ—ÏþŸÔÿ¢Öþ©×û»æùÂëÿÊïÿÌíþÌíþÉíýÄêÿÁçüÄéüÍìþÏìüÓñü×õÿÛøÿÚ÷ÿÖôÿÊíÿÂëÿ°Þÿ¦Øý›Ñý—ÐýŸÕÿ£Øÿ©Ýÿ§Þÿ¤ÛÿžØÿŸÖý§Ùü®Üý¼æþÍòÿÔöÿÜøüâûÿèÿÿçÿÿçÿÿêÿÿíýüëÿÿãüÿÒòýËïÿ´âüªÛûžÕü™Ôþ•Òþ’Ïû”Ñþ‘Íÿ‘ÍÿšÓÿžÔÿ¡Õý§Ùþ¨Øþ©ÙÿªÚþªÜÿ¬Þÿ¨Ùÿ¨Ùÿ¤×ÿ¦Úÿ£×ÿªÜÿ­Þÿµâÿ¸åÿ¿èüÅëþÁêþ¼æÿ¶âÿ¬ÚûªÛü©Ûþ¤Øý ÖúÐûžÑþÔýžÖû§Þü¬âþ¸êÿ³äÿ«ÝÿžÔÿ˜Òÿ‹Êÿ†Çý…ÇÿÅÿ}Ãþ|Äÿ|Ãÿx¾ú{Áý|ÂýÅÿÆÿÆÿÆÿÆÿ‚Çÿ‚ÄþƒÅÿ†Èÿ…Çÿ‚ÇÿƒÅÿ…Çÿ…Èÿ‡ÈÿŽÍÿŽÍÿÎÿÎÿÍþÎÿÍü—ÐýœÑû¨Úÿ¾éüÄïÿÌñÿËïÿËïÿÉîÿÂèý½æüÂæüÇèûÇçöÏìúÓñüÙõÿÙöþÖôÿÌðÿÆïÿ³áÿ¨ÚÿžÕþžÔÿ¤Ùÿ§ÜÿªÞÿ¨àÿ¦ÝÿŸÙÿ ×þ¨Úý°Þÿ¹ãüÎóÿÕ÷ÿÛ÷ûáúþåÿÿåÿÿçÿÿêÿÿïÿþîÿÿæÿÿÖôÿÌðÿ²Þù¦×÷¢Ùÿ›Öÿ•ÒþÍù’Ïü‘Ïÿ’Îÿ›Óÿž×ÿ Õý¤Øÿ¥×ü¦Øý§ÙþªÜÿ¥Ùÿ¡Õý¡Ôÿ Óþ¢×ÿ¥Ùÿ¬Þÿ®àÿ´ãÿ·äÿ½æúÂëÿ¿èþ¸äÿ³ßü¨Öø¥×ø£×üžÔúœÔù˜Ëø˜Ìû›ÒûŸ×ü¯åÿµéÿ¾îÿºéÿ°àÿ¤ØÿžÖÿÌÿ‡Èþ…ÇÿÅÿ}Ãþ|Äÿ}ÄÿzÀü}ÃÿÅÿ~Äÿ€Åþ‚ÇÿƒÈÿƒÈÿ‚Çÿ‚ÄþƒÅÿ†ÈÿƒÅÿƒÈÿƒÅÿ†Èÿ‡ÊÿˆÉÿÎÿŽÍÿÌÿŽÌýÍþÎÿÍü–Ïü›Ñý©Ûÿode-0.16/drawstuff/Makefile.am0000664000175200017520000000010513403272463013177 00000000000000if ENABLE_DRAWSTUFF
SUBDIRS = src dstest
EXTRA_DIST = textures
endif
ode-0.16/drawstuff/dstest/0000775000175200017520000000000013403273060012527 500000000000000ode-0.16/drawstuff/dstest/Makefile.am0000664000175200017520000000063213403272463014512 00000000000000noinst_PROGRAMS= dstest
AM_CPPFLAGS = -I$(top_srcdir)/drawstuff/src -I$(top_srcdir)/include

dstest_SOURCES= dstest.cpp
dstest_LDADD=$(top_builddir)/drawstuff/src/libdrawstuff.la \
            @GL_LIBS@

if WIN32
resources.o: $(top_srcdir)/drawstuff/src/resources.rc $(top_srcdir)/drawstuff/src/resource.h
	$(WINDRES) $(top_srcdir)/drawstuff/src/resources.rc -o resources.o

dstest_LDADD += resources.o
endif

ode-0.16/drawstuff/dstest/Makefile.in0000664000175200017520000004415513403272663014535 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am.
# @configure_input@

# Copyright (C) 1994-2014 Free Software Foundation, Inc.

# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.

@SET_MAKE@

VPATH = @srcdir@
am__is_gnu_make = { \
  if test -z '$(MAKELEVEL)'; then \
    false; \
  elif test -n '$(MAKE_HOST)'; then \
    true; \
  elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
    true; \
  else \
    false; \
  fi; \
}
am__make_running_with_option = \
  case $${target_option-} in \
      ?) ;; \
      *) echo "am__make_running_with_option: internal error: invalid" \
              "target option '$${target_option-}' specified" >&2; \
         exit 1;; \
  esac; \
  has_opt=no; \
  sane_makeflags=$$MAKEFLAGS; \
  if $(am__is_gnu_make); then \
    sane_makeflags=$$MFLAGS; \
  else \
    case $$MAKEFLAGS in \
      *\\[\ \	]*) \
        bs=\\; \
        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
    esac; \
  fi; \
  skip_next=no; \
  strip_trailopt () \
  { \
    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
  }; \
  for flg in $$sane_makeflags; do \
    test $$skip_next = yes && { skip_next=no; continue; }; \
    case $$flg in \
      *=*|--*) continue;; \
        -*I) strip_trailopt 'I'; skip_next=yes;; \
      -*I?*) strip_trailopt 'I';; \
        -*O) strip_trailopt 'O'; skip_next=yes;; \
      -*O?*) strip_trailopt 'O';; \
        -*l) strip_trailopt 'l'; skip_next=yes;; \
      -*l?*) strip_trailopt 'l';; \
      -[dEDm]) skip_next=yes;; \
      -[JT]) skip_next=yes;; \
    esac; \
    case $$flg in \
      *$$target_option*) has_opt=yes; break;; \
    esac; \
  done; \
  test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
noinst_PROGRAMS = dstest$(EXEEXT)
@WIN32_TRUE@am__append_1 = resources.o
subdir = drawstuff/dstest
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
	$(top_srcdir)/m4/pkg.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
	$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/ode/src/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
PROGRAMS = $(noinst_PROGRAMS)
am_dstest_OBJECTS = dstest.$(OBJEXT)
dstest_OBJECTS = $(am_dstest_OBJECTS)
dstest_DEPENDENCIES = $(top_builddir)/drawstuff/src/libdrawstuff.la \
	$(am__append_1)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
am__v_lt_0 = --silent
am__v_lt_1 = 
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo "  GEN     " $@;
am__v_GEN_1 = 
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 = 
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/ode/src
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
	$(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \
	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
	$(AM_CXXFLAGS) $(CXXFLAGS)
AM_V_CXX = $(am__v_CXX_@AM_V@)
am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@)
am__v_CXX_0 = @echo "  CXX     " $@;
am__v_CXX_1 = 
CXXLD = $(CXX)
CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
	$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
	$(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
AM_V_CXXLD = $(am__v_CXXLD_@AM_V@)
am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@)
am__v_CXXLD_0 = @echo "  CXXLD   " $@;
am__v_CXXLD_1 = 
SOURCES = $(dstest_SOURCES)
DIST_SOURCES = $(dstest_SOURCES)
am__can_run_installinfo = \
  case $$AM_UPDATE_INFO_DIR in \
    n|no|NO) false;; \
    *) (install-info --version) >/dev/null 2>&1;; \
  esac
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates.  Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
  BEGIN { nonempty = 0; } \
  { items[$$0] = 1; nonempty = 1; } \
  END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique.  This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
  list='$(am__tagged_files)'; \
  unique=`for i in $$list; do \
    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
  done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
ALLOCA = @ALLOCA@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
AS = @AS@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CCD_CFLAGS = @CCD_CFLAGS@
CCD_LIBS = @CCD_LIBS@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
DOXYGEN = @DOXYGEN@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
EXTRA_LIBTOOL_LDFLAGS = @EXTRA_LIBTOOL_LDFLAGS@
FGREP = @FGREP@
GL_LIBS = @GL_LIBS@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBSTDCXX = @LIBSTDCXX@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
ODE_PRECISION = @ODE_PRECISION@
ODE_VERSION = @ODE_VERSION@
ODE_VERSION_INFO = @ODE_VERSION_INFO@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
WINDRES = @WINDRES@
X11_CFLAGS = @X11_CFLAGS@
X11_LIBS = @X11_LIBS@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
ac_ct_WINDRES = @ac_ct_WINDRES@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
subdirs = @subdirs@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
AM_CPPFLAGS = -I$(top_srcdir)/drawstuff/src -I$(top_srcdir)/include
dstest_SOURCES = dstest.cpp
dstest_LDADD = $(top_builddir)/drawstuff/src/libdrawstuff.la @GL_LIBS@ \
	$(am__append_1)
all: all-am

.SUFFIXES:
.SUFFIXES: .cpp .lo .o .obj
$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
	@for dep in $?; do \
	  case '$(am__configure_deps)' in \
	    *$$dep*) \
	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
	        && { if test -f $@; then exit 0; else break; fi; }; \
	      exit 1;; \
	  esac; \
	done; \
	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign drawstuff/dstest/Makefile'; \
	$(am__cd) $(top_srcdir) && \
	  $(AUTOMAKE) --foreign drawstuff/dstest/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
	@case '$?' in \
	  *config.status*) \
	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
	  *) \
	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
	esac;

$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh

$(top_srcdir)/configure:  $(am__configure_deps)
	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):

clean-noinstPROGRAMS:
	@list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
	echo " rm -f" $$list; \
	rm -f $$list || exit $$?; \
	test -n "$(EXEEXT)" || exit 0; \
	list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
	echo " rm -f" $$list; \
	rm -f $$list

dstest$(EXEEXT): $(dstest_OBJECTS) $(dstest_DEPENDENCIES) $(EXTRA_dstest_DEPENDENCIES) 
	@rm -f dstest$(EXEEXT)
	$(AM_V_CXXLD)$(CXXLINK) $(dstest_OBJECTS) $(dstest_LDADD) $(LIBS)

mostlyclean-compile:
	-rm -f *.$(OBJEXT)

distclean-compile:
	-rm -f *.tab.c

@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dstest.Po@am__quote@

.cpp.o:
@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $<

.cpp.obj:
@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`

.cpp.lo:
@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $<

mostlyclean-libtool:
	-rm -f *.lo

clean-libtool:
	-rm -rf .libs _libs

ID: $(am__tagged_files)
	$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-am
TAGS: tags

tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
	set x; \
	here=`pwd`; \
	$(am__define_uniq_tagged_files); \
	shift; \
	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
	  test -n "$$unique" || unique=$$empty_fix; \
	  if test $$# -gt 0; then \
	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
	      "$$@" $$unique; \
	  else \
	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
	      $$unique; \
	  fi; \
	fi
ctags: ctags-am

CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
	$(am__define_uniq_tagged_files); \
	test -z "$(CTAGS_ARGS)$$unique" \
	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
	     $$unique

GTAGS:
	here=`$(am__cd) $(top_builddir) && pwd` \
	  && $(am__cd) $(top_srcdir) \
	  && gtags -i $(GTAGS_ARGS) "$$here"
cscopelist: cscopelist-am

cscopelist-am: $(am__tagged_files)
	list='$(am__tagged_files)'; \
	case "$(srcdir)" in \
	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
	  *) sdir=$(subdir)/$(srcdir) ;; \
	esac; \
	for i in $$list; do \
	  if test -f "$$i"; then \
	    echo "$(subdir)/$$i"; \
	  else \
	    echo "$$sdir/$$i"; \
	  fi; \
	done >> $(top_builddir)/cscope.files

distclean-tags:
	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags

distdir: $(DISTFILES)
	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
	list='$(DISTFILES)'; \
	  dist_files=`for file in $$list; do echo $$file; done | \
	  sed -e "s|^$$srcdirstrip/||;t" \
	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
	case $$dist_files in \
	  */*) $(MKDIR_P) `echo "$$dist_files" | \
			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
			   sort -u` ;; \
	esac; \
	for file in $$dist_files; do \
	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
	  if test -d $$d/$$file; then \
	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
	    if test -d "$(distdir)/$$file"; then \
	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
	    fi; \
	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
	    fi; \
	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
	  else \
	    test -f "$(distdir)/$$file" \
	    || cp -p $$d/$$file "$(distdir)/$$file" \
	    || exit 1; \
	  fi; \
	done
check-am: all-am
check: check-am
all-am: Makefile $(PROGRAMS)
installdirs:
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am

install-am: all-am
	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am

installcheck: installcheck-am
install-strip:
	if test -z '$(STRIP)'; then \
	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
	      install; \
	else \
	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
	fi
mostlyclean-generic:

clean-generic:

distclean-generic:
	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)

maintainer-clean-generic:
	@echo "This command is intended for maintainers to use"
	@echo "it deletes files that may require special tools to rebuild."
clean: clean-am

clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \
	mostlyclean-am

distclean: distclean-am
	-rm -rf ./$(DEPDIR)
	-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
	distclean-tags

dvi: dvi-am

dvi-am:

html: html-am

html-am:

info: info-am

info-am:

install-data-am:

install-dvi: install-dvi-am

install-dvi-am:

install-exec-am:

install-html: install-html-am

install-html-am:

install-info: install-info-am

install-info-am:

install-man:

install-pdf: install-pdf-am

install-pdf-am:

install-ps: install-ps-am

install-ps-am:

installcheck-am:

maintainer-clean: maintainer-clean-am
	-rm -rf ./$(DEPDIR)
	-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic

mostlyclean: mostlyclean-am

mostlyclean-am: mostlyclean-compile mostlyclean-generic \
	mostlyclean-libtool

pdf: pdf-am

pdf-am:

ps: ps-am

ps-am:

uninstall-am:

.MAKE: install-am install-strip

.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
	clean-libtool clean-noinstPROGRAMS cscopelist-am ctags \
	ctags-am distclean distclean-compile distclean-generic \
	distclean-libtool distclean-tags distdir dvi dvi-am html \
	html-am info info-am install install-am install-data \
	install-data-am install-dvi install-dvi-am install-exec \
	install-exec-am install-html install-html-am install-info \
	install-info-am install-man install-pdf install-pdf-am \
	install-ps install-ps-am install-strip installcheck \
	installcheck-am installdirs maintainer-clean \
	maintainer-clean-generic mostlyclean mostlyclean-compile \
	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
	tags tags-am uninstall uninstall-am

.PRECIOUS: Makefile


@WIN32_TRUE@resources.o: $(top_srcdir)/drawstuff/src/resources.rc $(top_srcdir)/drawstuff/src/resource.h
@WIN32_TRUE@	$(WINDRES) $(top_srcdir)/drawstuff/src/resources.rc -o resources.o

# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
ode-0.16/drawstuff/dstest/dstest.cpp0000664000175200017520000000715513403272463014477 00000000000000/*************************************************************************
 *                                                                       *
 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
 * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
 *                                                                       *
 * This library is free software; you can redistribute it and/or         *
 * modify it under the terms of EITHER:                                  *
 *   (1) The GNU Lesser General Public License as published by the Free  *
 *       Software Foundation; either version 2.1 of the License, or (at  *
 *       your option) any later version. The text of the GNU Lesser      *
 *       General Public License is included with this library in the     *
 *       file LICENSE.TXT.                                               *
 *   (2) The BSD-style license that is included with this library in     *
 *       the file LICENSE-BSD.TXT.                                       *
 *                                                                       *
 * This library is distributed in the hope that it will be useful,       *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
 * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
 *                                                                       *
 *************************************************************************/

#include 
#include 
#include 


#ifndef M_PI
#define M_PI (3.14159265358979323846)
#endif


void start()
{
  // adjust the starting viewpoint a bit
  float xyz[3],hpr[3];
  dsGetViewpoint (xyz,hpr);
  hpr[0] += 7;
  dsSetViewpoint (xyz,hpr);
}


void simLoop (int pause)
{
  float pos[3];
  float R[12];
  static float a = 0;

  if (!pause) a += 0.02f;
  if (a > (2*M_PI)) a -= (float) (2*M_PI);
  float ca = (float) cos(a);
  float sa = (float) sin(a);

  dsSetTexture (DS_WOOD);

  float b = (a > M_PI) ? (2*(a-(float)M_PI)) : a*2;
  pos[0] = -0.3f;
  pos[1] = 0;
  pos[2] = (float) (0.1f*(2*M_PI*b - b*b) + 0.65f);
  R[0] = ca; R[1] = 0; R[2] = -sa;
  R[4] = 0;  R[5] = 1; R[6] = 0;
  R[8] = sa; R[9] = 0; R[10] = ca;
  dsSetColor (1,0.8f,0.6f);
  dsDrawSphere (pos,R,0.3f);

  dsSetTexture (DS_NONE);

  pos[0] = -0.2f;
  pos[1] = 0.8f;
  pos[2] = 0.4f;
  R[0] = ca; R[1] = -sa; R[2] = 0;
  R[4] = sa; R[5] = ca;  R[6] = 0;
  R[8] = 0;  R[9] = 0;	 R[10] = 1;
  float sides[3] = {0.1f,0.4f,0.8f};
  dsSetColor (0.6f,0.6f,1);
  dsDrawBox (pos,R,sides);

  dsSetTexture (DS_WOOD);

  float r = 0.3f;		      // cylinder radius
  float d = (float)cos(a*2) * 0.4f;
  float cd = (float)cos(-d/r);
  float sd = (float)sin(-d/r);
  pos[0] = -0.2f;
  pos[1] = -1 + d;
  pos[2] = 0.3f;
  R[0] = 0;   R[1] = 0;  R[2] = -1;
  R[4] = -sd; R[5] = cd; R[6] =  0;
  R[8] =  cd; R[9] = sd; R[10] = 0;
  dsSetColor (0.4f,1,1);
  dsDrawCylinder (pos,R,0.8f,r);

  pos[0] = 0;
  pos[1] = 0;
  pos[2] = 0.2f;
  R[0] = 0; R[1] = sa; R[2] = -ca;
  R[4] = 0; R[5] = ca; R[6] = sa;
  R[8] = 1; R[9] = 0;  R[10] = 0;
  dsSetColor (1,0.9f,0.2f);
  dsDrawCappedCylinder (pos,R,0.8f,0.2f);
}


void command (int cmd)
{
  dsPrint ("received command %d (`%c')\n",cmd,cmd);
}


int main (int argc, char **argv)
{
  // setup pointers to callback functions
  dsFunctions fn;
  fn.version = DS_VERSION;
  fn.start = &start;
  fn.step = &simLoop;
  fn.command = command;
  fn.stop = 0;
  fn.path_to_textures = 0;	// uses default

  // run simulation
  dsSimulationLoop (argc,argv,400,400,&fn);

  return 0;
}
ode-0.16/drawstuff/Makefile.in0000664000175200017520000004514013403272663013222 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am.
# @configure_input@

# Copyright (C) 1994-2014 Free Software Foundation, Inc.

# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.

@SET_MAKE@
VPATH = @srcdir@
am__is_gnu_make = { \
  if test -z '$(MAKELEVEL)'; then \
    false; \
  elif test -n '$(MAKE_HOST)'; then \
    true; \
  elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
    true; \
  else \
    false; \
  fi; \
}
am__make_running_with_option = \
  case $${target_option-} in \
      ?) ;; \
      *) echo "am__make_running_with_option: internal error: invalid" \
              "target option '$${target_option-}' specified" >&2; \
         exit 1;; \
  esac; \
  has_opt=no; \
  sane_makeflags=$$MAKEFLAGS; \
  if $(am__is_gnu_make); then \
    sane_makeflags=$$MFLAGS; \
  else \
    case $$MAKEFLAGS in \
      *\\[\ \	]*) \
        bs=\\; \
        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
    esac; \
  fi; \
  skip_next=no; \
  strip_trailopt () \
  { \
    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
  }; \
  for flg in $$sane_makeflags; do \
    test $$skip_next = yes && { skip_next=no; continue; }; \
    case $$flg in \
      *=*|--*) continue;; \
        -*I) strip_trailopt 'I'; skip_next=yes;; \
      -*I?*) strip_trailopt 'I';; \
        -*O) strip_trailopt 'O'; skip_next=yes;; \
      -*O?*) strip_trailopt 'O';; \
        -*l) strip_trailopt 'l'; skip_next=yes;; \
      -*l?*) strip_trailopt 'l';; \
      -[dEDm]) skip_next=yes;; \
      -[JT]) skip_next=yes;; \
    esac; \
    case $$flg in \
      *$$target_option*) has_opt=yes; break;; \
    esac; \
  done; \
  test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
subdir = drawstuff
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
	$(top_srcdir)/m4/pkg.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
	$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/ode/src/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo "  GEN     " $@;
am__v_GEN_1 = 
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 = 
SOURCES =
DIST_SOURCES =
RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
	ctags-recursive dvi-recursive html-recursive info-recursive \
	install-data-recursive install-dvi-recursive \
	install-exec-recursive install-html-recursive \
	install-info-recursive install-pdf-recursive \
	install-ps-recursive install-recursive installcheck-recursive \
	installdirs-recursive pdf-recursive ps-recursive \
	tags-recursive uninstall-recursive
am__can_run_installinfo = \
  case $$AM_UPDATE_INFO_DIR in \
    n|no|NO) false;; \
    *) (install-info --version) >/dev/null 2>&1;; \
  esac
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive	\
  distclean-recursive maintainer-clean-recursive
am__recursive_targets = \
  $(RECURSIVE_TARGETS) \
  $(RECURSIVE_CLEAN_TARGETS) \
  $(am__extra_recursive_targets)
AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
	distdir
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates.  Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
  BEGIN { nonempty = 0; } \
  { items[$$0] = 1; nonempty = 1; } \
  END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique.  This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
  list='$(am__tagged_files)'; \
  unique=`for i in $$list; do \
    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
  done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
DIST_SUBDIRS = src dstest
am__DIST_COMMON = $(srcdir)/Makefile.in
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
am__relativize = \
  dir0=`pwd`; \
  sed_first='s,^\([^/]*\)/.*$$,\1,'; \
  sed_rest='s,^[^/]*/*,,'; \
  sed_last='s,^.*/\([^/]*\)$$,\1,'; \
  sed_butlast='s,/*[^/]*$$,,'; \
  while test -n "$$dir1"; do \
    first=`echo "$$dir1" | sed -e "$$sed_first"`; \
    if test "$$first" != "."; then \
      if test "$$first" = ".."; then \
        dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
        dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
      else \
        first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
        if test "$$first2" = "$$first"; then \
          dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
        else \
          dir2="../$$dir2"; \
        fi; \
        dir0="$$dir0"/"$$first"; \
      fi; \
    fi; \
    dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
  done; \
  reldir="$$dir2"
ACLOCAL = @ACLOCAL@
ALLOCA = @ALLOCA@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
AS = @AS@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CCD_CFLAGS = @CCD_CFLAGS@
CCD_LIBS = @CCD_LIBS@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
DOXYGEN = @DOXYGEN@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
EXTRA_LIBTOOL_LDFLAGS = @EXTRA_LIBTOOL_LDFLAGS@
FGREP = @FGREP@
GL_LIBS = @GL_LIBS@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBSTDCXX = @LIBSTDCXX@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
ODE_PRECISION = @ODE_PRECISION@
ODE_VERSION = @ODE_VERSION@
ODE_VERSION_INFO = @ODE_VERSION_INFO@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
WINDRES = @WINDRES@
X11_CFLAGS = @X11_CFLAGS@
X11_LIBS = @X11_LIBS@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
ac_ct_WINDRES = @ac_ct_WINDRES@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
subdirs = @subdirs@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
@ENABLE_DRAWSTUFF_TRUE@SUBDIRS = src dstest
@ENABLE_DRAWSTUFF_TRUE@EXTRA_DIST = textures
all: all-recursive

.SUFFIXES:
$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
	@for dep in $?; do \
	  case '$(am__configure_deps)' in \
	    *$$dep*) \
	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
	        && { if test -f $@; then exit 0; else break; fi; }; \
	      exit 1;; \
	  esac; \
	done; \
	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign drawstuff/Makefile'; \
	$(am__cd) $(top_srcdir) && \
	  $(AUTOMAKE) --foreign drawstuff/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
	@case '$?' in \
	  *config.status*) \
	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
	  *) \
	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
	esac;

$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh

$(top_srcdir)/configure:  $(am__configure_deps)
	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):

mostlyclean-libtool:
	-rm -f *.lo

clean-libtool:
	-rm -rf .libs _libs

# This directory's subdirectories are mostly independent; you can cd
# into them and run 'make' without going through this Makefile.
# To change the values of 'make' variables: instead of editing Makefiles,
# (1) if the variable is set in 'config.status', edit 'config.status'
#     (which will cause the Makefiles to be regenerated when you run 'make');
# (2) otherwise, pass the desired values on the 'make' command line.
$(am__recursive_targets):
	@fail=; \
	if $(am__make_keepgoing); then \
	  failcom='fail=yes'; \
	else \
	  failcom='exit 1'; \
	fi; \
	dot_seen=no; \
	target=`echo $@ | sed s/-recursive//`; \
	case "$@" in \
	  distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
	  *) list='$(SUBDIRS)' ;; \
	esac; \
	for subdir in $$list; do \
	  echo "Making $$target in $$subdir"; \
	  if test "$$subdir" = "."; then \
	    dot_seen=yes; \
	    local_target="$$target-am"; \
	  else \
	    local_target="$$target"; \
	  fi; \
	  ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
	  || eval $$failcom; \
	done; \
	if test "$$dot_seen" = "no"; then \
	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
	fi; test -z "$$fail"

ID: $(am__tagged_files)
	$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-recursive
TAGS: tags

tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
	set x; \
	here=`pwd`; \
	if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
	  include_option=--etags-include; \
	  empty_fix=.; \
	else \
	  include_option=--include; \
	  empty_fix=; \
	fi; \
	list='$(SUBDIRS)'; for subdir in $$list; do \
	  if test "$$subdir" = .; then :; else \
	    test ! -f $$subdir/TAGS || \
	      set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
	  fi; \
	done; \
	$(am__define_uniq_tagged_files); \
	shift; \
	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
	  test -n "$$unique" || unique=$$empty_fix; \
	  if test $$# -gt 0; then \
	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
	      "$$@" $$unique; \
	  else \
	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
	      $$unique; \
	  fi; \
	fi
ctags: ctags-recursive

CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
	$(am__define_uniq_tagged_files); \
	test -z "$(CTAGS_ARGS)$$unique" \
	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
	     $$unique

GTAGS:
	here=`$(am__cd) $(top_builddir) && pwd` \
	  && $(am__cd) $(top_srcdir) \
	  && gtags -i $(GTAGS_ARGS) "$$here"
cscopelist: cscopelist-recursive

cscopelist-am: $(am__tagged_files)
	list='$(am__tagged_files)'; \
	case "$(srcdir)" in \
	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
	  *) sdir=$(subdir)/$(srcdir) ;; \
	esac; \
	for i in $$list; do \
	  if test -f "$$i"; then \
	    echo "$(subdir)/$$i"; \
	  else \
	    echo "$$sdir/$$i"; \
	  fi; \
	done >> $(top_builddir)/cscope.files

distclean-tags:
	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags

distdir: $(DISTFILES)
	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
	list='$(DISTFILES)'; \
	  dist_files=`for file in $$list; do echo $$file; done | \
	  sed -e "s|^$$srcdirstrip/||;t" \
	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
	case $$dist_files in \
	  */*) $(MKDIR_P) `echo "$$dist_files" | \
			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
			   sort -u` ;; \
	esac; \
	for file in $$dist_files; do \
	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
	  if test -d $$d/$$file; then \
	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
	    if test -d "$(distdir)/$$file"; then \
	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
	    fi; \
	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
	    fi; \
	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
	  else \
	    test -f "$(distdir)/$$file" \
	    || cp -p $$d/$$file "$(distdir)/$$file" \
	    || exit 1; \
	  fi; \
	done
	@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
	  if test "$$subdir" = .; then :; else \
	    $(am__make_dryrun) \
	      || test -d "$(distdir)/$$subdir" \
	      || $(MKDIR_P) "$(distdir)/$$subdir" \
	      || exit 1; \
	    dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
	    $(am__relativize); \
	    new_distdir=$$reldir; \
	    dir1=$$subdir; dir2="$(top_distdir)"; \
	    $(am__relativize); \
	    new_top_distdir=$$reldir; \
	    echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
	    echo "     am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
	    ($(am__cd) $$subdir && \
	      $(MAKE) $(AM_MAKEFLAGS) \
	        top_distdir="$$new_top_distdir" \
	        distdir="$$new_distdir" \
		am__remove_distdir=: \
		am__skip_length_check=: \
		am__skip_mode_fix=: \
	        distdir) \
	      || exit 1; \
	  fi; \
	done
check-am: all-am
check: check-recursive
all-am: Makefile
installdirs: installdirs-recursive
installdirs-am:
install: install-recursive
install-exec: install-exec-recursive
install-data: install-data-recursive
uninstall: uninstall-recursive

install-am: all-am
	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am

installcheck: installcheck-recursive
install-strip:
	if test -z '$(STRIP)'; then \
	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
	      install; \
	else \
	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
	fi
mostlyclean-generic:

clean-generic:

distclean-generic:
	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)

maintainer-clean-generic:
	@echo "This command is intended for maintainers to use"
	@echo "it deletes files that may require special tools to rebuild."
clean: clean-recursive

clean-am: clean-generic clean-libtool mostlyclean-am

distclean: distclean-recursive
	-rm -f Makefile
distclean-am: clean-am distclean-generic distclean-tags

dvi: dvi-recursive

dvi-am:

html: html-recursive

html-am:

info: info-recursive

info-am:

install-data-am:

install-dvi: install-dvi-recursive

install-dvi-am:

install-exec-am:

install-html: install-html-recursive

install-html-am:

install-info: install-info-recursive

install-info-am:

install-man:

install-pdf: install-pdf-recursive

install-pdf-am:

install-ps: install-ps-recursive

install-ps-am:

installcheck-am:

maintainer-clean: maintainer-clean-recursive
	-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic

mostlyclean: mostlyclean-recursive

mostlyclean-am: mostlyclean-generic mostlyclean-libtool

pdf: pdf-recursive

pdf-am:

ps: ps-recursive

ps-am:

uninstall-am:

.MAKE: $(am__recursive_targets) install-am install-strip

.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \
	check-am clean clean-generic clean-libtool cscopelist-am ctags \
	ctags-am distclean distclean-generic distclean-libtool \
	distclean-tags distdir dvi dvi-am html html-am info info-am \
	install install-am install-data install-data-am install-dvi \
	install-dvi-am install-exec install-exec-am install-html \
	install-html-am install-info install-info-am install-man \
	install-pdf install-pdf-am install-ps install-ps-am \
	install-strip installcheck installcheck-am installdirs \
	installdirs-am maintainer-clean maintainer-clean-generic \
	mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \
	ps ps-am tags tags-am uninstall uninstall-am

.PRECIOUS: Makefile


# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
ode-0.16/ode-config.cmake.in0000664000175200017520000000057613403272463012573 00000000000000set(ODE_VERSION "@VERSION@")
set(ODE_VERSION_MAJOR "@VERSION_MAJOR@")
set(ODE_VERSION_MINOR "@VERSION_MINOR@")
set(ODE_VERSION_PATCH "@VERSION_PATCH@")

@PACKAGE_INIT@

include("${CMAKE_CURRENT_LIST_DIR}/ode-export.cmake")

set(ODE_DEFINITIONS "")
set(ODE_INCLUDE_DIRS "${PACKAGE_PREFIX_DIR}/include")
set(ODE_LIBRARY_DIRS "${PACKAGE_PREFIX_DIR}/lib")
set(ODE_LIBRARIES "ODE::ODE")
ode-0.16/compile0000755000175200017520000001624513403272662010527 00000000000000#! /bin/sh
# Wrapper for compilers which do not understand '-c -o'.

scriptversion=2012-10-14.11; # UTC

# Copyright (C) 1999-2014 Free Software Foundation, Inc.
# Written by Tom Tromey .
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see .

# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.

# This file is maintained in Automake, please report
# bugs to  or send patches to
# .

nl='
'

# We need space, tab and new line, in precisely that order.  Quoting is
# there to prevent tools from complaining about whitespace usage.
IFS=" ""	$nl"

file_conv=

# func_file_conv build_file lazy
# Convert a $build file to $host form and store it in $file
# Currently only supports Windows hosts. If the determined conversion
# type is listed in (the comma separated) LAZY, no conversion will
# take place.
func_file_conv ()
{
  file=$1
  case $file in
    / | /[!/]*) # absolute file, and not a UNC file
      if test -z "$file_conv"; then
	# lazily determine how to convert abs files
	case `uname -s` in
	  MINGW*)
	    file_conv=mingw
	    ;;
	  CYGWIN*)
	    file_conv=cygwin
	    ;;
	  *)
	    file_conv=wine
	    ;;
	esac
      fi
      case $file_conv/,$2, in
	*,$file_conv,*)
	  ;;
	mingw/*)
	  file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
	  ;;
	cygwin/*)
	  file=`cygpath -m "$file" || echo "$file"`
	  ;;
	wine/*)
	  file=`winepath -w "$file" || echo "$file"`
	  ;;
      esac
      ;;
  esac
}

# func_cl_dashL linkdir
# Make cl look for libraries in LINKDIR
func_cl_dashL ()
{
  func_file_conv "$1"
  if test -z "$lib_path"; then
    lib_path=$file
  else
    lib_path="$lib_path;$file"
  fi
  linker_opts="$linker_opts -LIBPATH:$file"
}

# func_cl_dashl library
# Do a library search-path lookup for cl
func_cl_dashl ()
{
  lib=$1
  found=no
  save_IFS=$IFS
  IFS=';'
  for dir in $lib_path $LIB
  do
    IFS=$save_IFS
    if $shared && test -f "$dir/$lib.dll.lib"; then
      found=yes
      lib=$dir/$lib.dll.lib
      break
    fi
    if test -f "$dir/$lib.lib"; then
      found=yes
      lib=$dir/$lib.lib
      break
    fi
    if test -f "$dir/lib$lib.a"; then
      found=yes
      lib=$dir/lib$lib.a
      break
    fi
  done
  IFS=$save_IFS

  if test "$found" != yes; then
    lib=$lib.lib
  fi
}

# func_cl_wrapper cl arg...
# Adjust compile command to suit cl
func_cl_wrapper ()
{
  # Assume a capable shell
  lib_path=
  shared=:
  linker_opts=
  for arg
  do
    if test -n "$eat"; then
      eat=
    else
      case $1 in
	-o)
	  # configure might choose to run compile as 'compile cc -o foo foo.c'.
	  eat=1
	  case $2 in
	    *.o | *.[oO][bB][jJ])
	      func_file_conv "$2"
	      set x "$@" -Fo"$file"
	      shift
	      ;;
	    *)
	      func_file_conv "$2"
	      set x "$@" -Fe"$file"
	      shift
	      ;;
	  esac
	  ;;
	-I)
	  eat=1
	  func_file_conv "$2" mingw
	  set x "$@" -I"$file"
	  shift
	  ;;
	-I*)
	  func_file_conv "${1#-I}" mingw
	  set x "$@" -I"$file"
	  shift
	  ;;
	-l)
	  eat=1
	  func_cl_dashl "$2"
	  set x "$@" "$lib"
	  shift
	  ;;
	-l*)
	  func_cl_dashl "${1#-l}"
	  set x "$@" "$lib"
	  shift
	  ;;
	-L)
	  eat=1
	  func_cl_dashL "$2"
	  ;;
	-L*)
	  func_cl_dashL "${1#-L}"
	  ;;
	-static)
	  shared=false
	  ;;
	-Wl,*)
	  arg=${1#-Wl,}
	  save_ifs="$IFS"; IFS=','
	  for flag in $arg; do
	    IFS="$save_ifs"
	    linker_opts="$linker_opts $flag"
	  done
	  IFS="$save_ifs"
	  ;;
	-Xlinker)
	  eat=1
	  linker_opts="$linker_opts $2"
	  ;;
	-*)
	  set x "$@" "$1"
	  shift
	  ;;
	*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
	  func_file_conv "$1"
	  set x "$@" -Tp"$file"
	  shift
	  ;;
	*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
	  func_file_conv "$1" mingw
	  set x "$@" "$file"
	  shift
	  ;;
	*)
	  set x "$@" "$1"
	  shift
	  ;;
      esac
    fi
    shift
  done
  if test -n "$linker_opts"; then
    linker_opts="-link$linker_opts"
  fi
  exec "$@" $linker_opts
  exit 1
}

eat=

case $1 in
  '')
     echo "$0: No command.  Try '$0 --help' for more information." 1>&2
     exit 1;
     ;;
  -h | --h*)
    cat <<\EOF
Usage: compile [--help] [--version] PROGRAM [ARGS]

Wrapper for compilers which do not understand '-c -o'.
Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
arguments, and rename the output as expected.

If you are trying to build a whole package this is not the
right script to run: please start by reading the file 'INSTALL'.

Report bugs to .
EOF
    exit $?
    ;;
  -v | --v*)
    echo "compile $scriptversion"
    exit $?
    ;;
  cl | *[/\\]cl | cl.exe | *[/\\]cl.exe )
    func_cl_wrapper "$@"      # Doesn't return...
    ;;
esac

ofile=
cfile=

for arg
do
  if test -n "$eat"; then
    eat=
  else
    case $1 in
      -o)
	# configure might choose to run compile as 'compile cc -o foo foo.c'.
	# So we strip '-o arg' only if arg is an object.
	eat=1
	case $2 in
	  *.o | *.obj)
	    ofile=$2
	    ;;
	  *)
	    set x "$@" -o "$2"
	    shift
	    ;;
	esac
	;;
      *.c)
	cfile=$1
	set x "$@" "$1"
	shift
	;;
      *)
	set x "$@" "$1"
	shift
	;;
    esac
  fi
  shift
done

if test -z "$ofile" || test -z "$cfile"; then
  # If no '-o' option was seen then we might have been invoked from a
  # pattern rule where we don't need one.  That is ok -- this is a
  # normal compilation that the losing compiler can handle.  If no
  # '.c' file was seen then we are probably linking.  That is also
  # ok.
  exec "$@"
fi

# Name of file we expect compiler to create.
cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`

# Create the lock directory.
# Note: use '[/\\:.-]' here to ensure that we don't use the same name
# that we are using for the .o file.  Also, base the name on the expected
# object file name, since that is what matters with a parallel build.
lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
while true; do
  if mkdir "$lockdir" >/dev/null 2>&1; then
    break
  fi
  sleep 1
done
# FIXME: race condition here if user kills between mkdir and trap.
trap "rmdir '$lockdir'; exit 1" 1 2 15

# Run the compile.
"$@"
ret=$?

if test -f "$cofile"; then
  test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
elif test -f "${cofile}bj"; then
  test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
fi

rmdir "$lockdir"
exit $ret

# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:
ode-0.16/ode-config.in0000664000175200017520000000160513403272463011506 00000000000000#!/bin/sh

prefix=@prefix@
exec_prefix=@exec_prefix@
exec_prefix_set=no

usage="\
Usage: ode-config [--prefix[=DIR]] [--exec-prefix[=DIR]] [--version] [--cflags] [--libs]"

if test $# -eq 0; then
      echo "${usage}" 1>&2
      exit 1
fi

while test $# -gt 0; do
  case "$1" in
  -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
  *) optarg= ;;
  esac

  case $1 in
    --prefix=*)
      prefix=$optarg
      if test $exec_prefix_set = no ; then
        exec_prefix=$optarg
      fi
      ;;
    --prefix)
      echo $prefix
      ;;
    --exec-prefix=*)
      exec_prefix=$optarg
      exec_prefix_set=yes
      ;;
    --exec-prefix)
      echo $exec_prefix
      ;;
    --version)
      echo @ODE_VERSION@
      ;;
    --cflags)
      echo  -I@includedir@
      ;;
    --libs)
      echo  -L@libdir@ -lode
      ;;
    *)
      echo "${usage}" 1>&2
      exit 1
      ;;
  esac
  shift
done
ode-0.16/cmake/0000775000175200017520000000000013403272463010302 500000000000000ode-0.16/cmake/cmake_uninstall.cmake.in0000664000175200017520000000103513403272463015001 00000000000000if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
	message(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"")
endif()

file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" FILES)
string(REGEX REPLACE "\n" ";" FILES "${FILES}")

foreach(FILE ${FILES})
	message(STATUS "Uninstalling: ${FILE}")
	if(EXISTS "${FILE}")
		file(REMOVE ${FILE})
	elseif(IS_SYMLINK "${FILE}")
		file(REMOVE ${FILE})
	else()
		message(STATUS "File \"${FILE}\" does not exist.")
	endif()
endforeach()
ode-0.16/bindings/0000775000175200017520000000000013403272463011017 500000000000000ode-0.16/bindings/python/0000775000175200017520000000000013403272463012340 500000000000000ode-0.16/bindings/python/setup.py0000664000175200017520000000335613403272463014001 00000000000000#! /usr/bin/env python
from distutils.core import setup
from distutils.extension import Extension
from subprocess import Popen, PIPE, CalledProcessError


try:
    from Cython.Distutils import build_ext
except ImportError:
    raise SystemExit("Requires Cython (http://cython.org/)")

try:
    ode_cflags = Popen(
        ["pkg-config", "--cflags", "ode"],
        stdout=PIPE).stdout.read().decode('ascii').split()
    ode_libs = Popen(
        ["pkg-config", "--libs", "ode"],
        stdout=PIPE).stdout.read().decode('ascii').split()
except (OSError, CalledProcessError):
    raise SystemExit("Failed to find ODE with 'pkg-config'. Please make sure "
                     "that it is installed and available on your system path.")

ode_ext = Extension("ode", ["ode.pyx"],
                    extra_compile_args=ode_cflags,
                    extra_link_args=ode_libs)

if __name__ == "__main__":
    setup(
        name="Open Dynamics Engine",
        version="0.12",
        author="Gideon Klompje",
#        author_email="",
#        maintainer="",
#        maintainer_email="",
        url="http://www.ode.org",
        description="Bindings for the Open Dynamics Engine",
        long_description=(
            "A free, industrial quality library for simulating articulated "
            "rigid body dynamics - for example ground vehicles, legged "
            "creatures, and moving objects in VR environments. It's fast, "
            "flexible & robust. Built-in collision detection."),
#        download_url="https://opende.svn.sourceforge.net/svnroot/opende",
#        classifiers=[],
#        platforms=[],
        license="BSD License, GNU Lesser General Public License (LGPL)",
        cmdclass={"build_ext": build_ext},
        ext_modules=[ode_ext]
    )
ode-0.16/bindings/python/ode.pxd0000664000175200017520000005322713403272463013555 00000000000000######################################################################
# Python Open Dynamics Engine Wrapper
# Copyright (C) 2004 PyODE developers (see file AUTHORS)
# All rights reserved.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of EITHER:
#   (1) The GNU Lesser General Public License as published by the Free
#       Software Foundation; either version 2.1 of the License, or (at
#       your option) any later version. The text of the GNU Lesser
#       General Public License is included with this library in the
#       file LICENSE.
#   (2) The BSD-style license that is included with this library in
#       the file LICENSE-BSD.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
# LICENSE and LICENSE-BSD for more details. 
######################################################################

cdef extern from "stdlib.h":

    void* malloc(long)
    void free(void*)

cdef extern from "stdio.h":
    int printf(char*)

# Include the basic floating point type -> dReal  (either float or double)
#include "_precision.pyx"
    
cdef extern from "ode/ode.h":

    ctypedef double dReal
    
    # Dummy structs
    cdef struct dxWorld:
        int _dummy
    cdef struct dxSpace:
        int _dummy
    cdef struct dxBody:
        int _dummy
    cdef struct dxGeom:
        int _dummy
    cdef struct dxJoint:
        int _dummy
    cdef struct dxJointGroup:
        int _dummy
    cdef struct dxTriMeshData:
        int _dummy
    cdef struct dxHeightfieldData:
        int _dummy

    # Types
    ctypedef dxWorld* dWorldID
    ctypedef dxSpace* dSpaceID
    ctypedef dxBody* dBodyID
    ctypedef dxGeom* dGeomID
    ctypedef dxJoint* dJointID
    ctypedef dxJointGroup* dJointGroupID
    ctypedef dxTriMeshData* dTriMeshDataID
    ctypedef dxHeightfieldData* dHeightfieldDataID
    ctypedef dReal dVector3[4]
    ctypedef dReal dVector4[4]
    ctypedef dReal dMatrix3[4*3]
    ctypedef dReal dMatrix4[4*4]
    ctypedef dReal dMatrix6[8*6]
    ctypedef dReal dQuaternion[4]

    cdef extern dReal dInfinity
    cdef extern int dAMotorUser
    cdef extern int dAMotorEuler

    ctypedef struct dMass:
        dReal    mass
        dVector4 c
        dMatrix3 I
        
    ctypedef struct dJointFeedback:
        dVector3 f1
        dVector3 t1
        dVector3 f2
        dVector3 t2

    ctypedef void dNearCallback(void* data, dGeomID o1, dGeomID o2)
    ctypedef dReal dHeightfieldGetHeight( void* p_user_data, int x, int z )

    ctypedef struct dSurfaceParameters:
        int mode
        dReal mu

        dReal mu2
        dReal bounce
        dReal bounce_vel
        dReal soft_erp
        dReal soft_cfm
        dReal motion1,motion2
        dReal slip1,slip2

    ctypedef struct dContactGeom:
        dVector3 pos
        dVector3 normal
        dReal depth
        dGeomID g1,g2

    ctypedef struct dContact:
        dSurfaceParameters surface
        dContactGeom geom
        dVector3 fdir1


    # World
    dWorldID dWorldCreate()
    void dWorldDestroy (dWorldID)

    void dCloseODE()
    void dInitODE()

    void dWorldSetGravity (dWorldID, dReal x, dReal y, dReal z)
    void dWorldGetGravity (dWorldID, dVector3 gravity)
    void dWorldSetERP (dWorldID, dReal erp)
    dReal dWorldGetERP (dWorldID)
    void dWorldSetCFM (dWorldID, dReal cfm)
    dReal dWorldGetCFM (dWorldID)
    void dWorldStep (dWorldID, dReal stepsize)
    void dWorldQuickStep (dWorldID, dReal stepsize)
    void dWorldSetQuickStepNumIterations (dWorldID, int num)
    int dWorldGetQuickStepNumIterations (dWorldID)
    void dWorldSetContactMaxCorrectingVel (dWorldID, dReal vel)
    dReal dWorldGetContactMaxCorrectingVel (dWorldID)
    void dWorldSetContactSurfaceLayer (dWorldID, dReal depth)
    dReal dWorldGetContactSurfaceLayer (dWorldID)
    void dWorldSetAutoDisableFlag (dWorldID, int do_auto_disable)
    int dWorldGetAutoDisableFlag (dWorldID)
    void dWorldSetAutoDisableLinearThreshold (dWorldID, dReal linear_threshold)
    dReal dWorldGetAutoDisableLinearThreshold (dWorldID)
    void dWorldSetAutoDisableAngularThreshold (dWorldID, dReal angular_threshold)
    dReal dWorldGetAutoDisableAngularThreshold (dWorldID)
    void dWorldSetAutoDisableSteps (dWorldID, int steps)
    int dWorldGetAutoDisableSteps (dWorldID)
    void dWorldSetAutoDisableTime (dWorldID, dReal time)
    dReal dWorldGetAutoDisableTime (dWorldID)
    dReal dWorldGetLinearDamping (dWorldID)
    void dWorldSetLinearDamping (dWorldID, dReal scale)
    dReal dWorldGetAngularDamping (dWorldID)
    void dWorldSetAngularDamping (dWorldID, dReal scale)
    void dWorldImpulseToForce (dWorldID, dReal stepsize,
                               dReal ix, dReal iy, dReal iz, dVector3 force)

    # Body
    dBodyID dBodyCreate (dWorldID)
    void dBodyDestroy (dBodyID)

    void  dBodySetData (dBodyID, void *data)
    void *dBodyGetData (dBodyID)

    void dBodySetPosition   (dBodyID, dReal x, dReal y, dReal z)
    void dBodySetRotation   (dBodyID, dMatrix3 R)
    void dBodySetQuaternion (dBodyID, dQuaternion q)
    void dBodySetLinearVel  (dBodyID, dReal x, dReal y, dReal z)
    void dBodySetAngularVel (dBodyID, dReal x, dReal y, dReal z)
    dReal * dBodyGetPosition   (dBodyID)
    dReal * dBodyGetRotation   (dBodyID)
    dReal * dBodyGetQuaternion (dBodyID)
    dReal * dBodyGetLinearVel  (dBodyID)
    dReal * dBodyGetAngularVel (dBodyID)

    void dBodySetMass (dBodyID, dMass *mass)
    void dBodyGetMass (dBodyID, dMass *mass)

    void dBodyAddForce            (dBodyID, dReal fx, dReal fy, dReal fz)
    void dBodyAddTorque           (dBodyID, dReal fx, dReal fy, dReal fz)
    void dBodyAddRelForce         (dBodyID, dReal fx, dReal fy, dReal fz)
    void dBodyAddRelTorque        (dBodyID, dReal fx, dReal fy, dReal fz)
    void dBodyAddForceAtPos       (dBodyID, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz)
    void dBodyAddForceAtRelPos    (dBodyID, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz)
    void dBodyAddRelForceAtPos    (dBodyID, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz)
    void dBodyAddRelForceAtRelPos (dBodyID, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz)

    dReal * dBodyGetForce   (dBodyID)
    dReal * dBodyGetTorque  (dBodyID)

    void dBodySetForce(dBodyID, dReal x, dReal y, dReal z)
    void dBodySetTorque(dBodyID, dReal x, dReal y, dReal z)

    void dBodyGetRelPointPos    (dBodyID, dReal px, dReal py, dReal pz, dVector3 result)
    void dBodyGetRelPointVel    (dBodyID, dReal px, dReal py, dReal pz, dVector3 result)
    void dBodyGetPointVel    (dBodyID, dReal px, dReal py, dReal pz,
                              dVector3 result)
    void dBodyGetPosRelPoint (dBodyID, dReal px, dReal py, dReal pz,
                              dVector3 result)
    void dBodyVectorToWorld   (dBodyID, dReal px, dReal py, dReal pz,
                               dVector3 result)
    void dBodyVectorFromWorld (dBodyID, dReal px, dReal py, dReal pz,
                               dVector3 result)

    void dBodySetFiniteRotationMode (dBodyID, int mode)
    void dBodySetFiniteRotationAxis (dBodyID, dReal x, dReal y, dReal z)

    int dBodyGetFiniteRotationMode (dBodyID)
    void dBodyGetFiniteRotationAxis (dBodyID, dVector3 result)

    int dBodyGetNumJoints (dBodyID b)
    dJointID dBodyGetJoint (dBodyID, int index)

    void dBodyEnable (dBodyID)
    void dBodyDisable (dBodyID)
    int dBodyIsEnabled (dBodyID)

    void dBodySetGravityMode (dBodyID b, int mode)
    int dBodyGetGravityMode (dBodyID b)

    void dBodySetDynamic (dBodyID)
    void dBodySetKinematic (dBodyID)
    int dBodyIsKinematic (dBodyID)

    void dBodySetMaxAngularSpeed (dBodyID, dReal max_speed)

    # Joints
    dJointID dJointCreateBall (dWorldID, dJointGroupID)
    dJointID dJointCreateHinge (dWorldID, dJointGroupID)
    dJointID dJointCreateSlider (dWorldID, dJointGroupID)
    dJointID dJointCreateContact (dWorldID, dJointGroupID, dContact *)
    dJointID dJointCreateUniversal (dWorldID, dJointGroupID)
    dJointID dJointCreatePR (dWorldID, dJointGroupID)
    dJointID dJointCreateHinge2 (dWorldID, dJointGroupID)
    dJointID dJointCreateFixed (dWorldID, dJointGroupID)
    dJointID dJointCreateNull (dWorldID, dJointGroupID)
    dJointID dJointCreateAMotor (dWorldID, dJointGroupID)
    dJointID dJointCreateLMotor (dWorldID, dJointGroupID)
    dJointID dJointCreatePlane2D (dWorldID, dJointGroupID)

    void dJointDestroy (dJointID)

    void dJointEnable (dJointID)
    void dJointDisable (dJointID)
    int dJointIsEnabled (dJointID)

    dJointGroupID dJointGroupCreate (int max_size)
    void dJointGroupDestroy (dJointGroupID)
    void dJointGroupEmpty (dJointGroupID)

    void dJointAttach (dJointID, dBodyID body1, dBodyID body2)
    void dJointSetData (dJointID, void *data)
    void *dJointGetData (dJointID)
    int dJointGetType (dJointID)
    dBodyID dJointGetBody (dJointID, int index)

    void dJointSetBallAnchor (dJointID, dReal x, dReal y, dReal z)
    void dJointSetHingeAnchor (dJointID, dReal x, dReal y, dReal z)
    void dJointSetHingeAxis (dJointID, dReal x, dReal y, dReal z)
    void dJointSetHingeParam (dJointID, int parameter, dReal value)
    void dJointAddHingeTorque(dJointID joint, dReal torque)
    void dJointSetSliderAxis (dJointID, dReal x, dReal y, dReal z)
    void dJointSetSliderParam (dJointID, int parameter, dReal value)
    void dJointAddSliderForce(dJointID joint, dReal force)
    void dJointSetHinge2Anchor (dJointID, dReal x, dReal y, dReal z)
    void dJointSetHinge2Axis1 (dJointID, dReal x, dReal y, dReal z)
    void dJointSetHinge2Axis2 (dJointID, dReal x, dReal y, dReal z)
    void dJointSetHinge2Param (dJointID, int parameter, dReal value)
    void dJointAddHinge2Torques(dJointID joint, dReal torque1, dReal torque2)
    void dJointSetUniversalAnchor (dJointID, dReal x, dReal y, dReal z)
    void dJointSetUniversalAxis1 (dJointID, dReal x, dReal y, dReal z)
    void dJointSetUniversalAxis2 (dJointID, dReal x, dReal y, dReal z)
    void dJointSetUniversalParam (dJointID, int parameter, dReal value)
    void dJointAddUniversalTorques(dJointID joint, dReal torque1, dReal torque2)
    void dJointSetFixed (dJointID)
    void dJointSetAMotorNumAxes (dJointID, int num)
    void dJointSetAMotorAxis (dJointID, int anum, int rel, dReal x, dReal y, dReal z)
    void dJointSetAMotorAngle (dJointID, int anum, dReal angle)
    void dJointSetAMotorParam (dJointID, int parameter, dReal value)
    void dJointSetAMotorMode (dJointID, int mode)
    void dJointAddAMotorTorques (dJointID, dReal torque1, dReal torque2, dReal torque3)
    void dJointSetLMotorAxis (dJointID, int anum, int rel, dReal x, dReal y, dReal z)
    void dJointSetLMotorNumAxes (dJointID, int num)
    void dJointSetLMotorParam (dJointID, int parameter, dReal value)
    
    void dJointGetBallAnchor (dJointID, dVector3 result)
    void dJointGetBallAnchor2 (dJointID, dVector3 result)
    void dJointGetHingeAnchor (dJointID, dVector3 result)
    void dJointGetHingeAnchor2 (dJointID, dVector3 result)
    void dJointGetHingeAxis (dJointID, dVector3 result)
    dReal dJointGetHingeParam (dJointID, int parameter)
    dReal dJointGetHingeAngle (dJointID)
    dReal dJointGetHingeAngleRate (dJointID)
    dReal dJointGetSliderPosition (dJointID)
    dReal dJointGetSliderPositionRate (dJointID)
    void dJointGetSliderAxis (dJointID, dVector3 result)
    dReal dJointGetSliderParam (dJointID, int parameter)
    void dJointGetHinge2Anchor (dJointID, dVector3 result)
    void dJointGetHinge2Anchor2 (dJointID, dVector3 result)
    void dJointGetHinge2Axis1 (dJointID, dVector3 result)
    void dJointGetHinge2Axis2 (dJointID, dVector3 result)
    dReal dJointGetHinge2Param (dJointID, int parameter)
    dReal dJointGetHinge2Angle1 (dJointID)
    dReal dJointGetHinge2Angle1Rate (dJointID)
    dReal dJointGetHinge2Angle2Rate (dJointID)
    void dJointGetUniversalAnchor (dJointID, dVector3 result)
    void dJointGetUniversalAnchor2 (dJointID, dVector3 result)
    void dJointGetUniversalAxis1 (dJointID, dVector3 result)
    void dJointGetUniversalAxis2 (dJointID, dVector3 result)
    dReal dJointGetUniversalParam (dJointID, int parameter)
    dReal dJointGetUniversalAngle1 (dJointID)
    dReal dJointGetUniversalAngle2 (dJointID)
    dReal dJointGetUniversalAngle1Rate (dJointID)
    dReal dJointGetUniversalAngle2Rate (dJointID)
    int dJointGetAMotorNumAxes (dJointID)
    void dJointGetAMotorAxis (dJointID, int anum, dVector3 result)
    int dJointGetAMotorAxisRel (dJointID, int anum)
    dReal dJointGetAMotorAngle (dJointID, int anum)
    dReal dJointGetAMotorAngleRate (dJointID, int anum)
    dReal dJointGetAMotorParam (dJointID, int parameter)
    int dJointGetAMotorMode (dJointID)
    int dJointGetLMotorNumAxes (dJointID)
    void dJointGetLMotorAxis (dJointID, int anum, dVector3 result)
    dReal dJointGetLMotorParam (dJointID, int parameter)
    void dJointSetPlane2DXParam (dJointID, int parameter, dReal value)
    void dJointSetPlane2DYParam (dJointID, int parameter, dReal value)
    void dJointSetPlane2DAngleParam (dJointID, int parameter, dReal value)
    dReal dJointGetPRPosition (dJointID j)
    void dJointSetPRAnchor (dJointID j, dReal x, dReal y, dReal z)
    void dJointSetPRAxis1 (dJointID j, dReal x, dReal y, dReal z)
    void dJointSetPRAxis2 (dJointID j, dReal x, dReal y, dReal z)
    void dJointGetPRAnchor (dJointID j, dVector3 result)
    void dJointGetPRAxis1 (dJointID j, dVector3 result)
    void dJointGetPRAxis2 (dJointID j, dVector3 result)

    void dJointSetFeedback (dJointID, dJointFeedback *)
    dJointFeedback *dJointGetFeedback (dJointID)

    int dAreConnected (dBodyID, dBodyID)

    # Mass
    void dMassSetZero (dMass *)
    void dMassSetParameters (dMass *, dReal themass,
             dReal cgx, dReal cgy, dReal cgz,
             dReal I11, dReal I22, dReal I33,
             dReal I12, dReal I13, dReal I23)
    void dMassSetSphere (dMass *, dReal density, dReal radius)
    void dMassSetSphereTotal (dMass *, dReal total_mass, dReal radius)
    void dMassSetCapsule (dMass *, dReal density, int direction, dReal radius, dReal length)
    void dMassSetCapsuleTotal (dMass *, dReal total_mass, int direction, dReal radius, dReal length)
    void dMassSetCylinder (dMass *, dReal density, int direction,
          dReal radius, dReal length)
    void dMassSetCylinderTotal (dMass *, dReal total_mass, int direction,
          dReal radius, dReal length)
    void dMassSetBox (dMass *, dReal density,
          dReal lx, dReal ly, dReal lz)
    void dMassSetBoxTotal (dMass *, dReal total_mass,
          dReal lx, dReal ly, dReal lz)
    void dMassAdjust (dMass *, dReal newmass)
    void dMassTranslate (dMass *, dReal x, dReal y, dReal z)
    void dMassRotate (dMass *, dMatrix3 R)
    void dMassAdd (dMass *a, dMass *b)

    # Space
#    dSpaceID dSimpleSpaceCreate(int space)
#    dSpaceID dHashSpaceCreate(int space)
    dSpaceID dSimpleSpaceCreate(dSpaceID space)
    dSpaceID dHashSpaceCreate(dSpaceID space)
    dSpaceID dQuadTreeSpaceCreate (dSpaceID space, dVector3 Center,
                                   dVector3 Extents, int Depth)

    void dSpaceDestroy (dSpaceID)
    void dSpaceAdd (dSpaceID, dGeomID)
    void dSpaceRemove (dSpaceID, dGeomID)
    int dSpaceQuery (dSpaceID, dGeomID)
    void dSpaceCollide (dSpaceID space, void *data, dNearCallback *callback)
    void dSpaceCollide2 (dGeomID o1, dGeomID o2, void *data, dNearCallback *callback)

    void dHashSpaceSetLevels (dSpaceID space, int minlevel, int maxlevel)
    void dHashSpaceGetLevels (dSpaceID space, int *minlevel, int *maxlevel)

    void dSpaceSetCleanup (dSpaceID space, int mode)
    int dSpaceGetCleanup (dSpaceID space)

    int dSpaceGetNumGeoms (dSpaceID)
    dGeomID dSpaceGetGeom (dSpaceID, int i)

    # Geom
    dGeomID dCreateSphere (dSpaceID space, dReal radius)
    dGeomID dCreateBox (dSpaceID space, dReal lx, dReal ly, dReal lz)
    dGeomID dCreatePlane (dSpaceID space, dReal a, dReal b, dReal c, dReal d)
    dGeomID dCreateCapsule (dSpaceID space, dReal radius, dReal length)
    dGeomID dCreateCylinder (dSpaceID space, dReal radius, dReal length)
    dGeomID dCreateGeomGroup (dSpaceID space)

    void dGeomSphereSetRadius (dGeomID sphere, dReal radius)
    void dGeomBoxSetLengths (dGeomID box, dReal lx, dReal ly, dReal lz)
    void dGeomPlaneSetParams (dGeomID plane, dReal a, dReal b, dReal c, dReal d)
    void dGeomCapsuleSetParams (dGeomID ccylinder, dReal radius, dReal length)
    void dGeomCylinderSetParams (dGeomID ccylinder, dReal radius, dReal length)

    dReal dGeomSphereGetRadius (dGeomID sphere)
    void  dGeomBoxGetLengths (dGeomID box, dVector3 result)
    void  dGeomPlaneGetParams (dGeomID plane, dVector4 result)
    void  dGeomCapsuleGetParams (dGeomID ccylinder, dReal *radius, dReal *length)
    void  dGeomCylinderGetParams (dGeomID ccylinder, dReal *radius, dReal *length)

    dReal dGeomSpherePointDepth (dGeomID sphere, dReal x, dReal y, dReal z)
    dReal dGeomBoxPointDepth (dGeomID box, dReal x, dReal y, dReal z)
    dReal dGeomPlanePointDepth (dGeomID plane, dReal x, dReal y, dReal z)
    dReal dGeomCapsulePointDepth (dGeomID ccylinder, dReal x, dReal y, dReal z)

    dGeomID dCreateRay (dSpaceID space, dReal length)
    void dGeomRaySetLength (dGeomID ray, dReal length)
    dReal dGeomRayGetLength (dGeomID ray)
    void dGeomRaySet (dGeomID ray, dReal px, dReal py, dReal pz,
          dReal dx, dReal dy, dReal dz)
    void dGeomRayGet (dGeomID ray, dVector3 start, dVector3 dir)

    void dGeomSetData (dGeomID, void *)
    void *dGeomGetData (dGeomID)
    void dGeomSetBody (dGeomID, dBodyID)
    dBodyID dGeomGetBody (dGeomID)
    void dGeomSetPosition (dGeomID, dReal x, dReal y, dReal z)
    void dGeomSetRotation (dGeomID, dMatrix3 R)
    void dGeomSetQuaternion (dGeomID, dQuaternion)
    dReal * dGeomGetPosition (dGeomID)
    dReal * dGeomGetRotation (dGeomID)
    void dGeomGetQuaternion (dGeomID, dQuaternion result)
    void dGeomSetOffsetPosition (dGeomID, dReal x, dReal y, dReal z)
    void dGeomSetOffsetRotation (dGeomID, dMatrix3 R)
    void dGeomClearOffset (dGeomID)
    dReal * dGeomGetOffsetPosition (dGeomID)
    dReal * dGeomGetOffsetRotation (dGeomID)
    void dGeomDestroy (dGeomID)
    void dGeomGetAABB (dGeomID, dReal aabb[6])
    dReal *dGeomGetSpaceAABB (dGeomID)
    int dGeomIsSpace (dGeomID)
    dSpaceID dGeomGetSpace (dGeomID)
    int dGeomGetClass (dGeomID)

    void dGeomSetCategoryBits(dGeomID, unsigned long bits)
    void dGeomSetCollideBits(dGeomID, unsigned long bits)
    unsigned long dGeomGetCategoryBits(dGeomID)
    unsigned long dGeomGetCollideBits(dGeomID)     

    void dGeomEnable (dGeomID)
    void dGeomDisable (dGeomID)
    int dGeomIsEnabled (dGeomID)

    void dGeomGroupAdd (dGeomID group, dGeomID x)
    void dGeomGroupRemove (dGeomID group, dGeomID x)
    int dGeomGroupGetNumGeoms (dGeomID group)
    dGeomID dGeomGroupGetGeom (dGeomID group, int i)

    dGeomID dCreateGeomTransform (dSpaceID space)
    void dGeomTransformSetGeom (dGeomID g, dGeomID obj)
    dGeomID dGeomTransformGetGeom (dGeomID g)
    void dGeomTransformSetCleanup (dGeomID g, int mode)
    int dGeomTransformGetCleanup (dGeomID g)
    void dGeomTransformSetInfo (dGeomID g, int mode)
    int dGeomTransformGetInfo (dGeomID g)

    int dCollide (dGeomID o1, dGeomID o2, int flags, dContactGeom *contact, int skip)

    # Trimesh
    dTriMeshDataID dGeomTriMeshDataCreate()
    void dGeomTriMeshDataDestroy(dTriMeshDataID g)
    void dGeomTriMeshDataBuildSingle1 (dTriMeshDataID g, void* Vertices,
                                int VertexStride, int VertexCount,
                                void* Indices, int IndexCount,
                                int TriStride, void* Normals)
    
    void dGeomTriMeshDataBuildSimple(dTriMeshDataID g,
                                 dReal* Vertices, int VertexCount,
                                 int* Indices, int IndexCount)

    dGeomID dCreateTriMesh (dSpaceID space, dTriMeshDataID Data,
                            void* Callback,
                            void* ArrayCallback,
                            void* RayCallback)   

    void dGeomTriMeshSetData (dGeomID g, dTriMeshDataID Data)
    
    void dGeomTriMeshClearTCCache (dGeomID g)

    void dGeomTriMeshGetTriangle (dGeomID g, int Index, dVector3 *v0,
                                  dVector3 *v1, dVector3 *v2)

    int dGeomTriMeshGetTriangleCount (dGeomID g)

    void dGeomTriMeshGetPoint (dGeomID g, int Index, dReal u, dReal v,
                               dVector3 Out)

    void dGeomTriMeshEnableTC(dGeomID g, int geomClass, int enable)
    int dGeomTriMeshIsTCEnabled(dGeomID g, int geomClass)

    # Heightfield
    dHeightfieldDataID dGeomHeightfieldDataCreate()
    void dGeomHeightfieldDataDestroy(dHeightfieldDataID g)
    void dGeomHeightfieldDataBuildCallback(dHeightfieldDataID d,
                                           void* pUserData,
                                           dHeightfieldGetHeight* pCallback,
                                           dReal width, dReal depth,
                                           int widthSamples, int depthSamples,
                                           dReal scale, dReal offset,
                                           dReal thickness, int bWrap)
    dGeomID dCreateHeightfield (dSpaceID space, dHeightfieldDataID data,
                                 int bPlaceable)

ode-0.16/bindings/python/INSTALL.txt0000664000175200017520000000342513403272463014133 000000000000001. REQUIREMENTS:

1. Python 2.4 or higher (http://www.python.org/)
   - Tested with Python 2.7 (2.6 on earlier builds)
2. Cython 0.14.1** or higher (http://cython.org/)
   - Tested with Cython 0.15 (0.14.1 on earlier builds)
3. ODE shared*** library (or static with -fPIC)
   - See the notes on building ODE below.
4. pkg-config (http://www.freedesktop.org/wiki/Software/pkg-config)
   - Windows executable (and GLib dependency) can be downloaded from
     http://www.gtk.org/download/win32.php
   - If you used premake to configure ODE, you may need to create an ode.pc file
     in your PKG_CONFIG_PATH manually.  See /ode.pc.in



2. BUILDING ODE

 On certain systems (*nix) there is a requirement that a shared library
 (such as the python module) contains only position-independent code
 (PIC). In those cases, ODE needs to be either compiled as a shared library
 too (--enable-shared), or as a static library with PIC (-fPIC).

 Once ODE is built and installed in your desired destination, proceed with
 building the wrapper.



3a. BUILDING WITH Visual Studio (Windows)

   python setup.py build_ext


3b. BUILDING WITH MINGW (Windows)

   python setup.py build_ext -c mingw32


3c. BUILDING WITH GCC/G++ (Linux, OS X, etc.)

   python setup.py build_ext



4. INSTALLATION

4a. For system-wide installation (needs administrator privileges):

    python setup.py install
    
4b. For user installation:

    python setup.py install --user



5. DEMOS and DOCUMENTATION

 Try running the tutorials in the 'demos' directory.  The tutorials were taken
 from the PyODE website (http://pyode.sourceforge.net/).

 For usage documentation, please refer to the PyODE API documentation at
 http://pyode.sourceforge.net/api-1.2.0/index.html.

ode-0.16/bindings/python/demos/0000775000175200017520000000000013403272463013447 500000000000000ode-0.16/bindings/python/demos/tutorial3.py0000664000175200017520000001405413403272463015673 00000000000000#!/usr/bin/env python

# http://pyode.sourceforge.net/tutorials/tutorial3.html

# pyODE example 3: Collision detection

# Originally by Matthias Baas.
# Updated by Pierre Gay to work without pygame or cgkit.

import sys, os, random, time
from math import *
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *

import ode

# geometric utility functions
def scalp (vec, scal):
    vec[0] *= scal
    vec[1] *= scal
    vec[2] *= scal

def length (vec):
    return sqrt (vec[0]**2 + vec[1]**2 + vec[2]**2)

# prepare_GL
def prepare_GL():
    """Prepare drawing.
    """

    # Viewport
    glViewport(0,0,640,480)

    # Initialize
    glClearColor(0.8,0.8,0.9,0)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST)
    glDisable(GL_LIGHTING)
    glEnable(GL_LIGHTING)
    glEnable(GL_NORMALIZE)
    glShadeModel(GL_FLAT)

    # Projection
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluPerspective (45,1.3333,0.2,20)

    # Initialize ModelView matrix
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()

    # Light source
    glLightfv(GL_LIGHT0,GL_POSITION,[0,0,1,0])
    glLightfv(GL_LIGHT0,GL_DIFFUSE,[1,1,1,1])
    glLightfv(GL_LIGHT0,GL_SPECULAR,[1,1,1,1])
    glEnable(GL_LIGHT0)

    # View transformation
    gluLookAt (2.4, 3.6, 4.8, 0.5, 0.5, 0, 0, 1, 0)

# draw_body
def draw_body(body):
    """Draw an ODE body.
    """

    x,y,z = body.getPosition()
    R = body.getRotation()
    rot = [R[0], R[3], R[6], 0.,
           R[1], R[4], R[7], 0.,
           R[2], R[5], R[8], 0.,
           x, y, z, 1.0]
    glPushMatrix()
    glMultMatrixd(rot)
    if body.shape=="box":
        sx,sy,sz = body.boxsize
        glScalef(sx, sy, sz)
        glutSolidCube(1)
    glPopMatrix()


# create_box
def create_box(world, space, density, lx, ly, lz):
    """Create a box body and its corresponding geom."""

    # Create body
    body = ode.Body(world)
    M = ode.Mass()
    M.setBox(density, lx, ly, lz)
    body.setMass(M)

    # Set parameters for drawing the body
    body.shape = "box"
    body.boxsize = (lx, ly, lz)

    # Create a box geom for collision detection
    geom = ode.GeomBox(space, lengths=body.boxsize)
    geom.setBody(body)

    return body, geom

# drop_object
def drop_object():
    """Drop an object into the scene."""

    global bodies, geom, counter, objcount

    body, geom = create_box(world, space, 1000, 1.0,0.2,0.2)
    body.setPosition( (random.gauss(0,0.1),3.0,random.gauss(0,0.1)) )
    theta = random.uniform(0,2*pi)
    ct = cos (theta)
    st = sin (theta)
    body.setRotation([ct, 0., -st, 0., 1., 0., st, 0., ct])
    bodies.append(body)
    geoms.append(geom)
    counter=0
    objcount+=1

# explosion
def explosion():
    """Simulate an explosion.

    Every object is pushed away from the origin.
    The force is dependent on the objects distance from the origin.
    """
    global bodies

    for b in bodies:
        l=b.getPosition ()
        d = length (l)
        a = max(0, 40000*(1.0-0.2*d*d))
        l = [l[0] / 4, l[1], l[2] /4]
        scalp (l, a / length (l))
        b.addForce(l)

# pull
def pull():
    """Pull the objects back to the origin.

    Every object will be pulled back to the origin.
    Every couple of frames there'll be a thrust upwards so that
    the objects won't stick to the ground all the time.
    """
    global bodies, counter

    for b in bodies:
        l=list (b.getPosition ())
        scalp (l, -1000 / length (l))
        b.addForce(l)
        if counter%60==0:
            b.addForce((0,10000,0))

# Collision callback
def near_callback(args, geom1, geom2):
    """Callback function for the collide() method.

    This function checks if the given geoms do collide and
    creates contact joints if they do.
    """

    # Check if the objects do collide
    contacts = ode.collide(geom1, geom2)

    # Create contact joints
    world,contactgroup = args
    for c in contacts:
        c.setBounce(0.2)
        c.setMu(5000)
        j = ode.ContactJoint(world, contactgroup, c)
        j.attach(geom1.getBody(), geom2.getBody())



######################################################################

# Initialize Glut
glutInit ([])

# Open a window
glutInitDisplayMode (GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE)

x = 0
y = 0
width = 640
height = 480
glutInitWindowPosition (x, y);
glutInitWindowSize (width, height);
glutCreateWindow ("testode")

# Create a world object
world = ode.World()
world.setGravity( (0,-9.81,0) )
world.setERP(0.8)
world.setCFM(1E-5)

# Create a space object
space = ode.Space()

# Create a plane geom which prevent the objects from falling forever
floor = ode.GeomPlane(space, (0,1,0), 0)

# A list with ODE bodies
bodies = []

# The geoms for each of the bodies
geoms = []

# A joint group for the contact joints that are generated whenever
# two bodies collide
contactgroup = ode.JointGroup()

# Some variables used inside the simulation loop
fps = 50
dt = 1.0/fps
running = True
state = 0
counter = 0
objcount = 0
lasttime = time.time()


# keyboard callback
def _keyfunc (c, x, y):
    sys.exit (0)

glutKeyboardFunc (_keyfunc)

# draw callback
def _drawfunc ():
    # Draw the scene
    prepare_GL()
    for b in bodies:
        draw_body(b)

    glutSwapBuffers ()

glutDisplayFunc (_drawfunc)

# idle callback
def _idlefunc ():
    global counter, state, lasttime

    t = dt - (time.time() - lasttime)
    if (t > 0):
        time.sleep(t)

    counter += 1

    if state==0:
        if counter==20:
            drop_object()
        if objcount==30:
            state=1
            counter=0
    # State 1: Explosion and pulling back the objects
    elif state==1:
        if counter==100:
            explosion()
        if counter>300:
            pull()
        if counter==500:
            counter=20

    glutPostRedisplay ()

    # Simulate
    n = 4

    for i in range(n):
        # Detect collisions and create contact joints
        space.collide((world,contactgroup), near_callback)

        # Simulation step
        world.step(dt/n)

        # Remove all contact joints
        contactgroup.empty()

    lasttime = time.time()

glutIdleFunc (_idlefunc)

glutMainLoop ()

ode-0.16/bindings/python/demos/tutorial1.py0000775000175200017520000000232213403272463015667 00000000000000#!/usr/bin/env python

# http://pyode.sourceforge.net/tutorials/tutorial1.html

# pyODE example 1: Getting started

# modified by Gideon Klompje (removed literals and using
# 'ode.Mass.setSphereTotal' instead of 'ode.Mass.setSphere')

import ode

# Simulation constants
GRAVITY = (0, -9.81, 0)

SPHERE_RADIUS = 0.05
SPHERE_MASS = 1.0
SPHERE_START_POS = (0, 2, 0)
SPHERE_FORCE = (0, 200, 0) # Initial force to apply to the sphere

TIME_STEP = 0.04
TIME_STOP = 2.0 # When to stop the simulation

# Create a world object
world = ode.World()
world.setGravity(GRAVITY)

# Create a spherical body inside the world
body = ode.Body(world)
mass = ode.Mass()
mass.setSphereTotal(SPHERE_MASS, SPHERE_RADIUS)
body.setMass(mass)

body.setPosition(SPHERE_START_POS)
body.addForce(SPHERE_FORCE)

# Do the simulation...
if __name__ == "__main__":
    total_time = 0.0
    while total_time < TIME_STOP:
        # output the body's position and velocity
        x, y, z = body.getPosition()
        u, v, w = body.getLinearVel()
        print "%1.2fsec: pos=(%6.3f, %6.3f, %6.3f)  vel=(%6.3f, %6.3f, %6.3f)" % \
            (total_time, x, y, z, u, v, w)

        # advance the simulation
        world.step(TIME_STEP)
        total_time += TIME_STEP

ode-0.16/bindings/python/demos/tutorial2.py0000775000175200017520000000660613403272463015701 00000000000000#!/usr/bin/env python

# http://pyode.sourceforge.net/tutorials/tutorial2.html

# pyODE example 2: Connecting bodies with joints

# modified by Gideon Klompje (removed literals and using
# 'ode.Mass.setSphereTotal' instead of 'ode.Mass.setSphere')


import ode
import pygame

from pygame.locals import QUIT, KEYDOWN

# Constants
WINDOW_RESOLUTION = (640, 480)

DRAW_SCALE = WINDOW_RESOLUTION[0] / 5
"""Factor to multiply physical coordinates by to obtain screen size in pixels"""

DRAW_OFFSET = (WINDOW_RESOLUTION[0] / 2, 50)
"""Screen coordinates (in pixels) that map to the physical origin (0, 0, 0)"""

BACKGROUND_COLOR = (255, 255, 255)

GRAVITY = (0, -9.81, 0)

SPHERE1_POSITION = (1, 0, 0)
SPHERE1_MASS = 1
SPHERE1_RADIUS = 0.15
SPHERE1_COLOR = (55, 0, 200)

SPHERE2_POSITION = (2, 0, 0)
SPHERE2_MASS = 1
SPHERE2_RADIUS = 0.15
SPHERE2_COLOR = (55, 0, 200)

JOINT1_ANCHOR = (0, 0, 0)
JOINT1_COLOR = (200, 0, 55)
JOINT1_WIDTH = 2
"""Width of the line (in pixels) representing the joint"""

JOINT2_ANCHOR = SPHERE1_POSITION
JOINT2_COLOR = (200, 0, 55)
JOINT2_WIDTH = 2
"""Width of the line (in pixels) representing the joint"""

TIME_STEP = 0.04

# Utility functions
def coord(x, y, integer=False):
    """
    Convert world coordinates to pixel coordinates.  Setting 'integer' to
    True will return integer coordinates.
    """
    xs = (DRAW_OFFSET[0] + DRAW_SCALE*x)
    ys = (DRAW_OFFSET[1] - DRAW_SCALE*y)

    if integer:
        return int(round(xs)), int(round(ys))
    else:
        return xs, ys

# Initialize pygame
pygame.init()

# Open a display
screen = pygame.display.set_mode(WINDOW_RESOLUTION)

# Create a world object
world = ode.World()
world.setGravity(GRAVITY)

# Create two bodies
body1 = ode.Body(world)
M = ode.Mass()
M.setSphereTotal(SPHERE1_MASS, SPHERE1_RADIUS)
body1.setMass(M)
body1.setPosition(SPHERE1_POSITION)

body2 = ode.Body(world)
M = ode.Mass()
M.setSphereTotal(SPHERE2_MASS, SPHERE2_RADIUS)
body2.setMass(M)
body2.setPosition(SPHERE2_POSITION)

# Connect body1 with the static environment
j1 = ode.BallJoint(world)
j1.attach(body1, ode.environment)
j1.setAnchor(JOINT1_ANCHOR)

# Connect body2 with body1
j2 = ode.BallJoint(world)
j2.attach(body1, body2)
j2.setAnchor(JOINT2_ANCHOR)

# Simulation loop...
if __name__ == "__main__":
    fps = 1.0 / TIME_STEP
    clk = pygame.time.Clock()

    sph1_rad = int(DRAW_SCALE * SPHERE1_RADIUS)
    sph2_rad = int(DRAW_SCALE * SPHERE2_RADIUS)

    loopFlag = True
    while loopFlag:
        for e in pygame.event.get():
            if e.type==QUIT:
                loopFlag=False
            if e.type==KEYDOWN:
                loopFlag=False

        # Clear the screen
        screen.fill(BACKGROUND_COLOR)

        # Draw the two bodies and the lines representing the joints
        x1, y1, z1 = body1.getPosition()
        x2, y2, z2 = body2.getPosition()
        xj1, yj1, zj1 = j1.getAnchor()
        xj2, yj2, zj2 = j2.getAnchor()

        pygame.draw.line(screen, JOINT1_COLOR, coord(xj1, yj1), coord(x1, y1), JOINT1_WIDTH)
        pygame.draw.line(screen, JOINT2_COLOR, coord(xj2, yj2), coord(x2, y2), JOINT2_WIDTH)
        pygame.draw.circle(screen, SPHERE1_COLOR, coord(x1, y1, integer=True), sph1_rad, 0)
        pygame.draw.circle(screen, SPHERE2_COLOR, coord(x2, y2, integer=True), sph2_rad, 0)

        pygame.display.flip()

        # Next simulation step
        world.step(TIME_STEP)

        # Try to keep the specified framerate    
        clk.tick(fps)

ode-0.16/bindings/python/TODO.txt0000664000175200017520000000106713403272463013572 00000000000000CODE:
* (setup.py) add package information (version, authors, etc.)
* (setup.py) add 'install' action
* (setup.py) add configurable ODE DLL (currently hard-coded to default single precision)
* (ode.pxd)  clean up, add more comments
* (ode.pyx)  refactor for a more Pythonic implementation (e.g. replace getters and setters with
             properties)?
* (?)        Add option to build bindings in ODE's makefiles


DOCS:

* Update and include API docs from PyODE
* Adapt and include PyODE tutorials/demos
* Update license text in ode.pxd and ode.pyx
ode-0.16/bindings/python/ode.pyx0000664000175200017520000040552313403272463013602 00000000000000######################################################################
# Python Open Dynamics Engine Wrapper
# Copyright (C) 2004 PyODE developers (see file AUTHORS)
# All rights reserved.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of EITHER:
#   (1) The GNU Lesser General Public License as published by the Free
#       Software Foundation; either version 2.1 of the License, or (at
#       your option) any later version. The text of the GNU Lesser
#       General Public License is included with this library in the
#       file LICENSE.
#   (2) The BSD-style license that is included with this library in
#       the file LICENSE-BSD.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
# LICENSE and LICENSE-BSD for more details.
######################################################################

from ode cimport *


paramLoStop        = 0
paramHiStop        = 1
paramVel           = 2
paramLoVel         = 3
paramHiVel         = 4
paramFMax          = 5
paramFudgeFactor   = 6
paramBounce        = 7
paramCFM           = 8
paramStopERP       = 9
paramStopCFM       = 10
paramSuspensionERP = 11
paramSuspensionCFM = 12
paramERP           = 13

ParamLoStop        = 0
ParamHiStop        = 1
ParamVel           = 2
ParamLoVel         = 3
ParamHiVel         = 4
ParamFMax          = 5
ParamFudgeFactor   = 6
ParamBounce        = 7
ParamCFM           = 8
ParamStopERP       = 9
ParamStopCFM       = 10
ParamSuspensionERP = 11
ParamSuspensionCFM = 12
ParamERP           = 13

ParamLoStop2        = 256 + 0
ParamHiStop2        = 256 + 1
ParamVel2           = 256 + 2
ParamLoVel2         = 256 + 3
ParamHiVel2         = 256 + 4
ParamFMax2          = 256 + 5
ParamFudgeFactor2   = 256 + 6
ParamBounce2        = 256 + 7
ParamCFM2           = 256 + 8
ParamStopERP2       = 256 + 9
ParamStopCFM2       = 256 + 10
ParamSuspensionERP2 = 256 + 11
ParamSuspensionCFM2 = 256 + 12
ParamERP2           = 256 + 13

ParamLoStop3        = 512 + 0
ParamHiStop3        = 512 + 1
ParamVel3           = 512 + 2
ParamLoVel3         = 512 + 3
ParamHiVel3         = 512 + 4
ParamFMax3          = 512 + 5
ParamFudgeFactor3   = 512 + 6
ParamBounce3        = 512 + 7
ParamCFM3           = 512 + 8
ParamStopERP3       = 512 + 9
ParamStopCFM3       = 512 + 10
ParamSuspensionERP3 = 512 + 11
ParamSuspensionCFM3 = 512 + 12
ParamERP3           = 512 + 13

ParamGroup = 256

ContactMu2          = 0x001
ContactAxisDep      = 0x001
ContactFDir1        = 0x002
ContactBounce       = 0x004
ContactSoftERP      = 0x008
ContactSoftCFM      = 0x010
ContactMotion1      = 0x020
ContactMotion2      = 0x040
ContactMotionN      = 0x080
ContactSlip1        = 0x100
ContactSlip2        = 0x200
ContactRolling      = 0x400

ContactApprox0      = 0x0000
ContactApprox1_1    = 0x1000
ContactApprox1_2    = 0x2000
ContactApprox1_N    = 0x4000
ContactApprox1      = 0x7000

AMotorUser = dAMotorUser
AMotorEuler = dAMotorEuler

Infinity = dInfinity


import weakref
_geom_c2py_lut = weakref.WeakValueDictionary()


cdef class Mass:
    """Mass parameters of a rigid body.

    This class stores mass parameters of a rigid body which can be
    accessed through the following attributes:

     - mass: The total mass of the body (float)
     - c:    The center of gravity position in body frame (3-tuple of floats)
     - I:    The 3x3 inertia tensor in body frame (3-tuple of 3-tuples)

    This class wraps the dMass structure from the C API.

    @ivar mass: The total mass of the body
    @ivar c: The center of gravity position in body frame (cx, cy, cz)
    @ivar I: The 3x3 inertia tensor in body frame ((I11, I12, I13), (I12, I22, I23), (I13, I23, I33))
    @type mass: float
    @type c: 3-tuple of floats
    @type I: 3-tuple of 3-tuples of floats
    """
    cdef dMass _mass

    def __cinit__(self):
        dMassSetZero(&self._mass)

    def setZero(self):
        """setZero()

        Set all the mass parameters to zero."""
        dMassSetZero(&self._mass)

    def setParameters(self, mass, cgx, cgy, cgz, I11, I22, I33, I12, I13, I23):
        """setParameters(mass, cgx, cgy, cgz, I11, I22, I33, I12, I13, I23)

        Set the mass parameters to the given values.

        @param mass: Total mass of the body.
        @param cgx: Center of gravity position in the body frame (x component).
        @param cgy: Center of gravity position in the body frame (y component).
        @param cgz: Center of gravity position in the body frame (z component).
        @param I11: Inertia tensor
        @param I22: Inertia tensor
        @param I33: Inertia tensor
        @param I12: Inertia tensor
        @param I13: Inertia tensor
        @param I23: Inertia tensor
        @type mass: float
        @type cgx: float
        @type cgy: float
        @type cgz: float
        @type I11: float
        @type I22: float
        @type I33: float
        @type I12: float
        @type I13: float
        @type I23: float
        """
        dMassSetParameters(&self._mass, mass, cgx, cgy, cgz,
                           I11, I22, I33, I12, I13, I23)

    def setSphere(self, density, radius):
        """setSphere(density, radius)
        
        Set the mass parameters to represent a sphere of the given radius
        and density, with the center of mass at (0,0,0) relative to the body.

        @param density: The density of the sphere
        @param radius: The radius of the sphere
        @type density: float
        @type radius: float
        """
        dMassSetSphere(&self._mass, density, radius)

    def setSphereTotal(self, total_mass, radius):
        """setSphereTotal(total_mass, radius)
        
        Set the mass parameters to represent a sphere of the given radius
        and mass, with the center of mass at (0,0,0) relative to the body.

        @param total_mass: The total mass of the sphere
        @param radius: The radius of the sphere
        @type total_mass: float
        @type radius: float
        """
        dMassSetSphereTotal(&self._mass, total_mass, radius)

    def setCapsule(self, density, direction, radius, length):
        """setCapsule(density, direction, radius, length)

        Set the mass parameters to represent a capsule of the given parameters
        and density, with the center of mass at (0,0,0) relative to the body.
        The radius of the cylinder (and the spherical cap) is radius. The length
        of the cylinder (not counting the spherical cap) is length. The
        cylinder's long axis is oriented along the body's x, y or z axis
        according to the value of direction (1=x, 2=y, 3=z). The first function
        accepts the density of the object, the second accepts its total mass.

        @param density: The density of the capsule
        @param direction: The direction of the capsule's cylinder (1=x axis, 2=y axis, 3=z axis)
        @param radius: The radius of the capsule's cylinder
        @param length: The length of the capsule's cylinder (without the caps)
        @type density: float
        @type direction: int
        @type radius: float
        @type length: float
        """
        dMassSetCapsule(&self._mass, density, direction, radius, length)

    def setCapsuleTotal(self, total_mass, direction, radius, length):
        """setCapsuleTotal(total_mass, direction, radius, length)

        Set the mass parameters to represent a capsule of the given parameters
        and mass, with the center of mass at (0,0,0) relative to the body. The
        radius of the cylinder (and the spherical cap) is radius. The length of
        the cylinder (not counting the spherical cap) is length. The cylinder's
        long axis is oriented along the body's x, y or z axis according to the
        value of direction (1=x, 2=y, 3=z). The first function accepts the
        density of the object, the second accepts its total mass.

        @param total_mass: The total mass of the capsule
        @param direction: The direction of the capsule's cylinder (1=x axis, 2=y axis, 3=z axis)
        @param radius: The radius of the capsule's cylinder
        @param length: The length of the capsule's cylinder (without the caps)
        @type total_mass: float
        @type direction: int
        @type radius: float
        @type length: float
        """
        dMassSetCapsuleTotal(&self._mass, total_mass, direction,
                             radius, length)

    def setCylinder(self, density, direction, r, h):
        """setCylinder(density, direction, r, h)
        
        Set the mass parameters to represent a flat-ended cylinder of
        the given parameters and density, with the center of mass at
        (0,0,0) relative to the body. The radius of the cylinder is r.
        The length of the cylinder is h. The cylinder's long axis is
        oriented along the body's x, y or z axis according to the value
        of direction (1=x, 2=y, 3=z).

        @param density: The density of the cylinder
        @param direction: The direction of the cylinder (1=x axis, 2=y axis, 3=z axis)
        @param r: The radius of the cylinder
        @param h: The length of the cylinder
        @type density: float
        @type direction: int
        @type r: float
        @type h: float
        """
        dMassSetCylinder(&self._mass, density, direction, r, h)

    def setCylinderTotal(self, total_mass, direction, r, h):
        """setCylinderTotal(total_mass, direction, r, h)
        
        Set the mass parameters to represent a flat-ended cylinder of
        the given parameters and mass, with the center of mass at
        (0,0,0) relative to the body. The radius of the cylinder is r.
        The length of the cylinder is h. The cylinder's long axis is
        oriented along the body's x, y or z axis according to the value
        of direction (1=x, 2=y, 3=z).

        @param total_mass: The total mass of the cylinder
        @param direction: The direction of the cylinder (1=x axis, 2=y axis, 3=z axis)
        @param r: The radius of the cylinder
        @param h: The length of the cylinder
        @type total_mass: float
        @type direction: int
        @type r: float
        @type h: float
        """
        dMassSetCylinderTotal(&self._mass, total_mass, direction, r, h)

    def setBox(self, density, lx, ly, lz):
        """setBox(density, lx, ly, lz)

        Set the mass parameters to represent a box of the given
        dimensions and density, with the center of mass at (0,0,0)
        relative to the body. The side lengths of the box along the x,
        y and z axes are lx, ly and lz.

        @param density: The density of the box
        @param lx: The length along the x axis
        @param ly: The length along the y axis
        @param lz: The length along the z axis
        @type density: float
        @type lx: float
        @type ly: float
        @type lz: float
        """
        dMassSetBox(&self._mass, density, lx, ly, lz)

    def setBoxTotal(self, total_mass, lx, ly, lz):
        """setBoxTotal(total_mass, lx, ly, lz)

        Set the mass parameters to represent a box of the given
        dimensions and mass, with the center of mass at (0,0,0)
        relative to the body. The side lengths of the box along the x,
        y and z axes are lx, ly and lz.

        @param total_mass: The total mass of the box
        @param lx: The length along the x axis
        @param ly: The length along the y axis
        @param lz: The length along the z axis
        @type total_mass: float
        @type lx: float
        @type ly: float
        @type lz: float
        """
        dMassSetBoxTotal(&self._mass, total_mass, lx, ly, lz)

    def adjust(self, newmass):
        """adjust(newmass)

        Adjust the total mass. Given mass parameters for some object,
        adjust them so the total mass is now newmass. This is useful
        when using the setXyz() methods to set the mass parameters for
        certain objects - they take the object density, not the total
        mass.

        @param newmass: The new total mass
        @type newmass: float
        """
        dMassAdjust(&self._mass, newmass)

    def translate(self, t):
        """translate(t)

        Adjust mass parameters. Given mass parameters for some object,
        adjust them to represent the object displaced by (x,y,z)
        relative to the body frame.

        @param t: Translation vector (x, y, z)
        @type t: 3-tuple of floats
        """
        dMassTranslate(&self._mass, t[0], t[1], t[2])

#    def rotate(self, R):
#        """
#        Given mass parameters for some object, adjust them to
#        represent the object rotated by R relative to the body frame.
#        """
#        pass

    def add(self, Mass b):
        """add(b)

        Add the mass b to the mass object. Masses can also be added using
        the + operator.

        @param b: The mass to add to this mass
        @type b: Mass
        """
        dMassAdd(&self._mass, &b._mass)

    def __getattr__(self, name):
        if name == "mass":
            return self._mass.mass
        elif name == "c":
            return self._mass.c[0], self._mass.c[1], self._mass.c[2]
        elif name == "I":
            return ((self._mass.I[0], self._mass.I[1], self._mass.I[2]),
                    (self._mass.I[4], self._mass.I[5], self._mass.I[6]),
                    (self._mass.I[8], self._mass.I[9], self._mass.I[10]))
        else:
            raise AttributeError("Mass object has no attribute '%s'" % name)

    def __setattr__(self, name, value):
        if name == "mass":
            self.adjust(value)
        elif name == "c":
            raise AttributeError("Use the setParameter() method to change c")
        elif name == "I":
            raise AttributeError("Use the setParameter() method to change I")
        else:
            raise AttributeError("Mass object has no attribute '%s" % name)

    def __add__(self, Mass b):
        self.add(b)
        return self

    def __str__(self):
        m = str(self._mass.mass)
        sc0 = str(self._mass.c[0])
        sc1 = str(self._mass.c[1])
        sc2 = str(self._mass.c[2])
        I11 = str(self._mass.I[0])
        I22 = str(self._mass.I[5])
        I33 = str(self._mass.I[10])
        I12 = str(self._mass.I[1])
        I13 = str(self._mass.I[2])
        I23 = str(self._mass.I[6])
        return ("Mass=%s\n"
                "Cg=(%s, %s, %s)\n"
                "I11=%s I22=%s I33=%s\n"
                "I12=%s I13=%s I23=%s" %
                (m, sc0, sc1, sc2, I11, I22, I33, I12, I13, I23))
#        return ("Mass=%s / "
#                "Cg=(%s, %s, %s) / "
#                "I11=%s I22=%s I33=%s "
#                "I12=%s I13=%s I23=%s" %
#                (m, sc0, sc1, sc2, I11, I22, I33, I12, I13, I23))


cdef class Contact:
    """This class represents a contact between two bodies in one point.

    A Contact object stores all the input parameters for a ContactJoint.
    This class wraps the ODE dContact structure which has 3 components::

     struct dContact {
       dSurfaceParameters surface;
       dContactGeom geom;
       dVector3 fdir1;
     };

    This wrapper class provides methods to get and set the items of those
    structures.
    """
    
    cdef dContact _contact

    def __cinit__(self):
        self._contact.surface.mode = ContactBounce
        self._contact.surface.mu = dInfinity

        self._contact.surface.bounce = 0.1

    # getMode
    def getMode(self):
        """getMode() -> flags

        Return the contact flags.
        """
        return self._contact.surface.mode

    # setMode
    def setMode(self, flags):
        """setMode(flags)

        Set the contact flags. The argument m is a combination of the
        ContactXyz flags (ContactMu2, ContactBounce, ...).
 
        @param flags: Contact flags
        @type flags: int
        """
        self._contact.surface.mode = flags

    # getMu
    def getMu(self):
        """getMu() -> float

        Return the Coulomb friction coefficient.
        """
        return self._contact.surface.mu

    # setMu
    def setMu(self, mu):
        """setMu(mu)

        Set the Coulomb friction coefficient.

        @param mu: Coulomb friction coefficient (0..Infinity)
        @type mu: float
        """
        self._contact.surface.mu = mu

    # getMu2
    def getMu2(self):
        """getMu2() -> float

        Return the optional Coulomb friction coefficient for direction 2.
        """
        return self._contact.surface.mu2

    # setMu2
    def setMu2(self, mu):
        """setMu2(mu)

        Set the optional Coulomb friction coefficient for direction 2.

        @param mu: Coulomb friction coefficient (0..Infinity)
        @type mu: float
        """
        self._contact.surface.mu2 = mu

    # getBounce
    def getBounce(self):
        """getBounce() -> float

        Return the restitution parameter.
        """
        return self._contact.surface.bounce

    # setBounce
    def setBounce(self, b):
        """setBounce(b)

        @param b: Restitution parameter (0..1)
        @type b: float
        """
        self._contact.surface.bounce = b

    # getBounceVel
    def getBounceVel(self):
        """getBounceVel() -> float

        Return the minimum incoming velocity necessary for bounce.
        """
        return self._contact.surface.bounce_vel

    # setBounceVel
    def setBounceVel(self, bv):
        """setBounceVel(bv)

        Set the minimum incoming velocity necessary for bounce. Incoming
        velocities below this will effectively have a bounce parameter of 0.

        @param bv: Velocity
        @type bv: float
        """
        self._contact.surface.bounce_vel = bv

    # getSoftERP
    def getSoftERP(self):
        """getSoftERP() -> float

        Return the contact normal "softness" parameter.
        """
        return self._contact.surface.soft_erp

    # setSoftERP
    def setSoftERP(self, erp):
        """setSoftERP(erp)

        Set the contact normal "softness" parameter.

        @param erp: Softness parameter
        @type erp: float
        """
        self._contact.surface.soft_erp = erp

    # getSoftCFM
    def getSoftCFM(self):
        """getSoftCFM() -> float

        Return the contact normal "softness" parameter.
        """
        return self._contact.surface.soft_cfm

    # setSoftCFM
    def setSoftCFM(self, cfm):
        """setSoftCFM(cfm)

        Set the contact normal "softness" parameter.

        @param cfm: Softness parameter
        @type cfm: float
        """
        self._contact.surface.soft_cfm = cfm

    # getMotion1
    def getMotion1(self):
        """getMotion1() -> float

        Get the surface velocity in friction direction 1.
        """
        return self._contact.surface.motion1

    # setMotion1
    def setMotion1(self, m):
        """setMotion1(m)

        Set the surface velocity in friction direction 1.

        @param m: Surface velocity
        @type m: float
        """
        self._contact.surface.motion1 = m

    # getMotion2
    def getMotion2(self):
        """getMotion2() -> float

        Get the surface velocity in friction direction 2.
        """
        return self._contact.surface.motion2

    # setMotion2
    def setMotion2(self, m):
        """setMotion2(m)

        Set the surface velocity in friction direction 2.

        @param m: Surface velocity
        @type m: float
        """
        self._contact.surface.motion2 = m

    # getSlip1
    def getSlip1(self):
        """getSlip1() -> float

        Get the coefficient of force-dependent-slip (FDS) for friction
        direction 1.
        """
        return self._contact.surface.slip1

    # setSlip1
    def setSlip1(self, s):
        """setSlip1(s)

        Set the coefficient of force-dependent-slip (FDS) for friction
        direction 1.

        @param s: FDS coefficient
        @type s: float
        """
        self._contact.surface.slip1 = s

    # getSlip2
    def getSlip2(self):
        """getSlip2() -> float

        Get the coefficient of force-dependent-slip (FDS) for friction
        direction 2.
        """
        return self._contact.surface.slip2

    # setSlip2
    def setSlip2(self, s):
        """setSlip2(s)

        Set the coefficient of force-dependent-slip (FDS) for friction
        direction 1.

        @param s: FDS coefficient
        @type s: float
        """
        self._contact.surface.slip2 = s

    # getFDir1
    def getFDir1(self):
        """getFDir1() -> (x, y, z)

        Get the "first friction direction" vector that defines a direction
        along which frictional force is applied.
        """
        return (self._contact.fdir1[0],
                self._contact.fdir1[1],
                self._contact.fdir1[2])

    # setFDir1
    def setFDir1(self, fdir):
        """setFDir1(fdir)

        Set the "first friction direction" vector that defines a direction
        along which frictional force is applied. It must be of unit length
        and perpendicular to the contact normal (so it is typically
        tangential to the contact surface).

        @param fdir: Friction direction
        @type fdir: 3-sequence of floats
        """
        self._contact.fdir1[0] = fdir[0]
        self._contact.fdir1[1] = fdir[1]
        self._contact.fdir1[2] = fdir[2]

    # getContactGeomParams
    def getContactGeomParams(self):
        """getContactGeomParams() -> (pos, normal, depth, geom1, geom2)

        Get the ContactGeom structure of the contact.

        The return value is a tuple (pos, normal, depth, geom1, geom2)
        where pos and normal are 3-tuples of floats and depth is a single
        float. geom1 and geom2 are the Geom objects of the geoms in contact.
        """
        cdef long id1, id2

        pos = (self._contact.geom.pos[0],
               self._contact.geom.pos[1],
               self._contact.geom.pos[2])
        normal = (self._contact.geom.normal[0],
                  self._contact.geom.normal[1],
                  self._contact.geom.normal[2])
        depth = self._contact.geom.depth

        id1 = self._contact.geom.g1
        id2 = self._contact.geom.g2
        g1 = _geom_c2py_lut[id1]
        g2 = _geom_c2py_lut[id2]
        return pos, normal, depth, g1, g2

    # setContactGeomParams
    def setContactGeomParams(self, pos, normal, depth, g1=None, g2=None):
        """setContactGeomParams(pos, normal, depth, geom1=None, geom2=None)
        
        Set the ContactGeom structure of the contact.

        @param pos:  Contact position, in global coordinates
        @type pos: 3-sequence of floats
        @param normal: Unit length normal vector
        @type normal: 3-sequence of floats
        @param depth: Depth to which the two bodies inter-penetrate
        @type depth: float
        @param geom1: Geometry object 1 that collided
        @type geom1: Geom
        @param geom2: Geometry object 2 that collided
        @type geom2: Geom
        """

        cdef long id

        self._contact.geom.pos[0] = pos[0]
        self._contact.geom.pos[1] = pos[1]
        self._contact.geom.pos[2] = pos[2]
        self._contact.geom.normal[0] = normal[0]
        self._contact.geom.normal[1] = normal[1]
        self._contact.geom.normal[2] = normal[2]
        self._contact.geom.depth = depth
        if g1 != None:
            id = g1._id()
            self._contact.geom.g1 = id
        else:
            self._contact.geom.g1 = 0
            
        if g2 != None:
            id = g2._id()
            self._contact.geom.g2 = id
        else:
            self._contact.geom.g2 = 0


# World
cdef class World:
    """Dynamics world.
    
    The world object is a container for rigid bodies and joints.
    
    
    Constructor::
    
      World()
    """

    cdef dWorldID wid

    def __cinit__(self):
        self.wid = dWorldCreate()

    def __dealloc__(self):
        if self.wid != NULL:
            dWorldDestroy(self.wid)

    # setGravity
    def setGravity(self, gravity):
        """setGravity(gravity)

        Set the world's global gravity vector.

        @param gravity: Gravity vector
        @type gravity: 3-sequence of floats
        """
        dWorldSetGravity(self.wid, gravity[0], gravity[1], gravity[2])

    # getGravity
    def getGravity(self):
        """getGravity() -> 3-tuple

        Return the world's global gravity vector as a 3-tuple of floats.
        """
        cdef dVector3 g
        dWorldGetGravity(self.wid, g)
        return g[0], g[1], g[2]

    # setERP
    def setERP(self, erp):
        """setERP(erp)

        Set the global ERP value, that controls how much error
        correction is performed in each time step. Typical values are
        in the range 0.1-0.8. The default is 0.2.

        @param erp: Global ERP value
        @type erp: float
        """
        dWorldSetERP(self.wid, erp)

    # getERP
    def getERP(self):
        """getERP() -> float

        Get the global ERP value, that controls how much error
        correction is performed in each time step. Typical values are
        in the range 0.1-0.8. The default is 0.2.
        """
        return dWorldGetERP(self.wid)

    # setCFM
    def setCFM(self, cfm):
        """setCFM(cfm)

        Set the global CFM (constraint force mixing) value. Typical
        values are in the range 10E-9 - 1. The default is 10E-5 if
        single precision is being used, or 10E-10 if double precision
        is being used.

        @param cfm: Constraint force mixing value
        @type cfm: float
        """
        dWorldSetCFM(self.wid, cfm)

    # getCFM
    def getCFM(self):
        """getCFM() -> float

        Get the global CFM (constraint force mixing) value. Typical
        values are in the range 10E-9 - 1. The default is 10E-5 if
        single precision is being used, or 10E-10 if double precision
        is being used.
        """
        return dWorldGetCFM(self.wid)

    # step
    def step(self, stepsize):
        """step(stepsize)

        Step the world. This uses a "big matrix" method that takes
        time on the order of O(m3) and memory on the order of O(m2), where m
        is the total number of constraint rows.

        For large systems this will use a lot of memory and can be
        very slow, but this is currently the most accurate method.

        @param stepsize: Time step
        @type stepsize: float
        """

        dWorldStep(self.wid, stepsize)

    # quickStep
    def quickStep(self, stepsize):
        """quickStep(stepsize)
        
        Step the world. This uses an iterative method that takes time
        on the order of O(m*N) and memory on the order of O(m), where m is
        the total number of constraint rows and N is the number of
        iterations.

        For large systems this is a lot faster than dWorldStep, but it
        is less accurate.

        @param stepsize: Time step
        @type stepsize: float
        """
        dWorldQuickStep(self.wid, stepsize)

    # setQuickStepNumIterations
    def setQuickStepNumIterations(self, num):
        """setQuickStepNumIterations(num)
        
        Set the number of iterations that the QuickStep method
        performs per step. More iterations will give a more accurate
        solution, but will take longer to compute. The default is 20
        iterations.

        @param num: Number of iterations
        @type num: int
        """
        
        dWorldSetQuickStepNumIterations(self.wid, num)

    # getQuickStepNumIterations
    def getQuickStepNumIterations(self):
        """getQuickStepNumIterations() -> int
        
        Get the number of iterations that the QuickStep method
        performs per step. More iterations will give a more accurate
        solution, but will take longer to compute. The default is 20
        iterations.
        """
        return dWorldGetQuickStepNumIterations(self.wid)

    # setQuickStepNumIterations
    def setContactMaxCorrectingVel(self, vel):
        """setContactMaxCorrectingVel(vel)

        Set the maximum correcting velocity that contacts are allowed
        to generate. The default value is infinity (i.e. no
        limit). Reducing this value can help prevent "popping" of
        deeply embedded objects.

        @param vel: Maximum correcting velocity
        @type vel: float
        """
        dWorldSetContactMaxCorrectingVel(self.wid, vel)

    # getQuickStepNumIterations
    def getContactMaxCorrectingVel(self):
        """getContactMaxCorrectingVel() -> float

        Get the maximum correcting velocity that contacts are allowed
        to generate. The default value is infinity (i.e. no
        limit). Reducing this value can help prevent "popping" of
        deeply embedded objects.

        """
        return dWorldGetContactMaxCorrectingVel(self.wid)

    # setContactSurfaceLayer
    def setContactSurfaceLayer(self, depth):
        """setContactSurfaceLayer(depth)

        Set the depth of the surface layer around all geometry
        objects. Contacts are allowed to sink into the surface layer
        up to the given depth before coming to rest. The default value
        is zero. Increasing this to some small value (e.g. 0.001) can
        help prevent jittering problems due to contacts being
        repeatedly made and broken.

        @param depth: Surface layer depth
        @type depth: float
        """
        dWorldSetContactSurfaceLayer(self.wid, depth)

    # getContactSurfaceLayer
    def getContactSurfaceLayer(self):
        """getContactSurfaceLayer()

        Get the depth of the surface layer around all geometry
        objects. Contacts are allowed to sink into the surface layer
        up to the given depth before coming to rest. The default value
        is zero. Increasing this to some small value (e.g. 0.001) can
        help prevent jittering problems due to contacts being
        repeatedly made and broken.
        """
        return dWorldGetContactSurfaceLayer(self.wid)

    # setAutoDisableFlag
    def setAutoDisableFlag(self, flag):
        """setAutoDisableFlag(flag)
        
        Set the default auto-disable flag for newly created bodies.

        @param flag: True = Do auto disable
        @type flag: bool
        """
        dWorldSetAutoDisableFlag(self.wid, flag)
        
    # getAutoDisableFlag
    def getAutoDisableFlag(self):
        """getAutoDisableFlag() -> bool
        
        Get the default auto-disable flag for newly created bodies.
        """
        return dWorldGetAutoDisableFlag(self.wid)

    # setAutoDisableLinearThreshold
    def setAutoDisableLinearThreshold(self, threshold):
        """setAutoDisableLinearThreshold(threshold)
        
        Set the default auto-disable linear threshold for newly created
        bodies.

        @param threshold: Linear threshold
        @type threshold: float
        """
        dWorldSetAutoDisableLinearThreshold(self.wid, threshold)

    # getAutoDisableLinearThreshold
    def getAutoDisableLinearThreshold(self):
        """getAutoDisableLinearThreshold() -> float
        
        Get the default auto-disable linear threshold for newly created
        bodies.
        """
        return dWorldGetAutoDisableLinearThreshold(self.wid)

    # setAutoDisableAngularThreshold
    def setAutoDisableAngularThreshold(self, threshold):
        """setAutoDisableAngularThreshold(threshold)
        
        Set the default auto-disable angular threshold for newly created
        bodies.

        @param threshold: Angular threshold
        @type threshold: float
        """
        dWorldSetAutoDisableAngularThreshold(self.wid, threshold)

    # getAutoDisableAngularThreshold
    def getAutoDisableAngularThreshold(self):
        """getAutoDisableAngularThreshold() -> float
        
        Get the default auto-disable angular threshold for newly created
        bodies.
        """
        return dWorldGetAutoDisableAngularThreshold(self.wid)
    
    # setAutoDisableSteps
    def setAutoDisableSteps(self, steps):
        """setAutoDisableSteps(steps)
        
        Set the default auto-disable steps for newly created bodies.

        @param steps: Auto disable steps
        @type steps: int
        """
        dWorldSetAutoDisableSteps(self.wid, steps)

    # getAutoDisableSteps
    def getAutoDisableSteps(self):
        """getAutoDisableSteps() -> int
        
        Get the default auto-disable steps for newly created bodies.
        """
        return dWorldGetAutoDisableSteps(self.wid)

    # setAutoDisableTime
    def setAutoDisableTime(self, time):
        """setAutoDisableTime(time)
        
        Set the default auto-disable time for newly created bodies.

        @param time: Auto disable time
        @type time: float
        """
        dWorldSetAutoDisableTime(self.wid, time)

    # getAutoDisableTime
    def getAutoDisableTime(self):
        """getAutoDisableTime() -> float
        
        Get the default auto-disable time for newly created bodies.
        """
        return dWorldGetAutoDisableTime(self.wid)

    # setLinearDamping
    def setLinearDamping(self, scale):
        """setLinearDamping(scale)

        Set the world's linear damping scale.
                @param scale The linear damping scale that is to be applied to bodies.
                Default is 0 (no damping). Should be in the interval [0, 1].
        @type scale: float
        """
        dWorldSetLinearDamping(self.wid, scale)

    # getLinearDamping
    def getLinearDamping(self):
        """getLinearDamping() -> float

        Get the world's linear damping scale.
        """
        return dWorldGetLinearDamping(self.wid)

    # setAngularDamping
    def setAngularDamping(self, scale):
        """setAngularDamping(scale)

        Set the world's angular damping scale.
                @param scale The angular damping scale that is to be applied to bodies.
                Default is 0 (no damping). Should be in the interval [0, 1].
        @type scale: float
        """
        dWorldSetAngularDamping(self.wid, scale)

    # getAngularDamping
    def getAngularDamping(self):
        """getAngularDamping() -> float

        Get the world's angular damping scale.
        """
        return dWorldGetAngularDamping(self.wid)

    # impulseToForce
    def impulseToForce(self, stepsize, impulse):
        """impulseToForce(stepsize, impulse) -> 3-tuple

        If you want to apply a linear or angular impulse to a rigid
        body, instead of a force or a torque, then you can use this
        function to convert the desired impulse into a force/torque
        vector before calling the dBodyAdd... function.

        @param stepsize: Time step
        @param impulse: Impulse vector
        @type stepsize: float
        @type impulse: 3-tuple of floats
        """
        cdef dVector3 force
        dWorldImpulseToForce(self.wid, stepsize,
                             impulse[0], impulse[1], impulse[2], force)
        return force[0], force[1], force[2]

    # createBody
#    def createBody(self):
#        return Body(self)

    # createBallJoint
#    def createBallJoint(self, jointgroup=None):
#        return BallJoint(self, jointgroup)

    # createHingeJoint
#    def createHingeJoint(self, jointgroup=None):
#        return HingeJoint(self, jointgroup)

    # createHinge2Joint
#    def createHinge2Joint(self, jointgroup=None):
#        return Hinge2Joint(self, jointgroup)

    # createSliderJoint
#    def createSliderJoint(self, jointgroup=None):
#        return SliderJoint(self, jointgroup)

    # createFixedJoint
#    def createFixedJoint(self, jointgroup=None):
#        return FixedJoint(self, jointgroup)

    # createContactJoint
#    def createContactJoint(self, jointgroup, contact):
#        return ContactJoint(self, jointgroup, contact)


# Body
cdef class Body:
    """The rigid body class encapsulating the ODE body.

    This class represents a rigid body that has a location and orientation
    in space and that stores the mass properties of an object.

    When creating a Body object you have to pass the world it belongs to
    as argument to the constructor::

      >>> import ode
      >>> w = ode.World()
      >>> b = ode.Body(w)
    """

    cdef dBodyID bid
    # A reference to the world so that the world won't be destroyed while
    # there are still joints using it.
    cdef object world
    
    # A dictionary with user attributes
    # (set via __getattr__ and __setattr__)
    cdef object userattribs

    def __cinit__(self, World world not None):
        self.bid = dBodyCreate(world.wid)

    def __init__(self, World world not None):
        """Constructor.

        @param world: The world in which the body should be created.
        @type world: World
        """
        self.world = world
        self.userattribs = {}

    def __dealloc__(self):
        if self.bid != NULL:
            dBodyDestroy(self.bid)

    def __getattr__(self, name):
        try:
            return self.userattribs[name]
        except:
            raise AttributeError("Body object has no attribute '%s'" % name)
            
    def __setattr__(self, name, value):
        self.userattribs[name] = value

    def __delattr__(self, name):
        try:
            del self.userattribs[name]
        except:
            raise AttributeError("Body object has no attribute '%s'" % name)

    # setPosition
    def setPosition(self, pos):
        """setPosition(pos)

        Set the position of the body.

        @param pos: The new position
        @type pos: 3-sequence of floats
        """
        dBodySetPosition(self.bid, pos[0], pos[1], pos[2])

    # getPosition
    def getPosition(self):
        """getPosition() -> 3-tuple

        Return the current position of the body.
        """
        cdef dReal* p
        # The "const" in the original return value is cast away
        p = dBodyGetPosition(self.bid)
        return p[0], p[1], p[2]

    # setRotation
    def setRotation(self, R):
        """setRotation(R)

        Set the orientation of the body. The rotation matrix must be
        given as a sequence of 9 floats which are the elements of the
        matrix in row-major order.

        @param R: Rotation matrix
        @type R: 9-sequence of floats
        """
        cdef dMatrix3 m
        m[0] = R[0]
        m[1] = R[1]
        m[2] = R[2]
        m[3] = 0
        m[4] = R[3]
        m[5] = R[4]
        m[6] = R[5]
        m[7] = 0
        m[8] = R[6]
        m[9] = R[7]
        m[10] = R[8]
        m[11] = 0
        dBodySetRotation(self.bid, m)

    # getRotation
    def getRotation(self):
        """getRotation() -> 9-tuple

        Return the current rotation matrix as a tuple of 9 floats (row-major
        order).
        """
        cdef dReal* m
        # The "const" in the original return value is cast away
        m = dBodyGetRotation(self.bid)
        return m[0], m[1], m[2], m[4], m[5], m[6], m[8], m[9], m[10]

    # getQuaternion
    def getQuaternion(self):
        """getQuaternion() -> 4-tuple

        Return the current rotation as a quaternion. The return value
        is a list of 4 floats.
        """
        cdef dReal* q
        q = dBodyGetQuaternion(self.bid)
        return q[0], q[1], q[2], q[3]

    # setQuaternion
    def setQuaternion(self, q):
        """setQuaternion(q)

        Set the orientation of the body. The quaternion must be given as a
        sequence of 4 floats.

        @param q: Quaternion
        @type q: 4-sequence of floats
        """
        cdef dQuaternion w
        w[0] = q[0]
        w[1] = q[1]
        w[2] = q[2]
        w[3] = q[3]
        dBodySetQuaternion(self.bid, w)

    # setLinearVel
    def setLinearVel(self, vel):
        """setLinearVel(vel)

        Set the linear velocity of the body.

        @param vel: New velocity
        @type vel: 3-sequence of floats
        """
        dBodySetLinearVel(self.bid, vel[0], vel[1], vel[2])

    # getLinearVel
    def getLinearVel(self):
        """getLinearVel() -> 3-tuple

        Get the current linear velocity of the body.
        """
        cdef dReal* p
        # The "const" in the original return value is cast away
        p = dBodyGetLinearVel(self.bid)
        return p[0], p[1], p[2]

    # setAngularVel
    def setAngularVel(self, vel):
        """setAngularVel(vel)

        Set the angular velocity of the body.

        @param vel: New angular velocity
        @type vel: 3-sequence of floats
        """
        dBodySetAngularVel(self.bid, vel[0], vel[1], vel[2])

    # getAngularVel
    def getAngularVel(self):
        """getAngularVel() -> 3-tuple

        Get the current angular velocity of the body.
        """
        cdef dReal* p
        # The "const" in the original return value is cast away
        p = dBodyGetAngularVel(self.bid)
        return p[0], p[1], p[2]
    
    # setMass
    def setMass(self, Mass mass):
        """setMass(mass)

        Set the mass properties of the body. The argument mass must be
        an instance of a Mass object.

        @param mass: Mass properties
        @type mass: Mass
        """
        dBodySetMass(self.bid, &mass._mass)

    # getMass
    def getMass(self):
        """getMass() -> mass

        Return the mass properties as a Mass object.
        """
        cdef Mass m
        m = Mass()
        dBodyGetMass(self.bid, &m._mass)
        return m

    # addForce
    def addForce(self, f):
        """addForce(f)

        Add an external force f given in absolute coordinates. The force
        is applied at the center of mass.

        @param f: Force
        @type f: 3-sequence of floats
        """
        dBodyAddForce(self.bid, f[0], f[1], f[2])

    # addTorque
    def addTorque(self, t):
        """addTorque(t)

        Add an external torque t given in absolute coordinates.

        @param t: Torque
        @type t: 3-sequence of floats
        """
        dBodyAddTorque(self.bid, t[0], t[1], t[2])

    # addRelForce
    def addRelForce(self, f):
        """addRelForce(f)

        Add an external force f given in relative coordinates
        (relative to the body's own frame of reference). The force
        is applied at the center of mass.

        @param f: Force
        @type f: 3-sequence of floats
        """
        dBodyAddRelForce(self.bid, f[0], f[1], f[2])

    # addRelTorque
    def addRelTorque(self, t):
        """addRelTorque(t)

        Add an external torque t given in relative coordinates
        (relative to the body's own frame of reference).

        @param t: Torque
        @type t: 3-sequence of floats
        """
        dBodyAddRelTorque(self.bid, t[0], t[1], t[2])

    # addForceAtPos
    def addForceAtPos(self, f, p):
        """addForceAtPos(f, p)

        Add an external force f at position p. Both arguments must be
        given in absolute coordinates.

        @param f: Force
        @param p: Position
        @type f: 3-sequence of floats
        @type p: 3-sequence of floats
        """
        dBodyAddForceAtPos(self.bid, f[0], f[1], f[2], p[0], p[1], p[2])

    # addForceAtRelPos
    def addForceAtRelPos(self, f, p):
        """addForceAtRelPos(f, p)

        Add an external force f at position p. f is given in absolute
        coordinates and p in absolute coordinates.

        @param f: Force
        @param p: Position
        @type f: 3-sequence of floats
        @type p: 3-sequence of floats
        """
        dBodyAddForceAtRelPos(self.bid, f[0], f[1], f[2], p[0], p[1], p[2])

    # addRelForceAtPos
    def addRelForceAtPos(self, f, p):
        """addRelForceAtPos(f, p)

        Add an external force f at position p. f is given in relative
        coordinates and p in relative coordinates.

        @param f: Force
        @param p: Position
        @type f: 3-sequence of floats
        @type p: 3-sequence of floats
        """
        dBodyAddRelForceAtPos(self.bid, f[0], f[1], f[2], p[0], p[1], p[2])

    # addRelForceAtRelPos
    def addRelForceAtRelPos(self, f, p):
        """addRelForceAtRelPos(f, p)

        Add an external force f at position p. Both arguments must be
        given in relative coordinates.

        @param f: Force
        @param p: Position
        @type f: 3-sequence of floats
        @type p: 3-sequence of floats
        """
        dBodyAddRelForceAtRelPos(self.bid, f[0], f[1], f[2], p[0], p[1], p[2])

    # getForce
    def getForce(self):
        """getForce() -> 3-tuple

        Return the current accumulated force.
        """
        cdef dReal* f
        # The "const" in the original return value is cast away
        f = dBodyGetForce(self.bid)
        return f[0], f[1], f[2]

    # getTorque
    def getTorque(self):
        """getTorque() -> 3-tuple

        Return the current accumulated torque.
        """
        cdef dReal* f
        # The "const" in the original return value is cast away
        f = dBodyGetTorque(self.bid)
        return f[0], f[1], f[2]

    # setForce
    def setForce(self, f):
        """setForce(f)

        Set the body force accumulation vector.

        @param f: Force
        @type f: 3-tuple of floats
        """
        dBodySetForce(self.bid, f[0], f[1], f[2])

    # setTorque
    def setTorque(self, t):
        """setTorque(t)

        Set the body torque accumulation vector.

        @param t: Torque
        @type t: 3-tuple of floats
        """
        dBodySetTorque(self.bid, t[0], t[1], t[2])

    # getRelPointPos
    def getRelPointPos(self, p):
        """getRelPointPos(p) -> 3-tuple

        Utility function that takes a point p on a body and returns
        that point's position in global coordinates. The point p
        must be given in body relative coordinates.

        @param p: Body point (local coordinates)
        @type p: 3-sequence of floats
        """

        cdef dVector3 res
        dBodyGetRelPointPos(self.bid, p[0], p[1], p[2], res)
        return res[0], res[1], res[2]

    # getRelPointVel
    def getRelPointVel(self, p):
        """getRelPointVel(p) -> 3-tuple

        Utility function that takes a point p on a body and returns
        that point's velocity in global coordinates. The point p
        must be given in body relative coordinates.

        @param p: Body point (local coordinates)
        @type p: 3-sequence of floats
        """
        cdef dVector3 res
        dBodyGetRelPointVel(self.bid, p[0], p[1], p[2], res)
        return res[0], res[1], res[2]

    # getPointVel
    def getPointVel(self, p):
        """getPointVel(p) -> 3-tuple

        Utility function that takes a point p on a body and returns
        that point's velocity in global coordinates. The point p
        must be given in global coordinates.

        @param p: Body point (global coordinates)
        @type p: 3-sequence of floats
        """
        cdef dVector3 res
        dBodyGetPointVel(self.bid, p[0], p[1], p[2], res)
        return res[0], res[1], res[2]

    # getPosRelPoint
    def getPosRelPoint(self, p):
        """getPosRelPoint(p) -> 3-tuple

        This is the inverse of getRelPointPos(). It takes a point p in
        global coordinates and returns the point's position in
        body-relative coordinates.

        @param p: Body point (global coordinates)
        @type p: 3-sequence of floats
        """
        cdef dVector3 res
        dBodyGetPosRelPoint(self.bid, p[0], p[1], p[2], res)
        return res[0], res[1], res[2]

    # vectorToWorld
    def vectorToWorld(self, v):
        """vectorToWorld(v) -> 3-tuple

        Given a vector v expressed in the body coordinate system, rotate
        it to the world coordinate system.

        @param v: Vector in body coordinate system
        @type v: 3-sequence of floats
        """
        cdef dVector3 res
        dBodyVectorToWorld(self.bid, v[0], v[1], v[2], res)
        return res[0], res[1], res[2]

    # vectorFromWorld
    def vectorFromWorld(self, v):
        """vectorFromWorld(v) -> 3-tuple

        Given a vector v expressed in the world coordinate system, rotate
        it to the body coordinate system.

        @param v: Vector in world coordinate system
        @type v: 3-sequence of floats
        """
        cdef dVector3 res
        dBodyVectorFromWorld(self.bid, v[0], v[1], v[2], res)
        return res[0], res[1], res[2]

    # Enable
    def enable(self):
        """enable()

        Manually enable a body.
        """
        dBodyEnable(self.bid)
        
    # Disable
    def disable(self):
        """disable()

        Manually disable a body. Note that a disabled body that is connected
        through a joint to an enabled body will be automatically re-enabled
        at the next simulation step.
        """
        dBodyDisable(self.bid)
        
    # isEnabled
    def isEnabled(self):
        """isEnabled() -> bool

        Check if a body is currently enabled.
        """
        return dBodyIsEnabled(self.bid)
        
    # setFiniteRotationMode
    def setFiniteRotationMode(self, mode):
        """setFiniteRotationMode(mode)

        This function controls the way a body's orientation is updated at
        each time step. The mode argument can be:
        
         - 0: An "infinitesimal" orientation update is used. This is
           fast to compute, but it can occasionally cause inaccuracies
           for bodies that are rotating at high speed, especially when
           those bodies are joined to other bodies. This is the default
           for every new body that is created.
        
         - 1: A "finite" orientation update is used. This is more
           costly to compute, but will be more accurate for high speed
           rotations. Note however that high speed rotations can result
           in many types of error in a simulation, and this mode will
           only fix one of those sources of error.

        @param mode: Rotation mode (0/1)
        @type mode: int
        """
        dBodySetFiniteRotationMode(self.bid, mode)
        
    # getFiniteRotationMode
    def getFiniteRotationMode(self):
        """getFiniteRotationMode() -> mode (0/1)

        Return the current finite rotation mode of a body (0 or 1).
        See setFiniteRotationMode().
        """
        return dBodyGetFiniteRotationMode(self.bid)

    # setFiniteRotationAxis
    def setFiniteRotationAxis(self, a):
        """setFiniteRotationAxis(a)

        Set the finite rotation axis of the body.  This axis only has a
        meaning when the finite rotation mode is set
        (see setFiniteRotationMode()).
        
        @param a: Axis
        @type a: 3-sequence of floats
        """
        dBodySetFiniteRotationAxis(self.bid, a[0], a[1], a[2])

    # getFiniteRotationAxis
    def getFiniteRotationAxis(self):
        """getFiniteRotationAxis() -> 3-tuple

        Return the current finite rotation axis of the body.
        """
        cdef dVector3 p
        # The "const" in the original return value is cast away
        dBodyGetFiniteRotationAxis(self.bid, p)
        return p[0], p[1], p[2]
        
    # getNumJoints
    def getNumJoints(self):
        """getNumJoints() -> int

        Return the number of joints that are attached to this body.
        """
        return dBodyGetNumJoints(self.bid)

    # setGravityMode
    def setGravityMode(self, mode):
        """setGravityMode(mode)

        Set whether the body is influenced by the world's gravity
        or not. If mode is True it is, otherwise it isn't.
        Newly created bodies are always influenced by the world's gravity.

        @param mode: Gravity mode
        @type mode: bool
        """
        dBodySetGravityMode(self.bid, mode)
        
    # getGravityMode
    def getGravityMode(self):
        """getGravityMode() -> bool

        Return True if the body is influenced by the world's gravity.
        """
        return dBodyGetGravityMode(self.bid)

    def setDynamic(self):
        """setDynamic()

        Set a body to the (default) "dynamic" state, instead of "kinematic".
        See setKinematic() for more information.
        """
        dBodySetDynamic(self.bid)

    def setKinematic(self):
        """setKinematic()

        Set the kinematic state of the body (change it into a kinematic body)

        Kinematic bodies behave as if they had infinite mass. This means they don't react
        to any force (gravity, constraints or user-supplied); they simply follow 
        velocity to reach the next position. [from ODE wiki]

        """
        dBodySetKinematic(self.bid)

    def isKinematic(self):
        """isKinematic() -> bool

        Return True if the body is kinematic (not influenced by other forces).

        Kinematic bodies behave as if they had infinite mass. This means they don't react
        to any force (gravity, constraints or user-supplied); they simply follow
        velocity to reach the next position. [from ODE wiki]

        """
        return dBodyIsKinematic(self.bid)

    def setMaxAngularSpeed(self, max_speed):
        """setMaxAngularSpeed(max_speed)

        You can also limit the maximum angular speed. In contrast to the damping
        functions, the angular velocity is affected before the body is moved.
        This means that it will introduce errors in joints that are forcing the
        body to rotate too fast. Some bodies have naturally high angular
        velocities (like cars' wheels), so you may want to give them a very high
        (like the default, dInfinity) limit.

        """
        dBodySetMaxAngularSpeed(self.bid, max_speed)


# JointGroup
cdef class JointGroup:
    """Joint group.

    Constructor::
    
      JointGroup()
    """

    # JointGroup ID
    cdef dJointGroupID gid
    # A list of Python joints that were added to the group
    cdef object jointlist

    def __cinit__(self):
        self.gid = dJointGroupCreate(0)

    def __init__(self):
        self.jointlist = []

    def __dealloc__(self):
        if self.gid != NULL:
            for j in self.jointlist:
                j._destroyed()
            dJointGroupDestroy(self.gid)

    # empty
    def empty(self):
        """empty()

        Destroy all joints in the group.
        """
        dJointGroupEmpty(self.gid)
        for j in self.jointlist:
            j._destroyed()
        self.jointlist = []

    def _addjoint(self, j):
        """_addjoint(j)

        Add a joint to the group.  This is an internal method that is
        called by the joints.  The group has to know the Python
        wrappers because it has to notify them when the group is
        emptied (so that the ODE joints won't get destroyed
        twice). The notification is done by calling _destroyed() on
        the Python joints.

        @param j: The joint to add
        @type j: Joint
        """
        self.jointlist.append(j)


######################################################################

# Joint
cdef class Joint:
    """Base class for all joint classes."""

    # Joint id as returned by dJointCreateXxx()
    cdef dJointID jid
    # A reference to the world so that the world won't be destroyed while
    # there are still joints using it.
    cdef object world
    # The feedback buffer
    cdef dJointFeedback* feedback

    cdef object body1
    cdef object body2

    # A dictionary with user attributes
    # (set via __getattr__ and __setattr__)
    cdef object userattribs

    def __cinit__(self, *a, **kw):
        self.jid = NULL
        self.world = None
        self.feedback = NULL
        self.body1 = None
        self.body2 = None
        self.userattribs = {}

    def __init__(self, *a, **kw):
        raise NotImplementedError("Joint base class can't be used directly")

    def __dealloc__(self):
        self.setFeedback(False)
        if self.jid != NULL:
            dJointDestroy(self.jid)

    def __getattr__(self, name):
        try:
            return self.userattribs[name]
        except:
            raise AttributeError("Joint object has no attribute '%s'" % name)
            
    def __setattr__(self, name, value):
        self.userattribs[name] = value

    def __delattr__(self, name):
        try:
            del self.userattribs[name]
        except:
            raise AttributeError("Joint object has no attribute '%s'" % name)

    # _destroyed
    def _destroyed(self):
        """Notify the joint object about an external destruction of the ODE joint.

        This method has to be called when the underlying ODE object
        was destroyed by someone else (e.g. by a joint group). The Python
        wrapper will then refrain from destroying it again.
        """
        self.jid = NULL

    # enable
    def enable(self):
        """enable()

        Enable the joint. Disabled joints are completely ignored during the
        simulation. Disabled joints don't lose the already computed information
        like anchors and axes.
        """
        dJointEnable(self.jid)

    # disable
    def disable(self):
        """disable()

        Disable the joint. Disabled joints are completely ignored during the
        simulation. Disabled joints don't lose the already computed information
        like anchors and axes.
        """
        dJointDisable(self.jid)

    # isEnabled
    def isEnabled(self):
        """isEnabled() -> bool

        Determine whether the joint is enabled. Disabled joints are completely
        ignored during the simulation. Disabled joints don't lose the already
        computed information like anchors and axes.
        """
        return dJointIsEnabled(self.jid)

    # attach
    def attach(self, Body body1, Body body2):
        """attach(body1, body2)

        Attach the joint to some new bodies. A body can be attached
        to the environment by passing None as second body.
        
        @param body1: First body
        @param body2: Second body
        @type body1: Body
        @type body2: Body
        """
        cdef dBodyID id1, id2

        if body1 == None:
            id1 = NULL
        else:
            id1 = body1.bid
            
        if body2 == None:
            id2 = NULL
        else:
            id2 = body2.bid

        self.body1 = body1
        self.body2 = body2
        dJointAttach(self.jid, id1, id2)

    # getBody
    def getBody(self, index):
        """getBody(index) -> Body

        Return the bodies that this joint connects. If index is 0 the
        "first" body will be returned, corresponding to the body1
        argument of the attach() method. If index is 1 the "second" body
        will be returned, corresponding to the body2 argument of the
        attach() method.

        @param index: Bodx index (0 or 1).
        @type index: int
        """
        
        if index == 0:
            return self.body1
        elif index == 1:
            return self.body2
        else:
            raise IndexError()

    # setFeedback
    def setFeedback(self, flag=1):
        """setFeedback(flag=True)

        Create a feedback buffer. If flag is True then a buffer is
        allocated and the forces/torques applied by the joint can
        be read using the getFeedback() method. If flag is False the
        buffer is released.

        @param flag: Specifies whether a buffer should be created or released
        @type flag: bool
        """
        
        if flag:
            # Was there already a buffer allocated? then we're finished
            if self.feedback != NULL:
                return
            # Allocate a buffer and pass it to ODE
            self.feedback = malloc(sizeof(dJointFeedback))
            if self.feedback == NULL:
                raise MemoryError("can't allocate feedback buffer")
            dJointSetFeedback(self.jid, self.feedback)
        else:
            if self.feedback != NULL:
                # Free a previously allocated buffer
                dJointSetFeedback(self.jid, NULL)
                free(self.feedback)
                self.feedback = NULL
        
    # getFeedback
    def getFeedback(self):
        """getFeedback() -> (force1, torque1, force2, torque2)

        Get the forces/torques applied by the joint. If feedback is
        activated (i.e. setFeedback(True) was called) then this method
        returns a tuple (force1, torque1, force2, torque2) with the
        forces and torques applied to body 1 and body 2.  The
        forces/torques are given as 3-tuples.

        If feedback is deactivated then the method always returns None.
        """
        cdef dJointFeedback* fb
        
        fb = dJointGetFeedback(self.jid)
        if fb == NULL:
            return None
           
        f1 = (fb.f1[0], fb.f1[1], fb.f1[2])
        t1 = (fb.t1[0], fb.t1[1], fb.t1[2])
        f2 = (fb.f2[0], fb.f2[1], fb.f2[2])
        t2 = (fb.t2[0], fb.t2[1], fb.t2[2])
        return f1, t1, f2, t2

######################################################################


# BallJoint
cdef class BallJoint(Joint):
    """Ball joint.

    Constructor::
    
      BallJoint(world, jointgroup=None)
    """

    def __cinit__(self, World world not None, jointgroup=None):
        cdef JointGroup jg
        cdef dJointGroupID jgid

        jgid = NULL
        if jointgroup != None:
            jg = jointgroup
            jgid = jg.gid
        self.jid = dJointCreateBall(world.wid, jgid)

    def __init__(self, World world not None, jointgroup=None):
        self.world = world
        if jointgroup != None:
            jointgroup._addjoint(self)
            
    # setAnchor
    def setAnchor(self, pos):
        """setAnchor(pos)

        Set the joint anchor point which must be specified in world
        coordinates.

        @param pos: Anchor position
        @type pos: 3-sequence of floats
        """
        dJointSetBallAnchor(self.jid, pos[0], pos[1], pos[2])
    
    # getAnchor
    def getAnchor(self):
        """getAnchor() -> 3-tuple of floats

        Get the joint anchor point, in world coordinates.  This
        returns the point on body 1.  If the joint is perfectly
        satisfied, this will be the same as the point on body 2.
        """
        
        cdef dVector3 p
        dJointGetBallAnchor(self.jid, p)
        return p[0], p[1], p[2]

    # getAnchor2
    def getAnchor2(self):
        """getAnchor2() -> 3-tuple of floats

        Get the joint anchor point, in world coordinates.  This
        returns the point on body 2. If the joint is perfectly
        satisfied, this will be the same as the point on body 1.
        """

        cdef dVector3 p
        dJointGetBallAnchor2(self.jid, p)
        return p[0], p[1], p[2]

    # setParam
    def setParam(self, param, value):
        pass

    # getParam
    def getParam(self, param):
        return 0.0
        
    
# HingeJoint
cdef class HingeJoint(Joint):
    """Hinge joint.

    Constructor::
    
      HingeJoint(world, jointgroup=None)
    """

    def __cinit__(self, World world not None, jointgroup=None):
        cdef JointGroup jg
        cdef dJointGroupID jgid
        
        jgid = NULL
        if jointgroup != None:
            jg = jointgroup
            jgid = jg.gid
        self.jid = dJointCreateHinge(world.wid, jgid)
        
    def __init__(self, World world not None, jointgroup=None):
        self.world = world
        if jointgroup != None:
            jointgroup._addjoint(self)

    # setAnchor
    def setAnchor(self, pos):
        """setAnchor(pos)

        Set the hinge anchor which must be given in world coordinates.

        @param pos: Anchor position
        @type pos: 3-sequence of floats
        """
        dJointSetHingeAnchor(self.jid, pos[0], pos[1], pos[2])
    
    # getAnchor
    def getAnchor(self):
        """getAnchor() -> 3-tuple of floats

        Get the joint anchor point, in world coordinates. This returns
        the point on body 1. If the joint is perfectly satisfied, this
        will be the same as the point on body 2.
        """
        cdef dVector3 p
        dJointGetHingeAnchor(self.jid, p)
        return p[0], p[1], p[2]

    # getAnchor2
    def getAnchor2(self):
        """getAnchor2() -> 3-tuple of floats

        Get the joint anchor point, in world coordinates. This returns
        the point on body 2. If the joint is perfectly satisfied, this
        will be the same as the point on body 1.
        """
        cdef dVector3 p
        dJointGetHingeAnchor2(self.jid, p)
        return p[0], p[1], p[2]

    # setAxis
    def setAxis(self, axis):
        """setAxis(axis)

        Set the hinge axis.

        @param axis: Hinge axis
        @type axis: 3-sequence of floats
        """
        dJointSetHingeAxis(self.jid, axis[0], axis[1], axis[2])
    
    # getAxis
    def getAxis(self):
        """getAxis() -> 3-tuple of floats

        Get the hinge axis.
        """
        cdef dVector3 a
        dJointGetHingeAxis(self.jid, a)
        return a[0], a[1], a[2]

    # getAngle
    def getAngle(self):
        """getAngle() -> float

        Get the hinge angle. The angle is measured between the two
        bodies, or between the body and the static environment. The
        angle will be between -pi..pi.

        When the hinge anchor or axis is set, the current position of
        the attached bodies is examined and that position will be the
        zero angle.
        """
        
        return dJointGetHingeAngle(self.jid)

    # getAngleRate
    def getAngleRate(self):
        """getAngleRate() -> float

        Get the time derivative of the angle.
        """
        return dJointGetHingeAngleRate(self.jid)

    # addTorque
    def addTorque(self, torque):
        """addTorque(torque)

        Applies the torque about the hinge axis.

        @param torque: Torque magnitude
        @type torque: float
        """
        dJointAddHingeTorque(self.jid, torque)

    # setParam
    def setParam(self, param, value):
        """setParam(param, value)

        Set limit/motor parameters for the joint.

        param is one of ParamLoStop, ParamHiStop, ParamVel, ParamFMax,
        ParamFudgeFactor, ParamBounce, ParamCFM, ParamStopERP, ParamStopCFM,
        ParamSuspensionERP, ParamSuspensionCFM.

        These parameter names can be optionally followed by a digit (2
        or 3) to indicate the second or third set of parameters.

        @param param: Selects the parameter to set
        @param value: Parameter value
        @type param: int
        @type value: float
        """
        
        dJointSetHingeParam(self.jid, param, value)

    # getParam
    def getParam(self, param):
        """getParam(param) -> float

        Get limit/motor parameters for the joint.

        param is one of ParamLoStop, ParamHiStop, ParamVel, ParamFMax,
        ParamFudgeFactor, ParamBounce, ParamCFM, ParamStopERP, ParamStopCFM,
        ParamSuspensionERP, ParamSuspensionCFM.

        These parameter names can be optionally followed by a digit (2
        or 3) to indicate the second or third set of parameters.

        @param param: Selects the parameter to read
        @type param: int
        """
        return dJointGetHingeParam(self.jid, param)
        
        
# SliderJoint
cdef class SliderJoint(Joint):
    """Slider joint.
    
    Constructor::
    
      SlideJoint(world, jointgroup=None)
    """

    def __cinit__(self, World world not None, jointgroup=None):
        cdef JointGroup jg
        cdef dJointGroupID jgid

        jgid = NULL
        if jointgroup != None:
            jg = jointgroup
            jgid = jg.gid
        self.jid = dJointCreateSlider(world.wid, jgid)

    def __init__(self, World world not None, jointgroup=None):
        self.world = world
        if jointgroup != None:
            jointgroup._addjoint(self)
          
    # setAxis
    def setAxis(self, axis):
        """setAxis(axis)

        Set the slider axis parameter.

        @param axis: Slider axis
        @type axis: 3-sequence of floats
        """
        dJointSetSliderAxis(self.jid, axis[0], axis[1], axis[2])
    
    # getAxis
    def getAxis(self):
        """getAxis() -> 3-tuple of floats

        Get the slider axis parameter.
        """
        cdef dVector3 a
        dJointGetSliderAxis(self.jid, a)
        return a[0], a[1], a[2]

    # getPosition
    def getPosition(self):
        """getPosition() -> float

        Get the slider linear position (i.e. the slider's "extension").

        When the axis is set, the current position of the attached
        bodies is examined and that position will be the zero
        position.
        """
        
        return dJointGetSliderPosition(self.jid)

    # getPositionRate
    def getPositionRate(self):
        """getPositionRate() -> float

        Get the time derivative of the position.
        """
        return dJointGetSliderPositionRate(self.jid)

    # addForce
    def addForce(self, force):
        """addForce(force)

        Applies the given force in the slider's direction.

        @param force: Force magnitude
        @type force: float
        """
        dJointAddSliderForce(self.jid, force)

    # setParam
    def setParam(self, param, value):
        dJointSetSliderParam(self.jid, param, value)

    # getParam
    def getParam(self, param):
        return dJointGetSliderParam(self.jid, param)
        
    
# UniversalJoint
cdef class UniversalJoint(Joint):
    """Universal joint.

    Constructor::
    
      UniversalJoint(world, jointgroup=None)
    """

    def __cinit__(self, World world not None, jointgroup=None):
        cdef JointGroup jg
        cdef dJointGroupID jgid

        jgid = NULL
        if jointgroup != None:
            jg = jointgroup
            jgid = jg.gid
        self.jid = dJointCreateUniversal(world.wid, jgid)

    def __init__(self, World world not None, jointgroup=None):
        self.world = world
        if jointgroup != None:
            jointgroup._addjoint(self)

    # setAnchor
    def setAnchor(self, pos):
        """setAnchor(pos)

        Set the universal anchor.

        @param pos: Anchor position
        @type pos: 3-sequence of floats
        """
        dJointSetUniversalAnchor(self.jid, pos[0], pos[1], pos[2])
    
    # getAnchor
    def getAnchor(self):
        """getAnchor() -> 3-tuple of floats

        Get the joint anchor point, in world coordinates. This returns
        the point on body 1. If the joint is perfectly satisfied, this
        will be the same as the point on body 2.
        """
        
        cdef dVector3 p
        dJointGetUniversalAnchor(self.jid, p)
        return p[0], p[1], p[2]

    # getAnchor2
    def getAnchor2(self):
        """getAnchor2() -> 3-tuple of floats

        Get the joint anchor point, in world coordinates. This returns
        the point on body 2. If the joint is perfectly satisfied, this
        will be the same as the point on body 1.
        """
        
        cdef dVector3 p
        dJointGetUniversalAnchor2(self.jid, p)
        return p[0], p[1], p[2]

    # setAxis1
    def setAxis1(self, axis):
        """setAxis1(axis)

        Set the first universal axis. Axis 1 and axis 2 should be
        perpendicular to each other.

        @param axis: Joint axis
        @type axis: 3-sequence of floats
        """
        dJointSetUniversalAxis1(self.jid, axis[0], axis[1], axis[2])
    
    # getAxis1
    def getAxis1(self):
        """getAxis1() -> 3-tuple of floats

        Get the first univeral axis.
        """
        cdef dVector3 a
        dJointGetUniversalAxis1(self.jid, a)
        return a[0], a[1], a[2]

    # setAxis2
    def setAxis2(self, axis):
        """setAxis2(axis)

        Set the second universal axis. Axis 1 and axis 2 should be
        perpendicular to each other.

        @param axis: Joint axis
        @type axis: 3-sequence of floats
        """
        dJointSetUniversalAxis2(self.jid, axis[0], axis[1], axis[2])
    
    # getAxis2
    def getAxis2(self):
        """getAxis2() -> 3-tuple of floats

        Get the second univeral axis.
        """
        cdef dVector3 a
        dJointGetUniversalAxis2(self.jid, a)
        return a[0], a[1], a[2]

    # addTorques
    def addTorques(self, torque1, torque2):
        """addTorques(torque1, torque2)

        Applies torque1 about axis 1, and torque2 about axis 2.

        @param torque1: Torque 1 magnitude
        @param torque2: Torque 2 magnitude
        @type torque1: float
        @type torque2: float
        """
        dJointAddUniversalTorques(self.jid, torque1, torque2)

    def getAngle1(self):
        return dJointGetUniversalAngle1(self.jid)

    def getAngle2(self):
        return dJointGetUniversalAngle2(self.jid)
    
    def getAngle1Rate(self):
        return dJointGetUniversalAngle1Rate(self.jid)

    def getAngle2Rate(self):
        return dJointGetUniversalAngle2Rate(self.jid)

    # setParam
    def setParam(self, param, value):
        dJointSetUniversalParam(self.jid, param, value)

    # getParam
    def getParam(self, param):
        return dJointGetUniversalParam(self.jid, param)

    
# Hinge2Joint
cdef class Hinge2Joint(Joint):
    """Hinge2 joint.

    Constructor::
    
      Hinge2Joint(world, jointgroup=None)
    """

    def __cinit__(self, World world not None, jointgroup=None):
        cdef JointGroup jg
        cdef dJointGroupID jgid

        jgid = NULL
        if jointgroup != None:
            jg = jointgroup
            jgid = jg.gid
        self.jid = dJointCreateHinge2(world.wid, jgid)

    def __init__(self, World world, jointgroup=None):
        self.world = world
        if jointgroup != None:
            jointgroup._addjoint(self)

    # setAnchor
    def setAnchor(self, pos):
        """setAnchor(pos)

        Set the hinge-2 anchor.

        @param pos: Anchor position
        @type pos: 3-sequence of floats
        """
        dJointSetHinge2Anchor(self.jid, pos[0], pos[1], pos[2])
    
    # getAnchor
    def getAnchor(self):
        """getAnchor() -> 3-tuple of floats

        Get the joint anchor point, in world coordinates. This returns
        the point on body 1. If the joint is perfectly satisfied, this
        will be the same as the point on body 2.
        """
        
        cdef dVector3 p
        dJointGetHinge2Anchor(self.jid, p)
        return p[0], p[1], p[2]

    # getAnchor2
    def getAnchor2(self):
        """getAnchor2() -> 3-tuple of floats

        Get the joint anchor point, in world coordinates. This returns
        the point on body 2. If the joint is perfectly satisfied, this
        will be the same as the point on body 1.
        """
        
        cdef dVector3 p
        dJointGetHinge2Anchor2(self.jid, p)
        return p[0], p[1], p[2]

    # setAxis1
    def setAxis1(self, axis):
        """setAxis1(axis)

        Set the first hinge-2 axis. Axis 1 and axis 2 must not lie
        along the same line.

        @param axis: Joint axis
        @type axis: 3-sequence of floats
        """
        
        dJointSetHinge2Axis1(self.jid, axis[0], axis[1], axis[2])
    
    # getAxis1
    def getAxis1(self):
        """getAxis1() -> 3-tuple of floats

        Get the first hinge-2 axis.
        """
        cdef dVector3 a
        dJointGetHinge2Axis1(self.jid, a)
        return a[0], a[1], a[2]

    # setAxis2
    def setAxis2(self, axis):
        """setAxis2(axis)

        Set the second hinge-2 axis. Axis 1 and axis 2 must not lie
        along the same line.

        @param axis: Joint axis
        @type axis: 3-sequence of floats
        """
        dJointSetHinge2Axis2(self.jid, axis[0], axis[1], axis[2])
    
    # getAxis2
    def getAxis2(self):
        """getAxis2() -> 3-tuple of floats

        Get the second hinge-2 axis.
        """
        cdef dVector3 a
        dJointGetHinge2Axis2(self.jid, a)
        return a[0], a[1], a[2]

    # getAngle
    def getAngle1(self):
        """getAngle1() -> float

        Get the first hinge-2 angle (around axis 1).

        When the anchor or axis is set, the current position of the
        attached bodies is examined and that position will be the zero
        angle.
        """
        return dJointGetHinge2Angle1(self.jid)

    # getAngle1Rate
    def getAngle1Rate(self):
        """getAngle1Rate() -> float

        Get the time derivative of the first hinge-2 angle.
        """
        return dJointGetHinge2Angle1Rate(self.jid)

    # getAngle2Rate
    def getAngle2Rate(self):
        """getAngle2Rate() -> float

        Get the time derivative of the second hinge-2 angle.
        """
        return dJointGetHinge2Angle2Rate(self.jid)

    # addTorques
    def addTorques(self, torque1, torque2):
        """addTorques(torque1, torque2)

        Applies torque1 about axis 1, and torque2 about axis 2.

        @param torque1: Torque 1 magnitude
        @param torque2: Torque 2 magnitude
        @type torque1: float
        @type torque2: float
        """
        dJointAddHinge2Torques(self.jid, torque1, torque2)

    # setParam
    def setParam(self, param, value):
        dJointSetHinge2Param(self.jid, param, value)

    # getParam
    def getParam(self, param):
        return dJointGetHinge2Param(self.jid, param)

    
# FixedJoint
cdef class FixedJoint(Joint):
    """Fixed joint.

    Constructor::
    
      FixedJoint(world, jointgroup=None)
    """

    def __cinit__(self, World world not None, jointgroup=None):
        cdef JointGroup jg
        cdef dJointGroupID jgid

        jgid = NULL
        if jointgroup != None:
            jg = jointgroup
            jgid = jg.gid
        self.jid = dJointCreateFixed(world.wid, jgid)

    def __init__(self, World world not None, jointgroup=None):
        self.world = world
        if jointgroup != None:
            jointgroup._addjoint(self)

    # setFixed
    def setFixed(self):
        """setFixed()

        Call this on the fixed joint after it has been attached to
        remember the current desired relative offset and desired
        relative rotation between the bodies.
        """
        dJointSetFixed(self.jid)

        
# ContactJoint
cdef class ContactJoint(Joint):
    """Contact joint.

    Constructor::
    
      ContactJoint(world, jointgroup, contact)
    """

    def __cinit__(self, World world not None, jointgroup, Contact contact):
        cdef JointGroup jg
        cdef dJointGroupID jgid
        jgid = NULL
        if jointgroup != None:
            jg = jointgroup
            jgid = jg.gid
        self.jid = dJointCreateContact(world.wid, jgid, &contact._contact)

    def __init__(self, World world not None, jointgroup, Contact contact):
        self.world = world
        if jointgroup != None:
            jointgroup._addjoint(self)

# AMotor
cdef class AMotor(Joint):
    """AMotor joint.
    
    Constructor::
    
      AMotor(world, jointgroup=None)
    """

    def __cinit__(self, World world not None, jointgroup=None):
        cdef JointGroup jg
        cdef dJointGroupID jgid

        jgid = NULL
        if jointgroup != None:
            jg = jointgroup
            jgid = jg.gid
        self.jid = dJointCreateAMotor(world.wid, jgid)

    def __init__(self, World world not None, jointgroup=None):
        self.world = world
        if jointgroup != None:
            jointgroup._addjoint(self)
            
    # setMode
    def setMode(self, mode):
        """setMode(mode)

        Set the angular motor mode.  mode must be either AMotorUser or
        AMotorEuler.

        @param mode: Angular motor mode
        @type mode: int
        """
        dJointSetAMotorMode(self.jid, mode)

    # getMode
    def getMode(self):
        """getMode()

        Return the angular motor mode (AMotorUser or AMotorEuler).
        """
        return dJointGetAMotorMode(self.jid)

    # setNumAxes
    def setNumAxes(self, int num):
        """setNumAxes(num)

        Set the number of angular axes that will be controlled by the AMotor.
        num may be in the range from 0 to 3.

        @param num: Number of axes (0-3)
        @type num: int
        """
        dJointSetAMotorNumAxes(self.jid, num)

    # getNumAxes
    def getNumAxes(self):
        """getNumAxes() -> int

        Get the number of angular axes that are controlled by the AMotor.
        """
        return dJointGetAMotorNumAxes(self.jid)

    # setAxis
    def setAxis(self, int anum, int rel, axis):
        """setAxis(anum, rel, axis)

        Set an AMotor axis.

        The anum argument selects the axis to change (0,1 or 2).
        Each axis can have one of three "relative orientation" modes,
        selected by rel:
        
        0: The axis is anchored to the global frame.
        1: The axis is anchored to the first body.
        2: The axis is anchored to the second body.

        The axis vector is always specified in global coordinates
        regardless of the setting of rel.

        @param anum: Axis number
        @param rel: Relative orientation mode
        @param axis: Axis
        @type anum: int
        @type rel: int
        @type axis: 3-sequence of floats
        """
        dJointSetAMotorAxis(self.jid, anum, rel, axis[0], axis[1], axis[2])

    # getAxis
    def getAxis(self, int anum):
        """getAxis(anum)

        Get an AMotor axis.

        @param anum: Axis index (0-2)
        @type anum: int
        """
        cdef dVector3 a
        dJointGetAMotorAxis(self.jid, anum, a)
        return a[0], a[1], a[2]

    # getAxisRel
    def getAxisRel(self, int anum):
        """getAxisRel(anum) -> int

        Get the relative mode of an axis.

        @param anum: Axis index (0-2)
        @type anum: int
        """
        return dJointGetAMotorAxisRel(self.jid, anum)

    # setAngle
    def setAngle(self, int anum, angle):
        """setAngle(anum, angle)

        Tell the AMotor what the current angle is along axis anum.

        @param anum: Axis index
        @param angle: Angle
        @type anum: int
        @type angle: float
        """
        dJointSetAMotorAngle(self.jid, anum, angle)

    # getAngle
    def getAngle(self, int anum):
        """getAngle(anum) -> float

        Return the current angle for axis anum.

        @param anum: Axis index
        @type anum: int
        """
        return dJointGetAMotorAngle(self.jid, anum)

    # getAngleRate
    def getAngleRate(self, int anum):
        """getAngleRate(anum) -> float

        Return the current angle rate for axis anum.

        @param anum: Axis index
        @type anum: int
        """
        return dJointGetAMotorAngleRate(self.jid, anum)

    # addTorques
    def addTorques(self, torque0, torque1, torque2):
        """addTorques(torque0, torque1, torque2)

        Applies torques about the AMotor's axes.

        @param torque0: Torque 0 magnitude
        @param torque1: Torque 1 magnitude
        @param torque2: Torque 2 magnitude
        @type torque0: float
        @type torque1: float
        @type torque2: float
        """
        dJointAddAMotorTorques(self.jid, torque0, torque1, torque2)

    # setParam
    def setParam(self, param, value):
        dJointSetAMotorParam(self.jid, param, value)

    # getParam
    def getParam(self, param):
        return dJointGetAMotorParam(self.jid, param)


# LMotor
cdef class LMotor(Joint):
    """LMotor joint.
    
    Constructor::
    
      LMotor(world, jointgroup=None)
    """

    def __cinit__(self, World world not None, jointgroup=None):
        cdef JointGroup jg
        cdef dJointGroupID jgid

        jgid = NULL
        if jointgroup != None:
            jg = jointgroup
            jgid = jg.gid
        self.jid = dJointCreateLMotor(world.wid, jgid)

    def __init__(self, World world not None, jointgroup=None):
        self.world = world
        if jointgroup != None:
            jointgroup._addjoint(self)
            
    # setNumAxes
    def setNumAxes(self, int num):
        """setNumAxes(num)

        Set the number of angular axes that will be controlled by the LMotor.
        num may be in the range from 0 to 3.

        @param num: Number of axes (0-3)
        @type num: int
        """
        dJointSetLMotorNumAxes(self.jid, num)

    # getNumAxes
    def getNumAxes(self):
        """getNumAxes() -> int

        Get the number of angular axes that are controlled by the LMotor.
        """
        return dJointGetLMotorNumAxes(self.jid)

    # setAxis
    def setAxis(self, int anum, int rel, axis):
        """setAxis(anum, rel, axis)

        Set an LMotor axis.

        The anum argument selects the axis to change (0,1 or 2).
        Each axis can have one of three "relative orientation" modes,
        selected by rel:

        0: The axis is anchored to the global frame.
        1: The axis is anchored to the first body.
        2: The axis is anchored to the second body.

        @param anum: Axis number
        @param rel: Relative orientation mode
        @param axis: Axis
        @type anum: int
        @type rel: int
        @type axis: 3-sequence of floats
        """
        dJointSetLMotorAxis(self.jid, anum, rel, axis[0], axis[1], axis[2])

    # getAxis
    def getAxis(self, int anum):
        """getAxis(anum)

        Get an LMotor axis.

        @param anum: Axis index (0-2)
        @type anum: int
        """
        cdef dVector3 a
        dJointGetLMotorAxis(self.jid, anum, a)
        return a[0], a[1], a[2]

    # setParam
    def setParam(self, param, value):
        dJointSetLMotorParam(self.jid, param, value)

    # getParam
    def getParam(self, param):
        return dJointGetLMotorParam(self.jid, param)


# Plane2DJoint
cdef class Plane2DJoint(Joint):
    """Plane-2D Joint.

    Constructor::
    
      Plane2DJoint(world, jointgroup=None)
    """

    def __cinit__(self, World world not None, jointgroup=None):
        cdef JointGroup jg
        cdef dJointGroupID jgid

        jgid = NULL
        if jointgroup != None:
            jg = jointgroup
            jgid = jg.gid
        self.jid = dJointCreatePlane2D(world.wid, jgid)

    def __init__(self, World world not None, jointgroup=None):
        self.world = world
        if jointgroup != None:
            jointgroup._addjoint(self)
            
    def setXParam(self, param, value):
        dJointSetPlane2DXParam(self.jid, param, value)
        
    def setYParam(self, param, value):
        dJointSetPlane2DYParam(self.jid, param, value)
        
    def setAngleParam(self, param, value):
        dJointSetPlane2DAngleParam(self.jid, param, value)


# PRJoint
cdef class PRJoint(Joint):
    """Prismatic and Rotoide Joint.

    Constructor::

      PRJoint(world, jointgroup=None)
    """

    def __cinit__(self, World world not None, jointgroup=None):
        cdef JointGroup jg
        cdef dJointGroupID jgid

        jgid = NULL
        if jointgroup != None:
            jg = jointgroup
            jgid = jg.gid
        self.jid = dJointCreatePR(world.wid, jgid)

    def __init__(self, World world not None, jointgroup=None):
        self.world = world
        if jointgroup != None:
            jointgroup._addjoint(self)

    def getPosition(self):
        """getPosition()

        Get a PRJoint's linear extension.  (i.e. the prismatic's extension)
        """
        return dJointGetPRPosition(self.jid)

    def setAnchor(self, pos):
        """setAnchor(pos)

        Set a PRJoint anchor.

        @param pos: Anchor position
        @type pos: 3-sequence of floats
        """
        dJointSetPRAnchor(self.jid, pos[0], pos[1], pos[2])

    def getAnchor(self):
        """getAnchor()

        Get a PRJoint anchor.
        """
        cdef dVector3 a
        dJointGetPRAnchor(self.jid, a)
        return a[0], a[1], a[2]

    def setAxis1(self, axis):
        """setAxis1(axis)

        Set a PRJoint's prismatic axis.

        @param axis: Axis
        @type axis: 3-sequence of floats
        """
        dJointSetPRAxis1(self.jid, axis[0], axis[1], axis[2])

    def getAxis1(self):
        """getAxis1()

        Get a PRJoint's prismatic axis.
        """
        cdef dVector3 a
        dJointGetPRAxis1(self.jid, a)
        return a[0], a[1], a[2]

    def setAxis2(self, axis):
        """setAxis2(axis)

        Set a PRJoint's rotoide axis.

        @param axis: Axis
        @type axis: 3-sequence of floats
        """
        dJointSetPRAxis2(self.jid, axis[0], axis[1], axis[2])

    def getAxis2(self):
        """getAxis2()

        Get a PRJoint's rotoide axis.
        """
        cdef dVector3 a
        dJointGetPRAxis2(self.jid, a)
        return a[0], a[1], a[2]


# Geom base class
cdef class GeomObject:
    """This is the abstract base class for all geom objects.
    """
    
    # The id of the geom object as returned by dCreateXxxx()
    cdef dGeomID gid
    # The space in which the geom was placed (or None). This reference
    # is kept so that the space won't be destroyed while there are still
    # geoms around that might use it.
    cdef object space
    # The body that the geom was attached to (or None).
    cdef object body

    # A dictionary with user defined attributes
    cdef object attribs

    cdef object __weakref__

    def __cinit__(self, *a, **kw):
        self.gid = NULL
        self.space = None
        self.body = None
        self.attribs = {}

    def __init__(self, *a, **kw):
        raise NotImplementedError(
            "GeomObject base class can't be used directly")

    def __dealloc__(self):
        if self.gid != NULL:
            dGeomDestroy(self.gid)
            self.gid = NULL

    def __getattr__(self, name):
        if name in self.attribs:
            return self.attribs[name]
        else:
            raise AttributeError("geom has no attribute '%s'" % name)

    def __setattr__(self, name, val):
        self.attribs[name] = val

    def __delattr__(self, name):
        if name in self.attribs:
            del self.attribs[name]
        else:
            raise AttributeError("geom has no attribute '%s'" % name)

    def _id(self):
        """_id() -> int

        Return the internal id of the geom (dGeomID) as returned by
        the dCreateXyz() functions.

        This method has to be overwritten in derived methods.
        """
        raise NotImplementedError("Bug: The _id() method is not implemented")

    def placeable(self):
        """placeable() -> bool

        Returns True if the geom object is a placeable geom.

        This method has to be overwritten in derived methods.
        """
        return False

    def setBody(self, Body body):
        """setBody(body)

        Set the body associated with a placeable geom.

        @param body: The Body object or None.
        @type body: Body
        """

        if not self.placeable():
            raise ValueError(
                "Non-placeable geoms cannot have a body associated to them")
        
        if body == None:
            dGeomSetBody(self.gid, NULL)
        else:
            dGeomSetBody(self.gid, body.bid)
        self.body = body

    def getBody(self):
        """getBody() -> Body

        Get the body associated with this geom.
        """
        if not self.placeable():
            return environment
        
        return self.body

    def setPosition(self, pos):
        """setPosition(pos)

        Set the position of the geom. If the geom is attached to a body,
        the body's position will also be changed.

        @param pos: Position
        @type pos: 3-sequence of floats
        """
        if not self.placeable():
            raise ValueError("Cannot set a position on non-placeable geoms")
        dGeomSetPosition(self.gid, pos[0], pos[1], pos[2])

    def getPosition(self):
        """getPosition() -> 3-tuple

        Get the current position of the geom. If the geom is attached to
        a body the returned value is the body's position.
        """
        if not self.placeable():
            raise ValueError("Non-placeable geoms do not have a position")

        cdef dReal* p
        p = dGeomGetPosition(self.gid)
        return p[0], p[1], p[2]

    def setRotation(self, R):
        """setRotation(R)

        Set the orientation of the geom. If the geom is attached to a body,
        the body's orientation will also be changed.

        @param R: Rotation matrix
        @type R: 9-sequence of floats
        """
        if not self.placeable():
            raise ValueError("Cannot set a rotation on non-placeable geoms")

        cdef dMatrix3 m
        m[0] = R[0]
        m[1] = R[1]
        m[2] = R[2]
        m[3] = 0
        m[4] = R[3]
        m[5] = R[4]
        m[6] = R[5]
        m[7] = 0
        m[8] = R[6]
        m[9] = R[7]
        m[10] = R[8]
        m[11] = 0
        dGeomSetRotation(self.gid, m)

    def getRotation(self):
        """getRotation() -> 9-tuple

        Get the current orientation of the geom. If the geom is attached to
        a body the returned value is the body's orientation.
        """
        if not self.placeable():
            raise ValueError("Non-placeable geoms do not have a rotation")

        cdef dReal* m
        m = dGeomGetRotation(self.gid)
        return [m[0], m[1], m[2], m[4], m[5], m[6], m[8], m[9], m[10]]

    def getQuaternion(self):
        """getQuaternion() -> (w,x,y,z)

        Get the current orientation of the geom. If the geom is attached to
        a body the returned value is the body's orientation.
        """
        if not self.placeable():
            raise ValueError("Non-placeable geoms do not have an orientation")

        cdef dQuaternion q
        dGeomGetQuaternion(self.gid, q)
        return q[0], q[1], q[2], q[3]

    def setQuaternion(self, q):
        """setQuaternion(q)

        Set the orientation of the geom. If the geom is attached to a body,
        the body's orientation will also be changed.

        @param q: Quaternion (w,x,y,z)
        @type q: 4-sequence of floats
        """
        if not self.placeable():
            raise ValueError("Cannot set a quaternion on non-placeable geoms")

        cdef dQuaternion cq
        cq[0] = q[0]
        cq[1] = q[1]
        cq[2] = q[2]
        cq[3] = q[3]
        dGeomSetQuaternion(self.gid, cq)

    def setOffsetPosition(self, pos):
        """setOffsetPosition(pos)

        Set the offset position of the geom. The geom must be attached to a
        body.  If the geom did not have an offset, it is automatically created.
        This sets up an additional (local) transformation for the geom, since
        geoms attached to a body share their global position and rotation.

        @param pos: Position
        @type pos: 3-sequence of floats
        """
        if self.body == None:
            raise ValueError("Cannot set an offset position on a geom before "
                             "calling setBody")
        dGeomSetOffsetPosition(self.gid, pos[0], pos[1], pos[2])

    def getOffsetPosition(self):
        """getOffsetPosition() -> 3-tuple

        Get the offset position of the geom.
        """
        cdef dReal* p
        p = dGeomGetOffsetPosition(self.gid)
        return (p[0],p[1],p[2])

    def setOffsetRotation(self, R):
        """setOffsetRotation(R)

        Set the offset rotation of the geom. The geom must be attached to a
        body.  If the geom did not have an offset, it is automatically created.
        This sets up an additional (local) transformation for the geom, since
        geoms attached to a body share their global position and rotation.

        @param R: Rotation matrix
        @type R: 9-sequence of floats
        """
        if self.body == None:
            raise ValueError("Cannot set an offset rotation on a geom before "
                             "calling setBody")

        cdef dMatrix3 m
        m[0] = R[0]
        m[1] = R[1]
        m[2] = R[2]
        m[3] = 0
        m[4] = R[3]
        m[5] = R[4]
        m[6] = R[5]
        m[7] = 0
        m[8] = R[6]
        m[9] = R[7]
        m[10] = R[8]
        m[11] = 0
        dGeomSetOffsetRotation(self.gid, m)

    def getOffsetRotation(self):
        """getOffsetRotation() -> 9-tuple

        Get the offset rotation of the geom.
        """
        cdef dReal* m
        m = dGeomGetOffsetRotation(self.gid)
        return [m[0], m[1], m[2], m[4], m[5], m[6], m[8], m[9], m[10]]

    def clearOffset(self):
        """clearOffset()

        Disable the offset transform of the geom.
        """
        dGeomClearOffset(self.gid)

    def getAABB(self):
        """getAABB() -> 6-tuple

        Return an axis aligned bounding box that surrounds the geom.
        The return value is a 6-tuple (minx, maxx, miny, maxy, minz, maxz).
        """
        cdef dReal aabb[6]
        
        dGeomGetAABB(self.gid, aabb)
        return aabb[0], aabb[1], aabb[2], aabb[3], aabb[4], aabb[5]

    def isSpace(self):
        """isSpace() -> bool

        Return 1 if the given geom is a space, or 0 if not."""
        return dGeomIsSpace(self.gid)

    def getSpace(self):
        """getSpace() -> Space

        Return the space that the given geometry is contained in,
        or return None if it is not contained in any space."""
        return self.space

    def setCollideBits(self, bits):
        """setCollideBits(bits)

        Set the "collide" bitfields for this geom.

        @param bits: Collide bit field
        @type bits: int/long
        """
        dGeomSetCollideBits(self.gid, long(bits))
        
    def setCategoryBits(self, bits):
        """setCategoryBits(bits)

        Set the "category" bitfields for this geom.

        @param bits: Category bit field
        @type bits: int/long
        """
        dGeomSetCategoryBits(self.gid, long(bits))

    def getCollideBits(self):
        """getCollideBits() -> long

        Return the "collide" bitfields for this geom.
        """
        return dGeomGetCollideBits(self.gid)

    def getCategoryBits(self):
        """getCategoryBits() -> long

        Return the "category" bitfields for this geom.
        """
        return dGeomGetCategoryBits(self.gid)
    
    def enable(self):
        """enable()

        Enable the geom."""
        dGeomEnable(self.gid)

    def disable(self):
        """disable()

        Disable the geom."""
        dGeomDisable(self.gid)

    def isEnabled(self):
        """isEnabled() -> bool

        Return True if the geom is enabled."""
        return dGeomIsEnabled(self.gid)


# _SpaceIterator
class _SpaceIterator:
    """Iterates over the geoms inside a Space.
    """

    def __init__(self, space):
        self.space = space
        self.idx = 0
        
    def __iter__(self):
        return self

    def next(self):
        if self.idx >= self.space.getNumGeoms():
            raise StopIteration
        else:
            res = self.space.getGeom(self.idx)
            self.idx = self.idx + 1
            return res


# SpaceBase
cdef class SpaceBase(GeomObject):
    """Space class (container for geometry objects).

    A Space object is a container for geometry objects which are used
    to do collision detection.
    The space does high level collision culling, which means that it
    can identify which pairs of geometry objects are potentially
    touching.

    This Space class can be used for both, a SimpleSpace and a HashSpace
    (see ODE documentation).

     >>> space = Space(type=0)   # Create a SimpleSpace
     >>> space = Space(type=1)   # Create a HashSpace
    """

    # The id of the space. Actually this is a copy of the value in self.gid
    # (as the Space is derived from GeomObject) which can be used without
    # casting whenever a *space* id is required.
    cdef dSpaceID sid
    
    # Dictionary with Geomobjects. Key is the ID (geom._id()) and the value
    # is the geom object (Python wrapper). This is used in collide_callback()
#    cdef object geom_dict

    def __cinit__(self, *a, **kw):
        pass

    def __init__(self, *a, **kw):
        raise NotImplementedError("The SpaceBase class can't be used directly")

    def __dealloc__(self):
        if self.gid != NULL:
            dSpaceDestroy(self.sid)
            self.sid = NULL
            self.gid = NULL

#    def _addgeom(self, geom):
#        """Insert the geom object into the dictionary (internal method).
#
#        This method has to called in the constructor of a geom object.
#        """
#        self.geom_dict[geom._id()]=geom

#    def _id2geom(self, id):
#        """Get the Python wrapper that corresponds to an ID.
#
#        The ID is the integer value, as returned by geom._id().
#        If the ID is unknown then None is returned.
#        """
#        if id in self.geom_dict:
#            return self.geom_dict[id]
#        else:
#            return None
       
    def _id(self):
        cdef long id
        id = self.sid
        return id

    def __len__(self):
        return self.getNumGeoms()

    def __iter__(self):
        return _SpaceIterator(self)

    def add(self, GeomObject geom):
        """add(geom)

        Add a geom to a space. This does nothing if the geom is
        already in the space.

        @param geom: Geom object to add
        @type geom: GeomObject
        """
        
        dSpaceAdd(self.sid, geom.gid)

    def remove(self, GeomObject geom):
        """remove(geom)

        Remove a geom from a space.

        @param geom: Geom object to remove
        @type geom: GeomObject
        """
        dSpaceRemove(self.sid, geom.gid)

    def query(self, GeomObject geom):
        """query(geom) -> bool

        Return True if the given geom is in the space.

        @param geom: Geom object to check
        @type geom: GeomObject
        """
        return dSpaceQuery(self.sid, geom.gid)

    def getNumGeoms(self):
        """getNumGeoms() -> int

        Return the number of geoms contained within the space.
        """
        return dSpaceGetNumGeoms(self.sid)

    def getGeom(self, int idx):
        """getGeom(idx) -> GeomObject

        Return the geom with the given index contained within the space.

        @param idx: Geom index (0,1,...,getNumGeoms()-1)
        @type idx: int
        """
        cdef dGeomID gid

        # Check the index
        if idx < 0 or idx >= dSpaceGetNumGeoms(self.sid):
            raise IndexError("geom index out of range")

        gid = dSpaceGetGeom(self.sid, idx)
        if gid not in _geom_c2py_lut:
            raise RuntimeError(
                "geom id cannot be translated to a Python object")

        return _geom_c2py_lut[gid]

    def collide(self, arg, callback):
        """collide(arg, callback)

        Call a callback function one or more times, for all
        potentially intersecting objects in the space. The callback
        function takes 3 arguments:

        def NearCallback(arg, geom1, geom2):

        The arg parameter is just passed on to the callback function.
        Its meaning is user defined. The geom1 and geom2 arguments are
        the geometry objects that may be near each other. The callback
        function can call the function collide() (not the Space
        method) on geom1 and geom2, perhaps first determining
        whether to collide them at all based on other information.

        @param arg: A user argument that is passed to the callback function
        @param callback: Callback function
        @type callback: callable
        """
        
        cdef void* data
        cdef object tup
        tup = (callback, arg)
        data = tup
        dSpaceCollide(self.sid, data, collide_callback)


# Callback function for the dSpaceCollide() call in the Space.collide() method
# The data parameter is a tuple (Python-Callback, Arguments).
# The function calls a Python callback function with 3 arguments:
# def callback(UserArg, Geom1, Geom2)
# Geom1 and Geom2 are instances of GeomXyz classes.
cdef void collide_callback(void* data, dGeomID o1, dGeomID o2):
    cdef object tup
#    cdef Space space
    cdef long id1, id2

#    if (dGeomGetBody(o1)==dGeomGetBody(o2)):
#        return
    
    tup = data
    callback, arg = tup
    id1 = o1
    id2 = o2
    g1 = _geom_c2py_lut[id1]
    g2 = _geom_c2py_lut[id2]
    callback(arg, g1, g2)


# SimpleSpace
cdef class SimpleSpace(SpaceBase):
    """Simple space.

    This does not do any collision culling - it simply checks every
    possible pair of geoms for intersection, and reports the pairs
    whose AABBs overlap. The time required to do intersection testing
    for n objects is O(n**2). This should not be used for large numbers
    of objects, but it can be the preferred algorithm for a small
    number of objects. This is also useful for debugging potential
    problems with the collision system.
    """

    def __cinit__(self, space=None):
        cdef SpaceBase sp
        cdef dSpaceID parentid

        parentid = NULL
        if space != None:
            sp = space
            parentid = sp.sid
        
        self.sid = dSimpleSpaceCreate(parentid)

        # Copy the ID
        self.gid = self.sid

        dSpaceSetCleanup(self.sid, 0)
        _geom_c2py_lut[self.sid] = self

    def __init__(self, space=None):
        pass

# HashSpace
cdef class HashSpace(SpaceBase):
    """Multi-resolution hash table space.

    This uses an internal data structure that records how each geom
    overlaps cells in one of several three dimensional grids. Each
    grid has cubical cells of side lengths 2**i, where i is an integer
    that ranges from a minimum to a maximum value. The time required
    to do intersection testing for n objects is O(n) (as long as those
    objects are not clustered together too closely), as each object
    can be quickly paired with the objects around it.
    """

    def __cinit__(self, space=None):
        cdef SpaceBase sp
        cdef dSpaceID parentid

        parentid = NULL
        if space != None:
            sp = space
            parentid = sp.sid
        
        self.sid = dHashSpaceCreate(parentid)

        # Copy the ID
        self.gid = self.sid

        dSpaceSetCleanup(self.sid, 0)
        _geom_c2py_lut[self.sid] = self

    def __init__(self, space=None):
        pass
    
    def setLevels(self, int minlevel, int maxlevel):
        """setLevels(minlevel, maxlevel)

        Sets the size of the smallest and largest cell used in the
        hash table. The actual size will be 2^minlevel and 2^maxlevel
        respectively.
        """
        
        if minlevel > maxlevel:
            raise ValueError(
                "minlevel (%d) must be less than or equal to maxlevel (%d)" %
                (minlevel, maxlevel))
            
        dHashSpaceSetLevels(self.sid, minlevel, maxlevel)

    def getLevels(self):
        """getLevels() -> (minlevel, maxlevel)

        Gets the size of the smallest and largest cell used in the
        hash table. The actual size is 2^minlevel and 2^maxlevel
        respectively.
        """
        
        cdef int minlevel
        cdef int maxlevel
        dHashSpaceGetLevels(self.sid, &minlevel, &maxlevel)
        return minlevel, maxlevel


# QuadTreeSpace
cdef class QuadTreeSpace(SpaceBase):
    """Quadtree space.

    This uses a pre-allocated hierarchical grid-based AABB tree to
    quickly cull collision checks. It's exceptionally quick for large
    amounts of objects in landscape-shaped worlds. The amount of
    memory used is 4**depth * 32 bytes.

    Currently getGeom() is not implemented for the quadtree space.
    """

    def __cinit__(self, center, extents, depth, space=None):
        cdef SpaceBase sp
        cdef dSpaceID parentid
        cdef dVector3 c
        cdef dVector3 e

        parentid = NULL
        if space != None:
            sp = space
            parentid = sp.sid

        c[0] = center[0]
        c[1] = center[1]
        c[2] = center[2]
        e[0] = extents[0]
        e[1] = extents[1]
        e[2] = extents[2]
        self.sid = dQuadTreeSpaceCreate(parentid, c, e, depth)

        # Copy the ID
        self.gid = self.sid

        dSpaceSetCleanup(self.sid, 0)
        _geom_c2py_lut[self.sid] = self

    def __init__(self, center, extents, depth, space=None):
        pass


def Space(space_type=0):
    """Space factory function.

    Depending on the type argument this function either returns a
    SimpleSpace (space_type=0) or a HashSpace (space_type=1).

    This function is provided to remain compatible with previous
    versions of PyODE where there was only one Space class.
    
     >>> space = Space(space_type=0)   # Create a SimpleSpace
     >>> space = Space(space_type=1)   # Create a HashSpace
    """
    if space_type == 0:
        return SimpleSpace()
    elif space_type == 1:
        return HashSpace()
    else:
        raise ValueError("Unknown space type (%d)" % space_type)


# GeomSphere
cdef class GeomSphere(GeomObject):
    """Sphere geometry.

    This class represents a sphere centered at the origin.

    Constructor::
    
      GeomSphere(space=None, radius=1.0)
    """

    def __cinit__(self, space=None, radius=1.0):
        cdef SpaceBase sp
        cdef dSpaceID sid

        sid = NULL
        if space != None:
            sp = space
            sid = sp.sid
        self.gid = dCreateSphere(sid, radius)
#        if space != None:
#            space._addgeom(self)

        _geom_c2py_lut[self.gid] = self

    def __init__(self, space=None, radius=1.0):
        self.space = space
        self.body = None

    def placeable(self):
        return True

    def _id(self):
        cdef long id
        id = self.gid
        return id

    def setRadius(self, radius):
        """setRadius(radius)

        Set the radius of the sphere.

        @param radius: New radius
        @type radius: float
        """
        dGeomSphereSetRadius(self.gid, radius)

    def getRadius(self):
        """getRadius() -> float

        Return the radius of the sphere.
        """
        return dGeomSphereGetRadius(self.gid)

    def pointDepth(self, p):
        """pointDepth(p) -> float

        Return the depth of the point p in the sphere. Points inside
        the geom will have positive depth, points outside it will have
        negative depth, and points on the surface will have zero
        depth.

        @param p: Point
        @type p: 3-sequence of floats
        """
        return dGeomSpherePointDepth(self.gid, p[0], p[1], p[2])

                
# GeomBox
cdef class GeomBox(GeomObject):
    """Box geometry.

    This class represents a box centered at the origin.

    Constructor::
    
      GeomBox(space=None, lengths=(1.0, 1.0, 1.0))
    """

    def __cinit__(self, space=None, lengths=(1.0, 1.0, 1.0)):
        cdef SpaceBase sp
        cdef dSpaceID sid
        
        sid = NULL
        if space != None:
            sp = space
            sid = sp.sid
        self.gid = dCreateBox(sid, lengths[0], lengths[1], lengths[2])
#        if space != None:
#            space._addgeom(self)

        _geom_c2py_lut[self.gid] = self

    def __init__(self, space=None, lengths=(1.0, 1.0, 1.0)):
        self.space = space
        self.body = None

    def placeable(self):
        return True

    def _id(self):
        cdef long id
        id = self.gid
        return id

    def setLengths(self, lengths):
        dGeomBoxSetLengths(self.gid, lengths[0], lengths[1], lengths[2])

    def getLengths(self):
        cdef dVector3 res
        dGeomBoxGetLengths(self.gid, res)
        return res[0], res[1], res[2]

    def pointDepth(self, p):
        """pointDepth(p) -> float

        Return the depth of the point p in the box. Points inside the
        geom will have positive depth, points outside it will have
        negative depth, and points on the surface will have zero
        depth.

        @param p: Point
        @type p: 3-sequence of floats
        """
        return dGeomBoxPointDepth(self.gid, p[0], p[1], p[2])


# GeomPlane
cdef class GeomPlane(GeomObject):
    """Plane geometry.

    This class represents an infinite plane. The plane equation is:
    n.x*x + n.y*y + n.z*z = dist

    This object can't be attached to a body.
    If you call getBody() on this object it always returns ode.environment.

    Constructor::
    
      GeomPlane(space=None, normal=(0,0,1), dist=0)

    """

    def __cinit__(self, space=None, normal=(0, 0, 1), dist=0):
        cdef SpaceBase sp
        cdef dSpaceID sid
        
        sid = NULL
        if space != None:
            sp = space
            sid = sp.sid
        self.gid = dCreatePlane(sid, normal[0], normal[1], normal[2], dist)
#        if space != None:
#            space._addgeom(self)

        _geom_c2py_lut[self.gid] = self

    def __init__(self, space=None, normal=(0, 0, 1), dist=0):
        self.space = space

    def _id(self):
        cdef long id
        id = self.gid
        return id

    def setParams(self, normal, dist):
        dGeomPlaneSetParams(self.gid, normal[0], normal[1], normal[2], dist)

    def getParams(self):
        cdef dVector4 res
        dGeomPlaneGetParams(self.gid, res)
        return ((res[0], res[1], res[2]), res[3])

    def pointDepth(self, p):
        """pointDepth(p) -> float

        Return the depth of the point p in the plane. Points inside the
        geom will have positive depth, points outside it will have
        negative depth, and points on the surface will have zero
        depth.

        @param p: Point
        @type p: 3-sequence of floats
        """
        return dGeomPlanePointDepth(self.gid, p[0], p[1], p[2])


# GeomCapsule
cdef class GeomCapsule(GeomObject):
    """Capped cylinder geometry.

    This class represents a capped cylinder aligned along the local Z axis
    and centered at the origin.

    Constructor::
    
      GeomCapsule(space=None, radius=0.5, length=1.0)

    The length parameter does not include the caps.
    """

    def __cinit__(self, space=None, radius=0.5, length=1.0):
        cdef SpaceBase sp
        cdef dSpaceID sid
        
        sid = NULL
        if space != None:
            sp = space
            sid = sp.sid
        self.gid = dCreateCapsule(sid, radius, length)
#        if space != None:
#            space._addgeom(self)

        _geom_c2py_lut[self.gid] = self

    def __init__(self, space=None, radius=0.5, length=1.0):
        self.space = space
        self.body = None

    def placeable(self):
        return True

    def _id(self):
        cdef long id
        id = self.gid
        return id

    def setParams(self, radius, length):
        dGeomCapsuleSetParams(self.gid, radius, length)

    def getParams(self):
        cdef dReal radius, length
        dGeomCapsuleGetParams(self.gid, &radius, &length)
        return radius, length

    def pointDepth(self, p):
        """pointDepth(p) -> float

        Return the depth of the point p in the cylinder. Points inside the
        geom will have positive depth, points outside it will have
        negative depth, and points on the surface will have zero
        depth.

        @param p: Point
        @type p: 3-sequence of floats
        """
        return dGeomCapsulePointDepth(self.gid, p[0], p[1], p[2])

GeomCCylinder = GeomCapsule # backwards compatibility


# GeomCylinder
cdef class GeomCylinder(GeomObject):
    """Plain cylinder geometry.

    This class represents an uncapped cylinder aligned along the local Z axis
    and centered at the origin.

    Constructor::
    
      GeomCylinder(space=None, radius=0.5, length=1.0)
    """

    def __cinit__(self, space=None, radius=0.5, length=1.0):
        cdef SpaceBase sp
        cdef dSpaceID sid
        
        sid = NULL
        if space != None:
            sp = space
            sid = sp.sid
        self.gid = dCreateCylinder(sid, radius, length)
#        if space != None:
#            space._addgeom(self)

        _geom_c2py_lut[self.gid] = self

    def __init__(self, space=None, radius=0.5, length=1.0):
        self.space = space
        self.body = None

    def placeable(self):
        return True

    def _id(self):
        cdef long id
        id = self.gid
        return id

    def setParams(self, radius, length):
        dGeomCylinderSetParams(self.gid, radius, length)

    def getParams(self):
        cdef dReal radius, length
        dGeomCylinderGetParams(self.gid, &radius, &length)
        return radius, length

    ## dGeomCylinderPointDepth not implemented upstream in ODE 0.7


# GeomRay
cdef class GeomRay(GeomObject):
    """Ray object.

    A ray is different from all the other geom classes in that it does
    not represent a solid object. It is an infinitely thin line that
    starts from the geom's position and extends in the direction of
    the geom's local Z-axis.

    Constructor::
    
      GeomRay(space=None, rlen=1.0)
    
    """

    def __cinit__(self, space=None, rlen=1.0):
        cdef SpaceBase sp
        cdef dSpaceID sid
        
        sid = NULL
        if space != None:
            sp = space
            sid = sp.sid
        self.gid = dCreateRay(sid, rlen)
#        if space != None:
#            space._addgeom(self)

        _geom_c2py_lut[self.gid] = self

    def __init__(self, space=None, rlen=1.0):
        self.space = space
        self.body = None

    def _id(self):
        cdef long id
        id = self.gid
        return id

    def placeable(self):
        return True

    def setLength(self, rlen):
        '''setLength(rlen)

        Set length of the ray.

        @param rlen: length of the ray
        @type rlen: float'''
        dGeomRaySetLength(self.gid, rlen)

    def getLength(self):
        '''getLength() -> length

        Get the length of the ray.

        @returns: length of the ray (float)'''
        return dGeomRayGetLength(self.gid)

    def set(self, p, u):
        '''set(p, u)

        Set the position and rotation of a ray.
        
        @param p: position
        @type p: 3-sequence of floats
        @param u: rotation
        @type u: 3-sequence of floats'''
        dGeomRaySet(self.gid, p[0], p[1], p[2], u[0], u[1], u[2])

    def get(self):
        '''get() -> ((p[0], p[1], p[2]), (u[0], u[1], u[2]))

        Return the position and rotation as a pair of
        tuples.

        @returns: position and rotation'''
        cdef dVector3 start
        cdef dVector3 dir
        dGeomRayGet(self.gid, start, dir)
        return (start[0], start[1], start[2]), (dir[0], dir[1], dir[2])


# GeomTransform
cdef class GeomTransform(GeomObject):
    """GeomTransform.

    A geometry transform "T" is a geom that encapsulates another geom
    "E", allowing E to be positioned and rotated arbitrarily with
    respect to its point of reference.

    Constructor::
    
      GeomTransform(space=None)
    """

    cdef object geom

    def __cinit__(self, space=None):
        cdef SpaceBase sp
        cdef dSpaceID sid
        
        sid = NULL
        if space != None:
            sp = space
            sid = sp.sid
        self.gid = dCreateGeomTransform(sid)
        # Set cleanup mode to 0 as a contained geom will be deleted
        # by its Python wrapper class
        dGeomTransformSetCleanup(self.gid, 0)
#        if space != None:
#            space._addgeom(self)

        _geom_c2py_lut[self.gid] = self

    def __init__(self, space=None):
        self.space = space
        self.body = None
        self.geom = None

        self.attribs = {}

    def placeable(self):
        return True

    def _id(self):
        cdef long id
        id = self.gid
        return id

    def setGeom(self, GeomObject geom not None):
        """setGeom(geom)

        Set the geom that the geometry transform encapsulates.
        A ValueError exception is thrown if a) the geom is not placeable,
        b) the geom was already inserted into a space or c) the geom is
        already associated with a body.

        @param geom: Geom object to encapsulate
        @type geom: GeomObject
        """
        cdef long id

        if not geom.placeable():
            raise ValueError(
                "Only placeable geoms can be encapsulated by a GeomTransform")
        if dGeomGetSpace(geom.gid) != 0:
            raise ValueError(
                "The encapsulated geom was already inserted into a space")
        if dGeomGetBody(geom.gid) != 0:
            raise ValueError(
                "The encapsulated geom is already associated with a body")
        
        id = geom._id()
        dGeomTransformSetGeom(self.gid, id)
        self.geom = geom

    def getGeom(self):
        """getGeom() -> GeomObject

        Get the geom that the geometry transform encapsulates.
        """
        return self.geom

    def setInfo(self, int mode):
        """setInfo(mode)

        Set the "information" mode of the geometry transform.

        With mode 0, when a transform object is collided with another
        object, the geom field of the ContactGeom structure is set to the
        geom that is encapsulated by the transform object.

        With mode 1, the geom field of the ContactGeom structure is set
        to the transform object itself.

        @param mode: Information mode (0 or 1)
        @type mode: int
        """
        if mode < 0 or mode > 1:
            raise ValueError(
                "Invalid information mode (%d). Must be either 0 or 1." % mode)
        dGeomTransformSetInfo(self.gid, mode)

    def getInfo(self):
        """getInfo() -> int

        Get the "information" mode of the geometry transform (0 or 1).

        With mode 0, when a transform object is collided with another
        object, the geom field of the ContactGeom structure is set to the
        geom that is encapsulated by the transform object.

        With mode 1, the geom field of the ContactGeom structure is set
        to the transform object itself.
        """
        return dGeomTransformGetInfo(self.gid)

######################################################################


cdef class TriMeshData:
    """This class stores the mesh data.
    """

    cdef dTriMeshDataID tmdid
    cdef dReal* vertex_buffer
    cdef int* face_buffer

    def __cinit__(self):
        self.tmdid = dGeomTriMeshDataCreate()
        self.vertex_buffer = NULL
        self.face_buffer = NULL

    def __dealloc__(self):
        if self.tmdid != NULL:
            dGeomTriMeshDataDestroy(self.tmdid)
        if self.vertex_buffer != NULL:
            free(self.vertex_buffer)
        if self.face_buffer != NULL:
            free(self.face_buffer)
    
    def build(self, verts, faces):
        """build(verts, faces)

        @param verts: Vertices
        @type verts: Sequence of 3-sequences of floats
        @param faces: Face definitions (three indices per face)
        @type faces: Sequence of 3-sequences of ints
        """
        cdef int numverts
        cdef int numfaces
        cdef dReal* vp
        cdef int* fp
        cdef int a, b, c
        
        numverts = len(verts)
        numfaces = len(faces)
        # Allocate the vertex and face buffer
        self.vertex_buffer = malloc(numverts * 4 * sizeof(dReal))
        self.face_buffer = malloc(numfaces * 3 * sizeof(int))

        # Fill the vertex buffer
        vp = self.vertex_buffer
        for v in verts:
            vp[0] = v[0]
            vp[1] = v[1]
            vp[2] = v[2]
            vp[3] = 0
            vp = vp + 4

        # Fill the face buffer
        fp = self.face_buffer
        for f in faces:
            a = f[0]
            b = f[1]
            c = f[2]
            if (a < 0 or b < 0 or c < 0 or a >= numverts or b >= numverts or c >= numverts):
                raise ValueError("Vertex index out of range")
            fp[0] = a
            fp[1] = b
            fp[2] = c
            fp = fp + 3

        # Pass the data to ODE
        dGeomTriMeshDataBuildSimple(self.tmdid, self.vertex_buffer, numverts,
                                    self.face_buffer, numfaces * 3)

######################################################################


# GeomTriMesh
cdef class GeomTriMesh(GeomObject):
    """TriMesh object.

    To construct the trimesh geom you need a TriMeshData object that
    stores the actual mesh. This object has to be passed as first
    argument to the constructor.

    Constructor::
    
      GeomTriMesh(data, space=None)
    """

    # Keep a reference to the data
    cdef TriMeshData data

    def __cinit__(self, TriMeshData data not None, space=None):
        cdef SpaceBase sp
        cdef dSpaceID sid

        self.data = data

        sid = NULL
        if space != None:
            sp = space
            sid = sp.sid
        self.gid = dCreateTriMesh(sid, data.tmdid, NULL, NULL, NULL)

        _geom_c2py_lut[self.gid] = self

    def __init__(self, TriMeshData data not None, space=None):
        self.space = space
        self.body = None

    def placeable(self):
        return True

    def _id(self):
        cdef long id
        id = self.gid
        return id

    def clearTCCache(self):
        """clearTCCache()

        Clears the internal temporal coherence caches.
        """
        dGeomTriMeshClearTCCache(self.gid)

    def getTriangle(self, int idx):
        """getTriangle(idx) -> (v0, v1, v2)

        @param idx: Triangle index
        @type idx: int
        """

        cdef dVector3 v0, v1, v2
        cdef dVector3* vp0
        cdef dVector3* vp1
        cdef dVector3* vp2

        vp0 = v0
        vp1 = v1
        vp2 = v2

        dGeomTriMeshGetTriangle(self.gid, idx, vp0, vp1, vp2)
        return ((v0[0], v0[1], v0[2]),
                (v1[0], v1[1], v1[2]),
                (v2[0], v2[1], v2[2]))
        
    def getTriangleCount(self):
        """getTriangleCount() -> n

        Returns the number of triangles in the TriMesh."""

        return dGeomTriMeshGetTriangleCount(self.gid)

######################################################################


def collide(geom1, geom2):
    """collide(geom1, geom2) -> contacts

    Generate contact information for two objects.

    Given two geometry objects that potentially touch (geom1 and geom2),
    generate contact information for them. Internally, this just calls
    the correct class-specific collision functions for geom1 and geom2.

    [flags specifies how contacts should be generated if the objects
    touch. Currently the lower 16 bits of flags specifies the maximum
    number of contact points to generate. If this number is zero, this
    function just pretends that it is one - in other words you can not
    ask for zero contacts. All other bits in flags must be zero. In
    the future the other bits may be used to select other contact
    generation strategies.]

    If the objects touch, this returns a list of Contact objects,
    otherwise it returns an empty list.

    @param geom1: First Geom
    @type geom1: GeomObject
    @param geom2: Second Geom
    @type geom2: GeomObject
    @returns: Returns a list of Contact objects.
    """
    
    cdef dContactGeom c[150]
    cdef long id1
    cdef long id2
    cdef int i, n
    cdef Contact cont

    id1 = geom1._id()
    id2 = geom2._id()

    n = dCollide(id1, id2, 150, c, sizeof(dContactGeom))
    res = []
    i = 0
    while i < n:
        cont = Contact()
        cont._contact.geom = c[i]
        res.append(cont)
        i = i + 1

    return res


def collide2(geom1, geom2, arg, callback):
    """collide2(geom1, geom2, arg, callback)
    
    Calls the callback for all potentially intersecting pairs that contain
    one geom from geom1 and one geom from geom2.

    @param geom1: First Geom
    @type geom1: GeomObject
    @param geom2: Second Geom
    @type geom2: GeomObject
    @param arg: A user argument that is passed to the callback function
    @param callback: Callback function
    @type callback: callable
    """
    cdef void* data
    cdef object tup
    cdef long id1
    cdef long id2

    id1 = geom1._id()
    id2 = geom2._id()
    
    tup = (callback, arg)
    data = tup
    # collide_callback is defined in space.pyx
    dSpaceCollide2(id1, id2, data, collide_callback)


def areConnected(Body body1, Body body2):
    """areConnected(body1, body2) -> bool

    Return True if the two bodies are connected together by a joint,
    otherwise return False.

    @param body1: First body
    @type body1: Body
    @param body2: Second body
    @type body2: Body
    @returns: True if the bodies are connected
    """

    if body1 is environment:
        return False
    if body2 is environment:
        return False

    return bool(dAreConnected( body1.bid,  body2.bid))


def CloseODE():
    """CloseODE()

    Deallocate some extra memory used by ODE that can not be deallocated
    using the normal destroy functions.
    """
    dCloseODE()


def InitODE():
    '''InitODE()

    Initialize some ODE internals. This will be called for you when you
    "import ode", but you should call this again if you CloseODE().'''
    dInitODE()


#environment = Body(None)
environment = None
InitODE()
ode-0.16/CHANGELOG.txt0000664000175200017520000012714413403272463011203 00000000000000ODE CHANGELOG
-------------

the rules for this file:
  * entries are sorted newest-first.
  * summarize sets of changes - dont reproduce every CVS log comment here.
  * don't ever delete anything.
  * keep the format consistent (79 char width, M/D/Y date format).

------------------------------------------------------------------------------
11/12/2018 Oleh Derevenko
        * The commentary from 11/05/2018 was wrong. The constraints were not
          reset to their natural order and remained randomized.
          The other thing that was missing was full contraint reorder without 
          separation into independent and dependent ones. The algorithm doesn't
          converge without it well.

11/10/2018 Oleh Derevenko
        * An incorrect optimization to Jacobian Copy building code from #1938
          that resulted in corrupt data in multi-threaded execution mode was 
          fixed.

11/05/2018 Oleh Derevenko
        * An unintended change from commit #1898 has been reverted.
          The QuickStep used to solve with randomized constraint order 
          each 8th iteration. The other iterations, the constraints 
          were reset to their natural order, as generated, with the dependent
          constraints gathered in reverse order at end (the reverse order is 
          somehow important). With the commit #1898 the constraints were
          randomly reordered each 8th iteration but then remained 
          in that randomized order and only were re-randomized on subsequent
          multiples of 8.

10/09/2017 Markus Rickert
        * CMake support for project file generation has been added.

06/14/2017 Oleh Derevenko
        * dxHashSpace::collide() has been changed to fault host program 
          if scene gets too large and causes integer overflow.

06/06/2017 Oleh Derevenko
        * Memory and pointer size integer type use has been changed so that 
          internal typedefs are used instead of "_t" suffixed types.

05/09/2017 Oleh Derevenko
        * Introduction of cooperative algorithms API. 
          L*D*LT cooperative factorization and linear equation system 
          cooperative solving have been implemented.
        * AtomicReadReorderBarrier, AtomicStore, AtomicStorePointer functions 
          have been added and some atomic function implementations have been 
          improved in OU.

02/20/2017 Oleh Derevenko
        * Project generation options have been changed to have built-in
          multithreaded threading implementation enabled by default.

02/19/2017 Oleh Derevenko
        * dWorldStep threaded implementation has been extended to the final 
          steps of constraint force applications and body position updates
          after the LCP solving. Note that body callbacks (if set) may be
          called from multiple threads if threaded execution is enabled.
        * OU atomicord32 type has been fixed to be unsigned on all supported
          platforms.

01/09/2017 Oleh Derevenko
        * dGeomTriMeshDataPreprocess2() public function has been added to 
          replace dGeomTriMeshDataPreprocess(). Face angles pre-computation
          for triangle meshes has been implemented.

11/13/2016 Oleh Derevenko
        * dGeomTriMeshDataGetBuff and dGeomTriMeshDataSetBuff have been marked 
          deprecated and their functionality implemented via 
          dGeomTriMeshDataGet and dGeomTriMeshDataSet. Extra function variant
          dGeomTriMeshDataGet2() has been added to allow returning data size.

11/07/2016 Oleh Derevenko
        * The implementation of OPCODE TriMesh data pre-processing 
          (dGeomTriMeshDataPreprocess()) has been optimized to only contain
          a sort and a single pass over edges (used to be a sort and O(N^2)).

10/29/2016 Oleh Derevenko
        * dGeomTriMeshDataPreprocess() public function has been changed to 
          return a boolean status (it can fail in low memory conditions).

07/10/2016 Oleh Derevenko
        * The correct handling of dJOINT_REVERSE mode for AngularMotor Joint 
          implemented (issue #37).

06/29/2016 Oleh Derevenko
        * A bug fixed with HashSpace calling big boxes collision twice 
          (both straight and reverse geometries order) since revision #1831.

06/03/2016 Oleh Derevenko
        * dJointSetHinge2Axes public function has been added and 
          dJointSetHinge2Axis1/2 have been marked deprecated due to being 
          unsafe.

05/13/2016 Oleh Derevenko
        * ICE Container class allocation strategy fixed to avoid reserving 
          excess memory with large collections.

05/10/2016 Oleh Derevenko
        * dSafeNormalize3 and dSafeNormalize4 functions changed to leave the
          parameter intact instead of replacing it with the X-axis unit in case 
          of fault.

04/12/2016 Oleh Derevenko
        * A function to create a self-threaded threading implementation object
          has been moved back to public headers as there could be a use for it
          while running several worlds in parallel threads.

01/09/2016 Oleh Derevenko
        * Hinge2 joint corected to avoid faulting asserts when the axes get 
          temporarily invalid during assignments (suggested by David Mansolino)

01/03/2016 Oleh Derevenko
        * An invalid memory access fixed in dxSAPSpace::BoxPruning() in case
          if there were NaN values in AABBs to be sorted.

12/25/2015 Oleh Derevenko
        * Unexpected joint mode assignment (instead of comparison) fixed within
          an dUASSERT in dJointSetTransmissionAxis2() of transmission joint

11/28/2015 Oleh Derevenko
        * Convex-Trimesh collider added (libccd+GIMPACT only)(by Piotr Piastucki)
        * dCreateConvex() and dGeomSetConvex() public APIs changed to expect 
          their parameter arrays as const pointers

11/01/2015 Oleh Derevenko
        * OPCODE mesh colliders' input coordinates have been offset to  
          mesh-relative frames to decrease potential computational errors
          (suggested by luckytrashsc2@g***l.com)

08/05/2015 Oleh Derevenko
        * Implemented change to return highest depth contacts subset for GIMPACT 
          in cases if contacts count exceeds requested maximum (as suggested in 
          the issue #36 by Piotr Piastucki)

11/17/2014 Daniel K. O.
        * Added support for using libccd from the system (if found via
          pkg-config)

11/10/2014 Oleh Derevenko
        * Floating point division by zero in capsule-ray collision routine 
          in case if the ray axis was parallel the cylinder and the ray started
          from within it fixed (issue #26)

11/08/2014 Oleh Derevenko
        * Threading support has been extended to complete implementation 
          of QuickStep

10/29/2014 Daniel K. O.
        * Added dJointSetDBallDistance

10/19/2014 Oleh Derevenko
        * Built-in threading implementation compilation fixed for OSX
          (clock_gettime() is missing from the system - reported by Bram)

08/10/2014 Oleh Derevenko
        * Declarations of dWorld[Get/Set]AutoDisableLinearAverageThreshold and
          dWorld[Get/Set]AutoDisableAngularAverageThreshold have been removed 
          from public headers (were orphaned since rev.1052)

07/16/2014 Oleh Derevenko
        * Two fixes by Francesco Cat applied (fixes for mistakes made during
          code style improvements in the past)
		 
02/27/14 Daniel K. O.
        * Added dODE_VERSION macro to public headers (issue #24).

02/11/14 Daniel K. O.
        * Added dJointGetHinge2Angle2 (issue #12).

02/07/14 Daniel K. O.
        * Added dWorldSetData/dWorldGetData (issue #21).

01/31/14 Daniel K. O.
        * Applied patch #185: Stable, implicit gyroscopic forces.

01/27/14 Daniel K. O.
        * Fixed cylinder AABB computation.

01/25/14 Daniel K. O.
        * Removed ALLOCA calls from dHashSpace; it should not depend
          on stack size limits anymore.

12/06/13 Daniel K. O.
        * Applied patch #181: fix some bugs in AMotor joint.
        * Applied patch #186: fix some bugs in PU joint.
        * Applied patch #182: Transmission joint.
        * Applied patch #184: implement rolling friction for contacts.

08/08/13 Oleh Derevenko
        * Joint feedback forces application fixed in QuickStep implementation
          (was broken since revision #1919 in old repository (#1927 in new one))

08/04/13 Oleh Derevenko
        * Bugfix #89 by Luc applied (dJointAddSliderForce() adds a zero force
          when the parent body is NULL) 

05/18/13 Oleh Derevenko
        * OU library has been included in ODE at revision #46 instead of  
          being used as an external link due to difficulties using external 
          references with new protocol used for storage at SF.

03/03/13 Oleh Derevenko
        * Fixed issue with "findex==-1" constraints being intermixed with 
          "findex!=-1" ones during constraints random reordering in QuickStep.

02/03/13 Oleh Derevenko
        * [u]int[8/16/32] renamed to contain "d" prefix so that global namespace
          was not polluted with these names unconditionally. 
          If your project depended on these types other than just for passing 
          parameters to ODE calls, add similar typedefs for yourself in some 
          of your project's global headers.

01/02/13 Oleh Derevenko
        * Applied patch #183 by Joseph Cooper (complementary matrix 
          calculation fix).

12/28/12 Oleh Derevenko
        * A bug with heightfield data assigned to a wrong field in 
          dGeomHeightfieldSetHeightfieldData fixed (bug report #88 by Luc).

12/18/12 Oleh Derevenko
        * Fixed issue with some kinds of joints (Ball, DBall, DHinge, Fixed)
          might overwrite world ERP value with their custom ERP during 
          getInfo2() call and that inappropriate value would then be passed 
          to subsequent joints in solver instead of world ERP.

12/01/12 Oleh Derevenko
        * Fixed issues reported in patches #151 and #22 (collisions with
          SAPSpace and QuadTreeSpace might not work because geometries list
          was misused in them).
        * Applied patch #160 "IsPointInPolygon in convex.cpp returns wrong 
          results" (by Janis Rucis)

11/25/12 Oleh Derevenko
        * Configuration option --disable-threading-intf added 
          (--no-threading-intf for Windows/Premake). This allows disabling
          threading interface support (external implementations may not be 
          assigned) but eliminates dependency on OU and use of atomics in 
          steppers.

11/05/12 Oleh Derevenko
        * Fixed zero comparisons in OPCODE to use relative error instead of
          absolute epsilon value (found by Bill Sellers)

06/08/12 Daniel K. O.
        * Removed the need for defining dSINGLE/dDOUBLE; this is stored now in
          the generated ode/precision.h header.
        * Some code cleanup to get rid of GCC warnings.

05/30/12 Daniel K. O.
        * Made drawstuff draw shadows for lines.
        * Fixed dhinge's last constraint to properly handle rotations.

05/03/12 Daniel K. O.
        * Added two new joints: Double Ball and Double Hinge.

04/22/12 Daniel K. O.
        * Fixed plane2d joint: uninitialized variables (reported by Dimitris
          Papavasiliou)

04/14/12 Oleh Derevenko
        * Assertion checking macros moved into library private headers.

04/13/12 Daniel K. O.
        * Applied patch from bug  #3431829 - better handling of capsule-box with
          deep penetrations.
        * Fixed zero-mu issues: now either mu or mu2 can be set to zero.

03/17/12 Oleh Derevenko
        * Threaded execution support interface added. Optional built-in threading
          implementation added.
          Internal threading implementation is excluded by default and to be used, 
          it must be enabled with configure/premake.
          At present, if threading interface is assigned to a world, island 
          selection and stepping is performed in multiple threads (one thread per 
          island).

03/12/12 Oleh Derevenko
        * PURE_INLINE macro renamed to ODE_PURE_INLINE and definition of 
          dNextAfter()/dCopySign() corrected to avoid creating conflicts with 
          other libraries.

02/03/12 Oleh Derevenko
        * Assertion checking macros moved from common.h to error.h

12/18/11 Oleh Derevenko
        * dIVERIFY macro added (same as dIASSERT in debug mode but evaluates its
          expression in release mode) to be used to assert variable value 
          which is not used further in text while avoiding compiler warning.
        * dICHECK macro added (same as dIASSERT but evaluates its expression and 
          raises assertion fault regardless of compilation mode) to be used to
          generate a fault in cases when error is very unlikely but must be 
          handled and handling is very troublesome (e.g. failure to lock a mutex
          due to lack of resources).

12/07/11 Oleh Derevenko
        * Partially fixed size_t to integer conversion warnings
        * Fixed type signedness and added casts to size_t wherever necessary 
          in Step/QuickStep

11/04/11 Daniel K. O.
        * Applied patch #3429454 - fix compilation on some platforms.

10/28/11 Daniel K. O.
        * Fixed a box-capsule bug: more reasonable normal for deep penetrations
          (contributed by Georg Martius.)

10/27/11 Daniel K. O.
        * Disabled merging of contacts for trimesh-sphere by default.
        * Added new demo: demo_tracks.

10/17/11 Daniel K. O.
        * Added python bindings, contributed by Gideon Klompje.
        * Updated some build scripts.
        * Changed spheres distribution in demo_space_stress.

05/17/11 Oleh Derevenko
        * A typo in step.cpp fixed (assignment operator in a conditional 
          instead of comparison) (reported by Bram Stolk)

01/29/11 Oleh Derevenko
        * Heightfield zone boundaries calculation code fixed to also consider
          whole next cell after the AABB if the AABB ends exactly at the cell
          boundary.

01/23/11 Daniel K. O.
        * Applied patch from Daniel Fiser, add libccd collider for
          box-cylinder.

01/20/11 Daniel K. O.
        * Applied patch from Daniel Fiser, fix infinite loop in libccd caused
          by numerical problems.

01/06/11 Daniel K. O.
        * Applied patch from Daniel Fiser, efficient libccd tests when using
          CONTACTS_UNIMPORTANT.

12/17/10 Daniel K. O.
        * Applied patches from Daniel Fiser for new colliders based on libccd.

11/08/10 Daniel K. O.
        * Applied patches from Daniel Fiser to incorporate libccd for
          Cylinder-Cylinder collision tests.

08/21/10 Oleh Derevenko
        * Fix applied to dxReallocateTemporayWorldProcessContext() to remove typo 
          which caused segmentation fault (by Kyle McKay).
          dTestSolveLCP() fixed to avoid exceeding allocated memory pool 
          (by Kyle McKay).

07/19/10 Oleh Derevenko
        * Patch applied (#3030783) to fix drawstuff dimensions being ignored
          in OSX GLUT port (by Danny Price).

         Daniel K. O.
        * Applied patch #2991622: dGeomGetRelPointPos, dGeomGetPosRelPoint,
          dGeomVectorToWorld, and dGeomVectorFromWorld.

07/16/10 Daniel K. O.
        * Fixed bug #2937076: don't try to build demos if drawstuff is disabled.

05/02/10 Oleh Derevenko
        * Missing extern "C" wrapper has been added to include/ode/export-dif.h
          (reported by Danny Price). The change affects dWorldExportDIF() public 
          function.

05/02/10 Oleh Derevenko
        * Patch applied (#2995450) to generate up to four contacts for box-
          plane collision test (by alexdu) and fix contact depths.

05/02/10 Oleh Derevenko
        * dGeomLowLevelControl function added with ability to change/query OPCODE 
          trimesh-sphere contact merging behavior at runtime.

02/18/10 Daniel K. O.
        * Fixed bug affecting disabled joints and dWorldStep.

01/16/10 Oleh Derevenko
        * Patch applied (#2931174) to make demos work for recent MacOS.
        * Patch applied (#2931177) to fix the demos' framerate on X11.

12/20/09 Oleh Derevenko
        * QuadTreeSpace implementation corrected to avoid object-block relation 
          ambiguity due to numeric errors.

12/04/09 Oleh Derevenko
        * odecpp classes changed to be inheritable and easily expandable

11/29/09 Oleh Derevenko
        * Improvement for trimesh-plane collision (also used in trimesh-heightfield)
          to exclude mesh vertices that have already generated contacts from further
          examination and contact generation in other triangles (suggested by LR).

10/25/09 Oleh Derevenko
        * Macros changed to static inline functions in odemath.h and related files.
          Some code duplication has been eliminated across the files.

        * Fixed handling of --disable-asserts and --enable-double-precision 
          (absence of --enable-double-precision) in configure script. The script
          was not appending compiler defines correctly.

        * dWorldStep implementation changed to remove allocation on stack. 
          dUSE_MALLOC_FOR_ALLOCA define has been removed as well as corresponding
          configuration parameter. Also dMemoryFlag public variable has been removed.
          (look for presence of ODE_EXT_malloc_not_alloca configuration string if
          your application is dependent on that variable).

09/05/09 Oleh Derevenko
        * dWorldStepFast1 API removed along with dWorld[Get/Set]AutoEnableDepthSF1

08/29/09 Oleh Derevenko
        * Fixed uninitialized floating point array used in computations.

08/12/09 Oleh Derevenko
        * A typo fixed in dGeomCopyOffsetRotation() (final_posr was used instead 
          of offset_posr). Reported by Tilmann.

08/11/09 Daniel K. O.
        * Made sure neither dSINGLE or dDOUBLE is defined by default; the user
          should always explicitly specify the precision.

06/27/09 Oleh Derevenko
        * New functions have been added:
           - dWorldUseSharedWorkingMemory
           - dWorldCleanupWorkingMemory
           - dWorldSetStepMemoryReservationPolicy
           - dWorldSetStepMemoryManager
		
06/25/09 Remi Ricard (papaDoc)
        * Add limit to the to the second axis of the universal joint
         for the pu joint.

06/14/09 Oleh Derevenko
		* dWorldQuickStep re-implemented to avoid memory allocation on stack.
		  Also several optimizations have been made to decrease memory 
		  requirements and optimize algorithm implementation of dWorldQuickStep.
		  dWorldStep still remains with old memory allocation however new APIs
		  mentioned below are fully functional for it.
		  Both dWorldStep and dWorldQuickStep have been changed to return boolean
		  success status.

		* dInitODE2() changed to automatically call 
		  AllocateODEDataForThread(dAllocateFlagBasicData) after library 
		  initialization as this is a required initialization minimum that
		  must always be performed anyway.

06/05/09 Daniel K. O.
         * Removed aliasing issues from OPCODE/Ice, plus some other warnings.
           Now it builds on gcc 4.3.2 with '-Wall -Werror -O3".

05/30/09 Oleh Derevenko
         * A minor memory usage optimization for QuickStep.

05/24/09 Daniel K. O.
         * Made the new trimesh collider the default.
         * Added a "-texturepath" option to drawstuff.

05/18/09 Oleh Derevenko
        * Heightfield rotation fixed to avoid NaNs while rotating infinite
          MIN/MAX heights.

05/03/09 Oleh Derevenko
        * Incorrect parameter order fixed on contact merging in Sphere-Trimesh
          collisions. The bug resulted in merged contact remaining with normal
          of first contact found. Thanks to Dimitris Papavasiliou for reporting.

04/23/09 Daniel K. O.
        * Fixed bug #2685170: use the C99 __func__ instead of __FUNCTION__ when
          a C99 implementation is available.

04/07/09 Remi Ricard (papaDoc)
        * Remove unused code in demo_joints.cpp, reported by Tilmann.

04/07/09 Remi Ricard (papaDoc)
        * Fix bug in collision categories in demo_jointPU, reported by Tilmann

03/14/09 Oleh Derevenko
        * A possibility to initialize/close ODE multiple times recursively has 
          been added.
          Also, now a call to dSpaceSetManualCleanup() is required for each 
          space right after creation if ODE has been initialized in thread data
          manual cleanup mode.
           
03/07/09 Oleh Derevenko
        * Thread local data has been cleaned up from OPCODE and OdeTls as it is
          not used (OPC_SweepAndPrune.* and OPC_BoxPruning.* have been removed
          - rebuilding project files is necessary).

02/07/09 Daniel K. O.
        * New house of cards demo, which stresses the friction handling stability.

01/29/09 Remi Ricard (papaDoc)
        * Fix bug: Fix problem when attaching no body to a joint. Before calling
          setRelativeValues a check is made for bodies.
        * Add unittest

01/28/09 Daniel K. O.
        * Applied patch #2538046: Heightfield AABB bounds patch.

01/23/09 Remi Ricard (papaDoc)
         * Add new function dJointSetUniversalAxis1Offset and dJointSetUniversalAxis2Offset
         * Add unittest for those funcitons.

01/23/09 Remi Ricard (papaDoc)
         * Fix problem with dJointGetUniversalAngle2 when the joint is attached to
           only a body 2. The sign was inverted.
         * Add unit test to verify for this problem

01/21/09 Remi Ricard (papaDoc)
         * Fix bug reported by Tilman: dxJointPU::getInfo1 was setting twice the
           limit of limot1 to zero and not limot2

01/17/09 Daniel K. O.
        * Fixed a bug in dSpaceCollide2: if both geoms are not in spaces they would
          not have valid AABBs.

12/20/08 Daniel K. O.
        * New functions: dJointEnable, dJointDisable, dJointIsEnabled
          (patch #2454764).

12/19/08 Daniel K. O.
        * Removed inline asm statements that break builds on 64-bit VC++.

12/09/08 Daniel K. O.
        * Applied patch #2381592, which adds support for Kinematic Bodies.

12/06/08 Oleh Derevenko

       * Applied a patch by Martijn Buijs to make GIMPACT trimesh-ray collisions to
         be consistent with those in OPCODE.
       * Swapped geometries returned in contacts for OPCODE Trimesh-Plane collisions
         as they were returned in unnatural order being different from that in GIMPACT
       * Applied a patch by Martijn Buijs to make side1, side2 fields of contact 
         structure be always initialized, either with -1 for non-trmesh geometries
         or with triangle index for trimeshes. These fields were only assigned for
         trimesh-trimesh collisions before.
       * dGeomTriMeshSetTriMergeCallback/dGeomTriMeshGetTriMergeCallback API added
         to set/get user defined callback procedure for trimeshes that would be 
         invoked when contacts are merged to let user code accumulate attributes of
         original contact triangles and generate a fake index by which it would 
         later be able to determine those attributes. If the callback is not 
         assigned (the default) -1 is generated as triangle index for merged 
         contacts (there was an index of first of merged triangles before!!!).
         The callback is currently used within OPCODE trimesh-sphere and OPCODE
         new trimesh-trimesh collisions.

11/20/08 Remi Ricard (papaDoc)
       * Fix problem with dJointGetPUPosition and
         dJointGetPUPositionRate when the joint is attached to only
         a body 2. The sign was inverted.
       * Fix bug: When a pu joint had only one body attached to position 2,
         dJointAttach(jId, 0, bId). The body was not push in the right direction to
         move back between the limits.
       * Add unit test to check the above problem
       * Add the function void dJointSetPUAnchorOffset
       * Make the function void dJointSetPUAnchorDelta deprecated

11/19/08 Remi Ricard (papaDoc)
       * Fix bug: When a pr joint had only one body attached to position 2,
         dJointAttach(jId, 0, bId). The body was not push in the right direction to
         move back between the limits.
       * Add unit test to check the above problem

11/19/08 Remi Ricard (papaDoc)
        * Fix problem with dJointGetPRPosition and
          dJointGetPRPositionRate when the joint is attached to only
          a body 2. The sign was inverted.
        * Add unit test to check the above problem
        * Increase the tolerance to remove failure in unit test
        * Remove compilation warning in unit test with the use of REAL()

11/18/08 Remi Ricard (papaDoc)
       * Fix bug: When a piston joint had only one body attached to position 2,
         dJointAttach(jId, 0, bId). The body was not push in the right direction to
         move back between the limits.
       * Add more functionality to demo_piston.cpp
       * Run astyle on modified files.

11/18/08 Remi Ricard (papaDoc)
        * Fix bug: When a slider joint had only one body attached to position 2,
         dJointAttach(jId, 0, bId). The body was not push in the right direction to
         move back between the limits.

10/29/08 Oleh Derevenko

        * Premake scripts changed to only include chosen collision library
          sources in project on Windows. --all-collis-libs premake option 
          added to allow inclusion of all collision library sources into the 
          project

10/15/08 Remi Ricard (papaDoc)
        * Applying patch #2158425 64-bit GIMPACT provided by Mark
          William. This patch enable GIMPACT to works on 64-bit machine.

10/15/08 Remi Ricard (papaDoc)
        * Add function dJointGetPRAngle and dJointGetPRAngleRate

10/15/08 Remi Ricard (papaDoc)
        * Enable the motor on the rotoide part of the PR joint

10/15/08 Remi Ricard (papaDoc)
        * Add unit test to check if using directly a joint
          or using after setting with default values is the same.
        * Add function setRelativeValues called in dJointAttach for
          all joints.

10/10/08 Remi Ricard (papaDoc)
        * Fix bug in dJointGetPUAxis2. The axis was not multiplied with the
          the rotation matrix of the good body.
        * Fix bug if there is only one body on the PU joint the axis returned
          was not the right one.
        * Add unit test to verify previous bug.

10/03/08 Rodrigo Hernandez (Kwizatz)
	* Added Blender script to create ODE convex geoms under tools.

10/01/08 Rodrigo Hernandez (Kwizatz)
	* Convex-Convex collision detection code is finally stable.

08/31/08 Daniel K. O.
        * Applied patch 2080674: Improved dBodySetRotation; now exact rotation
          matrices are preserved until the next simulation step.

08/07/08 Daniel K. O.
        * Fixed strict aliasing issue that was breaking the new trimesh collider.

07/24/08 Daniel K. O.
        * New functions: dBodyGetGyroscopicMode and dBodySetGyroscopicMode
          (patch #2019242).

07/15/08  Remi Ricard (papaDoc)
        * Add a new define ODE_API_DEPRECATED to mark function as deprecated
          when necessary.

07/14/08 Remi Ricard (papaDoc)
        * Finish adding patch 1336066: Joint feedback in quickstep by jsinecky
        * demo_boxstack.cpp can now print joint feedback

07/11/08 Daniel K. O.
        * Bumped version for 0.10.1
        * Added proper usage of libtool's version info.

07/10/08 Remi Ricard (papaDoc)
        * Add new function dJointSetPistonAnchorOffset
        * Add unittest for the piston joint
        * Fix problem with dJointGetPistonPosition and 
          dJointGetPistonPositionRate when the joint is attached to only
          a body 2. The sign was inverted.

07/09/08 Remi Ricard (papaDoc)
        * Optimize function Multiply1_12q1 in quickstep
          Patch proposed by Riemer v.d. Zee and modified by Patrick Baggett

07/08/08 Remi Ricard (papaDoc)
        * Update the slider joint to have the same behavior as the other joint
          when there is only a body2 attached to it.
        * Update documentation for the slider joint.
        * Remove warning by using REAL()
        * Add new unittest for dJointGetSliderPositionRate

07/08/08 Remi Ricard (papaDoc)
        * Update unittest for the slider.
        * Rename the new function dJointSetHingeAxisDelta to 
          dJointSetHingeAxisOffset. This remove will remove confusion with 
          the old function dJointSetHingeAnchorDelta
        * Update documentation for the Hinge unittest
        * Remove warning by using REAL()

07/07/08 Daniel K. O.
        * Max Correcting Vel doesn't affect bounciness, as before.

07/03/08 Remi Ricard (papaDoc)
        * Add new function dJointSetHingeAxisDelta
        * Add unittest for this new function

06/17/08 Remi Ricard (papaDoc)

        *  Move the computation of the Relative Rotation for the slider joint
           into a function.
        * Add unittest for to check qrel 

06/17/08 Remi Ricard (papaDoc)

       * Remove unused variables. 
       * Remove a conversion warning between unsigned int and int
        
06/17/08 Remi Ricard (papaDoc)

        * Move the function hingeComputeRelativeRotation as a member of 
          the hinge structure/class.

06/17/08 Remi Ricard (papaDoc)

        *  Move the computation of the Relative Rotation for the fixed joint
           into a function.

06/16/08 Remi Ricard (papaDoc)

        * Add testunit for the dxJointFixed

06/04/08 Daniel K. O.

        * Moved joints to ode/src/joints, converted them to true virtual
          methods.

06/02/08 Daniel K. O.

        * Added an Auto template to step.cpp to handle memory deallocation.

05/09/08 Daniel K. O.

        * Applied patch #1335202: Contact Joint Motion (with some corrections),
          and added demo_motion.

05/01/08 Oleh Derevenko

        * Memory leak in GIMPACT fixed (reported by Derek)

04/28/08 Oleh Derevenko

        * Added possibility to collide a space of lower sublevel as a geometry
          against another space of a higher level with dSpaceCollide2.
          dSpaceSetSublevel/dSpaceGetSublevel are used for sublevel assignment/
          retrieval.

04/27/08 Oleh Derevenko

        * Fixed incorrect memory copying which could lead to memory corruption
          in GIMPACT (luckily, in unused code)
        * Fixed possible memory read beyond the end of allocated buffer along
          with unnecessary extra memory copying in GIMPACT.
        * Fixed buffer reserve being incorrectly reset to zero for bitsets 
          what resulted in unnecessary memory reallocations in GIMPACT.
        * Implemented support for ability to run collision detection from
          multiple threads for separate spaces.
           
04/14/08 Oleh Derevenko

        * Fixed possible memory corruption in new trimesh-trimesh collider
          in case if two degenerated triangles are checked against each other.

04/12/08 Oleh Derevenko

        * Fixed sporadic assertion failure on vector normalization caused
          by small triangles degenerating into segments during space 
          transformations.

03/28/08 Remi

        * Fix a bug in dJointXXXGetInfo. The value in limot.limit was not
          always updated. (Ex: If hi and lo limit were changed). 

03/27/08 Remi

        * Added a new Joint: Prismatic Universal (patch #1828454).

         Daniel K. O.

        * Fixed bug #1841309: collide2() method buggy.

03/18/08 Rodrigo

        * New function: dVector4Copy.

03/14/08 david

        * Added stub calls for trimesh functions.
        * Applied patch #1914232: dGetConfiguration.
        * Applied patch #1655333: Optimize the function dNormalize3.
        * New function: dSetColliderOverride.
        * New function: dCheckConfiguration.
        
         Daniel K. O.

        * Disabled building shared library by default with autotools.

03/13/08 david

        * New function: dJointGetNumBodies (patch #1901550).
        * New function: dSpaceGetClass (patch #1901637).
        * Applied patch #1901649: Add missing function in the export

03/12/08 Rodrigo

        * Fixed drawstuff build issues on OSX.

01/12/08 Daniel K. O.

	* Fixed a typedef bug in configure.in.
	* Added dCylinder to the C++ wrappers.
	* Applied patch 1851394: support for GIMPACT with double precision,
	  dCollide fix.
	* Moved bunny geometry to bunny_geom.h.

12/11/07 Daniel K. O.

	* Added damping and MaxAngularVel() functions.
	* Const-correctness: added const qualifier to some dWorldGet and dBodyGet
	  functions.
	* Updated the odecpp.h header.

12/07/07 Daniel K. O.

	* Removed most of the compiler warnings from Drawstuff, ODE and
	  OPCODE
	* Upgraded automake requirement to 1.10, and change some Makefile.am

12/06/07 Rodrigo

	* Modified autotools to use libtool for
	  library generation and administration
	* Removed release and debug flags for configure.in
	  CPPFLAGS, CFLAGS, CXXFLAGS should be set by the
	  user to their liking, respecting autotools policies.

11/30/07 Daniel K. O.
	* Applied patch 1813079 (moved callback)
	* Replaced moveAndRotateBody by dxStepBody in stepfast.cpp

11/10/07 david

	* Added 'Sweep and Prune' collision space.
	* New Piston joint type with demo, by Remi Ricard
	* Added build option to use 16-bit indices for OPCODE trimesh

11/03/06 david

	* Integrated Christoph Beyer's average based sampling system for body
	  disabling.

10/26/06 Francisco Leon

	* Totally refactored trimesh collision system.
	  Using GIMPACT instead of OPCODE. Now works correctly, and faster.
	  Visit http://gimpact.sourceforge.net.
	  
	* Finally, test_moving_trimesh.exe works nicely.   
	  
	* Fixed autodisable system. Now is possible to set bigger sleeping 
	  threshold values and objects won't be sleeping on the air. They will
	  rest on the floor properly.
	  	  
	* dInitODE function added.
	
	* Is Obligatory to call dInitODE() at the beginning for initialize ODE,
	  and calling dCloseODE() when the program ends.

09/20/06 bram

	* Fixed two bugs in cyl/plane collision test.

09/13/06 Remi

	* New Rotoide - Prismatic joint type
	* dJointGetUniversalAngles for efficient angle retrieval.

08/09/06 david

	* Integrated plane2d joint type which constrains bodies to z == 0.

07/06/06 david

	* Added heightfield primitive collision code. Simple test available in
	  ode/test/test_heightfield

04/03/06 rodrigo

	* Added Convex primitive collision code,
	  currently only convex-sphere and convex-plane work

04/01/06 bram

	* Added program to test trimesh vs sphere: ode/test/test_basket

03/20/06 jason379

	* Added new autogenerated Visual Studio projects, with Premake scripts

03/17/06 bram

	* Added plane/cyl intersection test
	* Renamed CCylinder to Capsule
	
02/04/06 gcarlton

	* Added support for geom offsets.

10/26/05 rodrigo

	* Removed LIBTOOL from autotools since it was not really required.
	* Added a target to build ODE as a shared library, this shared
	  library gets build alongside the static one, no flags required.

10/24/05 tfautre

	(Backported patches from STABLE branch, applied by Adam)
	
	* dRandInt changed for a non-double all-int version.
	* mics minor fixes and improvements.

04/05/05 tfautre

	* Fixed segmentation fault with OPCODE on 64 bits systems.

03/31/05 tfautre

	* Fixed timer.cpp compiler error on x86-64 using GCC.

03/29/05 colin

	* Added trimesh preprocessing to mark unneeded edges and verts.  Also
	  added support for preprocessed info to the ccylinder-trimesh
	  collider.

12/07/04 adam

        * Important AMotors bugfix

09/22/04 jeff

	* Assorted small bugfixes and tweaks for
	  trimesh_{box,ccylinder,trimesh} collisions

09/21/04 jeff

	* added functions to joint.cpp to allow joint attachment to moving
	  geoms.

	* added malloc-based memory allocation in step.cpp & lcp.cpp (turned
	  on with a #define switch in common.h)
	
05/29/04 russ

	* added joint feedback to the QuickStep solver

05/18/04 russ

	* added warm starting to the QuickStep solver

05/18/04 russ

	* added the QuickStep solver
	
	* added contact parameter functions.

05/05/04 adam

        * use dRandInt instead of rand() in stepfast.

04/21/04 russ

	* added auto-disable support from Aras Pranckevicius (with
	  modifications by russ). this useful feature can speed up
	  simulation significantly in some cases.
	
	* various internal tidyups.

04/20/04 russ

	* changed the meaning of the 'index' argument to dJointGetBody():
	  it was the only remaining API function that does not respect
	  dJOINT_REVERSE (spotted by Matthew D. Hancher).
	
	* updated the C++ headers: fixed two minor bugs and added
	  support for dQuadTreeSpace, dRay, and the dGeom::getSpace() method
	  (from Matthew D. Hancher).

04/18/04 russ

	* changed the way that the dInfinity constant is implemented: now it
	  is #defined to be one of: FLT_MAX, DBL_MAX, HUGE_VAL, HUGE_VALF, or
	  a large numeric constant. previously it was a variable that was
	  exported from the library. this simplifies the configuration and
	  build process quite a bit, especially in the case of DLLs.
	
	* removed the old, deprecated collision system (geom.cpp,space.cpp,
	  geom.h,space.h,odecpp_old_collision.h). the ODE_OLD_COLLISION
	  configuration setting no longer has any meaning.
	
	* removed support for dGeomGroups, which have been deprecated for
	  a while and are equivalent to 'spaces' anyway.

04/13/04 russ

	* bug fix in dMassSetCappedCylinder(), from Matthew D. Hancher.

04/08/04 russ

	* added trimesh-CCylinder capability, from Vadim Macagon
	  .

04/04/04 adam

        * yet another rewrite of triangle-box collision code, this
        time based on code donated by Croteam, ported by asko@jetti.org
        and tweaked by Erwin.

04/04/04 adam

        * merged trimesh-trimesh collision code by
        Jeffrey Smith .

        * changed it to not break the trimesh interface, fix
        some GCC compilation problems, bring it up to date with
        ODE changes from 2003-11-15 -> 2004-04-04.

        * add ability to drop meshes on meshes in test_moving_trimesh,
        not as good as it could be but it's illustrative.

01/16/04 adam

	* implement a bunch of ultra-simple TriMesh functions that were
	in the headers but not in the code -- patch by
	Vadim Macagon 

	* disable temporal coherence on trimeshes by default, since
	it has scaleability issues that don't make it a general clear win.

12/01/03 adam

	* implement dxHashSpace::collide2(), not particularly efficiently.

11/14/03 adam

	* applied several Trimesh fixes and improvements from
	Aras Pranckevicius 

10/22/03 adam

	* apply Nguyen Binh's work for removing many dSetZero() calls
	and some other extraneous initializations.

07/29/03 martin

	* added dJointAdd*Torque/Force().

07/10/03 russ

	* added the StepFast code, by David Whittaker.

07/02/03 martin

	* added dMassSet*Total().

07/01/03 martin

	* added joint limits and motors to universal joints.

	* reversed the polarity of the dJOINT_REVERSE flag.

06/30/03 russ

	* added the TriMesh geom class and the quad tree space to the ODE
	  core. both of these were developed by Erwin de Vries. added OPCODE
	  to the ODE distribution, this is required by TriMesh.

06/23/03 martin

	* added dGeomSetQuaternion() and dGeomGetQuaternion()
	
	* added dJointGet*Anchor2()

05/07/03 russ

	* added dGeomGetSpace().

02/05/03 russ

	* added dMassSetCylinder().

12/07/02 russ

	* added dAreConnectedExcluding().

11/30/02 russ

	* added the ray geom class.

	* added the dGeomXXXPointDepth() functions.

	* added a collision test infrastructure, and some more tests.

11/24/02 russ

	* added support for multiple box-box contacts.

11/10/02 russ

	* added new collision system. select between the old/new system by
	  setting the ODE_OLD_COLLISION variable in config/user-settings.

10/28/02 russ

	* fixed two problems in the LCP code to improve the reliability of
	  the dContactApprox1 contact mode.

	* added a FAQ question about rolling bodies getting stuck when they
	  hit multiple geoms.

09/08/02 russ

	* added dClosestLineSegmentPoints().
	* implemented dCollideCB().

08/28/02 russ

	* added dJointSetFeedback() and dJointGetFeedback().

08/05/02 russ

	* added dGeomTransformSetInfo() and dGeomTransformGetInfo().

07/13/02 russ

	* added dBodySetForce(), dBodySetTorque(), dWorldImpulseToForce(),
	  dBodyGetPosRelPoint(), dBodyGetPosRelPoint(), dBodyVectorToWorld(),
	  dBodyVectorFromWorld().

	* added dBodyGetPointVel() (thanks to Colin Reed).

	* added a new C++ interface (from Martin C. Martin, with modifications
	  by russ). the old C++ interface is now in odecpp_old.h.

06/25/02 russ

	* added an additional BSD-style licensing option for ODE.

06/23/02 russ

	* added dCloseODE(), contributed by Nate Waddoups and David McClurg.

05/16/02 russ

	* added dSpaceQuery(), contributed by Nate Waddoups.

04/07/02 russ

	* added a section to the documentation for universal joints.
	  this includes a picture of the joint.

04/05/02 russ

	* added a universal joint class (generously contributed by
	  Martin C. Martin). it doesn't (yet) have a motor or joint limits,
	  but it does come with tests.

03/11/02 russ

	* makefile changes to accomodate OSs with command line length
	  limitations (thanks to Norman Lin).

01/06/02 russ

	* added the dBodySetGravityMode() and dBodyGetGravityMode()
	  functions, which change the dxBodyNoGravity body flag.

	* added support for building a DLL with MSVC - there is now a
	  msvc-dll target. thanks to Norman Lin for doing this.

12/28/01 russ

	* added the dParamCFM joint parameter.

12/24/01 russ

	* reworked the build system to make it more cross-platform.
	  there is now a single top-level makefile and a configurator.c
	  program. see the INSTALL file for details.

12/04/01 russ

	* the "angular motor" joint has been completed, and a new section
	  has been added to the documentation.

11/26/01 russ

	* added a new joint type: "angular motor". using this joint is a good
	  way to get ball-joint motors and limits. this is work in progress -
	  it has not been fully implemented or tested yet.

11/22/01 russ

	* replaced the mmap()-based joint group stack (stack.cpp) with a
	  malloc()-based arena stack (obstack.cpp). this will be more
	  portable and should not impact performance.

11/12/01 russ

	* changed the meaning of the 'flags' parameter to dCollide() and
	  related functions: now the size of the contact buffer is kept in
	  the lower 16 bits. this change will be backward compatible.

	* added dBodyGetFiniteRotationMode() and dBodyGetFiniteRotationAxis().

	* added dBodyAddForceAtRelPos() function.

11/11/01 russ

	* added the ability to manually enable and disable bodies.
	  see dBodyEnable(), dBodyDisable(), dBodyIsEnabled().

	* fixed a potential bug: when a world is destroyed that contains
	  joints in joint groups, those joints are marked as "deactivated" in
	  the joint group, so when the joint group is destroyed they can be
	  ignored.

	* the test_boxstack demo has new options to enable and disable bodies.

	* new configuration parameter in config.h: dEFFICIENT_SIZE.

11/11/01 russ

	* started the change log for ODE. changes older than today were added
	  to this file by inspecting the CVS logs.

11/05/01 russ

	* added REAL() constructions for floating point numbers, to prevent
	  many warnings when compiling under VC++.

11/03/01 russ

	* added geometry transform class, documented composite objects.

	* added collision rule: no contacts if both geoms on the same body.
	  this is not the best rule, may have to remove this in the future.

	* new dMassAdd() function.

	* capped cylinder to capped cylinder collision function.

10/31/01 russ

	* increase CFM in some demos to make them more robust.

10/29/01 russ

	* added new accessor functions.

10/19/01 russ

	* added the dJOINT_TWOBODIES flag to the joint, that says it can not
	  be attached to just one body.

10/12/01 russ

	* fixed a collision bug in dCollide() that was causing memory
	  corruption when multiple contacts were being returned.

10/11/01 russ

	* joints can now return m=0 to be "inactive". added a "null" joint
	  to test this.

10/09/01 russ

	* in the LCP solver, try to fail gracefully when s <= 0.

	* dAABBTestFn() API change.

10/08/01 russ

	* fixed a contact swapping bug in dCollide().

10/07/01 russ

	* added capped cylinder geometry object.

09/30/01 russ

	* the test_buggy demo now uses geometry groups.

	* added a dAABBTestFn field in the geometry classes.

09/29/01 russ

	* added geometry groups.

09/20/01 russ

	* added finite rotation stuff.
ode-0.16/config.guess0000755000175200017520000012475313403272662011475 00000000000000#! /bin/sh
# Attempt to guess a canonical system name.
#   Copyright 1992-2015 Free Software Foundation, Inc.

timestamp='2015-08-20'

# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see .
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that
# program.  This Exception is an additional permission under section 7
# of the GNU General Public License, version 3 ("GPLv3").
#
# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
#
# You can get the latest version of this script from:
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
#
# Please send patches to .


me=`echo "$0" | sed -e 's,.*/,,'`

usage="\
Usage: $0 [OPTION]

Output the configuration name of the system \`$me' is run on.

Operation modes:
  -h, --help         print this help, then exit
  -t, --time-stamp   print date of last modification, then exit
  -v, --version      print version number, then exit

Report bugs and patches to ."

version="\
GNU config.guess ($timestamp)

Originally written by Per Bothner.
Copyright 1992-2015 Free Software Foundation, Inc.

This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."

help="
Try \`$me --help' for more information."

# Parse command line
while test $# -gt 0 ; do
  case $1 in
    --time-stamp | --time* | -t )
       echo "$timestamp" ; exit ;;
    --version | -v )
       echo "$version" ; exit ;;
    --help | --h* | -h )
       echo "$usage"; exit ;;
    -- )     # Stop option processing
       shift; break ;;
    - )	# Use stdin as input.
       break ;;
    -* )
       echo "$me: invalid option $1$help" >&2
       exit 1 ;;
    * )
       break ;;
  esac
done

if test $# != 0; then
  echo "$me: too many arguments$help" >&2
  exit 1
fi

trap 'exit 1' 1 2 15

# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
# compiler to aid in system detection is discouraged as it requires
# temporary files to be created and, as you can see below, it is a
# headache to deal with in a portable fashion.

# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
# use `HOST_CC' if defined, but it is deprecated.

# Portable tmp directory creation inspired by the Autoconf team.

set_cc_for_build='
trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
: ${TMPDIR=/tmp} ;
 { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
 { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
 { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
 { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
dummy=$tmp/dummy ;
tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
case $CC_FOR_BUILD,$HOST_CC,$CC in
 ,,)    echo "int x;" > $dummy.c ;
	for c in cc gcc c89 c99 ; do
	  if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
	     CC_FOR_BUILD="$c"; break ;
	  fi ;
	done ;
	if test x"$CC_FOR_BUILD" = x ; then
	  CC_FOR_BUILD=no_compiler_found ;
	fi
	;;
 ,,*)   CC_FOR_BUILD=$CC ;;
 ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
esac ; set_cc_for_build= ;'

# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
# (ghazi@noc.rutgers.edu 1994-08-24)
if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
	PATH=$PATH:/.attbin ; export PATH
fi

UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown

case "${UNAME_SYSTEM}" in
Linux|GNU|GNU/*)
	# If the system lacks a compiler, then just pick glibc.
	# We could probably try harder.
	LIBC=gnu

	eval $set_cc_for_build
	cat <<-EOF > $dummy.c
	#include 
	#if defined(__UCLIBC__)
	LIBC=uclibc
	#elif defined(__dietlibc__)
	LIBC=dietlibc
	#else
	LIBC=gnu
	#endif
	EOF
	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
	;;
esac

# Note: order is significant - the case branches are not exclusive.

case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
    *:NetBSD:*:*)
	# NetBSD (nbsd) targets should (where applicable) match one or
	# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
	# switched to ELF, *-*-netbsd* would select the old
	# object file format.  This provides both forward
	# compatibility and a consistent mechanism for selecting the
	# object file format.
	#
	# Note: NetBSD doesn't particularly care about the vendor
	# portion of the name.  We always set it to "unknown".
	sysctl="sysctl -n hw.machine_arch"
	UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
	    /sbin/$sysctl 2>/dev/null || \
	    /usr/sbin/$sysctl 2>/dev/null || \
	    echo unknown)`
	case "${UNAME_MACHINE_ARCH}" in
	    armeb) machine=armeb-unknown ;;
	    arm*) machine=arm-unknown ;;
	    sh3el) machine=shl-unknown ;;
	    sh3eb) machine=sh-unknown ;;
	    sh5el) machine=sh5le-unknown ;;
	    earmv*)
		arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
		endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'`
		machine=${arch}${endian}-unknown
		;;
	    *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
	esac
	# The Operating System including object format, if it has switched
	# to ELF recently, or will in the future.
	case "${UNAME_MACHINE_ARCH}" in
	    arm*|earm*|i386|m68k|ns32k|sh3*|sparc|vax)
		eval $set_cc_for_build
		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
			| grep -q __ELF__
		then
		    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
		    # Return netbsd for either.  FIX?
		    os=netbsd
		else
		    os=netbsdelf
		fi
		;;
	    *)
		os=netbsd
		;;
	esac
	# Determine ABI tags.
	case "${UNAME_MACHINE_ARCH}" in
	    earm*)
		expr='s/^earmv[0-9]/-eabi/;s/eb$//'
		abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"`
		;;
	esac
	# The OS release
	# Debian GNU/NetBSD machines have a different userland, and
	# thus, need a distinct triplet. However, they do not need
	# kernel version information, so it can be replaced with a
	# suitable tag, in the style of linux-gnu.
	case "${UNAME_VERSION}" in
	    Debian*)
		release='-gnu'
		;;
	    *)
		release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2`
		;;
	esac
	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
	# contains redundant information, the shorter form:
	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
	echo "${machine}-${os}${release}${abi}"
	exit ;;
    *:Bitrig:*:*)
	UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
	echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
	exit ;;
    *:OpenBSD:*:*)
	UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
	echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
	exit ;;
    *:ekkoBSD:*:*)
	echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
	exit ;;
    *:SolidBSD:*:*)
	echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
	exit ;;
    macppc:MirBSD:*:*)
	echo powerpc-unknown-mirbsd${UNAME_RELEASE}
	exit ;;
    *:MirBSD:*:*)
	echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
	exit ;;
    *:Sortix:*:*)
	echo ${UNAME_MACHINE}-unknown-sortix
	exit ;;
    alpha:OSF1:*:*)
	case $UNAME_RELEASE in
	*4.0)
		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
		;;
	*5.*)
		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
		;;
	esac
	# According to Compaq, /usr/sbin/psrinfo has been available on
	# OSF/1 and Tru64 systems produced since 1995.  I hope that
	# covers most systems running today.  This code pipes the CPU
	# types through head -n 1, so we only detect the type of CPU 0.
	ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
	case "$ALPHA_CPU_TYPE" in
	    "EV4 (21064)")
		UNAME_MACHINE="alpha" ;;
	    "EV4.5 (21064)")
		UNAME_MACHINE="alpha" ;;
	    "LCA4 (21066/21068)")
		UNAME_MACHINE="alpha" ;;
	    "EV5 (21164)")
		UNAME_MACHINE="alphaev5" ;;
	    "EV5.6 (21164A)")
		UNAME_MACHINE="alphaev56" ;;
	    "EV5.6 (21164PC)")
		UNAME_MACHINE="alphapca56" ;;
	    "EV5.7 (21164PC)")
		UNAME_MACHINE="alphapca57" ;;
	    "EV6 (21264)")
		UNAME_MACHINE="alphaev6" ;;
	    "EV6.7 (21264A)")
		UNAME_MACHINE="alphaev67" ;;
	    "EV6.8CB (21264C)")
		UNAME_MACHINE="alphaev68" ;;
	    "EV6.8AL (21264B)")
		UNAME_MACHINE="alphaev68" ;;
	    "EV6.8CX (21264D)")
		UNAME_MACHINE="alphaev68" ;;
	    "EV6.9A (21264/EV69A)")
		UNAME_MACHINE="alphaev69" ;;
	    "EV7 (21364)")
		UNAME_MACHINE="alphaev7" ;;
	    "EV7.9 (21364A)")
		UNAME_MACHINE="alphaev79" ;;
	esac
	# A Pn.n version is a patched version.
	# A Vn.n version is a released version.
	# A Tn.n version is a released field test version.
	# A Xn.n version is an unreleased experimental baselevel.
	# 1.2 uses "1.2" for uname -r.
	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
	# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
	exitcode=$?
	trap '' 0
	exit $exitcode ;;
    Alpha\ *:Windows_NT*:*)
	# How do we know it's Interix rather than the generic POSIX subsystem?
	# Should we change UNAME_MACHINE based on the output of uname instead
	# of the specific Alpha model?
	echo alpha-pc-interix
	exit ;;
    21064:Windows_NT:50:3)
	echo alpha-dec-winnt3.5
	exit ;;
    Amiga*:UNIX_System_V:4.0:*)
	echo m68k-unknown-sysv4
	exit ;;
    *:[Aa]miga[Oo][Ss]:*:*)
	echo ${UNAME_MACHINE}-unknown-amigaos
	exit ;;
    *:[Mm]orph[Oo][Ss]:*:*)
	echo ${UNAME_MACHINE}-unknown-morphos
	exit ;;
    *:OS/390:*:*)
	echo i370-ibm-openedition
	exit ;;
    *:z/VM:*:*)
	echo s390-ibm-zvmoe
	exit ;;
    *:OS400:*:*)
	echo powerpc-ibm-os400
	exit ;;
    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
	echo arm-acorn-riscix${UNAME_RELEASE}
	exit ;;
    arm*:riscos:*:*|arm*:RISCOS:*:*)
	echo arm-unknown-riscos
	exit ;;
    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
	echo hppa1.1-hitachi-hiuxmpp
	exit ;;
    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
	# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
	if test "`(/bin/universe) 2>/dev/null`" = att ; then
		echo pyramid-pyramid-sysv3
	else
		echo pyramid-pyramid-bsd
	fi
	exit ;;
    NILE*:*:*:dcosx)
	echo pyramid-pyramid-svr4
	exit ;;
    DRS?6000:unix:4.0:6*)
	echo sparc-icl-nx6
	exit ;;
    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
	case `/usr/bin/uname -p` in
	    sparc) echo sparc-icl-nx7; exit ;;
	esac ;;
    s390x:SunOS:*:*)
	echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
	exit ;;
    sun4H:SunOS:5.*:*)
	echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
	exit ;;
    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
	exit ;;
    i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
	echo i386-pc-auroraux${UNAME_RELEASE}
	exit ;;
    i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
	eval $set_cc_for_build
	SUN_ARCH="i386"
	# If there is a compiler, see if it is configured for 64-bit objects.
	# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
	# This test works for both compilers.
	if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
	    if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
		(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
		grep IS_64BIT_ARCH >/dev/null
	    then
		SUN_ARCH="x86_64"
	    fi
	fi
	echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
	exit ;;
    sun4*:SunOS:6*:*)
	# According to config.sub, this is the proper way to canonicalize
	# SunOS6.  Hard to guess exactly what SunOS6 will be like, but
	# it's likely to be more like Solaris than SunOS4.
	echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
	exit ;;
    sun4*:SunOS:*:*)
	case "`/usr/bin/arch -k`" in
	    Series*|S4*)
		UNAME_RELEASE=`uname -v`
		;;
	esac
	# Japanese Language versions have a version number like `4.1.3-JL'.
	echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
	exit ;;
    sun3*:SunOS:*:*)
	echo m68k-sun-sunos${UNAME_RELEASE}
	exit ;;
    sun*:*:4.2BSD:*)
	UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
	test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
	case "`/bin/arch`" in
	    sun3)
		echo m68k-sun-sunos${UNAME_RELEASE}
		;;
	    sun4)
		echo sparc-sun-sunos${UNAME_RELEASE}
		;;
	esac
	exit ;;
    aushp:SunOS:*:*)
	echo sparc-auspex-sunos${UNAME_RELEASE}
	exit ;;
    # The situation for MiNT is a little confusing.  The machine name
    # can be virtually everything (everything which is not
    # "atarist" or "atariste" at least should have a processor
    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
    # to the lowercase version "mint" (or "freemint").  Finally
    # the system name "TOS" denotes a system which is actually not
    # MiNT.  But MiNT is downward compatible to TOS, so this should
    # be no problem.
    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
	echo m68k-atari-mint${UNAME_RELEASE}
	exit ;;
    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
	echo m68k-atari-mint${UNAME_RELEASE}
	exit ;;
    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
	echo m68k-atari-mint${UNAME_RELEASE}
	exit ;;
    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
	echo m68k-milan-mint${UNAME_RELEASE}
	exit ;;
    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
	echo m68k-hades-mint${UNAME_RELEASE}
	exit ;;
    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
	echo m68k-unknown-mint${UNAME_RELEASE}
	exit ;;
    m68k:machten:*:*)
	echo m68k-apple-machten${UNAME_RELEASE}
	exit ;;
    powerpc:machten:*:*)
	echo powerpc-apple-machten${UNAME_RELEASE}
	exit ;;
    RISC*:Mach:*:*)
	echo mips-dec-mach_bsd4.3
	exit ;;
    RISC*:ULTRIX:*:*)
	echo mips-dec-ultrix${UNAME_RELEASE}
	exit ;;
    VAX*:ULTRIX*:*:*)
	echo vax-dec-ultrix${UNAME_RELEASE}
	exit ;;
    2020:CLIX:*:* | 2430:CLIX:*:*)
	echo clipper-intergraph-clix${UNAME_RELEASE}
	exit ;;
    mips:*:*:UMIPS | mips:*:*:RISCos)
	eval $set_cc_for_build
	sed 's/^	//' << EOF >$dummy.c
#ifdef __cplusplus
#include   /* for printf() prototype */
	int main (int argc, char *argv[]) {
#else
	int main (argc, argv) int argc; char *argv[]; {
#endif
	#if defined (host_mips) && defined (MIPSEB)
	#if defined (SYSTYPE_SYSV)
	  printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
	#endif
	#if defined (SYSTYPE_SVR4)
	  printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
	#endif
	#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
	  printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
	#endif
	#endif
	  exit (-1);
	}
EOF
	$CC_FOR_BUILD -o $dummy $dummy.c &&
	  dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
	  SYSTEM_NAME=`$dummy $dummyarg` &&
	    { echo "$SYSTEM_NAME"; exit; }
	echo mips-mips-riscos${UNAME_RELEASE}
	exit ;;
    Motorola:PowerMAX_OS:*:*)
	echo powerpc-motorola-powermax
	exit ;;
    Motorola:*:4.3:PL8-*)
	echo powerpc-harris-powermax
	exit ;;
    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
	echo powerpc-harris-powermax
	exit ;;
    Night_Hawk:Power_UNIX:*:*)
	echo powerpc-harris-powerunix
	exit ;;
    m88k:CX/UX:7*:*)
	echo m88k-harris-cxux7
	exit ;;
    m88k:*:4*:R4*)
	echo m88k-motorola-sysv4
	exit ;;
    m88k:*:3*:R3*)
	echo m88k-motorola-sysv3
	exit ;;
    AViiON:dgux:*:*)
	# DG/UX returns AViiON for all architectures
	UNAME_PROCESSOR=`/usr/bin/uname -p`
	if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
	then
	    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
	       [ ${TARGET_BINARY_INTERFACE}x = x ]
	    then
		echo m88k-dg-dgux${UNAME_RELEASE}
	    else
		echo m88k-dg-dguxbcs${UNAME_RELEASE}
	    fi
	else
	    echo i586-dg-dgux${UNAME_RELEASE}
	fi
	exit ;;
    M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
	echo m88k-dolphin-sysv3
	exit ;;
    M88*:*:R3*:*)
	# Delta 88k system running SVR3
	echo m88k-motorola-sysv3
	exit ;;
    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
	echo m88k-tektronix-sysv3
	exit ;;
    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
	echo m68k-tektronix-bsd
	exit ;;
    *:IRIX*:*:*)
	echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
	exit ;;
    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
	echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
	exit ;;               # Note that: echo "'`uname -s`'" gives 'AIX '
    i*86:AIX:*:*)
	echo i386-ibm-aix
	exit ;;
    ia64:AIX:*:*)
	if [ -x /usr/bin/oslevel ] ; then
		IBM_REV=`/usr/bin/oslevel`
	else
		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
	fi
	echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
	exit ;;
    *:AIX:2:3)
	if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
		eval $set_cc_for_build
		sed 's/^		//' << EOF >$dummy.c
		#include 

		main()
			{
			if (!__power_pc())
				exit(1);
			puts("powerpc-ibm-aix3.2.5");
			exit(0);
			}
EOF
		if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
		then
			echo "$SYSTEM_NAME"
		else
			echo rs6000-ibm-aix3.2.5
		fi
	elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
		echo rs6000-ibm-aix3.2.4
	else
		echo rs6000-ibm-aix3.2
	fi
	exit ;;
    *:AIX:*:[4567])
	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
	if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
		IBM_ARCH=rs6000
	else
		IBM_ARCH=powerpc
	fi
	if [ -x /usr/bin/lslpp ] ; then
		IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
			   awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
	else
		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
	fi
	echo ${IBM_ARCH}-ibm-aix${IBM_REV}
	exit ;;
    *:AIX:*:*)
	echo rs6000-ibm-aix
	exit ;;
    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
	echo romp-ibm-bsd4.4
	exit ;;
    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
	echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
	exit ;;                             # report: romp-ibm BSD 4.3
    *:BOSX:*:*)
	echo rs6000-bull-bosx
	exit ;;
    DPX/2?00:B.O.S.:*:*)
	echo m68k-bull-sysv3
	exit ;;
    9000/[34]??:4.3bsd:1.*:*)
	echo m68k-hp-bsd
	exit ;;
    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
	echo m68k-hp-bsd4.4
	exit ;;
    9000/[34678]??:HP-UX:*:*)
	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
	case "${UNAME_MACHINE}" in
	    9000/31? )            HP_ARCH=m68000 ;;
	    9000/[34]?? )         HP_ARCH=m68k ;;
	    9000/[678][0-9][0-9])
		if [ -x /usr/bin/getconf ]; then
		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
		    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
		    case "${sc_cpu_version}" in
		      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
		      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
		      532)                      # CPU_PA_RISC2_0
			case "${sc_kernel_bits}" in
			  32) HP_ARCH="hppa2.0n" ;;
			  64) HP_ARCH="hppa2.0w" ;;
			  '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
			esac ;;
		    esac
		fi
		if [ "${HP_ARCH}" = "" ]; then
		    eval $set_cc_for_build
		    sed 's/^		//' << EOF >$dummy.c

		#define _HPUX_SOURCE
		#include 
		#include 

		int main ()
		{
		#if defined(_SC_KERNEL_BITS)
		    long bits = sysconf(_SC_KERNEL_BITS);
		#endif
		    long cpu  = sysconf (_SC_CPU_VERSION);

		    switch (cpu)
			{
			case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
			case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
			case CPU_PA_RISC2_0:
		#if defined(_SC_KERNEL_BITS)
			    switch (bits)
				{
				case 64: puts ("hppa2.0w"); break;
				case 32: puts ("hppa2.0n"); break;
				default: puts ("hppa2.0"); break;
				} break;
		#else  /* !defined(_SC_KERNEL_BITS) */
			    puts ("hppa2.0"); break;
		#endif
			default: puts ("hppa1.0"); break;
			}
		    exit (0);
		}
EOF
		    (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
		    test -z "$HP_ARCH" && HP_ARCH=hppa
		fi ;;
	esac
	if [ ${HP_ARCH} = "hppa2.0w" ]
	then
	    eval $set_cc_for_build

	    # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
	    # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
	    # generating 64-bit code.  GNU and HP use different nomenclature:
	    #
	    # $ CC_FOR_BUILD=cc ./config.guess
	    # => hppa2.0w-hp-hpux11.23
	    # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
	    # => hppa64-hp-hpux11.23

	    if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
		grep -q __LP64__
	    then
		HP_ARCH="hppa2.0w"
	    else
		HP_ARCH="hppa64"
	    fi
	fi
	echo ${HP_ARCH}-hp-hpux${HPUX_REV}
	exit ;;
    ia64:HP-UX:*:*)
	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
	echo ia64-hp-hpux${HPUX_REV}
	exit ;;
    3050*:HI-UX:*:*)
	eval $set_cc_for_build
	sed 's/^	//' << EOF >$dummy.c
	#include 
	int
	main ()
	{
	  long cpu = sysconf (_SC_CPU_VERSION);
	  /* The order matters, because CPU_IS_HP_MC68K erroneously returns
	     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
	     results, however.  */
	  if (CPU_IS_PA_RISC (cpu))
	    {
	      switch (cpu)
		{
		  case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
		  case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
		  case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
		  default: puts ("hppa-hitachi-hiuxwe2"); break;
		}
	    }
	  else if (CPU_IS_HP_MC68K (cpu))
	    puts ("m68k-hitachi-hiuxwe2");
	  else puts ("unknown-hitachi-hiuxwe2");
	  exit (0);
	}
EOF
	$CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
		{ echo "$SYSTEM_NAME"; exit; }
	echo unknown-hitachi-hiuxwe2
	exit ;;
    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
	echo hppa1.1-hp-bsd
	exit ;;
    9000/8??:4.3bsd:*:*)
	echo hppa1.0-hp-bsd
	exit ;;
    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
	echo hppa1.0-hp-mpeix
	exit ;;
    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
	echo hppa1.1-hp-osf
	exit ;;
    hp8??:OSF1:*:*)
	echo hppa1.0-hp-osf
	exit ;;
    i*86:OSF1:*:*)
	if [ -x /usr/sbin/sysversion ] ; then
	    echo ${UNAME_MACHINE}-unknown-osf1mk
	else
	    echo ${UNAME_MACHINE}-unknown-osf1
	fi
	exit ;;
    parisc*:Lites*:*:*)
	echo hppa1.1-hp-lites
	exit ;;
    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
	echo c1-convex-bsd
	exit ;;
    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
	if getsysinfo -f scalar_acc
	then echo c32-convex-bsd
	else echo c2-convex-bsd
	fi
	exit ;;
    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
	echo c34-convex-bsd
	exit ;;
    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
	echo c38-convex-bsd
	exit ;;
    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
	echo c4-convex-bsd
	exit ;;
    CRAY*Y-MP:*:*:*)
	echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
	exit ;;
    CRAY*[A-Z]90:*:*:*)
	echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
	| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
	      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
	      -e 's/\.[^.]*$/.X/'
	exit ;;
    CRAY*TS:*:*:*)
	echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
	exit ;;
    CRAY*T3E:*:*:*)
	echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
	exit ;;
    CRAY*SV1:*:*:*)
	echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
	exit ;;
    *:UNICOS/mp:*:*)
	echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
	exit ;;
    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
	FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
	FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
	echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
	exit ;;
    5000:UNIX_System_V:4.*:*)
	FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
	FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
	echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
	exit ;;
    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
	exit ;;
    sparc*:BSD/OS:*:*)
	echo sparc-unknown-bsdi${UNAME_RELEASE}
	exit ;;
    *:BSD/OS:*:*)
	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
	exit ;;
    *:FreeBSD:*:*)
	UNAME_PROCESSOR=`/usr/bin/uname -p`
	case ${UNAME_PROCESSOR} in
	    amd64)
		echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
	    *)
		echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
	esac
	exit ;;
    i*:CYGWIN*:*)
	echo ${UNAME_MACHINE}-pc-cygwin
	exit ;;
    *:MINGW64*:*)
	echo ${UNAME_MACHINE}-pc-mingw64
	exit ;;
    *:MINGW*:*)
	echo ${UNAME_MACHINE}-pc-mingw32
	exit ;;
    *:MSYS*:*)
	echo ${UNAME_MACHINE}-pc-msys
	exit ;;
    i*:windows32*:*)
	# uname -m includes "-pc" on this system.
	echo ${UNAME_MACHINE}-mingw32
	exit ;;
    i*:PW*:*)
	echo ${UNAME_MACHINE}-pc-pw32
	exit ;;
    *:Interix*:*)
	case ${UNAME_MACHINE} in
	    x86)
		echo i586-pc-interix${UNAME_RELEASE}
		exit ;;
	    authenticamd | genuineintel | EM64T)
		echo x86_64-unknown-interix${UNAME_RELEASE}
		exit ;;
	    IA64)
		echo ia64-unknown-interix${UNAME_RELEASE}
		exit ;;
	esac ;;
    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
	echo i${UNAME_MACHINE}-pc-mks
	exit ;;
    8664:Windows_NT:*)
	echo x86_64-pc-mks
	exit ;;
    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
	# How do we know it's Interix rather than the generic POSIX subsystem?
	# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
	# UNAME_MACHINE based on the output of uname instead of i386?
	echo i586-pc-interix
	exit ;;
    i*:UWIN*:*)
	echo ${UNAME_MACHINE}-pc-uwin
	exit ;;
    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
	echo x86_64-unknown-cygwin
	exit ;;
    p*:CYGWIN*:*)
	echo powerpcle-unknown-cygwin
	exit ;;
    prep*:SunOS:5.*:*)
	echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
	exit ;;
    *:GNU:*:*)
	# the GNU system
	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
	exit ;;
    *:GNU/*:*:*)
	# other systems with GNU libc and userland
	echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
	exit ;;
    i*86:Minix:*:*)
	echo ${UNAME_MACHINE}-pc-minix
	exit ;;
    aarch64:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	exit ;;
    aarch64_be:Linux:*:*)
	UNAME_MACHINE=aarch64_be
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	exit ;;
    alpha:Linux:*:*)
	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
	  EV5)   UNAME_MACHINE=alphaev5 ;;
	  EV56)  UNAME_MACHINE=alphaev56 ;;
	  PCA56) UNAME_MACHINE=alphapca56 ;;
	  PCA57) UNAME_MACHINE=alphapca56 ;;
	  EV6)   UNAME_MACHINE=alphaev6 ;;
	  EV67)  UNAME_MACHINE=alphaev67 ;;
	  EV68*) UNAME_MACHINE=alphaev68 ;;
	esac
	objdump --private-headers /bin/sh | grep -q ld.so.1
	if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	exit ;;
    arc:Linux:*:* | arceb:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	exit ;;
    arm*:Linux:*:*)
	eval $set_cc_for_build
	if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
	    | grep -q __ARM_EABI__
	then
	    echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	else
	    if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
		| grep -q __ARM_PCS_VFP
	    then
		echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
	    else
		echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
	    fi
	fi
	exit ;;
    avr32*:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	exit ;;
    cris:Linux:*:*)
	echo ${UNAME_MACHINE}-axis-linux-${LIBC}
	exit ;;
    crisv32:Linux:*:*)
	echo ${UNAME_MACHINE}-axis-linux-${LIBC}
	exit ;;
    e2k:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	exit ;;
    frv:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	exit ;;
    hexagon:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	exit ;;
    i*86:Linux:*:*)
	echo ${UNAME_MACHINE}-pc-linux-${LIBC}
	exit ;;
    ia64:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	exit ;;
    m32r*:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	exit ;;
    m68*:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	exit ;;
    mips:Linux:*:* | mips64:Linux:*:*)
	eval $set_cc_for_build
	sed 's/^	//' << EOF >$dummy.c
	#undef CPU
	#undef ${UNAME_MACHINE}
	#undef ${UNAME_MACHINE}el
	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
	CPU=${UNAME_MACHINE}el
	#else
	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
	CPU=${UNAME_MACHINE}
	#else
	CPU=
	#endif
	#endif
EOF
	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
	;;
    openrisc*:Linux:*:*)
	echo or1k-unknown-linux-${LIBC}
	exit ;;
    or32:Linux:*:* | or1k*:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	exit ;;
    padre:Linux:*:*)
	echo sparc-unknown-linux-${LIBC}
	exit ;;
    parisc64:Linux:*:* | hppa64:Linux:*:*)
	echo hppa64-unknown-linux-${LIBC}
	exit ;;
    parisc:Linux:*:* | hppa:Linux:*:*)
	# Look for CPU level
	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
	  PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
	  PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
	  *)    echo hppa-unknown-linux-${LIBC} ;;
	esac
	exit ;;
    ppc64:Linux:*:*)
	echo powerpc64-unknown-linux-${LIBC}
	exit ;;
    ppc:Linux:*:*)
	echo powerpc-unknown-linux-${LIBC}
	exit ;;
    ppc64le:Linux:*:*)
	echo powerpc64le-unknown-linux-${LIBC}
	exit ;;
    ppcle:Linux:*:*)
	echo powerpcle-unknown-linux-${LIBC}
	exit ;;
    s390:Linux:*:* | s390x:Linux:*:*)
	echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
	exit ;;
    sh64*:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	exit ;;
    sh*:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	exit ;;
    sparc:Linux:*:* | sparc64:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	exit ;;
    tile*:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	exit ;;
    vax:Linux:*:*)
	echo ${UNAME_MACHINE}-dec-linux-${LIBC}
	exit ;;
    x86_64:Linux:*:*)
	echo ${UNAME_MACHINE}-pc-linux-${LIBC}
	exit ;;
    xtensa*:Linux:*:*)
	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
	exit ;;
    i*86:DYNIX/ptx:4*:*)
	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
	# earlier versions are messed up and put the nodename in both
	# sysname and nodename.
	echo i386-sequent-sysv4
	exit ;;
    i*86:UNIX_SV:4.2MP:2.*)
	# Unixware is an offshoot of SVR4, but it has its own version
	# number series starting with 2...
	# I am not positive that other SVR4 systems won't match this,
	# I just have to hope.  -- rms.
	# Use sysv4.2uw... so that sysv4* matches it.
	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
	exit ;;
    i*86:OS/2:*:*)
	# If we were able to find `uname', then EMX Unix compatibility
	# is probably installed.
	echo ${UNAME_MACHINE}-pc-os2-emx
	exit ;;
    i*86:XTS-300:*:STOP)
	echo ${UNAME_MACHINE}-unknown-stop
	exit ;;
    i*86:atheos:*:*)
	echo ${UNAME_MACHINE}-unknown-atheos
	exit ;;
    i*86:syllable:*:*)
	echo ${UNAME_MACHINE}-pc-syllable
	exit ;;
    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
	echo i386-unknown-lynxos${UNAME_RELEASE}
	exit ;;
    i*86:*DOS:*:*)
	echo ${UNAME_MACHINE}-pc-msdosdjgpp
	exit ;;
    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
	UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
		echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
	else
		echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
	fi
	exit ;;
    i*86:*:5:[678]*)
	# UnixWare 7.x, OpenUNIX and OpenServer 6.
	case `/bin/uname -X | grep "^Machine"` in
	    *486*)	     UNAME_MACHINE=i486 ;;
	    *Pentium)	     UNAME_MACHINE=i586 ;;
	    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
	esac
	echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
	exit ;;
    i*86:*:3.2:*)
	if test -f /usr/options/cb.name; then
		UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then
		UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
		(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
		(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
			&& UNAME_MACHINE=i586
		(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
			&& UNAME_MACHINE=i686
		(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
			&& UNAME_MACHINE=i686
		echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
	else
		echo ${UNAME_MACHINE}-pc-sysv32
	fi
	exit ;;
    pc:*:*:*)
	# Left here for compatibility:
	# uname -m prints for DJGPP always 'pc', but it prints nothing about
	# the processor, so we play safe by assuming i586.
	# Note: whatever this is, it MUST be the same as what config.sub
	# prints for the "djgpp" host, or else GDB configury will decide that
	# this is a cross-build.
	echo i586-pc-msdosdjgpp
	exit ;;
    Intel:Mach:3*:*)
	echo i386-pc-mach3
	exit ;;
    paragon:*:*:*)
	echo i860-intel-osf1
	exit ;;
    i860:*:4.*:*) # i860-SVR4
	if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
	  echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
	else # Add other i860-SVR4 vendors below as they are discovered.
	  echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
	fi
	exit ;;
    mini*:CTIX:SYS*5:*)
	# "miniframe"
	echo m68010-convergent-sysv
	exit ;;
    mc68k:UNIX:SYSTEM5:3.51m)
	echo m68k-convergent-sysv
	exit ;;
    M680?0:D-NIX:5.3:*)
	echo m68k-diab-dnix
	exit ;;
    M68*:*:R3V[5678]*:*)
	test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
	OS_REL=''
	test -r /etc/.relid \
	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
	  && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
	  && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
	  && { echo i486-ncr-sysv4; exit; } ;;
    NCR*:*:4.2:* | MPRAS*:*:4.2:*)
	OS_REL='.3'
	test -r /etc/.relid \
	    && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
	    && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
	    && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
	/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
	    && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
	echo m68k-unknown-lynxos${UNAME_RELEASE}
	exit ;;
    mc68030:UNIX_System_V:4.*:*)
	echo m68k-atari-sysv4
	exit ;;
    TSUNAMI:LynxOS:2.*:*)
	echo sparc-unknown-lynxos${UNAME_RELEASE}
	exit ;;
    rs6000:LynxOS:2.*:*)
	echo rs6000-unknown-lynxos${UNAME_RELEASE}
	exit ;;
    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
	echo powerpc-unknown-lynxos${UNAME_RELEASE}
	exit ;;
    SM[BE]S:UNIX_SV:*:*)
	echo mips-dde-sysv${UNAME_RELEASE}
	exit ;;
    RM*:ReliantUNIX-*:*:*)
	echo mips-sni-sysv4
	exit ;;
    RM*:SINIX-*:*:*)
	echo mips-sni-sysv4
	exit ;;
    *:SINIX-*:*:*)
	if uname -p 2>/dev/null >/dev/null ; then
		UNAME_MACHINE=`(uname -p) 2>/dev/null`
		echo ${UNAME_MACHINE}-sni-sysv4
	else
		echo ns32k-sni-sysv
	fi
	exit ;;
    PENTIUM:*:4.0*:*)	# Unisys `ClearPath HMP IX 4000' SVR4/MP effort
			# says 
	echo i586-unisys-sysv4
	exit ;;
    *:UNIX_System_V:4*:FTX*)
	# From Gerald Hewes .
	# How about differentiating between stratus architectures? -djm
	echo hppa1.1-stratus-sysv4
	exit ;;
    *:*:*:FTX*)
	# From seanf@swdc.stratus.com.
	echo i860-stratus-sysv4
	exit ;;
    i*86:VOS:*:*)
	# From Paul.Green@stratus.com.
	echo ${UNAME_MACHINE}-stratus-vos
	exit ;;
    *:VOS:*:*)
	# From Paul.Green@stratus.com.
	echo hppa1.1-stratus-vos
	exit ;;
    mc68*:A/UX:*:*)
	echo m68k-apple-aux${UNAME_RELEASE}
	exit ;;
    news*:NEWS-OS:6*:*)
	echo mips-sony-newsos6
	exit ;;
    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
	if [ -d /usr/nec ]; then
		echo mips-nec-sysv${UNAME_RELEASE}
	else
		echo mips-unknown-sysv${UNAME_RELEASE}
	fi
	exit ;;
    BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
	echo powerpc-be-beos
	exit ;;
    BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
	echo powerpc-apple-beos
	exit ;;
    BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
	echo i586-pc-beos
	exit ;;
    BePC:Haiku:*:*)	# Haiku running on Intel PC compatible.
	echo i586-pc-haiku
	exit ;;
    x86_64:Haiku:*:*)
	echo x86_64-unknown-haiku
	exit ;;
    SX-4:SUPER-UX:*:*)
	echo sx4-nec-superux${UNAME_RELEASE}
	exit ;;
    SX-5:SUPER-UX:*:*)
	echo sx5-nec-superux${UNAME_RELEASE}
	exit ;;
    SX-6:SUPER-UX:*:*)
	echo sx6-nec-superux${UNAME_RELEASE}
	exit ;;
    SX-7:SUPER-UX:*:*)
	echo sx7-nec-superux${UNAME_RELEASE}
	exit ;;
    SX-8:SUPER-UX:*:*)
	echo sx8-nec-superux${UNAME_RELEASE}
	exit ;;
    SX-8R:SUPER-UX:*:*)
	echo sx8r-nec-superux${UNAME_RELEASE}
	exit ;;
    Power*:Rhapsody:*:*)
	echo powerpc-apple-rhapsody${UNAME_RELEASE}
	exit ;;
    *:Rhapsody:*:*)
	echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
	exit ;;
    *:Darwin:*:*)
	UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
	eval $set_cc_for_build
	if test "$UNAME_PROCESSOR" = unknown ; then
	    UNAME_PROCESSOR=powerpc
	fi
	if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
	    if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
		if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
		    (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
		    grep IS_64BIT_ARCH >/dev/null
		then
		    case $UNAME_PROCESSOR in
			i386) UNAME_PROCESSOR=x86_64 ;;
			powerpc) UNAME_PROCESSOR=powerpc64 ;;
		    esac
		fi
	    fi
	elif test "$UNAME_PROCESSOR" = i386 ; then
	    # Avoid executing cc on OS X 10.9, as it ships with a stub
	    # that puts up a graphical alert prompting to install
	    # developer tools.  Any system running Mac OS X 10.7 or
	    # later (Darwin 11 and later) is required to have a 64-bit
	    # processor. This is not true of the ARM version of Darwin
	    # that Apple uses in portable devices.
	    UNAME_PROCESSOR=x86_64
	fi
	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
	exit ;;
    *:procnto*:*:* | *:QNX:[0123456789]*:*)
	UNAME_PROCESSOR=`uname -p`
	if test "$UNAME_PROCESSOR" = "x86"; then
		UNAME_PROCESSOR=i386
		UNAME_MACHINE=pc
	fi
	echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
	exit ;;
    *:QNX:*:4*)
	echo i386-pc-qnx
	exit ;;
    NEO-?:NONSTOP_KERNEL:*:*)
	echo neo-tandem-nsk${UNAME_RELEASE}
	exit ;;
    NSE-*:NONSTOP_KERNEL:*:*)
	echo nse-tandem-nsk${UNAME_RELEASE}
	exit ;;
    NSR-?:NONSTOP_KERNEL:*:*)
	echo nsr-tandem-nsk${UNAME_RELEASE}
	exit ;;
    *:NonStop-UX:*:*)
	echo mips-compaq-nonstopux
	exit ;;
    BS2000:POSIX*:*:*)
	echo bs2000-siemens-sysv
	exit ;;
    DS/*:UNIX_System_V:*:*)
	echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
	exit ;;
    *:Plan9:*:*)
	# "uname -m" is not consistent, so use $cputype instead. 386
	# is converted to i386 for consistency with other x86
	# operating systems.
	if test "$cputype" = "386"; then
	    UNAME_MACHINE=i386
	else
	    UNAME_MACHINE="$cputype"
	fi
	echo ${UNAME_MACHINE}-unknown-plan9
	exit ;;
    *:TOPS-10:*:*)
	echo pdp10-unknown-tops10
	exit ;;
    *:TENEX:*:*)
	echo pdp10-unknown-tenex
	exit ;;
    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
	echo pdp10-dec-tops20
	exit ;;
    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
	echo pdp10-xkl-tops20
	exit ;;
    *:TOPS-20:*:*)
	echo pdp10-unknown-tops20
	exit ;;
    *:ITS:*:*)
	echo pdp10-unknown-its
	exit ;;
    SEI:*:*:SEIUX)
	echo mips-sei-seiux${UNAME_RELEASE}
	exit ;;
    *:DragonFly:*:*)
	echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
	exit ;;
    *:*VMS:*:*)
	UNAME_MACHINE=`(uname -p) 2>/dev/null`
	case "${UNAME_MACHINE}" in
	    A*) echo alpha-dec-vms ; exit ;;
	    I*) echo ia64-dec-vms ; exit ;;
	    V*) echo vax-dec-vms ; exit ;;
	esac ;;
    *:XENIX:*:SysV)
	echo i386-pc-xenix
	exit ;;
    i*86:skyos:*:*)
	echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
	exit ;;
    i*86:rdos:*:*)
	echo ${UNAME_MACHINE}-pc-rdos
	exit ;;
    i*86:AROS:*:*)
	echo ${UNAME_MACHINE}-pc-aros
	exit ;;
    x86_64:VMkernel:*:*)
	echo ${UNAME_MACHINE}-unknown-esx
	exit ;;
esac

cat >&2 < in order to provide the needed
information to handle your system.

config.guess timestamp = $timestamp

uname -m = `(uname -m) 2>/dev/null || echo unknown`
uname -r = `(uname -r) 2>/dev/null || echo unknown`
uname -s = `(uname -s) 2>/dev/null || echo unknown`
uname -v = `(uname -v) 2>/dev/null || echo unknown`

/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`

hostinfo               = `(hostinfo) 2>/dev/null`
/bin/universe          = `(/bin/universe) 2>/dev/null`
/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
/bin/arch              = `(/bin/arch) 2>/dev/null`
/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`

UNAME_MACHINE = ${UNAME_MACHINE}
UNAME_RELEASE = ${UNAME_RELEASE}
UNAME_SYSTEM  = ${UNAME_SYSTEM}
UNAME_VERSION = ${UNAME_VERSION}
EOF

exit 1

# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-end: "'"
# End:
ode-0.16/ltmain.sh0000644000175200017520000117146413403272662010777 00000000000000#! /bin/sh
## DO NOT EDIT - This file generated from ./build-aux/ltmain.in
##               by inline-source v2014-01-03.01

# libtool (GNU libtool) 2.4.6
# Provide generalized library-building support services.
# Written by Gordon Matzigkeit , 1996

# Copyright (C) 1996-2015 Free Software Foundation, Inc.
# This is free software; see the source for copying conditions.  There is NO
# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

# GNU Libtool is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# As a special exception to the GNU General Public License,
# if you distribute this file as part of a program or library that
# is built using GNU Libtool, you may include this file under the
# same distribution terms that you use for the rest of that program.
#
# GNU Libtool is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see .


PROGRAM=libtool
PACKAGE=libtool
VERSION="2.4.6 Debian-2.4.6-0.1"
package_revision=2.4.6


## ------ ##
## Usage. ##
## ------ ##

# Run './libtool --help' for help with using this script from the
# command line.


## ------------------------------- ##
## User overridable command paths. ##
## ------------------------------- ##

# After configure completes, it has a better idea of some of the
# shell tools we need than the defaults used by the functions shared
# with bootstrap, so set those here where they can still be over-
# ridden by the user, but otherwise take precedence.

: ${AUTOCONF="autoconf"}
: ${AUTOMAKE="automake"}


## -------------------------- ##
## Source external libraries. ##
## -------------------------- ##

# Much of our low-level functionality needs to be sourced from external
# libraries, which are installed to $pkgauxdir.

# Set a version string for this script.
scriptversion=2015-01-20.17; # UTC

# General shell script boiler plate, and helper functions.
# Written by Gary V. Vaughan, 2004

# Copyright (C) 2004-2015 Free Software Foundation, Inc.
# This is free software; see the source for copying conditions.  There is NO
# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.

# As a special exception to the GNU General Public License, if you distribute
# this file as part of a program or library that is built using GNU Libtool,
# you may include this file under the same distribution terms that you use
# for the rest of that program.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNES FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program. If not, see .

# Please report bugs or propose patches to gary@gnu.org.


## ------ ##
## Usage. ##
## ------ ##

# Evaluate this file near the top of your script to gain access to
# the functions and variables defined here:
#
#   . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh
#
# If you need to override any of the default environment variable
# settings, do that before evaluating this file.


## -------------------- ##
## Shell normalisation. ##
## -------------------- ##

# Some shells need a little help to be as Bourne compatible as possible.
# Before doing anything else, make sure all that help has been provided!

DUALCASE=1; export DUALCASE # for MKS sh
if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
  emulate sh
  NULLCMD=:
  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
  # is contrary to our usage.  Disable this feature.
  alias -g '${1+"$@"}'='"$@"'
  setopt NO_GLOB_SUBST
else
  case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac
fi

# NLS nuisances: We save the old values in case they are required later.
_G_user_locale=
_G_safe_locale=
for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
do
  eval "if test set = \"\${$_G_var+set}\"; then
          save_$_G_var=\$$_G_var
          $_G_var=C
	  export $_G_var
	  _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\"
	  _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\"
	fi"
done

# CDPATH.
(unset CDPATH) >/dev/null 2>&1 && unset CDPATH

# Make sure IFS has a sensible default
sp=' '
nl='
'
IFS="$sp	$nl"

# There are apparently some retarded systems that use ';' as a PATH separator!
if test "${PATH_SEPARATOR+set}" != set; then
  PATH_SEPARATOR=:
  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
      PATH_SEPARATOR=';'
  }
fi



## ------------------------- ##
## Locate command utilities. ##
## ------------------------- ##


# func_executable_p FILE
# ----------------------
# Check that FILE is an executable regular file.
func_executable_p ()
{
    test -f "$1" && test -x "$1"
}


# func_path_progs PROGS_LIST CHECK_FUNC [PATH]
# --------------------------------------------
# Search for either a program that responds to --version with output
# containing "GNU", or else returned by CHECK_FUNC otherwise, by
# trying all the directories in PATH with each of the elements of
# PROGS_LIST.
#
# CHECK_FUNC should accept the path to a candidate program, and
# set $func_check_prog_result if it truncates its output less than
# $_G_path_prog_max characters.
func_path_progs ()
{
    _G_progs_list=$1
    _G_check_func=$2
    _G_PATH=${3-"$PATH"}

    _G_path_prog_max=0
    _G_path_prog_found=false
    _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:}
    for _G_dir in $_G_PATH; do
      IFS=$_G_save_IFS
      test -z "$_G_dir" && _G_dir=.
      for _G_prog_name in $_G_progs_list; do
        for _exeext in '' .EXE; do
          _G_path_prog=$_G_dir/$_G_prog_name$_exeext
          func_executable_p "$_G_path_prog" || continue
          case `"$_G_path_prog" --version 2>&1` in
            *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;;
            *)     $_G_check_func $_G_path_prog
		   func_path_progs_result=$func_check_prog_result
		   ;;
          esac
          $_G_path_prog_found && break 3
        done
      done
    done
    IFS=$_G_save_IFS
    test -z "$func_path_progs_result" && {
      echo "no acceptable sed could be found in \$PATH" >&2
      exit 1
    }
}


# We want to be able to use the functions in this file before configure
# has figured out where the best binaries are kept, which means we have
# to search for them ourselves - except when the results are already set
# where we skip the searches.

# Unless the user overrides by setting SED, search the path for either GNU
# sed, or the sed that truncates its output the least.
test -z "$SED" && {
  _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
  for _G_i in 1 2 3 4 5 6 7; do
    _G_sed_script=$_G_sed_script$nl$_G_sed_script
  done
  echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed
  _G_sed_script=

  func_check_prog_sed ()
  {
    _G_path_prog=$1

    _G_count=0
    printf 0123456789 >conftest.in
    while :
    do
      cat conftest.in conftest.in >conftest.tmp
      mv conftest.tmp conftest.in
      cp conftest.in conftest.nl
      echo '' >> conftest.nl
      "$_G_path_prog" -f conftest.sed conftest.out 2>/dev/null || break
      diff conftest.out conftest.nl >/dev/null 2>&1 || break
      _G_count=`expr $_G_count + 1`
      if test "$_G_count" -gt "$_G_path_prog_max"; then
        # Best one so far, save it but keep looking for a better one
        func_check_prog_result=$_G_path_prog
        _G_path_prog_max=$_G_count
      fi
      # 10*(2^10) chars as input seems more than enough
      test 10 -lt "$_G_count" && break
    done
    rm -f conftest.in conftest.tmp conftest.nl conftest.out
  }

  func_path_progs "sed gsed" func_check_prog_sed $PATH:/usr/xpg4/bin
  rm -f conftest.sed
  SED=$func_path_progs_result
}


# Unless the user overrides by setting GREP, search the path for either GNU
# grep, or the grep that truncates its output the least.
test -z "$GREP" && {
  func_check_prog_grep ()
  {
    _G_path_prog=$1

    _G_count=0
    _G_path_prog_max=0
    printf 0123456789 >conftest.in
    while :
    do
      cat conftest.in conftest.in >conftest.tmp
      mv conftest.tmp conftest.in
      cp conftest.in conftest.nl
      echo 'GREP' >> conftest.nl
      "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' conftest.out 2>/dev/null || break
      diff conftest.out conftest.nl >/dev/null 2>&1 || break
      _G_count=`expr $_G_count + 1`
      if test "$_G_count" -gt "$_G_path_prog_max"; then
        # Best one so far, save it but keep looking for a better one
        func_check_prog_result=$_G_path_prog
        _G_path_prog_max=$_G_count
      fi
      # 10*(2^10) chars as input seems more than enough
      test 10 -lt "$_G_count" && break
    done
    rm -f conftest.in conftest.tmp conftest.nl conftest.out
  }

  func_path_progs "grep ggrep" func_check_prog_grep $PATH:/usr/xpg4/bin
  GREP=$func_path_progs_result
}


## ------------------------------- ##
## User overridable command paths. ##
## ------------------------------- ##

# All uppercase variable names are used for environment variables.  These
# variables can be overridden by the user before calling a script that
# uses them if a suitable command of that name is not already available
# in the command search PATH.

: ${CP="cp -f"}
: ${ECHO="printf %s\n"}
: ${EGREP="$GREP -E"}
: ${FGREP="$GREP -F"}
: ${LN_S="ln -s"}
: ${MAKE="make"}
: ${MKDIR="mkdir"}
: ${MV="mv -f"}
: ${RM="rm -f"}
: ${SHELL="${CONFIG_SHELL-/bin/sh}"}


## -------------------- ##
## Useful sed snippets. ##
## -------------------- ##

sed_dirname='s|/[^/]*$||'
sed_basename='s|^.*/||'

# Sed substitution that helps us do robust quoting.  It backslashifies
# metacharacters that are still active within double-quoted strings.
sed_quote_subst='s|\([`"$\\]\)|\\\1|g'

# Same as above, but do not quote variable references.
sed_double_quote_subst='s/\(["`\\]\)/\\\1/g'

# Sed substitution that turns a string into a regex matching for the
# string literally.
sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g'

# Sed substitution that converts a w32 file name or path
# that contains forward slashes, into one that contains
# (escaped) backslashes.  A very naive implementation.
sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g'

# Re-'\' parameter expansions in output of sed_double_quote_subst that
# were '\'-ed in input to the same.  If an odd number of '\' preceded a
# '$' in input to sed_double_quote_subst, that '$' was protected from
# expansion.  Since each input '\' is now two '\'s, look for any number
# of runs of four '\'s followed by two '\'s and then a '$'.  '\' that '$'.
_G_bs='\\'
_G_bs2='\\\\'
_G_bs4='\\\\\\\\'
_G_dollar='\$'
sed_double_backslash="\
  s/$_G_bs4/&\\
/g
  s/^$_G_bs2$_G_dollar/$_G_bs&/
  s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g
  s/\n//g"


## ----------------- ##
## Global variables. ##
## ----------------- ##

# Except for the global variables explicitly listed below, the following
# functions in the '^func_' namespace, and the '^require_' namespace
# variables initialised in the 'Resource management' section, sourcing
# this file will not pollute your global namespace with anything
# else. There's no portable way to scope variables in Bourne shell
# though, so actually running these functions will sometimes place
# results into a variable named after the function, and often use
# temporary variables in the '^_G_' namespace. If you are careful to
# avoid using those namespaces casually in your sourcing script, things
# should continue to work as you expect. And, of course, you can freely
# overwrite any of the functions or variables defined here before
# calling anything to customize them.

EXIT_SUCCESS=0
EXIT_FAILURE=1
EXIT_MISMATCH=63  # $? = 63 is used to indicate version mismatch to missing.
EXIT_SKIP=77	  # $? = 77 is used to indicate a skipped test to automake.

# Allow overriding, eg assuming that you follow the convention of
# putting '$debug_cmd' at the start of all your functions, you can get
# bash to show function call trace with:
#
#    debug_cmd='eval echo "${FUNCNAME[0]} $*" >&2' bash your-script-name
debug_cmd=${debug_cmd-":"}
exit_cmd=:

# By convention, finish your script with:
#
#    exit $exit_status
#
# so that you can set exit_status to non-zero if you want to indicate
# something went wrong during execution without actually bailing out at
# the point of failure.
exit_status=$EXIT_SUCCESS

# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh
# is ksh but when the shell is invoked as "sh" and the current value of
# the _XPG environment variable is not equal to 1 (one), the special
# positional parameter $0, within a function call, is the name of the
# function.
progpath=$0

# The name of this program.
progname=`$ECHO "$progpath" |$SED "$sed_basename"`

# Make sure we have an absolute progpath for reexecution:
case $progpath in
  [\\/]*|[A-Za-z]:\\*) ;;
  *[\\/]*)
     progdir=`$ECHO "$progpath" |$SED "$sed_dirname"`
     progdir=`cd "$progdir" && pwd`
     progpath=$progdir/$progname
     ;;
  *)
     _G_IFS=$IFS
     IFS=${PATH_SEPARATOR-:}
     for progdir in $PATH; do
       IFS=$_G_IFS
       test -x "$progdir/$progname" && break
     done
     IFS=$_G_IFS
     test -n "$progdir" || progdir=`pwd`
     progpath=$progdir/$progname
     ;;
esac


## ----------------- ##
## Standard options. ##
## ----------------- ##

# The following options affect the operation of the functions defined
# below, and should be set appropriately depending on run-time para-
# meters passed on the command line.

opt_dry_run=false
opt_quiet=false
opt_verbose=false

# Categories 'all' and 'none' are always available.  Append any others
# you will pass as the first argument to func_warning from your own
# code.
warning_categories=

# By default, display warnings according to 'opt_warning_types'.  Set
# 'warning_func'  to ':' to elide all warnings, or func_fatal_error to
# treat the next displayed warning as a fatal error.
warning_func=func_warn_and_continue

# Set to 'all' to display all warnings, 'none' to suppress all
# warnings, or a space delimited list of some subset of
# 'warning_categories' to display only the listed warnings.
opt_warning_types=all


## -------------------- ##
## Resource management. ##
## -------------------- ##

# This section contains definitions for functions that each ensure a
# particular resource (a file, or a non-empty configuration variable for
# example) is available, and if appropriate to extract default values
# from pertinent package files. Call them using their associated
# 'require_*' variable to ensure that they are executed, at most, once.
#
# It's entirely deliberate that calling these functions can set
# variables that don't obey the namespace limitations obeyed by the rest
# of this file, in order that that they be as useful as possible to
# callers.


# require_term_colors
# -------------------
# Allow display of bold text on terminals that support it.
require_term_colors=func_require_term_colors
func_require_term_colors ()
{
    $debug_cmd

    test -t 1 && {
      # COLORTERM and USE_ANSI_COLORS environment variables take
      # precedence, because most terminfo databases neglect to describe
      # whether color sequences are supported.
      test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"}

      if test 1 = "$USE_ANSI_COLORS"; then
        # Standard ANSI escape sequences
        tc_reset=''
        tc_bold='';   tc_standout=''
        tc_red='';   tc_green=''
        tc_blue='';  tc_cyan=''
      else
        # Otherwise trust the terminfo database after all.
        test -n "`tput sgr0 2>/dev/null`" && {
          tc_reset=`tput sgr0`
          test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold`
          tc_standout=$tc_bold
          test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso`
          test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1`
          test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2`
          test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4`
          test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5`
        }
      fi
    }

    require_term_colors=:
}


## ----------------- ##
## Function library. ##
## ----------------- ##

# This section contains a variety of useful functions to call in your
# scripts. Take note of the portable wrappers for features provided by
# some modern shells, which will fall back to slower equivalents on
# less featureful shells.


# func_append VAR VALUE
# ---------------------
# Append VALUE onto the existing contents of VAR.

  # We should try to minimise forks, especially on Windows where they are
  # unreasonably slow, so skip the feature probes when bash or zsh are
  # being used:
  if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then
    : ${_G_HAVE_ARITH_OP="yes"}
    : ${_G_HAVE_XSI_OPS="yes"}
    # The += operator was introduced in bash 3.1
    case $BASH_VERSION in
      [12].* | 3.0 | 3.0*) ;;
      *)
        : ${_G_HAVE_PLUSEQ_OP="yes"}
        ;;
    esac
  fi

  # _G_HAVE_PLUSEQ_OP
  # Can be empty, in which case the shell is probed, "yes" if += is
  # useable or anything else if it does not work.
  test -z "$_G_HAVE_PLUSEQ_OP" \
    && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \
    && _G_HAVE_PLUSEQ_OP=yes

if test yes = "$_G_HAVE_PLUSEQ_OP"
then
  # This is an XSI compatible shell, allowing a faster implementation...
  eval 'func_append ()
  {
    $debug_cmd

    eval "$1+=\$2"
  }'
else
  # ...otherwise fall back to using expr, which is often a shell builtin.
  func_append ()
  {
    $debug_cmd

    eval "$1=\$$1\$2"
  }
fi


# func_append_quoted VAR VALUE
# ----------------------------
# Quote VALUE and append to the end of shell variable VAR, separated
# by a space.
if test yes = "$_G_HAVE_PLUSEQ_OP"; then
  eval 'func_append_quoted ()
  {
    $debug_cmd

    func_quote_for_eval "$2"
    eval "$1+=\\ \$func_quote_for_eval_result"
  }'
else
  func_append_quoted ()
  {
    $debug_cmd

    func_quote_for_eval "$2"
    eval "$1=\$$1\\ \$func_quote_for_eval_result"
  }
fi


# func_append_uniq VAR VALUE
# --------------------------
# Append unique VALUE onto the existing contents of VAR, assuming
# entries are delimited by the first character of VALUE.  For example:
#
#   func_append_uniq options " --another-option option-argument"
#
# will only append to $options if " --another-option option-argument "
# is not already present somewhere in $options already (note spaces at
# each end implied by leading space in second argument).
func_append_uniq ()
{
    $debug_cmd

    eval _G_current_value='`$ECHO $'$1'`'
    _G_delim=`expr "$2" : '\(.\)'`

    case $_G_delim$_G_current_value$_G_delim in
      *"$2$_G_delim"*) ;;
      *) func_append "$@" ;;
    esac
}


# func_arith TERM...
# ------------------
# Set func_arith_result to the result of evaluating TERMs.
  test -z "$_G_HAVE_ARITH_OP" \
    && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \
    && _G_HAVE_ARITH_OP=yes

if test yes = "$_G_HAVE_ARITH_OP"; then
  eval 'func_arith ()
  {
    $debug_cmd

    func_arith_result=$(( $* ))
  }'
else
  func_arith ()
  {
    $debug_cmd

    func_arith_result=`expr "$@"`
  }
fi


# func_basename FILE
# ------------------
# Set func_basename_result to FILE with everything up to and including
# the last / stripped.
if test yes = "$_G_HAVE_XSI_OPS"; then
  # If this shell supports suffix pattern removal, then use it to avoid
  # forking. Hide the definitions single quotes in case the shell chokes
  # on unsupported syntax...
  _b='func_basename_result=${1##*/}'
  _d='case $1 in
        */*) func_dirname_result=${1%/*}$2 ;;
        *  ) func_dirname_result=$3        ;;
      esac'

else
  # ...otherwise fall back to using sed.
  _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`'
  _d='func_dirname_result=`$ECHO "$1"  |$SED "$sed_dirname"`
      if test "X$func_dirname_result" = "X$1"; then
        func_dirname_result=$3
      else
        func_append func_dirname_result "$2"
      fi'
fi

eval 'func_basename ()
{
    $debug_cmd

    '"$_b"'
}'


# func_dirname FILE APPEND NONDIR_REPLACEMENT
# -------------------------------------------
# Compute the dirname of FILE.  If nonempty, add APPEND to the result,
# otherwise set result to NONDIR_REPLACEMENT.
eval 'func_dirname ()
{
    $debug_cmd

    '"$_d"'
}'


# func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT
# --------------------------------------------------------
# Perform func_basename and func_dirname in a single function
# call:
#   dirname:  Compute the dirname of FILE.  If nonempty,
#             add APPEND to the result, otherwise set result
#             to NONDIR_REPLACEMENT.
#             value returned in "$func_dirname_result"
#   basename: Compute filename of FILE.
#             value retuned in "$func_basename_result"
# For efficiency, we do not delegate to the functions above but instead
# duplicate the functionality here.
eval 'func_dirname_and_basename ()
{
    $debug_cmd

    '"$_b"'
    '"$_d"'
}'


# func_echo ARG...
# ----------------
# Echo program name prefixed message.
func_echo ()
{
    $debug_cmd

    _G_message=$*

    func_echo_IFS=$IFS
    IFS=$nl
    for _G_line in $_G_message; do
      IFS=$func_echo_IFS
      $ECHO "$progname: $_G_line"
    done
    IFS=$func_echo_IFS
}


# func_echo_all ARG...
# --------------------
# Invoke $ECHO with all args, space-separated.
func_echo_all ()
{
    $ECHO "$*"
}


# func_echo_infix_1 INFIX ARG...
# ------------------------------
# Echo program name, followed by INFIX on the first line, with any
# additional lines not showing INFIX.
func_echo_infix_1 ()
{
    $debug_cmd

    $require_term_colors

    _G_infix=$1; shift
    _G_indent=$_G_infix
    _G_prefix="$progname: $_G_infix: "
    _G_message=$*

    # Strip color escape sequences before counting printable length
    for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan"
    do
      test -n "$_G_tc" && {
        _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"`
        _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"`
      }
    done
    _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`"  " ## exclude from sc_prohibit_nested_quotes

    func_echo_infix_1_IFS=$IFS
    IFS=$nl
    for _G_line in $_G_message; do
      IFS=$func_echo_infix_1_IFS
      $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2
      _G_prefix=$_G_indent
    done
    IFS=$func_echo_infix_1_IFS
}


# func_error ARG...
# -----------------
# Echo program name prefixed message to standard error.
func_error ()
{
    $debug_cmd

    $require_term_colors

    func_echo_infix_1 "  $tc_standout${tc_red}error$tc_reset" "$*" >&2
}


# func_fatal_error ARG...
# -----------------------
# Echo program name prefixed message to standard error, and exit.
func_fatal_error ()
{
    $debug_cmd

    func_error "$*"
    exit $EXIT_FAILURE
}


# func_grep EXPRESSION FILENAME
# -----------------------------
# Check whether EXPRESSION matches any line of FILENAME, without output.
func_grep ()
{
    $debug_cmd

    $GREP "$1" "$2" >/dev/null 2>&1
}


# func_len STRING
# ---------------
# Set func_len_result to the length of STRING. STRING may not
# start with a hyphen.
  test -z "$_G_HAVE_XSI_OPS" \
    && (eval 'x=a/b/c;
      test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \
    && _G_HAVE_XSI_OPS=yes

if test yes = "$_G_HAVE_XSI_OPS"; then
  eval 'func_len ()
  {
    $debug_cmd

    func_len_result=${#1}
  }'
else
  func_len ()
  {
    $debug_cmd

    func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len`
  }
fi


# func_mkdir_p DIRECTORY-PATH
# ---------------------------
# Make sure the entire path to DIRECTORY-PATH is available.
func_mkdir_p ()
{
    $debug_cmd

    _G_directory_path=$1
    _G_dir_list=

    if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then

      # Protect directory names starting with '-'
      case $_G_directory_path in
        -*) _G_directory_path=./$_G_directory_path ;;
      esac

      # While some portion of DIR does not yet exist...
      while test ! -d "$_G_directory_path"; do
        # ...make a list in topmost first order.  Use a colon delimited
	# list incase some portion of path contains whitespace.
        _G_dir_list=$_G_directory_path:$_G_dir_list

        # If the last portion added has no slash in it, the list is done
        case $_G_directory_path in */*) ;; *) break ;; esac

        # ...otherwise throw away the child directory and loop
        _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"`
      done
      _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'`

      func_mkdir_p_IFS=$IFS; IFS=:
      for _G_dir in $_G_dir_list; do
	IFS=$func_mkdir_p_IFS
        # mkdir can fail with a 'File exist' error if two processes
        # try to create one of the directories concurrently.  Don't
        # stop in that case!
        $MKDIR "$_G_dir" 2>/dev/null || :
      done
      IFS=$func_mkdir_p_IFS

      # Bail out if we (or some other process) failed to create a directory.
      test -d "$_G_directory_path" || \
        func_fatal_error "Failed to create '$1'"
    fi
}


# func_mktempdir [BASENAME]
# -------------------------
# Make a temporary directory that won't clash with other running
# libtool processes, and avoids race conditions if possible.  If
# given, BASENAME is the basename for that directory.
func_mktempdir ()
{
    $debug_cmd

    _G_template=${TMPDIR-/tmp}/${1-$progname}

    if test : = "$opt_dry_run"; then
      # Return a directory name, but don't create it in dry-run mode
      _G_tmpdir=$_G_template-$$
    else

      # If mktemp works, use that first and foremost
      _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null`

      if test ! -d "$_G_tmpdir"; then
        # Failing that, at least try and use $RANDOM to avoid a race
        _G_tmpdir=$_G_template-${RANDOM-0}$$

        func_mktempdir_umask=`umask`
        umask 0077
        $MKDIR "$_G_tmpdir"
        umask $func_mktempdir_umask
      fi

      # If we're not in dry-run mode, bomb out on failure
      test -d "$_G_tmpdir" || \
        func_fatal_error "cannot create temporary directory '$_G_tmpdir'"
    fi

    $ECHO "$_G_tmpdir"
}


# func_normal_abspath PATH
# ------------------------
# Remove doubled-up and trailing slashes, "." path components,
# and cancel out any ".." path components in PATH after making
# it an absolute path.
func_normal_abspath ()
{
    $debug_cmd

    # These SED scripts presuppose an absolute path with a trailing slash.
    _G_pathcar='s|^/\([^/]*\).*$|\1|'
    _G_pathcdr='s|^/[^/]*||'
    _G_removedotparts=':dotsl
		s|/\./|/|g
		t dotsl
		s|/\.$|/|'
    _G_collapseslashes='s|/\{1,\}|/|g'
    _G_finalslash='s|/*$|/|'

    # Start from root dir and reassemble the path.
    func_normal_abspath_result=
    func_normal_abspath_tpath=$1
    func_normal_abspath_altnamespace=
    case $func_normal_abspath_tpath in
      "")
        # Empty path, that just means $cwd.
        func_stripname '' '/' "`pwd`"
        func_normal_abspath_result=$func_stripname_result
        return
        ;;
      # The next three entries are used to spot a run of precisely
      # two leading slashes without using negated character classes;
      # we take advantage of case's first-match behaviour.
      ///*)
        # Unusual form of absolute path, do nothing.
        ;;
      //*)
        # Not necessarily an ordinary path; POSIX reserves leading '//'
        # and for example Cygwin uses it to access remote file shares
        # over CIFS/SMB, so we conserve a leading double slash if found.
        func_normal_abspath_altnamespace=/
        ;;
      /*)
        # Absolute path, do nothing.
        ;;
      *)
        # Relative path, prepend $cwd.
        func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath
        ;;
    esac

    # Cancel out all the simple stuff to save iterations.  We also want
    # the path to end with a slash for ease of parsing, so make sure
    # there is one (and only one) here.
    func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \
          -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"`
    while :; do
      # Processed it all yet?
      if test / = "$func_normal_abspath_tpath"; then
        # If we ascended to the root using ".." the result may be empty now.
        if test -z "$func_normal_abspath_result"; then
          func_normal_abspath_result=/
        fi
        break
      fi
      func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \
          -e "$_G_pathcar"`
      func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \
          -e "$_G_pathcdr"`
      # Figure out what to do with it
      case $func_normal_abspath_tcomponent in
        "")
          # Trailing empty path component, ignore it.
          ;;
        ..)
          # Parent dir; strip last assembled component from result.
          func_dirname "$func_normal_abspath_result"
          func_normal_abspath_result=$func_dirname_result
          ;;
        *)
          # Actual path component, append it.
          func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent"
          ;;
      esac
    done
    # Restore leading double-slash if one was found on entry.
    func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result
}


# func_notquiet ARG...
# --------------------
# Echo program name prefixed message only when not in quiet mode.
func_notquiet ()
{
    $debug_cmd

    $opt_quiet || func_echo ${1+"$@"}

    # A bug in bash halts the script if the last line of a function
    # fails when set -e is in force, so we need another command to
    # work around that:
    :
}


# func_relative_path SRCDIR DSTDIR
# --------------------------------
# Set func_relative_path_result to the relative path from SRCDIR to DSTDIR.
func_relative_path ()
{
    $debug_cmd

    func_relative_path_result=
    func_normal_abspath "$1"
    func_relative_path_tlibdir=$func_normal_abspath_result
    func_normal_abspath "$2"
    func_relative_path_tbindir=$func_normal_abspath_result

    # Ascend the tree starting from libdir
    while :; do
      # check if we have found a prefix of bindir
      case $func_relative_path_tbindir in
        $func_relative_path_tlibdir)
          # found an exact match
          func_relative_path_tcancelled=
          break
          ;;
        $func_relative_path_tlibdir*)
          # found a matching prefix
          func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir"
          func_relative_path_tcancelled=$func_stripname_result
          if test -z "$func_relative_path_result"; then
            func_relative_path_result=.
          fi
          break
          ;;
        *)
          func_dirname $func_relative_path_tlibdir
          func_relative_path_tlibdir=$func_dirname_result
          if test -z "$func_relative_path_tlibdir"; then
            # Have to descend all the way to the root!
            func_relative_path_result=../$func_relative_path_result
            func_relative_path_tcancelled=$func_relative_path_tbindir
            break
          fi
          func_relative_path_result=../$func_relative_path_result
          ;;
      esac
    done

    # Now calculate path; take care to avoid doubling-up slashes.
    func_stripname '' '/' "$func_relative_path_result"
    func_relative_path_result=$func_stripname_result
    func_stripname '/' '/' "$func_relative_path_tcancelled"
    if test -n "$func_stripname_result"; then
      func_append func_relative_path_result "/$func_stripname_result"
    fi

    # Normalisation. If bindir is libdir, return '.' else relative path.
    if test -n "$func_relative_path_result"; then
      func_stripname './' '' "$func_relative_path_result"
      func_relative_path_result=$func_stripname_result
    fi

    test -n "$func_relative_path_result" || func_relative_path_result=.

    :
}


# func_quote_for_eval ARG...
# --------------------------
# Aesthetically quote ARGs to be evaled later.
# This function returns two values:
#   i) func_quote_for_eval_result
#      double-quoted, suitable for a subsequent eval
#  ii) func_quote_for_eval_unquoted_result
#      has all characters that are still active within double
#      quotes backslashified.
func_quote_for_eval ()
{
    $debug_cmd

    func_quote_for_eval_unquoted_result=
    func_quote_for_eval_result=
    while test 0 -lt $#; do
      case $1 in
        *[\\\`\"\$]*)
	  _G_unquoted_arg=`printf '%s\n' "$1" |$SED "$sed_quote_subst"` ;;
        *)
          _G_unquoted_arg=$1 ;;
      esac
      if test -n "$func_quote_for_eval_unquoted_result"; then
	func_append func_quote_for_eval_unquoted_result " $_G_unquoted_arg"
      else
        func_append func_quote_for_eval_unquoted_result "$_G_unquoted_arg"
      fi

      case $_G_unquoted_arg in
        # Double-quote args containing shell metacharacters to delay
        # word splitting, command substitution and variable expansion
        # for a subsequent eval.
        # Many Bourne shells cannot handle close brackets correctly
        # in scan sets, so we specify it separately.
        *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
          _G_quoted_arg=\"$_G_unquoted_arg\"
          ;;
        *)
          _G_quoted_arg=$_G_unquoted_arg
	  ;;
      esac

      if test -n "$func_quote_for_eval_result"; then
	func_append func_quote_for_eval_result " $_G_quoted_arg"
      else
        func_append func_quote_for_eval_result "$_G_quoted_arg"
      fi
      shift
    done
}


# func_quote_for_expand ARG
# -------------------------
# Aesthetically quote ARG to be evaled later; same as above,
# but do not quote variable references.
func_quote_for_expand ()
{
    $debug_cmd

    case $1 in
      *[\\\`\"]*)
	_G_arg=`$ECHO "$1" | $SED \
	    -e "$sed_double_quote_subst" -e "$sed_double_backslash"` ;;
      *)
        _G_arg=$1 ;;
    esac

    case $_G_arg in
      # Double-quote args containing shell metacharacters to delay
      # word splitting and command substitution for a subsequent eval.
      # Many Bourne shells cannot handle close brackets correctly
      # in scan sets, so we specify it separately.
      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
        _G_arg=\"$_G_arg\"
        ;;
    esac

    func_quote_for_expand_result=$_G_arg
}


# func_stripname PREFIX SUFFIX NAME
# ---------------------------------
# strip PREFIX and SUFFIX from NAME, and store in func_stripname_result.
# PREFIX and SUFFIX must not contain globbing or regex special
# characters, hashes, percent signs, but SUFFIX may contain a leading
# dot (in which case that matches only a dot).
if test yes = "$_G_HAVE_XSI_OPS"; then
  eval 'func_stripname ()
  {
    $debug_cmd

    # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are
    # positional parameters, so assign one to ordinary variable first.
    func_stripname_result=$3
    func_stripname_result=${func_stripname_result#"$1"}
    func_stripname_result=${func_stripname_result%"$2"}
  }'
else
  func_stripname ()
  {
    $debug_cmd

    case $2 in
      .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;;
      *)  func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;;
    esac
  }
fi


# func_show_eval CMD [FAIL_EXP]
# -----------------------------
# Unless opt_quiet is true, then output CMD.  Then, if opt_dryrun is
# not true, evaluate CMD.  If the evaluation of CMD fails, and FAIL_EXP
# is given, then evaluate it.
func_show_eval ()
{
    $debug_cmd

    _G_cmd=$1
    _G_fail_exp=${2-':'}

    func_quote_for_expand "$_G_cmd"
    eval "func_notquiet $func_quote_for_expand_result"

    $opt_dry_run || {
      eval "$_G_cmd"
      _G_status=$?
      if test 0 -ne "$_G_status"; then
	eval "(exit $_G_status); $_G_fail_exp"
      fi
    }
}


# func_show_eval_locale CMD [FAIL_EXP]
# ------------------------------------
# Unless opt_quiet is true, then output CMD.  Then, if opt_dryrun is
# not true, evaluate CMD.  If the evaluation of CMD fails, and FAIL_EXP
# is given, then evaluate it.  Use the saved locale for evaluation.
func_show_eval_locale ()
{
    $debug_cmd

    _G_cmd=$1
    _G_fail_exp=${2-':'}

    $opt_quiet || {
      func_quote_for_expand "$_G_cmd"
      eval "func_echo $func_quote_for_expand_result"
    }

    $opt_dry_run || {
      eval "$_G_user_locale
	    $_G_cmd"
      _G_status=$?
      eval "$_G_safe_locale"
      if test 0 -ne "$_G_status"; then
	eval "(exit $_G_status); $_G_fail_exp"
      fi
    }
}


# func_tr_sh
# ----------
# Turn $1 into a string suitable for a shell variable name.
# Result is stored in $func_tr_sh_result.  All characters
# not in the set a-zA-Z0-9_ are replaced with '_'. Further,
# if $1 begins with a digit, a '_' is prepended as well.
func_tr_sh ()
{
    $debug_cmd

    case $1 in
    [0-9]* | *[!a-zA-Z0-9_]*)
      func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'`
      ;;
    * )
      func_tr_sh_result=$1
      ;;
    esac
}


# func_verbose ARG...
# -------------------
# Echo program name prefixed message in verbose mode only.
func_verbose ()
{
    $debug_cmd

    $opt_verbose && func_echo "$*"

    :
}


# func_warn_and_continue ARG...
# -----------------------------
# Echo program name prefixed warning message to standard error.
func_warn_and_continue ()
{
    $debug_cmd

    $require_term_colors

    func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2
}


# func_warning CATEGORY ARG...
# ----------------------------
# Echo program name prefixed warning message to standard error. Warning
# messages can be filtered according to CATEGORY, where this function
# elides messages where CATEGORY is not listed in the global variable
# 'opt_warning_types'.
func_warning ()
{
    $debug_cmd

    # CATEGORY must be in the warning_categories list!
    case " $warning_categories " in
      *" $1 "*) ;;
      *) func_internal_error "invalid warning category '$1'" ;;
    esac

    _G_category=$1
    shift

    case " $opt_warning_types " in
      *" $_G_category "*) $warning_func ${1+"$@"} ;;
    esac
}


# func_sort_ver VER1 VER2
# -----------------------
# 'sort -V' is not generally available.
# Note this deviates from the version comparison in automake
# in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a
# but this should suffice as we won't be specifying old
# version formats or redundant trailing .0 in bootstrap.conf.
# If we did want full compatibility then we should probably
# use m4_version_compare from autoconf.
func_sort_ver ()
{
    $debug_cmd

    printf '%s\n%s\n' "$1" "$2" \
      | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n
}

# func_lt_ver PREV CURR
# ---------------------
# Return true if PREV and CURR are in the correct order according to
# func_sort_ver, otherwise false.  Use it like this:
#
#  func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..."
func_lt_ver ()
{
    $debug_cmd

    test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q`
}


# Local variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC"
# time-stamp-time-zone: "UTC"
# End:
#! /bin/sh

# Set a version string for this script.
scriptversion=2014-01-07.03; # UTC

# A portable, pluggable option parser for Bourne shell.
# Written by Gary V. Vaughan, 2010

# Copyright (C) 2010-2015 Free Software Foundation, Inc.
# This is free software; see the source for copying conditions.  There is NO
# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program.  If not, see .

# Please report bugs or propose patches to gary@gnu.org.


## ------ ##
## Usage. ##
## ------ ##

# This file is a library for parsing options in your shell scripts along
# with assorted other useful supporting features that you can make use
# of too.
#
# For the simplest scripts you might need only:
#
#   #!/bin/sh
#   . relative/path/to/funclib.sh
#   . relative/path/to/options-parser
#   scriptversion=1.0
#   func_options ${1+"$@"}
#   eval set dummy "$func_options_result"; shift
#   ...rest of your script...
#
# In order for the '--version' option to work, you will need to have a
# suitably formatted comment like the one at the top of this file
# starting with '# Written by ' and ending with '# warranty; '.
#
# For '-h' and '--help' to work, you will also need a one line
# description of your script's purpose in a comment directly above the
# '# Written by ' line, like the one at the top of this file.
#
# The default options also support '--debug', which will turn on shell
# execution tracing (see the comment above debug_cmd below for another
# use), and '--verbose' and the func_verbose function to allow your script
# to display verbose messages only when your user has specified
# '--verbose'.
#
# After sourcing this file, you can plug processing for additional
# options by amending the variables from the 'Configuration' section
# below, and following the instructions in the 'Option parsing'
# section further down.

## -------------- ##
## Configuration. ##
## -------------- ##

# You should override these variables in your script after sourcing this
# file so that they reflect the customisations you have added to the
# option parser.

# The usage line for option parsing errors and the start of '-h' and
# '--help' output messages. You can embed shell variables for delayed
# expansion at the time the message is displayed, but you will need to
# quote other shell meta-characters carefully to prevent them being
# expanded when the contents are evaled.
usage='$progpath [OPTION]...'

# Short help message in response to '-h' and '--help'.  Add to this or
# override it after sourcing this library to reflect the full set of
# options your script accepts.
usage_message="\
       --debug        enable verbose shell tracing
   -W, --warnings=CATEGORY
                      report the warnings falling in CATEGORY [all]
   -v, --verbose      verbosely report processing
       --version      print version information and exit
   -h, --help         print short or long help message and exit
"

# Additional text appended to 'usage_message' in response to '--help'.
long_help_message="
Warning categories include:
       'all'          show all warnings
       'none'         turn off all the warnings
       'error'        warnings are treated as fatal errors"

# Help message printed before fatal option parsing errors.
fatal_help="Try '\$progname --help' for more information."



## ------------------------- ##
## Hook function management. ##
## ------------------------- ##

# This section contains functions for adding, removing, and running hooks
# to the main code.  A hook is just a named list of of function, that can
# be run in order later on.

# func_hookable FUNC_NAME
# -----------------------
# Declare that FUNC_NAME will run hooks added with
# 'func_add_hook FUNC_NAME ...'.
func_hookable ()
{
    $debug_cmd

    func_append hookable_fns " $1"
}


# func_add_hook FUNC_NAME HOOK_FUNC
# ---------------------------------
# Request that FUNC_NAME call HOOK_FUNC before it returns.  FUNC_NAME must
# first have been declared "hookable" by a call to 'func_hookable'.
func_add_hook ()
{
    $debug_cmd

    case " $hookable_fns " in
      *" $1 "*) ;;
      *) func_fatal_error "'$1' does not accept hook functions." ;;
    esac

    eval func_append ${1}_hooks '" $2"'
}


# func_remove_hook FUNC_NAME HOOK_FUNC
# ------------------------------------
# Remove HOOK_FUNC from the list of functions called by FUNC_NAME.
func_remove_hook ()
{
    $debug_cmd

    eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`'
}


# func_run_hooks FUNC_NAME [ARG]...
# ---------------------------------
# Run all hook functions registered to FUNC_NAME.
# It is assumed that the list of hook functions contains nothing more
# than a whitespace-delimited list of legal shell function names, and
# no effort is wasted trying to catch shell meta-characters or preserve
# whitespace.
func_run_hooks ()
{
    $debug_cmd

    case " $hookable_fns " in
      *" $1 "*) ;;
      *) func_fatal_error "'$1' does not support hook funcions.n" ;;
    esac

    eval _G_hook_fns=\$$1_hooks; shift

    for _G_hook in $_G_hook_fns; do
      eval $_G_hook '"$@"'

      # store returned options list back into positional
      # parameters for next 'cmd' execution.
      eval _G_hook_result=\$${_G_hook}_result
      eval set dummy "$_G_hook_result"; shift
    done

    func_quote_for_eval ${1+"$@"}
    func_run_hooks_result=$func_quote_for_eval_result
}



## --------------- ##
## Option parsing. ##
## --------------- ##

# In order to add your own option parsing hooks, you must accept the
# full positional parameter list in your hook function, remove any
# options that you action, and then pass back the remaining unprocessed
# options in '_result', escaped suitably for
# 'eval'.  Like this:
#
#    my_options_prep ()
#    {
#        $debug_cmd
#
#        # Extend the existing usage message.
#        usage_message=$usage_message'
#      -s, --silent       don'\''t print informational messages
#    '
#
#        func_quote_for_eval ${1+"$@"}
#        my_options_prep_result=$func_quote_for_eval_result
#    }
#    func_add_hook func_options_prep my_options_prep
#
#
#    my_silent_option ()
#    {
#        $debug_cmd
#
#        # Note that for efficiency, we parse as many options as we can
#        # recognise in a loop before passing the remainder back to the
#        # caller on the first unrecognised argument we encounter.
#        while test $# -gt 0; do
#          opt=$1; shift
#          case $opt in
#            --silent|-s) opt_silent=: ;;
#            # Separate non-argument short options:
#            -s*)         func_split_short_opt "$_G_opt"
#                         set dummy "$func_split_short_opt_name" \
#                             "-$func_split_short_opt_arg" ${1+"$@"}
#                         shift
#                         ;;
#            *)            set dummy "$_G_opt" "$*"; shift; break ;;
#          esac
#        done
#
#        func_quote_for_eval ${1+"$@"}
#        my_silent_option_result=$func_quote_for_eval_result
#    }
#    func_add_hook func_parse_options my_silent_option
#
#
#    my_option_validation ()
#    {
#        $debug_cmd
#
#        $opt_silent && $opt_verbose && func_fatal_help "\
#    '--silent' and '--verbose' options are mutually exclusive."
#
#        func_quote_for_eval ${1+"$@"}
#        my_option_validation_result=$func_quote_for_eval_result
#    }
#    func_add_hook func_validate_options my_option_validation
#
# You'll alse need to manually amend $usage_message to reflect the extra
# options you parse.  It's preferable to append if you can, so that
# multiple option parsing hooks can be added safely.


# func_options [ARG]...
# ---------------------
# All the functions called inside func_options are hookable. See the
# individual implementations for details.
func_hookable func_options
func_options ()
{
    $debug_cmd

    func_options_prep ${1+"$@"}
    eval func_parse_options \
        ${func_options_prep_result+"$func_options_prep_result"}
    eval func_validate_options \
        ${func_parse_options_result+"$func_parse_options_result"}

    eval func_run_hooks func_options \
        ${func_validate_options_result+"$func_validate_options_result"}

    # save modified positional parameters for caller
    func_options_result=$func_run_hooks_result
}


# func_options_prep [ARG]...
# --------------------------
# All initialisations required before starting the option parse loop.
# Note that when calling hook functions, we pass through the list of
# positional parameters.  If a hook function modifies that list, and
# needs to propogate that back to rest of this script, then the complete
# modified list must be put in 'func_run_hooks_result' before
# returning.
func_hookable func_options_prep
func_options_prep ()
{
    $debug_cmd

    # Option defaults:
    opt_verbose=false
    opt_warning_types=

    func_run_hooks func_options_prep ${1+"$@"}

    # save modified positional parameters for caller
    func_options_prep_result=$func_run_hooks_result
}


# func_parse_options [ARG]...
# ---------------------------
# The main option parsing loop.
func_hookable func_parse_options
func_parse_options ()
{
    $debug_cmd

    func_parse_options_result=

    # this just eases exit handling
    while test $# -gt 0; do
      # Defer to hook functions for initial option parsing, so they
      # get priority in the event of reusing an option name.
      func_run_hooks func_parse_options ${1+"$@"}

      # Adjust func_parse_options positional parameters to match
      eval set dummy "$func_run_hooks_result"; shift

      # Break out of the loop if we already parsed every option.
      test $# -gt 0 || break

      _G_opt=$1
      shift
      case $_G_opt in
        --debug|-x)   debug_cmd='set -x'
                      func_echo "enabling shell trace mode"
                      $debug_cmd
                      ;;

        --no-warnings|--no-warning|--no-warn)
                      set dummy --warnings none ${1+"$@"}
                      shift
		      ;;

        --warnings|--warning|-W)
                      test $# = 0 && func_missing_arg $_G_opt && break
                      case " $warning_categories $1" in
                        *" $1 "*)
                          # trailing space prevents matching last $1 above
                          func_append_uniq opt_warning_types " $1"
                          ;;
                        *all)
                          opt_warning_types=$warning_categories
                          ;;
                        *none)
                          opt_warning_types=none
                          warning_func=:
                          ;;
                        *error)
                          opt_warning_types=$warning_categories
                          warning_func=func_fatal_error
                          ;;
                        *)
                          func_fatal_error \
                             "unsupported warning category: '$1'"
                          ;;
                      esac
                      shift
                      ;;

        --verbose|-v) opt_verbose=: ;;
        --version)    func_version ;;
        -\?|-h)       func_usage ;;
        --help)       func_help ;;

	# Separate optargs to long options (plugins may need this):
	--*=*)        func_split_equals "$_G_opt"
	              set dummy "$func_split_equals_lhs" \
                          "$func_split_equals_rhs" ${1+"$@"}
                      shift
                      ;;

       # Separate optargs to short options:
        -W*)
                      func_split_short_opt "$_G_opt"
                      set dummy "$func_split_short_opt_name" \
                          "$func_split_short_opt_arg" ${1+"$@"}
                      shift
                      ;;

        # Separate non-argument short options:
        -\?*|-h*|-v*|-x*)
                      func_split_short_opt "$_G_opt"
                      set dummy "$func_split_short_opt_name" \
                          "-$func_split_short_opt_arg" ${1+"$@"}
                      shift
                      ;;

        --)           break ;;
        -*)           func_fatal_help "unrecognised option: '$_G_opt'" ;;
        *)            set dummy "$_G_opt" ${1+"$@"}; shift; break ;;
      esac
    done

    # save modified positional parameters for caller
    func_quote_for_eval ${1+"$@"}
    func_parse_options_result=$func_quote_for_eval_result
}


# func_validate_options [ARG]...
# ------------------------------
# Perform any sanity checks on option settings and/or unconsumed
# arguments.
func_hookable func_validate_options
func_validate_options ()
{
    $debug_cmd

    # Display all warnings if -W was not given.
    test -n "$opt_warning_types" || opt_warning_types=" $warning_categories"

    func_run_hooks func_validate_options ${1+"$@"}

    # Bail if the options were screwed!
    $exit_cmd $EXIT_FAILURE

    # save modified positional parameters for caller
    func_validate_options_result=$func_run_hooks_result
}



## ----------------- ##
## Helper functions. ##
## ----------------- ##

# This section contains the helper functions used by the rest of the
# hookable option parser framework in ascii-betical order.


# func_fatal_help ARG...
# ----------------------
# Echo program name prefixed message to standard error, followed by
# a help hint, and exit.
func_fatal_help ()
{
    $debug_cmd

    eval \$ECHO \""Usage: $usage"\"
    eval \$ECHO \""$fatal_help"\"
    func_error ${1+"$@"}
    exit $EXIT_FAILURE
}


# func_help
# ---------
# Echo long help message to standard output and exit.
func_help ()
{
    $debug_cmd

    func_usage_message
    $ECHO "$long_help_message"
    exit 0
}


# func_missing_arg ARGNAME
# ------------------------
# Echo program name prefixed message to standard error and set global
# exit_cmd.
func_missing_arg ()
{
    $debug_cmd

    func_error "Missing argument for '$1'."
    exit_cmd=exit
}


# func_split_equals STRING
# ------------------------
# Set func_split_equals_lhs and func_split_equals_rhs shell variables after
# splitting STRING at the '=' sign.
test -z "$_G_HAVE_XSI_OPS" \
    && (eval 'x=a/b/c;
      test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \
    && _G_HAVE_XSI_OPS=yes

if test yes = "$_G_HAVE_XSI_OPS"
then
  # This is an XSI compatible shell, allowing a faster implementation...
  eval 'func_split_equals ()
  {
      $debug_cmd

      func_split_equals_lhs=${1%%=*}
      func_split_equals_rhs=${1#*=}
      test "x$func_split_equals_lhs" = "x$1" \
        && func_split_equals_rhs=
  }'
else
  # ...otherwise fall back to using expr, which is often a shell builtin.
  func_split_equals ()
  {
      $debug_cmd

      func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'`
      func_split_equals_rhs=
      test "x$func_split_equals_lhs" = "x$1" \
        || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'`
  }
fi #func_split_equals


# func_split_short_opt SHORTOPT
# -----------------------------
# Set func_split_short_opt_name and func_split_short_opt_arg shell
# variables after splitting SHORTOPT after the 2nd character.
if test yes = "$_G_HAVE_XSI_OPS"
then
  # This is an XSI compatible shell, allowing a faster implementation...
  eval 'func_split_short_opt ()
  {
      $debug_cmd

      func_split_short_opt_arg=${1#??}
      func_split_short_opt_name=${1%"$func_split_short_opt_arg"}
  }'
else
  # ...otherwise fall back to using expr, which is often a shell builtin.
  func_split_short_opt ()
  {
      $debug_cmd

      func_split_short_opt_name=`expr "x$1" : 'x-\(.\)'`
      func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'`
  }
fi #func_split_short_opt


# func_usage
# ----------
# Echo short help message to standard output and exit.
func_usage ()
{
    $debug_cmd

    func_usage_message
    $ECHO "Run '$progname --help |${PAGER-more}' for full usage"
    exit 0
}


# func_usage_message
# ------------------
# Echo short help message to standard output.
func_usage_message ()
{
    $debug_cmd

    eval \$ECHO \""Usage: $usage"\"
    echo
    $SED -n 's|^# ||
        /^Written by/{
          x;p;x
        }
	h
	/^Written by/q' < "$progpath"
    echo
    eval \$ECHO \""$usage_message"\"
}


# func_version
# ------------
# Echo version message to standard output and exit.
func_version ()
{
    $debug_cmd

    printf '%s\n' "$progname $scriptversion"
    $SED -n '
        /(C)/!b go
        :more
        /\./!{
          N
          s|\n# | |
          b more
        }
        :go
        /^# Written by /,/# warranty; / {
          s|^# ||
          s|^# *$||
          s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2|
          p
        }
        /^# Written by / {
          s|^# ||
          p
        }
        /^warranty; /q' < "$progpath"

    exit $?
}


# Local variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC"
# time-stamp-time-zone: "UTC"
# End:

# Set a version string.
scriptversion='(GNU libtool) 2.4.6'


# func_echo ARG...
# ----------------
# Libtool also displays the current mode in messages, so override
# funclib.sh func_echo with this custom definition.
func_echo ()
{
    $debug_cmd

    _G_message=$*

    func_echo_IFS=$IFS
    IFS=$nl
    for _G_line in $_G_message; do
      IFS=$func_echo_IFS
      $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line"
    done
    IFS=$func_echo_IFS
}


# func_warning ARG...
# -------------------
# Libtool warnings are not categorized, so override funclib.sh
# func_warning with this simpler definition.
func_warning ()
{
    $debug_cmd

    $warning_func ${1+"$@"}
}


## ---------------- ##
## Options parsing. ##
## ---------------- ##

# Hook in the functions to make sure our own options are parsed during
# the option parsing loop.

usage='$progpath [OPTION]... [MODE-ARG]...'

# Short help message in response to '-h'.
usage_message="Options:
       --config             show all configuration variables
       --debug              enable verbose shell tracing
   -n, --dry-run            display commands without modifying any files
       --features           display basic configuration information and exit
       --mode=MODE          use operation mode MODE
       --no-warnings        equivalent to '-Wnone'
       --preserve-dup-deps  don't remove duplicate dependency libraries
       --quiet, --silent    don't print informational messages
       --tag=TAG            use configuration variables from tag TAG
   -v, --verbose            print more informational messages than default
       --version            print version information
   -W, --warnings=CATEGORY  report the warnings falling in CATEGORY [all]
   -h, --help, --help-all   print short, long, or detailed help message
"

# Additional text appended to 'usage_message' in response to '--help'.
func_help ()
{
    $debug_cmd

    func_usage_message
    $ECHO "$long_help_message

MODE must be one of the following:

       clean           remove files from the build directory
       compile         compile a source file into a libtool object
       execute         automatically set library path, then run a program
       finish          complete the installation of libtool libraries
       install         install libraries or executables
       link            create a library or an executable
       uninstall       remove libraries from an installed directory

MODE-ARGS vary depending on the MODE.  When passed as first option,
'--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that.
Try '$progname --help --mode=MODE' for a more detailed description of MODE.

When reporting a bug, please describe a test case to reproduce it and
include the following information:

       host-triplet:   $host
       shell:          $SHELL
       compiler:       $LTCC
       compiler flags: $LTCFLAGS
       linker:         $LD (gnu? $with_gnu_ld)
       version:        $progname (GNU libtool) 2.4.6
       automake:       `($AUTOMAKE --version) 2>/dev/null |$SED 1q`
       autoconf:       `($AUTOCONF --version) 2>/dev/null |$SED 1q`

Report bugs to .
GNU libtool home page: .
General help using GNU software: ."
    exit 0
}


# func_lo2o OBJECT-NAME
# ---------------------
# Transform OBJECT-NAME from a '.lo' suffix to the platform specific
# object suffix.

lo2o=s/\\.lo\$/.$objext/
o2lo=s/\\.$objext\$/.lo/

if test yes = "$_G_HAVE_XSI_OPS"; then
  eval 'func_lo2o ()
  {
    case $1 in
      *.lo) func_lo2o_result=${1%.lo}.$objext ;;
      *   ) func_lo2o_result=$1               ;;
    esac
  }'

  # func_xform LIBOBJ-OR-SOURCE
  # ---------------------------
  # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise)
  # suffix to a '.lo' libtool-object suffix.
  eval 'func_xform ()
  {
    func_xform_result=${1%.*}.lo
  }'
else
  # ...otherwise fall back to using sed.
  func_lo2o ()
  {
    func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"`
  }

  func_xform ()
  {
    func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'`
  }
fi


# func_fatal_configuration ARG...
# -------------------------------
# Echo program name prefixed message to standard error, followed by
# a configuration failure hint, and exit.
func_fatal_configuration ()
{
    func__fatal_error ${1+"$@"} \
      "See the $PACKAGE documentation for more information." \
      "Fatal configuration error."
}


# func_config
# -----------
# Display the configuration for all the tags in this script.
func_config ()
{
    re_begincf='^# ### BEGIN LIBTOOL'
    re_endcf='^# ### END LIBTOOL'

    # Default configuration.
    $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath"

    # Now print the configurations for the tags.
    for tagname in $taglist; do
      $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath"
    done

    exit $?
}


# func_features
# -------------
# Display the features supported by this script.
func_features ()
{
    echo "host: $host"
    if test yes = "$build_libtool_libs"; then
      echo "enable shared libraries"
    else
      echo "disable shared libraries"
    fi
    if test yes = "$build_old_libs"; then
      echo "enable static libraries"
    else
      echo "disable static libraries"
    fi

    exit $?
}


# func_enable_tag TAGNAME
# -----------------------
# Verify that TAGNAME is valid, and either flag an error and exit, or
# enable the TAGNAME tag.  We also add TAGNAME to the global $taglist
# variable here.
func_enable_tag ()
{
    # Global variable:
    tagname=$1

    re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$"
    re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$"
    sed_extractcf=/$re_begincf/,/$re_endcf/p

    # Validate tagname.
    case $tagname in
      *[!-_A-Za-z0-9,/]*)
        func_fatal_error "invalid tag name: $tagname"
        ;;
    esac

    # Don't test for the "default" C tag, as we know it's
    # there but not specially marked.
    case $tagname in
        CC) ;;
    *)
        if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then
	  taglist="$taglist $tagname"

	  # Evaluate the configuration.  Be careful to quote the path
	  # and the sed script, to avoid splitting on whitespace, but
	  # also don't use non-portable quotes within backquotes within
	  # quotes we have to do it in 2 steps:
	  extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"`
	  eval "$extractedcf"
        else
	  func_error "ignoring unknown tag $tagname"
        fi
        ;;
    esac
}


# func_check_version_match
# ------------------------
# Ensure that we are using m4 macros, and libtool script from the same
# release of libtool.
func_check_version_match ()
{
    if test "$package_revision" != "$macro_revision"; then
      if test "$VERSION" != "$macro_version"; then
        if test -z "$macro_version"; then
          cat >&2 <<_LT_EOF
$progname: Version mismatch error.  This is $PACKAGE $VERSION, but the
$progname: definition of this LT_INIT comes from an older release.
$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
$progname: and run autoconf again.
_LT_EOF
        else
          cat >&2 <<_LT_EOF
$progname: Version mismatch error.  This is $PACKAGE $VERSION, but the
$progname: definition of this LT_INIT comes from $PACKAGE $macro_version.
$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
$progname: and run autoconf again.
_LT_EOF
        fi
      else
        cat >&2 <<_LT_EOF
$progname: Version mismatch error.  This is $PACKAGE $VERSION, revision $package_revision,
$progname: but the definition of this LT_INIT comes from revision $macro_revision.
$progname: You should recreate aclocal.m4 with macros from revision $package_revision
$progname: of $PACKAGE $VERSION and run autoconf again.
_LT_EOF
      fi

      exit $EXIT_MISMATCH
    fi
}


# libtool_options_prep [ARG]...
# -----------------------------
# Preparation for options parsed by libtool.
libtool_options_prep ()
{
    $debug_mode

    # Option defaults:
    opt_config=false
    opt_dlopen=
    opt_dry_run=false
    opt_help=false
    opt_mode=
    opt_preserve_dup_deps=false
    opt_quiet=false

    nonopt=
    preserve_args=

    # Shorthand for --mode=foo, only valid as the first argument
    case $1 in
    clean|clea|cle|cl)
      shift; set dummy --mode clean ${1+"$@"}; shift
      ;;
    compile|compil|compi|comp|com|co|c)
      shift; set dummy --mode compile ${1+"$@"}; shift
      ;;
    execute|execut|execu|exec|exe|ex|e)
      shift; set dummy --mode execute ${1+"$@"}; shift
      ;;
    finish|finis|fini|fin|fi|f)
      shift; set dummy --mode finish ${1+"$@"}; shift
      ;;
    install|instal|insta|inst|ins|in|i)
      shift; set dummy --mode install ${1+"$@"}; shift
      ;;
    link|lin|li|l)
      shift; set dummy --mode link ${1+"$@"}; shift
      ;;
    uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u)
      shift; set dummy --mode uninstall ${1+"$@"}; shift
      ;;
    esac

    # Pass back the list of options.
    func_quote_for_eval ${1+"$@"}
    libtool_options_prep_result=$func_quote_for_eval_result
}
func_add_hook func_options_prep libtool_options_prep


# libtool_parse_options [ARG]...
# ---------------------------------
# Provide handling for libtool specific options.
libtool_parse_options ()
{
    $debug_cmd

    # Perform our own loop to consume as many options as possible in
    # each iteration.
    while test $# -gt 0; do
      _G_opt=$1
      shift
      case $_G_opt in
        --dry-run|--dryrun|-n)
                        opt_dry_run=:
                        ;;

        --config)       func_config ;;

        --dlopen|-dlopen)
                        opt_dlopen="${opt_dlopen+$opt_dlopen
}$1"
                        shift
                        ;;

        --preserve-dup-deps)
                        opt_preserve_dup_deps=: ;;

        --features)     func_features ;;

        --finish)       set dummy --mode finish ${1+"$@"}; shift ;;

        --help)         opt_help=: ;;

        --help-all)     opt_help=': help-all' ;;

        --mode)         test $# = 0 && func_missing_arg $_G_opt && break
                        opt_mode=$1
                        case $1 in
                          # Valid mode arguments:
                          clean|compile|execute|finish|install|link|relink|uninstall) ;;

                          # Catch anything else as an error
                          *) func_error "invalid argument for $_G_opt"
                             exit_cmd=exit
                             break
                             ;;
                        esac
                        shift
                        ;;

        --no-silent|--no-quiet)
                        opt_quiet=false
                        func_append preserve_args " $_G_opt"
                        ;;

        --no-warnings|--no-warning|--no-warn)
                        opt_warning=false
                        func_append preserve_args " $_G_opt"
                        ;;

        --no-verbose)
                        opt_verbose=false
                        func_append preserve_args " $_G_opt"
                        ;;

        --silent|--quiet)
                        opt_quiet=:
                        opt_verbose=false
                        func_append preserve_args " $_G_opt"
                        ;;

        --tag)          test $# = 0 && func_missing_arg $_G_opt && break
                        opt_tag=$1
                        func_append preserve_args " $_G_opt $1"
                        func_enable_tag "$1"
                        shift
                        ;;

        --verbose|-v)   opt_quiet=false
                        opt_verbose=:
                        func_append preserve_args " $_G_opt"
                        ;;

	# An option not handled by this hook function:
        *)		set dummy "$_G_opt" ${1+"$@"};	shift; break  ;;
      esac
    done


    # save modified positional parameters for caller
    func_quote_for_eval ${1+"$@"}
    libtool_parse_options_result=$func_quote_for_eval_result
}
func_add_hook func_parse_options libtool_parse_options



# libtool_validate_options [ARG]...
# ---------------------------------
# Perform any sanity checks on option settings and/or unconsumed
# arguments.
libtool_validate_options ()
{
    # save first non-option argument
    if test 0 -lt $#; then
      nonopt=$1
      shift
    fi

    # preserve --debug
    test : = "$debug_cmd" || func_append preserve_args " --debug"

    case $host in
      # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452
      # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788
      *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*)
        # don't eliminate duplications in $postdeps and $predeps
        opt_duplicate_compiler_generated_deps=:
        ;;
      *)
        opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps
        ;;
    esac

    $opt_help || {
      # Sanity checks first:
      func_check_version_match

      test yes != "$build_libtool_libs" \
        && test yes != "$build_old_libs" \
        && func_fatal_configuration "not configured to build any kind of library"

      # Darwin sucks
      eval std_shrext=\"$shrext_cmds\"

      # Only execute mode is allowed to have -dlopen flags.
      if test -n "$opt_dlopen" && test execute != "$opt_mode"; then
        func_error "unrecognized option '-dlopen'"
        $ECHO "$help" 1>&2
        exit $EXIT_FAILURE
      fi

      # Change the help message to a mode-specific one.
      generic_help=$help
      help="Try '$progname --help --mode=$opt_mode' for more information."
    }

    # Pass back the unparsed argument list
    func_quote_for_eval ${1+"$@"}
    libtool_validate_options_result=$func_quote_for_eval_result
}
func_add_hook func_validate_options libtool_validate_options


# Process options as early as possible so that --help and --version
# can return quickly.
func_options ${1+"$@"}
eval set dummy "$func_options_result"; shift



## ----------- ##
##    Main.    ##
## ----------- ##

magic='%%%MAGIC variable%%%'
magic_exe='%%%MAGIC EXE variable%%%'

# Global variables.
extracted_archives=
extracted_serial=0

# If this variable is set in any of the actions, the command in it
# will be execed at the end.  This prevents here-documents from being
# left over by shells.
exec_cmd=


# A function that is used when there is no print builtin or printf.
func_fallback_echo ()
{
  eval 'cat <<_LTECHO_EOF
$1
_LTECHO_EOF'
}

# func_generated_by_libtool
# True iff stdin has been generated by Libtool. This function is only
# a basic sanity check; it will hardly flush out determined imposters.
func_generated_by_libtool_p ()
{
  $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1
}

# func_lalib_p file
# True iff FILE is a libtool '.la' library or '.lo' object file.
# This function is only a basic sanity check; it will hardly flush out
# determined imposters.
func_lalib_p ()
{
    test -f "$1" &&
      $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p
}

# func_lalib_unsafe_p file
# True iff FILE is a libtool '.la' library or '.lo' object file.
# This function implements the same check as func_lalib_p without
# resorting to external programs.  To this end, it redirects stdin and
# closes it afterwards, without saving the original file descriptor.
# As a safety measure, use it only where a negative result would be
# fatal anyway.  Works if 'file' does not exist.
func_lalib_unsafe_p ()
{
    lalib_p=no
    if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then
	for lalib_p_l in 1 2 3 4
	do
	    read lalib_p_line
	    case $lalib_p_line in
		\#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;;
	    esac
	done
	exec 0<&5 5<&-
    fi
    test yes = "$lalib_p"
}

# func_ltwrapper_script_p file
# True iff FILE is a libtool wrapper script
# This function is only a basic sanity check; it will hardly flush out
# determined imposters.
func_ltwrapper_script_p ()
{
    test -f "$1" &&
      $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p
}

# func_ltwrapper_executable_p file
# True iff FILE is a libtool wrapper executable
# This function is only a basic sanity check; it will hardly flush out
# determined imposters.
func_ltwrapper_executable_p ()
{
    func_ltwrapper_exec_suffix=
    case $1 in
    *.exe) ;;
    *) func_ltwrapper_exec_suffix=.exe ;;
    esac
    $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1
}

# func_ltwrapper_scriptname file
# Assumes file is an ltwrapper_executable
# uses $file to determine the appropriate filename for a
# temporary ltwrapper_script.
func_ltwrapper_scriptname ()
{
    func_dirname_and_basename "$1" "" "."
    func_stripname '' '.exe' "$func_basename_result"
    func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper
}

# func_ltwrapper_p file
# True iff FILE is a libtool wrapper script or wrapper executable
# This function is only a basic sanity check; it will hardly flush out
# determined imposters.
func_ltwrapper_p ()
{
    func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1"
}


# func_execute_cmds commands fail_cmd
# Execute tilde-delimited COMMANDS.
# If FAIL_CMD is given, eval that upon failure.
# FAIL_CMD may read-access the current command in variable CMD!
func_execute_cmds ()
{
    $debug_cmd

    save_ifs=$IFS; IFS='~'
    for cmd in $1; do
      IFS=$sp$nl
      eval cmd=\"$cmd\"
      IFS=$save_ifs
      func_show_eval "$cmd" "${2-:}"
    done
    IFS=$save_ifs
}


# func_source file
# Source FILE, adding directory component if necessary.
# Note that it is not necessary on cygwin/mingw to append a dot to
# FILE even if both FILE and FILE.exe exist: automatic-append-.exe
# behavior happens only for exec(3), not for open(2)!  Also, sourcing
# 'FILE.' does not work on cygwin managed mounts.
func_source ()
{
    $debug_cmd

    case $1 in
    */* | *\\*)	. "$1" ;;
    *)		. "./$1" ;;
    esac
}


# func_resolve_sysroot PATH
# Replace a leading = in PATH with a sysroot.  Store the result into
# func_resolve_sysroot_result
func_resolve_sysroot ()
{
  func_resolve_sysroot_result=$1
  case $func_resolve_sysroot_result in
  =*)
    func_stripname '=' '' "$func_resolve_sysroot_result"
    func_resolve_sysroot_result=$lt_sysroot$func_stripname_result
    ;;
  esac
}

# func_replace_sysroot PATH
# If PATH begins with the sysroot, replace it with = and
# store the result into func_replace_sysroot_result.
func_replace_sysroot ()
{
  case $lt_sysroot:$1 in
  ?*:"$lt_sysroot"*)
    func_stripname "$lt_sysroot" '' "$1"
    func_replace_sysroot_result='='$func_stripname_result
    ;;
  *)
    # Including no sysroot.
    func_replace_sysroot_result=$1
    ;;
  esac
}

# func_infer_tag arg
# Infer tagged configuration to use if any are available and
# if one wasn't chosen via the "--tag" command line option.
# Only attempt this if the compiler in the base compile
# command doesn't match the default compiler.
# arg is usually of the form 'gcc ...'
func_infer_tag ()
{
    $debug_cmd

    if test -n "$available_tags" && test -z "$tagname"; then
      CC_quoted=
      for arg in $CC; do
	func_append_quoted CC_quoted "$arg"
      done
      CC_expanded=`func_echo_all $CC`
      CC_quoted_expanded=`func_echo_all $CC_quoted`
      case $@ in
      # Blanks in the command may have been stripped by the calling shell,
      # but not from the CC environment variable when configure was run.
      " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \
      " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;;
      # Blanks at the start of $base_compile will cause this to fail
      # if we don't check for them as well.
      *)
	for z in $available_tags; do
	  if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then
	    # Evaluate the configuration.
	    eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`"
	    CC_quoted=
	    for arg in $CC; do
	      # Double-quote args containing other shell metacharacters.
	      func_append_quoted CC_quoted "$arg"
	    done
	    CC_expanded=`func_echo_all $CC`
	    CC_quoted_expanded=`func_echo_all $CC_quoted`
	    case "$@ " in
	    " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \
	    " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*)
	      # The compiler in the base compile command matches
	      # the one in the tagged configuration.
	      # Assume this is the tagged configuration we want.
	      tagname=$z
	      break
	      ;;
	    esac
	  fi
	done
	# If $tagname still isn't set, then no tagged configuration
	# was found and let the user know that the "--tag" command
	# line option must be used.
	if test -z "$tagname"; then
	  func_echo "unable to infer tagged configuration"
	  func_fatal_error "specify a tag with '--tag'"
#	else
#	  func_verbose "using $tagname tagged configuration"
	fi
	;;
      esac
    fi
}



# func_write_libtool_object output_name pic_name nonpic_name
# Create a libtool object file (analogous to a ".la" file),
# but don't create it if we're doing a dry run.
func_write_libtool_object ()
{
    write_libobj=$1
    if test yes = "$build_libtool_libs"; then
      write_lobj=\'$2\'
    else
      write_lobj=none
    fi

    if test yes = "$build_old_libs"; then
      write_oldobj=\'$3\'
    else
      write_oldobj=none
    fi

    $opt_dry_run || {
      cat >${write_libobj}T </dev/null`
    if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then
      func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" |
        $SED -e "$sed_naive_backslashify"`
    else
      func_convert_core_file_wine_to_w32_result=
    fi
  fi
}
# end: func_convert_core_file_wine_to_w32


# func_convert_core_path_wine_to_w32 ARG
# Helper function used by path conversion functions when $build is *nix, and
# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly
# configured wine environment available, with the winepath program in $build's
# $PATH. Assumes ARG has no leading or trailing path separator characters.
#
# ARG is path to be converted from $build format to win32.
# Result is available in $func_convert_core_path_wine_to_w32_result.
# Unconvertible file (directory) names in ARG are skipped; if no directory names
# are convertible, then the result may be empty.
func_convert_core_path_wine_to_w32 ()
{
  $debug_cmd

  # unfortunately, winepath doesn't convert paths, only file names
  func_convert_core_path_wine_to_w32_result=
  if test -n "$1"; then
    oldIFS=$IFS
    IFS=:
    for func_convert_core_path_wine_to_w32_f in $1; do
      IFS=$oldIFS
      func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f"
      if test -n "$func_convert_core_file_wine_to_w32_result"; then
        if test -z "$func_convert_core_path_wine_to_w32_result"; then
          func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result
        else
          func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result"
        fi
      fi
    done
    IFS=$oldIFS
  fi
}
# end: func_convert_core_path_wine_to_w32


# func_cygpath ARGS...
# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when
# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2)
# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or
# (2), returns the Cygwin file name or path in func_cygpath_result (input
# file name or path is assumed to be in w32 format, as previously converted
# from $build's *nix or MSYS format). In case (3), returns the w32 file name
# or path in func_cygpath_result (input file name or path is assumed to be in
# Cygwin format). Returns an empty string on error.
#
# ARGS are passed to cygpath, with the last one being the file name or path to
# be converted.
#
# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH
# environment variable; do not put it in $PATH.
func_cygpath ()
{
  $debug_cmd

  if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then
    func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null`
    if test "$?" -ne 0; then
      # on failure, ensure result is empty
      func_cygpath_result=
    fi
  else
    func_cygpath_result=
    func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'"
  fi
}
#end: func_cygpath


# func_convert_core_msys_to_w32 ARG
# Convert file name or path ARG from MSYS format to w32 format.  Return
# result in func_convert_core_msys_to_w32_result.
func_convert_core_msys_to_w32 ()
{
  $debug_cmd

  # awkward: cmd appends spaces to result
  func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null |
    $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"`
}
#end: func_convert_core_msys_to_w32


# func_convert_file_check ARG1 ARG2
# Verify that ARG1 (a file name in $build format) was converted to $host
# format in ARG2. Otherwise, emit an error message, but continue (resetting
# func_to_host_file_result to ARG1).
func_convert_file_check ()
{
  $debug_cmd

  if test -z "$2" && test -n "$1"; then
    func_error "Could not determine host file name corresponding to"
    func_error "  '$1'"
    func_error "Continuing, but uninstalled executables may not work."
    # Fallback:
    func_to_host_file_result=$1
  fi
}
# end func_convert_file_check


# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH
# Verify that FROM_PATH (a path in $build format) was converted to $host
# format in TO_PATH. Otherwise, emit an error message, but continue, resetting
# func_to_host_file_result to a simplistic fallback value (see below).
func_convert_path_check ()
{
  $debug_cmd

  if test -z "$4" && test -n "$3"; then
    func_error "Could not determine the host path corresponding to"
    func_error "  '$3'"
    func_error "Continuing, but uninstalled executables may not work."
    # Fallback.  This is a deliberately simplistic "conversion" and
    # should not be "improved".  See libtool.info.
    if test "x$1" != "x$2"; then
      lt_replace_pathsep_chars="s|$1|$2|g"
      func_to_host_path_result=`echo "$3" |
        $SED -e "$lt_replace_pathsep_chars"`
    else
      func_to_host_path_result=$3
    fi
  fi
}
# end func_convert_path_check


# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG
# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT
# and appending REPL if ORIG matches BACKPAT.
func_convert_path_front_back_pathsep ()
{
  $debug_cmd

  case $4 in
  $1 ) func_to_host_path_result=$3$func_to_host_path_result
    ;;
  esac
  case $4 in
  $2 ) func_append func_to_host_path_result "$3"
    ;;
  esac
}
# end func_convert_path_front_back_pathsep


##################################################
# $build to $host FILE NAME CONVERSION FUNCTIONS #
##################################################
# invoked via '$to_host_file_cmd ARG'
#
# In each case, ARG is the path to be converted from $build to $host format.
# Result will be available in $func_to_host_file_result.


# func_to_host_file ARG
# Converts the file name ARG from $build format to $host format. Return result
# in func_to_host_file_result.
func_to_host_file ()
{
  $debug_cmd

  $to_host_file_cmd "$1"
}
# end func_to_host_file


# func_to_tool_file ARG LAZY
# converts the file name ARG from $build format to toolchain format. Return
# result in func_to_tool_file_result.  If the conversion in use is listed
# in (the comma separated) LAZY, no conversion takes place.
func_to_tool_file ()
{
  $debug_cmd

  case ,$2, in
    *,"$to_tool_file_cmd",*)
      func_to_tool_file_result=$1
      ;;
    *)
      $to_tool_file_cmd "$1"
      func_to_tool_file_result=$func_to_host_file_result
      ;;
  esac
}
# end func_to_tool_file


# func_convert_file_noop ARG
# Copy ARG to func_to_host_file_result.
func_convert_file_noop ()
{
  func_to_host_file_result=$1
}
# end func_convert_file_noop


# func_convert_file_msys_to_w32 ARG
# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic
# conversion to w32 is not available inside the cwrapper.  Returns result in
# func_to_host_file_result.
func_convert_file_msys_to_w32 ()
{
  $debug_cmd

  func_to_host_file_result=$1
  if test -n "$1"; then
    func_convert_core_msys_to_w32 "$1"
    func_to_host_file_result=$func_convert_core_msys_to_w32_result
  fi
  func_convert_file_check "$1" "$func_to_host_file_result"
}
# end func_convert_file_msys_to_w32


# func_convert_file_cygwin_to_w32 ARG
# Convert file name ARG from Cygwin to w32 format.  Returns result in
# func_to_host_file_result.
func_convert_file_cygwin_to_w32 ()
{
  $debug_cmd

  func_to_host_file_result=$1
  if test -n "$1"; then
    # because $build is cygwin, we call "the" cygpath in $PATH; no need to use
    # LT_CYGPATH in this case.
    func_to_host_file_result=`cygpath -m "$1"`
  fi
  func_convert_file_check "$1" "$func_to_host_file_result"
}
# end func_convert_file_cygwin_to_w32


# func_convert_file_nix_to_w32 ARG
# Convert file name ARG from *nix to w32 format.  Requires a wine environment
# and a working winepath. Returns result in func_to_host_file_result.
func_convert_file_nix_to_w32 ()
{
  $debug_cmd

  func_to_host_file_result=$1
  if test -n "$1"; then
    func_convert_core_file_wine_to_w32 "$1"
    func_to_host_file_result=$func_convert_core_file_wine_to_w32_result
  fi
  func_convert_file_check "$1" "$func_to_host_file_result"
}
# end func_convert_file_nix_to_w32


# func_convert_file_msys_to_cygwin ARG
# Convert file name ARG from MSYS to Cygwin format.  Requires LT_CYGPATH set.
# Returns result in func_to_host_file_result.
func_convert_file_msys_to_cygwin ()
{
  $debug_cmd

  func_to_host_file_result=$1
  if test -n "$1"; then
    func_convert_core_msys_to_w32 "$1"
    func_cygpath -u "$func_convert_core_msys_to_w32_result"
    func_to_host_file_result=$func_cygpath_result
  fi
  func_convert_file_check "$1" "$func_to_host_file_result"
}
# end func_convert_file_msys_to_cygwin


# func_convert_file_nix_to_cygwin ARG
# Convert file name ARG from *nix to Cygwin format.  Requires Cygwin installed
# in a wine environment, working winepath, and LT_CYGPATH set.  Returns result
# in func_to_host_file_result.
func_convert_file_nix_to_cygwin ()
{
  $debug_cmd

  func_to_host_file_result=$1
  if test -n "$1"; then
    # convert from *nix to w32, then use cygpath to convert from w32 to cygwin.
    func_convert_core_file_wine_to_w32 "$1"
    func_cygpath -u "$func_convert_core_file_wine_to_w32_result"
    func_to_host_file_result=$func_cygpath_result
  fi
  func_convert_file_check "$1" "$func_to_host_file_result"
}
# end func_convert_file_nix_to_cygwin


#############################################
# $build to $host PATH CONVERSION FUNCTIONS #
#############################################
# invoked via '$to_host_path_cmd ARG'
#
# In each case, ARG is the path to be converted from $build to $host format.
# The result will be available in $func_to_host_path_result.
#
# Path separators are also converted from $build format to $host format.  If
# ARG begins or ends with a path separator character, it is preserved (but
# converted to $host format) on output.
#
# All path conversion functions are named using the following convention:
#   file name conversion function    : func_convert_file_X_to_Y ()
#   path conversion function         : func_convert_path_X_to_Y ()
# where, for any given $build/$host combination the 'X_to_Y' value is the
# same.  If conversion functions are added for new $build/$host combinations,
# the two new functions must follow this pattern, or func_init_to_host_path_cmd
# will break.


# func_init_to_host_path_cmd
# Ensures that function "pointer" variable $to_host_path_cmd is set to the
# appropriate value, based on the value of $to_host_file_cmd.
to_host_path_cmd=
func_init_to_host_path_cmd ()
{
  $debug_cmd

  if test -z "$to_host_path_cmd"; then
    func_stripname 'func_convert_file_' '' "$to_host_file_cmd"
    to_host_path_cmd=func_convert_path_$func_stripname_result
  fi
}


# func_to_host_path ARG
# Converts the path ARG from $build format to $host format. Return result
# in func_to_host_path_result.
func_to_host_path ()
{
  $debug_cmd

  func_init_to_host_path_cmd
  $to_host_path_cmd "$1"
}
# end func_to_host_path


# func_convert_path_noop ARG
# Copy ARG to func_to_host_path_result.
func_convert_path_noop ()
{
  func_to_host_path_result=$1
}
# end func_convert_path_noop


# func_convert_path_msys_to_w32 ARG
# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic
# conversion to w32 is not available inside the cwrapper.  Returns result in
# func_to_host_path_result.
func_convert_path_msys_to_w32 ()
{
  $debug_cmd

  func_to_host_path_result=$1
  if test -n "$1"; then
    # Remove leading and trailing path separator characters from ARG.  MSYS
    # behavior is inconsistent here; cygpath turns them into '.;' and ';.';
    # and winepath ignores them completely.
    func_stripname : : "$1"
    func_to_host_path_tmp1=$func_stripname_result
    func_convert_core_msys_to_w32 "$func_to_host_path_tmp1"
    func_to_host_path_result=$func_convert_core_msys_to_w32_result
    func_convert_path_check : ";" \
      "$func_to_host_path_tmp1" "$func_to_host_path_result"
    func_convert_path_front_back_pathsep ":*" "*:" ";" "$1"
  fi
}
# end func_convert_path_msys_to_w32


# func_convert_path_cygwin_to_w32 ARG
# Convert path ARG from Cygwin to w32 format.  Returns result in
# func_to_host_file_result.
func_convert_path_cygwin_to_w32 ()
{
  $debug_cmd

  func_to_host_path_result=$1
  if test -n "$1"; then
    # See func_convert_path_msys_to_w32:
    func_stripname : : "$1"
    func_to_host_path_tmp1=$func_stripname_result
    func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"`
    func_convert_path_check : ";" \
      "$func_to_host_path_tmp1" "$func_to_host_path_result"
    func_convert_path_front_back_pathsep ":*" "*:" ";" "$1"
  fi
}
# end func_convert_path_cygwin_to_w32


# func_convert_path_nix_to_w32 ARG
# Convert path ARG from *nix to w32 format.  Requires a wine environment and
# a working winepath.  Returns result in func_to_host_file_result.
func_convert_path_nix_to_w32 ()
{
  $debug_cmd

  func_to_host_path_result=$1
  if test -n "$1"; then
    # See func_convert_path_msys_to_w32:
    func_stripname : : "$1"
    func_to_host_path_tmp1=$func_stripname_result
    func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1"
    func_to_host_path_result=$func_convert_core_path_wine_to_w32_result
    func_convert_path_check : ";" \
      "$func_to_host_path_tmp1" "$func_to_host_path_result"
    func_convert_path_front_back_pathsep ":*" "*:" ";" "$1"
  fi
}
# end func_convert_path_nix_to_w32


# func_convert_path_msys_to_cygwin ARG
# Convert path ARG from MSYS to Cygwin format.  Requires LT_CYGPATH set.
# Returns result in func_to_host_file_result.
func_convert_path_msys_to_cygwin ()
{
  $debug_cmd

  func_to_host_path_result=$1
  if test -n "$1"; then
    # See func_convert_path_msys_to_w32:
    func_stripname : : "$1"
    func_to_host_path_tmp1=$func_stripname_result
    func_convert_core_msys_to_w32 "$func_to_host_path_tmp1"
    func_cygpath -u -p "$func_convert_core_msys_to_w32_result"
    func_to_host_path_result=$func_cygpath_result
    func_convert_path_check : : \
      "$func_to_host_path_tmp1" "$func_to_host_path_result"
    func_convert_path_front_back_pathsep ":*" "*:" : "$1"
  fi
}
# end func_convert_path_msys_to_cygwin


# func_convert_path_nix_to_cygwin ARG
# Convert path ARG from *nix to Cygwin format.  Requires Cygwin installed in a
# a wine environment, working winepath, and LT_CYGPATH set.  Returns result in
# func_to_host_file_result.
func_convert_path_nix_to_cygwin ()
{
  $debug_cmd

  func_to_host_path_result=$1
  if test -n "$1"; then
    # Remove leading and trailing path separator characters from
    # ARG. msys behavior is inconsistent here, cygpath turns them
    # into '.;' and ';.', and winepath ignores them completely.
    func_stripname : : "$1"
    func_to_host_path_tmp1=$func_stripname_result
    func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1"
    func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result"
    func_to_host_path_result=$func_cygpath_result
    func_convert_path_check : : \
      "$func_to_host_path_tmp1" "$func_to_host_path_result"
    func_convert_path_front_back_pathsep ":*" "*:" : "$1"
  fi
}
# end func_convert_path_nix_to_cygwin


# func_dll_def_p FILE
# True iff FILE is a Windows DLL '.def' file.
# Keep in sync with _LT_DLL_DEF_P in libtool.m4
func_dll_def_p ()
{
  $debug_cmd

  func_dll_def_p_tmp=`$SED -n \
    -e 's/^[	 ]*//' \
    -e '/^\(;.*\)*$/d' \
    -e 's/^\(EXPORTS\|LIBRARY\)\([	 ].*\)*$/DEF/p' \
    -e q \
    "$1"`
  test DEF = "$func_dll_def_p_tmp"
}


# func_mode_compile arg...
func_mode_compile ()
{
    $debug_cmd

    # Get the compilation command and the source file.
    base_compile=
    srcfile=$nonopt  #  always keep a non-empty value in "srcfile"
    suppress_opt=yes
    suppress_output=
    arg_mode=normal
    libobj=
    later=
    pie_flag=

    for arg
    do
      case $arg_mode in
      arg  )
	# do not "continue".  Instead, add this to base_compile
	lastarg=$arg
	arg_mode=normal
	;;

      target )
	libobj=$arg
	arg_mode=normal
	continue
	;;

      normal )
	# Accept any command-line options.
	case $arg in
	-o)
	  test -n "$libobj" && \
	    func_fatal_error "you cannot specify '-o' more than once"
	  arg_mode=target
	  continue
	  ;;

	-pie | -fpie | -fPIE)
          func_append pie_flag " $arg"
	  continue
	  ;;

	-shared | -static | -prefer-pic | -prefer-non-pic)
	  func_append later " $arg"
	  continue
	  ;;

	-no-suppress)
	  suppress_opt=no
	  continue
	  ;;

	-Xcompiler)
	  arg_mode=arg  #  the next one goes into the "base_compile" arg list
	  continue      #  The current "srcfile" will either be retained or
	  ;;            #  replaced later.  I would guess that would be a bug.

	-Wc,*)
	  func_stripname '-Wc,' '' "$arg"
	  args=$func_stripname_result
	  lastarg=
	  save_ifs=$IFS; IFS=,
	  for arg in $args; do
	    IFS=$save_ifs
	    func_append_quoted lastarg "$arg"
	  done
	  IFS=$save_ifs
	  func_stripname ' ' '' "$lastarg"
	  lastarg=$func_stripname_result

	  # Add the arguments to base_compile.
	  func_append base_compile " $lastarg"
	  continue
	  ;;

	*)
	  # Accept the current argument as the source file.
	  # The previous "srcfile" becomes the current argument.
	  #
	  lastarg=$srcfile
	  srcfile=$arg
	  ;;
	esac  #  case $arg
	;;
      esac    #  case $arg_mode

      # Aesthetically quote the previous argument.
      func_append_quoted base_compile "$lastarg"
    done # for arg

    case $arg_mode in
    arg)
      func_fatal_error "you must specify an argument for -Xcompile"
      ;;
    target)
      func_fatal_error "you must specify a target with '-o'"
      ;;
    *)
      # Get the name of the library object.
      test -z "$libobj" && {
	func_basename "$srcfile"
	libobj=$func_basename_result
      }
      ;;
    esac

    # Recognize several different file suffixes.
    # If the user specifies -o file.o, it is replaced with file.lo
    case $libobj in
    *.[cCFSifmso] | \
    *.ada | *.adb | *.ads | *.asm | \
    *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \
    *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup)
      func_xform "$libobj"
      libobj=$func_xform_result
      ;;
    esac

    case $libobj in
    *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;;
    *)
      func_fatal_error "cannot determine name of library object from '$libobj'"
      ;;
    esac

    func_infer_tag $base_compile

    for arg in $later; do
      case $arg in
      -shared)
	test yes = "$build_libtool_libs" \
	  || func_fatal_configuration "cannot build a shared library"
	build_old_libs=no
	continue
	;;

      -static)
	build_libtool_libs=no
	build_old_libs=yes
	continue
	;;

      -prefer-pic)
	pic_mode=yes
	continue
	;;

      -prefer-non-pic)
	pic_mode=no
	continue
	;;
      esac
    done

    func_quote_for_eval "$libobj"
    test "X$libobj" != "X$func_quote_for_eval_result" \
      && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"'	 &()|`$[]' \
      && func_warning "libobj name '$libobj' may not contain shell special characters."
    func_dirname_and_basename "$obj" "/" ""
    objname=$func_basename_result
    xdir=$func_dirname_result
    lobj=$xdir$objdir/$objname

    test -z "$base_compile" && \
      func_fatal_help "you must specify a compilation command"

    # Delete any leftover library objects.
    if test yes = "$build_old_libs"; then
      removelist="$obj $lobj $libobj ${libobj}T"
    else
      removelist="$lobj $libobj ${libobj}T"
    fi

    # On Cygwin there's no "real" PIC flag so we must build both object types
    case $host_os in
    cygwin* | mingw* | pw32* | os2* | cegcc*)
      pic_mode=default
      ;;
    esac
    if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then
      # non-PIC code in shared libraries is not supported
      pic_mode=default
    fi

    # Calculate the filename of the output object if compiler does
    # not support -o with -c
    if test no = "$compiler_c_o"; then
      output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext
      lockfile=$output_obj.lock
    else
      output_obj=
      need_locks=no
      lockfile=
    fi

    # Lock this critical section if it is needed
    # We use this script file to make the link, it avoids creating a new file
    if test yes = "$need_locks"; then
      until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do
	func_echo "Waiting for $lockfile to be removed"
	sleep 2
      done
    elif test warn = "$need_locks"; then
      if test -f "$lockfile"; then
	$ECHO "\
*** ERROR, $lockfile exists and contains:
`cat $lockfile 2>/dev/null`

This indicates that another process is trying to use the same
temporary object file, and libtool could not work around it because
your compiler does not support '-c' and '-o' together.  If you
repeat this compilation, it may succeed, by chance, but you had better
avoid parallel builds (make -j) in this platform, or get a better
compiler."

	$opt_dry_run || $RM $removelist
	exit $EXIT_FAILURE
      fi
      func_append removelist " $output_obj"
      $ECHO "$srcfile" > "$lockfile"
    fi

    $opt_dry_run || $RM $removelist
    func_append removelist " $lockfile"
    trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15

    func_to_tool_file "$srcfile" func_convert_file_msys_to_w32
    srcfile=$func_to_tool_file_result
    func_quote_for_eval "$srcfile"
    qsrcfile=$func_quote_for_eval_result

    # Only build a PIC object if we are building libtool libraries.
    if test yes = "$build_libtool_libs"; then
      # Without this assignment, base_compile gets emptied.
      fbsd_hideous_sh_bug=$base_compile

      if test no != "$pic_mode"; then
	command="$base_compile $qsrcfile $pic_flag"
      else
	# Don't build PIC code
	command="$base_compile $qsrcfile"
      fi

      func_mkdir_p "$xdir$objdir"

      if test -z "$output_obj"; then
	# Place PIC objects in $objdir
	func_append command " -o $lobj"
      fi

      func_show_eval_locale "$command"	\
          'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE'

      if test warn = "$need_locks" &&
	 test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
	$ECHO "\
*** ERROR, $lockfile contains:
`cat $lockfile 2>/dev/null`

but it should contain:
$srcfile

This indicates that another process is trying to use the same
temporary object file, and libtool could not work around it because
your compiler does not support '-c' and '-o' together.  If you
repeat this compilation, it may succeed, by chance, but you had better
avoid parallel builds (make -j) in this platform, or get a better
compiler."

	$opt_dry_run || $RM $removelist
	exit $EXIT_FAILURE
      fi

      # Just move the object if needed, then go on to compile the next one
      if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then
	func_show_eval '$MV "$output_obj" "$lobj"' \
	  'error=$?; $opt_dry_run || $RM $removelist; exit $error'
      fi

      # Allow error messages only from the first compilation.
      if test yes = "$suppress_opt"; then
	suppress_output=' >/dev/null 2>&1'
      fi
    fi

    # Only build a position-dependent object if we build old libraries.
    if test yes = "$build_old_libs"; then
      if test yes != "$pic_mode"; then
	# Don't build PIC code
	command="$base_compile $qsrcfile$pie_flag"
      else
	command="$base_compile $qsrcfile $pic_flag"
      fi
      if test yes = "$compiler_c_o"; then
	func_append command " -o $obj"
      fi

      # Suppress compiler output if we already did a PIC compilation.
      func_append command "$suppress_output"
      func_show_eval_locale "$command" \
        '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE'

      if test warn = "$need_locks" &&
	 test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
	$ECHO "\
*** ERROR, $lockfile contains:
`cat $lockfile 2>/dev/null`

but it should contain:
$srcfile

This indicates that another process is trying to use the same
temporary object file, and libtool could not work around it because
your compiler does not support '-c' and '-o' together.  If you
repeat this compilation, it may succeed, by chance, but you had better
avoid parallel builds (make -j) in this platform, or get a better
compiler."

	$opt_dry_run || $RM $removelist
	exit $EXIT_FAILURE
      fi

      # Just move the object if needed
      if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then
	func_show_eval '$MV "$output_obj" "$obj"' \
	  'error=$?; $opt_dry_run || $RM $removelist; exit $error'
      fi
    fi

    $opt_dry_run || {
      func_write_libtool_object "$libobj" "$objdir/$objname" "$objname"

      # Unlock the critical section if it was locked
      if test no != "$need_locks"; then
	removelist=$lockfile
        $RM "$lockfile"
      fi
    }

    exit $EXIT_SUCCESS
}

$opt_help || {
  test compile = "$opt_mode" && func_mode_compile ${1+"$@"}
}

func_mode_help ()
{
    # We need to display help for each of the modes.
    case $opt_mode in
      "")
        # Generic help is extracted from the usage comments
        # at the start of this file.
        func_help
        ;;

      clean)
        $ECHO \
"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE...

Remove files from the build directory.

RM is the name of the program to use to delete files associated with each FILE
(typically '/bin/rm').  RM-OPTIONS are options (such as '-f') to be passed
to RM.

If FILE is a libtool library, object or program, all the files associated
with it are deleted. Otherwise, only FILE itself is deleted using RM."
        ;;

      compile)
      $ECHO \
"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE

Compile a source file into a libtool library object.

This mode accepts the following additional options:

  -o OUTPUT-FILE    set the output file name to OUTPUT-FILE
  -no-suppress      do not suppress compiler output for multiple passes
  -prefer-pic       try to build PIC objects only
  -prefer-non-pic   try to build non-PIC objects only
  -shared           do not build a '.o' file suitable for static linking
  -static           only build a '.o' file suitable for static linking
  -Wc,FLAG          pass FLAG directly to the compiler

COMPILE-COMMAND is a command to be used in creating a 'standard' object file
from the given SOURCEFILE.

The output file name is determined by removing the directory component from
SOURCEFILE, then substituting the C source code suffix '.c' with the
library object suffix, '.lo'."
        ;;

      execute)
        $ECHO \
"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]...

Automatically set library path, then run a program.

This mode accepts the following additional options:

  -dlopen FILE      add the directory containing FILE to the library path

This mode sets the library path environment variable according to '-dlopen'
flags.

If any of the ARGS are libtool executable wrappers, then they are translated
into their corresponding uninstalled binary, and any of their required library
directories are added to the library path.

Then, COMMAND is executed, with ARGS as arguments."
        ;;

      finish)
        $ECHO \
"Usage: $progname [OPTION]... --mode=finish [LIBDIR]...

Complete the installation of libtool libraries.

Each LIBDIR is a directory that contains libtool libraries.

The commands that this mode executes may require superuser privileges.  Use
the '--dry-run' option if you just want to see what would be executed."
        ;;

      install)
        $ECHO \
"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND...

Install executables or libraries.

INSTALL-COMMAND is the installation command.  The first component should be
either the 'install' or 'cp' program.

The following components of INSTALL-COMMAND are treated specially:

  -inst-prefix-dir PREFIX-DIR  Use PREFIX-DIR as a staging area for installation

The rest of the components are interpreted as arguments to that command (only
BSD-compatible install options are recognized)."
        ;;

      link)
        $ECHO \
"Usage: $progname [OPTION]... --mode=link LINK-COMMAND...

Link object files or libraries together to form another library, or to
create an executable program.

LINK-COMMAND is a command using the C compiler that you would use to create
a program from several object files.

The following components of LINK-COMMAND are treated specially:

  -all-static       do not do any dynamic linking at all
  -avoid-version    do not add a version suffix if possible
  -bindir BINDIR    specify path to binaries directory (for systems where
                    libraries must be found in the PATH setting at runtime)
  -dlopen FILE      '-dlpreopen' FILE if it cannot be dlopened at runtime
  -dlpreopen FILE   link in FILE and add its symbols to lt_preloaded_symbols
  -export-dynamic   allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
  -export-symbols SYMFILE
                    try to export only the symbols listed in SYMFILE
  -export-symbols-regex REGEX
                    try to export only the symbols matching REGEX
  -LLIBDIR          search LIBDIR for required installed libraries
  -lNAME            OUTPUT-FILE requires the installed library libNAME
  -module           build a library that can dlopened
  -no-fast-install  disable the fast-install mode
  -no-install       link a not-installable executable
  -no-undefined     declare that a library does not refer to external symbols
  -o OUTPUT-FILE    create OUTPUT-FILE from the specified objects
  -objectlist FILE  use a list of object files found in FILE to specify objects
  -os2dllname NAME  force a short DLL name on OS/2 (no effect on other OSes)
  -precious-files-regex REGEX
                    don't remove output files matching REGEX
  -release RELEASE  specify package release information
  -rpath LIBDIR     the created library will eventually be installed in LIBDIR
  -R[ ]LIBDIR       add LIBDIR to the runtime path of programs and libraries
  -shared           only do dynamic linking of libtool libraries
  -shrext SUFFIX    override the standard shared library file extension
  -static           do not do any dynamic linking of uninstalled libtool libraries
  -static-libtool-libs
                    do not do any dynamic linking of libtool libraries
  -version-info CURRENT[:REVISION[:AGE]]
                    specify library version info [each variable defaults to 0]
  -weak LIBNAME     declare that the target provides the LIBNAME interface
  -Wc,FLAG
  -Xcompiler FLAG   pass linker-specific FLAG directly to the compiler
  -Wl,FLAG
  -Xlinker FLAG     pass linker-specific FLAG directly to the linker
  -XCClinker FLAG   pass link-specific FLAG to the compiler driver (CC)

All other options (arguments beginning with '-') are ignored.

Every other argument is treated as a filename.  Files ending in '.la' are
treated as uninstalled libtool libraries, other files are standard or library
object files.

If the OUTPUT-FILE ends in '.la', then a libtool library is created,
only library objects ('.lo' files) may be specified, and '-rpath' is
required, except when creating a convenience library.

If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created
using 'ar' and 'ranlib', or on Windows using 'lib'.

If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file
is created, otherwise an executable program is created."
        ;;

      uninstall)
        $ECHO \
"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...

Remove libraries from an installation directory.

RM is the name of the program to use to delete files associated with each FILE
(typically '/bin/rm').  RM-OPTIONS are options (such as '-f') to be passed
to RM.

If FILE is a libtool library, all the files associated with it are deleted.
Otherwise, only FILE itself is deleted using RM."
        ;;

      *)
        func_fatal_help "invalid operation mode '$opt_mode'"
        ;;
    esac

    echo
    $ECHO "Try '$progname --help' for more information about other modes."
}

# Now that we've collected a possible --mode arg, show help if necessary
if $opt_help; then
  if test : = "$opt_help"; then
    func_mode_help
  else
    {
      func_help noexit
      for opt_mode in compile link execute install finish uninstall clean; do
	func_mode_help
      done
    } | $SED -n '1p; 2,$s/^Usage:/  or: /p'
    {
      func_help noexit
      for opt_mode in compile link execute install finish uninstall clean; do
	echo
	func_mode_help
      done
    } |
    $SED '1d
      /^When reporting/,/^Report/{
	H
	d
      }
      $x
      /information about other modes/d
      /more detailed .*MODE/d
      s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/'
  fi
  exit $?
fi


# func_mode_execute arg...
func_mode_execute ()
{
    $debug_cmd

    # The first argument is the command name.
    cmd=$nonopt
    test -z "$cmd" && \
      func_fatal_help "you must specify a COMMAND"

    # Handle -dlopen flags immediately.
    for file in $opt_dlopen; do
      test -f "$file" \
	|| func_fatal_help "'$file' is not a file"

      dir=
      case $file in
      *.la)
	func_resolve_sysroot "$file"
	file=$func_resolve_sysroot_result

	# Check to see that this really is a libtool archive.
	func_lalib_unsafe_p "$file" \
	  || func_fatal_help "'$lib' is not a valid libtool archive"

	# Read the libtool library.
	dlname=
	library_names=
	func_source "$file"

	# Skip this library if it cannot be dlopened.
	if test -z "$dlname"; then
	  # Warn if it was a shared library.
	  test -n "$library_names" && \
	    func_warning "'$file' was not linked with '-export-dynamic'"
	  continue
	fi

	func_dirname "$file" "" "."
	dir=$func_dirname_result

	if test -f "$dir/$objdir/$dlname"; then
	  func_append dir "/$objdir"
	else
	  if test ! -f "$dir/$dlname"; then
	    func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'"
	  fi
	fi
	;;

      *.lo)
	# Just add the directory containing the .lo file.
	func_dirname "$file" "" "."
	dir=$func_dirname_result
	;;

      *)
	func_warning "'-dlopen' is ignored for non-libtool libraries and objects"
	continue
	;;
      esac

      # Get the absolute pathname.
      absdir=`cd "$dir" && pwd`
      test -n "$absdir" && dir=$absdir

      # Now add the directory to shlibpath_var.
      if eval "test -z \"\$$shlibpath_var\""; then
	eval "$shlibpath_var=\"\$dir\""
      else
	eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
      fi
    done

    # This variable tells wrapper scripts just to set shlibpath_var
    # rather than running their programs.
    libtool_execute_magic=$magic

    # Check if any of the arguments is a wrapper script.
    args=
    for file
    do
      case $file in
      -* | *.la | *.lo ) ;;
      *)
	# Do a test to see if this is really a libtool program.
	if func_ltwrapper_script_p "$file"; then
	  func_source "$file"
	  # Transform arg to wrapped name.
	  file=$progdir/$program
	elif func_ltwrapper_executable_p "$file"; then
	  func_ltwrapper_scriptname "$file"
	  func_source "$func_ltwrapper_scriptname_result"
	  # Transform arg to wrapped name.
	  file=$progdir/$program
	fi
	;;
      esac
      # Quote arguments (to preserve shell metacharacters).
      func_append_quoted args "$file"
    done

    if $opt_dry_run; then
      # Display what would be done.
      if test -n "$shlibpath_var"; then
	eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\""
	echo "export $shlibpath_var"
      fi
      $ECHO "$cmd$args"
      exit $EXIT_SUCCESS
    else
      if test -n "$shlibpath_var"; then
	# Export the shlibpath_var.
	eval "export $shlibpath_var"
      fi

      # Restore saved environment variables
      for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
      do
	eval "if test \"\${save_$lt_var+set}\" = set; then
                $lt_var=\$save_$lt_var; export $lt_var
	      else
		$lt_unset $lt_var
	      fi"
      done

      # Now prepare to actually exec the command.
      exec_cmd=\$cmd$args
    fi
}

test execute = "$opt_mode" && func_mode_execute ${1+"$@"}


# func_mode_finish arg...
func_mode_finish ()
{
    $debug_cmd

    libs=
    libdirs=
    admincmds=

    for opt in "$nonopt" ${1+"$@"}
    do
      if test -d "$opt"; then
	func_append libdirs " $opt"

      elif test -f "$opt"; then
	if func_lalib_unsafe_p "$opt"; then
	  func_append libs " $opt"
	else
	  func_warning "'$opt' is not a valid libtool archive"
	fi

      else
	func_fatal_error "invalid argument '$opt'"
      fi
    done

    if test -n "$libs"; then
      if test -n "$lt_sysroot"; then
        sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"`
        sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;"
      else
        sysroot_cmd=
      fi

      # Remove sysroot references
      if $opt_dry_run; then
        for lib in $libs; do
          echo "removing references to $lt_sysroot and '=' prefixes from $lib"
        done
      else
        tmpdir=`func_mktempdir`
        for lib in $libs; do
	  $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \
	    > $tmpdir/tmp-la
	  mv -f $tmpdir/tmp-la $lib
	done
        ${RM}r "$tmpdir"
      fi
    fi

    if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
      for libdir in $libdirs; do
	if test -n "$finish_cmds"; then
	  # Do each command in the finish commands.
	  func_execute_cmds "$finish_cmds" 'admincmds="$admincmds
'"$cmd"'"'
	fi
	if test -n "$finish_eval"; then
	  # Do the single finish_eval.
	  eval cmds=\"$finish_eval\"
	  $opt_dry_run || eval "$cmds" || func_append admincmds "
       $cmds"
	fi
      done
    fi

    # Exit here if they wanted silent mode.
    $opt_quiet && exit $EXIT_SUCCESS

    if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
      echo "----------------------------------------------------------------------"
      echo "Libraries have been installed in:"
      for libdir in $libdirs; do
	$ECHO "   $libdir"
      done
      echo
      echo "If you ever happen to want to link against installed libraries"
      echo "in a given directory, LIBDIR, you must either use libtool, and"
      echo "specify the full pathname of the library, or use the '-LLIBDIR'"
      echo "flag during linking and do at least one of the following:"
      if test -n "$shlibpath_var"; then
	echo "   - add LIBDIR to the '$shlibpath_var' environment variable"
	echo "     during execution"
      fi
      if test -n "$runpath_var"; then
	echo "   - add LIBDIR to the '$runpath_var' environment variable"
	echo "     during linking"
      fi
      if test -n "$hardcode_libdir_flag_spec"; then
	libdir=LIBDIR
	eval flag=\"$hardcode_libdir_flag_spec\"

	$ECHO "   - use the '$flag' linker flag"
      fi
      if test -n "$admincmds"; then
	$ECHO "   - have your system administrator run these commands:$admincmds"
      fi
      if test -f /etc/ld.so.conf; then
	echo "   - have your system administrator add LIBDIR to '/etc/ld.so.conf'"
      fi
      echo

      echo "See any operating system documentation about shared libraries for"
      case $host in
	solaris2.[6789]|solaris2.1[0-9])
	  echo "more information, such as the ld(1), crle(1) and ld.so(8) manual"
	  echo "pages."
	  ;;
	*)
	  echo "more information, such as the ld(1) and ld.so(8) manual pages."
	  ;;
      esac
      echo "----------------------------------------------------------------------"
    fi
    exit $EXIT_SUCCESS
}

test finish = "$opt_mode" && func_mode_finish ${1+"$@"}


# func_mode_install arg...
func_mode_install ()
{
    $debug_cmd

    # There may be an optional sh(1) argument at the beginning of
    # install_prog (especially on Windows NT).
    if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" ||
       # Allow the use of GNU shtool's install command.
       case $nonopt in *shtool*) :;; *) false;; esac
    then
      # Aesthetically quote it.
      func_quote_for_eval "$nonopt"
      install_prog="$func_quote_for_eval_result "
      arg=$1
      shift
    else
      install_prog=
      arg=$nonopt
    fi

    # The real first argument should be the name of the installation program.
    # Aesthetically quote it.
    func_quote_for_eval "$arg"
    func_append install_prog "$func_quote_for_eval_result"
    install_shared_prog=$install_prog
    case " $install_prog " in
      *[\\\ /]cp\ *) install_cp=: ;;
      *) install_cp=false ;;
    esac

    # We need to accept at least all the BSD install flags.
    dest=
    files=
    opts=
    prev=
    install_type=
    isdir=false
    stripme=
    no_mode=:
    for arg
    do
      arg2=
      if test -n "$dest"; then
	func_append files " $dest"
	dest=$arg
	continue
      fi

      case $arg in
      -d) isdir=: ;;
      -f)
	if $install_cp; then :; else
	  prev=$arg
	fi
	;;
      -g | -m | -o)
	prev=$arg
	;;
      -s)
	stripme=" -s"
	continue
	;;
      -*)
	;;
      *)
	# If the previous option needed an argument, then skip it.
	if test -n "$prev"; then
	  if test X-m = "X$prev" && test -n "$install_override_mode"; then
	    arg2=$install_override_mode
	    no_mode=false
	  fi
	  prev=
	else
	  dest=$arg
	  continue
	fi
	;;
      esac

      # Aesthetically quote the argument.
      func_quote_for_eval "$arg"
      func_append install_prog " $func_quote_for_eval_result"
      if test -n "$arg2"; then
	func_quote_for_eval "$arg2"
      fi
      func_append install_shared_prog " $func_quote_for_eval_result"
    done

    test -z "$install_prog" && \
      func_fatal_help "you must specify an install program"

    test -n "$prev" && \
      func_fatal_help "the '$prev' option requires an argument"

    if test -n "$install_override_mode" && $no_mode; then
      if $install_cp; then :; else
	func_quote_for_eval "$install_override_mode"
	func_append install_shared_prog " -m $func_quote_for_eval_result"
      fi
    fi

    if test -z "$files"; then
      if test -z "$dest"; then
	func_fatal_help "no file or destination specified"
      else
	func_fatal_help "you must specify a destination"
      fi
    fi

    # Strip any trailing slash from the destination.
    func_stripname '' '/' "$dest"
    dest=$func_stripname_result

    # Check to see that the destination is a directory.
    test -d "$dest" && isdir=:
    if $isdir; then
      destdir=$dest
      destname=
    else
      func_dirname_and_basename "$dest" "" "."
      destdir=$func_dirname_result
      destname=$func_basename_result

      # Not a directory, so check to see that there is only one file specified.
      set dummy $files; shift
      test "$#" -gt 1 && \
	func_fatal_help "'$dest' is not a directory"
    fi
    case $destdir in
    [\\/]* | [A-Za-z]:[\\/]*) ;;
    *)
      for file in $files; do
	case $file in
	*.lo) ;;
	*)
	  func_fatal_help "'$destdir' must be an absolute directory name"
	  ;;
	esac
      done
      ;;
    esac

    # This variable tells wrapper scripts just to set variables rather
    # than running their programs.
    libtool_install_magic=$magic

    staticlibs=
    future_libdirs=
    current_libdirs=
    for file in $files; do

      # Do each installation.
      case $file in
      *.$libext)
	# Do the static libraries later.
	func_append staticlibs " $file"
	;;

      *.la)
	func_resolve_sysroot "$file"
	file=$func_resolve_sysroot_result

	# Check to see that this really is a libtool archive.
	func_lalib_unsafe_p "$file" \
	  || func_fatal_help "'$file' is not a valid libtool archive"

	library_names=
	old_library=
	relink_command=
	func_source "$file"

	# Add the libdir to current_libdirs if it is the destination.
	if test "X$destdir" = "X$libdir"; then
	  case "$current_libdirs " in
	  *" $libdir "*) ;;
	  *) func_append current_libdirs " $libdir" ;;
	  esac
	else
	  # Note the libdir as a future libdir.
	  case "$future_libdirs " in
	  *" $libdir "*) ;;
	  *) func_append future_libdirs " $libdir" ;;
	  esac
	fi

	func_dirname "$file" "/" ""
	dir=$func_dirname_result
	func_append dir "$objdir"

	if test -n "$relink_command"; then
	  # Determine the prefix the user has applied to our future dir.
	  inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"`

	  # Don't allow the user to place us outside of our expected
	  # location b/c this prevents finding dependent libraries that
	  # are installed to the same prefix.
	  # At present, this check doesn't affect windows .dll's that
	  # are installed into $libdir/../bin (currently, that works fine)
	  # but it's something to keep an eye on.
	  test "$inst_prefix_dir" = "$destdir" && \
	    func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir"

	  if test -n "$inst_prefix_dir"; then
	    # Stick the inst_prefix_dir data into the link command.
	    relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"`
	  else
	    relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"`
	  fi

	  func_warning "relinking '$file'"
	  func_show_eval "$relink_command" \
	    'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"'
	fi

	# See the names of the shared library.
	set dummy $library_names; shift
	if test -n "$1"; then
	  realname=$1
	  shift

	  srcname=$realname
	  test -n "$relink_command" && srcname=${realname}T

	  # Install the shared library and build the symlinks.
	  func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \
	      'exit $?'
	  tstripme=$stripme
	  case $host_os in
	  cygwin* | mingw* | pw32* | cegcc*)
	    case $realname in
	    *.dll.a)
	      tstripme=
	      ;;
	    esac
	    ;;
	  os2*)
	    case $realname in
	    *_dll.a)
	      tstripme=
	      ;;
	    esac
	    ;;
	  esac
	  if test -n "$tstripme" && test -n "$striplib"; then
	    func_show_eval "$striplib $destdir/$realname" 'exit $?'
	  fi

	  if test "$#" -gt 0; then
	    # Delete the old symlinks, and create new ones.
	    # Try 'ln -sf' first, because the 'ln' binary might depend on
	    # the symlink we replace!  Solaris /bin/ln does not understand -f,
	    # so we also need to try rm && ln -s.
	    for linkname
	    do
	      test "$linkname" != "$realname" \
		&& func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })"
	    done
	  fi

	  # Do each command in the postinstall commands.
	  lib=$destdir/$realname
	  func_execute_cmds "$postinstall_cmds" 'exit $?'
	fi

	# Install the pseudo-library for information purposes.
	func_basename "$file"
	name=$func_basename_result
	instname=$dir/${name}i
	func_show_eval "$install_prog $instname $destdir/$name" 'exit $?'

	# Maybe install the static library, too.
	test -n "$old_library" && func_append staticlibs " $dir/$old_library"
	;;

      *.lo)
	# Install (i.e. copy) a libtool object.

	# Figure out destination file name, if it wasn't already specified.
	if test -n "$destname"; then
	  destfile=$destdir/$destname
	else
	  func_basename "$file"
	  destfile=$func_basename_result
	  destfile=$destdir/$destfile
	fi

	# Deduce the name of the destination old-style object file.
	case $destfile in
	*.lo)
	  func_lo2o "$destfile"
	  staticdest=$func_lo2o_result
	  ;;
	*.$objext)
	  staticdest=$destfile
	  destfile=
	  ;;
	*)
	  func_fatal_help "cannot copy a libtool object to '$destfile'"
	  ;;
	esac

	# Install the libtool object if requested.
	test -n "$destfile" && \
	  func_show_eval "$install_prog $file $destfile" 'exit $?'

	# Install the old object if enabled.
	if test yes = "$build_old_libs"; then
	  # Deduce the name of the old-style object file.
	  func_lo2o "$file"
	  staticobj=$func_lo2o_result
	  func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?'
	fi
	exit $EXIT_SUCCESS
	;;

      *)
	# Figure out destination file name, if it wasn't already specified.
	if test -n "$destname"; then
	  destfile=$destdir/$destname
	else
	  func_basename "$file"
	  destfile=$func_basename_result
	  destfile=$destdir/$destfile
	fi

	# If the file is missing, and there is a .exe on the end, strip it
	# because it is most likely a libtool script we actually want to
	# install
	stripped_ext=
	case $file in
	  *.exe)
	    if test ! -f "$file"; then
	      func_stripname '' '.exe' "$file"
	      file=$func_stripname_result
	      stripped_ext=.exe
	    fi
	    ;;
	esac

	# Do a test to see if this is really a libtool program.
	case $host in
	*cygwin* | *mingw*)
	    if func_ltwrapper_executable_p "$file"; then
	      func_ltwrapper_scriptname "$file"
	      wrapper=$func_ltwrapper_scriptname_result
	    else
	      func_stripname '' '.exe' "$file"
	      wrapper=$func_stripname_result
	    fi
	    ;;
	*)
	    wrapper=$file
	    ;;
	esac
	if func_ltwrapper_script_p "$wrapper"; then
	  notinst_deplibs=
	  relink_command=

	  func_source "$wrapper"

	  # Check the variables that should have been set.
	  test -z "$generated_by_libtool_version" && \
	    func_fatal_error "invalid libtool wrapper script '$wrapper'"

	  finalize=:
	  for lib in $notinst_deplibs; do
	    # Check to see that each library is installed.
	    libdir=
	    if test -f "$lib"; then
	      func_source "$lib"
	    fi
	    libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'`
	    if test -n "$libdir" && test ! -f "$libfile"; then
	      func_warning "'$lib' has not been installed in '$libdir'"
	      finalize=false
	    fi
	  done

	  relink_command=
	  func_source "$wrapper"

	  outputname=
	  if test no = "$fast_install" && test -n "$relink_command"; then
	    $opt_dry_run || {
	      if $finalize; then
	        tmpdir=`func_mktempdir`
		func_basename "$file$stripped_ext"
		file=$func_basename_result
	        outputname=$tmpdir/$file
	        # Replace the output file specification.
	        relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'`

	        $opt_quiet || {
	          func_quote_for_expand "$relink_command"
		  eval "func_echo $func_quote_for_expand_result"
	        }
	        if eval "$relink_command"; then :
	          else
		  func_error "error: relink '$file' with the above command before installing it"
		  $opt_dry_run || ${RM}r "$tmpdir"
		  continue
	        fi
	        file=$outputname
	      else
	        func_warning "cannot relink '$file'"
	      fi
	    }
	  else
	    # Install the binary that we compiled earlier.
	    file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"`
	  fi
	fi

	# remove .exe since cygwin /usr/bin/install will append another
	# one anyway
	case $install_prog,$host in
	*/usr/bin/install*,*cygwin*)
	  case $file:$destfile in
	  *.exe:*.exe)
	    # this is ok
	    ;;
	  *.exe:*)
	    destfile=$destfile.exe
	    ;;
	  *:*.exe)
	    func_stripname '' '.exe' "$destfile"
	    destfile=$func_stripname_result
	    ;;
	  esac
	  ;;
	esac
	func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?'
	$opt_dry_run || if test -n "$outputname"; then
	  ${RM}r "$tmpdir"
	fi
	;;
      esac
    done

    for file in $staticlibs; do
      func_basename "$file"
      name=$func_basename_result

      # Set up the ranlib parameters.
      oldlib=$destdir/$name
      func_to_tool_file "$oldlib" func_convert_file_msys_to_w32
      tool_oldlib=$func_to_tool_file_result

      func_show_eval "$install_prog \$file \$oldlib" 'exit $?'

      if test -n "$stripme" && test -n "$old_striplib"; then
	func_show_eval "$old_striplib $tool_oldlib" 'exit $?'
      fi

      # Do each command in the postinstall commands.
      func_execute_cmds "$old_postinstall_cmds" 'exit $?'
    done

    test -n "$future_libdirs" && \
      func_warning "remember to run '$progname --finish$future_libdirs'"

    if test -n "$current_libdirs"; then
      # Maybe just do a dry run.
      $opt_dry_run && current_libdirs=" -n$current_libdirs"
      exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs'
    else
      exit $EXIT_SUCCESS
    fi
}

test install = "$opt_mode" && func_mode_install ${1+"$@"}


# func_generate_dlsyms outputname originator pic_p
# Extract symbols from dlprefiles and create ${outputname}S.o with
# a dlpreopen symbol table.
func_generate_dlsyms ()
{
    $debug_cmd

    my_outputname=$1
    my_originator=$2
    my_pic_p=${3-false}
    my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'`
    my_dlsyms=

    if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then
      if test -n "$NM" && test -n "$global_symbol_pipe"; then
	my_dlsyms=${my_outputname}S.c
      else
	func_error "not configured to extract global symbols from dlpreopened files"
      fi
    fi

    if test -n "$my_dlsyms"; then
      case $my_dlsyms in
      "") ;;
      *.c)
	# Discover the nlist of each of the dlfiles.
	nlist=$output_objdir/$my_outputname.nm

	func_show_eval "$RM $nlist ${nlist}S ${nlist}T"

	# Parse the name list into a source file.
	func_verbose "creating $output_objdir/$my_dlsyms"

	$opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\
/* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */
/* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */

#ifdef __cplusplus
extern \"C\" {
#endif

#if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4))
#pragma GCC diagnostic ignored \"-Wstrict-prototypes\"
#endif

/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests.  */
#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE
/* DATA imports from DLLs on WIN32 can't be const, because runtime
   relocations are performed -- see ld's documentation on pseudo-relocs.  */
# define LT_DLSYM_CONST
#elif defined __osf__
/* This system does not cope well with relocations in const data.  */
# define LT_DLSYM_CONST
#else
# define LT_DLSYM_CONST const
#endif

#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0)

/* External symbol declarations for the compiler. */\
"

	if test yes = "$dlself"; then
	  func_verbose "generating symbol list for '$output'"

	  $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist"

	  # Add our own program objects to the symbol list.
	  progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP`
	  for progfile in $progfiles; do
	    func_to_tool_file "$progfile" func_convert_file_msys_to_w32
	    func_verbose "extracting global C symbols from '$func_to_tool_file_result'"
	    $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'"
	  done

	  if test -n "$exclude_expsyms"; then
	    $opt_dry_run || {
	      eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
	      eval '$MV "$nlist"T "$nlist"'
	    }
	  fi

	  if test -n "$export_symbols_regex"; then
	    $opt_dry_run || {
	      eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T'
	      eval '$MV "$nlist"T "$nlist"'
	    }
	  fi

	  # Prepare the list of exported symbols
	  if test -z "$export_symbols"; then
	    export_symbols=$output_objdir/$outputname.exp
	    $opt_dry_run || {
	      $RM $export_symbols
	      eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
	      case $host in
	      *cygwin* | *mingw* | *cegcc* )
                eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
                eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"'
	        ;;
	      esac
	    }
	  else
	    $opt_dry_run || {
	      eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"'
	      eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T'
	      eval '$MV "$nlist"T "$nlist"'
	      case $host in
	        *cygwin* | *mingw* | *cegcc* )
	          eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
	          eval 'cat "$nlist" >> "$output_objdir/$outputname.def"'
	          ;;
	      esac
	    }
	  fi
	fi

	for dlprefile in $dlprefiles; do
	  func_verbose "extracting global C symbols from '$dlprefile'"
	  func_basename "$dlprefile"
	  name=$func_basename_result
          case $host in
	    *cygwin* | *mingw* | *cegcc* )
	      # if an import library, we need to obtain dlname
	      if func_win32_import_lib_p "$dlprefile"; then
	        func_tr_sh "$dlprefile"
	        eval "curr_lafile=\$libfile_$func_tr_sh_result"
	        dlprefile_dlbasename=
	        if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then
	          # Use subshell, to avoid clobbering current variable values
	          dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"`
	          if test -n "$dlprefile_dlname"; then
	            func_basename "$dlprefile_dlname"
	            dlprefile_dlbasename=$func_basename_result
	          else
	            # no lafile. user explicitly requested -dlpreopen .
	            $sharedlib_from_linklib_cmd "$dlprefile"
	            dlprefile_dlbasename=$sharedlib_from_linklib_result
	          fi
	        fi
	        $opt_dry_run || {
	          if test -n "$dlprefile_dlbasename"; then
	            eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"'
	          else
	            func_warning "Could not compute DLL name from $name"
	            eval '$ECHO ": $name " >> "$nlist"'
	          fi
	          func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32
	          eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe |
	            $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'"
	        }
	      else # not an import lib
	        $opt_dry_run || {
	          eval '$ECHO ": $name " >> "$nlist"'
	          func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32
	          eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'"
	        }
	      fi
	    ;;
	    *)
	      $opt_dry_run || {
	        eval '$ECHO ": $name " >> "$nlist"'
	        func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32
	        eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'"
	      }
	    ;;
          esac
	done

	$opt_dry_run || {
	  # Make sure we have at least an empty file.
	  test -f "$nlist" || : > "$nlist"

	  if test -n "$exclude_expsyms"; then
	    $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
	    $MV "$nlist"T "$nlist"
	  fi

	  # Try sorting and uniquifying the output.
	  if $GREP -v "^: " < "$nlist" |
	      if sort -k 3 /dev/null 2>&1; then
		sort -k 3
	      else
		sort +2
	      fi |
	      uniq > "$nlist"S; then
	    :
	  else
	    $GREP -v "^: " < "$nlist" > "$nlist"S
	  fi

	  if test -f "$nlist"S; then
	    eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"'
	  else
	    echo '/* NONE */' >> "$output_objdir/$my_dlsyms"
	  fi

	  func_show_eval '$RM "${nlist}I"'
	  if test -n "$global_symbol_to_import"; then
	    eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I'
	  fi

	  echo >> "$output_objdir/$my_dlsyms" "\

/* The mapping between symbol names and symbols.  */
typedef struct {
  const char *name;
  void *address;
} lt_dlsymlist;
extern LT_DLSYM_CONST lt_dlsymlist
lt_${my_prefix}_LTX_preloaded_symbols[];\
"

	  if test -s "$nlist"I; then
	    echo >> "$output_objdir/$my_dlsyms" "\
static void lt_syminit(void)
{
  LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols;
  for (; symbol->name; ++symbol)
    {"
	    $SED 's/.*/      if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms"
	    echo >> "$output_objdir/$my_dlsyms" "\
    }
}"
	  fi
	  echo >> "$output_objdir/$my_dlsyms" "\
LT_DLSYM_CONST lt_dlsymlist
lt_${my_prefix}_LTX_preloaded_symbols[] =
{ {\"$my_originator\", (void *) 0},"

	  if test -s "$nlist"I; then
	    echo >> "$output_objdir/$my_dlsyms" "\
  {\"@INIT@\", (void *) <_syminit},"
	  fi

	  case $need_lib_prefix in
	  no)
	    eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms"
	    ;;
	  *)
	    eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms"
	    ;;
	  esac
	  echo >> "$output_objdir/$my_dlsyms" "\
  {0, (void *) 0}
};

/* This works around a problem in FreeBSD linker */
#ifdef FREEBSD_WORKAROUND
static const void *lt_preloaded_setup() {
  return lt_${my_prefix}_LTX_preloaded_symbols;
}
#endif

#ifdef __cplusplus
}
#endif\
"
	} # !$opt_dry_run

	pic_flag_for_symtable=
	case "$compile_command " in
	*" -static "*) ;;
	*)
	  case $host in
	  # compiling the symbol table file with pic_flag works around
	  # a FreeBSD bug that causes programs to crash when -lm is
	  # linked before any other PIC object.  But we must not use
	  # pic_flag when linking with -static.  The problem exists in
	  # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
	  *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)
	    pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;;
	  *-*-hpux*)
	    pic_flag_for_symtable=" $pic_flag"  ;;
	  *)
	    $my_pic_p && pic_flag_for_symtable=" $pic_flag"
	    ;;
	  esac
	  ;;
	esac
	symtab_cflags=
	for arg in $LTCFLAGS; do
	  case $arg in
	  -pie | -fpie | -fPIE) ;;
	  *) func_append symtab_cflags " $arg" ;;
	  esac
	done

	# Now compile the dynamic symbol file.
	func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?'

	# Clean up the generated files.
	func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"'

	# Transform the symbol file into the correct name.
	symfileobj=$output_objdir/${my_outputname}S.$objext
	case $host in
	*cygwin* | *mingw* | *cegcc* )
	  if test -f "$output_objdir/$my_outputname.def"; then
	    compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
	    finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
	  else
	    compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"`
	    finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"`
	  fi
	  ;;
	*)
	  compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"`
	  finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"`
	  ;;
	esac
	;;
      *)
	func_fatal_error "unknown suffix for '$my_dlsyms'"
	;;
      esac
    else
      # We keep going just in case the user didn't refer to
      # lt_preloaded_symbols.  The linker will fail if global_symbol_pipe
      # really was required.

      # Nullify the symbol file.
      compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"`
      finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"`
    fi
}

# func_cygming_gnu_implib_p ARG
# This predicate returns with zero status (TRUE) if
# ARG is a GNU/binutils-style import library. Returns
# with nonzero status (FALSE) otherwise.
func_cygming_gnu_implib_p ()
{
  $debug_cmd

  func_to_tool_file "$1" func_convert_file_msys_to_w32
  func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'`
  test -n "$func_cygming_gnu_implib_tmp"
}

# func_cygming_ms_implib_p ARG
# This predicate returns with zero status (TRUE) if
# ARG is an MS-style import library. Returns
# with nonzero status (FALSE) otherwise.
func_cygming_ms_implib_p ()
{
  $debug_cmd

  func_to_tool_file "$1" func_convert_file_msys_to_w32
  func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'`
  test -n "$func_cygming_ms_implib_tmp"
}

# func_win32_libid arg
# return the library type of file 'arg'
#
# Need a lot of goo to handle *both* DLLs and import libs
# Has to be a shell function in order to 'eat' the argument
# that is supplied when $file_magic_command is called.
# Despite the name, also deal with 64 bit binaries.
func_win32_libid ()
{
  $debug_cmd

  win32_libid_type=unknown
  win32_fileres=`file -L $1 2>/dev/null`
  case $win32_fileres in
  *ar\ archive\ import\ library*) # definitely import
    win32_libid_type="x86 archive import"
    ;;
  *ar\ archive*) # could be an import, or static
    # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD.
    if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null |
       $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then
      case $nm_interface in
      "MS dumpbin")
	if func_cygming_ms_implib_p "$1" ||
	   func_cygming_gnu_implib_p "$1"
	then
	  win32_nmres=import
	else
	  win32_nmres=
	fi
	;;
      *)
	func_to_tool_file "$1" func_convert_file_msys_to_w32
	win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" |
	  $SED -n -e '
	    1,100{
		/ I /{
		    s|.*|import|
		    p
		    q
		}
	    }'`
	;;
      esac
      case $win32_nmres in
      import*)  win32_libid_type="x86 archive import";;
      *)        win32_libid_type="x86 archive static";;
      esac
    fi
    ;;
  *DLL*)
    win32_libid_type="x86 DLL"
    ;;
  *executable*) # but shell scripts are "executable" too...
    case $win32_fileres in
    *MS\ Windows\ PE\ Intel*)
      win32_libid_type="x86 DLL"
      ;;
    esac
    ;;
  esac
  $ECHO "$win32_libid_type"
}

# func_cygming_dll_for_implib ARG
#
# Platform-specific function to extract the
# name of the DLL associated with the specified
# import library ARG.
# Invoked by eval'ing the libtool variable
#    $sharedlib_from_linklib_cmd
# Result is available in the variable
#    $sharedlib_from_linklib_result
func_cygming_dll_for_implib ()
{
  $debug_cmd

  sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"`
}

# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs
#
# The is the core of a fallback implementation of a
# platform-specific function to extract the name of the
# DLL associated with the specified import library LIBNAME.
#
# SECTION_NAME is either .idata$6 or .idata$7, depending
# on the platform and compiler that created the implib.
#
# Echos the name of the DLL associated with the
# specified import library.
func_cygming_dll_for_implib_fallback_core ()
{
  $debug_cmd

  match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"`
  $OBJDUMP -s --section "$1" "$2" 2>/dev/null |
    $SED '/^Contents of section '"$match_literal"':/{
      # Place marker at beginning of archive member dllname section
      s/.*/====MARK====/
      p
      d
    }
    # These lines can sometimes be longer than 43 characters, but
    # are always uninteresting
    /:[	 ]*file format pe[i]\{,1\}-/d
    /^In archive [^:]*:/d
    # Ensure marker is printed
    /^====MARK====/p
    # Remove all lines with less than 43 characters
    /^.\{43\}/!d
    # From remaining lines, remove first 43 characters
    s/^.\{43\}//' |
    $SED -n '
      # Join marker and all lines until next marker into a single line
      /^====MARK====/ b para
      H
      $ b para
      b
      :para
      x
      s/\n//g
      # Remove the marker
      s/^====MARK====//
      # Remove trailing dots and whitespace
      s/[\. \t]*$//
      # Print
      /./p' |
    # we now have a list, one entry per line, of the stringified
    # contents of the appropriate section of all members of the
    # archive that possess that section. Heuristic: eliminate
    # all those that have a first or second character that is
    # a '.' (that is, objdump's representation of an unprintable
    # character.) This should work for all archives with less than
    # 0x302f exports -- but will fail for DLLs whose name actually
    # begins with a literal '.' or a single character followed by
    # a '.'.
    #
    # Of those that remain, print the first one.
    $SED -e '/^\./d;/^.\./d;q'
}

# func_cygming_dll_for_implib_fallback ARG
# Platform-specific function to extract the
# name of the DLL associated with the specified
# import library ARG.
#
# This fallback implementation is for use when $DLLTOOL
# does not support the --identify-strict option.
# Invoked by eval'ing the libtool variable
#    $sharedlib_from_linklib_cmd
# Result is available in the variable
#    $sharedlib_from_linklib_result
func_cygming_dll_for_implib_fallback ()
{
  $debug_cmd

  if func_cygming_gnu_implib_p "$1"; then
    # binutils import library
    sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"`
  elif func_cygming_ms_implib_p "$1"; then
    # ms-generated import library
    sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"`
  else
    # unknown
    sharedlib_from_linklib_result=
  fi
}


# func_extract_an_archive dir oldlib
func_extract_an_archive ()
{
    $debug_cmd

    f_ex_an_ar_dir=$1; shift
    f_ex_an_ar_oldlib=$1
    if test yes = "$lock_old_archive_extraction"; then
      lockfile=$f_ex_an_ar_oldlib.lock
      until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do
	func_echo "Waiting for $lockfile to be removed"
	sleep 2
      done
    fi
    func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \
		   'stat=$?; rm -f "$lockfile"; exit $stat'
    if test yes = "$lock_old_archive_extraction"; then
      $opt_dry_run || rm -f "$lockfile"
    fi
    if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then
     :
    else
      func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib"
    fi
}


# func_extract_archives gentop oldlib ...
func_extract_archives ()
{
    $debug_cmd

    my_gentop=$1; shift
    my_oldlibs=${1+"$@"}
    my_oldobjs=
    my_xlib=
    my_xabs=
    my_xdir=

    for my_xlib in $my_oldlibs; do
      # Extract the objects.
      case $my_xlib in
	[\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;;
	*) my_xabs=`pwd`"/$my_xlib" ;;
      esac
      func_basename "$my_xlib"
      my_xlib=$func_basename_result
      my_xlib_u=$my_xlib
      while :; do
        case " $extracted_archives " in
	*" $my_xlib_u "*)
	  func_arith $extracted_serial + 1
	  extracted_serial=$func_arith_result
	  my_xlib_u=lt$extracted_serial-$my_xlib ;;
	*) break ;;
	esac
      done
      extracted_archives="$extracted_archives $my_xlib_u"
      my_xdir=$my_gentop/$my_xlib_u

      func_mkdir_p "$my_xdir"

      case $host in
      *-darwin*)
	func_verbose "Extracting $my_xabs"
	# Do not bother doing anything if just a dry run
	$opt_dry_run || {
	  darwin_orig_dir=`pwd`
	  cd $my_xdir || exit $?
	  darwin_archive=$my_xabs
	  darwin_curdir=`pwd`
	  func_basename "$darwin_archive"
	  darwin_base_archive=$func_basename_result
	  darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true`
	  if test -n "$darwin_arches"; then
	    darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'`
	    darwin_arch=
	    func_verbose "$darwin_base_archive has multiple architectures $darwin_arches"
	    for darwin_arch in  $darwin_arches; do
	      func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch"
	      $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive"
	      cd "unfat-$$/$darwin_base_archive-$darwin_arch"
	      func_extract_an_archive "`pwd`" "$darwin_base_archive"
	      cd "$darwin_curdir"
	      $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive"
	    done # $darwin_arches
            ## Okay now we've a bunch of thin objects, gotta fatten them up :)
	    darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u`
	    darwin_file=
	    darwin_files=
	    for darwin_file in $darwin_filelist; do
	      darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP`
	      $LIPO -create -output "$darwin_file" $darwin_files
	    done # $darwin_filelist
	    $RM -rf unfat-$$
	    cd "$darwin_orig_dir"
	  else
	    cd $darwin_orig_dir
	    func_extract_an_archive "$my_xdir" "$my_xabs"
	  fi # $darwin_arches
	} # !$opt_dry_run
	;;
      *)
        func_extract_an_archive "$my_xdir" "$my_xabs"
	;;
      esac
      my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP`
    done

    func_extract_archives_result=$my_oldobjs
}


# func_emit_wrapper [arg=no]
#
# Emit a libtool wrapper script on stdout.
# Don't directly open a file because we may want to
# incorporate the script contents within a cygwin/mingw
# wrapper executable.  Must ONLY be called from within
# func_mode_link because it depends on a number of variables
# set therein.
#
# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR
# variable will take.  If 'yes', then the emitted script
# will assume that the directory where it is stored is
# the $objdir directory.  This is a cygwin/mingw-specific
# behavior.
func_emit_wrapper ()
{
	func_emit_wrapper_arg1=${1-no}

	$ECHO "\
#! $SHELL

# $output - temporary wrapper script for $objdir/$outputname
# Generated by $PROGRAM (GNU $PACKAGE) $VERSION
#
# The $output program cannot be directly executed until all the libtool
# libraries that it depends on are installed.
#
# This wrapper script should never be moved out of the build directory.
# If it is, it will not operate correctly.

# Sed substitution that helps us do robust quoting.  It backslashifies
# metacharacters that are still active within double-quoted strings.
sed_quote_subst='$sed_quote_subst'

# Be Bourne compatible
if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then
  emulate sh
  NULLCMD=:
  # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which
  # is contrary to our usage.  Disable this feature.
  alias -g '\${1+\"\$@\"}'='\"\$@\"'
  setopt NO_GLOB_SUBST
else
  case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac
fi
BIN_SH=xpg4; export BIN_SH # for Tru64
DUALCASE=1; export DUALCASE # for MKS sh

# The HP-UX ksh and POSIX shell print the target directory to stdout
# if CDPATH is set.
(unset CDPATH) >/dev/null 2>&1 && unset CDPATH

relink_command=\"$relink_command\"

# This environment variable determines our operation mode.
if test \"\$libtool_install_magic\" = \"$magic\"; then
  # install mode needs the following variables:
  generated_by_libtool_version='$macro_version'
  notinst_deplibs='$notinst_deplibs'
else
  # When we are sourced in execute mode, \$file and \$ECHO are already set.
  if test \"\$libtool_execute_magic\" != \"$magic\"; then
    file=\"\$0\""

    qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"`
    $ECHO "\

# A function that is used when there is no print builtin or printf.
func_fallback_echo ()
{
  eval 'cat <<_LTECHO_EOF
\$1
_LTECHO_EOF'
}
    ECHO=\"$qECHO\"
  fi

# Very basic option parsing. These options are (a) specific to
# the libtool wrapper, (b) are identical between the wrapper
# /script/ and the wrapper /executable/ that is used only on
# windows platforms, and (c) all begin with the string "--lt-"
# (application programs are unlikely to have options that match
# this pattern).
#
# There are only two supported options: --lt-debug and
# --lt-dump-script. There is, deliberately, no --lt-help.
#
# The first argument to this parsing function should be the
# script's $0 value, followed by "$@".
lt_option_debug=
func_parse_lt_options ()
{
  lt_script_arg0=\$0
  shift
  for lt_opt
  do
    case \"\$lt_opt\" in
    --lt-debug) lt_option_debug=1 ;;
    --lt-dump-script)
        lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\`
        test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=.
        lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\`
        cat \"\$lt_dump_D/\$lt_dump_F\"
        exit 0
      ;;
    --lt-*)
        \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2
        exit 1
      ;;
    esac
  done

  # Print the debug banner immediately:
  if test -n \"\$lt_option_debug\"; then
    echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2
  fi
}

# Used when --lt-debug. Prints its arguments to stdout
# (redirection is the responsibility of the caller)
func_lt_dump_args ()
{
  lt_dump_args_N=1;
  for lt_arg
  do
    \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\"
    lt_dump_args_N=\`expr \$lt_dump_args_N + 1\`
  done
}

# Core function for launching the target application
func_exec_program_core ()
{
"
  case $host in
  # Backslashes separate directories on plain windows
  *-*-mingw | *-*-os2* | *-cegcc*)
    $ECHO "\
      if test -n \"\$lt_option_debug\"; then
        \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2
        func_lt_dump_args \${1+\"\$@\"} 1>&2
      fi
      exec \"\$progdir\\\\\$program\" \${1+\"\$@\"}
"
    ;;

  *)
    $ECHO "\
      if test -n \"\$lt_option_debug\"; then
        \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2
        func_lt_dump_args \${1+\"\$@\"} 1>&2
      fi
      exec \"\$progdir/\$program\" \${1+\"\$@\"}
"
    ;;
  esac
  $ECHO "\
      \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2
      exit 1
}

# A function to encapsulate launching the target application
# Strips options in the --lt-* namespace from \$@ and
# launches target application with the remaining arguments.
func_exec_program ()
{
  case \" \$* \" in
  *\\ --lt-*)
    for lt_wr_arg
    do
      case \$lt_wr_arg in
      --lt-*) ;;
      *) set x \"\$@\" \"\$lt_wr_arg\"; shift;;
      esac
      shift
    done ;;
  esac
  func_exec_program_core \${1+\"\$@\"}
}

  # Parse options
  func_parse_lt_options \"\$0\" \${1+\"\$@\"}

  # Find the directory that this script lives in.
  thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\`
  test \"x\$thisdir\" = \"x\$file\" && thisdir=.

  # Follow symbolic links until we get to the real thisdir.
  file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\`
  while test -n \"\$file\"; do
    destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\`

    # If there was a directory component, then change thisdir.
    if test \"x\$destdir\" != \"x\$file\"; then
      case \"\$destdir\" in
      [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;;
      *) thisdir=\"\$thisdir/\$destdir\" ;;
      esac
    fi

    file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\`
    file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\`
  done

  # Usually 'no', except on cygwin/mingw when embedded into
  # the cwrapper.
  WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1
  if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then
    # special case for '.'
    if test \"\$thisdir\" = \".\"; then
      thisdir=\`pwd\`
    fi
    # remove .libs from thisdir
    case \"\$thisdir\" in
    *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;;
    $objdir )   thisdir=. ;;
    esac
  fi

  # Try to get the absolute directory name.
  absdir=\`cd \"\$thisdir\" && pwd\`
  test -n \"\$absdir\" && thisdir=\"\$absdir\"
"

	if test yes = "$fast_install"; then
	  $ECHO "\
  program=lt-'$outputname'$exeext
  progdir=\"\$thisdir/$objdir\"

  if test ! -f \"\$progdir/\$program\" ||
     { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\
       test \"X\$file\" != \"X\$progdir/\$program\"; }; then

    file=\"\$\$-\$program\"

    if test ! -d \"\$progdir\"; then
      $MKDIR \"\$progdir\"
    else
      $RM \"\$progdir/\$file\"
    fi"

	  $ECHO "\

    # relink executable if necessary
    if test -n \"\$relink_command\"; then
      if relink_command_output=\`eval \$relink_command 2>&1\`; then :
      else
	\$ECHO \"\$relink_command_output\" >&2
	$RM \"\$progdir/\$file\"
	exit 1
      fi
    fi

    $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
    { $RM \"\$progdir/\$program\";
      $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; }
    $RM \"\$progdir/\$file\"
  fi"
	else
	  $ECHO "\
  program='$outputname'
  progdir=\"\$thisdir/$objdir\"
"
	fi

	$ECHO "\

  if test -f \"\$progdir/\$program\"; then"

	# fixup the dll searchpath if we need to.
	#
	# Fix the DLL searchpath if we need to.  Do this before prepending
	# to shlibpath, because on Windows, both are PATH and uninstalled
	# libraries must come first.
	if test -n "$dllsearchpath"; then
	  $ECHO "\
    # Add the dll search path components to the executable PATH
    PATH=$dllsearchpath:\$PATH
"
	fi

	# Export our shlibpath_var if we have one.
	if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
	  $ECHO "\
    # Add our own library path to $shlibpath_var
    $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"

    # Some systems cannot cope with colon-terminated $shlibpath_var
    # The second colon is a workaround for a bug in BeOS R4 sed
    $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\`

    export $shlibpath_var
"
	fi

	$ECHO "\
    if test \"\$libtool_execute_magic\" != \"$magic\"; then
      # Run the actual program with our arguments.
      func_exec_program \${1+\"\$@\"}
    fi
  else
    # The program doesn't exist.
    \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2
    \$ECHO \"This script is just a wrapper for \$program.\" 1>&2
    \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2
    exit 1
  fi
fi\
"
}


# func_emit_cwrapperexe_src
# emit the source code for a wrapper executable on stdout
# Must ONLY be called from within func_mode_link because
# it depends on a number of variable set therein.
func_emit_cwrapperexe_src ()
{
	cat <
#include 
#ifdef _MSC_VER
# include 
# include 
# include 
#else
# include 
# include 
# ifdef __CYGWIN__
#  include 
# endif
#endif
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0)

/* declarations of non-ANSI functions */
#if defined __MINGW32__
# ifdef __STRICT_ANSI__
int _putenv (const char *);
# endif
#elif defined __CYGWIN__
# ifdef __STRICT_ANSI__
char *realpath (const char *, char *);
int putenv (char *);
int setenv (const char *, const char *, int);
# endif
/* #elif defined other_platform || defined ... */
#endif

/* portability defines, excluding path handling macros */
#if defined _MSC_VER
# define setmode _setmode
# define stat    _stat
# define chmod   _chmod
# define getcwd  _getcwd
# define putenv  _putenv
# define S_IXUSR _S_IEXEC
#elif defined __MINGW32__
# define setmode _setmode
# define stat    _stat
# define chmod   _chmod
# define getcwd  _getcwd
# define putenv  _putenv
#elif defined __CYGWIN__
# define HAVE_SETENV
# define FOPEN_WB "wb"
/* #elif defined other platforms ... */
#endif

#if defined PATH_MAX
# define LT_PATHMAX PATH_MAX
#elif defined MAXPATHLEN
# define LT_PATHMAX MAXPATHLEN
#else
# define LT_PATHMAX 1024
#endif

#ifndef S_IXOTH
# define S_IXOTH 0
#endif
#ifndef S_IXGRP
# define S_IXGRP 0
#endif

/* path handling portability macros */
#ifndef DIR_SEPARATOR
# define DIR_SEPARATOR '/'
# define PATH_SEPARATOR ':'
#endif

#if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \
  defined __OS2__
# define HAVE_DOS_BASED_FILE_SYSTEM
# define FOPEN_WB "wb"
# ifndef DIR_SEPARATOR_2
#  define DIR_SEPARATOR_2 '\\'
# endif
# ifndef PATH_SEPARATOR_2
#  define PATH_SEPARATOR_2 ';'
# endif
#endif

#ifndef DIR_SEPARATOR_2
# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
#else /* DIR_SEPARATOR_2 */
# define IS_DIR_SEPARATOR(ch) \
	(((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
#endif /* DIR_SEPARATOR_2 */

#ifndef PATH_SEPARATOR_2
# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR)
#else /* PATH_SEPARATOR_2 */
# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2)
#endif /* PATH_SEPARATOR_2 */

#ifndef FOPEN_WB
# define FOPEN_WB "w"
#endif
#ifndef _O_BINARY
# define _O_BINARY 0
#endif

#define XMALLOC(type, num)      ((type *) xmalloc ((num) * sizeof(type)))
#define XFREE(stale) do { \
  if (stale) { free (stale); stale = 0; } \
} while (0)

#if defined LT_DEBUGWRAPPER
static int lt_debug = 1;
#else
static int lt_debug = 0;
#endif

const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */

void *xmalloc (size_t num);
char *xstrdup (const char *string);
const char *base_name (const char *name);
char *find_executable (const char *wrapper);
char *chase_symlinks (const char *pathspec);
int make_executable (const char *path);
int check_executable (const char *path);
char *strendzap (char *str, const char *pat);
void lt_debugprintf (const char *file, int line, const char *fmt, ...);
void lt_fatal (const char *file, int line, const char *message, ...);
static const char *nonnull (const char *s);
static const char *nonempty (const char *s);
void lt_setenv (const char *name, const char *value);
char *lt_extend_str (const char *orig_value, const char *add, int to_end);
void lt_update_exe_path (const char *name, const char *value);
void lt_update_lib_path (const char *name, const char *value);
char **prepare_spawn (char **argv);
void lt_dump_script (FILE *f);
EOF

	    cat <= 0)
      && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
    return 1;
  else
    return 0;
}

int
make_executable (const char *path)
{
  int rval = 0;
  struct stat st;

  lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n",
                  nonempty (path));
  if ((!path) || (!*path))
    return 0;

  if (stat (path, &st) >= 0)
    {
      rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR);
    }
  return rval;
}

/* Searches for the full path of the wrapper.  Returns
   newly allocated full path name if found, NULL otherwise
   Does not chase symlinks, even on platforms that support them.
*/
char *
find_executable (const char *wrapper)
{
  int has_slash = 0;
  const char *p;
  const char *p_next;
  /* static buffer for getcwd */
  char tmp[LT_PATHMAX + 1];
  size_t tmp_len;
  char *concat_name;

  lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n",
                  nonempty (wrapper));

  if ((wrapper == NULL) || (*wrapper == '\0'))
    return NULL;

  /* Absolute path? */
#if defined HAVE_DOS_BASED_FILE_SYSTEM
  if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':')
    {
      concat_name = xstrdup (wrapper);
      if (check_executable (concat_name))
	return concat_name;
      XFREE (concat_name);
    }
  else
    {
#endif
      if (IS_DIR_SEPARATOR (wrapper[0]))
	{
	  concat_name = xstrdup (wrapper);
	  if (check_executable (concat_name))
	    return concat_name;
	  XFREE (concat_name);
	}
#if defined HAVE_DOS_BASED_FILE_SYSTEM
    }
#endif

  for (p = wrapper; *p; p++)
    if (*p == '/')
      {
	has_slash = 1;
	break;
      }
  if (!has_slash)
    {
      /* no slashes; search PATH */
      const char *path = getenv ("PATH");
      if (path != NULL)
	{
	  for (p = path; *p; p = p_next)
	    {
	      const char *q;
	      size_t p_len;
	      for (q = p; *q; q++)
		if (IS_PATH_SEPARATOR (*q))
		  break;
	      p_len = (size_t) (q - p);
	      p_next = (*q == '\0' ? q : q + 1);
	      if (p_len == 0)
		{
		  /* empty path: current directory */
		  if (getcwd (tmp, LT_PATHMAX) == NULL)
		    lt_fatal (__FILE__, __LINE__, "getcwd failed: %s",
                              nonnull (strerror (errno)));
		  tmp_len = strlen (tmp);
		  concat_name =
		    XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);
		  memcpy (concat_name, tmp, tmp_len);
		  concat_name[tmp_len] = '/';
		  strcpy (concat_name + tmp_len + 1, wrapper);
		}
	      else
		{
		  concat_name =
		    XMALLOC (char, p_len + 1 + strlen (wrapper) + 1);
		  memcpy (concat_name, p, p_len);
		  concat_name[p_len] = '/';
		  strcpy (concat_name + p_len + 1, wrapper);
		}
	      if (check_executable (concat_name))
		return concat_name;
	      XFREE (concat_name);
	    }
	}
      /* not found in PATH; assume curdir */
    }
  /* Relative path | not found in path: prepend cwd */
  if (getcwd (tmp, LT_PATHMAX) == NULL)
    lt_fatal (__FILE__, __LINE__, "getcwd failed: %s",
              nonnull (strerror (errno)));
  tmp_len = strlen (tmp);
  concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);
  memcpy (concat_name, tmp, tmp_len);
  concat_name[tmp_len] = '/';
  strcpy (concat_name + tmp_len + 1, wrapper);

  if (check_executable (concat_name))
    return concat_name;
  XFREE (concat_name);
  return NULL;
}

char *
chase_symlinks (const char *pathspec)
{
#ifndef S_ISLNK
  return xstrdup (pathspec);
#else
  char buf[LT_PATHMAX];
  struct stat s;
  char *tmp_pathspec = xstrdup (pathspec);
  char *p;
  int has_symlinks = 0;
  while (strlen (tmp_pathspec) && !has_symlinks)
    {
      lt_debugprintf (__FILE__, __LINE__,
		      "checking path component for symlinks: %s\n",
		      tmp_pathspec);
      if (lstat (tmp_pathspec, &s) == 0)
	{
	  if (S_ISLNK (s.st_mode) != 0)
	    {
	      has_symlinks = 1;
	      break;
	    }

	  /* search backwards for last DIR_SEPARATOR */
	  p = tmp_pathspec + strlen (tmp_pathspec) - 1;
	  while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p)))
	    p--;
	  if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p)))
	    {
	      /* no more DIR_SEPARATORS left */
	      break;
	    }
	  *p = '\0';
	}
      else
	{
	  lt_fatal (__FILE__, __LINE__,
		    "error accessing file \"%s\": %s",
		    tmp_pathspec, nonnull (strerror (errno)));
	}
    }
  XFREE (tmp_pathspec);

  if (!has_symlinks)
    {
      return xstrdup (pathspec);
    }

  tmp_pathspec = realpath (pathspec, buf);
  if (tmp_pathspec == 0)
    {
      lt_fatal (__FILE__, __LINE__,
		"could not follow symlinks for %s", pathspec);
    }
  return xstrdup (tmp_pathspec);
#endif
}

char *
strendzap (char *str, const char *pat)
{
  size_t len, patlen;

  assert (str != NULL);
  assert (pat != NULL);

  len = strlen (str);
  patlen = strlen (pat);

  if (patlen <= len)
    {
      str += len - patlen;
      if (STREQ (str, pat))
	*str = '\0';
    }
  return str;
}

void
lt_debugprintf (const char *file, int line, const char *fmt, ...)
{
  va_list args;
  if (lt_debug)
    {
      (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line);
      va_start (args, fmt);
      (void) vfprintf (stderr, fmt, args);
      va_end (args);
    }
}

static void
lt_error_core (int exit_status, const char *file,
	       int line, const char *mode,
	       const char *message, va_list ap)
{
  fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode);
  vfprintf (stderr, message, ap);
  fprintf (stderr, ".\n");

  if (exit_status >= 0)
    exit (exit_status);
}

void
lt_fatal (const char *file, int line, const char *message, ...)
{
  va_list ap;
  va_start (ap, message);
  lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap);
  va_end (ap);
}

static const char *
nonnull (const char *s)
{
  return s ? s : "(null)";
}

static const char *
nonempty (const char *s)
{
  return (s && !*s) ? "(empty)" : nonnull (s);
}

void
lt_setenv (const char *name, const char *value)
{
  lt_debugprintf (__FILE__, __LINE__,
		  "(lt_setenv) setting '%s' to '%s'\n",
                  nonnull (name), nonnull (value));
  {
#ifdef HAVE_SETENV
    /* always make a copy, for consistency with !HAVE_SETENV */
    char *str = xstrdup (value);
    setenv (name, str, 1);
#else
    size_t len = strlen (name) + 1 + strlen (value) + 1;
    char *str = XMALLOC (char, len);
    sprintf (str, "%s=%s", name, value);
    if (putenv (str) != EXIT_SUCCESS)
      {
        XFREE (str);
      }
#endif
  }
}

char *
lt_extend_str (const char *orig_value, const char *add, int to_end)
{
  char *new_value;
  if (orig_value && *orig_value)
    {
      size_t orig_value_len = strlen (orig_value);
      size_t add_len = strlen (add);
      new_value = XMALLOC (char, add_len + orig_value_len + 1);
      if (to_end)
        {
          strcpy (new_value, orig_value);
          strcpy (new_value + orig_value_len, add);
        }
      else
        {
          strcpy (new_value, add);
          strcpy (new_value + add_len, orig_value);
        }
    }
  else
    {
      new_value = xstrdup (add);
    }
  return new_value;
}

void
lt_update_exe_path (const char *name, const char *value)
{
  lt_debugprintf (__FILE__, __LINE__,
		  "(lt_update_exe_path) modifying '%s' by prepending '%s'\n",
                  nonnull (name), nonnull (value));

  if (name && *name && value && *value)
    {
      char *new_value = lt_extend_str (getenv (name), value, 0);
      /* some systems can't cope with a ':'-terminated path #' */
      size_t len = strlen (new_value);
      while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1]))
        {
          new_value[--len] = '\0';
        }
      lt_setenv (name, new_value);
      XFREE (new_value);
    }
}

void
lt_update_lib_path (const char *name, const char *value)
{
  lt_debugprintf (__FILE__, __LINE__,
		  "(lt_update_lib_path) modifying '%s' by prepending '%s'\n",
                  nonnull (name), nonnull (value));

  if (name && *name && value && *value)
    {
      char *new_value = lt_extend_str (getenv (name), value, 0);
      lt_setenv (name, new_value);
      XFREE (new_value);
    }
}

EOF
	    case $host_os in
	      mingw*)
		cat <<"EOF"

/* Prepares an argument vector before calling spawn().
   Note that spawn() does not by itself call the command interpreter
     (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") :
      ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
         GetVersionEx(&v);
         v.dwPlatformId == VER_PLATFORM_WIN32_NT;
      }) ? "cmd.exe" : "command.com").
   Instead it simply concatenates the arguments, separated by ' ', and calls
   CreateProcess().  We must quote the arguments since Win32 CreateProcess()
   interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a
   special way:
   - Space and tab are interpreted as delimiters. They are not treated as
     delimiters if they are surrounded by double quotes: "...".
   - Unescaped double quotes are removed from the input. Their only effect is
     that within double quotes, space and tab are treated like normal
     characters.
   - Backslashes not followed by double quotes are not special.
   - But 2*n+1 backslashes followed by a double quote become
     n backslashes followed by a double quote (n >= 0):
       \" -> "
       \\\" -> \"
       \\\\\" -> \\"
 */
#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
char **
prepare_spawn (char **argv)
{
  size_t argc;
  char **new_argv;
  size_t i;

  /* Count number of arguments.  */
  for (argc = 0; argv[argc] != NULL; argc++)
    ;

  /* Allocate new argument vector.  */
  new_argv = XMALLOC (char *, argc + 1);

  /* Put quoted arguments into the new argument vector.  */
  for (i = 0; i < argc; i++)
    {
      const char *string = argv[i];

      if (string[0] == '\0')
	new_argv[i] = xstrdup ("\"\"");
      else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL)
	{
	  int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL);
	  size_t length;
	  unsigned int backslashes;
	  const char *s;
	  char *quoted_string;
	  char *p;

	  length = 0;
	  backslashes = 0;
	  if (quote_around)
	    length++;
	  for (s = string; *s != '\0'; s++)
	    {
	      char c = *s;
	      if (c == '"')
		length += backslashes + 1;
	      length++;
	      if (c == '\\')
		backslashes++;
	      else
		backslashes = 0;
	    }
	  if (quote_around)
	    length += backslashes + 1;

	  quoted_string = XMALLOC (char, length + 1);

	  p = quoted_string;
	  backslashes = 0;
	  if (quote_around)
	    *p++ = '"';
	  for (s = string; *s != '\0'; s++)
	    {
	      char c = *s;
	      if (c == '"')
		{
		  unsigned int j;
		  for (j = backslashes + 1; j > 0; j--)
		    *p++ = '\\';
		}
	      *p++ = c;
	      if (c == '\\')
		backslashes++;
	      else
		backslashes = 0;
	    }
	  if (quote_around)
	    {
	      unsigned int j;
	      for (j = backslashes; j > 0; j--)
		*p++ = '\\';
	      *p++ = '"';
	    }
	  *p = '\0';

	  new_argv[i] = quoted_string;
	}
      else
	new_argv[i] = (char *) string;
    }
  new_argv[argc] = NULL;

  return new_argv;
}
EOF
		;;
	    esac

            cat <<"EOF"
void lt_dump_script (FILE* f)
{
EOF
	    func_emit_wrapper yes |
	      $SED -n -e '
s/^\(.\{79\}\)\(..*\)/\1\
\2/
h
s/\([\\"]\)/\\\1/g
s/$/\\n/
s/\([^\n]*\).*/  fputs ("\1", f);/p
g
D'
            cat <<"EOF"
}
EOF
}
# end: func_emit_cwrapperexe_src

# func_win32_import_lib_p ARG
# True if ARG is an import lib, as indicated by $file_magic_cmd
func_win32_import_lib_p ()
{
    $debug_cmd

    case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in
    *import*) : ;;
    *) false ;;
    esac
}

# func_suncc_cstd_abi
# !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!!
# Several compiler flags select an ABI that is incompatible with the
# Cstd library. Avoid specifying it if any are in CXXFLAGS.
func_suncc_cstd_abi ()
{
    $debug_cmd

    case " $compile_command " in
    *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*)
      suncc_use_cstd_abi=no
      ;;
    *)
      suncc_use_cstd_abi=yes
      ;;
    esac
}

# func_mode_link arg...
func_mode_link ()
{
    $debug_cmd

    case $host in
    *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
      # It is impossible to link a dll without this setting, and
      # we shouldn't force the makefile maintainer to figure out
      # what system we are compiling for in order to pass an extra
      # flag for every libtool invocation.
      # allow_undefined=no

      # FIXME: Unfortunately, there are problems with the above when trying
      # to make a dll that has undefined symbols, in which case not
      # even a static library is built.  For now, we need to specify
      # -no-undefined on the libtool link line when we can be certain
      # that all symbols are satisfied, otherwise we get a static library.
      allow_undefined=yes
      ;;
    *)
      allow_undefined=yes
      ;;
    esac
    libtool_args=$nonopt
    base_compile="$nonopt $@"
    compile_command=$nonopt
    finalize_command=$nonopt

    compile_rpath=
    finalize_rpath=
    compile_shlibpath=
    finalize_shlibpath=
    convenience=
    old_convenience=
    deplibs=
    old_deplibs=
    compiler_flags=
    linker_flags=
    dllsearchpath=
    lib_search_path=`pwd`
    inst_prefix_dir=
    new_inherited_linker_flags=

    avoid_version=no
    bindir=
    dlfiles=
    dlprefiles=
    dlself=no
    export_dynamic=no
    export_symbols=
    export_symbols_regex=
    generated=
    libobjs=
    ltlibs=
    module=no
    no_install=no
    objs=
    os2dllname=
    non_pic_objects=
    precious_files_regex=
    prefer_static_libs=no
    preload=false
    prev=
    prevarg=
    release=
    rpath=
    xrpath=
    perm_rpath=
    temp_rpath=
    thread_safe=no
    vinfo=
    vinfo_number=no
    weak_libs=
    single_module=$wl-single_module
    func_infer_tag $base_compile

    # We need to know -static, to get the right output filenames.
    for arg
    do
      case $arg in
      -shared)
	test yes != "$build_libtool_libs" \
	  && func_fatal_configuration "cannot build a shared library"
	build_old_libs=no
	break
	;;
      -all-static | -static | -static-libtool-libs)
	case $arg in
	-all-static)
	  if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then
	    func_warning "complete static linking is impossible in this configuration"
	  fi
	  if test -n "$link_static_flag"; then
	    dlopen_self=$dlopen_self_static
	  fi
	  prefer_static_libs=yes
	  ;;
	-static)
	  if test -z "$pic_flag" && test -n "$link_static_flag"; then
	    dlopen_self=$dlopen_self_static
	  fi
	  prefer_static_libs=built
	  ;;
	-static-libtool-libs)
	  if test -z "$pic_flag" && test -n "$link_static_flag"; then
	    dlopen_self=$dlopen_self_static
	  fi
	  prefer_static_libs=yes
	  ;;
	esac
	build_libtool_libs=no
	build_old_libs=yes
	break
	;;
      esac
    done

    # See if our shared archives depend on static archives.
    test -n "$old_archive_from_new_cmds" && build_old_libs=yes

    # Go through the arguments, transforming them on the way.
    while test "$#" -gt 0; do
      arg=$1
      shift
      func_quote_for_eval "$arg"
      qarg=$func_quote_for_eval_unquoted_result
      func_append libtool_args " $func_quote_for_eval_result"

      # If the previous option needs an argument, assign it.
      if test -n "$prev"; then
	case $prev in
	output)
	  func_append compile_command " @OUTPUT@"
	  func_append finalize_command " @OUTPUT@"
	  ;;
	esac

	case $prev in
	bindir)
	  bindir=$arg
	  prev=
	  continue
	  ;;
	dlfiles|dlprefiles)
	  $preload || {
	    # Add the symbol object into the linking commands.
	    func_append compile_command " @SYMFILE@"
	    func_append finalize_command " @SYMFILE@"
	    preload=:
	  }
	  case $arg in
	  *.la | *.lo) ;;  # We handle these cases below.
	  force)
	    if test no = "$dlself"; then
	      dlself=needless
	      export_dynamic=yes
	    fi
	    prev=
	    continue
	    ;;
	  self)
	    if test dlprefiles = "$prev"; then
	      dlself=yes
	    elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then
	      dlself=yes
	    else
	      dlself=needless
	      export_dynamic=yes
	    fi
	    prev=
	    continue
	    ;;
	  *)
	    if test dlfiles = "$prev"; then
	      func_append dlfiles " $arg"
	    else
	      func_append dlprefiles " $arg"
	    fi
	    prev=
	    continue
	    ;;
	  esac
	  ;;
	expsyms)
	  export_symbols=$arg
	  test -f "$arg" \
	    || func_fatal_error "symbol file '$arg' does not exist"
	  prev=
	  continue
	  ;;
	expsyms_regex)
	  export_symbols_regex=$arg
	  prev=
	  continue
	  ;;
	framework)
	  case $host in
	    *-*-darwin*)
	      case "$deplibs " in
		*" $qarg.ltframework "*) ;;
		*) func_append deplibs " $qarg.ltframework" # this is fixed later
		   ;;
	      esac
	      ;;
	  esac
	  prev=
	  continue
	  ;;
	inst_prefix)
	  inst_prefix_dir=$arg
	  prev=
	  continue
	  ;;
	mllvm)
	  # Clang does not use LLVM to link, so we can simply discard any
	  # '-mllvm $arg' options when doing the link step.
	  prev=
	  continue
	  ;;
	objectlist)
	  if test -f "$arg"; then
	    save_arg=$arg
	    moreargs=
	    for fil in `cat "$save_arg"`
	    do
#	      func_append moreargs " $fil"
	      arg=$fil
	      # A libtool-controlled object.

	      # Check to see that this really is a libtool object.
	      if func_lalib_unsafe_p "$arg"; then
		pic_object=
		non_pic_object=

		# Read the .lo file
		func_source "$arg"

		if test -z "$pic_object" ||
		   test -z "$non_pic_object" ||
		   test none = "$pic_object" &&
		   test none = "$non_pic_object"; then
		  func_fatal_error "cannot find name of object for '$arg'"
		fi

		# Extract subdirectory from the argument.
		func_dirname "$arg" "/" ""
		xdir=$func_dirname_result

		if test none != "$pic_object"; then
		  # Prepend the subdirectory the object is found in.
		  pic_object=$xdir$pic_object

		  if test dlfiles = "$prev"; then
		    if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then
		      func_append dlfiles " $pic_object"
		      prev=
		      continue
		    else
		      # If libtool objects are unsupported, then we need to preload.
		      prev=dlprefiles
		    fi
		  fi

		  # CHECK ME:  I think I busted this.  -Ossama
		  if test dlprefiles = "$prev"; then
		    # Preload the old-style object.
		    func_append dlprefiles " $pic_object"
		    prev=
		  fi

		  # A PIC object.
		  func_append libobjs " $pic_object"
		  arg=$pic_object
		fi

		# Non-PIC object.
		if test none != "$non_pic_object"; then
		  # Prepend the subdirectory the object is found in.
		  non_pic_object=$xdir$non_pic_object

		  # A standard non-PIC object
		  func_append non_pic_objects " $non_pic_object"
		  if test -z "$pic_object" || test none = "$pic_object"; then
		    arg=$non_pic_object
		  fi
		else
		  # If the PIC object exists, use it instead.
		  # $xdir was prepended to $pic_object above.
		  non_pic_object=$pic_object
		  func_append non_pic_objects " $non_pic_object"
		fi
	      else
		# Only an error if not doing a dry-run.
		if $opt_dry_run; then
		  # Extract subdirectory from the argument.
		  func_dirname "$arg" "/" ""
		  xdir=$func_dirname_result

		  func_lo2o "$arg"
		  pic_object=$xdir$objdir/$func_lo2o_result
		  non_pic_object=$xdir$func_lo2o_result
		  func_append libobjs " $pic_object"
		  func_append non_pic_objects " $non_pic_object"
	        else
		  func_fatal_error "'$arg' is not a valid libtool object"
		fi
	      fi
	    done
	  else
	    func_fatal_error "link input file '$arg' does not exist"
	  fi
	  arg=$save_arg
	  prev=
	  continue
	  ;;
	os2dllname)
	  os2dllname=$arg
	  prev=
	  continue
	  ;;
	precious_regex)
	  precious_files_regex=$arg
	  prev=
	  continue
	  ;;
	release)
	  release=-$arg
	  prev=
	  continue
	  ;;
	rpath | xrpath)
	  # We need an absolute path.
	  case $arg in
	  [\\/]* | [A-Za-z]:[\\/]*) ;;
	  *)
	    func_fatal_error "only absolute run-paths are allowed"
	    ;;
	  esac
	  if test rpath = "$prev"; then
	    case "$rpath " in
	    *" $arg "*) ;;
	    *) func_append rpath " $arg" ;;
	    esac
	  else
	    case "$xrpath " in
	    *" $arg "*) ;;
	    *) func_append xrpath " $arg" ;;
	    esac
	  fi
	  prev=
	  continue
	  ;;
	shrext)
	  shrext_cmds=$arg
	  prev=
	  continue
	  ;;
	weak)
	  func_append weak_libs " $arg"
	  prev=
	  continue
	  ;;
	xcclinker)
	  func_append linker_flags " $qarg"
	  func_append compiler_flags " $qarg"
	  prev=
	  func_append compile_command " $qarg"
	  func_append finalize_command " $qarg"
	  continue
	  ;;
	xcompiler)
	  func_append compiler_flags " $qarg"
	  prev=
	  func_append compile_command " $qarg"
	  func_append finalize_command " $qarg"
	  continue
	  ;;
	xlinker)
	  func_append linker_flags " $qarg"
	  func_append compiler_flags " $wl$qarg"
	  prev=
	  func_append compile_command " $wl$qarg"
	  func_append finalize_command " $wl$qarg"
	  continue
	  ;;
	*)
	  eval "$prev=\"\$arg\""
	  prev=
	  continue
	  ;;
	esac
      fi # test -n "$prev"

      prevarg=$arg

      case $arg in
      -all-static)
	if test -n "$link_static_flag"; then
	  # See comment for -static flag below, for more details.
	  func_append compile_command " $link_static_flag"
	  func_append finalize_command " $link_static_flag"
	fi
	continue
	;;

      -allow-undefined)
	# FIXME: remove this flag sometime in the future.
	func_fatal_error "'-allow-undefined' must not be used because it is the default"
	;;

      -avoid-version)
	avoid_version=yes
	continue
	;;

      -bindir)
	prev=bindir
	continue
	;;

      -dlopen)
	prev=dlfiles
	continue
	;;

      -dlpreopen)
	prev=dlprefiles
	continue
	;;

      -export-dynamic)
	export_dynamic=yes
	continue
	;;

      -export-symbols | -export-symbols-regex)
	if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
	  func_fatal_error "more than one -exported-symbols argument is not allowed"
	fi
	if test X-export-symbols = "X$arg"; then
	  prev=expsyms
	else
	  prev=expsyms_regex
	fi
	continue
	;;

      -framework)
	prev=framework
	continue
	;;

      -inst-prefix-dir)
	prev=inst_prefix
	continue
	;;

      # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:*
      # so, if we see these flags be careful not to treat them like -L
      -L[A-Z][A-Z]*:*)
	case $with_gcc/$host in
	no/*-*-irix* | /*-*-irix*)
	  func_append compile_command " $arg"
	  func_append finalize_command " $arg"
	  ;;
	esac
	continue
	;;

      -L*)
	func_stripname "-L" '' "$arg"
	if test -z "$func_stripname_result"; then
	  if test "$#" -gt 0; then
	    func_fatal_error "require no space between '-L' and '$1'"
	  else
	    func_fatal_error "need path for '-L' option"
	  fi
	fi
	func_resolve_sysroot "$func_stripname_result"
	dir=$func_resolve_sysroot_result
	# We need an absolute path.
	case $dir in
	[\\/]* | [A-Za-z]:[\\/]*) ;;
	*)
	  absdir=`cd "$dir" && pwd`
	  test -z "$absdir" && \
	    func_fatal_error "cannot determine absolute directory name of '$dir'"
	  dir=$absdir
	  ;;
	esac
	case "$deplibs " in
	*" -L$dir "* | *" $arg "*)
	  # Will only happen for absolute or sysroot arguments
	  ;;
	*)
	  # Preserve sysroot, but never include relative directories
	  case $dir in
	    [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;;
	    *) func_append deplibs " -L$dir" ;;
	  esac
	  func_append lib_search_path " $dir"
	  ;;
	esac
	case $host in
	*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
	  testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'`
	  case :$dllsearchpath: in
	  *":$dir:"*) ;;
	  ::) dllsearchpath=$dir;;
	  *) func_append dllsearchpath ":$dir";;
	  esac
	  case :$dllsearchpath: in
	  *":$testbindir:"*) ;;
	  ::) dllsearchpath=$testbindir;;
	  *) func_append dllsearchpath ":$testbindir";;
	  esac
	  ;;
	esac
	continue
	;;

      -l*)
	if test X-lc = "X$arg" || test X-lm = "X$arg"; then
	  case $host in
	  *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*)
	    # These systems don't actually have a C or math library (as such)
	    continue
	    ;;
	  *-*-os2*)
	    # These systems don't actually have a C library (as such)
	    test X-lc = "X$arg" && continue
	    ;;
	  *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*)
	    # Do not include libc due to us having libc/libc_r.
	    test X-lc = "X$arg" && continue
	    ;;
	  *-*-rhapsody* | *-*-darwin1.[012])
	    # Rhapsody C and math libraries are in the System framework
	    func_append deplibs " System.ltframework"
	    continue
	    ;;
	  *-*-sco3.2v5* | *-*-sco5v6*)
	    # Causes problems with __ctype
	    test X-lc = "X$arg" && continue
	    ;;
	  *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
	    # Compiler inserts libc in the correct place for threads to work
	    test X-lc = "X$arg" && continue
	    ;;
	  esac
	elif test X-lc_r = "X$arg"; then
	 case $host in
	 *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*)
	   # Do not include libc_r directly, use -pthread flag.
	   continue
	   ;;
	 esac
	fi
	func_append deplibs " $arg"
	continue
	;;

      -mllvm)
	prev=mllvm
	continue
	;;

      -module)
	module=yes
	continue
	;;

      # Tru64 UNIX uses -model [arg] to determine the layout of C++
      # classes, name mangling, and exception handling.
      # Darwin uses the -arch flag to determine output architecture.
      -model|-arch|-isysroot|--sysroot)
	func_append compiler_flags " $arg"
	func_append compile_command " $arg"
	func_append finalize_command " $arg"
	prev=xcompiler
	continue
	;;

      -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \
      |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*)
	func_append compiler_flags " $arg"
	func_append compile_command " $arg"
	func_append finalize_command " $arg"
	case "$new_inherited_linker_flags " in
	    *" $arg "*) ;;
	    * ) func_append new_inherited_linker_flags " $arg" ;;
	esac
	continue
	;;

      -multi_module)
	single_module=$wl-multi_module
	continue
	;;

      -no-fast-install)
	fast_install=no
	continue
	;;

      -no-install)
	case $host in
	*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*)
	  # The PATH hackery in wrapper scripts is required on Windows
	  # and Darwin in order for the loader to find any dlls it needs.
	  func_warning "'-no-install' is ignored for $host"
	  func_warning "assuming '-no-fast-install' instead"
	  fast_install=no
	  ;;
	*) no_install=yes ;;
	esac
	continue
	;;

      -no-undefined)
	allow_undefined=no
	continue
	;;

      -objectlist)
	prev=objectlist
	continue
	;;

      -os2dllname)
	prev=os2dllname
	continue
	;;

      -o) prev=output ;;

      -precious-files-regex)
	prev=precious_regex
	continue
	;;

      -release)
	prev=release
	continue
	;;

      -rpath)
	prev=rpath
	continue
	;;

      -R)
	prev=xrpath
	continue
	;;

      -R*)
	func_stripname '-R' '' "$arg"
	dir=$func_stripname_result
	# We need an absolute path.
	case $dir in
	[\\/]* | [A-Za-z]:[\\/]*) ;;
	=*)
	  func_stripname '=' '' "$dir"
	  dir=$lt_sysroot$func_stripname_result
	  ;;
	*)
	  func_fatal_error "only absolute run-paths are allowed"
	  ;;
	esac
	case "$xrpath " in
	*" $dir "*) ;;
	*) func_append xrpath " $dir" ;;
	esac
	continue
	;;

      -shared)
	# The effects of -shared are defined in a previous loop.
	continue
	;;

      -shrext)
	prev=shrext
	continue
	;;

      -static | -static-libtool-libs)
	# The effects of -static are defined in a previous loop.
	# We used to do the same as -all-static on platforms that
	# didn't have a PIC flag, but the assumption that the effects
	# would be equivalent was wrong.  It would break on at least
	# Digital Unix and AIX.
	continue
	;;

      -thread-safe)
	thread_safe=yes
	continue
	;;

      -version-info)
	prev=vinfo
	continue
	;;

      -version-number)
	prev=vinfo
	vinfo_number=yes
	continue
	;;

      -weak)
        prev=weak
	continue
	;;

      -Wc,*)
	func_stripname '-Wc,' '' "$arg"
	args=$func_stripname_result
	arg=
	save_ifs=$IFS; IFS=,
	for flag in $args; do
	  IFS=$save_ifs
          func_quote_for_eval "$flag"
	  func_append arg " $func_quote_for_eval_result"
	  func_append compiler_flags " $func_quote_for_eval_result"
	done
	IFS=$save_ifs
	func_stripname ' ' '' "$arg"
	arg=$func_stripname_result
	;;

      -Wl,*)
	func_stripname '-Wl,' '' "$arg"
	args=$func_stripname_result
	arg=
	save_ifs=$IFS; IFS=,
	for flag in $args; do
	  IFS=$save_ifs
          func_quote_for_eval "$flag"
	  func_append arg " $wl$func_quote_for_eval_result"
	  func_append compiler_flags " $wl$func_quote_for_eval_result"
	  func_append linker_flags " $func_quote_for_eval_result"
	done
	IFS=$save_ifs
	func_stripname ' ' '' "$arg"
	arg=$func_stripname_result
	;;

      -Xcompiler)
	prev=xcompiler
	continue
	;;

      -Xlinker)
	prev=xlinker
	continue
	;;

      -XCClinker)
	prev=xcclinker
	continue
	;;

      # -msg_* for osf cc
      -msg_*)
	func_quote_for_eval "$arg"
	arg=$func_quote_for_eval_result
	;;

      # Flags to be passed through unchanged, with rationale:
      # -64, -mips[0-9]      enable 64-bit mode for the SGI compiler
      # -r[0-9][0-9]*        specify processor for the SGI compiler
      # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler
      # +DA*, +DD*           enable 64-bit mode for the HP compiler
      # -q*                  compiler args for the IBM compiler
      # -m*, -t[45]*, -txscale* architecture-specific flags for GCC
      # -F/path              path to uninstalled frameworks, gcc on darwin
      # -p, -pg, --coverage, -fprofile-*  profiling flags for GCC
      # -fstack-protector*   stack protector flags for GCC
      # @file                GCC response files
      # -tp=*                Portland pgcc target processor selection
      # --sysroot=*          for sysroot support
      # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization
      # -specs=*             GCC specs files
      # -stdlib=*            select c++ std lib with clang
      # -fsanitize=*         Clang/GCC memory and address sanitizer
      -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \
      -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \
      -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \
      -specs=*|-fsanitize=*)
        func_quote_for_eval "$arg"
	arg=$func_quote_for_eval_result
        func_append compile_command " $arg"
        func_append finalize_command " $arg"
        func_append compiler_flags " $arg"
        continue
        ;;

      -Z*)
        if test os2 = "`expr $host : '.*\(os2\)'`"; then
          # OS/2 uses -Zxxx to specify OS/2-specific options
	  compiler_flags="$compiler_flags $arg"
	  func_append compile_command " $arg"
	  func_append finalize_command " $arg"
	  case $arg in
	  -Zlinker | -Zstack)
	    prev=xcompiler
	    ;;
	  esac
	  continue
        else
	  # Otherwise treat like 'Some other compiler flag' below
	  func_quote_for_eval "$arg"
	  arg=$func_quote_for_eval_result
        fi
	;;

      # Some other compiler flag.
      -* | +*)
        func_quote_for_eval "$arg"
	arg=$func_quote_for_eval_result
	;;

      *.$objext)
	# A standard object.
	func_append objs " $arg"
	;;

      *.lo)
	# A libtool-controlled object.

	# Check to see that this really is a libtool object.
	if func_lalib_unsafe_p "$arg"; then
	  pic_object=
	  non_pic_object=

	  # Read the .lo file
	  func_source "$arg"

	  if test -z "$pic_object" ||
	     test -z "$non_pic_object" ||
	     test none = "$pic_object" &&
	     test none = "$non_pic_object"; then
	    func_fatal_error "cannot find name of object for '$arg'"
	  fi

	  # Extract subdirectory from the argument.
	  func_dirname "$arg" "/" ""
	  xdir=$func_dirname_result

	  test none = "$pic_object" || {
	    # Prepend the subdirectory the object is found in.
	    pic_object=$xdir$pic_object

	    if test dlfiles = "$prev"; then
	      if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then
		func_append dlfiles " $pic_object"
		prev=
		continue
	      else
		# If libtool objects are unsupported, then we need to preload.
		prev=dlprefiles
	      fi
	    fi

	    # CHECK ME:  I think I busted this.  -Ossama
	    if test dlprefiles = "$prev"; then
	      # Preload the old-style object.
	      func_append dlprefiles " $pic_object"
	      prev=
	    fi

	    # A PIC object.
	    func_append libobjs " $pic_object"
	    arg=$pic_object
	  }

	  # Non-PIC object.
	  if test none != "$non_pic_object"; then
	    # Prepend the subdirectory the object is found in.
	    non_pic_object=$xdir$non_pic_object

	    # A standard non-PIC object
	    func_append non_pic_objects " $non_pic_object"
	    if test -z "$pic_object" || test none = "$pic_object"; then
	      arg=$non_pic_object
	    fi
	  else
	    # If the PIC object exists, use it instead.
	    # $xdir was prepended to $pic_object above.
	    non_pic_object=$pic_object
	    func_append non_pic_objects " $non_pic_object"
	  fi
	else
	  # Only an error if not doing a dry-run.
	  if $opt_dry_run; then
	    # Extract subdirectory from the argument.
	    func_dirname "$arg" "/" ""
	    xdir=$func_dirname_result

	    func_lo2o "$arg"
	    pic_object=$xdir$objdir/$func_lo2o_result
	    non_pic_object=$xdir$func_lo2o_result
	    func_append libobjs " $pic_object"
	    func_append non_pic_objects " $non_pic_object"
	  else
	    func_fatal_error "'$arg' is not a valid libtool object"
	  fi
	fi
	;;

      *.$libext)
	# An archive.
	func_append deplibs " $arg"
	func_append old_deplibs " $arg"
	continue
	;;

      *.la)
	# A libtool-controlled library.

	func_resolve_sysroot "$arg"
	if test dlfiles = "$prev"; then
	  # This library was specified with -dlopen.
	  func_append dlfiles " $func_resolve_sysroot_result"
	  prev=
	elif test dlprefiles = "$prev"; then
	  # The library was specified with -dlpreopen.
	  func_append dlprefiles " $func_resolve_sysroot_result"
	  prev=
	else
	  func_append deplibs " $func_resolve_sysroot_result"
	fi
	continue
	;;

      # Some other compiler argument.
      *)
	# Unknown arguments in both finalize_command and compile_command need
	# to be aesthetically quoted because they are evaled later.
	func_quote_for_eval "$arg"
	arg=$func_quote_for_eval_result
	;;
      esac # arg

      # Now actually substitute the argument into the commands.
      if test -n "$arg"; then
	func_append compile_command " $arg"
	func_append finalize_command " $arg"
      fi
    done # argument parsing loop

    test -n "$prev" && \
      func_fatal_help "the '$prevarg' option requires an argument"

    if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then
      eval arg=\"$export_dynamic_flag_spec\"
      func_append compile_command " $arg"
      func_append finalize_command " $arg"
    fi

    oldlibs=
    # calculate the name of the file, without its directory
    func_basename "$output"
    outputname=$func_basename_result
    libobjs_save=$libobjs

    if test -n "$shlibpath_var"; then
      # get the directories listed in $shlibpath_var
      eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\`
    else
      shlib_search_path=
    fi
    eval sys_lib_search_path=\"$sys_lib_search_path_spec\"
    eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"

    # Definition is injected by LT_CONFIG during libtool generation.
    func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH"

    func_dirname "$output" "/" ""
    output_objdir=$func_dirname_result$objdir
    func_to_tool_file "$output_objdir/"
    tool_output_objdir=$func_to_tool_file_result
    # Create the object directory.
    func_mkdir_p "$output_objdir"

    # Determine the type of output
    case $output in
    "")
      func_fatal_help "you must specify an output file"
      ;;
    *.$libext) linkmode=oldlib ;;
    *.lo | *.$objext) linkmode=obj ;;
    *.la) linkmode=lib ;;
    *) linkmode=prog ;; # Anything else should be a program.
    esac

    specialdeplibs=

    libs=
    # Find all interdependent deplibs by searching for libraries
    # that are linked more than once (e.g. -la -lb -la)
    for deplib in $deplibs; do
      if $opt_preserve_dup_deps; then
	case "$libs " in
	*" $deplib "*) func_append specialdeplibs " $deplib" ;;
	esac
      fi
      func_append libs " $deplib"
    done

    if test lib = "$linkmode"; then
      libs="$predeps $libs $compiler_lib_search_path $postdeps"

      # Compute libraries that are listed more than once in $predeps
      # $postdeps and mark them as special (i.e., whose duplicates are
      # not to be eliminated).
      pre_post_deps=
      if $opt_duplicate_compiler_generated_deps; then
	for pre_post_dep in $predeps $postdeps; do
	  case "$pre_post_deps " in
	  *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;;
	  esac
	  func_append pre_post_deps " $pre_post_dep"
	done
      fi
      pre_post_deps=
    fi

    deplibs=
    newdependency_libs=
    newlib_search_path=
    need_relink=no # whether we're linking any uninstalled libtool libraries
    notinst_deplibs= # not-installed libtool libraries
    notinst_path= # paths that contain not-installed libtool libraries

    case $linkmode in
    lib)
	passes="conv dlpreopen link"
	for file in $dlfiles $dlprefiles; do
	  case $file in
	  *.la) ;;
	  *)
	    func_fatal_help "libraries can '-dlopen' only libtool libraries: $file"
	    ;;
	  esac
	done
	;;
    prog)
	compile_deplibs=
	finalize_deplibs=
	alldeplibs=false
	newdlfiles=
	newdlprefiles=
	passes="conv scan dlopen dlpreopen link"
	;;
    *)  passes="conv"
	;;
    esac

    for pass in $passes; do
      # The preopen pass in lib mode reverses $deplibs; put it back here
      # so that -L comes before libs that need it for instance...
      if test lib,link = "$linkmode,$pass"; then
	## FIXME: Find the place where the list is rebuilt in the wrong
	##        order, and fix it there properly
        tmp_deplibs=
	for deplib in $deplibs; do
	  tmp_deplibs="$deplib $tmp_deplibs"
	done
	deplibs=$tmp_deplibs
      fi

      if test lib,link = "$linkmode,$pass" ||
	 test prog,scan = "$linkmode,$pass"; then
	libs=$deplibs
	deplibs=
      fi
      if test prog = "$linkmode"; then
	case $pass in
	dlopen) libs=$dlfiles ;;
	dlpreopen) libs=$dlprefiles ;;
	link)
	  libs="$deplibs %DEPLIBS%"
	  test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs"
	  ;;
	esac
      fi
      if test lib,dlpreopen = "$linkmode,$pass"; then
	# Collect and forward deplibs of preopened libtool libs
	for lib in $dlprefiles; do
	  # Ignore non-libtool-libs
	  dependency_libs=
	  func_resolve_sysroot "$lib"
	  case $lib in
	  *.la)	func_source "$func_resolve_sysroot_result" ;;
	  esac

	  # Collect preopened libtool deplibs, except any this library
	  # has declared as weak libs
	  for deplib in $dependency_libs; do
	    func_basename "$deplib"
            deplib_base=$func_basename_result
	    case " $weak_libs " in
	    *" $deplib_base "*) ;;
	    *) func_append deplibs " $deplib" ;;
	    esac
	  done
	done
	libs=$dlprefiles
      fi
      if test dlopen = "$pass"; then
	# Collect dlpreopened libraries
	save_deplibs=$deplibs
	deplibs=
      fi

      for deplib in $libs; do
	lib=
	found=false
	case $deplib in
	-mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \
        |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*)
	  if test prog,link = "$linkmode,$pass"; then
	    compile_deplibs="$deplib $compile_deplibs"
	    finalize_deplibs="$deplib $finalize_deplibs"
	  else
	    func_append compiler_flags " $deplib"
	    if test lib = "$linkmode"; then
		case "$new_inherited_linker_flags " in
		    *" $deplib "*) ;;
		    * ) func_append new_inherited_linker_flags " $deplib" ;;
		esac
	    fi
	  fi
	  continue
	  ;;
	-l*)
	  if test lib != "$linkmode" && test prog != "$linkmode"; then
	    func_warning "'-l' is ignored for archives/objects"
	    continue
	  fi
	  func_stripname '-l' '' "$deplib"
	  name=$func_stripname_result
	  if test lib = "$linkmode"; then
	    searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path"
	  else
	    searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path"
	  fi
	  for searchdir in $searchdirs; do
	    for search_ext in .la $std_shrext .so .a; do
	      # Search the libtool library
	      lib=$searchdir/lib$name$search_ext
	      if test -f "$lib"; then
		if test .la = "$search_ext"; then
		  found=:
		else
		  found=false
		fi
		break 2
	      fi
	    done
	  done
	  if $found; then
	    # deplib is a libtool library
	    # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib,
	    # We need to do some special things here, and not later.
	    if test yes = "$allow_libtool_libs_with_static_runtimes"; then
	      case " $predeps $postdeps " in
	      *" $deplib "*)
		if func_lalib_p "$lib"; then
		  library_names=
		  old_library=
		  func_source "$lib"
		  for l in $old_library $library_names; do
		    ll=$l
		  done
		  if test "X$ll" = "X$old_library"; then # only static version available
		    found=false
		    func_dirname "$lib" "" "."
		    ladir=$func_dirname_result
		    lib=$ladir/$old_library
		    if test prog,link = "$linkmode,$pass"; then
		      compile_deplibs="$deplib $compile_deplibs"
		      finalize_deplibs="$deplib $finalize_deplibs"
		    else
		      deplibs="$deplib $deplibs"
		      test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs"
		    fi
		    continue
		  fi
		fi
		;;
	      *) ;;
	      esac
	    fi
	  else
	    # deplib doesn't seem to be a libtool library
	    if test prog,link = "$linkmode,$pass"; then
	      compile_deplibs="$deplib $compile_deplibs"
	      finalize_deplibs="$deplib $finalize_deplibs"
	    else
	      deplibs="$deplib $deplibs"
	      test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs"
	    fi
	    continue
	  fi
	  ;; # -l
	*.ltframework)
	  if test prog,link = "$linkmode,$pass"; then
	    compile_deplibs="$deplib $compile_deplibs"
	    finalize_deplibs="$deplib $finalize_deplibs"
	  else
	    deplibs="$deplib $deplibs"
	    if test lib = "$linkmode"; then
		case "$new_inherited_linker_flags " in
		    *" $deplib "*) ;;
		    * ) func_append new_inherited_linker_flags " $deplib" ;;
		esac
	    fi
	  fi
	  continue
	  ;;
	-L*)
	  case $linkmode in
	  lib)
	    deplibs="$deplib $deplibs"
	    test conv = "$pass" && continue
	    newdependency_libs="$deplib $newdependency_libs"
	    func_stripname '-L' '' "$deplib"
	    func_resolve_sysroot "$func_stripname_result"
	    func_append newlib_search_path " $func_resolve_sysroot_result"
	    ;;
	  prog)
	    if test conv = "$pass"; then
	      deplibs="$deplib $deplibs"
	      continue
	    fi
	    if test scan = "$pass"; then
	      deplibs="$deplib $deplibs"
	    else
	      compile_deplibs="$deplib $compile_deplibs"
	      finalize_deplibs="$deplib $finalize_deplibs"
	    fi
	    func_stripname '-L' '' "$deplib"
	    func_resolve_sysroot "$func_stripname_result"
	    func_append newlib_search_path " $func_resolve_sysroot_result"
	    ;;
	  *)
	    func_warning "'-L' is ignored for archives/objects"
	    ;;
	  esac # linkmode
	  continue
	  ;; # -L
	-R*)
	  if test link = "$pass"; then
	    func_stripname '-R' '' "$deplib"
	    func_resolve_sysroot "$func_stripname_result"
	    dir=$func_resolve_sysroot_result
	    # Make sure the xrpath contains only unique directories.
	    case "$xrpath " in
	    *" $dir "*) ;;
	    *) func_append xrpath " $dir" ;;
	    esac
	  fi
	  deplibs="$deplib $deplibs"
	  continue
	  ;;
	*.la)
	  func_resolve_sysroot "$deplib"
	  lib=$func_resolve_sysroot_result
	  ;;
	*.$libext)
	  if test conv = "$pass"; then
	    deplibs="$deplib $deplibs"
	    continue
	  fi
	  case $linkmode in
	  lib)
	    # Linking convenience modules into shared libraries is allowed,
	    # but linking other static libraries is non-portable.
	    case " $dlpreconveniencelibs " in
	    *" $deplib "*) ;;
	    *)
	      valid_a_lib=false
	      case $deplibs_check_method in
		match_pattern*)
		  set dummy $deplibs_check_method; shift
		  match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
		  if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \
		    | $EGREP "$match_pattern_regex" > /dev/null; then
		    valid_a_lib=:
		  fi
		;;
		pass_all)
		  valid_a_lib=:
		;;
	      esac
	      if $valid_a_lib; then
		echo
		$ECHO "*** Warning: Linking the shared library $output against the"
		$ECHO "*** static library $deplib is not portable!"
		deplibs="$deplib $deplibs"
	      else
		echo
		$ECHO "*** Warning: Trying to link with static lib archive $deplib."
		echo "*** I have the capability to make that library automatically link in when"
		echo "*** you link to this library.  But I can only do this if you have a"
		echo "*** shared version of the library, which you do not appear to have"
		echo "*** because the file extensions .$libext of this argument makes me believe"
		echo "*** that it is just a static archive that I should not use here."
	      fi
	      ;;
	    esac
	    continue
	    ;;
	  prog)
	    if test link != "$pass"; then
	      deplibs="$deplib $deplibs"
	    else
	      compile_deplibs="$deplib $compile_deplibs"
	      finalize_deplibs="$deplib $finalize_deplibs"
	    fi
	    continue
	    ;;
	  esac # linkmode
	  ;; # *.$libext
	*.lo | *.$objext)
	  if test conv = "$pass"; then
	    deplibs="$deplib $deplibs"
	  elif test prog = "$linkmode"; then
	    if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then
	      # If there is no dlopen support or we're linking statically,
	      # we need to preload.
	      func_append newdlprefiles " $deplib"
	      compile_deplibs="$deplib $compile_deplibs"
	      finalize_deplibs="$deplib $finalize_deplibs"
	    else
	      func_append newdlfiles " $deplib"
	    fi
	  fi
	  continue
	  ;;
	%DEPLIBS%)
	  alldeplibs=:
	  continue
	  ;;
	esac # case $deplib

	$found || test -f "$lib" \
	  || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'"

	# Check to see that this really is a libtool archive.
	func_lalib_unsafe_p "$lib" \
	  || func_fatal_error "'$lib' is not a valid libtool archive"

	func_dirname "$lib" "" "."
	ladir=$func_dirname_result

	dlname=
	dlopen=
	dlpreopen=
	libdir=
	library_names=
	old_library=
	inherited_linker_flags=
	# If the library was installed with an old release of libtool,
	# it will not redefine variables installed, or shouldnotlink
	installed=yes
	shouldnotlink=no
	avoidtemprpath=


	# Read the .la file
	func_source "$lib"

	# Convert "-framework foo" to "foo.ltframework"
	if test -n "$inherited_linker_flags"; then
	  tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'`
	  for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do
	    case " $new_inherited_linker_flags " in
	      *" $tmp_inherited_linker_flag "*) ;;
	      *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";;
	    esac
	  done
	fi
	dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
	if test lib,link = "$linkmode,$pass" ||
	   test prog,scan = "$linkmode,$pass" ||
	   { test prog != "$linkmode" && test lib != "$linkmode"; }; then
	  test -n "$dlopen" && func_append dlfiles " $dlopen"
	  test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen"
	fi

	if test conv = "$pass"; then
	  # Only check for convenience libraries
	  deplibs="$lib $deplibs"
	  if test -z "$libdir"; then
	    if test -z "$old_library"; then
	      func_fatal_error "cannot find name of link library for '$lib'"
	    fi
	    # It is a libtool convenience library, so add in its objects.
	    func_append convenience " $ladir/$objdir/$old_library"
	    func_append old_convenience " $ladir/$objdir/$old_library"
	    tmp_libs=
	    for deplib in $dependency_libs; do
	      deplibs="$deplib $deplibs"
	      if $opt_preserve_dup_deps; then
		case "$tmp_libs " in
		*" $deplib "*) func_append specialdeplibs " $deplib" ;;
		esac
	      fi
	      func_append tmp_libs " $deplib"
	    done
	  elif test prog != "$linkmode" && test lib != "$linkmode"; then
	    func_fatal_error "'$lib' is not a convenience library"
	  fi
	  continue
	fi # $pass = conv


	# Get the name of the library we link against.
	linklib=
	if test -n "$old_library" &&
	   { test yes = "$prefer_static_libs" ||
	     test built,no = "$prefer_static_libs,$installed"; }; then
	  linklib=$old_library
	else
	  for l in $old_library $library_names; do
	    linklib=$l
	  done
	fi
	if test -z "$linklib"; then
	  func_fatal_error "cannot find name of link library for '$lib'"
	fi

	# This library was specified with -dlopen.
	if test dlopen = "$pass"; then
	  test -z "$libdir" \
	    && func_fatal_error "cannot -dlopen a convenience library: '$lib'"
	  if test -z "$dlname" ||
	     test yes != "$dlopen_support" ||
	     test no = "$build_libtool_libs"
	  then
	    # If there is no dlname, no dlopen support or we're linking
	    # statically, we need to preload.  We also need to preload any
	    # dependent libraries so libltdl's deplib preloader doesn't
	    # bomb out in the load deplibs phase.
	    func_append dlprefiles " $lib $dependency_libs"
	  else
	    func_append newdlfiles " $lib"
	  fi
	  continue
	fi # $pass = dlopen

	# We need an absolute path.
	case $ladir in
	[\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;;
	*)
	  abs_ladir=`cd "$ladir" && pwd`
	  if test -z "$abs_ladir"; then
	    func_warning "cannot determine absolute directory name of '$ladir'"
	    func_warning "passing it literally to the linker, although it might fail"
	    abs_ladir=$ladir
	  fi
	  ;;
	esac
	func_basename "$lib"
	laname=$func_basename_result

	# Find the relevant object directory and library name.
	if test yes = "$installed"; then
	  if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then
	    func_warning "library '$lib' was moved."
	    dir=$ladir
	    absdir=$abs_ladir
	    libdir=$abs_ladir
	  else
	    dir=$lt_sysroot$libdir
	    absdir=$lt_sysroot$libdir
	  fi
	  test yes = "$hardcode_automatic" && avoidtemprpath=yes
	else
	  if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then
	    dir=$ladir
	    absdir=$abs_ladir
	    # Remove this search path later
	    func_append notinst_path " $abs_ladir"
	  else
	    dir=$ladir/$objdir
	    absdir=$abs_ladir/$objdir
	    # Remove this search path later
	    func_append notinst_path " $abs_ladir"
	  fi
	fi # $installed = yes
	func_stripname 'lib' '.la' "$laname"
	name=$func_stripname_result

	# This library was specified with -dlpreopen.
	if test dlpreopen = "$pass"; then
	  if test -z "$libdir" && test prog = "$linkmode"; then
	    func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'"
	  fi
	  case $host in
	    # special handling for platforms with PE-DLLs.
	    *cygwin* | *mingw* | *cegcc* )
	      # Linker will automatically link against shared library if both
	      # static and shared are present.  Therefore, ensure we extract
	      # symbols from the import library if a shared library is present
	      # (otherwise, the dlopen module name will be incorrect).  We do
	      # this by putting the import library name into $newdlprefiles.
	      # We recover the dlopen module name by 'saving' the la file
	      # name in a special purpose variable, and (later) extracting the
	      # dlname from the la file.
	      if test -n "$dlname"; then
	        func_tr_sh "$dir/$linklib"
	        eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname"
	        func_append newdlprefiles " $dir/$linklib"
	      else
	        func_append newdlprefiles " $dir/$old_library"
	        # Keep a list of preopened convenience libraries to check
	        # that they are being used correctly in the link pass.
	        test -z "$libdir" && \
	          func_append dlpreconveniencelibs " $dir/$old_library"
	      fi
	    ;;
	    * )
	      # Prefer using a static library (so that no silly _DYNAMIC symbols
	      # are required to link).
	      if test -n "$old_library"; then
	        func_append newdlprefiles " $dir/$old_library"
	        # Keep a list of preopened convenience libraries to check
	        # that they are being used correctly in the link pass.
	        test -z "$libdir" && \
	          func_append dlpreconveniencelibs " $dir/$old_library"
	      # Otherwise, use the dlname, so that lt_dlopen finds it.
	      elif test -n "$dlname"; then
	        func_append newdlprefiles " $dir/$dlname"
	      else
	        func_append newdlprefiles " $dir/$linklib"
	      fi
	    ;;
	  esac
	fi # $pass = dlpreopen

	if test -z "$libdir"; then
	  # Link the convenience library
	  if test lib = "$linkmode"; then
	    deplibs="$dir/$old_library $deplibs"
	  elif test prog,link = "$linkmode,$pass"; then
	    compile_deplibs="$dir/$old_library $compile_deplibs"
	    finalize_deplibs="$dir/$old_library $finalize_deplibs"
	  else
	    deplibs="$lib $deplibs" # used for prog,scan pass
	  fi
	  continue
	fi


	if test prog = "$linkmode" && test link != "$pass"; then
	  func_append newlib_search_path " $ladir"
	  deplibs="$lib $deplibs"

	  linkalldeplibs=false
	  if test no != "$link_all_deplibs" || test -z "$library_names" ||
	     test no = "$build_libtool_libs"; then
	    linkalldeplibs=:
	  fi

	  tmp_libs=
	  for deplib in $dependency_libs; do
	    case $deplib in
	    -L*) func_stripname '-L' '' "$deplib"
	         func_resolve_sysroot "$func_stripname_result"
	         func_append newlib_search_path " $func_resolve_sysroot_result"
		 ;;
	    esac
	    # Need to link against all dependency_libs?
	    if $linkalldeplibs; then
	      deplibs="$deplib $deplibs"
	    else
	      # Need to hardcode shared library paths
	      # or/and link against static libraries
	      newdependency_libs="$deplib $newdependency_libs"
	    fi
	    if $opt_preserve_dup_deps; then
	      case "$tmp_libs " in
	      *" $deplib "*) func_append specialdeplibs " $deplib" ;;
	      esac
	    fi
	    func_append tmp_libs " $deplib"
	  done # for deplib
	  continue
	fi # $linkmode = prog...

	if test prog,link = "$linkmode,$pass"; then
	  if test -n "$library_names" &&
	     { { test no = "$prefer_static_libs" ||
	         test built,yes = "$prefer_static_libs,$installed"; } ||
	       test -z "$old_library"; }; then
	    # We need to hardcode the library path
	    if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then
	      # Make sure the rpath contains only unique directories.
	      case $temp_rpath: in
	      *"$absdir:"*) ;;
	      *) func_append temp_rpath "$absdir:" ;;
	      esac
	    fi

	    # Hardcode the library path.
	    # Skip directories that are in the system default run-time
	    # search path.
	    case " $sys_lib_dlsearch_path " in
	    *" $absdir "*) ;;
	    *)
	      case "$compile_rpath " in
	      *" $absdir "*) ;;
	      *) func_append compile_rpath " $absdir" ;;
	      esac
	      ;;
	    esac
	    case " $sys_lib_dlsearch_path " in
	    *" $libdir "*) ;;
	    *)
	      case "$finalize_rpath " in
	      *" $libdir "*) ;;
	      *) func_append finalize_rpath " $libdir" ;;
	      esac
	      ;;
	    esac
	  fi # $linkmode,$pass = prog,link...

	  if $alldeplibs &&
	     { test pass_all = "$deplibs_check_method" ||
	       { test yes = "$build_libtool_libs" &&
		 test -n "$library_names"; }; }; then
	    # We only need to search for static libraries
	    continue
	  fi
	fi

	link_static=no # Whether the deplib will be linked statically
	use_static_libs=$prefer_static_libs
	if test built = "$use_static_libs" && test yes = "$installed"; then
	  use_static_libs=no
	fi
	if test -n "$library_names" &&
	   { test no = "$use_static_libs" || test -z "$old_library"; }; then
	  case $host in
	  *cygwin* | *mingw* | *cegcc* | *os2*)
	      # No point in relinking DLLs because paths are not encoded
	      func_append notinst_deplibs " $lib"
	      need_relink=no
	    ;;
	  *)
	    if test no = "$installed"; then
	      func_append notinst_deplibs " $lib"
	      need_relink=yes
	    fi
	    ;;
	  esac
	  # This is a shared library

	  # Warn about portability, can't link against -module's on some
	  # systems (darwin).  Don't bleat about dlopened modules though!
	  dlopenmodule=
	  for dlpremoduletest in $dlprefiles; do
	    if test "X$dlpremoduletest" = "X$lib"; then
	      dlopenmodule=$dlpremoduletest
	      break
	    fi
	  done
	  if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then
	    echo
	    if test prog = "$linkmode"; then
	      $ECHO "*** Warning: Linking the executable $output against the loadable module"
	    else
	      $ECHO "*** Warning: Linking the shared library $output against the loadable module"
	    fi
	    $ECHO "*** $linklib is not portable!"
	  fi
	  if test lib = "$linkmode" &&
	     test yes = "$hardcode_into_libs"; then
	    # Hardcode the library path.
	    # Skip directories that are in the system default run-time
	    # search path.
	    case " $sys_lib_dlsearch_path " in
	    *" $absdir "*) ;;
	    *)
	      case "$compile_rpath " in
	      *" $absdir "*) ;;
	      *) func_append compile_rpath " $absdir" ;;
	      esac
	      ;;
	    esac
	    case " $sys_lib_dlsearch_path " in
	    *" $libdir "*) ;;
	    *)
	      case "$finalize_rpath " in
	      *" $libdir "*) ;;
	      *) func_append finalize_rpath " $libdir" ;;
	      esac
	      ;;
	    esac
	  fi

	  if test -n "$old_archive_from_expsyms_cmds"; then
	    # figure out the soname
	    set dummy $library_names
	    shift
	    realname=$1
	    shift
	    libname=`eval "\\$ECHO \"$libname_spec\""`
	    # use dlname if we got it. it's perfectly good, no?
	    if test -n "$dlname"; then
	      soname=$dlname
	    elif test -n "$soname_spec"; then
	      # bleh windows
	      case $host in
	      *cygwin* | mingw* | *cegcc* | *os2*)
	        func_arith $current - $age
		major=$func_arith_result
		versuffix=-$major
		;;
	      esac
	      eval soname=\"$soname_spec\"
	    else
	      soname=$realname
	    fi

	    # Make a new name for the extract_expsyms_cmds to use
	    soroot=$soname
	    func_basename "$soroot"
	    soname=$func_basename_result
	    func_stripname 'lib' '.dll' "$soname"
	    newlib=libimp-$func_stripname_result.a

	    # If the library has no export list, then create one now
	    if test -f "$output_objdir/$soname-def"; then :
	    else
	      func_verbose "extracting exported symbol list from '$soname'"
	      func_execute_cmds "$extract_expsyms_cmds" 'exit $?'
	    fi

	    # Create $newlib
	    if test -f "$output_objdir/$newlib"; then :; else
	      func_verbose "generating import library for '$soname'"
	      func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?'
	    fi
	    # make sure the library variables are pointing to the new library
	    dir=$output_objdir
	    linklib=$newlib
	  fi # test -n "$old_archive_from_expsyms_cmds"

	  if test prog = "$linkmode" || test relink != "$opt_mode"; then
	    add_shlibpath=
	    add_dir=
	    add=
	    lib_linked=yes
	    case $hardcode_action in
	    immediate | unsupported)
	      if test no = "$hardcode_direct"; then
		add=$dir/$linklib
		case $host in
		  *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;;
		  *-*-sysv4*uw2*) add_dir=-L$dir ;;
		  *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \
		    *-*-unixware7*) add_dir=-L$dir ;;
		  *-*-darwin* )
		    # if the lib is a (non-dlopened) module then we cannot
		    # link against it, someone is ignoring the earlier warnings
		    if /usr/bin/file -L $add 2> /dev/null |
			 $GREP ": [^:]* bundle" >/dev/null; then
		      if test "X$dlopenmodule" != "X$lib"; then
			$ECHO "*** Warning: lib $linklib is a module, not a shared library"
			if test -z "$old_library"; then
			  echo
			  echo "*** And there doesn't seem to be a static archive available"
			  echo "*** The link will probably fail, sorry"
			else
			  add=$dir/$old_library
			fi
		      elif test -n "$old_library"; then
			add=$dir/$old_library
		      fi
		    fi
		esac
	      elif test no = "$hardcode_minus_L"; then
		case $host in
		*-*-sunos*) add_shlibpath=$dir ;;
		esac
		add_dir=-L$dir
		add=-l$name
	      elif test no = "$hardcode_shlibpath_var"; then
		add_shlibpath=$dir
		add=-l$name
	      else
		lib_linked=no
	      fi
	      ;;
	    relink)
	      if test yes = "$hardcode_direct" &&
	         test no = "$hardcode_direct_absolute"; then
		add=$dir/$linklib
	      elif test yes = "$hardcode_minus_L"; then
		add_dir=-L$absdir
		# Try looking first in the location we're being installed to.
		if test -n "$inst_prefix_dir"; then
		  case $libdir in
		    [\\/]*)
		      func_append add_dir " -L$inst_prefix_dir$libdir"
		      ;;
		  esac
		fi
		add=-l$name
	      elif test yes = "$hardcode_shlibpath_var"; then
		add_shlibpath=$dir
		add=-l$name
	      else
		lib_linked=no
	      fi
	      ;;
	    *) lib_linked=no ;;
	    esac

	    if test yes != "$lib_linked"; then
	      func_fatal_configuration "unsupported hardcode properties"
	    fi

	    if test -n "$add_shlibpath"; then
	      case :$compile_shlibpath: in
	      *":$add_shlibpath:"*) ;;
	      *) func_append compile_shlibpath "$add_shlibpath:" ;;
	      esac
	    fi
	    if test prog = "$linkmode"; then
	      test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs"
	      test -n "$add" && compile_deplibs="$add $compile_deplibs"
	    else
	      test -n "$add_dir" && deplibs="$add_dir $deplibs"
	      test -n "$add" && deplibs="$add $deplibs"
	      if test yes != "$hardcode_direct" &&
		 test yes != "$hardcode_minus_L" &&
		 test yes = "$hardcode_shlibpath_var"; then
		case :$finalize_shlibpath: in
		*":$libdir:"*) ;;
		*) func_append finalize_shlibpath "$libdir:" ;;
		esac
	      fi
	    fi
	  fi

	  if test prog = "$linkmode" || test relink = "$opt_mode"; then
	    add_shlibpath=
	    add_dir=
	    add=
	    # Finalize command for both is simple: just hardcode it.
	    if test yes = "$hardcode_direct" &&
	       test no = "$hardcode_direct_absolute"; then
	      add=$libdir/$linklib
	    elif test yes = "$hardcode_minus_L"; then
	      add_dir=-L$libdir
	      add=-l$name
	    elif test yes = "$hardcode_shlibpath_var"; then
	      case :$finalize_shlibpath: in
	      *":$libdir:"*) ;;
	      *) func_append finalize_shlibpath "$libdir:" ;;
	      esac
	      add=-l$name
	    elif test yes = "$hardcode_automatic"; then
	      if test -n "$inst_prefix_dir" &&
		 test -f "$inst_prefix_dir$libdir/$linklib"; then
		add=$inst_prefix_dir$libdir/$linklib
	      else
		add=$libdir/$linklib
	      fi
	    else
	      # We cannot seem to hardcode it, guess we'll fake it.
	      add_dir=-L$libdir
	      # Try looking first in the location we're being installed to.
	      if test -n "$inst_prefix_dir"; then
		case $libdir in
		  [\\/]*)
		    func_append add_dir " -L$inst_prefix_dir$libdir"
		    ;;
		esac
	      fi
	      add=-l$name
	    fi

	    if test prog = "$linkmode"; then
	      test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs"
	      test -n "$add" && finalize_deplibs="$add $finalize_deplibs"
	    else
	      test -n "$add_dir" && deplibs="$add_dir $deplibs"
	      test -n "$add" && deplibs="$add $deplibs"
	    fi
	  fi
	elif test prog = "$linkmode"; then
	  # Here we assume that one of hardcode_direct or hardcode_minus_L
	  # is not unsupported.  This is valid on all known static and
	  # shared platforms.
	  if test unsupported != "$hardcode_direct"; then
	    test -n "$old_library" && linklib=$old_library
	    compile_deplibs="$dir/$linklib $compile_deplibs"
	    finalize_deplibs="$dir/$linklib $finalize_deplibs"
	  else
	    compile_deplibs="-l$name -L$dir $compile_deplibs"
	    finalize_deplibs="-l$name -L$dir $finalize_deplibs"
	  fi
	elif test yes = "$build_libtool_libs"; then
	  # Not a shared library
	  if test pass_all != "$deplibs_check_method"; then
	    # We're trying link a shared library against a static one
	    # but the system doesn't support it.

	    # Just print a warning and add the library to dependency_libs so
	    # that the program can be linked against the static library.
	    echo
	    $ECHO "*** Warning: This system cannot link to static lib archive $lib."
	    echo "*** I have the capability to make that library automatically link in when"
	    echo "*** you link to this library.  But I can only do this if you have a"
	    echo "*** shared version of the library, which you do not appear to have."
	    if test yes = "$module"; then
	      echo "*** But as you try to build a module library, libtool will still create "
	      echo "*** a static module, that should work as long as the dlopening application"
	      echo "*** is linked with the -dlopen flag to resolve symbols at runtime."
	      if test -z "$global_symbol_pipe"; then
		echo
		echo "*** However, this would only work if libtool was able to extract symbol"
		echo "*** lists from a program, using 'nm' or equivalent, but libtool could"
		echo "*** not find such a program.  So, this module is probably useless."
		echo "*** 'nm' from GNU binutils and a full rebuild may help."
	      fi
	      if test no = "$build_old_libs"; then
		build_libtool_libs=module
		build_old_libs=yes
	      else
		build_libtool_libs=no
	      fi
	    fi
	  else
	    deplibs="$dir/$old_library $deplibs"
	    link_static=yes
	  fi
	fi # link shared/static library?

	if test lib = "$linkmode"; then
	  if test -n "$dependency_libs" &&
	     { test yes != "$hardcode_into_libs" ||
	       test yes = "$build_old_libs" ||
	       test yes = "$link_static"; }; then
	    # Extract -R from dependency_libs
	    temp_deplibs=
	    for libdir in $dependency_libs; do
	      case $libdir in
	      -R*) func_stripname '-R' '' "$libdir"
	           temp_xrpath=$func_stripname_result
		   case " $xrpath " in
		   *" $temp_xrpath "*) ;;
		   *) func_append xrpath " $temp_xrpath";;
		   esac;;
	      *) func_append temp_deplibs " $libdir";;
	      esac
	    done
	    dependency_libs=$temp_deplibs
	  fi

	  func_append newlib_search_path " $absdir"
	  # Link against this library
	  test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs"
	  # ... and its dependency_libs
	  tmp_libs=
	  for deplib in $dependency_libs; do
	    newdependency_libs="$deplib $newdependency_libs"
	    case $deplib in
              -L*) func_stripname '-L' '' "$deplib"
                   func_resolve_sysroot "$func_stripname_result";;
              *) func_resolve_sysroot "$deplib" ;;
            esac
	    if $opt_preserve_dup_deps; then
	      case "$tmp_libs " in
	      *" $func_resolve_sysroot_result "*)
                func_append specialdeplibs " $func_resolve_sysroot_result" ;;
	      esac
	    fi
	    func_append tmp_libs " $func_resolve_sysroot_result"
	  done

	  if test no != "$link_all_deplibs"; then
	    # Add the search paths of all dependency libraries
	    for deplib in $dependency_libs; do
	      path=
	      case $deplib in
	      -L*) path=$deplib ;;
	      *.la)
	        func_resolve_sysroot "$deplib"
	        deplib=$func_resolve_sysroot_result
	        func_dirname "$deplib" "" "."
		dir=$func_dirname_result
		# We need an absolute path.
		case $dir in
		[\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;;
		*)
		  absdir=`cd "$dir" && pwd`
		  if test -z "$absdir"; then
		    func_warning "cannot determine absolute directory name of '$dir'"
		    absdir=$dir
		  fi
		  ;;
		esac
		if $GREP "^installed=no" $deplib > /dev/null; then
		case $host in
		*-*-darwin*)
		  depdepl=
		  eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib`
		  if test -n "$deplibrary_names"; then
		    for tmp in $deplibrary_names; do
		      depdepl=$tmp
		    done
		    if test -f "$absdir/$objdir/$depdepl"; then
		      depdepl=$absdir/$objdir/$depdepl
		      darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'`
                      if test -z "$darwin_install_name"; then
                          darwin_install_name=`$OTOOL64 -L $depdepl  | awk '{if (NR == 2) {print $1;exit}}'`
                      fi
		      func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl"
		      func_append linker_flags " -dylib_file $darwin_install_name:$depdepl"
		      path=
		    fi
		  fi
		  ;;
		*)
		  path=-L$absdir/$objdir
		  ;;
		esac
		else
		  eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
		  test -z "$libdir" && \
		    func_fatal_error "'$deplib' is not a valid libtool archive"
		  test "$absdir" != "$libdir" && \
		    func_warning "'$deplib' seems to be moved"

		  path=-L$absdir
		fi
		;;
	      esac
	      case " $deplibs " in
	      *" $path "*) ;;
	      *) deplibs="$path $deplibs" ;;
	      esac
	    done
	  fi # link_all_deplibs != no
	fi # linkmode = lib
      done # for deplib in $libs
      if test link = "$pass"; then
	if test prog = "$linkmode"; then
	  compile_deplibs="$new_inherited_linker_flags $compile_deplibs"
	  finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs"
	else
	  compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
	fi
      fi
      dependency_libs=$newdependency_libs
      if test dlpreopen = "$pass"; then
	# Link the dlpreopened libraries before other libraries
	for deplib in $save_deplibs; do
	  deplibs="$deplib $deplibs"
	done
      fi
      if test dlopen != "$pass"; then
	test conv = "$pass" || {
	  # Make sure lib_search_path contains only unique directories.
	  lib_search_path=
	  for dir in $newlib_search_path; do
	    case "$lib_search_path " in
	    *" $dir "*) ;;
	    *) func_append lib_search_path " $dir" ;;
	    esac
	  done
	  newlib_search_path=
	}

	if test prog,link = "$linkmode,$pass"; then
	  vars="compile_deplibs finalize_deplibs"
	else
	  vars=deplibs
	fi
	for var in $vars dependency_libs; do
	  # Add libraries to $var in reverse order
	  eval tmp_libs=\"\$$var\"
	  new_libs=
	  for deplib in $tmp_libs; do
	    # FIXME: Pedantically, this is the right thing to do, so
	    #        that some nasty dependency loop isn't accidentally
	    #        broken:
	    #new_libs="$deplib $new_libs"
	    # Pragmatically, this seems to cause very few problems in
	    # practice:
	    case $deplib in
	    -L*) new_libs="$deplib $new_libs" ;;
	    -R*) ;;
	    *)
	      # And here is the reason: when a library appears more
	      # than once as an explicit dependence of a library, or
	      # is implicitly linked in more than once by the
	      # compiler, it is considered special, and multiple
	      # occurrences thereof are not removed.  Compare this
	      # with having the same library being listed as a
	      # dependency of multiple other libraries: in this case,
	      # we know (pedantically, we assume) the library does not
	      # need to be listed more than once, so we keep only the
	      # last copy.  This is not always right, but it is rare
	      # enough that we require users that really mean to play
	      # such unportable linking tricks to link the library
	      # using -Wl,-lname, so that libtool does not consider it
	      # for duplicate removal.
	      case " $specialdeplibs " in
	      *" $deplib "*) new_libs="$deplib $new_libs" ;;
	      *)
		case " $new_libs " in
		*" $deplib "*) ;;
		*) new_libs="$deplib $new_libs" ;;
		esac
		;;
	      esac
	      ;;
	    esac
	  done
	  tmp_libs=
	  for deplib in $new_libs; do
	    case $deplib in
	    -L*)
	      case " $tmp_libs " in
	      *" $deplib "*) ;;
	      *) func_append tmp_libs " $deplib" ;;
	      esac
	      ;;
	    *) func_append tmp_libs " $deplib" ;;
	    esac
	  done
	  eval $var=\"$tmp_libs\"
	done # for var
      fi

      # Add Sun CC postdeps if required:
      test CXX = "$tagname" && {
        case $host_os in
        linux*)
          case `$CC -V 2>&1 | sed 5q` in
          *Sun\ C*) # Sun C++ 5.9
            func_suncc_cstd_abi

            if test no != "$suncc_use_cstd_abi"; then
              func_append postdeps ' -library=Cstd -library=Crun'
            fi
            ;;
          esac
          ;;

        solaris*)
          func_cc_basename "$CC"
          case $func_cc_basename_result in
          CC* | sunCC*)
            func_suncc_cstd_abi

            if test no != "$suncc_use_cstd_abi"; then
              func_append postdeps ' -library=Cstd -library=Crun'
            fi
            ;;
          esac
          ;;
        esac
      }

      # Last step: remove runtime libs from dependency_libs
      # (they stay in deplibs)
      tmp_libs=
      for i in $dependency_libs; do
	case " $predeps $postdeps $compiler_lib_search_path " in
	*" $i "*)
	  i=
	  ;;
	esac
	if test -n "$i"; then
	  func_append tmp_libs " $i"
	fi
      done
      dependency_libs=$tmp_libs
    done # for pass
    if test prog = "$linkmode"; then
      dlfiles=$newdlfiles
    fi
    if test prog = "$linkmode" || test lib = "$linkmode"; then
      dlprefiles=$newdlprefiles
    fi

    case $linkmode in
    oldlib)
      if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then
	func_warning "'-dlopen' is ignored for archives"
      fi

      case " $deplibs" in
      *\ -l* | *\ -L*)
	func_warning "'-l' and '-L' are ignored for archives" ;;
      esac

      test -n "$rpath" && \
	func_warning "'-rpath' is ignored for archives"

      test -n "$xrpath" && \
	func_warning "'-R' is ignored for archives"

      test -n "$vinfo" && \
	func_warning "'-version-info/-version-number' is ignored for archives"

      test -n "$release" && \
	func_warning "'-release' is ignored for archives"

      test -n "$export_symbols$export_symbols_regex" && \
	func_warning "'-export-symbols' is ignored for archives"

      # Now set the variables for building old libraries.
      build_libtool_libs=no
      oldlibs=$output
      func_append objs "$old_deplibs"
      ;;

    lib)
      # Make sure we only generate libraries of the form 'libNAME.la'.
      case $outputname in
      lib*)
	func_stripname 'lib' '.la' "$outputname"
	name=$func_stripname_result
	eval shared_ext=\"$shrext_cmds\"
	eval libname=\"$libname_spec\"
	;;
      *)
	test no = "$module" \
	  && func_fatal_help "libtool library '$output' must begin with 'lib'"

	if test no != "$need_lib_prefix"; then
	  # Add the "lib" prefix for modules if required
	  func_stripname '' '.la' "$outputname"
	  name=$func_stripname_result
	  eval shared_ext=\"$shrext_cmds\"
	  eval libname=\"$libname_spec\"
	else
	  func_stripname '' '.la' "$outputname"
	  libname=$func_stripname_result
	fi
	;;
      esac

      if test -n "$objs"; then
	if test pass_all != "$deplibs_check_method"; then
	  func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs"
	else
	  echo
	  $ECHO "*** Warning: Linking the shared library $output against the non-libtool"
	  $ECHO "*** objects $objs is not portable!"
	  func_append libobjs " $objs"
	fi
      fi

      test no = "$dlself" \
	|| func_warning "'-dlopen self' is ignored for libtool libraries"

      set dummy $rpath
      shift
      test 1 -lt "$#" \
	&& func_warning "ignoring multiple '-rpath's for a libtool library"

      install_libdir=$1

      oldlibs=
      if test -z "$rpath"; then
	if test yes = "$build_libtool_libs"; then
	  # Building a libtool convenience library.
	  # Some compilers have problems with a '.al' extension so
	  # convenience libraries should have the same extension an
	  # archive normally would.
	  oldlibs="$output_objdir/$libname.$libext $oldlibs"
	  build_libtool_libs=convenience
	  build_old_libs=yes
	fi

	test -n "$vinfo" && \
	  func_warning "'-version-info/-version-number' is ignored for convenience libraries"

	test -n "$release" && \
	  func_warning "'-release' is ignored for convenience libraries"
      else

	# Parse the version information argument.
	save_ifs=$IFS; IFS=:
	set dummy $vinfo 0 0 0
	shift
	IFS=$save_ifs

	test -n "$7" && \
	  func_fatal_help "too many parameters to '-version-info'"

	# convert absolute version numbers to libtool ages
	# this retains compatibility with .la files and attempts
	# to make the code below a bit more comprehensible

	case $vinfo_number in
	yes)
	  number_major=$1
	  number_minor=$2
	  number_revision=$3
	  #
	  # There are really only two kinds -- those that
	  # use the current revision as the major version
	  # and those that subtract age and use age as
	  # a minor version.  But, then there is irix
	  # that has an extra 1 added just for fun
	  #
	  case $version_type in
	  # correct linux to gnu/linux during the next big refactor
	  darwin|freebsd-elf|linux|osf|windows|none)
	    func_arith $number_major + $number_minor
	    current=$func_arith_result
	    age=$number_minor
	    revision=$number_revision
	    ;;
	  freebsd-aout|qnx|sunos)
	    current=$number_major
	    revision=$number_minor
	    age=0
	    ;;
	  irix|nonstopux)
	    func_arith $number_major + $number_minor
	    current=$func_arith_result
	    age=$number_minor
	    revision=$number_minor
	    lt_irix_increment=no
	    ;;
	  *)
	    func_fatal_configuration "$modename: unknown library version type '$version_type'"
	    ;;
	  esac
	  ;;
	no)
	  current=$1
	  revision=$2
	  age=$3
	  ;;
	esac

	# Check that each of the things are valid numbers.
	case $current in
	0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
	*)
	  func_error "CURRENT '$current' must be a nonnegative integer"
	  func_fatal_error "'$vinfo' is not valid version information"
	  ;;
	esac

	case $revision in
	0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
	*)
	  func_error "REVISION '$revision' must be a nonnegative integer"
	  func_fatal_error "'$vinfo' is not valid version information"
	  ;;
	esac

	case $age in
	0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
	*)
	  func_error "AGE '$age' must be a nonnegative integer"
	  func_fatal_error "'$vinfo' is not valid version information"
	  ;;
	esac

	if test "$age" -gt "$current"; then
	  func_error "AGE '$age' is greater than the current interface number '$current'"
	  func_fatal_error "'$vinfo' is not valid version information"
	fi

	# Calculate the version variables.
	major=
	versuffix=
	verstring=
	case $version_type in
	none) ;;

	darwin)
	  # Like Linux, but with the current version available in
	  # verstring for coding it into the library header
	  func_arith $current - $age
	  major=.$func_arith_result
	  versuffix=$major.$age.$revision
	  # Darwin ld doesn't like 0 for these options...
	  func_arith $current + 1
	  minor_current=$func_arith_result
	  xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision"
	  verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
          # On Darwin other compilers
          case $CC in
              nagfor*)
                  verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision"
                  ;;
              *)
                  verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
                  ;;
          esac
	  ;;

	freebsd-aout)
	  major=.$current
	  versuffix=.$current.$revision
	  ;;

	freebsd-elf)
	  func_arith $current - $age
	  major=.$func_arith_result
	  versuffix=$major.$age.$revision
	  ;;

	irix | nonstopux)
	  if test no = "$lt_irix_increment"; then
	    func_arith $current - $age
	  else
	    func_arith $current - $age + 1
	  fi
	  major=$func_arith_result

	  case $version_type in
	    nonstopux) verstring_prefix=nonstopux ;;
	    *)         verstring_prefix=sgi ;;
	  esac
	  verstring=$verstring_prefix$major.$revision

	  # Add in all the interfaces that we are compatible with.
	  loop=$revision
	  while test 0 -ne "$loop"; do
	    func_arith $revision - $loop
	    iface=$func_arith_result
	    func_arith $loop - 1
	    loop=$func_arith_result
	    verstring=$verstring_prefix$major.$iface:$verstring
	  done

	  # Before this point, $major must not contain '.'.
	  major=.$major
	  versuffix=$major.$revision
	  ;;

	linux) # correct to gnu/linux during the next big refactor
	  func_arith $current - $age
	  major=.$func_arith_result
	  versuffix=$major.$age.$revision
	  ;;

	osf)
	  func_arith $current - $age
	  major=.$func_arith_result
	  versuffix=.$current.$age.$revision
	  verstring=$current.$age.$revision

	  # Add in all the interfaces that we are compatible with.
	  loop=$age
	  while test 0 -ne "$loop"; do
	    func_arith $current - $loop
	    iface=$func_arith_result
	    func_arith $loop - 1
	    loop=$func_arith_result
	    verstring=$verstring:$iface.0
	  done

	  # Make executables depend on our current version.
	  func_append verstring ":$current.0"
	  ;;

	qnx)
	  major=.$current
	  versuffix=.$current
	  ;;

	sco)
	  major=.$current
	  versuffix=.$current
	  ;;

	sunos)
	  major=.$current
	  versuffix=.$current.$revision
	  ;;

	windows)
	  # Use '-' rather than '.', since we only want one
	  # extension on DOS 8.3 file systems.
	  func_arith $current - $age
	  major=$func_arith_result
	  versuffix=-$major
	  ;;

	*)
	  func_fatal_configuration "unknown library version type '$version_type'"
	  ;;
	esac

	# Clear the version info if we defaulted, and they specified a release.
	if test -z "$vinfo" && test -n "$release"; then
	  major=
	  case $version_type in
	  darwin)
	    # we can't check for "0.0" in archive_cmds due to quoting
	    # problems, so we reset it completely
	    verstring=
	    ;;
	  *)
	    verstring=0.0
	    ;;
	  esac
	  if test no = "$need_version"; then
	    versuffix=
	  else
	    versuffix=.0.0
	  fi
	fi

	# Remove version info from name if versioning should be avoided
	if test yes,no = "$avoid_version,$need_version"; then
	  major=
	  versuffix=
	  verstring=
	fi

	# Check to see if the archive will have undefined symbols.
	if test yes = "$allow_undefined"; then
	  if test unsupported = "$allow_undefined_flag"; then
	    if test yes = "$build_old_libs"; then
	      func_warning "undefined symbols not allowed in $host shared libraries; building static only"
	      build_libtool_libs=no
	    else
	      func_fatal_error "can't build $host shared library unless -no-undefined is specified"
	    fi
	  fi
	else
	  # Don't allow undefined symbols.
	  allow_undefined_flag=$no_undefined_flag
	fi

      fi

      func_generate_dlsyms "$libname" "$libname" :
      func_append libobjs " $symfileobj"
      test " " = "$libobjs" && libobjs=

      if test relink != "$opt_mode"; then
	# Remove our outputs, but don't remove object files since they
	# may have been created when compiling PIC objects.
	removelist=
	tempremovelist=`$ECHO "$output_objdir/*"`
	for p in $tempremovelist; do
	  case $p in
	    *.$objext | *.gcno)
	       ;;
	    $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*)
	       if test -n "$precious_files_regex"; then
		 if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1
		 then
		   continue
		 fi
	       fi
	       func_append removelist " $p"
	       ;;
	    *) ;;
	  esac
	done
	test -n "$removelist" && \
	  func_show_eval "${RM}r \$removelist"
      fi

      # Now set the variables for building old libraries.
      if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then
	func_append oldlibs " $output_objdir/$libname.$libext"

	# Transform .lo files to .o files.
	oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP`
      fi

      # Eliminate all temporary directories.
      #for path in $notinst_path; do
      #	lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"`
      #	deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"`
      #	dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"`
      #done

      if test -n "$xrpath"; then
	# If the user specified any rpath flags, then add them.
	temp_xrpath=
	for libdir in $xrpath; do
	  func_replace_sysroot "$libdir"
	  func_append temp_xrpath " -R$func_replace_sysroot_result"
	  case "$finalize_rpath " in
	  *" $libdir "*) ;;
	  *) func_append finalize_rpath " $libdir" ;;
	  esac
	done
	if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then
	  dependency_libs="$temp_xrpath $dependency_libs"
	fi
      fi

      # Make sure dlfiles contains only unique files that won't be dlpreopened
      old_dlfiles=$dlfiles
      dlfiles=
      for lib in $old_dlfiles; do
	case " $dlprefiles $dlfiles " in
	*" $lib "*) ;;
	*) func_append dlfiles " $lib" ;;
	esac
      done

      # Make sure dlprefiles contains only unique files
      old_dlprefiles=$dlprefiles
      dlprefiles=
      for lib in $old_dlprefiles; do
	case "$dlprefiles " in
	*" $lib "*) ;;
	*) func_append dlprefiles " $lib" ;;
	esac
      done

      if test yes = "$build_libtool_libs"; then
	if test -n "$rpath"; then
	  case $host in
	  *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*)
	    # these systems don't actually have a c library (as such)!
	    ;;
	  *-*-rhapsody* | *-*-darwin1.[012])
	    # Rhapsody C library is in the System framework
	    func_append deplibs " System.ltframework"
	    ;;
	  *-*-netbsd*)
	    # Don't link with libc until the a.out ld.so is fixed.
	    ;;
	  *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
	    # Do not include libc due to us having libc/libc_r.
	    ;;
	  *-*-sco3.2v5* | *-*-sco5v6*)
	    # Causes problems with __ctype
	    ;;
	  *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
	    # Compiler inserts libc in the correct place for threads to work
	    ;;
	  *)
	    # Add libc to deplibs on all other systems if necessary.
	    if test yes = "$build_libtool_need_lc"; then
	      func_append deplibs " -lc"
	    fi
	    ;;
	  esac
	fi

	# Transform deplibs into only deplibs that can be linked in shared.
	name_save=$name
	libname_save=$libname
	release_save=$release
	versuffix_save=$versuffix
	major_save=$major
	# I'm not sure if I'm treating the release correctly.  I think
	# release should show up in the -l (ie -lgmp5) so we don't want to
	# add it in twice.  Is that correct?
	release=
	versuffix=
	major=
	newdeplibs=
	droppeddeps=no
	case $deplibs_check_method in
	pass_all)
	  # Don't check for shared/static.  Everything works.
	  # This might be a little naive.  We might want to check
	  # whether the library exists or not.  But this is on
	  # osf3 & osf4 and I'm not really sure... Just
	  # implementing what was already the behavior.
	  newdeplibs=$deplibs
	  ;;
	test_compile)
	  # This code stresses the "libraries are programs" paradigm to its
	  # limits. Maybe even breaks it.  We compile a program, linking it
	  # against the deplibs as a proxy for the library.  Then we can check
	  # whether they linked in statically or dynamically with ldd.
	  $opt_dry_run || $RM conftest.c
	  cat > conftest.c </dev/null`
		    $nocaseglob
		  else
		    potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null`
		  fi
		  for potent_lib in $potential_libs; do
		      # Follow soft links.
		      if ls -lLd "$potent_lib" 2>/dev/null |
			 $GREP " -> " >/dev/null; then
			continue
		      fi
		      # The statement above tries to avoid entering an
		      # endless loop below, in case of cyclic links.
		      # We might still enter an endless loop, since a link
		      # loop can be closed while we follow links,
		      # but so what?
		      potlib=$potent_lib
		      while test -h "$potlib" 2>/dev/null; do
			potliblink=`ls -ld $potlib | $SED 's/.* -> //'`
			case $potliblink in
			[\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;;
			*) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";;
			esac
		      done
		      if eval $file_magic_cmd \"\$potlib\" 2>/dev/null |
			 $SED -e 10q |
			 $EGREP "$file_magic_regex" > /dev/null; then
			func_append newdeplibs " $a_deplib"
			a_deplib=
			break 2
		      fi
		  done
		done
	      fi
	      if test -n "$a_deplib"; then
		droppeddeps=yes
		echo
		$ECHO "*** Warning: linker path does not have real file for library $a_deplib."
		echo "*** I have the capability to make that library automatically link in when"
		echo "*** you link to this library.  But I can only do this if you have a"
		echo "*** shared version of the library, which you do not appear to have"
		echo "*** because I did check the linker path looking for a file starting"
		if test -z "$potlib"; then
		  $ECHO "*** with $libname but no candidates were found. (...for file magic test)"
		else
		  $ECHO "*** with $libname and none of the candidates passed a file format test"
		  $ECHO "*** using a file magic. Last file checked: $potlib"
		fi
	      fi
	      ;;
	    *)
	      # Add a -L argument.
	      func_append newdeplibs " $a_deplib"
	      ;;
	    esac
	  done # Gone through all deplibs.
	  ;;
	match_pattern*)
	  set dummy $deplibs_check_method; shift
	  match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
	  for a_deplib in $deplibs; do
	    case $a_deplib in
	    -l*)
	      func_stripname -l '' "$a_deplib"
	      name=$func_stripname_result
	      if test yes = "$allow_libtool_libs_with_static_runtimes"; then
		case " $predeps $postdeps " in
		*" $a_deplib "*)
		  func_append newdeplibs " $a_deplib"
		  a_deplib=
		  ;;
		esac
	      fi
	      if test -n "$a_deplib"; then
		libname=`eval "\\$ECHO \"$libname_spec\""`
		for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
		  potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
		  for potent_lib in $potential_libs; do
		    potlib=$potent_lib # see symlink-check above in file_magic test
		    if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \
		       $EGREP "$match_pattern_regex" > /dev/null; then
		      func_append newdeplibs " $a_deplib"
		      a_deplib=
		      break 2
		    fi
		  done
		done
	      fi
	      if test -n "$a_deplib"; then
		droppeddeps=yes
		echo
		$ECHO "*** Warning: linker path does not have real file for library $a_deplib."
		echo "*** I have the capability to make that library automatically link in when"
		echo "*** you link to this library.  But I can only do this if you have a"
		echo "*** shared version of the library, which you do not appear to have"
		echo "*** because I did check the linker path looking for a file starting"
		if test -z "$potlib"; then
		  $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)"
		else
		  $ECHO "*** with $libname and none of the candidates passed a file format test"
		  $ECHO "*** using a regex pattern. Last file checked: $potlib"
		fi
	      fi
	      ;;
	    *)
	      # Add a -L argument.
	      func_append newdeplibs " $a_deplib"
	      ;;
	    esac
	  done # Gone through all deplibs.
	  ;;
	none | unknown | *)
	  newdeplibs=
	  tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'`
	  if test yes = "$allow_libtool_libs_with_static_runtimes"; then
	    for i in $predeps $postdeps; do
	      # can't use Xsed below, because $i might contain '/'
	      tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"`
	    done
	  fi
	  case $tmp_deplibs in
	  *[!\	\ ]*)
	    echo
	    if test none = "$deplibs_check_method"; then
	      echo "*** Warning: inter-library dependencies are not supported in this platform."
	    else
	      echo "*** Warning: inter-library dependencies are not known to be supported."
	    fi
	    echo "*** All declared inter-library dependencies are being dropped."
	    droppeddeps=yes
	    ;;
	  esac
	  ;;
	esac
	versuffix=$versuffix_save
	major=$major_save
	release=$release_save
	libname=$libname_save
	name=$name_save

	case $host in
	*-*-rhapsody* | *-*-darwin1.[012])
	  # On Rhapsody replace the C library with the System framework
	  newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'`
	  ;;
	esac

	if test yes = "$droppeddeps"; then
	  if test yes = "$module"; then
	    echo
	    echo "*** Warning: libtool could not satisfy all declared inter-library"
	    $ECHO "*** dependencies of module $libname.  Therefore, libtool will create"
	    echo "*** a static module, that should work as long as the dlopening"
	    echo "*** application is linked with the -dlopen flag."
	    if test -z "$global_symbol_pipe"; then
	      echo
	      echo "*** However, this would only work if libtool was able to extract symbol"
	      echo "*** lists from a program, using 'nm' or equivalent, but libtool could"
	      echo "*** not find such a program.  So, this module is probably useless."
	      echo "*** 'nm' from GNU binutils and a full rebuild may help."
	    fi
	    if test no = "$build_old_libs"; then
	      oldlibs=$output_objdir/$libname.$libext
	      build_libtool_libs=module
	      build_old_libs=yes
	    else
	      build_libtool_libs=no
	    fi
	  else
	    echo "*** The inter-library dependencies that have been dropped here will be"
	    echo "*** automatically added whenever a program is linked with this library"
	    echo "*** or is declared to -dlopen it."

	    if test no = "$allow_undefined"; then
	      echo
	      echo "*** Since this library must not contain undefined symbols,"
	      echo "*** because either the platform does not support them or"
	      echo "*** it was explicitly requested with -no-undefined,"
	      echo "*** libtool will only create a static version of it."
	      if test no = "$build_old_libs"; then
		oldlibs=$output_objdir/$libname.$libext
		build_libtool_libs=module
		build_old_libs=yes
	      else
		build_libtool_libs=no
	      fi
	    fi
	  fi
	fi
	# Done checking deplibs!
	deplibs=$newdeplibs
      fi
      # Time to change all our "foo.ltframework" stuff back to "-framework foo"
      case $host in
	*-*-darwin*)
	  newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
	  new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
	  deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
	  ;;
      esac

      # move library search paths that coincide with paths to not yet
      # installed libraries to the beginning of the library search list
      new_libs=
      for path in $notinst_path; do
	case " $new_libs " in
	*" -L$path/$objdir "*) ;;
	*)
	  case " $deplibs " in
	  *" -L$path/$objdir "*)
	    func_append new_libs " -L$path/$objdir" ;;
	  esac
	  ;;
	esac
      done
      for deplib in $deplibs; do
	case $deplib in
	-L*)
	  case " $new_libs " in
	  *" $deplib "*) ;;
	  *) func_append new_libs " $deplib" ;;
	  esac
	  ;;
	*) func_append new_libs " $deplib" ;;
	esac
      done
      deplibs=$new_libs

      # All the library-specific variables (install_libdir is set above).
      library_names=
      old_library=
      dlname=

      # Test again, we may have decided not to build it any more
      if test yes = "$build_libtool_libs"; then
	# Remove $wl instances when linking with ld.
	# FIXME: should test the right _cmds variable.
	case $archive_cmds in
	  *\$LD\ *) wl= ;;
        esac
	if test yes = "$hardcode_into_libs"; then
	  # Hardcode the library paths
	  hardcode_libdirs=
	  dep_rpath=
	  rpath=$finalize_rpath
	  test relink = "$opt_mode" || rpath=$compile_rpath$rpath
	  for libdir in $rpath; do
	    if test -n "$hardcode_libdir_flag_spec"; then
	      if test -n "$hardcode_libdir_separator"; then
		func_replace_sysroot "$libdir"
		libdir=$func_replace_sysroot_result
		if test -z "$hardcode_libdirs"; then
		  hardcode_libdirs=$libdir
		else
		  # Just accumulate the unique libdirs.
		  case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
		  *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
		    ;;
		  *)
		    func_append hardcode_libdirs "$hardcode_libdir_separator$libdir"
		    ;;
		  esac
		fi
	      else
		eval flag=\"$hardcode_libdir_flag_spec\"
		func_append dep_rpath " $flag"
	      fi
	    elif test -n "$runpath_var"; then
	      case "$perm_rpath " in
	      *" $libdir "*) ;;
	      *) func_append perm_rpath " $libdir" ;;
	      esac
	    fi
	  done
	  # Substitute the hardcoded libdirs into the rpath.
	  if test -n "$hardcode_libdir_separator" &&
	     test -n "$hardcode_libdirs"; then
	    libdir=$hardcode_libdirs
	    eval "dep_rpath=\"$hardcode_libdir_flag_spec\""
	  fi
	  if test -n "$runpath_var" && test -n "$perm_rpath"; then
	    # We should set the runpath_var.
	    rpath=
	    for dir in $perm_rpath; do
	      func_append rpath "$dir:"
	    done
	    eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var"
	  fi
	  test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs"
	fi

	shlibpath=$finalize_shlibpath
	test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath
	if test -n "$shlibpath"; then
	  eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var"
	fi

	# Get the real and link names of the library.
	eval shared_ext=\"$shrext_cmds\"
	eval library_names=\"$library_names_spec\"
	set dummy $library_names
	shift
	realname=$1
	shift

	if test -n "$soname_spec"; then
	  eval soname=\"$soname_spec\"
	else
	  soname=$realname
	fi
	if test -z "$dlname"; then
	  dlname=$soname
	fi

	lib=$output_objdir/$realname
	linknames=
	for link
	do
	  func_append linknames " $link"
	done

	# Use standard objects if they are pic
	test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP`
	test "X$libobjs" = "X " && libobjs=

	delfiles=
	if test -n "$export_symbols" && test -n "$include_expsyms"; then
	  $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp"
	  export_symbols=$output_objdir/$libname.uexp
	  func_append delfiles " $export_symbols"
	fi

	orig_export_symbols=
	case $host_os in
	cygwin* | mingw* | cegcc*)
	  if test -n "$export_symbols" && test -z "$export_symbols_regex"; then
	    # exporting using user supplied symfile
	    func_dll_def_p "$export_symbols" || {
	      # and it's NOT already a .def file. Must figure out
	      # which of the given symbols are data symbols and tag
	      # them as such. So, trigger use of export_symbols_cmds.
	      # export_symbols gets reassigned inside the "prepare
	      # the list of exported symbols" if statement, so the
	      # include_expsyms logic still works.
	      orig_export_symbols=$export_symbols
	      export_symbols=
	      always_export_symbols=yes
	    }
	  fi
	  ;;
	esac

	# Prepare the list of exported symbols
	if test -z "$export_symbols"; then
	  if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then
	    func_verbose "generating symbol list for '$libname.la'"
	    export_symbols=$output_objdir/$libname.exp
	    $opt_dry_run || $RM $export_symbols
	    cmds=$export_symbols_cmds
	    save_ifs=$IFS; IFS='~'
	    for cmd1 in $cmds; do
	      IFS=$save_ifs
	      # Take the normal branch if the nm_file_list_spec branch
	      # doesn't work or if tool conversion is not needed.
	      case $nm_file_list_spec~$to_tool_file_cmd in
		*~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*)
		  try_normal_branch=yes
		  eval cmd=\"$cmd1\"
		  func_len " $cmd"
		  len=$func_len_result
		  ;;
		*)
		  try_normal_branch=no
		  ;;
	      esac
	      if test yes = "$try_normal_branch" \
		 && { test "$len" -lt "$max_cmd_len" \
		      || test "$max_cmd_len" -le -1; }
	      then
		func_show_eval "$cmd" 'exit $?'
		skipped_export=false
	      elif test -n "$nm_file_list_spec"; then
		func_basename "$output"
		output_la=$func_basename_result
		save_libobjs=$libobjs
		save_output=$output
		output=$output_objdir/$output_la.nm
		func_to_tool_file "$output"
		libobjs=$nm_file_list_spec$func_to_tool_file_result
		func_append delfiles " $output"
		func_verbose "creating $NM input file list: $output"
		for obj in $save_libobjs; do
		  func_to_tool_file "$obj"
		  $ECHO "$func_to_tool_file_result"
		done > "$output"
		eval cmd=\"$cmd1\"
		func_show_eval "$cmd" 'exit $?'
		output=$save_output
		libobjs=$save_libobjs
		skipped_export=false
	      else
		# The command line is too long to execute in one step.
		func_verbose "using reloadable object file for export list..."
		skipped_export=:
		# Break out early, otherwise skipped_export may be
		# set to false by a later but shorter cmd.
		break
	      fi
	    done
	    IFS=$save_ifs
	    if test -n "$export_symbols_regex" && test : != "$skipped_export"; then
	      func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
	      func_show_eval '$MV "${export_symbols}T" "$export_symbols"'
	    fi
	  fi
	fi

	if test -n "$export_symbols" && test -n "$include_expsyms"; then
	  tmp_export_symbols=$export_symbols
	  test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols
	  $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"'
	fi

	if test : != "$skipped_export" && test -n "$orig_export_symbols"; then
	  # The given exports_symbols file has to be filtered, so filter it.
	  func_verbose "filter symbol list for '$libname.la' to tag DATA exports"
	  # FIXME: $output_objdir/$libname.filter potentially contains lots of
	  # 's' commands, which not all seds can handle. GNU sed should be fine
	  # though. Also, the filter scales superlinearly with the number of
	  # global variables. join(1) would be nice here, but unfortunately
	  # isn't a blessed tool.
	  $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter
	  func_append delfiles " $export_symbols $output_objdir/$libname.filter"
	  export_symbols=$output_objdir/$libname.def
	  $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols
	fi

	tmp_deplibs=
	for test_deplib in $deplibs; do
	  case " $convenience " in
	  *" $test_deplib "*) ;;
	  *)
	    func_append tmp_deplibs " $test_deplib"
	    ;;
	  esac
	done
	deplibs=$tmp_deplibs

	if test -n "$convenience"; then
	  if test -n "$whole_archive_flag_spec" &&
	    test yes = "$compiler_needs_object" &&
	    test -z "$libobjs"; then
	    # extract the archives, so we have objects to list.
	    # TODO: could optimize this to just extract one archive.
	    whole_archive_flag_spec=
	  fi
	  if test -n "$whole_archive_flag_spec"; then
	    save_libobjs=$libobjs
	    eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
	    test "X$libobjs" = "X " && libobjs=
	  else
	    gentop=$output_objdir/${outputname}x
	    func_append generated " $gentop"

	    func_extract_archives $gentop $convenience
	    func_append libobjs " $func_extract_archives_result"
	    test "X$libobjs" = "X " && libobjs=
	  fi
	fi

	if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then
	  eval flag=\"$thread_safe_flag_spec\"
	  func_append linker_flags " $flag"
	fi

	# Make a backup of the uninstalled library when relinking
	if test relink = "$opt_mode"; then
	  $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $?
	fi

	# Do each of the archive commands.
	if test yes = "$module" && test -n "$module_cmds"; then
	  if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
	    eval test_cmds=\"$module_expsym_cmds\"
	    cmds=$module_expsym_cmds
	  else
	    eval test_cmds=\"$module_cmds\"
	    cmds=$module_cmds
	  fi
	else
	  if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
	    eval test_cmds=\"$archive_expsym_cmds\"
	    cmds=$archive_expsym_cmds
	  else
	    eval test_cmds=\"$archive_cmds\"
	    cmds=$archive_cmds
	  fi
	fi

	if test : != "$skipped_export" &&
	   func_len " $test_cmds" &&
	   len=$func_len_result &&
	   test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
	  :
	else
	  # The command line is too long to link in one step, link piecewise
	  # or, if using GNU ld and skipped_export is not :, use a linker
	  # script.

	  # Save the value of $output and $libobjs because we want to
	  # use them later.  If we have whole_archive_flag_spec, we
	  # want to use save_libobjs as it was before
	  # whole_archive_flag_spec was expanded, because we can't
	  # assume the linker understands whole_archive_flag_spec.
	  # This may have to be revisited, in case too many
	  # convenience libraries get linked in and end up exceeding
	  # the spec.
	  if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then
	    save_libobjs=$libobjs
	  fi
	  save_output=$output
	  func_basename "$output"
	  output_la=$func_basename_result

	  # Clear the reloadable object creation command queue and
	  # initialize k to one.
	  test_cmds=
	  concat_cmds=
	  objlist=
	  last_robj=
	  k=1

	  if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then
	    output=$output_objdir/$output_la.lnkscript
	    func_verbose "creating GNU ld script: $output"
	    echo 'INPUT (' > $output
	    for obj in $save_libobjs
	    do
	      func_to_tool_file "$obj"
	      $ECHO "$func_to_tool_file_result" >> $output
	    done
	    echo ')' >> $output
	    func_append delfiles " $output"
	    func_to_tool_file "$output"
	    output=$func_to_tool_file_result
	  elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then
	    output=$output_objdir/$output_la.lnk
	    func_verbose "creating linker input file list: $output"
	    : > $output
	    set x $save_libobjs
	    shift
	    firstobj=
	    if test yes = "$compiler_needs_object"; then
	      firstobj="$1 "
	      shift
	    fi
	    for obj
	    do
	      func_to_tool_file "$obj"
	      $ECHO "$func_to_tool_file_result" >> $output
	    done
	    func_append delfiles " $output"
	    func_to_tool_file "$output"
	    output=$firstobj\"$file_list_spec$func_to_tool_file_result\"
	  else
	    if test -n "$save_libobjs"; then
	      func_verbose "creating reloadable object files..."
	      output=$output_objdir/$output_la-$k.$objext
	      eval test_cmds=\"$reload_cmds\"
	      func_len " $test_cmds"
	      len0=$func_len_result
	      len=$len0

	      # Loop over the list of objects to be linked.
	      for obj in $save_libobjs
	      do
		func_len " $obj"
		func_arith $len + $func_len_result
		len=$func_arith_result
		if test -z "$objlist" ||
		   test "$len" -lt "$max_cmd_len"; then
		  func_append objlist " $obj"
		else
		  # The command $test_cmds is almost too long, add a
		  # command to the queue.
		  if test 1 -eq "$k"; then
		    # The first file doesn't have a previous command to add.
		    reload_objs=$objlist
		    eval concat_cmds=\"$reload_cmds\"
		  else
		    # All subsequent reloadable object files will link in
		    # the last one created.
		    reload_objs="$objlist $last_robj"
		    eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\"
		  fi
		  last_robj=$output_objdir/$output_la-$k.$objext
		  func_arith $k + 1
		  k=$func_arith_result
		  output=$output_objdir/$output_la-$k.$objext
		  objlist=" $obj"
		  func_len " $last_robj"
		  func_arith $len0 + $func_len_result
		  len=$func_arith_result
		fi
	      done
	      # Handle the remaining objects by creating one last
	      # reloadable object file.  All subsequent reloadable object
	      # files will link in the last one created.
	      test -z "$concat_cmds" || concat_cmds=$concat_cmds~
	      reload_objs="$objlist $last_robj"
	      eval concat_cmds=\"\$concat_cmds$reload_cmds\"
	      if test -n "$last_robj"; then
	        eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\"
	      fi
	      func_append delfiles " $output"

	    else
	      output=
	    fi

	    ${skipped_export-false} && {
	      func_verbose "generating symbol list for '$libname.la'"
	      export_symbols=$output_objdir/$libname.exp
	      $opt_dry_run || $RM $export_symbols
	      libobjs=$output
	      # Append the command to create the export file.
	      test -z "$concat_cmds" || concat_cmds=$concat_cmds~
	      eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\"
	      if test -n "$last_robj"; then
		eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\"
	      fi
	    }

	    test -n "$save_libobjs" &&
	      func_verbose "creating a temporary reloadable object file: $output"

	    # Loop through the commands generated above and execute them.
	    save_ifs=$IFS; IFS='~'
	    for cmd in $concat_cmds; do
	      IFS=$save_ifs
	      $opt_quiet || {
		  func_quote_for_expand "$cmd"
		  eval "func_echo $func_quote_for_expand_result"
	      }
	      $opt_dry_run || eval "$cmd" || {
		lt_exit=$?

		# Restore the uninstalled library and exit
		if test relink = "$opt_mode"; then
		  ( cd "$output_objdir" && \
		    $RM "${realname}T" && \
		    $MV "${realname}U" "$realname" )
		fi

		exit $lt_exit
	      }
	    done
	    IFS=$save_ifs

	    if test -n "$export_symbols_regex" && ${skipped_export-false}; then
	      func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
	      func_show_eval '$MV "${export_symbols}T" "$export_symbols"'
	    fi
	  fi

          ${skipped_export-false} && {
	    if test -n "$export_symbols" && test -n "$include_expsyms"; then
	      tmp_export_symbols=$export_symbols
	      test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols
	      $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"'
	    fi

	    if test -n "$orig_export_symbols"; then
	      # The given exports_symbols file has to be filtered, so filter it.
	      func_verbose "filter symbol list for '$libname.la' to tag DATA exports"
	      # FIXME: $output_objdir/$libname.filter potentially contains lots of
	      # 's' commands, which not all seds can handle. GNU sed should be fine
	      # though. Also, the filter scales superlinearly with the number of
	      # global variables. join(1) would be nice here, but unfortunately
	      # isn't a blessed tool.
	      $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter
	      func_append delfiles " $export_symbols $output_objdir/$libname.filter"
	      export_symbols=$output_objdir/$libname.def
	      $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols
	    fi
	  }

	  libobjs=$output
	  # Restore the value of output.
	  output=$save_output

	  if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then
	    eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
	    test "X$libobjs" = "X " && libobjs=
	  fi
	  # Expand the library linking commands again to reset the
	  # value of $libobjs for piecewise linking.

	  # Do each of the archive commands.
	  if test yes = "$module" && test -n "$module_cmds"; then
	    if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
	      cmds=$module_expsym_cmds
	    else
	      cmds=$module_cmds
	    fi
	  else
	    if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
	      cmds=$archive_expsym_cmds
	    else
	      cmds=$archive_cmds
	    fi
	  fi
	fi

	if test -n "$delfiles"; then
	  # Append the command to remove temporary files to $cmds.
	  eval cmds=\"\$cmds~\$RM $delfiles\"
	fi

	# Add any objects from preloaded convenience libraries
	if test -n "$dlprefiles"; then
	  gentop=$output_objdir/${outputname}x
	  func_append generated " $gentop"

	  func_extract_archives $gentop $dlprefiles
	  func_append libobjs " $func_extract_archives_result"
	  test "X$libobjs" = "X " && libobjs=
	fi

	save_ifs=$IFS; IFS='~'
	for cmd in $cmds; do
	  IFS=$sp$nl
	  eval cmd=\"$cmd\"
	  IFS=$save_ifs
	  $opt_quiet || {
	    func_quote_for_expand "$cmd"
	    eval "func_echo $func_quote_for_expand_result"
	  }
	  $opt_dry_run || eval "$cmd" || {
	    lt_exit=$?

	    # Restore the uninstalled library and exit
	    if test relink = "$opt_mode"; then
	      ( cd "$output_objdir" && \
	        $RM "${realname}T" && \
		$MV "${realname}U" "$realname" )
	    fi

	    exit $lt_exit
	  }
	done
	IFS=$save_ifs

	# Restore the uninstalled library and exit
	if test relink = "$opt_mode"; then
	  $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $?

	  if test -n "$convenience"; then
	    if test -z "$whole_archive_flag_spec"; then
	      func_show_eval '${RM}r "$gentop"'
	    fi
	  fi

	  exit $EXIT_SUCCESS
	fi

	# Create links to the real library.
	for linkname in $linknames; do
	  if test "$realname" != "$linkname"; then
	    func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?'
	  fi
	done

	# If -module or -export-dynamic was specified, set the dlname.
	if test yes = "$module" || test yes = "$export_dynamic"; then
	  # On all known operating systems, these are identical.
	  dlname=$soname
	fi
      fi
      ;;

    obj)
      if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then
	func_warning "'-dlopen' is ignored for objects"
      fi

      case " $deplibs" in
      *\ -l* | *\ -L*)
	func_warning "'-l' and '-L' are ignored for objects" ;;
      esac

      test -n "$rpath" && \
	func_warning "'-rpath' is ignored for objects"

      test -n "$xrpath" && \
	func_warning "'-R' is ignored for objects"

      test -n "$vinfo" && \
	func_warning "'-version-info' is ignored for objects"

      test -n "$release" && \
	func_warning "'-release' is ignored for objects"

      case $output in
      *.lo)
	test -n "$objs$old_deplibs" && \
	  func_fatal_error "cannot build library object '$output' from non-libtool objects"

	libobj=$output
	func_lo2o "$libobj"
	obj=$func_lo2o_result
	;;
      *)
	libobj=
	obj=$output
	;;
      esac

      # Delete the old objects.
      $opt_dry_run || $RM $obj $libobj

      # Objects from convenience libraries.  This assumes
      # single-version convenience libraries.  Whenever we create
      # different ones for PIC/non-PIC, this we'll have to duplicate
      # the extraction.
      reload_conv_objs=
      gentop=
      # if reload_cmds runs $LD directly, get rid of -Wl from
      # whole_archive_flag_spec and hope we can get by with turning comma
      # into space.
      case $reload_cmds in
        *\$LD[\ \$]*) wl= ;;
      esac
      if test -n "$convenience"; then
	if test -n "$whole_archive_flag_spec"; then
	  eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\"
	  test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'`
	  reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags
	else
	  gentop=$output_objdir/${obj}x
	  func_append generated " $gentop"

	  func_extract_archives $gentop $convenience
	  reload_conv_objs="$reload_objs $func_extract_archives_result"
	fi
      fi

      # If we're not building shared, we need to use non_pic_objs
      test yes = "$build_libtool_libs" || libobjs=$non_pic_objects

      # Create the old-style object.
      reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs

      output=$obj
      func_execute_cmds "$reload_cmds" 'exit $?'

      # Exit if we aren't doing a library object file.
      if test -z "$libobj"; then
	if test -n "$gentop"; then
	  func_show_eval '${RM}r "$gentop"'
	fi

	exit $EXIT_SUCCESS
      fi

      test yes = "$build_libtool_libs" || {
	if test -n "$gentop"; then
	  func_show_eval '${RM}r "$gentop"'
	fi

	# Create an invalid libtool object if no PIC, so that we don't
	# accidentally link it into a program.
	# $show "echo timestamp > $libobj"
	# $opt_dry_run || eval "echo timestamp > $libobj" || exit $?
	exit $EXIT_SUCCESS
      }

      if test -n "$pic_flag" || test default != "$pic_mode"; then
	# Only do commands if we really have different PIC objects.
	reload_objs="$libobjs $reload_conv_objs"
	output=$libobj
	func_execute_cmds "$reload_cmds" 'exit $?'
      fi

      if test -n "$gentop"; then
	func_show_eval '${RM}r "$gentop"'
      fi

      exit $EXIT_SUCCESS
      ;;

    prog)
      case $host in
	*cygwin*) func_stripname '' '.exe' "$output"
	          output=$func_stripname_result.exe;;
      esac
      test -n "$vinfo" && \
	func_warning "'-version-info' is ignored for programs"

      test -n "$release" && \
	func_warning "'-release' is ignored for programs"

      $preload \
	&& test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \
	&& func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support."

      case $host in
      *-*-rhapsody* | *-*-darwin1.[012])
	# On Rhapsody replace the C library is the System framework
	compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'`
	finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'`
	;;
      esac

      case $host in
      *-*-darwin*)
	# Don't allow lazy linking, it breaks C++ global constructors
	# But is supposedly fixed on 10.4 or later (yay!).
	if test CXX = "$tagname"; then
	  case ${MACOSX_DEPLOYMENT_TARGET-10.0} in
	    10.[0123])
	      func_append compile_command " $wl-bind_at_load"
	      func_append finalize_command " $wl-bind_at_load"
	    ;;
	  esac
	fi
	# Time to change all our "foo.ltframework" stuff back to "-framework foo"
	compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
	finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
	;;
      esac


      # move library search paths that coincide with paths to not yet
      # installed libraries to the beginning of the library search list
      new_libs=
      for path in $notinst_path; do
	case " $new_libs " in
	*" -L$path/$objdir "*) ;;
	*)
	  case " $compile_deplibs " in
	  *" -L$path/$objdir "*)
	    func_append new_libs " -L$path/$objdir" ;;
	  esac
	  ;;
	esac
      done
      for deplib in $compile_deplibs; do
	case $deplib in
	-L*)
	  case " $new_libs " in
	  *" $deplib "*) ;;
	  *) func_append new_libs " $deplib" ;;
	  esac
	  ;;
	*) func_append new_libs " $deplib" ;;
	esac
      done
      compile_deplibs=$new_libs


      func_append compile_command " $compile_deplibs"
      func_append finalize_command " $finalize_deplibs"

      if test -n "$rpath$xrpath"; then
	# If the user specified any rpath flags, then add them.
	for libdir in $rpath $xrpath; do
	  # This is the magic to use -rpath.
	  case "$finalize_rpath " in
	  *" $libdir "*) ;;
	  *) func_append finalize_rpath " $libdir" ;;
	  esac
	done
      fi

      # Now hardcode the library paths
      rpath=
      hardcode_libdirs=
      for libdir in $compile_rpath $finalize_rpath; do
	if test -n "$hardcode_libdir_flag_spec"; then
	  if test -n "$hardcode_libdir_separator"; then
	    if test -z "$hardcode_libdirs"; then
	      hardcode_libdirs=$libdir
	    else
	      # Just accumulate the unique libdirs.
	      case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
	      *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
		;;
	      *)
		func_append hardcode_libdirs "$hardcode_libdir_separator$libdir"
		;;
	      esac
	    fi
	  else
	    eval flag=\"$hardcode_libdir_flag_spec\"
	    func_append rpath " $flag"
	  fi
	elif test -n "$runpath_var"; then
	  case "$perm_rpath " in
	  *" $libdir "*) ;;
	  *) func_append perm_rpath " $libdir" ;;
	  esac
	fi
	case $host in
	*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
	  testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'`
	  case :$dllsearchpath: in
	  *":$libdir:"*) ;;
	  ::) dllsearchpath=$libdir;;
	  *) func_append dllsearchpath ":$libdir";;
	  esac
	  case :$dllsearchpath: in
	  *":$testbindir:"*) ;;
	  ::) dllsearchpath=$testbindir;;
	  *) func_append dllsearchpath ":$testbindir";;
	  esac
	  ;;
	esac
      done
      # Substitute the hardcoded libdirs into the rpath.
      if test -n "$hardcode_libdir_separator" &&
	 test -n "$hardcode_libdirs"; then
	libdir=$hardcode_libdirs
	eval rpath=\" $hardcode_libdir_flag_spec\"
      fi
      compile_rpath=$rpath

      rpath=
      hardcode_libdirs=
      for libdir in $finalize_rpath; do
	if test -n "$hardcode_libdir_flag_spec"; then
	  if test -n "$hardcode_libdir_separator"; then
	    if test -z "$hardcode_libdirs"; then
	      hardcode_libdirs=$libdir
	    else
	      # Just accumulate the unique libdirs.
	      case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
	      *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
		;;
	      *)
		func_append hardcode_libdirs "$hardcode_libdir_separator$libdir"
		;;
	      esac
	    fi
	  else
	    eval flag=\"$hardcode_libdir_flag_spec\"
	    func_append rpath " $flag"
	  fi
	elif test -n "$runpath_var"; then
	  case "$finalize_perm_rpath " in
	  *" $libdir "*) ;;
	  *) func_append finalize_perm_rpath " $libdir" ;;
	  esac
	fi
      done
      # Substitute the hardcoded libdirs into the rpath.
      if test -n "$hardcode_libdir_separator" &&
	 test -n "$hardcode_libdirs"; then
	libdir=$hardcode_libdirs
	eval rpath=\" $hardcode_libdir_flag_spec\"
      fi
      finalize_rpath=$rpath

      if test -n "$libobjs" && test yes = "$build_old_libs"; then
	# Transform all the library objects into standard objects.
	compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP`
	finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP`
      fi

      func_generate_dlsyms "$outputname" "@PROGRAM@" false

      # template prelinking step
      if test -n "$prelink_cmds"; then
	func_execute_cmds "$prelink_cmds" 'exit $?'
      fi

      wrappers_required=:
      case $host in
      *cegcc* | *mingw32ce*)
        # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway.
        wrappers_required=false
        ;;
      *cygwin* | *mingw* )
        test yes = "$build_libtool_libs" || wrappers_required=false
        ;;
      *)
        if test no = "$need_relink" || test yes != "$build_libtool_libs"; then
          wrappers_required=false
        fi
        ;;
      esac
      $wrappers_required || {
	# Replace the output file specification.
	compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'`
	link_command=$compile_command$compile_rpath

	# We have no uninstalled library dependencies, so finalize right now.
	exit_status=0
	func_show_eval "$link_command" 'exit_status=$?'

	if test -n "$postlink_cmds"; then
	  func_to_tool_file "$output"
	  postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'`
	  func_execute_cmds "$postlink_cmds" 'exit $?'
	fi

	# Delete the generated files.
	if test -f "$output_objdir/${outputname}S.$objext"; then
	  func_show_eval '$RM "$output_objdir/${outputname}S.$objext"'
	fi

	exit $exit_status
      }

      if test -n "$compile_shlibpath$finalize_shlibpath"; then
	compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
      fi
      if test -n "$finalize_shlibpath"; then
	finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
      fi

      compile_var=
      finalize_var=
      if test -n "$runpath_var"; then
	if test -n "$perm_rpath"; then
	  # We should set the runpath_var.
	  rpath=
	  for dir in $perm_rpath; do
	    func_append rpath "$dir:"
	  done
	  compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
	fi
	if test -n "$finalize_perm_rpath"; then
	  # We should set the runpath_var.
	  rpath=
	  for dir in $finalize_perm_rpath; do
	    func_append rpath "$dir:"
	  done
	  finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
	fi
      fi

      if test yes = "$no_install"; then
	# We don't need to create a wrapper script.
	link_command=$compile_var$compile_command$compile_rpath
	# Replace the output file specification.
	link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'`
	# Delete the old output file.
	$opt_dry_run || $RM $output
	# Link the executable and exit
	func_show_eval "$link_command" 'exit $?'

	if test -n "$postlink_cmds"; then
	  func_to_tool_file "$output"
	  postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'`
	  func_execute_cmds "$postlink_cmds" 'exit $?'
	fi

	exit $EXIT_SUCCESS
      fi

      case $hardcode_action,$fast_install in
        relink,*)
	  # Fast installation is not supported
	  link_command=$compile_var$compile_command$compile_rpath
	  relink_command=$finalize_var$finalize_command$finalize_rpath

	  func_warning "this platform does not like uninstalled shared libraries"
	  func_warning "'$output' will be relinked during installation"
	  ;;
        *,yes)
	  link_command=$finalize_var$compile_command$finalize_rpath
	  relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'`
          ;;
	*,no)
	  link_command=$compile_var$compile_command$compile_rpath
	  relink_command=$finalize_var$finalize_command$finalize_rpath
          ;;
	*,needless)
	  link_command=$finalize_var$compile_command$finalize_rpath
	  relink_command=
          ;;
      esac

      # Replace the output file specification.
      link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`

      # Delete the old output files.
      $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname

      func_show_eval "$link_command" 'exit $?'

      if test -n "$postlink_cmds"; then
	func_to_tool_file "$output_objdir/$outputname"
	postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'`
	func_execute_cmds "$postlink_cmds" 'exit $?'
      fi

      # Now create the wrapper script.
      func_verbose "creating $output"

      # Quote the relink command for shipping.
      if test -n "$relink_command"; then
	# Preserve any variables that may affect compiler behavior
	for var in $variables_saved_for_relink; do
	  if eval test -z \"\${$var+set}\"; then
	    relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command"
	  elif eval var_value=\$$var; test -z "$var_value"; then
	    relink_command="$var=; export $var; $relink_command"
	  else
	    func_quote_for_eval "$var_value"
	    relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command"
	  fi
	done
	relink_command="(cd `pwd`; $relink_command)"
	relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"`
      fi

      # Only actually do things if not in dry run mode.
      $opt_dry_run || {
	# win32 will think the script is a binary if it has
	# a .exe suffix, so we strip it off here.
	case $output in
	  *.exe) func_stripname '' '.exe' "$output"
	         output=$func_stripname_result ;;
	esac
	# test for cygwin because mv fails w/o .exe extensions
	case $host in
	  *cygwin*)
	    exeext=.exe
	    func_stripname '' '.exe' "$outputname"
	    outputname=$func_stripname_result ;;
	  *) exeext= ;;
	esac
	case $host in
	  *cygwin* | *mingw* )
	    func_dirname_and_basename "$output" "" "."
	    output_name=$func_basename_result
	    output_path=$func_dirname_result
	    cwrappersource=$output_path/$objdir/lt-$output_name.c
	    cwrapper=$output_path/$output_name.exe
	    $RM $cwrappersource $cwrapper
	    trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15

	    func_emit_cwrapperexe_src > $cwrappersource

	    # The wrapper executable is built using the $host compiler,
	    # because it contains $host paths and files. If cross-
	    # compiling, it, like the target executable, must be
	    # executed on the $host or under an emulation environment.
	    $opt_dry_run || {
	      $LTCC $LTCFLAGS -o $cwrapper $cwrappersource
	      $STRIP $cwrapper
	    }

	    # Now, create the wrapper script for func_source use:
	    func_ltwrapper_scriptname $cwrapper
	    $RM $func_ltwrapper_scriptname_result
	    trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15
	    $opt_dry_run || {
	      # note: this script will not be executed, so do not chmod.
	      if test "x$build" = "x$host"; then
		$cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result
	      else
		func_emit_wrapper no > $func_ltwrapper_scriptname_result
	      fi
	    }
	  ;;
	  * )
	    $RM $output
	    trap "$RM $output; exit $EXIT_FAILURE" 1 2 15

	    func_emit_wrapper no > $output
	    chmod +x $output
	  ;;
	esac
      }
      exit $EXIT_SUCCESS
      ;;
    esac

    # See if we need to build an old-fashioned archive.
    for oldlib in $oldlibs; do

      case $build_libtool_libs in
        convenience)
	  oldobjs="$libobjs_save $symfileobj"
	  addlibs=$convenience
	  build_libtool_libs=no
	  ;;
	module)
	  oldobjs=$libobjs_save
	  addlibs=$old_convenience
	  build_libtool_libs=no
          ;;
	*)
	  oldobjs="$old_deplibs $non_pic_objects"
	  $preload && test -f "$symfileobj" \
	    && func_append oldobjs " $symfileobj"
	  addlibs=$old_convenience
	  ;;
      esac

      if test -n "$addlibs"; then
	gentop=$output_objdir/${outputname}x
	func_append generated " $gentop"

	func_extract_archives $gentop $addlibs
	func_append oldobjs " $func_extract_archives_result"
      fi

      # Do each command in the archive commands.
      if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then
	cmds=$old_archive_from_new_cmds
      else

	# Add any objects from preloaded convenience libraries
	if test -n "$dlprefiles"; then
	  gentop=$output_objdir/${outputname}x
	  func_append generated " $gentop"

	  func_extract_archives $gentop $dlprefiles
	  func_append oldobjs " $func_extract_archives_result"
	fi

	# POSIX demands no paths to be encoded in archives.  We have
	# to avoid creating archives with duplicate basenames if we
	# might have to extract them afterwards, e.g., when creating a
	# static archive out of a convenience library, or when linking
	# the entirety of a libtool archive into another (currently
	# not supported by libtool).
	if (for obj in $oldobjs
	    do
	      func_basename "$obj"
	      $ECHO "$func_basename_result"
	    done | sort | sort -uc >/dev/null 2>&1); then
	  :
	else
	  echo "copying selected object files to avoid basename conflicts..."
	  gentop=$output_objdir/${outputname}x
	  func_append generated " $gentop"
	  func_mkdir_p "$gentop"
	  save_oldobjs=$oldobjs
	  oldobjs=
	  counter=1
	  for obj in $save_oldobjs
	  do
	    func_basename "$obj"
	    objbase=$func_basename_result
	    case " $oldobjs " in
	    " ") oldobjs=$obj ;;
	    *[\ /]"$objbase "*)
	      while :; do
		# Make sure we don't pick an alternate name that also
		# overlaps.
		newobj=lt$counter-$objbase
		func_arith $counter + 1
		counter=$func_arith_result
		case " $oldobjs " in
		*[\ /]"$newobj "*) ;;
		*) if test ! -f "$gentop/$newobj"; then break; fi ;;
		esac
	      done
	      func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj"
	      func_append oldobjs " $gentop/$newobj"
	      ;;
	    *) func_append oldobjs " $obj" ;;
	    esac
	  done
	fi
	func_to_tool_file "$oldlib" func_convert_file_msys_to_w32
	tool_oldlib=$func_to_tool_file_result
	eval cmds=\"$old_archive_cmds\"

	func_len " $cmds"
	len=$func_len_result
	if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
	  cmds=$old_archive_cmds
	elif test -n "$archiver_list_spec"; then
	  func_verbose "using command file archive linking..."
	  for obj in $oldobjs
	  do
	    func_to_tool_file "$obj"
	    $ECHO "$func_to_tool_file_result"
	  done > $output_objdir/$libname.libcmd
	  func_to_tool_file "$output_objdir/$libname.libcmd"
	  oldobjs=" $archiver_list_spec$func_to_tool_file_result"
	  cmds=$old_archive_cmds
	else
	  # the command line is too long to link in one step, link in parts
	  func_verbose "using piecewise archive linking..."
	  save_RANLIB=$RANLIB
	  RANLIB=:
	  objlist=
	  concat_cmds=
	  save_oldobjs=$oldobjs
	  oldobjs=
	  # Is there a better way of finding the last object in the list?
	  for obj in $save_oldobjs
	  do
	    last_oldobj=$obj
	  done
	  eval test_cmds=\"$old_archive_cmds\"
	  func_len " $test_cmds"
	  len0=$func_len_result
	  len=$len0
	  for obj in $save_oldobjs
	  do
	    func_len " $obj"
	    func_arith $len + $func_len_result
	    len=$func_arith_result
	    func_append objlist " $obj"
	    if test "$len" -lt "$max_cmd_len"; then
	      :
	    else
	      # the above command should be used before it gets too long
	      oldobjs=$objlist
	      if test "$obj" = "$last_oldobj"; then
		RANLIB=$save_RANLIB
	      fi
	      test -z "$concat_cmds" || concat_cmds=$concat_cmds~
	      eval concat_cmds=\"\$concat_cmds$old_archive_cmds\"
	      objlist=
	      len=$len0
	    fi
	  done
	  RANLIB=$save_RANLIB
	  oldobjs=$objlist
	  if test -z "$oldobjs"; then
	    eval cmds=\"\$concat_cmds\"
	  else
	    eval cmds=\"\$concat_cmds~\$old_archive_cmds\"
	  fi
	fi
      fi
      func_execute_cmds "$cmds" 'exit $?'
    done

    test -n "$generated" && \
      func_show_eval "${RM}r$generated"

    # Now create the libtool archive.
    case $output in
    *.la)
      old_library=
      test yes = "$build_old_libs" && old_library=$libname.$libext
      func_verbose "creating $output"

      # Preserve any variables that may affect compiler behavior
      for var in $variables_saved_for_relink; do
	if eval test -z \"\${$var+set}\"; then
	  relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command"
	elif eval var_value=\$$var; test -z "$var_value"; then
	  relink_command="$var=; export $var; $relink_command"
	else
	  func_quote_for_eval "$var_value"
	  relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command"
	fi
      done
      # Quote the link command for shipping.
      relink_command="(cd `pwd`; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
      relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"`
      if test yes = "$hardcode_automatic"; then
	relink_command=
      fi

      # Only create the output if not a dry run.
      $opt_dry_run || {
	for installed in no yes; do
	  if test yes = "$installed"; then
	    if test -z "$install_libdir"; then
	      break
	    fi
	    output=$output_objdir/${outputname}i
	    # Replace all uninstalled libtool libraries with the installed ones
	    newdependency_libs=
	    for deplib in $dependency_libs; do
	      case $deplib in
	      *.la)
		func_basename "$deplib"
		name=$func_basename_result
		func_resolve_sysroot "$deplib"
		eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result`
		test -z "$libdir" && \
		  func_fatal_error "'$deplib' is not a valid libtool archive"
		func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name"
		;;
	      -L*)
		func_stripname -L '' "$deplib"
		func_replace_sysroot "$func_stripname_result"
		func_append newdependency_libs " -L$func_replace_sysroot_result"
		;;
	      -R*)
		func_stripname -R '' "$deplib"
		func_replace_sysroot "$func_stripname_result"
		func_append newdependency_libs " -R$func_replace_sysroot_result"
		;;
	      *) func_append newdependency_libs " $deplib" ;;
	      esac
	    done
	    dependency_libs=$newdependency_libs
	    newdlfiles=

	    for lib in $dlfiles; do
	      case $lib in
	      *.la)
	        func_basename "$lib"
		name=$func_basename_result
		eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
		test -z "$libdir" && \
		  func_fatal_error "'$lib' is not a valid libtool archive"
		func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name"
		;;
	      *) func_append newdlfiles " $lib" ;;
	      esac
	    done
	    dlfiles=$newdlfiles
	    newdlprefiles=
	    for lib in $dlprefiles; do
	      case $lib in
	      *.la)
		# Only pass preopened files to the pseudo-archive (for
		# eventual linking with the app. that links it) if we
		# didn't already link the preopened objects directly into
		# the library:
		func_basename "$lib"
		name=$func_basename_result
		eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
		test -z "$libdir" && \
		  func_fatal_error "'$lib' is not a valid libtool archive"
		func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name"
		;;
	      esac
	    done
	    dlprefiles=$newdlprefiles
	  else
	    newdlfiles=
	    for lib in $dlfiles; do
	      case $lib in
		[\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;;
		*) abs=`pwd`"/$lib" ;;
	      esac
	      func_append newdlfiles " $abs"
	    done
	    dlfiles=$newdlfiles
	    newdlprefiles=
	    for lib in $dlprefiles; do
	      case $lib in
		[\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;;
		*) abs=`pwd`"/$lib" ;;
	      esac
	      func_append newdlprefiles " $abs"
	    done
	    dlprefiles=$newdlprefiles
	  fi
	  $RM $output
	  # place dlname in correct position for cygwin
	  # In fact, it would be nice if we could use this code for all target
	  # systems that can't hard-code library paths into their executables
	  # and that have no shared library path variable independent of PATH,
	  # but it turns out we can't easily determine that from inspecting
	  # libtool variables, so we have to hard-code the OSs to which it
	  # applies here; at the moment, that means platforms that use the PE
	  # object format with DLL files.  See the long comment at the top of
	  # tests/bindir.at for full details.
	  tdlname=$dlname
	  case $host,$output,$installed,$module,$dlname in
	    *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll)
	      # If a -bindir argument was supplied, place the dll there.
	      if test -n "$bindir"; then
		func_relative_path "$install_libdir" "$bindir"
		tdlname=$func_relative_path_result/$dlname
	      else
		# Otherwise fall back on heuristic.
		tdlname=../bin/$dlname
	      fi
	      ;;
	  esac
	  $ECHO > $output "\
# $outputname - a libtool library file
# Generated by $PROGRAM (GNU $PACKAGE) $VERSION
#
# Please DO NOT delete this file!
# It is necessary for linking the library.

# The name that we can dlopen(3).
dlname='$tdlname'

# Names of this library.
library_names='$library_names'

# The name of the static archive.
old_library='$old_library'

# Linker flags that cannot go in dependency_libs.
inherited_linker_flags='$new_inherited_linker_flags'

# Libraries that this one depends upon.
dependency_libs='$dependency_libs'

# Names of additional weak libraries provided by this library
weak_library_names='$weak_libs'

# Version information for $libname.
current=$current
age=$age
revision=$revision

# Is this an already installed library?
installed=$installed

# Should we warn about portability when linking against -modules?
shouldnotlink=$module

# Files to dlopen/dlpreopen
dlopen='$dlfiles'
dlpreopen='$dlprefiles'

# Directory that this library needs to be installed in:
libdir='$install_libdir'"
	  if test no,yes = "$installed,$need_relink"; then
	    $ECHO >> $output "\
relink_command=\"$relink_command\""
	  fi
	done
      }

      # Do a symbolic link so that the libtool archive can be found in
      # LD_LIBRARY_PATH before the program is installed.
      func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?'
      ;;
    esac
    exit $EXIT_SUCCESS
}

if test link = "$opt_mode" || test relink = "$opt_mode"; then
  func_mode_link ${1+"$@"}
fi


# func_mode_uninstall arg...
func_mode_uninstall ()
{
    $debug_cmd

    RM=$nonopt
    files=
    rmforce=false
    exit_status=0

    # This variable tells wrapper scripts just to set variables rather
    # than running their programs.
    libtool_install_magic=$magic

    for arg
    do
      case $arg in
      -f) func_append RM " $arg"; rmforce=: ;;
      -*) func_append RM " $arg" ;;
      *) func_append files " $arg" ;;
      esac
    done

    test -z "$RM" && \
      func_fatal_help "you must specify an RM program"

    rmdirs=

    for file in $files; do
      func_dirname "$file" "" "."
      dir=$func_dirname_result
      if test . = "$dir"; then
	odir=$objdir
      else
	odir=$dir/$objdir
      fi
      func_basename "$file"
      name=$func_basename_result
      test uninstall = "$opt_mode" && odir=$dir

      # Remember odir for removal later, being careful to avoid duplicates
      if test clean = "$opt_mode"; then
	case " $rmdirs " in
	  *" $odir "*) ;;
	  *) func_append rmdirs " $odir" ;;
	esac
      fi

      # Don't error if the file doesn't exist and rm -f was used.
      if { test -L "$file"; } >/dev/null 2>&1 ||
	 { test -h "$file"; } >/dev/null 2>&1 ||
	 test -f "$file"; then
	:
      elif test -d "$file"; then
	exit_status=1
	continue
      elif $rmforce; then
	continue
      fi

      rmfiles=$file

      case $name in
      *.la)
	# Possibly a libtool archive, so verify it.
	if func_lalib_p "$file"; then
	  func_source $dir/$name

	  # Delete the libtool libraries and symlinks.
	  for n in $library_names; do
	    func_append rmfiles " $odir/$n"
	  done
	  test -n "$old_library" && func_append rmfiles " $odir/$old_library"

	  case $opt_mode in
	  clean)
	    case " $library_names " in
	    *" $dlname "*) ;;
	    *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;;
	    esac
	    test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i"
	    ;;
	  uninstall)
	    if test -n "$library_names"; then
	      # Do each command in the postuninstall commands.
	      func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1'
	    fi

	    if test -n "$old_library"; then
	      # Do each command in the old_postuninstall commands.
	      func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1'
	    fi
	    # FIXME: should reinstall the best remaining shared library.
	    ;;
	  esac
	fi
	;;

      *.lo)
	# Possibly a libtool object, so verify it.
	if func_lalib_p "$file"; then

	  # Read the .lo file
	  func_source $dir/$name

	  # Add PIC object to the list of files to remove.
	  if test -n "$pic_object" && test none != "$pic_object"; then
	    func_append rmfiles " $dir/$pic_object"
	  fi

	  # Add non-PIC object to the list of files to remove.
	  if test -n "$non_pic_object" && test none != "$non_pic_object"; then
	    func_append rmfiles " $dir/$non_pic_object"
	  fi
	fi
	;;

      *)
	if test clean = "$opt_mode"; then
	  noexename=$name
	  case $file in
	  *.exe)
	    func_stripname '' '.exe' "$file"
	    file=$func_stripname_result
	    func_stripname '' '.exe' "$name"
	    noexename=$func_stripname_result
	    # $file with .exe has already been added to rmfiles,
	    # add $file without .exe
	    func_append rmfiles " $file"
	    ;;
	  esac
	  # Do a test to see if this is a libtool program.
	  if func_ltwrapper_p "$file"; then
	    if func_ltwrapper_executable_p "$file"; then
	      func_ltwrapper_scriptname "$file"
	      relink_command=
	      func_source $func_ltwrapper_scriptname_result
	      func_append rmfiles " $func_ltwrapper_scriptname_result"
	    else
	      relink_command=
	      func_source $dir/$noexename
	    fi

	    # note $name still contains .exe if it was in $file originally
	    # as does the version of $file that was added into $rmfiles
	    func_append rmfiles " $odir/$name $odir/${name}S.$objext"
	    if test yes = "$fast_install" && test -n "$relink_command"; then
	      func_append rmfiles " $odir/lt-$name"
	    fi
	    if test "X$noexename" != "X$name"; then
	      func_append rmfiles " $odir/lt-$noexename.c"
	    fi
	  fi
	fi
	;;
      esac
      func_show_eval "$RM $rmfiles" 'exit_status=1'
    done

    # Try to remove the $objdir's in the directories where we deleted files
    for dir in $rmdirs; do
      if test -d "$dir"; then
	func_show_eval "rmdir $dir >/dev/null 2>&1"
      fi
    done

    exit $exit_status
}

if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then
  func_mode_uninstall ${1+"$@"}
fi

test -z "$opt_mode" && {
  help=$generic_help
  func_fatal_help "you must specify a MODE"
}

test -z "$exec_cmd" && \
  func_fatal_help "invalid operation mode '$opt_mode'"

if test -n "$exec_cmd"; then
  eval exec "$exec_cmd"
  exit $EXIT_FAILURE
fi

exit $exit_status


# The TAGs below are defined such that we never get into a situation
# where we disable both kinds of libraries.  Given conflicting
# choices, we go for a static library, that is the most portable,
# since we can't tell whether shared libraries were disabled because
# the user asked for that or because the platform doesn't support
# them.  This is particularly important on AIX, because we don't
# support having both static and shared libraries enabled at the same
# time on that platform, so we default to a shared-only configuration.
# If a disable-shared tag is given, we'll fallback to a static-only
# configuration.  But we'll never go from static-only to shared-only.

# ### BEGIN LIBTOOL TAG CONFIG: disable-shared
build_libtool_libs=no
build_old_libs=yes
# ### END LIBTOOL TAG CONFIG: disable-shared

# ### BEGIN LIBTOOL TAG CONFIG: disable-static
build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac`
# ### END LIBTOOL TAG CONFIG: disable-static

# Local Variables:
# mode:shell-script
# sh-indentation:2
# End:
ode-0.16/m4/0000775000175200017520000000000013403273060007534 500000000000000ode-0.16/m4/ltoptions.m40000644000175200017520000003426213403272661011764 00000000000000# Helper functions for option handling.                    -*- Autoconf -*-
#
#   Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software
#   Foundation, Inc.
#   Written by Gary V. Vaughan, 2004
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.

# serial 8 ltoptions.m4

# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])])


# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME)
# ------------------------------------------
m4_define([_LT_MANGLE_OPTION],
[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])])


# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME)
# ---------------------------------------
# Set option OPTION-NAME for macro MACRO-NAME, and if there is a
# matching handler defined, dispatch to it.  Other OPTION-NAMEs are
# saved as a flag.
m4_define([_LT_SET_OPTION],
[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl
m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]),
        _LT_MANGLE_DEFUN([$1], [$2]),
    [m4_warning([Unknown $1 option '$2'])])[]dnl
])


# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET])
# ------------------------------------------------------------
# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
m4_define([_LT_IF_OPTION],
[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])])


# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET)
# -------------------------------------------------------
# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME
# are set.
m4_define([_LT_UNLESS_OPTIONS],
[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
	    [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option),
		      [m4_define([$0_found])])])[]dnl
m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3
])[]dnl
])


# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST)
# ----------------------------------------
# OPTION-LIST is a space-separated list of Libtool options associated
# with MACRO-NAME.  If any OPTION has a matching handler declared with
# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about
# the unknown option and exit.
m4_defun([_LT_SET_OPTIONS],
[# Set options
m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
    [_LT_SET_OPTION([$1], _LT_Option)])

m4_if([$1],[LT_INIT],[
  dnl
  dnl Simply set some default values (i.e off) if boolean options were not
  dnl specified:
  _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no
  ])
  _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no
  ])
  dnl
  dnl If no reference was made to various pairs of opposing options, then
  dnl we run the default mode handler for the pair.  For example, if neither
  dnl 'shared' nor 'disable-shared' was passed, we enable building of shared
  dnl archives by default:
  _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED])
  _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC])
  _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC])
  _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install],
		   [_LT_ENABLE_FAST_INSTALL])
  _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4],
		   [_LT_WITH_AIX_SONAME([aix])])
  ])
])# _LT_SET_OPTIONS


## --------------------------------- ##
## Macros to handle LT_INIT options. ##
## --------------------------------- ##

# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME)
# -----------------------------------------
m4_define([_LT_MANGLE_DEFUN],
[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])])


# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE)
# -----------------------------------------------
m4_define([LT_OPTION_DEFINE],
[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl
])# LT_OPTION_DEFINE


# dlopen
# ------
LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes
])

AU_DEFUN([AC_LIBTOOL_DLOPEN],
[_LT_SET_OPTION([LT_INIT], [dlopen])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you
put the 'dlopen' option into LT_INIT's first parameter.])
])

dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], [])


# win32-dll
# ---------
# Declare package support for building win32 dll's.
LT_OPTION_DEFINE([LT_INIT], [win32-dll],
[enable_win32_dll=yes

case $host in
*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*)
  AC_CHECK_TOOL(AS, as, false)
  AC_CHECK_TOOL(DLLTOOL, dlltool, false)
  AC_CHECK_TOOL(OBJDUMP, objdump, false)
  ;;
esac

test -z "$AS" && AS=as
_LT_DECL([], [AS],      [1], [Assembler program])dnl

test -z "$DLLTOOL" && DLLTOOL=dlltool
_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl

test -z "$OBJDUMP" && OBJDUMP=objdump
_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl
])# win32-dll

AU_DEFUN([AC_LIBTOOL_WIN32_DLL],
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
_LT_SET_OPTION([LT_INIT], [win32-dll])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you
put the 'win32-dll' option into LT_INIT's first parameter.])
])

dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [])


# _LT_ENABLE_SHARED([DEFAULT])
# ----------------------------
# implement the --enable-shared flag, and supports the 'shared' and
# 'disable-shared' LT_INIT options.
# DEFAULT is either 'yes' or 'no'.  If omitted, it defaults to 'yes'.
m4_define([_LT_ENABLE_SHARED],
[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl
AC_ARG_ENABLE([shared],
    [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
	[build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])],
    [p=${PACKAGE-default}
    case $enableval in
    yes) enable_shared=yes ;;
    no) enable_shared=no ;;
    *)
      enable_shared=no
      # Look at the argument we got.  We use all the common list separators.
      lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
      for pkg in $enableval; do
	IFS=$lt_save_ifs
	if test "X$pkg" = "X$p"; then
	  enable_shared=yes
	fi
      done
      IFS=$lt_save_ifs
      ;;
    esac],
    [enable_shared=]_LT_ENABLE_SHARED_DEFAULT)

    _LT_DECL([build_libtool_libs], [enable_shared], [0],
	[Whether or not to build shared libraries])
])# _LT_ENABLE_SHARED

LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])])
LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])])

# Old names:
AC_DEFUN([AC_ENABLE_SHARED],
[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared])
])

AC_DEFUN([AC_DISABLE_SHARED],
[_LT_SET_OPTION([LT_INIT], [disable-shared])
])

AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])

dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AM_ENABLE_SHARED], [])
dnl AC_DEFUN([AM_DISABLE_SHARED], [])



# _LT_ENABLE_STATIC([DEFAULT])
# ----------------------------
# implement the --enable-static flag, and support the 'static' and
# 'disable-static' LT_INIT options.
# DEFAULT is either 'yes' or 'no'.  If omitted, it defaults to 'yes'.
m4_define([_LT_ENABLE_STATIC],
[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl
AC_ARG_ENABLE([static],
    [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@],
	[build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])],
    [p=${PACKAGE-default}
    case $enableval in
    yes) enable_static=yes ;;
    no) enable_static=no ;;
    *)
     enable_static=no
      # Look at the argument we got.  We use all the common list separators.
      lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
      for pkg in $enableval; do
	IFS=$lt_save_ifs
	if test "X$pkg" = "X$p"; then
	  enable_static=yes
	fi
      done
      IFS=$lt_save_ifs
      ;;
    esac],
    [enable_static=]_LT_ENABLE_STATIC_DEFAULT)

    _LT_DECL([build_old_libs], [enable_static], [0],
	[Whether or not to build static libraries])
])# _LT_ENABLE_STATIC

LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])])
LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])])

# Old names:
AC_DEFUN([AC_ENABLE_STATIC],
[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static])
])

AC_DEFUN([AC_DISABLE_STATIC],
[_LT_SET_OPTION([LT_INIT], [disable-static])
])

AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])

dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AM_ENABLE_STATIC], [])
dnl AC_DEFUN([AM_DISABLE_STATIC], [])



# _LT_ENABLE_FAST_INSTALL([DEFAULT])
# ----------------------------------
# implement the --enable-fast-install flag, and support the 'fast-install'
# and 'disable-fast-install' LT_INIT options.
# DEFAULT is either 'yes' or 'no'.  If omitted, it defaults to 'yes'.
m4_define([_LT_ENABLE_FAST_INSTALL],
[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl
AC_ARG_ENABLE([fast-install],
    [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
    [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
    [p=${PACKAGE-default}
    case $enableval in
    yes) enable_fast_install=yes ;;
    no) enable_fast_install=no ;;
    *)
      enable_fast_install=no
      # Look at the argument we got.  We use all the common list separators.
      lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
      for pkg in $enableval; do
	IFS=$lt_save_ifs
	if test "X$pkg" = "X$p"; then
	  enable_fast_install=yes
	fi
      done
      IFS=$lt_save_ifs
      ;;
    esac],
    [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT)

_LT_DECL([fast_install], [enable_fast_install], [0],
	 [Whether or not to optimize for fast installation])dnl
])# _LT_ENABLE_FAST_INSTALL

LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])])
LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])])

# Old names:
AU_DEFUN([AC_ENABLE_FAST_INSTALL],
[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you put
the 'fast-install' option into LT_INIT's first parameter.])
])

AU_DEFUN([AC_DISABLE_FAST_INSTALL],
[_LT_SET_OPTION([LT_INIT], [disable-fast-install])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you put
the 'disable-fast-install' option into LT_INIT's first parameter.])
])

dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], [])
dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], [])


# _LT_WITH_AIX_SONAME([DEFAULT])
# ----------------------------------
# implement the --with-aix-soname flag, and support the `aix-soname=aix'
# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT
# is either `aix', `both' or `svr4'.  If omitted, it defaults to `aix'.
m4_define([_LT_WITH_AIX_SONAME],
[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl
shared_archive_member_spec=
case $host,$enable_shared in
power*-*-aix[[5-9]]*,yes)
  AC_MSG_CHECKING([which variant of shared library versioning to provide])
  AC_ARG_WITH([aix-soname],
    [AS_HELP_STRING([--with-aix-soname=aix|svr4|both],
      [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])],
    [case $withval in
    aix|svr4|both)
      ;;
    *)
      AC_MSG_ERROR([Unknown argument to --with-aix-soname])
      ;;
    esac
    lt_cv_with_aix_soname=$with_aix_soname],
    [AC_CACHE_VAL([lt_cv_with_aix_soname],
      [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT)
    with_aix_soname=$lt_cv_with_aix_soname])
  AC_MSG_RESULT([$with_aix_soname])
  if test aix != "$with_aix_soname"; then
    # For the AIX way of multilib, we name the shared archive member
    # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o',
    # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File.
    # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag,
    # the AIX toolchain works better with OBJECT_MODE set (default 32).
    if test 64 = "${OBJECT_MODE-32}"; then
      shared_archive_member_spec=shr_64
    else
      shared_archive_member_spec=shr
    fi
  fi
  ;;
*)
  with_aix_soname=aix
  ;;
esac

_LT_DECL([], [shared_archive_member_spec], [0],
    [Shared archive member basename, for filename based shared library versioning on AIX])dnl
])# _LT_WITH_AIX_SONAME

LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])])
LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])])
LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])])


# _LT_WITH_PIC([MODE])
# --------------------
# implement the --with-pic flag, and support the 'pic-only' and 'no-pic'
# LT_INIT options.
# MODE is either 'yes' or 'no'.  If omitted, it defaults to 'both'.
m4_define([_LT_WITH_PIC],
[AC_ARG_WITH([pic],
    [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@],
	[try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
    [lt_p=${PACKAGE-default}
    case $withval in
    yes|no) pic_mode=$withval ;;
    *)
      pic_mode=default
      # Look at the argument we got.  We use all the common list separators.
      lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
      for lt_pkg in $withval; do
	IFS=$lt_save_ifs
	if test "X$lt_pkg" = "X$lt_p"; then
	  pic_mode=yes
	fi
      done
      IFS=$lt_save_ifs
      ;;
    esac],
    [pic_mode=m4_default([$1], [default])])

_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl
])# _LT_WITH_PIC

LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])])
LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])])

# Old name:
AU_DEFUN([AC_LIBTOOL_PICMODE],
[_LT_SET_OPTION([LT_INIT], [pic-only])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you
put the 'pic-only' option into LT_INIT's first parameter.])
])

dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_PICMODE], [])

## ----------------- ##
## LTDL_INIT Options ##
## ----------------- ##

m4_define([_LTDL_MODE], [])
LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive],
		 [m4_define([_LTDL_MODE], [nonrecursive])])
LT_OPTION_DEFINE([LTDL_INIT], [recursive],
		 [m4_define([_LTDL_MODE], [recursive])])
LT_OPTION_DEFINE([LTDL_INIT], [subproject],
		 [m4_define([_LTDL_MODE], [subproject])])

m4_define([_LTDL_TYPE], [])
LT_OPTION_DEFINE([LTDL_INIT], [installable],
		 [m4_define([_LTDL_TYPE], [installable])])
LT_OPTION_DEFINE([LTDL_INIT], [convenience],
		 [m4_define([_LTDL_TYPE], [convenience])])
ode-0.16/m4/lt~obsolete.m40000644000175200017520000001377413403272661012310 00000000000000# lt~obsolete.m4 -- aclocal satisfying obsolete definitions.    -*-Autoconf-*-
#
#   Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software
#   Foundation, Inc.
#   Written by Scott James Remnant, 2004.
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.

# serial 5 lt~obsolete.m4

# These exist entirely to fool aclocal when bootstrapping libtool.
#
# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN),
# which have later been changed to m4_define as they aren't part of the
# exported API, or moved to Autoconf or Automake where they belong.
#
# The trouble is, aclocal is a bit thick.  It'll see the old AC_DEFUN
# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us
# using a macro with the same name in our local m4/libtool.m4 it'll
# pull the old libtool.m4 in (it doesn't see our shiny new m4_define
# and doesn't know about Autoconf macros at all.)
#
# So we provide this file, which has a silly filename so it's always
# included after everything else.  This provides aclocal with the
# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything
# because those macros already exist, or will be overwritten later.
# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6.
#
# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.
# Yes, that means every name once taken will need to remain here until
# we give up compatibility with versions before 1.7, at which point
# we need to keep only those names which we still refer to.

# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])])

m4_ifndef([AC_LIBTOOL_LINKER_OPTION],	[AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])])
m4_ifndef([AC_PROG_EGREP],		[AC_DEFUN([AC_PROG_EGREP])])
m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH],	[AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])])
m4_ifndef([_LT_AC_SHELL_INIT],		[AC_DEFUN([_LT_AC_SHELL_INIT])])
m4_ifndef([_LT_AC_SYS_LIBPATH_AIX],	[AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])])
m4_ifndef([_LT_PROG_LTMAIN],		[AC_DEFUN([_LT_PROG_LTMAIN])])
m4_ifndef([_LT_AC_TAGVAR],		[AC_DEFUN([_LT_AC_TAGVAR])])
m4_ifndef([AC_LTDL_ENABLE_INSTALL],	[AC_DEFUN([AC_LTDL_ENABLE_INSTALL])])
m4_ifndef([AC_LTDL_PREOPEN],		[AC_DEFUN([AC_LTDL_PREOPEN])])
m4_ifndef([_LT_AC_SYS_COMPILER],	[AC_DEFUN([_LT_AC_SYS_COMPILER])])
m4_ifndef([_LT_AC_LOCK],		[AC_DEFUN([_LT_AC_LOCK])])
m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE],	[AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])])
m4_ifndef([_LT_AC_TRY_DLOPEN_SELF],	[AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])])
m4_ifndef([AC_LIBTOOL_PROG_CC_C_O],	[AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])])
m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])])
m4_ifndef([AC_LIBTOOL_OBJDIR],		[AC_DEFUN([AC_LIBTOOL_OBJDIR])])
m4_ifndef([AC_LTDL_OBJDIR],		[AC_DEFUN([AC_LTDL_OBJDIR])])
m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])])
m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP],	[AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])])
m4_ifndef([AC_PATH_MAGIC],		[AC_DEFUN([AC_PATH_MAGIC])])
m4_ifndef([AC_PROG_LD_GNU],		[AC_DEFUN([AC_PROG_LD_GNU])])
m4_ifndef([AC_PROG_LD_RELOAD_FLAG],	[AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])])
m4_ifndef([AC_DEPLIBS_CHECK_METHOD],	[AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])])
m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])])
m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])])
m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])])
m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS],	[AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])])
m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP],	[AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])])
m4_ifndef([LT_AC_PROG_EGREP],		[AC_DEFUN([LT_AC_PROG_EGREP])])
m4_ifndef([LT_AC_PROG_SED],		[AC_DEFUN([LT_AC_PROG_SED])])
m4_ifndef([_LT_CC_BASENAME],		[AC_DEFUN([_LT_CC_BASENAME])])
m4_ifndef([_LT_COMPILER_BOILERPLATE],	[AC_DEFUN([_LT_COMPILER_BOILERPLATE])])
m4_ifndef([_LT_LINKER_BOILERPLATE],	[AC_DEFUN([_LT_LINKER_BOILERPLATE])])
m4_ifndef([_AC_PROG_LIBTOOL],		[AC_DEFUN([_AC_PROG_LIBTOOL])])
m4_ifndef([AC_LIBTOOL_SETUP],		[AC_DEFUN([AC_LIBTOOL_SETUP])])
m4_ifndef([_LT_AC_CHECK_DLFCN],		[AC_DEFUN([_LT_AC_CHECK_DLFCN])])
m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER],	[AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])])
m4_ifndef([_LT_AC_TAGCONFIG],		[AC_DEFUN([_LT_AC_TAGCONFIG])])
m4_ifndef([AC_DISABLE_FAST_INSTALL],	[AC_DEFUN([AC_DISABLE_FAST_INSTALL])])
m4_ifndef([_LT_AC_LANG_CXX],		[AC_DEFUN([_LT_AC_LANG_CXX])])
m4_ifndef([_LT_AC_LANG_F77],		[AC_DEFUN([_LT_AC_LANG_F77])])
m4_ifndef([_LT_AC_LANG_GCJ],		[AC_DEFUN([_LT_AC_LANG_GCJ])])
m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])
m4_ifndef([_LT_AC_LANG_C_CONFIG],	[AC_DEFUN([_LT_AC_LANG_C_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])
m4_ifndef([_LT_AC_LANG_CXX_CONFIG],	[AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])])
m4_ifndef([_LT_AC_LANG_F77_CONFIG],	[AC_DEFUN([_LT_AC_LANG_F77_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])])
m4_ifndef([_LT_AC_LANG_GCJ_CONFIG],	[AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])
m4_ifndef([_LT_AC_LANG_RC_CONFIG],	[AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])
m4_ifndef([AC_LIBTOOL_CONFIG],		[AC_DEFUN([AC_LIBTOOL_CONFIG])])
m4_ifndef([_LT_AC_FILE_LTDLL_C],	[AC_DEFUN([_LT_AC_FILE_LTDLL_C])])
m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS],	[AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])])
m4_ifndef([_LT_AC_PROG_CXXCPP],		[AC_DEFUN([_LT_AC_PROG_CXXCPP])])
m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS],	[AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])])
m4_ifndef([_LT_PROG_ECHO_BACKSLASH],	[AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])])
m4_ifndef([_LT_PROG_F77],		[AC_DEFUN([_LT_PROG_F77])])
m4_ifndef([_LT_PROG_FC],		[AC_DEFUN([_LT_PROG_FC])])
m4_ifndef([_LT_PROG_CXX],		[AC_DEFUN([_LT_PROG_CXX])])
ode-0.16/m4/pkg.m40000664000175200017520000001247313403272463010514 00000000000000# pkg.m4 - Macros to locate and utilise pkg-config.            -*- Autoconf -*-
# serial 1 (pkg-config-0.24)
# 
# Copyright © 2004 Scott James Remnant .
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.

# PKG_PROG_PKG_CONFIG([MIN-VERSION])
# ----------------------------------
AC_DEFUN([PKG_PROG_PKG_CONFIG],
[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
m4_pattern_allow([^PKG_CONFIG(_PATH)?$])
AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])
AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path])
AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path])

if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
	AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
fi
if test -n "$PKG_CONFIG"; then
	_pkg_min_version=m4_default([$1], [0.9.0])
	AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
	if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
		AC_MSG_RESULT([yes])
	else
		AC_MSG_RESULT([no])
		PKG_CONFIG=""
	fi
fi[]dnl
])# PKG_PROG_PKG_CONFIG

# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
#
# Check to see whether a particular set of modules exists.  Similar
# to PKG_CHECK_MODULES(), but does not set variables or print errors.
#
# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
# only at the first occurence in configure.ac, so if the first place
# it's called might be skipped (such as if it is within an "if", you
# have to call PKG_CHECK_EXISTS manually
# --------------------------------------------------------------
AC_DEFUN([PKG_CHECK_EXISTS],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
if test -n "$PKG_CONFIG" && \
    AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
  m4_default([$2], [:])
m4_ifvaln([$3], [else
  $3])dnl
fi])

# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
# ---------------------------------------------
m4_define([_PKG_CONFIG],
[if test -n "$$1"; then
    pkg_cv_[]$1="$$1"
 elif test -n "$PKG_CONFIG"; then
    PKG_CHECK_EXISTS([$3],
                     [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
		     [pkg_failed=yes])
 else
    pkg_failed=untried
fi[]dnl
])# _PKG_CONFIG

# _PKG_SHORT_ERRORS_SUPPORTED
# -----------------------------
AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
        _pkg_short_errors_supported=yes
else
        _pkg_short_errors_supported=no
fi[]dnl
])# _PKG_SHORT_ERRORS_SUPPORTED


# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
# [ACTION-IF-NOT-FOUND])
#
#
# Note that if there is a possibility the first call to
# PKG_CHECK_MODULES might not happen, you should be sure to include an
# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
#
#
# --------------------------------------------------------------
AC_DEFUN([PKG_CHECK_MODULES],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl

pkg_failed=no
AC_MSG_CHECKING([for $1])

_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
_PKG_CONFIG([$1][_LIBS], [libs], [$2])

m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
and $1[]_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details.])

if test $pkg_failed = yes; then
   	AC_MSG_RESULT([no])
        _PKG_SHORT_ERRORS_SUPPORTED
        if test $_pkg_short_errors_supported = yes; then
	        $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "$2" 2>&1`
        else 
	        $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors "$2" 2>&1`
        fi
	# Put the nasty error message in config.log where it belongs
	echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD

	m4_default([$4], [AC_MSG_ERROR(
[Package requirements ($2) were not met:

$$1_PKG_ERRORS

Consider adjusting the PKG_CONFIG_PATH environment variable if you
installed software in a non-standard prefix.

_PKG_TEXT])
        ])
elif test $pkg_failed = untried; then
     	AC_MSG_RESULT([no])
	m4_default([$4], [AC_MSG_FAILURE(
[The pkg-config script could not be found or is too old.  Make sure it
is in your PATH or set the PKG_CONFIG environment variable to the full
path to pkg-config.

_PKG_TEXT

To get pkg-config, see .])
        ])
else
	$1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
	$1[]_LIBS=$pkg_cv_[]$1[]_LIBS
        AC_MSG_RESULT([yes])
	$3
fi[]dnl
])# PKG_CHECK_MODULES
ode-0.16/m4/ltsugar.m40000644000175200017520000001044013403272661011402 00000000000000# ltsugar.m4 -- libtool m4 base layer.                         -*-Autoconf-*-
#
# Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software
# Foundation, Inc.
# Written by Gary V. Vaughan, 2004
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.

# serial 6 ltsugar.m4

# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])])


# lt_join(SEP, ARG1, [ARG2...])
# -----------------------------
# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their
# associated separator.
# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier
# versions in m4sugar had bugs.
m4_define([lt_join],
[m4_if([$#], [1], [],
       [$#], [2], [[$2]],
       [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])])
m4_define([_lt_join],
[m4_if([$#$2], [2], [],
       [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])])


# lt_car(LIST)
# lt_cdr(LIST)
# ------------
# Manipulate m4 lists.
# These macros are necessary as long as will still need to support
# Autoconf-2.59, which quotes differently.
m4_define([lt_car], [[$1]])
m4_define([lt_cdr],
[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],
       [$#], 1, [],
       [m4_dquote(m4_shift($@))])])
m4_define([lt_unquote], $1)


# lt_append(MACRO-NAME, STRING, [SEPARATOR])
# ------------------------------------------
# Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'.
# Note that neither SEPARATOR nor STRING are expanded; they are appended
# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked).
# No SEPARATOR is output if MACRO-NAME was previously undefined (different
# than defined and empty).
#
# This macro is needed until we can rely on Autoconf 2.62, since earlier
# versions of m4sugar mistakenly expanded SEPARATOR but not STRING.
m4_define([lt_append],
[m4_define([$1],
	   m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])])



# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...])
# ----------------------------------------------------------
# Produce a SEP delimited list of all paired combinations of elements of
# PREFIX-LIST with SUFFIX1 through SUFFIXn.  Each element of the list
# has the form PREFIXmINFIXSUFFIXn.
# Needed until we can rely on m4_combine added in Autoconf 2.62.
m4_define([lt_combine],
[m4_if(m4_eval([$# > 3]), [1],
       [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl
[[m4_foreach([_Lt_prefix], [$2],
	     [m4_foreach([_Lt_suffix],
		]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[,
	[_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])])


# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ])
# -----------------------------------------------------------------------
# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited
# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ.
m4_define([lt_if_append_uniq],
[m4_ifdef([$1],
	  [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1],
		 [lt_append([$1], [$2], [$3])$4],
		 [$5])],
	  [lt_append([$1], [$2], [$3])$4])])


# lt_dict_add(DICT, KEY, VALUE)
# -----------------------------
m4_define([lt_dict_add],
[m4_define([$1($2)], [$3])])


# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE)
# --------------------------------------------
m4_define([lt_dict_add_subkey],
[m4_define([$1($2:$3)], [$4])])


# lt_dict_fetch(DICT, KEY, [SUBKEY])
# ----------------------------------
m4_define([lt_dict_fetch],
[m4_ifval([$3],
	m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]),
    m4_ifdef([$1($2)], [m4_defn([$1($2)])]))])


# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE])
# -----------------------------------------------------------------
m4_define([lt_if_dict_fetch],
[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4],
	[$5],
    [$6])])


# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...])
# --------------------------------------------------------------
m4_define([lt_dict_filter],
[m4_if([$5], [], [],
  [lt_join(m4_quote(m4_default([$4], [[, ]])),
           lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]),
		      [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl
])
ode-0.16/m4/libtool.m40000644000175200017520000112631113403272661011373 00000000000000# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
#
#   Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc.
#   Written by Gordon Matzigkeit, 1996
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.

m4_define([_LT_COPYING], [dnl
# Copyright (C) 2014 Free Software Foundation, Inc.
# This is free software; see the source for copying conditions.  There is NO
# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

# GNU Libtool is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of of the License, or
# (at your option) any later version.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program or library that is built
# using GNU Libtool, you may include this file under the  same
# distribution terms that you use for the rest of that program.
#
# GNU Libtool is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see .
])

# serial 58 LT_INIT


# LT_PREREQ(VERSION)
# ------------------
# Complain and exit if this libtool version is less that VERSION.
m4_defun([LT_PREREQ],
[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1,
       [m4_default([$3],
		   [m4_fatal([Libtool version $1 or higher is required],
		             63)])],
       [$2])])


# _LT_CHECK_BUILDDIR
# ------------------
# Complain if the absolute build directory name contains unusual characters
m4_defun([_LT_CHECK_BUILDDIR],
[case `pwd` in
  *\ * | *\	*)
    AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;;
esac
])


# LT_INIT([OPTIONS])
# ------------------
AC_DEFUN([LT_INIT],
[AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK
AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
AC_BEFORE([$0], [LT_LANG])dnl
AC_BEFORE([$0], [LT_OUTPUT])dnl
AC_BEFORE([$0], [LTDL_INIT])dnl
m4_require([_LT_CHECK_BUILDDIR])dnl

dnl Autoconf doesn't catch unexpanded LT_ macros by default:
m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl
m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl
dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4
dnl unless we require an AC_DEFUNed macro:
AC_REQUIRE([LTOPTIONS_VERSION])dnl
AC_REQUIRE([LTSUGAR_VERSION])dnl
AC_REQUIRE([LTVERSION_VERSION])dnl
AC_REQUIRE([LTOBSOLETE_VERSION])dnl
m4_require([_LT_PROG_LTMAIN])dnl

_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}])

dnl Parse OPTIONS
_LT_SET_OPTIONS([$0], [$1])

# This can be used to rebuild libtool when needed
LIBTOOL_DEPS=$ltmain

# Always use our own libtool.
LIBTOOL='$(SHELL) $(top_builddir)/libtool'
AC_SUBST(LIBTOOL)dnl

_LT_SETUP

# Only expand once:
m4_define([LT_INIT])
])# LT_INIT

# Old names:
AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT])
AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_PROG_LIBTOOL], [])
dnl AC_DEFUN([AM_PROG_LIBTOOL], [])


# _LT_PREPARE_CC_BASENAME
# -----------------------
m4_defun([_LT_PREPARE_CC_BASENAME], [
# Calculate cc_basename.  Skip known compiler wrappers and cross-prefix.
func_cc_basename ()
{
    for cc_temp in @S|@*""; do
      case $cc_temp in
        compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;;
        distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;;
        \-*) ;;
        *) break;;
      esac
    done
    func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
}
])# _LT_PREPARE_CC_BASENAME


# _LT_CC_BASENAME(CC)
# -------------------
# It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME,
# but that macro is also expanded into generated libtool script, which
# arranges for $SED and $ECHO to be set by different means.
m4_defun([_LT_CC_BASENAME],
[m4_require([_LT_PREPARE_CC_BASENAME])dnl
AC_REQUIRE([_LT_DECL_SED])dnl
AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl
func_cc_basename $1
cc_basename=$func_cc_basename_result
])


# _LT_FILEUTILS_DEFAULTS
# ----------------------
# It is okay to use these file commands and assume they have been set
# sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'.
m4_defun([_LT_FILEUTILS_DEFAULTS],
[: ${CP="cp -f"}
: ${MV="mv -f"}
: ${RM="rm -f"}
])# _LT_FILEUTILS_DEFAULTS


# _LT_SETUP
# ---------
m4_defun([_LT_SETUP],
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
AC_REQUIRE([AC_CANONICAL_BUILD])dnl
AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl
AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl

_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl
dnl
_LT_DECL([], [host_alias], [0], [The host system])dnl
_LT_DECL([], [host], [0])dnl
_LT_DECL([], [host_os], [0])dnl
dnl
_LT_DECL([], [build_alias], [0], [The build system])dnl
_LT_DECL([], [build], [0])dnl
_LT_DECL([], [build_os], [0])dnl
dnl
AC_REQUIRE([AC_PROG_CC])dnl
AC_REQUIRE([LT_PATH_LD])dnl
AC_REQUIRE([LT_PATH_NM])dnl
dnl
AC_REQUIRE([AC_PROG_LN_S])dnl
test -z "$LN_S" && LN_S="ln -s"
_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl
dnl
AC_REQUIRE([LT_CMD_MAX_LEN])dnl
_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl
_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl
dnl
m4_require([_LT_FILEUTILS_DEFAULTS])dnl
m4_require([_LT_CHECK_SHELL_FEATURES])dnl
m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl
m4_require([_LT_CMD_RELOAD])dnl
m4_require([_LT_CHECK_MAGIC_METHOD])dnl
m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl
m4_require([_LT_CMD_OLD_ARCHIVE])dnl
m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
m4_require([_LT_WITH_SYSROOT])dnl
m4_require([_LT_CMD_TRUNCATE])dnl

_LT_CONFIG_LIBTOOL_INIT([
# See if we are running on zsh, and set the options that allow our
# commands through without removal of \ escapes INIT.
if test -n "\${ZSH_VERSION+set}"; then
   setopt NO_GLOB_SUBST
fi
])
if test -n "${ZSH_VERSION+set}"; then
   setopt NO_GLOB_SUBST
fi

_LT_CHECK_OBJDIR

m4_require([_LT_TAG_COMPILER])dnl

case $host_os in
aix3*)
  # AIX sometimes has problems with the GCC collect2 program.  For some
  # reason, if we set the COLLECT_NAMES environment variable, the problems
  # vanish in a puff of smoke.
  if test set != "${COLLECT_NAMES+set}"; then
    COLLECT_NAMES=
    export COLLECT_NAMES
  fi
  ;;
esac

# Global variables:
ofile=libtool
can_build_shared=yes

# All known linkers require a '.a' archive for static linking (except MSVC,
# which needs '.lib').
libext=a

with_gnu_ld=$lt_cv_prog_gnu_ld

old_CC=$CC
old_CFLAGS=$CFLAGS

# Set sane defaults for various variables
test -z "$CC" && CC=cc
test -z "$LTCC" && LTCC=$CC
test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
test -z "$LD" && LD=ld
test -z "$ac_objext" && ac_objext=o

_LT_CC_BASENAME([$compiler])

# Only perform the check for file, if the check method requires it
test -z "$MAGIC_CMD" && MAGIC_CMD=file
case $deplibs_check_method in
file_magic*)
  if test "$file_magic_cmd" = '$MAGIC_CMD'; then
    _LT_PATH_MAGIC
  fi
  ;;
esac

# Use C for the default configuration in the libtool script
LT_SUPPORTED_TAG([CC])
_LT_LANG_C_CONFIG
_LT_LANG_DEFAULT_CONFIG
_LT_CONFIG_COMMANDS
])# _LT_SETUP


# _LT_PREPARE_SED_QUOTE_VARS
# --------------------------
# Define a few sed substitution that help us do robust quoting.
m4_defun([_LT_PREPARE_SED_QUOTE_VARS],
[# Backslashify metacharacters that are still active within
# double-quoted strings.
sed_quote_subst='s/\([["`$\\]]\)/\\\1/g'

# Same as above, but do not quote variable references.
double_quote_subst='s/\([["`\\]]\)/\\\1/g'

# Sed substitution to delay expansion of an escaped shell variable in a
# double_quote_subst'ed string.
delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'

# Sed substitution to delay expansion of an escaped single quote.
delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'

# Sed substitution to avoid accidental globbing in evaled expressions
no_glob_subst='s/\*/\\\*/g'
])

# _LT_PROG_LTMAIN
# ---------------
# Note that this code is called both from 'configure', and 'config.status'
# now that we use AC_CONFIG_COMMANDS to generate libtool.  Notably,
# 'config.status' has no value for ac_aux_dir unless we are using Automake,
# so we pass a copy along to make sure it has a sensible value anyway.
m4_defun([_LT_PROG_LTMAIN],
[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl
_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir'])
ltmain=$ac_aux_dir/ltmain.sh
])# _LT_PROG_LTMAIN


## ------------------------------------- ##
## Accumulate code for creating libtool. ##
## ------------------------------------- ##

# So that we can recreate a full libtool script including additional
# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS
# in macros and then make a single call at the end using the 'libtool'
# label.


# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS])
# ----------------------------------------
# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later.
m4_define([_LT_CONFIG_LIBTOOL_INIT],
[m4_ifval([$1],
          [m4_append([_LT_OUTPUT_LIBTOOL_INIT],
                     [$1
])])])

# Initialize.
m4_define([_LT_OUTPUT_LIBTOOL_INIT])


# _LT_CONFIG_LIBTOOL([COMMANDS])
# ------------------------------
# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later.
m4_define([_LT_CONFIG_LIBTOOL],
[m4_ifval([$1],
          [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS],
                     [$1
])])])

# Initialize.
m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS])


# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS])
# -----------------------------------------------------
m4_defun([_LT_CONFIG_SAVE_COMMANDS],
[_LT_CONFIG_LIBTOOL([$1])
_LT_CONFIG_LIBTOOL_INIT([$2])
])


# _LT_FORMAT_COMMENT([COMMENT])
# -----------------------------
# Add leading comment marks to the start of each line, and a trailing
# full-stop to the whole comment if one is not present already.
m4_define([_LT_FORMAT_COMMENT],
[m4_ifval([$1], [
m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])],
              [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.])
)])



## ------------------------ ##
## FIXME: Eliminate VARNAME ##
## ------------------------ ##


# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?])
# -------------------------------------------------------------------
# CONFIGNAME is the name given to the value in the libtool script.
# VARNAME is the (base) name used in the configure script.
# VALUE may be 0, 1 or 2 for a computed quote escaped value based on
# VARNAME.  Any other value will be used directly.
m4_define([_LT_DECL],
[lt_if_append_uniq([lt_decl_varnames], [$2], [, ],
    [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name],
	[m4_ifval([$1], [$1], [$2])])
    lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3])
    m4_ifval([$4],
	[lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])])
    lt_dict_add_subkey([lt_decl_dict], [$2],
	[tagged?], [m4_ifval([$5], [yes], [no])])])
])


# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION])
# --------------------------------------------------------
m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])])


# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...])
# ------------------------------------------------
m4_define([lt_decl_tag_varnames],
[_lt_decl_filter([tagged?], [yes], $@)])


# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..])
# ---------------------------------------------------------
m4_define([_lt_decl_filter],
[m4_case([$#],
  [0], [m4_fatal([$0: too few arguments: $#])],
  [1], [m4_fatal([$0: too few arguments: $#: $1])],
  [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)],
  [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)],
  [lt_dict_filter([lt_decl_dict], $@)])[]dnl
])


# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...])
# --------------------------------------------------
m4_define([lt_decl_quote_varnames],
[_lt_decl_filter([value], [1], $@)])


# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...])
# ---------------------------------------------------
m4_define([lt_decl_dquote_varnames],
[_lt_decl_filter([value], [2], $@)])


# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...])
# ---------------------------------------------------
m4_define([lt_decl_varnames_tagged],
[m4_assert([$# <= 2])dnl
_$0(m4_quote(m4_default([$1], [[, ]])),
    m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]),
    m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))])
m4_define([_lt_decl_varnames_tagged],
[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])])


# lt_decl_all_varnames([SEPARATOR], [VARNAME1...])
# ------------------------------------------------
m4_define([lt_decl_all_varnames],
[_$0(m4_quote(m4_default([$1], [[, ]])),
     m4_if([$2], [],
	   m4_quote(lt_decl_varnames),
	m4_quote(m4_shift($@))))[]dnl
])
m4_define([_lt_decl_all_varnames],
[lt_join($@, lt_decl_varnames_tagged([$1],
			lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl
])


# _LT_CONFIG_STATUS_DECLARE([VARNAME])
# ------------------------------------
# Quote a variable value, and forward it to 'config.status' so that its
# declaration there will have the same value as in 'configure'.  VARNAME
# must have a single quote delimited value for this to work.
m4_define([_LT_CONFIG_STATUS_DECLARE],
[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`'])


# _LT_CONFIG_STATUS_DECLARATIONS
# ------------------------------
# We delimit libtool config variables with single quotes, so when
# we write them to config.status, we have to be sure to quote all
# embedded single quotes properly.  In configure, this macro expands
# each variable declared with _LT_DECL (and _LT_TAGDECL) into:
#
#    ='`$ECHO "$" | $SED "$delay_single_quote_subst"`'
m4_defun([_LT_CONFIG_STATUS_DECLARATIONS],
[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames),
    [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])])


# _LT_LIBTOOL_TAGS
# ----------------
# Output comment and list of tags supported by the script
m4_defun([_LT_LIBTOOL_TAGS],
[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl
available_tags='_LT_TAGS'dnl
])


# _LT_LIBTOOL_DECLARE(VARNAME, [TAG])
# -----------------------------------
# Extract the dictionary values for VARNAME (optionally with TAG) and
# expand to a commented shell variable setting:
#
#    # Some comment about what VAR is for.
#    visible_name=$lt_internal_name
m4_define([_LT_LIBTOOL_DECLARE],
[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1],
					   [description])))[]dnl
m4_pushdef([_libtool_name],
    m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl
m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])),
    [0], [_libtool_name=[$]$1],
    [1], [_libtool_name=$lt_[]$1],
    [2], [_libtool_name=$lt_[]$1],
    [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl
m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl
])


# _LT_LIBTOOL_CONFIG_VARS
# -----------------------
# Produce commented declarations of non-tagged libtool config variables
# suitable for insertion in the LIBTOOL CONFIG section of the 'libtool'
# script.  Tagged libtool config variables (even for the LIBTOOL CONFIG
# section) are produced by _LT_LIBTOOL_TAG_VARS.
m4_defun([_LT_LIBTOOL_CONFIG_VARS],
[m4_foreach([_lt_var],
    m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)),
    [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])])


# _LT_LIBTOOL_TAG_VARS(TAG)
# -------------------------
m4_define([_LT_LIBTOOL_TAG_VARS],
[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames),
    [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])])


# _LT_TAGVAR(VARNAME, [TAGNAME])
# ------------------------------
m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])])


# _LT_CONFIG_COMMANDS
# -------------------
# Send accumulated output to $CONFIG_STATUS.  Thanks to the lists of
# variables for single and double quote escaping we saved from calls
# to _LT_DECL, we can put quote escaped variables declarations
# into 'config.status', and then the shell code to quote escape them in
# for loops in 'config.status'.  Finally, any additional code accumulated
# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded.
m4_defun([_LT_CONFIG_COMMANDS],
[AC_PROVIDE_IFELSE([LT_OUTPUT],
	dnl If the libtool generation code has been placed in $CONFIG_LT,
	dnl instead of duplicating it all over again into config.status,
	dnl then we will have config.status run $CONFIG_LT later, so it
	dnl needs to know what name is stored there:
        [AC_CONFIG_COMMANDS([libtool],
            [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])],
    dnl If the libtool generation code is destined for config.status,
    dnl expand the accumulated commands and init code now:
    [AC_CONFIG_COMMANDS([libtool],
        [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])])
])#_LT_CONFIG_COMMANDS


# Initialize.
m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT],
[

# The HP-UX ksh and POSIX shell print the target directory to stdout
# if CDPATH is set.
(unset CDPATH) >/dev/null 2>&1 && unset CDPATH

sed_quote_subst='$sed_quote_subst'
double_quote_subst='$double_quote_subst'
delay_variable_subst='$delay_variable_subst'
_LT_CONFIG_STATUS_DECLARATIONS
LTCC='$LTCC'
LTCFLAGS='$LTCFLAGS'
compiler='$compiler_DEFAULT'

# A function that is used when there is no print builtin or printf.
func_fallback_echo ()
{
  eval 'cat <<_LTECHO_EOF
\$[]1
_LTECHO_EOF'
}

# Quote evaled strings.
for var in lt_decl_all_varnames([[ \
]], lt_decl_quote_varnames); do
    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
    *[[\\\\\\\`\\"\\\$]]*)
      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
      ;;
    *)
      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
      ;;
    esac
done

# Double-quote double-evaled strings.
for var in lt_decl_all_varnames([[ \
]], lt_decl_dquote_varnames); do
    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
    *[[\\\\\\\`\\"\\\$]]*)
      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
      ;;
    *)
      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
      ;;
    esac
done

_LT_OUTPUT_LIBTOOL_INIT
])

# _LT_GENERATED_FILE_INIT(FILE, [COMMENT])
# ------------------------------------
# Generate a child script FILE with all initialization necessary to
# reuse the environment learned by the parent script, and make the
# file executable.  If COMMENT is supplied, it is inserted after the
# '#!' sequence but before initialization text begins.  After this
# macro, additional text can be appended to FILE to form the body of
# the child script.  The macro ends with non-zero status if the
# file could not be fully written (such as if the disk is full).
m4_ifdef([AS_INIT_GENERATED],
[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])],
[m4_defun([_LT_GENERATED_FILE_INIT],
[m4_require([AS_PREPARE])]dnl
[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl
[lt_write_fail=0
cat >$1 <<_ASEOF || lt_write_fail=1
#! $SHELL
# Generated by $as_me.
$2
SHELL=\${CONFIG_SHELL-$SHELL}
export SHELL
_ASEOF
cat >>$1 <<\_ASEOF || lt_write_fail=1
AS_SHELL_SANITIZE
_AS_PREPARE
exec AS_MESSAGE_FD>&1
_ASEOF
test 0 = "$lt_write_fail" && chmod +x $1[]dnl
m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT

# LT_OUTPUT
# ---------
# This macro allows early generation of the libtool script (before
# AC_OUTPUT is called), incase it is used in configure for compilation
# tests.
AC_DEFUN([LT_OUTPUT],
[: ${CONFIG_LT=./config.lt}
AC_MSG_NOTICE([creating $CONFIG_LT])
_LT_GENERATED_FILE_INIT(["$CONFIG_LT"],
[# Run this file to recreate a libtool stub with the current configuration.])

cat >>"$CONFIG_LT" <<\_LTEOF
lt_cl_silent=false
exec AS_MESSAGE_LOG_FD>>config.log
{
  echo
  AS_BOX([Running $as_me.])
} >&AS_MESSAGE_LOG_FD

lt_cl_help="\
'$as_me' creates a local libtool stub from the current configuration,
for use in further configure time tests before the real libtool is
generated.

Usage: $[0] [[OPTIONS]]

  -h, --help      print this help, then exit
  -V, --version   print version number, then exit
  -q, --quiet     do not print progress messages
  -d, --debug     don't remove temporary files

Report bugs to ."

lt_cl_version="\
m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl
m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION])
configured by $[0], generated by m4_PACKAGE_STRING.

Copyright (C) 2011 Free Software Foundation, Inc.
This config.lt script is free software; the Free Software Foundation
gives unlimited permision to copy, distribute and modify it."

while test 0 != $[#]
do
  case $[1] in
    --version | --v* | -V )
      echo "$lt_cl_version"; exit 0 ;;
    --help | --h* | -h )
      echo "$lt_cl_help"; exit 0 ;;
    --debug | --d* | -d )
      debug=: ;;
    --quiet | --q* | --silent | --s* | -q )
      lt_cl_silent=: ;;

    -*) AC_MSG_ERROR([unrecognized option: $[1]
Try '$[0] --help' for more information.]) ;;

    *) AC_MSG_ERROR([unrecognized argument: $[1]
Try '$[0] --help' for more information.]) ;;
  esac
  shift
done

if $lt_cl_silent; then
  exec AS_MESSAGE_FD>/dev/null
fi
_LTEOF

cat >>"$CONFIG_LT" <<_LTEOF
_LT_OUTPUT_LIBTOOL_COMMANDS_INIT
_LTEOF

cat >>"$CONFIG_LT" <<\_LTEOF
AC_MSG_NOTICE([creating $ofile])
_LT_OUTPUT_LIBTOOL_COMMANDS
AS_EXIT(0)
_LTEOF
chmod +x "$CONFIG_LT"

# configure is writing to config.log, but config.lt does its own redirection,
# appending to config.log, which fails on DOS, as config.log is still kept
# open by configure.  Here we exec the FD to /dev/null, effectively closing
# config.log, so it can be properly (re)opened and appended to by config.lt.
lt_cl_success=:
test yes = "$silent" &&
  lt_config_lt_args="$lt_config_lt_args --quiet"
exec AS_MESSAGE_LOG_FD>/dev/null
$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false
exec AS_MESSAGE_LOG_FD>>config.log
$lt_cl_success || AS_EXIT(1)
])# LT_OUTPUT


# _LT_CONFIG(TAG)
# ---------------
# If TAG is the built-in tag, create an initial libtool script with a
# default configuration from the untagged config vars.  Otherwise add code
# to config.status for appending the configuration named by TAG from the
# matching tagged config vars.
m4_defun([_LT_CONFIG],
[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
_LT_CONFIG_SAVE_COMMANDS([
  m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl
  m4_if(_LT_TAG, [C], [
    # See if we are running on zsh, and set the options that allow our
    # commands through without removal of \ escapes.
    if test -n "${ZSH_VERSION+set}"; then
      setopt NO_GLOB_SUBST
    fi

    cfgfile=${ofile}T
    trap "$RM \"$cfgfile\"; exit 1" 1 2 15
    $RM "$cfgfile"

    cat <<_LT_EOF >> "$cfgfile"
#! $SHELL
# Generated automatically by $as_me ($PACKAGE) $VERSION
# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
# NOTE: Changes made to this file will be lost: look at ltmain.sh.

# Provide generalized library-building support services.
# Written by Gordon Matzigkeit, 1996

_LT_COPYING
_LT_LIBTOOL_TAGS

# Configured defaults for sys_lib_dlsearch_path munging.
: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"}

# ### BEGIN LIBTOOL CONFIG
_LT_LIBTOOL_CONFIG_VARS
_LT_LIBTOOL_TAG_VARS
# ### END LIBTOOL CONFIG

_LT_EOF

    cat <<'_LT_EOF' >> "$cfgfile"

# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE

_LT_PREPARE_MUNGE_PATH_LIST
_LT_PREPARE_CC_BASENAME

# ### END FUNCTIONS SHARED WITH CONFIGURE

_LT_EOF

  case $host_os in
  aix3*)
    cat <<\_LT_EOF >> "$cfgfile"
# AIX sometimes has problems with the GCC collect2 program.  For some
# reason, if we set the COLLECT_NAMES environment variable, the problems
# vanish in a puff of smoke.
if test set != "${COLLECT_NAMES+set}"; then
  COLLECT_NAMES=
  export COLLECT_NAMES
fi
_LT_EOF
    ;;
  esac

  _LT_PROG_LTMAIN

  # We use sed instead of cat because bash on DJGPP gets confused if
  # if finds mixed CR/LF and LF-only lines.  Since sed operates in
  # text mode, it properly converts lines to CR/LF.  This bash problem
  # is reportedly fixed, but why not run on old versions too?
  sed '$q' "$ltmain" >> "$cfgfile" \
     || (rm -f "$cfgfile"; exit 1)

   mv -f "$cfgfile" "$ofile" ||
    (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
  chmod +x "$ofile"
],
[cat <<_LT_EOF >> "$ofile"

dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded
dnl in a comment (ie after a #).
# ### BEGIN LIBTOOL TAG CONFIG: $1
_LT_LIBTOOL_TAG_VARS(_LT_TAG)
# ### END LIBTOOL TAG CONFIG: $1
_LT_EOF
])dnl /m4_if
],
[m4_if([$1], [], [
    PACKAGE='$PACKAGE'
    VERSION='$VERSION'
    RM='$RM'
    ofile='$ofile'], [])
])dnl /_LT_CONFIG_SAVE_COMMANDS
])# _LT_CONFIG


# LT_SUPPORTED_TAG(TAG)
# ---------------------
# Trace this macro to discover what tags are supported by the libtool
# --tag option, using:
#    autoconf --trace 'LT_SUPPORTED_TAG:$1'
AC_DEFUN([LT_SUPPORTED_TAG], [])


# C support is built-in for now
m4_define([_LT_LANG_C_enabled], [])
m4_define([_LT_TAGS], [])


# LT_LANG(LANG)
# -------------
# Enable libtool support for the given language if not already enabled.
AC_DEFUN([LT_LANG],
[AC_BEFORE([$0], [LT_OUTPUT])dnl
m4_case([$1],
  [C],			[_LT_LANG(C)],
  [C++],		[_LT_LANG(CXX)],
  [Go],			[_LT_LANG(GO)],
  [Java],		[_LT_LANG(GCJ)],
  [Fortran 77],		[_LT_LANG(F77)],
  [Fortran],		[_LT_LANG(FC)],
  [Windows Resource],	[_LT_LANG(RC)],
  [m4_ifdef([_LT_LANG_]$1[_CONFIG],
    [_LT_LANG($1)],
    [m4_fatal([$0: unsupported language: "$1"])])])dnl
])# LT_LANG


# _LT_LANG(LANGNAME)
# ------------------
m4_defun([_LT_LANG],
[m4_ifdef([_LT_LANG_]$1[_enabled], [],
  [LT_SUPPORTED_TAG([$1])dnl
  m4_append([_LT_TAGS], [$1 ])dnl
  m4_define([_LT_LANG_]$1[_enabled], [])dnl
  _LT_LANG_$1_CONFIG($1)])dnl
])# _LT_LANG


m4_ifndef([AC_PROG_GO], [
############################################################
# NOTE: This macro has been submitted for inclusion into   #
#  GNU Autoconf as AC_PROG_GO.  When it is available in    #
#  a released version of Autoconf we should remove this    #
#  macro and use it instead.                               #
############################################################
m4_defun([AC_PROG_GO],
[AC_LANG_PUSH(Go)dnl
AC_ARG_VAR([GOC],     [Go compiler command])dnl
AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl
_AC_ARG_VAR_LDFLAGS()dnl
AC_CHECK_TOOL(GOC, gccgo)
if test -z "$GOC"; then
  if test -n "$ac_tool_prefix"; then
    AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo])
  fi
fi
if test -z "$GOC"; then
  AC_CHECK_PROG(GOC, gccgo, gccgo, false)
fi
])#m4_defun
])#m4_ifndef


# _LT_LANG_DEFAULT_CONFIG
# -----------------------
m4_defun([_LT_LANG_DEFAULT_CONFIG],
[AC_PROVIDE_IFELSE([AC_PROG_CXX],
  [LT_LANG(CXX)],
  [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])])

AC_PROVIDE_IFELSE([AC_PROG_F77],
  [LT_LANG(F77)],
  [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])])

AC_PROVIDE_IFELSE([AC_PROG_FC],
  [LT_LANG(FC)],
  [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])])

dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal
dnl pulling things in needlessly.
AC_PROVIDE_IFELSE([AC_PROG_GCJ],
  [LT_LANG(GCJ)],
  [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],
    [LT_LANG(GCJ)],
    [AC_PROVIDE_IFELSE([LT_PROG_GCJ],
      [LT_LANG(GCJ)],
      [m4_ifdef([AC_PROG_GCJ],
	[m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])])
       m4_ifdef([A][M_PROG_GCJ],
	[m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])])
       m4_ifdef([LT_PROG_GCJ],
	[m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])])

AC_PROVIDE_IFELSE([AC_PROG_GO],
  [LT_LANG(GO)],
  [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])])

AC_PROVIDE_IFELSE([LT_PROG_RC],
  [LT_LANG(RC)],
  [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])])
])# _LT_LANG_DEFAULT_CONFIG

# Obsolete macros:
AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)])
AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)])
AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)])
AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)])
AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_CXX], [])
dnl AC_DEFUN([AC_LIBTOOL_F77], [])
dnl AC_DEFUN([AC_LIBTOOL_FC], [])
dnl AC_DEFUN([AC_LIBTOOL_GCJ], [])
dnl AC_DEFUN([AC_LIBTOOL_RC], [])


# _LT_TAG_COMPILER
# ----------------
m4_defun([_LT_TAG_COMPILER],
[AC_REQUIRE([AC_PROG_CC])dnl

_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl
_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl
_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl
_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl

# If no C compiler was specified, use CC.
LTCC=${LTCC-"$CC"}

# If no C compiler flags were specified, use CFLAGS.
LTCFLAGS=${LTCFLAGS-"$CFLAGS"}

# Allow CC to be a program name with arguments.
compiler=$CC
])# _LT_TAG_COMPILER


# _LT_COMPILER_BOILERPLATE
# ------------------------
# Check for compiler boilerplate output or warnings with
# the simple compiler test code.
m4_defun([_LT_COMPILER_BOILERPLATE],
[m4_require([_LT_DECL_SED])dnl
ac_outfile=conftest.$ac_objext
echo "$lt_simple_compile_test_code" >conftest.$ac_ext
eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
_lt_compiler_boilerplate=`cat conftest.err`
$RM conftest*
])# _LT_COMPILER_BOILERPLATE


# _LT_LINKER_BOILERPLATE
# ----------------------
# Check for linker boilerplate output or warnings with
# the simple link test code.
m4_defun([_LT_LINKER_BOILERPLATE],
[m4_require([_LT_DECL_SED])dnl
ac_outfile=conftest.$ac_objext
echo "$lt_simple_link_test_code" >conftest.$ac_ext
eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
_lt_linker_boilerplate=`cat conftest.err`
$RM -r conftest*
])# _LT_LINKER_BOILERPLATE

# _LT_REQUIRED_DARWIN_CHECKS
# -------------------------
m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[
  case $host_os in
    rhapsody* | darwin*)
    AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:])
    AC_CHECK_TOOL([NMEDIT], [nmedit], [:])
    AC_CHECK_TOOL([LIPO], [lipo], [:])
    AC_CHECK_TOOL([OTOOL], [otool], [:])
    AC_CHECK_TOOL([OTOOL64], [otool64], [:])
    _LT_DECL([], [DSYMUTIL], [1],
      [Tool to manipulate archived DWARF debug symbol files on Mac OS X])
    _LT_DECL([], [NMEDIT], [1],
      [Tool to change global to local symbols on Mac OS X])
    _LT_DECL([], [LIPO], [1],
      [Tool to manipulate fat objects and archives on Mac OS X])
    _LT_DECL([], [OTOOL], [1],
      [ldd/readelf like tool for Mach-O binaries on Mac OS X])
    _LT_DECL([], [OTOOL64], [1],
      [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4])

    AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod],
      [lt_cv_apple_cc_single_mod=no
      if test -z "$LT_MULTI_MODULE"; then
	# By default we will add the -single_module flag. You can override
	# by either setting the environment variable LT_MULTI_MODULE
	# non-empty at configure time, or by adding -multi_module to the
	# link flags.
	rm -rf libconftest.dylib*
	echo "int foo(void){return 1;}" > conftest.c
	echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD
	$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
	  -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
        _lt_result=$?
	# If there is a non-empty error log, and "single_module"
	# appears in it, assume the flag caused a linker warning
        if test -s conftest.err && $GREP single_module conftest.err; then
	  cat conftest.err >&AS_MESSAGE_LOG_FD
	# Otherwise, if the output was created with a 0 exit code from
	# the compiler, it worked.
	elif test -f libconftest.dylib && test 0 = "$_lt_result"; then
	  lt_cv_apple_cc_single_mod=yes
	else
	  cat conftest.err >&AS_MESSAGE_LOG_FD
	fi
	rm -rf libconftest.dylib*
	rm -f conftest.*
      fi])

    AC_CACHE_CHECK([for -exported_symbols_list linker flag],
      [lt_cv_ld_exported_symbols_list],
      [lt_cv_ld_exported_symbols_list=no
      save_LDFLAGS=$LDFLAGS
      echo "_main" > conftest.sym
      LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
      AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
	[lt_cv_ld_exported_symbols_list=yes],
	[lt_cv_ld_exported_symbols_list=no])
	LDFLAGS=$save_LDFLAGS
    ])

    AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load],
      [lt_cv_ld_force_load=no
      cat > conftest.c << _LT_EOF
int forced_loaded() { return 2;}
_LT_EOF
      echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD
      $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD
      echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD
      $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD
      echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD
      $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD
      cat > conftest.c << _LT_EOF
int main() { return 0;}
_LT_EOF
      echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD
      $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err
      _lt_result=$?
      if test -s conftest.err && $GREP force_load conftest.err; then
	cat conftest.err >&AS_MESSAGE_LOG_FD
      elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then
	lt_cv_ld_force_load=yes
      else
	cat conftest.err >&AS_MESSAGE_LOG_FD
      fi
        rm -f conftest.err libconftest.a conftest conftest.c
        rm -rf conftest.dSYM
    ])
    case $host_os in
    rhapsody* | darwin1.[[012]])
      _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;;
    darwin1.*)
      _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
    darwin*) # darwin 5.x on
      # if running on 10.5 or later, the deployment target defaults
      # to the OS version, if on x86, and 10.4, the deployment
      # target defaults to 10.4. Don't you love it?
      case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
	10.0,*86*-darwin8*|10.0,*-darwin[[91]]*)
	  _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
	10.[[012]][[,.]]*)
	  _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
	10.*)
	  _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
      esac
    ;;
  esac
    if test yes = "$lt_cv_apple_cc_single_mod"; then
      _lt_dar_single_mod='$single_module'
    fi
    if test yes = "$lt_cv_ld_exported_symbols_list"; then
      _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym'
    else
      _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib'
    fi
    if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then
      _lt_dsymutil='~$DSYMUTIL $lib || :'
    else
      _lt_dsymutil=
    fi
    ;;
  esac
])


# _LT_DARWIN_LINKER_FEATURES([TAG])
# ---------------------------------
# Checks for linker and compiler features on darwin
m4_defun([_LT_DARWIN_LINKER_FEATURES],
[
  m4_require([_LT_REQUIRED_DARWIN_CHECKS])
  _LT_TAGVAR(archive_cmds_need_lc, $1)=no
  _LT_TAGVAR(hardcode_direct, $1)=no
  _LT_TAGVAR(hardcode_automatic, $1)=yes
  _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
  if test yes = "$lt_cv_ld_force_load"; then
    _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
    m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes],
                  [FC],  [_LT_TAGVAR(compiler_needs_object, $1)=yes])
  else
    _LT_TAGVAR(whole_archive_flag_spec, $1)=''
  fi
  _LT_TAGVAR(link_all_deplibs, $1)=yes
  _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined
  case $cc_basename in
     ifort*|nagfor*) _lt_dar_can_shared=yes ;;
     *) _lt_dar_can_shared=$GCC ;;
  esac
  if test yes = "$_lt_dar_can_shared"; then
    output_verbose_link_cmd=func_echo_all
    _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil"
    _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil"
    _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil"
    _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil"
    m4_if([$1], [CXX],
[   if test yes != "$lt_cv_apple_cc_single_mod"; then
      _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil"
      _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil"
    fi
],[])
  else
  _LT_TAGVAR(ld_shlibs, $1)=no
  fi
])

# _LT_SYS_MODULE_PATH_AIX([TAGNAME])
# ----------------------------------
# Links a minimal program and checks the executable
# for the system default hardcoded library path. In most cases,
# this is /usr/lib:/lib, but when the MPI compilers are used
# the location of the communication and MPI libs are included too.
# If we don't find anything, use the default library path according
# to the aix ld manual.
# Store the results from the different compilers for each TAGNAME.
# Allow to override them for all tags through lt_cv_aix_libpath.
m4_defun([_LT_SYS_MODULE_PATH_AIX],
[m4_require([_LT_DECL_SED])dnl
if test set = "${lt_cv_aix_libpath+set}"; then
  aix_libpath=$lt_cv_aix_libpath
else
  AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])],
  [AC_LINK_IFELSE([AC_LANG_PROGRAM],[
  lt_aix_libpath_sed='[
      /Import File Strings/,/^$/ {
	  /^0/ {
	      s/^0  *\([^ ]*\) *$/\1/
	      p
	  }
      }]'
  _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
  # Check for a 64-bit object if we didn't find anything.
  if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then
    _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
  fi],[])
  if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then
    _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib
  fi
  ])
  aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])
fi
])# _LT_SYS_MODULE_PATH_AIX


# _LT_SHELL_INIT(ARG)
# -------------------
m4_define([_LT_SHELL_INIT],
[m4_divert_text([M4SH-INIT], [$1
])])# _LT_SHELL_INIT



# _LT_PROG_ECHO_BACKSLASH
# -----------------------
# Find how we can fake an echo command that does not interpret backslash.
# In particular, with Autoconf 2.60 or later we add some code to the start
# of the generated configure script that will find a shell with a builtin
# printf (that we can use as an echo command).
m4_defun([_LT_PROG_ECHO_BACKSLASH],
[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO

AC_MSG_CHECKING([how to print strings])
# Test print first, because it will be a builtin if present.
if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \
   test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then
  ECHO='print -r --'
elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then
  ECHO='printf %s\n'
else
  # Use this function as a fallback that always works.
  func_fallback_echo ()
  {
    eval 'cat <<_LTECHO_EOF
$[]1
_LTECHO_EOF'
  }
  ECHO='func_fallback_echo'
fi

# func_echo_all arg...
# Invoke $ECHO with all args, space-separated.
func_echo_all ()
{
    $ECHO "$*"
}

case $ECHO in
  printf*) AC_MSG_RESULT([printf]) ;;
  print*) AC_MSG_RESULT([print -r]) ;;
  *) AC_MSG_RESULT([cat]) ;;
esac

m4_ifdef([_AS_DETECT_SUGGESTED],
[_AS_DETECT_SUGGESTED([
  test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || (
    ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
    ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
    ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
    PATH=/empty FPATH=/empty; export PATH FPATH
    test "X`printf %s $ECHO`" = "X$ECHO" \
      || test "X`print -r -- $ECHO`" = "X$ECHO" )])])

_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts])
_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes])
])# _LT_PROG_ECHO_BACKSLASH


# _LT_WITH_SYSROOT
# ----------------
AC_DEFUN([_LT_WITH_SYSROOT],
[AC_MSG_CHECKING([for sysroot])
AC_ARG_WITH([sysroot],
[AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@],
  [Search for dependent libraries within DIR (or the compiler's sysroot
   if not specified).])],
[], [with_sysroot=no])

dnl lt_sysroot will always be passed unquoted.  We quote it here
dnl in case the user passed a directory name.
lt_sysroot=
case $with_sysroot in #(
 yes)
   if test yes = "$GCC"; then
     lt_sysroot=`$CC --print-sysroot 2>/dev/null`
   fi
   ;; #(
 /*)
   lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"`
   ;; #(
 no|'')
   ;; #(
 *)
   AC_MSG_RESULT([$with_sysroot])
   AC_MSG_ERROR([The sysroot must be an absolute path.])
   ;;
esac

 AC_MSG_RESULT([${lt_sysroot:-no}])
_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl
[dependent libraries, and where our libraries should be installed.])])

# _LT_ENABLE_LOCK
# ---------------
m4_defun([_LT_ENABLE_LOCK],
[AC_ARG_ENABLE([libtool-lock],
  [AS_HELP_STRING([--disable-libtool-lock],
    [avoid locking (might break parallel builds)])])
test no = "$enable_libtool_lock" || enable_libtool_lock=yes

# Some flags need to be propagated to the compiler or linker for good
# libtool support.
case $host in
ia64-*-hpux*)
  # Find out what ABI is being produced by ac_compile, and set mode
  # options accordingly.
  echo 'int i;' > conftest.$ac_ext
  if AC_TRY_EVAL(ac_compile); then
    case `/usr/bin/file conftest.$ac_objext` in
      *ELF-32*)
	HPUX_IA64_MODE=32
	;;
      *ELF-64*)
	HPUX_IA64_MODE=64
	;;
    esac
  fi
  rm -rf conftest*
  ;;
*-*-irix6*)
  # Find out what ABI is being produced by ac_compile, and set linker
  # options accordingly.
  echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext
  if AC_TRY_EVAL(ac_compile); then
    if test yes = "$lt_cv_prog_gnu_ld"; then
      case `/usr/bin/file conftest.$ac_objext` in
	*32-bit*)
	  LD="${LD-ld} -melf32bsmip"
	  ;;
	*N32*)
	  LD="${LD-ld} -melf32bmipn32"
	  ;;
	*64-bit*)
	  LD="${LD-ld} -melf64bmip"
	;;
      esac
    else
      case `/usr/bin/file conftest.$ac_objext` in
	*32-bit*)
	  LD="${LD-ld} -32"
	  ;;
	*N32*)
	  LD="${LD-ld} -n32"
	  ;;
	*64-bit*)
	  LD="${LD-ld} -64"
	  ;;
      esac
    fi
  fi
  rm -rf conftest*
  ;;

mips64*-*linux*)
  # Find out what ABI is being produced by ac_compile, and set linker
  # options accordingly.
  echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext
  if AC_TRY_EVAL(ac_compile); then
    emul=elf
    case `/usr/bin/file conftest.$ac_objext` in
      *32-bit*)
	emul="${emul}32"
	;;
      *64-bit*)
	emul="${emul}64"
	;;
    esac
    case `/usr/bin/file conftest.$ac_objext` in
      *MSB*)
	emul="${emul}btsmip"
	;;
      *LSB*)
	emul="${emul}ltsmip"
	;;
    esac
    case `/usr/bin/file conftest.$ac_objext` in
      *N32*)
	emul="${emul}n32"
	;;
    esac
    LD="${LD-ld} -m $emul"
  fi
  rm -rf conftest*
  ;;

x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
  # Find out what ABI is being produced by ac_compile, and set linker
  # options accordingly.  Note that the listed cases only cover the
  # situations where additional linker options are needed (such as when
  # doing 32-bit compilation for a host where ld defaults to 64-bit, or
  # vice versa); the common cases where no linker options are needed do
  # not appear in the list.
  echo 'int i;' > conftest.$ac_ext
  if AC_TRY_EVAL(ac_compile); then
    case `/usr/bin/file conftest.o` in
      *32-bit*)
	case $host in
	  x86_64-*kfreebsd*-gnu)
	    LD="${LD-ld} -m elf_i386_fbsd"
	    ;;
	  x86_64-*linux*)
	    case `/usr/bin/file conftest.o` in
	      *x86-64*)
		LD="${LD-ld} -m elf32_x86_64"
		;;
	      *)
		LD="${LD-ld} -m elf_i386"
		;;
	    esac
	    ;;
	  powerpc64le-*linux*)
	    LD="${LD-ld} -m elf32lppclinux"
	    ;;
	  powerpc64-*linux*)
	    LD="${LD-ld} -m elf32ppclinux"
	    ;;
	  s390x-*linux*)
	    LD="${LD-ld} -m elf_s390"
	    ;;
	  sparc64-*linux*)
	    LD="${LD-ld} -m elf32_sparc"
	    ;;
	esac
	;;
      *64-bit*)
	case $host in
	  x86_64-*kfreebsd*-gnu)
	    LD="${LD-ld} -m elf_x86_64_fbsd"
	    ;;
	  x86_64-*linux*)
	    LD="${LD-ld} -m elf_x86_64"
	    ;;
	  powerpcle-*linux*)
	    LD="${LD-ld} -m elf64lppc"
	    ;;
	  powerpc-*linux*)
	    LD="${LD-ld} -m elf64ppc"
	    ;;
	  s390*-*linux*|s390*-*tpf*)
	    LD="${LD-ld} -m elf64_s390"
	    ;;
	  sparc*-*linux*)
	    LD="${LD-ld} -m elf64_sparc"
	    ;;
	esac
	;;
    esac
  fi
  rm -rf conftest*
  ;;

*-*-sco3.2v5*)
  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
  SAVE_CFLAGS=$CFLAGS
  CFLAGS="$CFLAGS -belf"
  AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
    [AC_LANG_PUSH(C)
     AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
     AC_LANG_POP])
  if test yes != "$lt_cv_cc_needs_belf"; then
    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
    CFLAGS=$SAVE_CFLAGS
  fi
  ;;
*-*solaris*)
  # Find out what ABI is being produced by ac_compile, and set linker
  # options accordingly.
  echo 'int i;' > conftest.$ac_ext
  if AC_TRY_EVAL(ac_compile); then
    case `/usr/bin/file conftest.o` in
    *64-bit*)
      case $lt_cv_prog_gnu_ld in
      yes*)
        case $host in
        i?86-*-solaris*|x86_64-*-solaris*)
          LD="${LD-ld} -m elf_x86_64"
          ;;
        sparc*-*-solaris*)
          LD="${LD-ld} -m elf64_sparc"
          ;;
        esac
        # GNU ld 2.21 introduced _sol2 emulations.  Use them if available.
        if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then
          LD=${LD-ld}_sol2
        fi
        ;;
      *)
	if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
	  LD="${LD-ld} -64"
	fi
	;;
      esac
      ;;
    esac
  fi
  rm -rf conftest*
  ;;
esac

need_locks=$enable_libtool_lock
])# _LT_ENABLE_LOCK


# _LT_PROG_AR
# -----------
m4_defun([_LT_PROG_AR],
[AC_CHECK_TOOLS(AR, [ar], false)
: ${AR=ar}
: ${AR_FLAGS=cru}
_LT_DECL([], [AR], [1], [The archiver])
_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive])

AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file],
  [lt_cv_ar_at_file=no
   AC_COMPILE_IFELSE([AC_LANG_PROGRAM],
     [echo conftest.$ac_objext > conftest.lst
      lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD'
      AC_TRY_EVAL([lt_ar_try])
      if test 0 -eq "$ac_status"; then
	# Ensure the archiver fails upon bogus file names.
	rm -f conftest.$ac_objext libconftest.a
	AC_TRY_EVAL([lt_ar_try])
	if test 0 -ne "$ac_status"; then
          lt_cv_ar_at_file=@
        fi
      fi
      rm -f conftest.* libconftest.a
     ])
  ])

if test no = "$lt_cv_ar_at_file"; then
  archiver_list_spec=
else
  archiver_list_spec=$lt_cv_ar_at_file
fi
_LT_DECL([], [archiver_list_spec], [1],
  [How to feed a file listing to the archiver])
])# _LT_PROG_AR


# _LT_CMD_OLD_ARCHIVE
# -------------------
m4_defun([_LT_CMD_OLD_ARCHIVE],
[_LT_PROG_AR

AC_CHECK_TOOL(STRIP, strip, :)
test -z "$STRIP" && STRIP=:
_LT_DECL([], [STRIP], [1], [A symbol stripping program])

AC_CHECK_TOOL(RANLIB, ranlib, :)
test -z "$RANLIB" && RANLIB=:
_LT_DECL([], [RANLIB], [1],
    [Commands used to install an old-style archive])

# Determine commands to create old-style static archives.
old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
old_postinstall_cmds='chmod 644 $oldlib'
old_postuninstall_cmds=

if test -n "$RANLIB"; then
  case $host_os in
  bitrig* | openbsd*)
    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib"
    ;;
  *)
    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib"
    ;;
  esac
  old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib"
fi

case $host_os in
  darwin*)
    lock_old_archive_extraction=yes ;;
  *)
    lock_old_archive_extraction=no ;;
esac
_LT_DECL([], [old_postinstall_cmds], [2])
_LT_DECL([], [old_postuninstall_cmds], [2])
_LT_TAGDECL([], [old_archive_cmds], [2],
    [Commands used to build an old-style archive])
_LT_DECL([], [lock_old_archive_extraction], [0],
    [Whether to use a lock for old archive extraction])
])# _LT_CMD_OLD_ARCHIVE


# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
#		[OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE])
# ----------------------------------------------------------------
# Check whether the given compiler option works
AC_DEFUN([_LT_COMPILER_OPTION],
[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
m4_require([_LT_DECL_SED])dnl
AC_CACHE_CHECK([$1], [$2],
  [$2=no
   m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4])
   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
   lt_compiler_flag="$3"  ## exclude from sc_useless_quotes_in_assignment
   # Insert the option either (1) after the last *FLAGS variable, or
   # (2) before a word containing "conftest.", or (3) at the end.
   # Note that $ac_compile itself does not contain backslashes and begins
   # with a dollar sign (not a hyphen), so the echo should work correctly.
   # The option is referenced via a variable to avoid confusing sed.
   lt_compile=`echo "$ac_compile" | $SED \
   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
   -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
   -e 's:$: $lt_compiler_flag:'`
   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
   (eval "$lt_compile" 2>conftest.err)
   ac_status=$?
   cat conftest.err >&AS_MESSAGE_LOG_FD
   echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
   if (exit $ac_status) && test -s "$ac_outfile"; then
     # The compiler can only warn and ignore the option if not recognized
     # So say no if there are warnings other than the usual output.
     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
       $2=yes
     fi
   fi
   $RM conftest*
])

if test yes = "[$]$2"; then
    m4_if([$5], , :, [$5])
else
    m4_if([$6], , :, [$6])
fi
])# _LT_COMPILER_OPTION

# Old name:
AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], [])


# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
#                  [ACTION-SUCCESS], [ACTION-FAILURE])
# ----------------------------------------------------
# Check whether the given linker option works
AC_DEFUN([_LT_LINKER_OPTION],
[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
m4_require([_LT_DECL_SED])dnl
AC_CACHE_CHECK([$1], [$2],
  [$2=no
   save_LDFLAGS=$LDFLAGS
   LDFLAGS="$LDFLAGS $3"
   echo "$lt_simple_link_test_code" > conftest.$ac_ext
   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
     # The linker can only warn and ignore the option if not recognized
     # So say no if there are warnings
     if test -s conftest.err; then
       # Append any errors to the config.log.
       cat conftest.err 1>&AS_MESSAGE_LOG_FD
       $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
       if diff conftest.exp conftest.er2 >/dev/null; then
         $2=yes
       fi
     else
       $2=yes
     fi
   fi
   $RM -r conftest*
   LDFLAGS=$save_LDFLAGS
])

if test yes = "[$]$2"; then
    m4_if([$4], , :, [$4])
else
    m4_if([$5], , :, [$5])
fi
])# _LT_LINKER_OPTION

# Old name:
AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], [])


# LT_CMD_MAX_LEN
#---------------
AC_DEFUN([LT_CMD_MAX_LEN],
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
# find the maximum length of command line arguments
AC_MSG_CHECKING([the maximum length of command line arguments])
AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
  i=0
  teststring=ABCD

  case $build_os in
  msdosdjgpp*)
    # On DJGPP, this test can blow up pretty badly due to problems in libc
    # (any single argument exceeding 2000 bytes causes a buffer overrun
    # during glob expansion).  Even if it were fixed, the result of this
    # check would be larger than it should be.
    lt_cv_sys_max_cmd_len=12288;    # 12K is about right
    ;;

  gnu*)
    # Under GNU Hurd, this test is not required because there is
    # no limit to the length of command line arguments.
    # Libtool will interpret -1 as no limit whatsoever
    lt_cv_sys_max_cmd_len=-1;
    ;;

  cygwin* | mingw* | cegcc*)
    # On Win9x/ME, this test blows up -- it succeeds, but takes
    # about 5 minutes as the teststring grows exponentially.
    # Worse, since 9x/ME are not pre-emptively multitasking,
    # you end up with a "frozen" computer, even though with patience
    # the test eventually succeeds (with a max line length of 256k).
    # Instead, let's just punt: use the minimum linelength reported by
    # all of the supported platforms: 8192 (on NT/2K/XP).
    lt_cv_sys_max_cmd_len=8192;
    ;;

  mint*)
    # On MiNT this can take a long time and run out of memory.
    lt_cv_sys_max_cmd_len=8192;
    ;;

  amigaos*)
    # On AmigaOS with pdksh, this test takes hours, literally.
    # So we just punt and use a minimum line length of 8192.
    lt_cv_sys_max_cmd_len=8192;
    ;;

  bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*)
    # This has been around since 386BSD, at least.  Likely further.
    if test -x /sbin/sysctl; then
      lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
    elif test -x /usr/sbin/sysctl; then
      lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
    else
      lt_cv_sys_max_cmd_len=65536	# usable default for all BSDs
    fi
    # And add a safety zone
    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
    ;;

  interix*)
    # We know the value 262144 and hardcode it with a safety zone (like BSD)
    lt_cv_sys_max_cmd_len=196608
    ;;

  os2*)
    # The test takes a long time on OS/2.
    lt_cv_sys_max_cmd_len=8192
    ;;

  osf*)
    # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
    # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
    # nice to cause kernel panics so lets avoid the loop below.
    # First set a reasonable default.
    lt_cv_sys_max_cmd_len=16384
    #
    if test -x /sbin/sysconfig; then
      case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
        *1*) lt_cv_sys_max_cmd_len=-1 ;;
      esac
    fi
    ;;
  sco3.2v5*)
    lt_cv_sys_max_cmd_len=102400
    ;;
  sysv5* | sco5v6* | sysv4.2uw2*)
    kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
    if test -n "$kargmax"; then
      lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[	 ]]//'`
    else
      lt_cv_sys_max_cmd_len=32768
    fi
    ;;
  *)
    lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
    if test -n "$lt_cv_sys_max_cmd_len" && \
       test undefined != "$lt_cv_sys_max_cmd_len"; then
      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
    else
      # Make teststring a little bigger before we do anything with it.
      # a 1K string should be a reasonable start.
      for i in 1 2 3 4 5 6 7 8; do
        teststring=$teststring$teststring
      done
      SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
      # If test is not a shell built-in, we'll probably end up computing a
      # maximum length that is only half of the actual maximum length, but
      # we can't tell.
      while { test X`env echo "$teststring$teststring" 2>/dev/null` \
	         = "X$teststring$teststring"; } >/dev/null 2>&1 &&
	      test 17 != "$i" # 1/2 MB should be enough
      do
        i=`expr $i + 1`
        teststring=$teststring$teststring
      done
      # Only check the string length outside the loop.
      lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
      teststring=
      # Add a significant safety factor because C++ compilers can tack on
      # massive amounts of additional arguments before passing them to the
      # linker.  It appears as though 1/2 is a usable value.
      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
    fi
    ;;
  esac
])
if test -n "$lt_cv_sys_max_cmd_len"; then
  AC_MSG_RESULT($lt_cv_sys_max_cmd_len)
else
  AC_MSG_RESULT(none)
fi
max_cmd_len=$lt_cv_sys_max_cmd_len
_LT_DECL([], [max_cmd_len], [0],
    [What is the maximum length of a command?])
])# LT_CMD_MAX_LEN

# Old name:
AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], [])


# _LT_HEADER_DLFCN
# ----------------
m4_defun([_LT_HEADER_DLFCN],
[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl
])# _LT_HEADER_DLFCN


# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
#                      ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
# ----------------------------------------------------------------
m4_defun([_LT_TRY_DLOPEN_SELF],
[m4_require([_LT_HEADER_DLFCN])dnl
if test yes = "$cross_compiling"; then :
  [$4]
else
  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
  lt_status=$lt_dlunknown
  cat > conftest.$ac_ext <<_LT_EOF
[#line $LINENO "configure"
#include "confdefs.h"

#if HAVE_DLFCN_H
#include 
#endif

#include 

#ifdef RTLD_GLOBAL
#  define LT_DLGLOBAL		RTLD_GLOBAL
#else
#  ifdef DL_GLOBAL
#    define LT_DLGLOBAL		DL_GLOBAL
#  else
#    define LT_DLGLOBAL		0
#  endif
#endif

/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
   find out it does not work in some platform. */
#ifndef LT_DLLAZY_OR_NOW
#  ifdef RTLD_LAZY
#    define LT_DLLAZY_OR_NOW		RTLD_LAZY
#  else
#    ifdef DL_LAZY
#      define LT_DLLAZY_OR_NOW		DL_LAZY
#    else
#      ifdef RTLD_NOW
#        define LT_DLLAZY_OR_NOW	RTLD_NOW
#      else
#        ifdef DL_NOW
#          define LT_DLLAZY_OR_NOW	DL_NOW
#        else
#          define LT_DLLAZY_OR_NOW	0
#        endif
#      endif
#    endif
#  endif
#endif

/* When -fvisibility=hidden is used, assume the code has been annotated
   correspondingly for the symbols needed.  */
#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
int fnord () __attribute__((visibility("default")));
#endif

int fnord () { return 42; }
int main ()
{
  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
  int status = $lt_dlunknown;

  if (self)
    {
      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
      else
        {
	  if (dlsym( self,"_fnord"))  status = $lt_dlneed_uscore;
          else puts (dlerror ());
	}
      /* dlclose (self); */
    }
  else
    puts (dlerror ());

  return status;
}]
_LT_EOF
  if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then
    (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null
    lt_status=$?
    case x$lt_status in
      x$lt_dlno_uscore) $1 ;;
      x$lt_dlneed_uscore) $2 ;;
      x$lt_dlunknown|x*) $3 ;;
    esac
  else :
    # compilation failed
    $3
  fi
fi
rm -fr conftest*
])# _LT_TRY_DLOPEN_SELF


# LT_SYS_DLOPEN_SELF
# ------------------
AC_DEFUN([LT_SYS_DLOPEN_SELF],
[m4_require([_LT_HEADER_DLFCN])dnl
if test yes != "$enable_dlopen"; then
  enable_dlopen=unknown
  enable_dlopen_self=unknown
  enable_dlopen_self_static=unknown
else
  lt_cv_dlopen=no
  lt_cv_dlopen_libs=

  case $host_os in
  beos*)
    lt_cv_dlopen=load_add_on
    lt_cv_dlopen_libs=
    lt_cv_dlopen_self=yes
    ;;

  mingw* | pw32* | cegcc*)
    lt_cv_dlopen=LoadLibrary
    lt_cv_dlopen_libs=
    ;;

  cygwin*)
    lt_cv_dlopen=dlopen
    lt_cv_dlopen_libs=
    ;;

  darwin*)
    # if libdl is installed we need to link against it
    AC_CHECK_LIB([dl], [dlopen],
		[lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[
    lt_cv_dlopen=dyld
    lt_cv_dlopen_libs=
    lt_cv_dlopen_self=yes
    ])
    ;;

  tpf*)
    # Don't try to run any link tests for TPF.  We know it's impossible
    # because TPF is a cross-compiler, and we know how we open DSOs.
    lt_cv_dlopen=dlopen
    lt_cv_dlopen_libs=
    lt_cv_dlopen_self=no
    ;;

  *)
    AC_CHECK_FUNC([shl_load],
	  [lt_cv_dlopen=shl_load],
      [AC_CHECK_LIB([dld], [shl_load],
	    [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld],
	[AC_CHECK_FUNC([dlopen],
	      [lt_cv_dlopen=dlopen],
	  [AC_CHECK_LIB([dl], [dlopen],
		[lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],
	    [AC_CHECK_LIB([svld], [dlopen],
		  [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld],
	      [AC_CHECK_LIB([dld], [dld_link],
		    [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld])
	      ])
	    ])
	  ])
	])
      ])
    ;;
  esac

  if test no = "$lt_cv_dlopen"; then
    enable_dlopen=no
  else
    enable_dlopen=yes
  fi

  case $lt_cv_dlopen in
  dlopen)
    save_CPPFLAGS=$CPPFLAGS
    test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"

    save_LDFLAGS=$LDFLAGS
    wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"

    save_LIBS=$LIBS
    LIBS="$lt_cv_dlopen_libs $LIBS"

    AC_CACHE_CHECK([whether a program can dlopen itself],
	  lt_cv_dlopen_self, [dnl
	  _LT_TRY_DLOPEN_SELF(
	    lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes,
	    lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross)
    ])

    if test yes = "$lt_cv_dlopen_self"; then
      wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
      AC_CACHE_CHECK([whether a statically linked program can dlopen itself],
	  lt_cv_dlopen_self_static, [dnl
	  _LT_TRY_DLOPEN_SELF(
	    lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes,
	    lt_cv_dlopen_self_static=no,  lt_cv_dlopen_self_static=cross)
      ])
    fi

    CPPFLAGS=$save_CPPFLAGS
    LDFLAGS=$save_LDFLAGS
    LIBS=$save_LIBS
    ;;
  esac

  case $lt_cv_dlopen_self in
  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
  *) enable_dlopen_self=unknown ;;
  esac

  case $lt_cv_dlopen_self_static in
  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
  *) enable_dlopen_self_static=unknown ;;
  esac
fi
_LT_DECL([dlopen_support], [enable_dlopen], [0],
	 [Whether dlopen is supported])
_LT_DECL([dlopen_self], [enable_dlopen_self], [0],
	 [Whether dlopen of programs is supported])
_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0],
	 [Whether dlopen of statically linked programs is supported])
])# LT_SYS_DLOPEN_SELF

# Old name:
AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], [])


# _LT_COMPILER_C_O([TAGNAME])
# ---------------------------
# Check to see if options -c and -o are simultaneously supported by compiler.
# This macro does not hard code the compiler like AC_PROG_CC_C_O.
m4_defun([_LT_COMPILER_C_O],
[m4_require([_LT_DECL_SED])dnl
m4_require([_LT_FILEUTILS_DEFAULTS])dnl
m4_require([_LT_TAG_COMPILER])dnl
AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
  [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)],
  [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no
   $RM -r conftest 2>/dev/null
   mkdir conftest
   cd conftest
   mkdir out
   echo "$lt_simple_compile_test_code" > conftest.$ac_ext

   lt_compiler_flag="-o out/conftest2.$ac_objext"
   # Insert the option either (1) after the last *FLAGS variable, or
   # (2) before a word containing "conftest.", or (3) at the end.
   # Note that $ac_compile itself does not contain backslashes and begins
   # with a dollar sign (not a hyphen), so the echo should work correctly.
   lt_compile=`echo "$ac_compile" | $SED \
   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
   -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
   -e 's:$: $lt_compiler_flag:'`
   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
   (eval "$lt_compile" 2>out/conftest.err)
   ac_status=$?
   cat out/conftest.err >&AS_MESSAGE_LOG_FD
   echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
   if (exit $ac_status) && test -s out/conftest2.$ac_objext
   then
     # The compiler can only warn and ignore the option if not recognized
     # So say no if there are warnings
     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
       _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
     fi
   fi
   chmod u+w . 2>&AS_MESSAGE_LOG_FD
   $RM conftest*
   # SGI C++ compiler will create directory out/ii_files/ for
   # template instantiation
   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
   $RM out/* && rmdir out
   cd ..
   $RM -r conftest
   $RM conftest*
])
_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1],
	[Does compiler simultaneously support -c and -o options?])
])# _LT_COMPILER_C_O


# _LT_COMPILER_FILE_LOCKS([TAGNAME])
# ----------------------------------
# Check to see if we can do hard links to lock some files if needed
m4_defun([_LT_COMPILER_FILE_LOCKS],
[m4_require([_LT_ENABLE_LOCK])dnl
m4_require([_LT_FILEUTILS_DEFAULTS])dnl
_LT_COMPILER_C_O([$1])

hard_links=nottested
if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then
  # do not overwrite the value of need_locks provided by the user
  AC_MSG_CHECKING([if we can lock with hard links])
  hard_links=yes
  $RM conftest*
  ln conftest.a conftest.b 2>/dev/null && hard_links=no
  touch conftest.a
  ln conftest.a conftest.b 2>&5 || hard_links=no
  ln conftest.a conftest.b 2>/dev/null && hard_links=no
  AC_MSG_RESULT([$hard_links])
  if test no = "$hard_links"; then
    AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe])
    need_locks=warn
  fi
else
  need_locks=no
fi
_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?])
])# _LT_COMPILER_FILE_LOCKS


# _LT_CHECK_OBJDIR
# ----------------
m4_defun([_LT_CHECK_OBJDIR],
[AC_CACHE_CHECK([for objdir], [lt_cv_objdir],
[rm -f .libs 2>/dev/null
mkdir .libs 2>/dev/null
if test -d .libs; then
  lt_cv_objdir=.libs
else
  # MS-DOS does not allow filenames that begin with a dot.
  lt_cv_objdir=_libs
fi
rmdir .libs 2>/dev/null])
objdir=$lt_cv_objdir
_LT_DECL([], [objdir], [0],
         [The name of the directory that contains temporary libtool files])dnl
m4_pattern_allow([LT_OBJDIR])dnl
AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/",
  [Define to the sub-directory where libtool stores uninstalled libraries.])
])# _LT_CHECK_OBJDIR


# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME])
# --------------------------------------
# Check hardcoding attributes.
m4_defun([_LT_LINKER_HARDCODE_LIBPATH],
[AC_MSG_CHECKING([how to hardcode library paths into programs])
_LT_TAGVAR(hardcode_action, $1)=
if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" ||
   test -n "$_LT_TAGVAR(runpath_var, $1)" ||
   test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then

  # We can hardcode non-existent directories.
  if test no != "$_LT_TAGVAR(hardcode_direct, $1)" &&
     # If the only mechanism to avoid hardcoding is shlibpath_var, we
     # have to relink, otherwise we might link with an installed library
     # when we should be linking with a yet-to-be-installed one
     ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" &&
     test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then
    # Linking always hardcodes the temporary library directory.
    _LT_TAGVAR(hardcode_action, $1)=relink
  else
    # We can link without hardcoding, and we can hardcode nonexisting dirs.
    _LT_TAGVAR(hardcode_action, $1)=immediate
  fi
else
  # We cannot hardcode anything, or else we can only hardcode existing
  # directories.
  _LT_TAGVAR(hardcode_action, $1)=unsupported
fi
AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)])

if test relink = "$_LT_TAGVAR(hardcode_action, $1)" ||
   test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then
  # Fast installation is not supported
  enable_fast_install=no
elif test yes = "$shlibpath_overrides_runpath" ||
     test no = "$enable_shared"; then
  # Fast installation is not necessary
  enable_fast_install=needless
fi
_LT_TAGDECL([], [hardcode_action], [0],
    [How to hardcode a shared library path into an executable])
])# _LT_LINKER_HARDCODE_LIBPATH


# _LT_CMD_STRIPLIB
# ----------------
m4_defun([_LT_CMD_STRIPLIB],
[m4_require([_LT_DECL_EGREP])
striplib=
old_striplib=
AC_MSG_CHECKING([whether stripping libraries is possible])
if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
  test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
  test -z "$striplib" && striplib="$STRIP --strip-unneeded"
  AC_MSG_RESULT([yes])
else
# FIXME - insert some real tests, host_os isn't really good enough
  case $host_os in
  darwin*)
    if test -n "$STRIP"; then
      striplib="$STRIP -x"
      old_striplib="$STRIP -S"
      AC_MSG_RESULT([yes])
    else
      AC_MSG_RESULT([no])
    fi
    ;;
  *)
    AC_MSG_RESULT([no])
    ;;
  esac
fi
_LT_DECL([], [old_striplib], [1], [Commands to strip libraries])
_LT_DECL([], [striplib], [1])
])# _LT_CMD_STRIPLIB


# _LT_PREPARE_MUNGE_PATH_LIST
# ---------------------------
# Make sure func_munge_path_list() is defined correctly.
m4_defun([_LT_PREPARE_MUNGE_PATH_LIST],
[[# func_munge_path_list VARIABLE PATH
# -----------------------------------
# VARIABLE is name of variable containing _space_ separated list of
# directories to be munged by the contents of PATH, which is string
# having a format:
# "DIR[:DIR]:"
#       string "DIR[ DIR]" will be prepended to VARIABLE
# ":DIR[:DIR]"
#       string "DIR[ DIR]" will be appended to VARIABLE
# "DIRP[:DIRP]::[DIRA:]DIRA"
#       string "DIRP[ DIRP]" will be prepended to VARIABLE and string
#       "DIRA[ DIRA]" will be appended to VARIABLE
# "DIR[:DIR]"
#       VARIABLE will be replaced by "DIR[ DIR]"
func_munge_path_list ()
{
    case x@S|@2 in
    x)
        ;;
    *:)
        eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\"
        ;;
    x:*)
        eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\"
        ;;
    *::*)
        eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\"
        eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\"
        ;;
    *)
        eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\"
        ;;
    esac
}
]])# _LT_PREPARE_PATH_LIST


# _LT_SYS_DYNAMIC_LINKER([TAG])
# -----------------------------
# PORTME Fill in your ld.so characteristics
m4_defun([_LT_SYS_DYNAMIC_LINKER],
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
m4_require([_LT_DECL_EGREP])dnl
m4_require([_LT_FILEUTILS_DEFAULTS])dnl
m4_require([_LT_DECL_OBJDUMP])dnl
m4_require([_LT_DECL_SED])dnl
m4_require([_LT_CHECK_SHELL_FEATURES])dnl
m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl
AC_MSG_CHECKING([dynamic linker characteristics])
m4_if([$1],
	[], [
if test yes = "$GCC"; then
  case $host_os in
    darwin*) lt_awk_arg='/^libraries:/,/LR/' ;;
    *) lt_awk_arg='/^libraries:/' ;;
  esac
  case $host_os in
    mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;;
    *) lt_sed_strip_eq='s|=/|/|g' ;;
  esac
  lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq`
  case $lt_search_path_spec in
  *\;*)
    # if the path contains ";" then we assume it to be the separator
    # otherwise default to the standard path separator (i.e. ":") - it is
    # assumed that no part of a normal pathname contains ";" but that should
    # okay in the real world where ";" in dirpaths is itself problematic.
    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'`
    ;;
  *)
    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"`
    ;;
  esac
  # Ok, now we have the path, separated by spaces, we can step through it
  # and add multilib dir if necessary...
  lt_tmp_lt_search_path_spec=
  lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
  # ...but if some path component already ends with the multilib dir we assume
  # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer).
  case "$lt_multi_os_dir; $lt_search_path_spec " in
  "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*)
    lt_multi_os_dir=
    ;;
  esac
  for lt_sys_path in $lt_search_path_spec; do
    if test -d "$lt_sys_path$lt_multi_os_dir"; then
      lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir"
    elif test -n "$lt_multi_os_dir"; then
      test -d "$lt_sys_path" && \
	lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
    fi
  done
  lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk '
BEGIN {RS = " "; FS = "/|\n";} {
  lt_foo = "";
  lt_count = 0;
  for (lt_i = NF; lt_i > 0; lt_i--) {
    if ($lt_i != "" && $lt_i != ".") {
      if ($lt_i == "..") {
        lt_count++;
      } else {
        if (lt_count == 0) {
          lt_foo = "/" $lt_i lt_foo;
        } else {
          lt_count--;
        }
      }
    }
  }
  if (lt_foo != "") { lt_freq[[lt_foo]]++; }
  if (lt_freq[[lt_foo]] == 1) { print lt_foo; }
}'`
  # AWK program above erroneously prepends '/' to C:/dos/paths
  # for these hosts.
  case $host_os in
    mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\
      $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;;
  esac
  sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP`
else
  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
fi])
library_names_spec=
libname_spec='lib$name'
soname_spec=
shrext_cmds=.so
postinstall_cmds=
postuninstall_cmds=
finish_cmds=
finish_eval=
shlibpath_var=
shlibpath_overrides_runpath=unknown
version_type=none
dynamic_linker="$host_os ld.so"
sys_lib_dlsearch_path_spec="/lib /usr/lib"
need_lib_prefix=unknown
hardcode_into_libs=no

# when you set need_version to no, make sure it does not cause -set_version
# flags to be left without arguments
need_version=unknown

AC_ARG_VAR([LT_SYS_LIBRARY_PATH],
[User-defined run-time library search path.])

case $host_os in
aix3*)
  version_type=linux # correct to gnu/linux during the next big refactor
  library_names_spec='$libname$release$shared_ext$versuffix $libname.a'
  shlibpath_var=LIBPATH

  # AIX 3 has no versioning support, so we append a major version to the name.
  soname_spec='$libname$release$shared_ext$major'
  ;;

aix[[4-9]]*)
  version_type=linux # correct to gnu/linux during the next big refactor
  need_lib_prefix=no
  need_version=no
  hardcode_into_libs=yes
  if test ia64 = "$host_cpu"; then
    # AIX 5 supports IA64
    library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext'
    shlibpath_var=LD_LIBRARY_PATH
  else
    # With GCC up to 2.95.x, collect2 would create an import file
    # for dependence libraries.  The import file would start with
    # the line '#! .'.  This would cause the generated library to
    # depend on '.', always an invalid library.  This was fixed in
    # development snapshots of GCC prior to 3.0.
    case $host_os in
      aix4 | aix4.[[01]] | aix4.[[01]].*)
      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
	   echo ' yes '
	   echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then
	:
      else
	can_build_shared=no
      fi
      ;;
    esac
    # Using Import Files as archive members, it is possible to support
    # filename-based versioning of shared library archives on AIX. While
    # this would work for both with and without runtime linking, it will
    # prevent static linking of such archives. So we do filename-based
    # shared library versioning with .so extension only, which is used
    # when both runtime linking and shared linking is enabled.
    # Unfortunately, runtime linking may impact performance, so we do
    # not want this to be the default eventually. Also, we use the
    # versioned .so libs for executables only if there is the -brtl
    # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only.
    # To allow for filename-based versioning support, we need to create
    # libNAME.so.V as an archive file, containing:
    # *) an Import File, referring to the versioned filename of the
    #    archive as well as the shared archive member, telling the
    #    bitwidth (32 or 64) of that shared object, and providing the
    #    list of exported symbols of that shared object, eventually
    #    decorated with the 'weak' keyword
    # *) the shared object with the F_LOADONLY flag set, to really avoid
    #    it being seen by the linker.
    # At run time we better use the real file rather than another symlink,
    # but for link time we create the symlink libNAME.so -> libNAME.so.V

    case $with_aix_soname,$aix_use_runtimelinking in
    # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct
    # soname into executable. Probably we can add versioning support to
    # collect2, so additional links can be useful in future.
    aix,yes) # traditional libtool
      dynamic_linker='AIX unversionable lib.so'
      # If using run time linking (on AIX 4.2 or later) use lib.so
      # instead of lib.a to let people know that these are not
      # typical AIX shared libraries.
      library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
      ;;
    aix,no) # traditional AIX only
      dynamic_linker='AIX lib.a[(]lib.so.V[)]'
      # We preserve .a as extension for shared libraries through AIX4.2
      # and later when we are not doing run time linking.
      library_names_spec='$libname$release.a $libname.a'
      soname_spec='$libname$release$shared_ext$major'
      ;;
    svr4,*) # full svr4 only
      dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]"
      library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
      # We do not specify a path in Import Files, so LIBPATH fires.
      shlibpath_overrides_runpath=yes
      ;;
    *,yes) # both, prefer svr4
      dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]"
      library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
      # unpreferred sharedlib libNAME.a needs extra handling
      postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"'
      postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"'
      # We do not specify a path in Import Files, so LIBPATH fires.
      shlibpath_overrides_runpath=yes
      ;;
    *,no) # both, prefer aix
      dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]"
      library_names_spec='$libname$release.a $libname.a'
      soname_spec='$libname$release$shared_ext$major'
      # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling
      postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)'
      postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"'
      ;;
    esac
    shlibpath_var=LIBPATH
  fi
  ;;

amigaos*)
  case $host_cpu in
  powerpc)
    # Since July 2007 AmigaOS4 officially supports .so libraries.
    # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    ;;
  m68k)
    library_names_spec='$libname.ixlibrary $libname.a'
    # Create ${libname}_ixlibrary.a entries in /sys/libs.
    finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
    ;;
  esac
  ;;

beos*)
  library_names_spec='$libname$shared_ext'
  dynamic_linker="$host_os ld.so"
  shlibpath_var=LIBRARY_PATH
  ;;

bsdi[[45]]*)
  version_type=linux # correct to gnu/linux during the next big refactor
  need_version=no
  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
  soname_spec='$libname$release$shared_ext$major'
  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
  shlibpath_var=LD_LIBRARY_PATH
  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
  # the default ld.so.conf also contains /usr/contrib/lib and
  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
  # libtool to hard-code these into programs
  ;;

cygwin* | mingw* | pw32* | cegcc*)
  version_type=windows
  shrext_cmds=.dll
  need_version=no
  need_lib_prefix=no

  case $GCC,$cc_basename in
  yes,*)
    # gcc
    library_names_spec='$libname.dll.a'
    # DLL is installed to $(libdir)/../bin by postinstall_cmds
    postinstall_cmds='base_file=`basename \$file`~
      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
      dldir=$destdir/`dirname \$dlpath`~
      test -d \$dldir || mkdir -p \$dldir~
      $install_prog $dir/$dlname \$dldir/$dlname~
      chmod a+x \$dldir/$dlname~
      if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
        eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
      fi'
    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
      dlpath=$dir/\$dldll~
       $RM \$dlpath'
    shlibpath_overrides_runpath=yes

    case $host_os in
    cygwin*)
      # Cygwin DLLs use 'cyg' prefix rather than 'lib'
      soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
m4_if([$1], [],[
      sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"])
      ;;
    mingw* | cegcc*)
      # MinGW DLLs use traditional 'lib' prefix
      soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
      ;;
    pw32*)
      # pw32 DLLs use 'pw' prefix rather than 'lib'
      library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
      ;;
    esac
    dynamic_linker='Win32 ld.exe'
    ;;

  *,cl*)
    # Native MSVC
    libname_spec='$name'
    soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
    library_names_spec='$libname.dll.lib'

    case $build_os in
    mingw*)
      sys_lib_search_path_spec=
      lt_save_ifs=$IFS
      IFS=';'
      for lt_path in $LIB
      do
        IFS=$lt_save_ifs
        # Let DOS variable expansion print the short 8.3 style file name.
        lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"`
        sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path"
      done
      IFS=$lt_save_ifs
      # Convert to MSYS style.
      sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'`
      ;;
    cygwin*)
      # Convert to unix form, then to dos form, then back to unix form
      # but this time dos style (no spaces!) so that the unix form looks
      # like /cygdrive/c/PROGRA~1:/cygdr...
      sys_lib_search_path_spec=`cygpath --path --unix "$LIB"`
      sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null`
      sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
      ;;
    *)
      sys_lib_search_path_spec=$LIB
      if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then
        # It is most probably a Windows format PATH.
        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
      else
        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
      fi
      # FIXME: find the short name or the path components, as spaces are
      # common. (e.g. "Program Files" -> "PROGRA~1")
      ;;
    esac

    # DLL is installed to $(libdir)/../bin by postinstall_cmds
    postinstall_cmds='base_file=`basename \$file`~
      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
      dldir=$destdir/`dirname \$dlpath`~
      test -d \$dldir || mkdir -p \$dldir~
      $install_prog $dir/$dlname \$dldir/$dlname'
    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
      dlpath=$dir/\$dldll~
       $RM \$dlpath'
    shlibpath_overrides_runpath=yes
    dynamic_linker='Win32 link.exe'
    ;;

  *)
    # Assume MSVC wrapper
    library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib'
    dynamic_linker='Win32 ld.exe'
    ;;
  esac
  # FIXME: first we should search . and the directory the executable is in
  shlibpath_var=PATH
  ;;

darwin* | rhapsody*)
  dynamic_linker="$host_os dyld"
  version_type=darwin
  need_lib_prefix=no
  need_version=no
  library_names_spec='$libname$release$major$shared_ext $libname$shared_ext'
  soname_spec='$libname$release$major$shared_ext'
  shlibpath_overrides_runpath=yes
  shlibpath_var=DYLD_LIBRARY_PATH
  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
m4_if([$1], [],[
  sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"])
  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
  ;;

dgux*)
  version_type=linux # correct to gnu/linux during the next big refactor
  need_lib_prefix=no
  need_version=no
  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
  soname_spec='$libname$release$shared_ext$major'
  shlibpath_var=LD_LIBRARY_PATH
  ;;

freebsd* | dragonfly*)
  # DragonFly does not have aout.  When/if they implement a new
  # versioning mechanism, adjust this.
  if test -x /usr/bin/objformat; then
    objformat=`/usr/bin/objformat`
  else
    case $host_os in
    freebsd[[23]].*) objformat=aout ;;
    *) objformat=elf ;;
    esac
  fi
  version_type=freebsd-$objformat
  case $version_type in
    freebsd-elf*)
      library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
      soname_spec='$libname$release$shared_ext$major'
      need_version=no
      need_lib_prefix=no
      ;;
    freebsd-*)
      library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
      need_version=yes
      ;;
  esac
  shlibpath_var=LD_LIBRARY_PATH
  case $host_os in
  freebsd2.*)
    shlibpath_overrides_runpath=yes
    ;;
  freebsd3.[[01]]* | freebsdelf3.[[01]]*)
    shlibpath_overrides_runpath=yes
    hardcode_into_libs=yes
    ;;
  freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \
  freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1)
    shlibpath_overrides_runpath=no
    hardcode_into_libs=yes
    ;;
  *) # from 4.6 on, and DragonFly
    shlibpath_overrides_runpath=yes
    hardcode_into_libs=yes
    ;;
  esac
  ;;

haiku*)
  version_type=linux # correct to gnu/linux during the next big refactor
  need_lib_prefix=no
  need_version=no
  dynamic_linker="$host_os runtime_loader"
  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
  soname_spec='$libname$release$shared_ext$major'
  shlibpath_var=LIBRARY_PATH
  shlibpath_overrides_runpath=no
  sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib'
  hardcode_into_libs=yes
  ;;

hpux9* | hpux10* | hpux11*)
  # Give a soname corresponding to the major version so that dld.sl refuses to
  # link against other versions.
  version_type=sunos
  need_lib_prefix=no
  need_version=no
  case $host_cpu in
  ia64*)
    shrext_cmds='.so'
    hardcode_into_libs=yes
    dynamic_linker="$host_os dld.so"
    shlibpath_var=LD_LIBRARY_PATH
    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    soname_spec='$libname$release$shared_ext$major'
    if test 32 = "$HPUX_IA64_MODE"; then
      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
      sys_lib_dlsearch_path_spec=/usr/lib/hpux32
    else
      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
      sys_lib_dlsearch_path_spec=/usr/lib/hpux64
    fi
    ;;
  hppa*64*)
    shrext_cmds='.sl'
    hardcode_into_libs=yes
    dynamic_linker="$host_os dld.sl"
    shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    soname_spec='$libname$release$shared_ext$major'
    sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
    ;;
  *)
    shrext_cmds='.sl'
    dynamic_linker="$host_os dld.sl"
    shlibpath_var=SHLIB_PATH
    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    soname_spec='$libname$release$shared_ext$major'
    ;;
  esac
  # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
  postinstall_cmds='chmod 555 $lib'
  # or fails outright, so override atomically:
  install_override_mode=555
  ;;

interix[[3-9]]*)
  version_type=linux # correct to gnu/linux during the next big refactor
  need_lib_prefix=no
  need_version=no
  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
  soname_spec='$libname$release$shared_ext$major'
  dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
  shlibpath_var=LD_LIBRARY_PATH
  shlibpath_overrides_runpath=no
  hardcode_into_libs=yes
  ;;

irix5* | irix6* | nonstopux*)
  case $host_os in
    nonstopux*) version_type=nonstopux ;;
    *)
	if test yes = "$lt_cv_prog_gnu_ld"; then
		version_type=linux # correct to gnu/linux during the next big refactor
	else
		version_type=irix
	fi ;;
  esac
  need_lib_prefix=no
  need_version=no
  soname_spec='$libname$release$shared_ext$major'
  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext'
  case $host_os in
  irix5* | nonstopux*)
    libsuff= shlibsuff=
    ;;
  *)
    case $LD in # libtool.m4 will add one of these switches to LD
    *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
      libsuff= shlibsuff= libmagic=32-bit;;
    *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
      libsuff=32 shlibsuff=N32 libmagic=N32;;
    *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
      libsuff=64 shlibsuff=64 libmagic=64-bit;;
    *) libsuff= shlibsuff= libmagic=never-match;;
    esac
    ;;
  esac
  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
  shlibpath_overrides_runpath=no
  sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff"
  sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff"
  hardcode_into_libs=yes
  ;;

# No shared lib support for Linux oldld, aout, or coff.
linux*oldld* | linux*aout* | linux*coff*)
  dynamic_linker=no
  ;;

linux*android*)
  version_type=none # Android doesn't support versioned libraries.
  need_lib_prefix=no
  need_version=no
  library_names_spec='$libname$release$shared_ext'
  soname_spec='$libname$release$shared_ext'
  finish_cmds=
  shlibpath_var=LD_LIBRARY_PATH
  shlibpath_overrides_runpath=yes

  # This implies no fast_install, which is unacceptable.
  # Some rework will be needed to allow for fast_install
  # before this can be enabled.
  hardcode_into_libs=yes

  dynamic_linker='Android linker'
  # Don't embed -rpath directories since the linker doesn't support them.
  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
  ;;

# This must be glibc/ELF.
linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
  version_type=linux # correct to gnu/linux during the next big refactor
  need_lib_prefix=no
  need_version=no
  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
  soname_spec='$libname$release$shared_ext$major'
  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
  shlibpath_var=LD_LIBRARY_PATH
  shlibpath_overrides_runpath=no

  # Some binutils ld are patched to set DT_RUNPATH
  AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath],
    [lt_cv_shlibpath_overrides_runpath=no
    save_LDFLAGS=$LDFLAGS
    save_libdir=$libdir
    eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \
	 LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\""
    AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
      [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null],
	 [lt_cv_shlibpath_overrides_runpath=yes])])
    LDFLAGS=$save_LDFLAGS
    libdir=$save_libdir
    ])
  shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath

  # This implies no fast_install, which is unacceptable.
  # Some rework will be needed to allow for fast_install
  # before this can be enabled.
  hardcode_into_libs=yes

  # Ideally, we could use ldconfig to report *all* directores which are
  # searched for libraries, however this is still not possible.  Aside from not
  # being certain /sbin/ldconfig is available, command
  # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64,
  # even though it is searched at run-time.  Try to do the best guess by
  # appending ld.so.conf contents (and includes) to the search path.
  if test -f /etc/ld.so.conf; then
    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[	 ]*hwcap[	 ]/d;s/[:,	]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
  fi

  # We used to test for /lib/ld.so.1 and disable shared libraries on
  # powerpc, because MkLinux only supported shared libraries with the
  # GNU dynamic linker.  Since this was broken with cross compilers,
  # most powerpc-linux boxes support dynamic linking these days and
  # people can always --disable-shared, the test was removed, and we
  # assume the GNU/Linux dynamic linker is in use.
  dynamic_linker='GNU/Linux ld.so'
  ;;

netbsdelf*-gnu)
  version_type=linux
  need_lib_prefix=no
  need_version=no
  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
  soname_spec='${libname}${release}${shared_ext}$major'
  shlibpath_var=LD_LIBRARY_PATH
  shlibpath_overrides_runpath=no
  hardcode_into_libs=yes
  dynamic_linker='NetBSD ld.elf_so'
  ;;

netbsd*)
  version_type=sunos
  need_lib_prefix=no
  need_version=no
  if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
    library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
    dynamic_linker='NetBSD (a.out) ld.so'
  else
    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    soname_spec='$libname$release$shared_ext$major'
    dynamic_linker='NetBSD ld.elf_so'
  fi
  shlibpath_var=LD_LIBRARY_PATH
  shlibpath_overrides_runpath=yes
  hardcode_into_libs=yes
  ;;

newsos6)
  version_type=linux # correct to gnu/linux during the next big refactor
  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
  shlibpath_var=LD_LIBRARY_PATH
  shlibpath_overrides_runpath=yes
  ;;

*nto* | *qnx*)
  version_type=qnx
  need_lib_prefix=no
  need_version=no
  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
  soname_spec='$libname$release$shared_ext$major'
  shlibpath_var=LD_LIBRARY_PATH
  shlibpath_overrides_runpath=no
  hardcode_into_libs=yes
  dynamic_linker='ldqnx.so'
  ;;

openbsd* | bitrig*)
  version_type=sunos
  sys_lib_dlsearch_path_spec=/usr/lib
  need_lib_prefix=no
  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
    need_version=no
  else
    need_version=yes
  fi
  library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
  shlibpath_var=LD_LIBRARY_PATH
  shlibpath_overrides_runpath=yes
  ;;

os2*)
  libname_spec='$name'
  version_type=windows
  shrext_cmds=.dll
  need_version=no
  need_lib_prefix=no
  # OS/2 can only load a DLL with a base name of 8 characters or less.
  soname_spec='`test -n "$os2dllname" && libname="$os2dllname";
    v=$($ECHO $release$versuffix | tr -d .-);
    n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _);
    $ECHO $n$v`$shared_ext'
  library_names_spec='${libname}_dll.$libext'
  dynamic_linker='OS/2 ld.exe'
  shlibpath_var=BEGINLIBPATH
  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
  sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
  postinstall_cmds='base_file=`basename \$file`~
    dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~
    dldir=$destdir/`dirname \$dlpath`~
    test -d \$dldir || mkdir -p \$dldir~
    $install_prog $dir/$dlname \$dldir/$dlname~
    chmod a+x \$dldir/$dlname~
    if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
      eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
    fi'
  postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~
    dlpath=$dir/\$dldll~
    $RM \$dlpath'
  ;;

osf3* | osf4* | osf5*)
  version_type=osf
  need_lib_prefix=no
  need_version=no
  soname_spec='$libname$release$shared_ext$major'
  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
  shlibpath_var=LD_LIBRARY_PATH
  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
  sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
  ;;

rdos*)
  dynamic_linker=no
  ;;

solaris*)
  version_type=linux # correct to gnu/linux during the next big refactor
  need_lib_prefix=no
  need_version=no
  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
  soname_spec='$libname$release$shared_ext$major'
  shlibpath_var=LD_LIBRARY_PATH
  shlibpath_overrides_runpath=yes
  hardcode_into_libs=yes
  # ldd complains unless libraries are executable
  postinstall_cmds='chmod +x $lib'
  ;;

sunos4*)
  version_type=sunos
  library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
  shlibpath_var=LD_LIBRARY_PATH
  shlibpath_overrides_runpath=yes
  if test yes = "$with_gnu_ld"; then
    need_lib_prefix=no
  fi
  need_version=yes
  ;;

sysv4 | sysv4.3*)
  version_type=linux # correct to gnu/linux during the next big refactor
  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
  soname_spec='$libname$release$shared_ext$major'
  shlibpath_var=LD_LIBRARY_PATH
  case $host_vendor in
    sni)
      shlibpath_overrides_runpath=no
      need_lib_prefix=no
      runpath_var=LD_RUN_PATH
      ;;
    siemens)
      need_lib_prefix=no
      ;;
    motorola)
      need_lib_prefix=no
      need_version=no
      shlibpath_overrides_runpath=no
      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
      ;;
  esac
  ;;

sysv4*MP*)
  if test -d /usr/nec; then
    version_type=linux # correct to gnu/linux during the next big refactor
    library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext'
    soname_spec='$libname$shared_ext.$major'
    shlibpath_var=LD_LIBRARY_PATH
  fi
  ;;

sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
  version_type=sco
  need_lib_prefix=no
  need_version=no
  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext'
  soname_spec='$libname$release$shared_ext$major'
  shlibpath_var=LD_LIBRARY_PATH
  shlibpath_overrides_runpath=yes
  hardcode_into_libs=yes
  if test yes = "$with_gnu_ld"; then
    sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
  else
    sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
    case $host_os in
      sco3.2v5*)
        sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
	;;
    esac
  fi
  sys_lib_dlsearch_path_spec='/usr/lib'
  ;;

tpf*)
  # TPF is a cross-target only.  Preferred cross-host = GNU/Linux.
  version_type=linux # correct to gnu/linux during the next big refactor
  need_lib_prefix=no
  need_version=no
  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
  shlibpath_var=LD_LIBRARY_PATH
  shlibpath_overrides_runpath=no
  hardcode_into_libs=yes
  ;;

uts4*)
  version_type=linux # correct to gnu/linux during the next big refactor
  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
  soname_spec='$libname$release$shared_ext$major'
  shlibpath_var=LD_LIBRARY_PATH
  ;;

*)
  dynamic_linker=no
  ;;
esac
AC_MSG_RESULT([$dynamic_linker])
test no = "$dynamic_linker" && can_build_shared=no

variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
if test yes = "$GCC"; then
  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
fi

if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then
  sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec
fi

if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then
  sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec
fi

# remember unaugmented sys_lib_dlsearch_path content for libtool script decls...
configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec

# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code
func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH"

# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool
configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH

_LT_DECL([], [variables_saved_for_relink], [1],
    [Variables whose values should be saved in libtool wrapper scripts and
    restored at link time])
_LT_DECL([], [need_lib_prefix], [0],
    [Do we need the "lib" prefix for modules?])
_LT_DECL([], [need_version], [0], [Do we need a version for libraries?])
_LT_DECL([], [version_type], [0], [Library versioning type])
_LT_DECL([], [runpath_var], [0],  [Shared library runtime path variable])
_LT_DECL([], [shlibpath_var], [0],[Shared library path variable])
_LT_DECL([], [shlibpath_overrides_runpath], [0],
    [Is shlibpath searched before the hard-coded library search path?])
_LT_DECL([], [libname_spec], [1], [Format of library name prefix])
_LT_DECL([], [library_names_spec], [1],
    [[List of archive names.  First name is the real one, the rest are links.
    The last name is the one that the linker finds with -lNAME]])
_LT_DECL([], [soname_spec], [1],
    [[The coded name of the library, if different from the real name]])
_LT_DECL([], [install_override_mode], [1],
    [Permission mode override for installation of shared libraries])
_LT_DECL([], [postinstall_cmds], [2],
    [Command to use after installation of a shared archive])
_LT_DECL([], [postuninstall_cmds], [2],
    [Command to use after uninstallation of a shared archive])
_LT_DECL([], [finish_cmds], [2],
    [Commands used to finish a libtool library installation in a directory])
_LT_DECL([], [finish_eval], [1],
    [[As "finish_cmds", except a single script fragment to be evaled but
    not shown]])
_LT_DECL([], [hardcode_into_libs], [0],
    [Whether we should hardcode library paths into libraries])
_LT_DECL([], [sys_lib_search_path_spec], [2],
    [Compile-time system search path for libraries])
_LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2],
    [Detected run-time system search path for libraries])
_LT_DECL([], [configure_time_lt_sys_library_path], [2],
    [Explicit LT_SYS_LIBRARY_PATH set during ./configure time])
])# _LT_SYS_DYNAMIC_LINKER


# _LT_PATH_TOOL_PREFIX(TOOL)
# --------------------------
# find a file program that can recognize shared library
AC_DEFUN([_LT_PATH_TOOL_PREFIX],
[m4_require([_LT_DECL_EGREP])dnl
AC_MSG_CHECKING([for $1])
AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
[case $MAGIC_CMD in
[[\\/*] |  ?:[\\/]*])
  lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path.
  ;;
*)
  lt_save_MAGIC_CMD=$MAGIC_CMD
  lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
dnl $ac_dummy forces splitting on constant user-supplied paths.
dnl POSIX.2 word splitting is done only on the output of word expansions,
dnl not every word.  This closes a longstanding sh security hole.
  ac_dummy="m4_if([$2], , $PATH, [$2])"
  for ac_dir in $ac_dummy; do
    IFS=$lt_save_ifs
    test -z "$ac_dir" && ac_dir=.
    if test -f "$ac_dir/$1"; then
      lt_cv_path_MAGIC_CMD=$ac_dir/"$1"
      if test -n "$file_magic_test_file"; then
	case $deplibs_check_method in
	"file_magic "*)
	  file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
	  MAGIC_CMD=$lt_cv_path_MAGIC_CMD
	  if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
	    $EGREP "$file_magic_regex" > /dev/null; then
	    :
	  else
	    cat <<_LT_EOF 1>&2

*** Warning: the command libtool uses to detect shared libraries,
*** $file_magic_cmd, produces output that libtool cannot recognize.
*** The result is that libtool may fail to recognize shared libraries
*** as such.  This will affect the creation of libtool libraries that
*** depend on shared libraries, but programs linked with such libtool
*** libraries will work regardless of this problem.  Nevertheless, you
*** may want to report the problem to your system manager and/or to
*** bug-libtool@gnu.org

_LT_EOF
	  fi ;;
	esac
      fi
      break
    fi
  done
  IFS=$lt_save_ifs
  MAGIC_CMD=$lt_save_MAGIC_CMD
  ;;
esac])
MAGIC_CMD=$lt_cv_path_MAGIC_CMD
if test -n "$MAGIC_CMD"; then
  AC_MSG_RESULT($MAGIC_CMD)
else
  AC_MSG_RESULT(no)
fi
_LT_DECL([], [MAGIC_CMD], [0],
	 [Used to examine libraries when file_magic_cmd begins with "file"])dnl
])# _LT_PATH_TOOL_PREFIX

# Old name:
AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], [])


# _LT_PATH_MAGIC
# --------------
# find a file program that can recognize a shared library
m4_defun([_LT_PATH_MAGIC],
[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH)
if test -z "$lt_cv_path_MAGIC_CMD"; then
  if test -n "$ac_tool_prefix"; then
    _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH)
  else
    MAGIC_CMD=:
  fi
fi
])# _LT_PATH_MAGIC


# LT_PATH_LD
# ----------
# find the pathname to the GNU or non-GNU linker
AC_DEFUN([LT_PATH_LD],
[AC_REQUIRE([AC_PROG_CC])dnl
AC_REQUIRE([AC_CANONICAL_HOST])dnl
AC_REQUIRE([AC_CANONICAL_BUILD])dnl
m4_require([_LT_DECL_SED])dnl
m4_require([_LT_DECL_EGREP])dnl
m4_require([_LT_PROG_ECHO_BACKSLASH])dnl

AC_ARG_WITH([gnu-ld],
    [AS_HELP_STRING([--with-gnu-ld],
	[assume the C compiler uses GNU ld @<:@default=no@:>@])],
    [test no = "$withval" || with_gnu_ld=yes],
    [with_gnu_ld=no])dnl

ac_prog=ld
if test yes = "$GCC"; then
  # Check if gcc -print-prog-name=ld gives a path.
  AC_MSG_CHECKING([for ld used by $CC])
  case $host in
  *-*-mingw*)
    # gcc leaves a trailing carriage return, which upsets mingw
    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
  *)
    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
  esac
  case $ac_prog in
    # Accept absolute paths.
    [[\\/]]* | ?:[[\\/]]*)
      re_direlt='/[[^/]][[^/]]*/\.\./'
      # Canonicalize the pathname of ld
      ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
      while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
	ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
      done
      test -z "$LD" && LD=$ac_prog
      ;;
  "")
    # If it fails, then pretend we aren't using GCC.
    ac_prog=ld
    ;;
  *)
    # If it is relative, then search for the first ld in PATH.
    with_gnu_ld=unknown
    ;;
  esac
elif test yes = "$with_gnu_ld"; then
  AC_MSG_CHECKING([for GNU ld])
else
  AC_MSG_CHECKING([for non-GNU ld])
fi
AC_CACHE_VAL(lt_cv_path_LD,
[if test -z "$LD"; then
  lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
  for ac_dir in $PATH; do
    IFS=$lt_save_ifs
    test -z "$ac_dir" && ac_dir=.
    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
      lt_cv_path_LD=$ac_dir/$ac_prog
      # Check to see if the program is GNU ld.  I'd rather use --version,
      # but apparently some variants of GNU ld only accept -v.
      # Break only if it was the GNU/non-GNU ld that we prefer.
      case `"$lt_cv_path_LD" -v 2>&1 &1 conftest.i
cat conftest.i conftest.i >conftest2.i
: ${lt_DD:=$DD}
AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd],
[if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then
  cmp -s conftest.i conftest.out \
  && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=:
fi])
rm -f conftest.i conftest2.i conftest.out])
])# _LT_PATH_DD


# _LT_CMD_TRUNCATE
# ----------------
# find command to truncate a binary pipe
m4_defun([_LT_CMD_TRUNCATE],
[m4_require([_LT_PATH_DD])
AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin],
[printf 0123456789abcdef0123456789abcdef >conftest.i
cat conftest.i conftest.i >conftest2.i
lt_cv_truncate_bin=
if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then
  cmp -s conftest.i conftest.out \
  && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1"
fi
rm -f conftest.i conftest2.i conftest.out
test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"])
_LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1],
  [Command to truncate a binary pipe])
])# _LT_CMD_TRUNCATE


# _LT_CHECK_MAGIC_METHOD
# ----------------------
# how to check for library dependencies
#  -- PORTME fill in with the dynamic library characteristics
m4_defun([_LT_CHECK_MAGIC_METHOD],
[m4_require([_LT_DECL_EGREP])
m4_require([_LT_DECL_OBJDUMP])
AC_CACHE_CHECK([how to recognize dependent libraries],
lt_cv_deplibs_check_method,
[lt_cv_file_magic_cmd='$MAGIC_CMD'
lt_cv_file_magic_test_file=
lt_cv_deplibs_check_method='unknown'
# Need to set the preceding variable on all platforms that support
# interlibrary dependencies.
# 'none' -- dependencies not supported.
# 'unknown' -- same as none, but documents that we really don't know.
# 'pass_all' -- all dependencies passed with no checks.
# 'test_compile' -- check by making test program.
# 'file_magic [[regex]]' -- check by looking for files in library path
# that responds to the $file_magic_cmd with a given extended regex.
# If you have 'file' or equivalent on your system and you're not sure
# whether 'pass_all' will *always* work, you probably want this one.

case $host_os in
aix[[4-9]]*)
  lt_cv_deplibs_check_method=pass_all
  ;;

beos*)
  lt_cv_deplibs_check_method=pass_all
  ;;

bsdi[[45]]*)
  lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
  lt_cv_file_magic_cmd='/usr/bin/file -L'
  lt_cv_file_magic_test_file=/shlib/libc.so
  ;;

cygwin*)
  # func_win32_libid is a shell function defined in ltmain.sh
  lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
  lt_cv_file_magic_cmd='func_win32_libid'
  ;;

mingw* | pw32*)
  # Base MSYS/MinGW do not provide the 'file' command needed by
  # func_win32_libid shell function, so use a weaker test based on 'objdump',
  # unless we find 'file', for example because we are cross-compiling.
  if ( file / ) >/dev/null 2>&1; then
    lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
    lt_cv_file_magic_cmd='func_win32_libid'
  else
    # Keep this pattern in sync with the one in func_win32_libid.
    lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)'
    lt_cv_file_magic_cmd='$OBJDUMP -f'
  fi
  ;;

cegcc*)
  # use the weaker test based on 'objdump'. See mingw*.
  lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
  lt_cv_file_magic_cmd='$OBJDUMP -f'
  ;;

darwin* | rhapsody*)
  lt_cv_deplibs_check_method=pass_all
  ;;

freebsd* | dragonfly*)
  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
    case $host_cpu in
    i*86 )
      # Not sure whether the presence of OpenBSD here was a mistake.
      # Let's accept both of them until this is cleared up.
      lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library'
      lt_cv_file_magic_cmd=/usr/bin/file
      lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
      ;;
    esac
  else
    lt_cv_deplibs_check_method=pass_all
  fi
  ;;

haiku*)
  lt_cv_deplibs_check_method=pass_all
  ;;

hpux10.20* | hpux11*)
  lt_cv_file_magic_cmd=/usr/bin/file
  case $host_cpu in
  ia64*)
    lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'
    lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
    ;;
  hppa*64*)
    [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]']
    lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
    ;;
  *)
    lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library'
    lt_cv_file_magic_test_file=/usr/lib/libc.sl
    ;;
  esac
  ;;

interix[[3-9]]*)
  # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
  lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$'
  ;;

irix5* | irix6* | nonstopux*)
  case $LD in
  *-32|*"-32 ") libmagic=32-bit;;
  *-n32|*"-n32 ") libmagic=N32;;
  *-64|*"-64 ") libmagic=64-bit;;
  *) libmagic=never-match;;
  esac
  lt_cv_deplibs_check_method=pass_all
  ;;

# This must be glibc/ELF.
linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
  lt_cv_deplibs_check_method=pass_all
  ;;

netbsd* | netbsdelf*-gnu)
  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
  else
    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$'
  fi
  ;;

newos6*)
  lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
  lt_cv_file_magic_cmd=/usr/bin/file
  lt_cv_file_magic_test_file=/usr/lib/libnls.so
  ;;

*nto* | *qnx*)
  lt_cv_deplibs_check_method=pass_all
  ;;

openbsd* | bitrig*)
  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$'
  else
    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
  fi
  ;;

osf3* | osf4* | osf5*)
  lt_cv_deplibs_check_method=pass_all
  ;;

rdos*)
  lt_cv_deplibs_check_method=pass_all
  ;;

solaris*)
  lt_cv_deplibs_check_method=pass_all
  ;;

sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
  lt_cv_deplibs_check_method=pass_all
  ;;

sysv4 | sysv4.3*)
  case $host_vendor in
  motorola)
    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
    lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
    ;;
  ncr)
    lt_cv_deplibs_check_method=pass_all
    ;;
  sequent)
    lt_cv_file_magic_cmd='/bin/file'
    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
    ;;
  sni)
    lt_cv_file_magic_cmd='/bin/file'
    lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
    lt_cv_file_magic_test_file=/lib/libc.so
    ;;
  siemens)
    lt_cv_deplibs_check_method=pass_all
    ;;
  pc)
    lt_cv_deplibs_check_method=pass_all
    ;;
  esac
  ;;

tpf*)
  lt_cv_deplibs_check_method=pass_all
  ;;
os2*)
  lt_cv_deplibs_check_method=pass_all
  ;;
esac
])

file_magic_glob=
want_nocaseglob=no
if test "$build" = "$host"; then
  case $host_os in
  mingw* | pw32*)
    if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then
      want_nocaseglob=yes
    else
      file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"`
    fi
    ;;
  esac
fi

file_magic_cmd=$lt_cv_file_magic_cmd
deplibs_check_method=$lt_cv_deplibs_check_method
test -z "$deplibs_check_method" && deplibs_check_method=unknown

_LT_DECL([], [deplibs_check_method], [1],
    [Method to check whether dependent libraries are shared objects])
_LT_DECL([], [file_magic_cmd], [1],
    [Command to use when deplibs_check_method = "file_magic"])
_LT_DECL([], [file_magic_glob], [1],
    [How to find potential files when deplibs_check_method = "file_magic"])
_LT_DECL([], [want_nocaseglob], [1],
    [Find potential files using nocaseglob when deplibs_check_method = "file_magic"])
])# _LT_CHECK_MAGIC_METHOD


# LT_PATH_NM
# ----------
# find the pathname to a BSD- or MS-compatible name lister
AC_DEFUN([LT_PATH_NM],
[AC_REQUIRE([AC_PROG_CC])dnl
AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM,
[if test -n "$NM"; then
  # Let the user override the test.
  lt_cv_path_NM=$NM
else
  lt_nm_to_check=${ac_tool_prefix}nm
  if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
    lt_nm_to_check="$lt_nm_to_check nm"
  fi
  for lt_tmp_nm in $lt_nm_to_check; do
    lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
    for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
      IFS=$lt_save_ifs
      test -z "$ac_dir" && ac_dir=.
      tmp_nm=$ac_dir/$lt_tmp_nm
      if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then
	# Check to see if the nm accepts a BSD-compat flag.
	# Adding the 'sed 1q' prevents false positives on HP-UX, which says:
	#   nm: unknown option "B" ignored
	# Tru64's nm complains that /dev/null is an invalid object file
	# MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty
	case $build_os in
	mingw*) lt_bad_file=conftest.nm/nofile ;;
	*) lt_bad_file=/dev/null ;;
	esac
	case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in
	*$lt_bad_file* | *'Invalid file or object type'*)
	  lt_cv_path_NM="$tmp_nm -B"
	  break 2
	  ;;
	*)
	  case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
	  */dev/null*)
	    lt_cv_path_NM="$tmp_nm -p"
	    break 2
	    ;;
	  *)
	    lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
	    continue # so that we can try to find one that supports BSD flags
	    ;;
	  esac
	  ;;
	esac
      fi
    done
    IFS=$lt_save_ifs
  done
  : ${lt_cv_path_NM=no}
fi])
if test no != "$lt_cv_path_NM"; then
  NM=$lt_cv_path_NM
else
  # Didn't find any BSD compatible name lister, look for dumpbin.
  if test -n "$DUMPBIN"; then :
    # Let the user override the test.
  else
    AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :)
    case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in
    *COFF*)
      DUMPBIN="$DUMPBIN -symbols -headers"
      ;;
    *)
      DUMPBIN=:
      ;;
    esac
  fi
  AC_SUBST([DUMPBIN])
  if test : != "$DUMPBIN"; then
    NM=$DUMPBIN
  fi
fi
test -z "$NM" && NM=nm
AC_SUBST([NM])
_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl

AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface],
  [lt_cv_nm_interface="BSD nm"
  echo "int some_variable = 0;" > conftest.$ac_ext
  (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD)
  (eval "$ac_compile" 2>conftest.err)
  cat conftest.err >&AS_MESSAGE_LOG_FD
  (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD)
  (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
  cat conftest.err >&AS_MESSAGE_LOG_FD
  (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD)
  cat conftest.out >&AS_MESSAGE_LOG_FD
  if $GREP 'External.*some_variable' conftest.out > /dev/null; then
    lt_cv_nm_interface="MS dumpbin"
  fi
  rm -f conftest*])
])# LT_PATH_NM

# Old names:
AU_ALIAS([AM_PROG_NM], [LT_PATH_NM])
AU_ALIAS([AC_PROG_NM], [LT_PATH_NM])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AM_PROG_NM], [])
dnl AC_DEFUN([AC_PROG_NM], [])

# _LT_CHECK_SHAREDLIB_FROM_LINKLIB
# --------------------------------
# how to determine the name of the shared library
# associated with a specific link library.
#  -- PORTME fill in with the dynamic library characteristics
m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB],
[m4_require([_LT_DECL_EGREP])
m4_require([_LT_DECL_OBJDUMP])
m4_require([_LT_DECL_DLLTOOL])
AC_CACHE_CHECK([how to associate runtime and link libraries],
lt_cv_sharedlib_from_linklib_cmd,
[lt_cv_sharedlib_from_linklib_cmd='unknown'

case $host_os in
cygwin* | mingw* | pw32* | cegcc*)
  # two different shell functions defined in ltmain.sh;
  # decide which one to use based on capabilities of $DLLTOOL
  case `$DLLTOOL --help 2>&1` in
  *--identify-strict*)
    lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib
    ;;
  *)
    lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback
    ;;
  esac
  ;;
*)
  # fallback: assume linklib IS sharedlib
  lt_cv_sharedlib_from_linklib_cmd=$ECHO
  ;;
esac
])
sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd
test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO

_LT_DECL([], [sharedlib_from_linklib_cmd], [1],
    [Command to associate shared and link libraries])
])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB


# _LT_PATH_MANIFEST_TOOL
# ----------------------
# locate the manifest tool
m4_defun([_LT_PATH_MANIFEST_TOOL],
[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :)
test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt
AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool],
  [lt_cv_path_mainfest_tool=no
  echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD
  $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out
  cat conftest.err >&AS_MESSAGE_LOG_FD
  if $GREP 'Manifest Tool' conftest.out > /dev/null; then
    lt_cv_path_mainfest_tool=yes
  fi
  rm -f conftest*])
if test yes != "$lt_cv_path_mainfest_tool"; then
  MANIFEST_TOOL=:
fi
_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl
])# _LT_PATH_MANIFEST_TOOL


# _LT_DLL_DEF_P([FILE])
# ---------------------
# True iff FILE is a Windows DLL '.def' file.
# Keep in sync with func_dll_def_p in the libtool script
AC_DEFUN([_LT_DLL_DEF_P],
[dnl
  test DEF = "`$SED -n dnl
    -e '\''s/^[[	 ]]*//'\'' dnl Strip leading whitespace
    -e '\''/^\(;.*\)*$/d'\'' dnl      Delete empty lines and comments
    -e '\''s/^\(EXPORTS\|LIBRARY\)\([[	 ]].*\)*$/DEF/p'\'' dnl
    -e q dnl                          Only consider the first "real" line
    $1`" dnl
])# _LT_DLL_DEF_P


# LT_LIB_M
# --------
# check for math library
AC_DEFUN([LT_LIB_M],
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
LIBM=
case $host in
*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*)
  # These system don't have libm, or don't need it
  ;;
*-ncr-sysv4.3*)
  AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw)
  AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm")
  ;;
*)
  AC_CHECK_LIB(m, cos, LIBM=-lm)
  ;;
esac
AC_SUBST([LIBM])
])# LT_LIB_M

# Old name:
AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_CHECK_LIBM], [])


# _LT_COMPILER_NO_RTTI([TAGNAME])
# -------------------------------
m4_defun([_LT_COMPILER_NO_RTTI],
[m4_require([_LT_TAG_COMPILER])dnl

_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=

if test yes = "$GCC"; then
  case $cc_basename in
  nvcc*)
    _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;;
  *)
    _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;;
  esac

  _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions],
    lt_cv_prog_compiler_rtti_exceptions,
    [-fno-rtti -fno-exceptions], [],
    [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"])
fi
_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1],
	[Compiler flag to turn off builtin functions])
])# _LT_COMPILER_NO_RTTI


# _LT_CMD_GLOBAL_SYMBOLS
# ----------------------
m4_defun([_LT_CMD_GLOBAL_SYMBOLS],
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
AC_REQUIRE([AC_PROG_CC])dnl
AC_REQUIRE([AC_PROG_AWK])dnl
AC_REQUIRE([LT_PATH_NM])dnl
AC_REQUIRE([LT_PATH_LD])dnl
m4_require([_LT_DECL_SED])dnl
m4_require([_LT_DECL_EGREP])dnl
m4_require([_LT_TAG_COMPILER])dnl

# Check for command to grab the raw symbol name followed by C symbol from nm.
AC_MSG_CHECKING([command to parse $NM output from $compiler object])
AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe],
[
# These are sane defaults that work on at least a few old systems.
# [They come from Ultrix.  What could be older than Ultrix?!! ;)]

# Character class describing NM global symbol codes.
symcode='[[BCDEGRST]]'

# Regexp to match symbols that can be accessed directly from C.
sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'

# Define system-specific variables.
case $host_os in
aix*)
  symcode='[[BCDT]]'
  ;;
cygwin* | mingw* | pw32* | cegcc*)
  symcode='[[ABCDGISTW]]'
  ;;
hpux*)
  if test ia64 = "$host_cpu"; then
    symcode='[[ABCDEGRST]]'
  fi
  ;;
irix* | nonstopux*)
  symcode='[[BCDEGRST]]'
  ;;
osf*)
  symcode='[[BCDEGQRST]]'
  ;;
solaris*)
  symcode='[[BDRT]]'
  ;;
sco3.2v5*)
  symcode='[[DT]]'
  ;;
sysv4.2uw2*)
  symcode='[[DT]]'
  ;;
sysv5* | sco5v6* | unixware* | OpenUNIX*)
  symcode='[[ABDT]]'
  ;;
sysv4)
  symcode='[[DFNSTU]]'
  ;;
esac

# If we're using GNU nm, then use its standard symbol codes.
case `$NM -V 2>&1` in
*GNU* | *'with BFD'*)
  symcode='[[ABCDGIRSTW]]' ;;
esac

if test "$lt_cv_nm_interface" = "MS dumpbin"; then
  # Gets list of data symbols to import.
  lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'"
  # Adjust the below global symbol transforms to fixup imported variables.
  lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'"
  lt_c_name_hook=" -e 's/^I .* \(.*\)$/  {\"\1\", (void *) 0},/p'"
  lt_c_name_lib_hook="\
  -e 's/^I .* \(lib.*\)$/  {\"\1\", (void *) 0},/p'\
  -e 's/^I .* \(.*\)$/  {\"lib\1\", (void *) 0},/p'"
else
  # Disable hooks by default.
  lt_cv_sys_global_symbol_to_import=
  lt_cdecl_hook=
  lt_c_name_hook=
  lt_c_name_lib_hook=
fi

# Transform an extracted symbol line into a proper C declaration.
# Some systems (esp. on ia64) link data and code symbols differently,
# so use this general approach.
lt_cv_sys_global_symbol_to_cdecl="sed -n"\
$lt_cdecl_hook\
" -e 's/^T .* \(.*\)$/extern int \1();/p'"\
" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'"

# Transform an extracted symbol line into symbol name and symbol address
lt_cv_sys_global_symbol_to_c_name_address="sed -n"\
$lt_c_name_hook\
" -e 's/^: \(.*\) .*$/  {\"\1\", (void *) 0},/p'"\
" -e 's/^$symcode$symcode* .* \(.*\)$/  {\"\1\", (void *) \&\1},/p'"

# Transform an extracted symbol line into symbol name with lib prefix and
# symbol address.
lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\
$lt_c_name_lib_hook\
" -e 's/^: \(.*\) .*$/  {\"\1\", (void *) 0},/p'"\
" -e 's/^$symcode$symcode* .* \(lib.*\)$/  {\"\1\", (void *) \&\1},/p'"\
" -e 's/^$symcode$symcode* .* \(.*\)$/  {\"lib\1\", (void *) \&\1},/p'"

# Handle CRLF in mingw tool chain
opt_cr=
case $build_os in
mingw*)
  opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
  ;;
esac

# Try without a prefix underscore, then with it.
for ac_symprfx in "" "_"; do

  # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
  symxfrm="\\1 $ac_symprfx\\2 \\2"

  # Write the raw and C identifiers.
  if test "$lt_cv_nm_interface" = "MS dumpbin"; then
    # Fake it for dumpbin and say T for any non-static function,
    # D for any global variable and I for any imported variable.
    # Also find C++ and __fastcall symbols from MSVC++,
    # which start with @ or ?.
    lt_cv_sys_global_symbol_pipe="$AWK ['"\
"     {last_section=section; section=\$ 3};"\
"     /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\
"     /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
"     /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\
"     /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\
"     /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\
"     \$ 0!~/External *\|/{next};"\
"     / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
"     {if(hide[section]) next};"\
"     {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\
"     {split(\$ 0,a,/\||\r/); split(a[2],s)};"\
"     s[1]~/^[@?]/{print f,s[1],s[1]; next};"\
"     s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\
"     ' prfx=^$ac_symprfx]"
  else
    lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[	 ]]\($symcode$symcode*\)[[	 ]][[	 ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
  fi
  lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'"

  # Check to see that the pipe works correctly.
  pipe_works=no

  rm -f conftest*
  cat > conftest.$ac_ext <<_LT_EOF
#ifdef __cplusplus
extern "C" {
#endif
char nm_test_var;
void nm_test_func(void);
void nm_test_func(void){}
#ifdef __cplusplus
}
#endif
int main(){nm_test_var='a';nm_test_func();return(0);}
_LT_EOF

  if AC_TRY_EVAL(ac_compile); then
    # Now try to grab the symbols.
    nlist=conftest.nm
    if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then
      # Try sorting and uniquifying the output.
      if sort "$nlist" | uniq > "$nlist"T; then
	mv -f "$nlist"T "$nlist"
      else
	rm -f "$nlist"T
      fi

      # Make sure that we snagged all the symbols we need.
      if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
	if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
	  cat <<_LT_EOF > conftest.$ac_ext
/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests.  */
#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE
/* DATA imports from DLLs on WIN32 can't be const, because runtime
   relocations are performed -- see ld's documentation on pseudo-relocs.  */
# define LT@&t@_DLSYM_CONST
#elif defined __osf__
/* This system does not cope well with relocations in const data.  */
# define LT@&t@_DLSYM_CONST
#else
# define LT@&t@_DLSYM_CONST const
#endif

#ifdef __cplusplus
extern "C" {
#endif

_LT_EOF
	  # Now generate the symbol file.
	  eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'

	  cat <<_LT_EOF >> conftest.$ac_ext

/* The mapping between symbol names and symbols.  */
LT@&t@_DLSYM_CONST struct {
  const char *name;
  void       *address;
}
lt__PROGRAM__LTX_preloaded_symbols[[]] =
{
  { "@PROGRAM@", (void *) 0 },
_LT_EOF
	  $SED "s/^$symcode$symcode* .* \(.*\)$/  {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
	  cat <<\_LT_EOF >> conftest.$ac_ext
  {0, (void *) 0}
};

/* This works around a problem in FreeBSD linker */
#ifdef FREEBSD_WORKAROUND
static const void *lt_preloaded_setup() {
  return lt__PROGRAM__LTX_preloaded_symbols;
}
#endif

#ifdef __cplusplus
}
#endif
_LT_EOF
	  # Now try linking the two files.
	  mv conftest.$ac_objext conftstm.$ac_objext
	  lt_globsym_save_LIBS=$LIBS
	  lt_globsym_save_CFLAGS=$CFLAGS
	  LIBS=conftstm.$ac_objext
	  CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)"
	  if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then
	    pipe_works=yes
	  fi
	  LIBS=$lt_globsym_save_LIBS
	  CFLAGS=$lt_globsym_save_CFLAGS
	else
	  echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD
	fi
      else
	echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD
      fi
    else
      echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD
    fi
  else
    echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD
    cat conftest.$ac_ext >&5
  fi
  rm -rf conftest* conftst*

  # Do not use the global_symbol_pipe unless it works.
  if test yes = "$pipe_works"; then
    break
  else
    lt_cv_sys_global_symbol_pipe=
  fi
done
])
if test -z "$lt_cv_sys_global_symbol_pipe"; then
  lt_cv_sys_global_symbol_to_cdecl=
fi
if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
  AC_MSG_RESULT(failed)
else
  AC_MSG_RESULT(ok)
fi

# Response file support.
if test "$lt_cv_nm_interface" = "MS dumpbin"; then
  nm_file_list_spec='@'
elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then
  nm_file_list_spec='@'
fi

_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1],
    [Take the output of nm and produce a listing of raw symbols and C names])
_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1],
    [Transform the output of nm in a proper C declaration])
_LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1],
    [Transform the output of nm into a list of symbols to manually relocate])
_LT_DECL([global_symbol_to_c_name_address],
    [lt_cv_sys_global_symbol_to_c_name_address], [1],
    [Transform the output of nm in a C name address pair])
_LT_DECL([global_symbol_to_c_name_address_lib_prefix],
    [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1],
    [Transform the output of nm in a C name address pair when lib prefix is needed])
_LT_DECL([nm_interface], [lt_cv_nm_interface], [1],
    [The name lister interface])
_LT_DECL([], [nm_file_list_spec], [1],
    [Specify filename containing input files for $NM])
]) # _LT_CMD_GLOBAL_SYMBOLS


# _LT_COMPILER_PIC([TAGNAME])
# ---------------------------
m4_defun([_LT_COMPILER_PIC],
[m4_require([_LT_TAG_COMPILER])dnl
_LT_TAGVAR(lt_prog_compiler_wl, $1)=
_LT_TAGVAR(lt_prog_compiler_pic, $1)=
_LT_TAGVAR(lt_prog_compiler_static, $1)=

m4_if([$1], [CXX], [
  # C++ specific cases for pic, static, wl, etc.
  if test yes = "$GXX"; then
    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'

    case $host_os in
    aix*)
      # All AIX code is PIC.
      if test ia64 = "$host_cpu"; then
	# AIX 5 now supports IA64 processor
	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
      fi
      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
      ;;

    amigaos*)
      case $host_cpu in
      powerpc)
            # see comment about AmigaOS4 .so support
            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
        ;;
      m68k)
            # FIXME: we need at least 68020 code to build shared libraries, but
            # adding the '-m68020' flag to GCC prevents building anything better,
            # like '-m68040'.
            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
        ;;
      esac
      ;;

    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
      # PIC is the default for these OSes.
      ;;
    mingw* | cygwin* | os2* | pw32* | cegcc*)
      # This hack is so that the source file can tell whether it is being
      # built for inclusion in a dll (and should export symbols for example).
      # Although the cygwin gcc ignores -fPIC, still need this for old-style
      # (--disable-auto-import) libraries
      m4_if([$1], [GCJ], [],
	[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
      case $host_os in
      os2*)
	_LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static'
	;;
      esac
      ;;
    darwin* | rhapsody*)
      # PIC is the default on this platform
      # Common symbols not allowed in MH_DYLIB files
      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
      ;;
    *djgpp*)
      # DJGPP does not support shared libraries at all
      _LT_TAGVAR(lt_prog_compiler_pic, $1)=
      ;;
    haiku*)
      # PIC is the default for Haiku.
      # The "-static" flag exists, but is broken.
      _LT_TAGVAR(lt_prog_compiler_static, $1)=
      ;;
    interix[[3-9]]*)
      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
      # Instead, we relocate shared libraries at runtime.
      ;;
    sysv4*MP*)
      if test -d /usr/nec; then
	_LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
      fi
      ;;
    hpux*)
      # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
      # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
      # sets the default TLS model and affects inlining.
      case $host_cpu in
      hppa*64*)
	;;
      *)
	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
	;;
      esac
      ;;
    *qnx* | *nto*)
      # QNX uses GNU C++, but need to define -shared option too, otherwise
      # it will coredump.
      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
      ;;
    *)
      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
      ;;
    esac
  else
    case $host_os in
      aix[[4-9]]*)
	# All AIX code is PIC.
	if test ia64 = "$host_cpu"; then
	  # AIX 5 now supports IA64 processor
	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
	else
	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
	fi
	;;
      chorus*)
	case $cc_basename in
	cxch68*)
	  # Green Hills C++ Compiler
	  # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
	  ;;
	esac
	;;
      mingw* | cygwin* | os2* | pw32* | cegcc*)
	# This hack is so that the source file can tell whether it is being
	# built for inclusion in a dll (and should export symbols for example).
	m4_if([$1], [GCJ], [],
	  [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
	;;
      dgux*)
	case $cc_basename in
	  ec++*)
	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
	    ;;
	  ghcx*)
	    # Green Hills C++ Compiler
	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
	    ;;
	  *)
	    ;;
	esac
	;;
      freebsd* | dragonfly*)
	# FreeBSD uses GNU C++
	;;
      hpux9* | hpux10* | hpux11*)
	case $cc_basename in
	  CC*)
	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
	    _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive'
	    if test ia64 != "$host_cpu"; then
	      _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
	    fi
	    ;;
	  aCC*)
	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
	    _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive'
	    case $host_cpu in
	    hppa*64*|ia64*)
	      # +Z the default
	      ;;
	    *)
	      _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
	      ;;
	    esac
	    ;;
	  *)
	    ;;
	esac
	;;
      interix*)
	# This is c89, which is MS Visual C++ (no shared libs)
	# Anyone wants to do a port?
	;;
      irix5* | irix6* | nonstopux*)
	case $cc_basename in
	  CC*)
	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
	    # CC pic flag -KPIC is the default.
	    ;;
	  *)
	    ;;
	esac
	;;
      linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
	case $cc_basename in
	  KCC*)
	    # KAI C++ Compiler
	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
	    ;;
	  ecpc* )
	    # old Intel C++ for x86_64, which still supported -KPIC.
	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
	    ;;
	  icpc* )
	    # Intel C++, used to be incompatible with GCC.
	    # ICC 10 doesn't accept -KPIC any more.
	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
	    ;;
	  pgCC* | pgcpp*)
	    # Portland Group C++ compiler
	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
	    ;;
	  cxx*)
	    # Compaq C++
	    # Make sure the PIC flag is empty.  It appears that all Alpha
	    # Linux and Compaq Tru64 Unix objects are PIC.
	    _LT_TAGVAR(lt_prog_compiler_pic, $1)=
	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
	    ;;
	  xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*)
	    # IBM XL 8.0, 9.0 on PPC and BlueGene
	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
	    ;;
	  *)
	    case `$CC -V 2>&1 | sed 5q` in
	    *Sun\ C*)
	      # Sun C++ 5.9
	      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
	      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
	      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
	      ;;
	    esac
	    ;;
	esac
	;;
      lynxos*)
	;;
      m88k*)
	;;
      mvs*)
	case $cc_basename in
	  cxx*)
	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall'
	    ;;
	  *)
	    ;;
	esac
	;;
      netbsd* | netbsdelf*-gnu)
	;;
      *qnx* | *nto*)
        # QNX uses GNU C++, but need to define -shared option too, otherwise
        # it will coredump.
        _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
        ;;
      osf3* | osf4* | osf5*)
	case $cc_basename in
	  KCC*)
	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
	    ;;
	  RCC*)
	    # Rational C++ 2.4.1
	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
	    ;;
	  cxx*)
	    # Digital/Compaq C++
	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
	    # Make sure the PIC flag is empty.  It appears that all Alpha
	    # Linux and Compaq Tru64 Unix objects are PIC.
	    _LT_TAGVAR(lt_prog_compiler_pic, $1)=
	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
	    ;;
	  *)
	    ;;
	esac
	;;
      psos*)
	;;
      solaris*)
	case $cc_basename in
	  CC* | sunCC*)
	    # Sun C++ 4.2, 5.x and Centerline C++
	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
	    ;;
	  gcx*)
	    # Green Hills C++ Compiler
	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
	    ;;
	  *)
	    ;;
	esac
	;;
      sunos4*)
	case $cc_basename in
	  CC*)
	    # Sun C++ 4.x
	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
	    ;;
	  lcc*)
	    # Lucid
	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
	    ;;
	  *)
	    ;;
	esac
	;;
      sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
	case $cc_basename in
	  CC*)
	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
	    ;;
	esac
	;;
      tandem*)
	case $cc_basename in
	  NCC*)
	    # NonStop-UX NCC 3.20
	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
	    ;;
	  *)
	    ;;
	esac
	;;
      vxworks*)
	;;
      *)
	_LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
	;;
    esac
  fi
],
[
  if test yes = "$GCC"; then
    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'

    case $host_os in
      aix*)
      # All AIX code is PIC.
      if test ia64 = "$host_cpu"; then
	# AIX 5 now supports IA64 processor
	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
      fi
      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
      ;;

    amigaos*)
      case $host_cpu in
      powerpc)
            # see comment about AmigaOS4 .so support
            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
        ;;
      m68k)
            # FIXME: we need at least 68020 code to build shared libraries, but
            # adding the '-m68020' flag to GCC prevents building anything better,
            # like '-m68040'.
            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
        ;;
      esac
      ;;

    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
      # PIC is the default for these OSes.
      ;;

    mingw* | cygwin* | pw32* | os2* | cegcc*)
      # This hack is so that the source file can tell whether it is being
      # built for inclusion in a dll (and should export symbols for example).
      # Although the cygwin gcc ignores -fPIC, still need this for old-style
      # (--disable-auto-import) libraries
      m4_if([$1], [GCJ], [],
	[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
      case $host_os in
      os2*)
	_LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static'
	;;
      esac
      ;;

    darwin* | rhapsody*)
      # PIC is the default on this platform
      # Common symbols not allowed in MH_DYLIB files
      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
      ;;

    haiku*)
      # PIC is the default for Haiku.
      # The "-static" flag exists, but is broken.
      _LT_TAGVAR(lt_prog_compiler_static, $1)=
      ;;

    hpux*)
      # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
      # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
      # sets the default TLS model and affects inlining.
      case $host_cpu in
      hppa*64*)
	# +Z the default
	;;
      *)
	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
	;;
      esac
      ;;

    interix[[3-9]]*)
      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
      # Instead, we relocate shared libraries at runtime.
      ;;

    msdosdjgpp*)
      # Just because we use GCC doesn't mean we suddenly get shared libraries
      # on systems that don't support them.
      _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
      enable_shared=no
      ;;

    *nto* | *qnx*)
      # QNX uses GNU C++, but need to define -shared option too, otherwise
      # it will coredump.
      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
      ;;

    sysv4*MP*)
      if test -d /usr/nec; then
	_LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
      fi
      ;;

    *)
      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
      ;;
    esac

    case $cc_basename in
    nvcc*) # Cuda Compiler Driver 2.2
      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker '
      if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
        _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)"
      fi
      ;;
    esac
  else
    # PORTME Check for flag to pass linker flags through the system compiler.
    case $host_os in
    aix*)
      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
      if test ia64 = "$host_cpu"; then
	# AIX 5 now supports IA64 processor
	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
      else
	_LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
      fi
      ;;

    darwin* | rhapsody*)
      # PIC is the default on this platform
      # Common symbols not allowed in MH_DYLIB files
      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
      case $cc_basename in
      nagfor*)
        # NAG Fortran compiler
        _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,'
        _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
        _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
        ;;
      esac
      ;;

    mingw* | cygwin* | pw32* | os2* | cegcc*)
      # This hack is so that the source file can tell whether it is being
      # built for inclusion in a dll (and should export symbols for example).
      m4_if([$1], [GCJ], [],
	[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
      case $host_os in
      os2*)
	_LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static'
	;;
      esac
      ;;

    hpux9* | hpux10* | hpux11*)
      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
      # not for PA HP-UX.
      case $host_cpu in
      hppa*64*|ia64*)
	# +Z the default
	;;
      *)
	_LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
	;;
      esac
      # Is there a better lt_prog_compiler_static that works with the bundled CC?
      _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive'
      ;;

    irix5* | irix6* | nonstopux*)
      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
      # PIC (with -KPIC) is the default.
      _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
      ;;

    linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
      case $cc_basename in
      # old Intel for x86_64, which still supported -KPIC.
      ecc*)
	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
	_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
        ;;
      # icc used to be incompatible with GCC.
      # ICC 10 doesn't accept -KPIC any more.
      icc* | ifort*)
	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
	_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
        ;;
      # Lahey Fortran 8.1.
      lf95*)
	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
	_LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared'
	_LT_TAGVAR(lt_prog_compiler_static, $1)='--static'
	;;
      nagfor*)
	# NAG Fortran compiler
	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,'
	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
	;;
      tcc*)
	# Fabrice Bellard et al's Tiny C Compiler
	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
	_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
	;;
      pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
        # Portland Group compilers (*not* the Pentium gcc compiler,
	# which looks to be a dead project)
	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
        ;;
      ccc*)
        _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
        # All Alpha code is PIC.
        _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
        ;;
      xl* | bgxl* | bgf* | mpixl*)
	# IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene
	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
	_LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
	;;
      *)
	case `$CC -V 2>&1 | sed 5q` in
	*Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*)
	  # Sun Fortran 8.3 passes all unrecognized flags to the linker
	  _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
	  _LT_TAGVAR(lt_prog_compiler_wl, $1)=''
	  ;;
	*Sun\ F* | *Sun*Fortran*)
	  _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
	  _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
	  ;;
	*Sun\ C*)
	  # Sun C 5.9
	  _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
	  _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
	  ;;
        *Intel*\ [[CF]]*Compiler*)
	  _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
	  _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
	  ;;
	*Portland\ Group*)
	  _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
	  _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
	  ;;
	esac
	;;
      esac
      ;;

    newsos6)
      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
      ;;

    *nto* | *qnx*)
      # QNX uses GNU C++, but need to define -shared option too, otherwise
      # it will coredump.
      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
      ;;

    osf3* | osf4* | osf5*)
      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
      # All OSF/1 code is PIC.
      _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
      ;;

    rdos*)
      _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
      ;;

    solaris*)
      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
      case $cc_basename in
      f77* | f90* | f95* | sunf77* | sunf90* | sunf95*)
	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';;
      *)
	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';;
      esac
      ;;

    sunos4*)
      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
      ;;

    sysv4 | sysv4.2uw2* | sysv4.3*)
      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
      ;;

    sysv4*MP*)
      if test -d /usr/nec; then
	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic'
	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
      fi
      ;;

    sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
      ;;

    unicos*)
      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
      _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
      ;;

    uts4*)
      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
      ;;

    *)
      _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
      ;;
    esac
  fi
])
case $host_os in
  # For platforms that do not support PIC, -DPIC is meaningless:
  *djgpp*)
    _LT_TAGVAR(lt_prog_compiler_pic, $1)=
    ;;
  *)
    _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])"
    ;;
esac

AC_CACHE_CHECK([for $compiler option to produce PIC],
  [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)],
  [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)])
_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)

#
# Check to make sure the PIC flag actually works.
#
if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
  _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works],
    [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)],
    [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [],
    [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in
     "" | " "*) ;;
     *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;;
     esac],
    [_LT_TAGVAR(lt_prog_compiler_pic, $1)=
     _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no])
fi
_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1],
	[Additional compiler flags for building library objects])

_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1],
	[How to pass a linker flag through the compiler])
#
# Check to make sure the static flag actually works.
#
wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\"
_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works],
  _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1),
  $lt_tmp_static_flag,
  [],
  [_LT_TAGVAR(lt_prog_compiler_static, $1)=])
_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1],
	[Compiler flag to prevent dynamic linking])
])# _LT_COMPILER_PIC


# _LT_LINKER_SHLIBS([TAGNAME])
# ----------------------------
# See if the linker supports building shared libraries.
m4_defun([_LT_LINKER_SHLIBS],
[AC_REQUIRE([LT_PATH_LD])dnl
AC_REQUIRE([LT_PATH_NM])dnl
m4_require([_LT_PATH_MANIFEST_TOOL])dnl
m4_require([_LT_FILEUTILS_DEFAULTS])dnl
m4_require([_LT_DECL_EGREP])dnl
m4_require([_LT_DECL_SED])dnl
m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
m4_require([_LT_TAG_COMPILER])dnl
AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
m4_if([$1], [CXX], [
  _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
  _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
  case $host_os in
  aix[[4-9]]*)
    # If we're using GNU nm, then we don't want the "-C" option.
    # -C means demangle to GNU nm, but means don't demangle to AIX nm.
    # Without the "-l" option, or with the "-B" option, AIX nm treats
    # weak defined symbols like other global defined symbols, whereas
    # GNU nm marks them as "W".
    # While the 'weak' keyword is ignored in the Export File, we need
    # it in the Import File for the 'aix-soname' feature, so we have
    # to replace the "-B" option with "-P" for AIX nm.
    if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
      _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
    else
      _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
    fi
    ;;
  pw32*)
    _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds
    ;;
  cygwin* | mingw* | cegcc*)
    case $cc_basename in
    cl*)
      _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
      ;;
    *)
      _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
      _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname']
      ;;
    esac
    ;;
  linux* | k*bsd*-gnu | gnu*)
    _LT_TAGVAR(link_all_deplibs, $1)=no
    ;;
  *)
    _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
    ;;
  esac
], [
  runpath_var=
  _LT_TAGVAR(allow_undefined_flag, $1)=
  _LT_TAGVAR(always_export_symbols, $1)=no
  _LT_TAGVAR(archive_cmds, $1)=
  _LT_TAGVAR(archive_expsym_cmds, $1)=
  _LT_TAGVAR(compiler_needs_object, $1)=no
  _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
  _LT_TAGVAR(export_dynamic_flag_spec, $1)=
  _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
  _LT_TAGVAR(hardcode_automatic, $1)=no
  _LT_TAGVAR(hardcode_direct, $1)=no
  _LT_TAGVAR(hardcode_direct_absolute, $1)=no
  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
  _LT_TAGVAR(hardcode_libdir_separator, $1)=
  _LT_TAGVAR(hardcode_minus_L, $1)=no
  _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
  _LT_TAGVAR(inherit_rpath, $1)=no
  _LT_TAGVAR(link_all_deplibs, $1)=unknown
  _LT_TAGVAR(module_cmds, $1)=
  _LT_TAGVAR(module_expsym_cmds, $1)=
  _LT_TAGVAR(old_archive_from_new_cmds, $1)=
  _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)=
  _LT_TAGVAR(thread_safe_flag_spec, $1)=
  _LT_TAGVAR(whole_archive_flag_spec, $1)=
  # include_expsyms should be a list of space-separated symbols to be *always*
  # included in the symbol list
  _LT_TAGVAR(include_expsyms, $1)=
  # exclude_expsyms can be an extended regexp of symbols to exclude
  # it will be wrapped by ' (' and ')$', so one must not match beginning or
  # end of line.  Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc',
  # as well as any symbol that contains 'd'.
  _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
  # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
  # platforms (ab)use it in PIC code, but their linkers get confused if
  # the symbol is explicitly referenced.  Since portable code cannot
  # rely on this symbol name, it's probably fine to never include it in
  # preloaded symbol tables.
  # Exclude shared library initialization/finalization symbols.
dnl Note also adjust exclude_expsyms for C++ above.
  extract_expsyms_cmds=

  case $host_os in
  cygwin* | mingw* | pw32* | cegcc*)
    # FIXME: the MSVC++ port hasn't been tested in a loooong time
    # When not using gcc, we currently assume that we are using
    # Microsoft Visual C++.
    if test yes != "$GCC"; then
      with_gnu_ld=no
    fi
    ;;
  interix*)
    # we just hope/assume this is gcc and not c89 (= MSVC++)
    with_gnu_ld=yes
    ;;
  openbsd* | bitrig*)
    with_gnu_ld=no
    ;;
  linux* | k*bsd*-gnu | gnu*)
    _LT_TAGVAR(link_all_deplibs, $1)=no
    ;;
  esac

  _LT_TAGVAR(ld_shlibs, $1)=yes

  # On some targets, GNU ld is compatible enough with the native linker
  # that we're better off using the native interface for both.
  lt_use_gnu_ld_interface=no
  if test yes = "$with_gnu_ld"; then
    case $host_os in
      aix*)
	# The AIX port of GNU ld has always aspired to compatibility
	# with the native linker.  However, as the warning in the GNU ld
	# block says, versions before 2.19.5* couldn't really create working
	# shared libraries, regardless of the interface used.
	case `$LD -v 2>&1` in
	  *\ \(GNU\ Binutils\)\ 2.19.5*) ;;
	  *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;;
	  *\ \(GNU\ Binutils\)\ [[3-9]]*) ;;
	  *)
	    lt_use_gnu_ld_interface=yes
	    ;;
	esac
	;;
      *)
	lt_use_gnu_ld_interface=yes
	;;
    esac
  fi

  if test yes = "$lt_use_gnu_ld_interface"; then
    # If archive_cmds runs LD, not CC, wlarc should be empty
    wlarc='$wl'

    # Set some defaults for GNU ld with shared library support. These
    # are reset later if shared libraries are not supported. Putting them
    # here allows them to be overridden if necessary.
    runpath_var=LD_RUN_PATH
    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
    _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
    # ancient GNU ld didn't support --whole-archive et. al.
    if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
      _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
    else
      _LT_TAGVAR(whole_archive_flag_spec, $1)=
    fi
    supports_anon_versioning=no
    case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in
      *GNU\ gold*) supports_anon_versioning=yes ;;
      *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
      *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
      *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
      *\ 2.11.*) ;; # other 2.11 versions
      *) supports_anon_versioning=yes ;;
    esac

    # See if GNU ld supports shared libraries.
    case $host_os in
    aix[[3-9]]*)
      # On AIX/PPC, the GNU linker is very broken
      if test ia64 != "$host_cpu"; then
	_LT_TAGVAR(ld_shlibs, $1)=no
	cat <<_LT_EOF 1>&2

*** Warning: the GNU linker, at least up to release 2.19, is reported
*** to be unable to reliably create shared libraries on AIX.
*** Therefore, libtool is disabling shared libraries support.  If you
*** really care for shared libraries, you may want to install binutils
*** 2.20 or above, or modify your PATH so that a non-GNU linker is found.
*** You will then need to restart the configuration process.

_LT_EOF
      fi
      ;;

    amigaos*)
      case $host_cpu in
      powerpc)
            # see comment about AmigaOS4 .so support
            _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
            _LT_TAGVAR(archive_expsym_cmds, $1)=''
        ;;
      m68k)
            _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
            _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
            _LT_TAGVAR(hardcode_minus_L, $1)=yes
        ;;
      esac
      ;;

    beos*)
      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
	_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
	# Joseph Beckenbach  says some releases of gcc
	# support --undefined.  This deserves some investigation.  FIXME
	_LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
      else
	_LT_TAGVAR(ld_shlibs, $1)=no
      fi
      ;;

    cygwin* | mingw* | pw32* | cegcc*)
      # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
      # as there is no search path for DLLs.
      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
      _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols'
      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
      _LT_TAGVAR(always_export_symbols, $1)=no
      _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
      _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
      _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname']

      if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
	# If the export-symbols file already is a .def file, use it as
	# is; otherwise, prepend EXPORTS...
	_LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
          cp $export_symbols $output_objdir/$soname.def;
        else
          echo EXPORTS > $output_objdir/$soname.def;
          cat $export_symbols >> $output_objdir/$soname.def;
        fi~
        $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
      else
	_LT_TAGVAR(ld_shlibs, $1)=no
      fi
      ;;

    haiku*)
      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
      _LT_TAGVAR(link_all_deplibs, $1)=yes
      ;;

    os2*)
      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
      _LT_TAGVAR(hardcode_minus_L, $1)=yes
      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
      shrext_cmds=.dll
      _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
	$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
	$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
	$ECHO EXPORTS >> $output_objdir/$libname.def~
	emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
	$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
	emximp -o $lib $output_objdir/$libname.def'
      _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
	$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
	$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
	$ECHO EXPORTS >> $output_objdir/$libname.def~
	prefix_cmds="$SED"~
	if test EXPORTS = "`$SED 1q $export_symbols`"; then
	  prefix_cmds="$prefix_cmds -e 1d";
	fi~
	prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
	cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
	$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
	emximp -o $lib $output_objdir/$libname.def'
      _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
      _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
      ;;

    interix[[3-9]]*)
      _LT_TAGVAR(hardcode_direct, $1)=no
      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
      _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
      # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
      # Instead, shared libraries are loaded at an image base (0x10000000 by
      # default) and relocated if they conflict, which is a slow very memory
      # consuming and fragmenting process.  To avoid this, we pick a random,
      # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
      # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
      _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
      ;;

    gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
      tmp_diet=no
      if test linux-dietlibc = "$host_os"; then
	case $cc_basename in
	  diet\ *) tmp_diet=yes;;	# linux-dietlibc with static linking (!diet-dyn)
	esac
      fi
      if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
	 && test no = "$tmp_diet"
      then
	tmp_addflag=' $pic_flag'
	tmp_sharedflag='-shared'
	case $cc_basename,$host_cpu in
        pgcc*)				# Portland Group C compiler
	  _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
	  tmp_addflag=' $pic_flag'
	  ;;
	pgf77* | pgf90* | pgf95* | pgfortran*)
					# Portland Group f77 and f90 compilers
	  _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
	  tmp_addflag=' $pic_flag -Mnomain' ;;
	ecc*,ia64* | icc*,ia64*)	# Intel C compiler on ia64
	  tmp_addflag=' -i_dynamic' ;;
	efc*,ia64* | ifort*,ia64*)	# Intel Fortran compiler on ia64
	  tmp_addflag=' -i_dynamic -nofor_main' ;;
	ifc* | ifort*)			# Intel Fortran compiler
	  tmp_addflag=' -nofor_main' ;;
	lf95*)				# Lahey Fortran 8.1
	  _LT_TAGVAR(whole_archive_flag_spec, $1)=
	  tmp_sharedflag='--shared' ;;
        nagfor*)                        # NAGFOR 5.3
          tmp_sharedflag='-Wl,-shared' ;;
	xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below)
	  tmp_sharedflag='-qmkshrobj'
	  tmp_addflag= ;;
	nvcc*)	# Cuda Compiler Driver 2.2
	  _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
	  _LT_TAGVAR(compiler_needs_object, $1)=yes
	  ;;
	esac
	case `$CC -V 2>&1 | sed 5q` in
	*Sun\ C*)			# Sun C 5.9
	  _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
	  _LT_TAGVAR(compiler_needs_object, $1)=yes
	  tmp_sharedflag='-G' ;;
	*Sun\ F*)			# Sun Fortran 8.3
	  tmp_sharedflag='-G' ;;
	esac
	_LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'

        if test yes = "$supports_anon_versioning"; then
          _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
            cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
            echo "local: *; };" >> $output_objdir/$libname.ver~
            $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
        fi

	case $cc_basename in
	tcc*)
	  _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic'
	  ;;
	xlf* | bgf* | bgxlf* | mpixlf*)
	  # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
	  _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive'
	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
	  _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib'
	  if test yes = "$supports_anon_versioning"; then
	    _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
              cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
              echo "local: *; };" >> $output_objdir/$libname.ver~
              $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
	  fi
	  ;;
	esac
      else
        _LT_TAGVAR(ld_shlibs, $1)=no
      fi
      ;;

    netbsd* | netbsdelf*-gnu)
      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
	_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
	wlarc=
      else
	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
      fi
      ;;

    solaris*)
      if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
	_LT_TAGVAR(ld_shlibs, $1)=no
	cat <<_LT_EOF 1>&2

*** Warning: The releases 2.8.* of the GNU linker cannot reliably
*** create shared libraries on Solaris systems.  Therefore, libtool
*** is disabling shared libraries support.  We urge you to upgrade GNU
*** binutils to release 2.9.1 or newer.  Another option is to modify
*** your PATH or compiler configuration so that the native linker is
*** used, and then restart.

_LT_EOF
      elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
      else
	_LT_TAGVAR(ld_shlibs, $1)=no
      fi
      ;;

    sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
      case `$LD -v 2>&1` in
        *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*)
	_LT_TAGVAR(ld_shlibs, $1)=no
	cat <<_LT_EOF 1>&2

*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot
*** reliably create shared libraries on SCO systems.  Therefore, libtool
*** is disabling shared libraries support.  We urge you to upgrade GNU
*** binutils to release 2.16.91.0.3 or newer.  Another option is to modify
*** your PATH or compiler configuration so that the native linker is
*** used, and then restart.

_LT_EOF
	;;
	*)
	  # For security reasons, it is highly recommended that you always
	  # use absolute paths for naming shared libraries, and exclude the
	  # DT_RUNPATH tag from executables and libraries.  But doing so
	  # requires that you compile everything twice, which is a pain.
	  if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
	  else
	    _LT_TAGVAR(ld_shlibs, $1)=no
	  fi
	;;
      esac
      ;;

    sunos4*)
      _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
      wlarc=
      _LT_TAGVAR(hardcode_direct, $1)=yes
      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
      ;;

    *)
      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
      else
	_LT_TAGVAR(ld_shlibs, $1)=no
      fi
      ;;
    esac

    if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then
      runpath_var=
      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
      _LT_TAGVAR(export_dynamic_flag_spec, $1)=
      _LT_TAGVAR(whole_archive_flag_spec, $1)=
    fi
  else
    # PORTME fill in a description of your system's linker (not GNU ld)
    case $host_os in
    aix3*)
      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
      _LT_TAGVAR(always_export_symbols, $1)=yes
      _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
      # Note: this linker hardcodes the directories in LIBPATH if there
      # are no directories specified by -L.
      _LT_TAGVAR(hardcode_minus_L, $1)=yes
      if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then
	# Neither direct hardcoding nor static linking is supported with a
	# broken collect2.
	_LT_TAGVAR(hardcode_direct, $1)=unsupported
      fi
      ;;

    aix[[4-9]]*)
      if test ia64 = "$host_cpu"; then
	# On IA64, the linker does run time linking by default, so we don't
	# have to do anything special.
	aix_use_runtimelinking=no
	exp_sym_flag='-Bexport'
	no_entry_flag=
      else
	# If we're using GNU nm, then we don't want the "-C" option.
	# -C means demangle to GNU nm, but means don't demangle to AIX nm.
	# Without the "-l" option, or with the "-B" option, AIX nm treats
	# weak defined symbols like other global defined symbols, whereas
	# GNU nm marks them as "W".
	# While the 'weak' keyword is ignored in the Export File, we need
	# it in the Import File for the 'aix-soname' feature, so we have
	# to replace the "-B" option with "-P" for AIX nm.
	if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
	  _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
	else
	  _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
	fi
	aix_use_runtimelinking=no

	# Test if we are trying to use run time linking or normal
	# AIX style linking. If -brtl is somewhere in LDFLAGS, we
	# have runtime linking enabled, and use it for executables.
	# For shared libraries, we enable/disable runtime linking
	# depending on the kind of the shared library created -
	# when "with_aix_soname,aix_use_runtimelinking" is:
	# "aix,no"   lib.a(lib.so.V) shared, rtl:no,  for executables
	# "aix,yes"  lib.so          shared, rtl:yes, for executables
	#            lib.a           static archive
	# "both,no"  lib.so.V(shr.o) shared, rtl:yes
	#            lib.a(lib.so.V) shared, rtl:no,  for executables
	# "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables
	#            lib.a(lib.so.V) shared, rtl:no
	# "svr4,*"   lib.so.V(shr.o) shared, rtl:yes, for executables
	#            lib.a           static archive
	case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
	  for ld_flag in $LDFLAGS; do
	  if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then
	    aix_use_runtimelinking=yes
	    break
	  fi
	  done
	  if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then
	    # With aix-soname=svr4, we create the lib.so.V shared archives only,
	    # so we don't have lib.a shared libs to link our executables.
	    # We have to force runtime linking in this case.
	    aix_use_runtimelinking=yes
	    LDFLAGS="$LDFLAGS -Wl,-brtl"
	  fi
	  ;;
	esac

	exp_sym_flag='-bexport'
	no_entry_flag='-bnoentry'
      fi

      # When large executables or shared objects are built, AIX ld can
      # have problems creating the table of contents.  If linking a library
      # or program results in "error TOC overflow" add -mminimal-toc to
      # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
      # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.

      _LT_TAGVAR(archive_cmds, $1)=''
      _LT_TAGVAR(hardcode_direct, $1)=yes
      _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
      _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
      _LT_TAGVAR(link_all_deplibs, $1)=yes
      _LT_TAGVAR(file_list_spec, $1)='$wl-f,'
      case $with_aix_soname,$aix_use_runtimelinking in
      aix,*) ;; # traditional, no import file
      svr4,* | *,yes) # use import file
	# The Import File defines what to hardcode.
	_LT_TAGVAR(hardcode_direct, $1)=no
	_LT_TAGVAR(hardcode_direct_absolute, $1)=no
	;;
      esac

      if test yes = "$GCC"; then
	case $host_os in aix4.[[012]]|aix4.[[012]].*)
	# We only want to do this on AIX 4.2 and lower, the check
	# below for broken collect2 doesn't work under 4.3+
	  collect2name=`$CC -print-prog-name=collect2`
	  if test -f "$collect2name" &&
	   strings "$collect2name" | $GREP resolve_lib_name >/dev/null
	  then
	  # We have reworked collect2
	  :
	  else
	  # We have old collect2
	  _LT_TAGVAR(hardcode_direct, $1)=unsupported
	  # It fails to find uninstalled libraries when the uninstalled
	  # path is not listed in the libpath.  Setting hardcode_minus_L
	  # to unsupported forces relinking
	  _LT_TAGVAR(hardcode_minus_L, $1)=yes
	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
	  _LT_TAGVAR(hardcode_libdir_separator, $1)=
	  fi
	  ;;
	esac
	shared_flag='-shared'
	if test yes = "$aix_use_runtimelinking"; then
	  shared_flag="$shared_flag "'$wl-G'
	fi
	# Need to ensure runtime linking is disabled for the traditional
	# shared library, or the linker may eventually find shared libraries
	# /with/ Import File - we do not want to mix them.
	shared_flag_aix='-shared'
	shared_flag_svr4='-shared $wl-G'
      else
	# not using gcc
	if test ia64 = "$host_cpu"; then
	# VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
	# chokes on -Wl,-G. The following line is correct:
	  shared_flag='-G'
	else
	  if test yes = "$aix_use_runtimelinking"; then
	    shared_flag='$wl-G'
	  else
	    shared_flag='$wl-bM:SRE'
	  fi
	  shared_flag_aix='$wl-bM:SRE'
	  shared_flag_svr4='$wl-G'
	fi
      fi

      _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall'
      # It seems that -bexpall does not export symbols beginning with
      # underscore (_), so it is better to generate a list of symbols to export.
      _LT_TAGVAR(always_export_symbols, $1)=yes
      if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then
	# Warning - without using the other runtime loading flags (-brtl),
	# -berok will link without error, but may produce a broken library.
	_LT_TAGVAR(allow_undefined_flag, $1)='-berok'
        # Determine the default libpath from the value encoded in an
        # empty executable.
        _LT_SYS_MODULE_PATH_AIX([$1])
        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
        _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag
      else
	if test ia64 = "$host_cpu"; then
	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib'
	  _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
	  _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols"
	else
	 # Determine the default libpath from the value encoded in an
	 # empty executable.
	 _LT_SYS_MODULE_PATH_AIX([$1])
	 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
	  # Warning - without using the other run time loading flags,
	  # -berok will link without error, but may produce a broken library.
	  _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok'
	  _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok'
	  if test yes = "$with_gnu_ld"; then
	    # We only use this code for GNU lds that support --whole-archive.
	    _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive'
	  else
	    # Exported symbols can be pulled into shared objects from archives
	    _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
	  fi
	  _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
	  _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d'
	  # -brtl affects multiple linker settings, -berok does not and is overridden later
	  compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`'
	  if test svr4 != "$with_aix_soname"; then
	    # This is similar to how AIX traditionally builds its shared libraries.
	    _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname'
	  fi
	  if test aix != "$with_aix_soname"; then
	    _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp'
	  else
	    # used by -dlpreopen to get the symbols
	    _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV  $output_objdir/$realname.d/$soname $output_objdir'
	  fi
	  _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d'
	fi
      fi
      ;;

    amigaos*)
      case $host_cpu in
      powerpc)
            # see comment about AmigaOS4 .so support
            _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
            _LT_TAGVAR(archive_expsym_cmds, $1)=''
        ;;
      m68k)
            _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
            _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
            _LT_TAGVAR(hardcode_minus_L, $1)=yes
        ;;
      esac
      ;;

    bsdi[[45]]*)
      _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic
      ;;

    cygwin* | mingw* | pw32* | cegcc*)
      # When not using gcc, we currently assume that we are using
      # Microsoft Visual C++.
      # hardcode_libdir_flag_spec is actually meaningless, as there is
      # no search path for DLLs.
      case $cc_basename in
      cl*)
	# Native MSVC
	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
	_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
	_LT_TAGVAR(always_export_symbols, $1)=yes
	_LT_TAGVAR(file_list_spec, $1)='@'
	# Tell ltmain to make .lib files, not .a files.
	libext=lib
	# Tell ltmain to make .dll files, not .so files.
	shrext_cmds=.dll
	# FIXME: Setting linknames here is a bad hack.
	_LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
	_LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
            cp "$export_symbols" "$output_objdir/$soname.def";
            echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp";
          else
            $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp;
          fi~
          $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
          linknames='
	# The linker will not automatically build a static lib if we build a DLL.
	# _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
	_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
	_LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
	_LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols'
	# Don't use ranlib
	_LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib'
	_LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~
          lt_tool_outputfile="@TOOL_OUTPUT@"~
          case $lt_outputfile in
            *.exe|*.EXE) ;;
            *)
              lt_outputfile=$lt_outputfile.exe
              lt_tool_outputfile=$lt_tool_outputfile.exe
              ;;
          esac~
          if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then
            $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
            $RM "$lt_outputfile.manifest";
          fi'
	;;
      *)
	# Assume MSVC wrapper
	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
	_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
	# Tell ltmain to make .lib files, not .a files.
	libext=lib
	# Tell ltmain to make .dll files, not .so files.
	shrext_cmds=.dll
	# FIXME: Setting linknames here is a bad hack.
	_LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames='
	# The linker will automatically build a .lib file if we build a DLL.
	_LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
	# FIXME: Should let the user specify the lib program.
	_LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs'
	_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
	;;
      esac
      ;;

    darwin* | rhapsody*)
      _LT_DARWIN_LINKER_FEATURES($1)
      ;;

    dgux*)
      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
      ;;

    # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
    # support.  Future versions do this automatically, but an explicit c++rt0.o
    # does not break anything, and helps significantly (at the cost of a little
    # extra space).
    freebsd2.2*)
      _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
      _LT_TAGVAR(hardcode_direct, $1)=yes
      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
      ;;

    # Unfortunately, older versions of FreeBSD 2 do not have this feature.
    freebsd2.*)
      _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
      _LT_TAGVAR(hardcode_direct, $1)=yes
      _LT_TAGVAR(hardcode_minus_L, $1)=yes
      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
      ;;

    # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
    freebsd* | dragonfly*)
      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
      _LT_TAGVAR(hardcode_direct, $1)=yes
      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
      ;;

    hpux9*)
      if test yes = "$GCC"; then
	_LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
      else
	_LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
      fi
      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
      _LT_TAGVAR(hardcode_direct, $1)=yes

      # hardcode_minus_L: Not really in the search PATH,
      # but as the default location of the library.
      _LT_TAGVAR(hardcode_minus_L, $1)=yes
      _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
      ;;

    hpux10*)
      if test yes,no = "$GCC,$with_gnu_ld"; then
	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
      else
	_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
      fi
      if test no = "$with_gnu_ld"; then
	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
	_LT_TAGVAR(hardcode_libdir_separator, $1)=:
	_LT_TAGVAR(hardcode_direct, $1)=yes
	_LT_TAGVAR(hardcode_direct_absolute, $1)=yes
	_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
	# hardcode_minus_L: Not really in the search PATH,
	# but as the default location of the library.
	_LT_TAGVAR(hardcode_minus_L, $1)=yes
      fi
      ;;

    hpux11*)
      if test yes,no = "$GCC,$with_gnu_ld"; then
	case $host_cpu in
	hppa*64*)
	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
	  ;;
	ia64*)
	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
	  ;;
	*)
	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
	  ;;
	esac
      else
	case $host_cpu in
	hppa*64*)
	  _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
	  ;;
	ia64*)
	  _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
	  ;;
	*)
	m4_if($1, [], [
	  # Older versions of the 11.00 compiler do not understand -b yet
	  # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does)
	  _LT_LINKER_OPTION([if $CC understands -b],
	    _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b],
	    [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'],
	    [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])],
	  [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'])
	  ;;
	esac
      fi
      if test no = "$with_gnu_ld"; then
	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
	_LT_TAGVAR(hardcode_libdir_separator, $1)=:

	case $host_cpu in
	hppa*64*|ia64*)
	  _LT_TAGVAR(hardcode_direct, $1)=no
	  _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
	  ;;
	*)
	  _LT_TAGVAR(hardcode_direct, $1)=yes
	  _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
	  _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'

	  # hardcode_minus_L: Not really in the search PATH,
	  # but as the default location of the library.
	  _LT_TAGVAR(hardcode_minus_L, $1)=yes
	  ;;
	esac
      fi
      ;;

    irix5* | irix6* | nonstopux*)
      if test yes = "$GCC"; then
	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
	# Try to use the -exported_symbol ld option, if it does not
	# work, assume that -exports_file does not work either and
	# implicitly export all symbols.
	# This should be the same for all languages, so no per-tag cache variable.
	AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol],
	  [lt_cv_irix_exported_symbol],
	  [save_LDFLAGS=$LDFLAGS
	   LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null"
	   AC_LINK_IFELSE(
	     [AC_LANG_SOURCE(
	        [AC_LANG_CASE([C], [[int foo (void) { return 0; }]],
			      [C++], [[int foo (void) { return 0; }]],
			      [Fortran 77], [[
      subroutine foo
      end]],
			      [Fortran], [[
      subroutine foo
      end]])])],
	      [lt_cv_irix_exported_symbol=yes],
	      [lt_cv_irix_exported_symbol=no])
           LDFLAGS=$save_LDFLAGS])
	if test yes = "$lt_cv_irix_exported_symbol"; then
          _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib'
	fi
	_LT_TAGVAR(link_all_deplibs, $1)=no
      else
	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib'
      fi
      _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
      _LT_TAGVAR(inherit_rpath, $1)=yes
      _LT_TAGVAR(link_all_deplibs, $1)=yes
      ;;

    linux*)
      case $cc_basename in
      tcc*)
	# Fabrice Bellard et al's Tiny C Compiler
	_LT_TAGVAR(ld_shlibs, $1)=yes
	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
	;;
      esac
      ;;

    netbsd* | netbsdelf*-gnu)
      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
	_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
      else
	_LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
      fi
      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
      _LT_TAGVAR(hardcode_direct, $1)=yes
      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
      ;;

    newsos6)
      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
      _LT_TAGVAR(hardcode_direct, $1)=yes
      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
      ;;

    *nto* | *qnx*)
      ;;

    openbsd* | bitrig*)
      if test -f /usr/libexec/ld.so; then
	_LT_TAGVAR(hardcode_direct, $1)=yes
	_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
	_LT_TAGVAR(hardcode_direct_absolute, $1)=yes
	if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
	  _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols'
	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
	  _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
	else
	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
	fi
      else
	_LT_TAGVAR(ld_shlibs, $1)=no
      fi
      ;;

    os2*)
      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
      _LT_TAGVAR(hardcode_minus_L, $1)=yes
      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
      shrext_cmds=.dll
      _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
	$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
	$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
	$ECHO EXPORTS >> $output_objdir/$libname.def~
	emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
	$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
	emximp -o $lib $output_objdir/$libname.def'
      _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
	$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
	$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
	$ECHO EXPORTS >> $output_objdir/$libname.def~
	prefix_cmds="$SED"~
	if test EXPORTS = "`$SED 1q $export_symbols`"; then
	  prefix_cmds="$prefix_cmds -e 1d";
	fi~
	prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
	cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
	$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
	emximp -o $lib $output_objdir/$libname.def'
      _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
      _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
      ;;

    osf3*)
      if test yes = "$GCC"; then
	_LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
	_LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
      else
	_LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
	_LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
      fi
      _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
      ;;

    osf4* | osf5*)	# as osf3* with the addition of -msym flag
      if test yes = "$GCC"; then
	_LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
	_LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
      else
	_LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
	_LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
	_LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
          $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp'

	# Both c and cxx compiler support -rpath directly
	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
      fi
      _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
      ;;

    solaris*)
      _LT_TAGVAR(no_undefined_flag, $1)=' -z defs'
      if test yes = "$GCC"; then
	wlarc='$wl'
	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
	_LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
          $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
      else
	case `$CC -V 2>&1` in
	*"Compilers 5.0"*)
	  wlarc=''
	  _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags'
	  _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
            $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
	  ;;
	*)
	  wlarc='$wl'
	  _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags'
	  _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
            $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
	  ;;
	esac
      fi
      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
      case $host_os in
      solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
      *)
	# The compiler driver will combine and reorder linker options,
	# but understands '-z linker_flag'.  GCC discards it without '$wl',
	# but is careful enough not to reorder.
	# Supported since Solaris 2.6 (maybe 2.5.1?)
	if test yes = "$GCC"; then
	  _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract'
	else
	  _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
	fi
	;;
      esac
      _LT_TAGVAR(link_all_deplibs, $1)=yes
      ;;

    sunos4*)
      if test sequent = "$host_vendor"; then
	# Use $CC to link under sequent, because it throws in some extra .o
	# files that make .init and .fini sections work.
	_LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags'
      else
	_LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
      fi
      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
      _LT_TAGVAR(hardcode_direct, $1)=yes
      _LT_TAGVAR(hardcode_minus_L, $1)=yes
      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
      ;;

    sysv4)
      case $host_vendor in
	sni)
	  _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
	  _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true???
	;;
	siemens)
	  ## LD is ld it makes a PLAMLIB
	  ## CC just makes a GrossModule.
	  _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
	  _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs'
	  _LT_TAGVAR(hardcode_direct, $1)=no
        ;;
	motorola)
	  _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
	  _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie
	;;
      esac
      runpath_var='LD_RUN_PATH'
      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
      ;;

    sysv4.3*)
      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
      _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport'
      ;;

    sysv4*MP*)
      if test -d /usr/nec; then
	_LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
	_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
	runpath_var=LD_RUN_PATH
	hardcode_runpath_var=yes
	_LT_TAGVAR(ld_shlibs, $1)=yes
      fi
      ;;

    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
      _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
      _LT_TAGVAR(archive_cmds_need_lc, $1)=no
      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
      runpath_var='LD_RUN_PATH'

      if test yes = "$GCC"; then
	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
      else
	_LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
      fi
      ;;

    sysv5* | sco3.2v5* | sco5v6*)
      # Note: We CANNOT use -z defs as we might desire, because we do not
      # link with -lc, and that would cause any symbols used from libc to
      # always be unresolved, which means just about no library would
      # ever link correctly.  If we're not using GNU ld we use -z text
      # though, which does catch some bad symbols but isn't as heavy-handed
      # as -z defs.
      _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
      _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs'
      _LT_TAGVAR(archive_cmds_need_lc, $1)=no
      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir'
      _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
      _LT_TAGVAR(link_all_deplibs, $1)=yes
      _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport'
      runpath_var='LD_RUN_PATH'

      if test yes = "$GCC"; then
	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
      else
	_LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
      fi
      ;;

    uts4*)
      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
      ;;

    *)
      _LT_TAGVAR(ld_shlibs, $1)=no
      ;;
    esac

    if test sni = "$host_vendor"; then
      case $host in
      sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
	_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym'
	;;
      esac
    fi
  fi
])
AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no

_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld

_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl
_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl
_LT_DECL([], [extract_expsyms_cmds], [2],
    [The commands to extract the exported symbol list from a shared archive])

#
# Do we need to explicitly link libc?
#
case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in
x|xyes)
  # Assume -lc should be added
  _LT_TAGVAR(archive_cmds_need_lc, $1)=yes

  if test yes,yes = "$GCC,$enable_shared"; then
    case $_LT_TAGVAR(archive_cmds, $1) in
    *'~'*)
      # FIXME: we may have to deal with multi-command sequences.
      ;;
    '$CC '*)
      # Test whether the compiler implicitly links with -lc since on some
      # systems, -lgcc has to come before -lc. If gcc already passes -lc
      # to ld, don't add -lc before -lgcc.
      AC_CACHE_CHECK([whether -lc should be explicitly linked in],
	[lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1),
	[$RM conftest*
	echo "$lt_simple_compile_test_code" > conftest.$ac_ext

	if AC_TRY_EVAL(ac_compile) 2>conftest.err; then
	  soname=conftest
	  lib=conftest
	  libobjs=conftest.$ac_objext
	  deplibs=
	  wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1)
	  pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1)
	  compiler_flags=-v
	  linker_flags=-v
	  verstring=
	  output_objdir=.
	  libname=conftest
	  lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1)
	  _LT_TAGVAR(allow_undefined_flag, $1)=
	  if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1)
	  then
	    lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no
	  else
	    lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes
	  fi
	  _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag
	else
	  cat conftest.err 1>&5
	fi
	$RM conftest*
	])
      _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)
      ;;
    esac
  fi
  ;;
esac

_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0],
    [Whether or not to add -lc for building shared libraries])
_LT_TAGDECL([allow_libtool_libs_with_static_runtimes],
    [enable_shared_with_static_runtimes], [0],
    [Whether or not to disallow shared libs when runtime libs are static])
_LT_TAGDECL([], [export_dynamic_flag_spec], [1],
    [Compiler flag to allow reflexive dlopens])
_LT_TAGDECL([], [whole_archive_flag_spec], [1],
    [Compiler flag to generate shared objects directly from archives])
_LT_TAGDECL([], [compiler_needs_object], [1],
    [Whether the compiler copes with passing no objects directly])
_LT_TAGDECL([], [old_archive_from_new_cmds], [2],
    [Create an old-style archive from a shared archive])
_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2],
    [Create a temporary old-style archive to link instead of a shared archive])
_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive])
_LT_TAGDECL([], [archive_expsym_cmds], [2])
_LT_TAGDECL([], [module_cmds], [2],
    [Commands used to build a loadable module if different from building
    a shared archive.])
_LT_TAGDECL([], [module_expsym_cmds], [2])
_LT_TAGDECL([], [with_gnu_ld], [1],
    [Whether we are building with GNU ld or not])
_LT_TAGDECL([], [allow_undefined_flag], [1],
    [Flag that allows shared libraries with undefined symbols to be built])
_LT_TAGDECL([], [no_undefined_flag], [1],
    [Flag that enforces no undefined symbols])
_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1],
    [Flag to hardcode $libdir into a binary during linking.
    This must work even if $libdir does not exist])
_LT_TAGDECL([], [hardcode_libdir_separator], [1],
    [Whether we need a single "-rpath" flag with a separated argument])
_LT_TAGDECL([], [hardcode_direct], [0],
    [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes
    DIR into the resulting binary])
_LT_TAGDECL([], [hardcode_direct_absolute], [0],
    [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes
    DIR into the resulting binary and the resulting library dependency is
    "absolute", i.e impossible to change by setting $shlibpath_var if the
    library is relocated])
_LT_TAGDECL([], [hardcode_minus_L], [0],
    [Set to "yes" if using the -LDIR flag during linking hardcodes DIR
    into the resulting binary])
_LT_TAGDECL([], [hardcode_shlibpath_var], [0],
    [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
    into the resulting binary])
_LT_TAGDECL([], [hardcode_automatic], [0],
    [Set to "yes" if building a shared library automatically hardcodes DIR
    into the library and all subsequent libraries and executables linked
    against it])
_LT_TAGDECL([], [inherit_rpath], [0],
    [Set to yes if linker adds runtime paths of dependent libraries
    to runtime path list])
_LT_TAGDECL([], [link_all_deplibs], [0],
    [Whether libtool must link a program against all its dependency libraries])
_LT_TAGDECL([], [always_export_symbols], [0],
    [Set to "yes" if exported symbols are required])
_LT_TAGDECL([], [export_symbols_cmds], [2],
    [The commands to list exported symbols])
_LT_TAGDECL([], [exclude_expsyms], [1],
    [Symbols that should not be listed in the preloaded symbols])
_LT_TAGDECL([], [include_expsyms], [1],
    [Symbols that must always be exported])
_LT_TAGDECL([], [prelink_cmds], [2],
    [Commands necessary for linking programs (against libraries) with templates])
_LT_TAGDECL([], [postlink_cmds], [2],
    [Commands necessary for finishing linking programs])
_LT_TAGDECL([], [file_list_spec], [1],
    [Specify filename containing input files])
dnl FIXME: Not yet implemented
dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1],
dnl    [Compiler flag to generate thread safe objects])
])# _LT_LINKER_SHLIBS


# _LT_LANG_C_CONFIG([TAG])
# ------------------------
# Ensure that the configuration variables for a C compiler are suitably
# defined.  These variables are subsequently used by _LT_CONFIG to write
# the compiler configuration to 'libtool'.
m4_defun([_LT_LANG_C_CONFIG],
[m4_require([_LT_DECL_EGREP])dnl
lt_save_CC=$CC
AC_LANG_PUSH(C)

# Source file extension for C test sources.
ac_ext=c

# Object file extension for compiled C test sources.
objext=o
_LT_TAGVAR(objext, $1)=$objext

# Code to be used in simple compile tests
lt_simple_compile_test_code="int some_variable = 0;"

# Code to be used in simple link tests
lt_simple_link_test_code='int main(){return(0);}'

_LT_TAG_COMPILER
# Save the default compiler, since it gets overwritten when the other
# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
compiler_DEFAULT=$CC

# save warnings/boilerplate of simple test code
_LT_COMPILER_BOILERPLATE
_LT_LINKER_BOILERPLATE

## CAVEAT EMPTOR:
## There is no encapsulation within the following macros, do not change
## the running order or otherwise move them around unless you know exactly
## what you are doing...
if test -n "$compiler"; then
  _LT_COMPILER_NO_RTTI($1)
  _LT_COMPILER_PIC($1)
  _LT_COMPILER_C_O($1)
  _LT_COMPILER_FILE_LOCKS($1)
  _LT_LINKER_SHLIBS($1)
  _LT_SYS_DYNAMIC_LINKER($1)
  _LT_LINKER_HARDCODE_LIBPATH($1)
  LT_SYS_DLOPEN_SELF
  _LT_CMD_STRIPLIB

  # Report what library types will actually be built
  AC_MSG_CHECKING([if libtool supports shared libraries])
  AC_MSG_RESULT([$can_build_shared])

  AC_MSG_CHECKING([whether to build shared libraries])
  test no = "$can_build_shared" && enable_shared=no

  # On AIX, shared libraries and static libraries use the same namespace, and
  # are all built from PIC.
  case $host_os in
  aix3*)
    test yes = "$enable_shared" && enable_static=no
    if test -n "$RANLIB"; then
      archive_cmds="$archive_cmds~\$RANLIB \$lib"
      postinstall_cmds='$RANLIB $lib'
    fi
    ;;

  aix[[4-9]]*)
    if test ia64 != "$host_cpu"; then
      case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
      yes,aix,yes) ;;			# shared object as lib.so file only
      yes,svr4,*) ;;			# shared object as lib.so archive member only
      yes,*) enable_static=no ;;	# shared object in lib.a archive as well
      esac
    fi
    ;;
  esac
  AC_MSG_RESULT([$enable_shared])

  AC_MSG_CHECKING([whether to build static libraries])
  # Make sure either enable_shared or enable_static is yes.
  test yes = "$enable_shared" || enable_static=yes
  AC_MSG_RESULT([$enable_static])

  _LT_CONFIG($1)
fi
AC_LANG_POP
CC=$lt_save_CC
])# _LT_LANG_C_CONFIG


# _LT_LANG_CXX_CONFIG([TAG])
# --------------------------
# Ensure that the configuration variables for a C++ compiler are suitably
# defined.  These variables are subsequently used by _LT_CONFIG to write
# the compiler configuration to 'libtool'.
m4_defun([_LT_LANG_CXX_CONFIG],
[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
m4_require([_LT_DECL_EGREP])dnl
m4_require([_LT_PATH_MANIFEST_TOOL])dnl
if test -n "$CXX" && ( test no != "$CXX" &&
    ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) ||
    (test g++ != "$CXX"))); then
  AC_PROG_CXXCPP
else
  _lt_caught_CXX_error=yes
fi

AC_LANG_PUSH(C++)
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
_LT_TAGVAR(allow_undefined_flag, $1)=
_LT_TAGVAR(always_export_symbols, $1)=no
_LT_TAGVAR(archive_expsym_cmds, $1)=
_LT_TAGVAR(compiler_needs_object, $1)=no
_LT_TAGVAR(export_dynamic_flag_spec, $1)=
_LT_TAGVAR(hardcode_direct, $1)=no
_LT_TAGVAR(hardcode_direct_absolute, $1)=no
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
_LT_TAGVAR(hardcode_libdir_separator, $1)=
_LT_TAGVAR(hardcode_minus_L, $1)=no
_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
_LT_TAGVAR(hardcode_automatic, $1)=no
_LT_TAGVAR(inherit_rpath, $1)=no
_LT_TAGVAR(module_cmds, $1)=
_LT_TAGVAR(module_expsym_cmds, $1)=
_LT_TAGVAR(link_all_deplibs, $1)=unknown
_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
_LT_TAGVAR(reload_flag, $1)=$reload_flag
_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
_LT_TAGVAR(no_undefined_flag, $1)=
_LT_TAGVAR(whole_archive_flag_spec, $1)=
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no

# Source file extension for C++ test sources.
ac_ext=cpp

# Object file extension for compiled C++ test sources.
objext=o
_LT_TAGVAR(objext, $1)=$objext

# No sense in running all these tests if we already determined that
# the CXX compiler isn't working.  Some variables (like enable_shared)
# are currently assumed to apply to all compilers on this platform,
# and will be corrupted by setting them based on a non-working compiler.
if test yes != "$_lt_caught_CXX_error"; then
  # Code to be used in simple compile tests
  lt_simple_compile_test_code="int some_variable = 0;"

  # Code to be used in simple link tests
  lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }'

  # ltmain only uses $CC for tagged configurations so make sure $CC is set.
  _LT_TAG_COMPILER

  # save warnings/boilerplate of simple test code
  _LT_COMPILER_BOILERPLATE
  _LT_LINKER_BOILERPLATE

  # Allow CC to be a program name with arguments.
  lt_save_CC=$CC
  lt_save_CFLAGS=$CFLAGS
  lt_save_LD=$LD
  lt_save_GCC=$GCC
  GCC=$GXX
  lt_save_with_gnu_ld=$with_gnu_ld
  lt_save_path_LD=$lt_cv_path_LD
  if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
    lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
  else
    $as_unset lt_cv_prog_gnu_ld
  fi
  if test -n "${lt_cv_path_LDCXX+set}"; then
    lt_cv_path_LD=$lt_cv_path_LDCXX
  else
    $as_unset lt_cv_path_LD
  fi
  test -z "${LDCXX+set}" || LD=$LDCXX
  CC=${CXX-"c++"}
  CFLAGS=$CXXFLAGS
  compiler=$CC
  _LT_TAGVAR(compiler, $1)=$CC
  _LT_CC_BASENAME([$compiler])

  if test -n "$compiler"; then
    # We don't want -fno-exception when compiling C++ code, so set the
    # no_builtin_flag separately
    if test yes = "$GXX"; then
      _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
    else
      _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
    fi

    if test yes = "$GXX"; then
      # Set up default GNU C++ configuration

      LT_PATH_LD

      # Check if GNU C++ uses GNU ld as the underlying linker, since the
      # archiving commands below assume that GNU ld is being used.
      if test yes = "$with_gnu_ld"; then
        _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
        _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'

        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
        _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'

        # If archive_cmds runs LD, not CC, wlarc should be empty
        # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
        #     investigate it a little bit more. (MM)
        wlarc='$wl'

        # ancient GNU ld didn't support --whole-archive et. al.
        if eval "`$CC -print-prog-name=ld` --help 2>&1" |
	  $GREP 'no-whole-archive' > /dev/null; then
          _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
        else
          _LT_TAGVAR(whole_archive_flag_spec, $1)=
        fi
      else
        with_gnu_ld=no
        wlarc=

        # A generic and very simple default shared library creation
        # command for GNU C++ for the case where it uses the native
        # linker, instead of GNU ld.  If possible, this setting should
        # overridden to take advantage of the native linker features on
        # the platform it is being used on.
        _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
      fi

      # Commands to make compiler produce verbose output that lists
      # what "hidden" libraries, object files and flags are used when
      # linking a shared library.
      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'

    else
      GXX=no
      with_gnu_ld=no
      wlarc=
    fi

    # PORTME: fill in a description of your system's C++ link characteristics
    AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
    _LT_TAGVAR(ld_shlibs, $1)=yes
    case $host_os in
      aix3*)
        # FIXME: insert proper C++ library support
        _LT_TAGVAR(ld_shlibs, $1)=no
        ;;
      aix[[4-9]]*)
        if test ia64 = "$host_cpu"; then
          # On IA64, the linker does run time linking by default, so we don't
          # have to do anything special.
          aix_use_runtimelinking=no
          exp_sym_flag='-Bexport'
          no_entry_flag=
        else
          aix_use_runtimelinking=no

          # Test if we are trying to use run time linking or normal
          # AIX style linking. If -brtl is somewhere in LDFLAGS, we
          # have runtime linking enabled, and use it for executables.
          # For shared libraries, we enable/disable runtime linking
          # depending on the kind of the shared library created -
          # when "with_aix_soname,aix_use_runtimelinking" is:
          # "aix,no"   lib.a(lib.so.V) shared, rtl:no,  for executables
          # "aix,yes"  lib.so          shared, rtl:yes, for executables
          #            lib.a           static archive
          # "both,no"  lib.so.V(shr.o) shared, rtl:yes
          #            lib.a(lib.so.V) shared, rtl:no,  for executables
          # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables
          #            lib.a(lib.so.V) shared, rtl:no
          # "svr4,*"   lib.so.V(shr.o) shared, rtl:yes, for executables
          #            lib.a           static archive
          case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
	    for ld_flag in $LDFLAGS; do
	      case $ld_flag in
	      *-brtl*)
	        aix_use_runtimelinking=yes
	        break
	        ;;
	      esac
	    done
	    if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then
	      # With aix-soname=svr4, we create the lib.so.V shared archives only,
	      # so we don't have lib.a shared libs to link our executables.
	      # We have to force runtime linking in this case.
	      aix_use_runtimelinking=yes
	      LDFLAGS="$LDFLAGS -Wl,-brtl"
	    fi
	    ;;
          esac

          exp_sym_flag='-bexport'
          no_entry_flag='-bnoentry'
        fi

        # When large executables or shared objects are built, AIX ld can
        # have problems creating the table of contents.  If linking a library
        # or program results in "error TOC overflow" add -mminimal-toc to
        # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
        # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.

        _LT_TAGVAR(archive_cmds, $1)=''
        _LT_TAGVAR(hardcode_direct, $1)=yes
        _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
        _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
        _LT_TAGVAR(link_all_deplibs, $1)=yes
        _LT_TAGVAR(file_list_spec, $1)='$wl-f,'
        case $with_aix_soname,$aix_use_runtimelinking in
        aix,*) ;;	# no import file
        svr4,* | *,yes) # use import file
          # The Import File defines what to hardcode.
          _LT_TAGVAR(hardcode_direct, $1)=no
          _LT_TAGVAR(hardcode_direct_absolute, $1)=no
          ;;
        esac

        if test yes = "$GXX"; then
          case $host_os in aix4.[[012]]|aix4.[[012]].*)
          # We only want to do this on AIX 4.2 and lower, the check
          # below for broken collect2 doesn't work under 4.3+
	  collect2name=`$CC -print-prog-name=collect2`
	  if test -f "$collect2name" &&
	     strings "$collect2name" | $GREP resolve_lib_name >/dev/null
	  then
	    # We have reworked collect2
	    :
	  else
	    # We have old collect2
	    _LT_TAGVAR(hardcode_direct, $1)=unsupported
	    # It fails to find uninstalled libraries when the uninstalled
	    # path is not listed in the libpath.  Setting hardcode_minus_L
	    # to unsupported forces relinking
	    _LT_TAGVAR(hardcode_minus_L, $1)=yes
	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
	    _LT_TAGVAR(hardcode_libdir_separator, $1)=
	  fi
          esac
          shared_flag='-shared'
	  if test yes = "$aix_use_runtimelinking"; then
	    shared_flag=$shared_flag' $wl-G'
	  fi
	  # Need to ensure runtime linking is disabled for the traditional
	  # shared library, or the linker may eventually find shared libraries
	  # /with/ Import File - we do not want to mix them.
	  shared_flag_aix='-shared'
	  shared_flag_svr4='-shared $wl-G'
        else
          # not using gcc
          if test ia64 = "$host_cpu"; then
	  # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
	  # chokes on -Wl,-G. The following line is correct:
	  shared_flag='-G'
          else
	    if test yes = "$aix_use_runtimelinking"; then
	      shared_flag='$wl-G'
	    else
	      shared_flag='$wl-bM:SRE'
	    fi
	    shared_flag_aix='$wl-bM:SRE'
	    shared_flag_svr4='$wl-G'
          fi
        fi

        _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall'
        # It seems that -bexpall does not export symbols beginning with
        # underscore (_), so it is better to generate a list of symbols to
	# export.
        _LT_TAGVAR(always_export_symbols, $1)=yes
	if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then
          # Warning - without using the other runtime loading flags (-brtl),
          # -berok will link without error, but may produce a broken library.
          # The "-G" linker flag allows undefined symbols.
          _LT_TAGVAR(no_undefined_flag, $1)='-bernotok'
          # Determine the default libpath from the value encoded in an empty
          # executable.
          _LT_SYS_MODULE_PATH_AIX([$1])
          _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"

          _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag
        else
          if test ia64 = "$host_cpu"; then
	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib'
	    _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
	    _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols"
          else
	    # Determine the default libpath from the value encoded in an
	    # empty executable.
	    _LT_SYS_MODULE_PATH_AIX([$1])
	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
	    # Warning - without using the other run time loading flags,
	    # -berok will link without error, but may produce a broken library.
	    _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok'
	    _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok'
	    if test yes = "$with_gnu_ld"; then
	      # We only use this code for GNU lds that support --whole-archive.
	      _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive'
	    else
	      # Exported symbols can be pulled into shared objects from archives
	      _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
	    fi
	    _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
	    _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d'
	    # -brtl affects multiple linker settings, -berok does not and is overridden later
	    compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`'
	    if test svr4 != "$with_aix_soname"; then
	      # This is similar to how AIX traditionally builds its shared
	      # libraries. Need -bnortl late, we may have -brtl in LDFLAGS.
	      _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname'
	    fi
	    if test aix != "$with_aix_soname"; then
	      _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp'
	    else
	      # used by -dlpreopen to get the symbols
	      _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV  $output_objdir/$realname.d/$soname $output_objdir'
	    fi
	    _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d'
          fi
        fi
        ;;

      beos*)
	if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
	  _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
	  # Joseph Beckenbach  says some releases of gcc
	  # support --undefined.  This deserves some investigation.  FIXME
	  _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
	else
	  _LT_TAGVAR(ld_shlibs, $1)=no
	fi
	;;

      chorus*)
        case $cc_basename in
          *)
	  # FIXME: insert proper C++ library support
	  _LT_TAGVAR(ld_shlibs, $1)=no
	  ;;
        esac
        ;;

      cygwin* | mingw* | pw32* | cegcc*)
	case $GXX,$cc_basename in
	,cl* | no,cl*)
	  # Native MSVC
	  # hardcode_libdir_flag_spec is actually meaningless, as there is
	  # no search path for DLLs.
	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
	  _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
	  _LT_TAGVAR(always_export_symbols, $1)=yes
	  _LT_TAGVAR(file_list_spec, $1)='@'
	  # Tell ltmain to make .lib files, not .a files.
	  libext=lib
	  # Tell ltmain to make .dll files, not .so files.
	  shrext_cmds=.dll
	  # FIXME: Setting linknames here is a bad hack.
	  _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
	  _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
              cp "$export_symbols" "$output_objdir/$soname.def";
              echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp";
            else
              $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp;
            fi~
            $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
            linknames='
	  # The linker will not automatically build a static lib if we build a DLL.
	  # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
	  _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
	  # Don't use ranlib
	  _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib'
	  _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~
            lt_tool_outputfile="@TOOL_OUTPUT@"~
            case $lt_outputfile in
              *.exe|*.EXE) ;;
              *)
                lt_outputfile=$lt_outputfile.exe
                lt_tool_outputfile=$lt_tool_outputfile.exe
                ;;
            esac~
            func_to_tool_file "$lt_outputfile"~
            if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then
              $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
              $RM "$lt_outputfile.manifest";
            fi'
	  ;;
	*)
	  # g++
	  # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
	  # as there is no search path for DLLs.
	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
	  _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols'
	  _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
	  _LT_TAGVAR(always_export_symbols, $1)=no
	  _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes

	  if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
	    # If the export-symbols file already is a .def file, use it as
	    # is; otherwise, prepend EXPORTS...
	    _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
              cp $export_symbols $output_objdir/$soname.def;
            else
              echo EXPORTS > $output_objdir/$soname.def;
              cat $export_symbols >> $output_objdir/$soname.def;
            fi~
            $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
	  else
	    _LT_TAGVAR(ld_shlibs, $1)=no
	  fi
	  ;;
	esac
	;;
      darwin* | rhapsody*)
        _LT_DARWIN_LINKER_FEATURES($1)
	;;

      os2*)
	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
	_LT_TAGVAR(hardcode_minus_L, $1)=yes
	_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
	shrext_cmds=.dll
	_LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
	  $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
	  $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
	  $ECHO EXPORTS >> $output_objdir/$libname.def~
	  emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
	  $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
	  emximp -o $lib $output_objdir/$libname.def'
	_LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
	  $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
	  $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
	  $ECHO EXPORTS >> $output_objdir/$libname.def~
	  prefix_cmds="$SED"~
	  if test EXPORTS = "`$SED 1q $export_symbols`"; then
	    prefix_cmds="$prefix_cmds -e 1d";
	  fi~
	  prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
	  cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
	  $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
	  emximp -o $lib $output_objdir/$libname.def'
	_LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
	_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
	;;

      dgux*)
        case $cc_basename in
          ec++*)
	    # FIXME: insert proper C++ library support
	    _LT_TAGVAR(ld_shlibs, $1)=no
	    ;;
          ghcx*)
	    # Green Hills C++ Compiler
	    # FIXME: insert proper C++ library support
	    _LT_TAGVAR(ld_shlibs, $1)=no
	    ;;
          *)
	    # FIXME: insert proper C++ library support
	    _LT_TAGVAR(ld_shlibs, $1)=no
	    ;;
        esac
        ;;

      freebsd2.*)
        # C++ shared libraries reported to be fairly broken before
	# switch to ELF
        _LT_TAGVAR(ld_shlibs, $1)=no
        ;;

      freebsd-elf*)
        _LT_TAGVAR(archive_cmds_need_lc, $1)=no
        ;;

      freebsd* | dragonfly*)
        # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
        # conventions
        _LT_TAGVAR(ld_shlibs, $1)=yes
        ;;

      haiku*)
        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
        _LT_TAGVAR(link_all_deplibs, $1)=yes
        ;;

      hpux9*)
        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
        _LT_TAGVAR(hardcode_libdir_separator, $1)=:
        _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
        _LT_TAGVAR(hardcode_direct, $1)=yes
        _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
				             # but as the default
				             # location of the library.

        case $cc_basename in
          CC*)
            # FIXME: insert proper C++ library support
            _LT_TAGVAR(ld_shlibs, $1)=no
            ;;
          aCC*)
            _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
            # Commands to make compiler produce verbose output that lists
            # what "hidden" libraries, object files and flags are used when
            # linking a shared library.
            #
            # There doesn't appear to be a way to prevent this compiler from
            # explicitly linking system object files so we need to strip them
            # from the output so that they don't get included in the library
            # dependencies.
            output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
            ;;
          *)
            if test yes = "$GXX"; then
              _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
            else
              # FIXME: insert proper C++ library support
              _LT_TAGVAR(ld_shlibs, $1)=no
            fi
            ;;
        esac
        ;;

      hpux10*|hpux11*)
        if test no = "$with_gnu_ld"; then
	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
	  _LT_TAGVAR(hardcode_libdir_separator, $1)=:

          case $host_cpu in
            hppa*64*|ia64*)
              ;;
            *)
	      _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
              ;;
          esac
        fi
        case $host_cpu in
          hppa*64*|ia64*)
            _LT_TAGVAR(hardcode_direct, $1)=no
            _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
            ;;
          *)
            _LT_TAGVAR(hardcode_direct, $1)=yes
            _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
            _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
					         # but as the default
					         # location of the library.
            ;;
        esac

        case $cc_basename in
          CC*)
	    # FIXME: insert proper C++ library support
	    _LT_TAGVAR(ld_shlibs, $1)=no
	    ;;
          aCC*)
	    case $host_cpu in
	      hppa*64*)
	        _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
	        ;;
	      ia64*)
	        _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
	        ;;
	      *)
	        _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
	        ;;
	    esac
	    # Commands to make compiler produce verbose output that lists
	    # what "hidden" libraries, object files and flags are used when
	    # linking a shared library.
	    #
	    # There doesn't appear to be a way to prevent this compiler from
	    # explicitly linking system object files so we need to strip them
	    # from the output so that they don't get included in the library
	    # dependencies.
	    output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
	    ;;
          *)
	    if test yes = "$GXX"; then
	      if test no = "$with_gnu_ld"; then
	        case $host_cpu in
	          hppa*64*)
	            _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
	            ;;
	          ia64*)
	            _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
	            ;;
	          *)
	            _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
	            ;;
	        esac
	      fi
	    else
	      # FIXME: insert proper C++ library support
	      _LT_TAGVAR(ld_shlibs, $1)=no
	    fi
	    ;;
        esac
        ;;

      interix[[3-9]]*)
	_LT_TAGVAR(hardcode_direct, $1)=no
	_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
	_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
	# Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
	# Instead, shared libraries are loaded at an image base (0x10000000 by
	# default) and relocated if they conflict, which is a slow very memory
	# consuming and fragmenting process.  To avoid this, we pick a random,
	# 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
	# time.  Moving up from 0x10000000 also allows more sbrk(2) space.
	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
	_LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
	;;
      irix5* | irix6*)
        case $cc_basename in
          CC*)
	    # SGI C++
	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'

	    # Archives containing C++ object files must be created using
	    # "CC -ar", where "CC" is the IRIX C++ compiler.  This is
	    # necessary to make sure instantiated templates are included
	    # in the archive.
	    _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs'
	    ;;
          *)
	    if test yes = "$GXX"; then
	      if test no = "$with_gnu_ld"; then
	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
	      else
	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib'
	      fi
	    fi
	    _LT_TAGVAR(link_all_deplibs, $1)=yes
	    ;;
        esac
        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
        _LT_TAGVAR(hardcode_libdir_separator, $1)=:
        _LT_TAGVAR(inherit_rpath, $1)=yes
        ;;

      linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
        case $cc_basename in
          KCC*)
	    # Kuck and Associates, Inc. (KAI) C++ Compiler

	    # KCC will only create a shared library if the output file
	    # ends with ".so" (or ".sl" for HP-UX), so rename the library
	    # to its proper name (with version) after linking.
	    _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
	    _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib'
	    # Commands to make compiler produce verbose output that lists
	    # what "hidden" libraries, object files and flags are used when
	    # linking a shared library.
	    #
	    # There doesn't appear to be a way to prevent this compiler from
	    # explicitly linking system object files so we need to strip them
	    # from the output so that they don't get included in the library
	    # dependencies.
	    output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'

	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'

	    # Archives containing C++ object files must be created using
	    # "CC -Bstatic", where "CC" is the KAI C++ compiler.
	    _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
	    ;;
	  icpc* | ecpc* )
	    # Intel C++
	    with_gnu_ld=yes
	    # version 8.0 and above of icpc choke on multiply defined symbols
	    # if we add $predep_objects and $postdep_objects, however 7.1 and
	    # earlier do not add the objects themselves.
	    case `$CC -V 2>&1` in
	      *"Version 7."*)
	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
		_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
		;;
	      *)  # Version 8.0 or newer
	        tmp_idyn=
	        case $host_cpu in
		  ia64*) tmp_idyn=' -i_dynamic';;
		esac
	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
		_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
		;;
	    esac
	    _LT_TAGVAR(archive_cmds_need_lc, $1)=no
	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
	    _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive'
	    ;;
          pgCC* | pgcpp*)
            # Portland Group C++ compiler
	    case `$CC -V` in
	    *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*)
	      _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~
               rm -rf $tpldir~
               $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~
               compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"'
	      _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~
                rm -rf $tpldir~
                $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~
                $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~
                $RANLIB $oldlib'
	      _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~
                rm -rf $tpldir~
                $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
                $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
	      _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~
                rm -rf $tpldir~
                $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
                $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
	      ;;
	    *) # Version 6 and above use weak symbols
	      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
	      _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
	      ;;
	    esac

	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir'
	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
	    _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
            ;;
	  cxx*)
	    # Compaq C++
	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname  -o $lib $wl-retain-symbols-file $wl$export_symbols'

	    runpath_var=LD_RUN_PATH
	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
	    _LT_TAGVAR(hardcode_libdir_separator, $1)=:

	    # Commands to make compiler produce verbose output that lists
	    # what "hidden" libraries, object files and flags are used when
	    # linking a shared library.
	    #
	    # There doesn't appear to be a way to prevent this compiler from
	    # explicitly linking system object files so we need to strip them
	    # from the output so that they don't get included in the library
	    # dependencies.
	    output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed'
	    ;;
	  xl* | mpixl* | bgxl*)
	    # IBM XL 8.0 on PPC, with GNU ld
	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
	    _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
	    if test yes = "$supports_anon_versioning"; then
	      _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
                cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
                echo "local: *; };" >> $output_objdir/$libname.ver~
                $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
	    fi
	    ;;
	  *)
	    case `$CC -V 2>&1 | sed 5q` in
	    *Sun\ C*)
	      # Sun C++ 5.9
	      _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
	      _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
	      _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols'
	      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
	      _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
	      _LT_TAGVAR(compiler_needs_object, $1)=yes

	      # Not sure whether something based on
	      # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1
	      # would be better.
	      output_verbose_link_cmd='func_echo_all'

	      # Archives containing C++ object files must be created using
	      # "CC -xar", where "CC" is the Sun C++ compiler.  This is
	      # necessary to make sure instantiated templates are included
	      # in the archive.
	      _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
	      ;;
	    esac
	    ;;
	esac
	;;

      lynxos*)
        # FIXME: insert proper C++ library support
	_LT_TAGVAR(ld_shlibs, $1)=no
	;;

      m88k*)
        # FIXME: insert proper C++ library support
        _LT_TAGVAR(ld_shlibs, $1)=no
	;;

      mvs*)
        case $cc_basename in
          cxx*)
	    # FIXME: insert proper C++ library support
	    _LT_TAGVAR(ld_shlibs, $1)=no
	    ;;
	  *)
	    # FIXME: insert proper C++ library support
	    _LT_TAGVAR(ld_shlibs, $1)=no
	    ;;
	esac
	;;

      netbsd*)
        if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
	  _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable  -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
	  wlarc=
	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
	  _LT_TAGVAR(hardcode_direct, $1)=yes
	  _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
	fi
	# Workaround some broken pre-1.5 toolchains
	output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
	;;

      *nto* | *qnx*)
        _LT_TAGVAR(ld_shlibs, $1)=yes
	;;

      openbsd* | bitrig*)
	if test -f /usr/libexec/ld.so; then
	  _LT_TAGVAR(hardcode_direct, $1)=yes
	  _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
	  _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
	  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then
	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib'
	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
	    _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
	  fi
	  output_verbose_link_cmd=func_echo_all
	else
	  _LT_TAGVAR(ld_shlibs, $1)=no
	fi
	;;

      osf3* | osf4* | osf5*)
        case $cc_basename in
          KCC*)
	    # Kuck and Associates, Inc. (KAI) C++ Compiler

	    # KCC will only create a shared library if the output file
	    # ends with ".so" (or ".sl" for HP-UX), so rename the library
	    # to its proper name (with version) after linking.
	    _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'

	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
	    _LT_TAGVAR(hardcode_libdir_separator, $1)=:

	    # Archives containing C++ object files must be created using
	    # the KAI C++ compiler.
	    case $host in
	      osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;;
	      *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;;
	    esac
	    ;;
          RCC*)
	    # Rational C++ 2.4.1
	    # FIXME: insert proper C++ library support
	    _LT_TAGVAR(ld_shlibs, $1)=no
	    ;;
          cxx*)
	    case $host in
	      osf3*)
	        _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
	        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
		;;
	      *)
	        _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
	        _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
                  echo "-hidden">> $lib.exp~
                  $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp  `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~
                  $RM $lib.exp'
	        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
		;;
	    esac

	    _LT_TAGVAR(hardcode_libdir_separator, $1)=:

	    # Commands to make compiler produce verbose output that lists
	    # what "hidden" libraries, object files and flags are used when
	    # linking a shared library.
	    #
	    # There doesn't appear to be a way to prevent this compiler from
	    # explicitly linking system object files so we need to strip them
	    # from the output so that they don't get included in the library
	    # dependencies.
	    output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
	    ;;
	  *)
	    if test yes,no = "$GXX,$with_gnu_ld"; then
	      _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
	      case $host in
	        osf3*)
	          _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
		  ;;
	        *)
	          _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
		  ;;
	      esac

	      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
	      _LT_TAGVAR(hardcode_libdir_separator, $1)=:

	      # Commands to make compiler produce verbose output that lists
	      # what "hidden" libraries, object files and flags are used when
	      # linking a shared library.
	      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'

	    else
	      # FIXME: insert proper C++ library support
	      _LT_TAGVAR(ld_shlibs, $1)=no
	    fi
	    ;;
        esac
        ;;

      psos*)
        # FIXME: insert proper C++ library support
        _LT_TAGVAR(ld_shlibs, $1)=no
        ;;

      sunos4*)
        case $cc_basename in
          CC*)
	    # Sun C++ 4.x
	    # FIXME: insert proper C++ library support
	    _LT_TAGVAR(ld_shlibs, $1)=no
	    ;;
          lcc*)
	    # Lucid
	    # FIXME: insert proper C++ library support
	    _LT_TAGVAR(ld_shlibs, $1)=no
	    ;;
          *)
	    # FIXME: insert proper C++ library support
	    _LT_TAGVAR(ld_shlibs, $1)=no
	    ;;
        esac
        ;;

      solaris*)
        case $cc_basename in
          CC* | sunCC*)
	    # Sun C++ 4.2, 5.x and Centerline C++
            _LT_TAGVAR(archive_cmds_need_lc,$1)=yes
	    _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
	    _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
	    _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
              $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'

	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
	    _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
	    case $host_os in
	      solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
	      *)
		# The compiler driver will combine and reorder linker options,
		# but understands '-z linker_flag'.
	        # Supported since Solaris 2.6 (maybe 2.5.1?)
		_LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
	        ;;
	    esac
	    _LT_TAGVAR(link_all_deplibs, $1)=yes

	    output_verbose_link_cmd='func_echo_all'

	    # Archives containing C++ object files must be created using
	    # "CC -xar", where "CC" is the Sun C++ compiler.  This is
	    # necessary to make sure instantiated templates are included
	    # in the archive.
	    _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
	    ;;
          gcx*)
	    # Green Hills C++ Compiler
	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'

	    # The C++ compiler must be used to create the archive.
	    _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
	    ;;
          *)
	    # GNU C++ compiler with Solaris linker
	    if test yes,no = "$GXX,$with_gnu_ld"; then
	      _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs'
	      if $CC --version | $GREP -v '^2\.7' > /dev/null; then
	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
	        _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
                  $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'

	        # Commands to make compiler produce verbose output that lists
	        # what "hidden" libraries, object files and flags are used when
	        # linking a shared library.
	        output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
	      else
	        # g++ 2.7 appears to require '-G' NOT '-shared' on this
	        # platform.
	        _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
	        _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
                  $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'

	        # Commands to make compiler produce verbose output that lists
	        # what "hidden" libraries, object files and flags are used when
	        # linking a shared library.
	        output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
	      fi

	      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir'
	      case $host_os in
		solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
		*)
		  _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract'
		  ;;
	      esac
	    fi
	    ;;
        esac
        ;;

    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
      _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
      _LT_TAGVAR(archive_cmds_need_lc, $1)=no
      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
      runpath_var='LD_RUN_PATH'

      case $cc_basename in
        CC*)
	  _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
	  _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
	  ;;
	*)
	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
	  _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
	  ;;
      esac
      ;;

      sysv5* | sco3.2v5* | sco5v6*)
	# Note: We CANNOT use -z defs as we might desire, because we do not
	# link with -lc, and that would cause any symbols used from libc to
	# always be unresolved, which means just about no library would
	# ever link correctly.  If we're not using GNU ld we use -z text
	# though, which does catch some bad symbols but isn't as heavy-handed
	# as -z defs.
	_LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
	_LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs'
	_LT_TAGVAR(archive_cmds_need_lc, $1)=no
	_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir'
	_LT_TAGVAR(hardcode_libdir_separator, $1)=':'
	_LT_TAGVAR(link_all_deplibs, $1)=yes
	_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport'
	runpath_var='LD_RUN_PATH'

	case $cc_basename in
          CC*)
	    _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
	    _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~
              '"$_LT_TAGVAR(old_archive_cmds, $1)"
	    _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~
              '"$_LT_TAGVAR(reload_cmds, $1)"
	    ;;
	  *)
	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
	    ;;
	esac
      ;;

      tandem*)
        case $cc_basename in
          NCC*)
	    # NonStop-UX NCC 3.20
	    # FIXME: insert proper C++ library support
	    _LT_TAGVAR(ld_shlibs, $1)=no
	    ;;
          *)
	    # FIXME: insert proper C++ library support
	    _LT_TAGVAR(ld_shlibs, $1)=no
	    ;;
        esac
        ;;

      vxworks*)
        # FIXME: insert proper C++ library support
        _LT_TAGVAR(ld_shlibs, $1)=no
        ;;

      *)
        # FIXME: insert proper C++ library support
        _LT_TAGVAR(ld_shlibs, $1)=no
        ;;
    esac

    AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
    test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no

    _LT_TAGVAR(GCC, $1)=$GXX
    _LT_TAGVAR(LD, $1)=$LD

    ## CAVEAT EMPTOR:
    ## There is no encapsulation within the following macros, do not change
    ## the running order or otherwise move them around unless you know exactly
    ## what you are doing...
    _LT_SYS_HIDDEN_LIBDEPS($1)
    _LT_COMPILER_PIC($1)
    _LT_COMPILER_C_O($1)
    _LT_COMPILER_FILE_LOCKS($1)
    _LT_LINKER_SHLIBS($1)
    _LT_SYS_DYNAMIC_LINKER($1)
    _LT_LINKER_HARDCODE_LIBPATH($1)

    _LT_CONFIG($1)
  fi # test -n "$compiler"

  CC=$lt_save_CC
  CFLAGS=$lt_save_CFLAGS
  LDCXX=$LD
  LD=$lt_save_LD
  GCC=$lt_save_GCC
  with_gnu_ld=$lt_save_with_gnu_ld
  lt_cv_path_LDCXX=$lt_cv_path_LD
  lt_cv_path_LD=$lt_save_path_LD
  lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
  lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
fi # test yes != "$_lt_caught_CXX_error"

AC_LANG_POP
])# _LT_LANG_CXX_CONFIG


# _LT_FUNC_STRIPNAME_CNF
# ----------------------
# func_stripname_cnf prefix suffix name
# strip PREFIX and SUFFIX off of NAME.
# PREFIX and SUFFIX must not contain globbing or regex special
# characters, hashes, percent signs, but SUFFIX may contain a leading
# dot (in which case that matches only a dot).
#
# This function is identical to the (non-XSI) version of func_stripname,
# except this one can be used by m4 code that may be executed by configure,
# rather than the libtool script.
m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl
AC_REQUIRE([_LT_DECL_SED])
AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])
func_stripname_cnf ()
{
  case @S|@2 in
  .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;;
  *)  func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;;
  esac
} # func_stripname_cnf
])# _LT_FUNC_STRIPNAME_CNF


# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME])
# ---------------------------------
# Figure out "hidden" library dependencies from verbose
# compiler output when linking a shared library.
# Parse the compiler output and extract the necessary
# objects, libraries and library flags.
m4_defun([_LT_SYS_HIDDEN_LIBDEPS],
[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl
# Dependencies to place before and after the object being linked:
_LT_TAGVAR(predep_objects, $1)=
_LT_TAGVAR(postdep_objects, $1)=
_LT_TAGVAR(predeps, $1)=
_LT_TAGVAR(postdeps, $1)=
_LT_TAGVAR(compiler_lib_search_path, $1)=

dnl we can't use the lt_simple_compile_test_code here,
dnl because it contains code intended for an executable,
dnl not a library.  It's possible we should let each
dnl tag define a new lt_????_link_test_code variable,
dnl but it's only used here...
m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF
int a;
void foo (void) { a = 0; }
_LT_EOF
], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF
class Foo
{
public:
  Foo (void) { a = 0; }
private:
  int a;
};
_LT_EOF
], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF
      subroutine foo
      implicit none
      integer*4 a
      a=0
      return
      end
_LT_EOF
], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF
      subroutine foo
      implicit none
      integer a
      a=0
      return
      end
_LT_EOF
], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF
public class foo {
  private int a;
  public void bar (void) {
    a = 0;
  }
};
_LT_EOF
], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF
package foo
func foo() {
}
_LT_EOF
])

_lt_libdeps_save_CFLAGS=$CFLAGS
case "$CC $CFLAGS " in #(
*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;;
*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;;
*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;;
esac

dnl Parse the compiler output and extract the necessary
dnl objects, libraries and library flags.
if AC_TRY_EVAL(ac_compile); then
  # Parse the compiler output and extract the necessary
  # objects, libraries and library flags.

  # Sentinel used to keep track of whether or not we are before
  # the conftest object file.
  pre_test_object_deps_done=no

  for p in `eval "$output_verbose_link_cmd"`; do
    case $prev$p in

    -L* | -R* | -l*)
       # Some compilers place space between "-{L,R}" and the path.
       # Remove the space.
       if test x-L = "$p" ||
          test x-R = "$p"; then
	 prev=$p
	 continue
       fi

       # Expand the sysroot to ease extracting the directories later.
       if test -z "$prev"; then
         case $p in
         -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;;
         -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;;
         -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;;
         esac
       fi
       case $p in
       =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;;
       esac
       if test no = "$pre_test_object_deps_done"; then
	 case $prev in
	 -L | -R)
	   # Internal compiler library paths should come after those
	   # provided the user.  The postdeps already come after the
	   # user supplied libs so there is no need to process them.
	   if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then
	     _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p
	   else
	     _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p"
	   fi
	   ;;
	 # The "-l" case would never come before the object being
	 # linked, so don't bother handling this case.
	 esac
       else
	 if test -z "$_LT_TAGVAR(postdeps, $1)"; then
	   _LT_TAGVAR(postdeps, $1)=$prev$p
	 else
	   _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p"
	 fi
       fi
       prev=
       ;;

    *.lto.$objext) ;; # Ignore GCC LTO objects
    *.$objext)
       # This assumes that the test object file only shows up
       # once in the compiler output.
       if test "$p" = "conftest.$objext"; then
	 pre_test_object_deps_done=yes
	 continue
       fi

       if test no = "$pre_test_object_deps_done"; then
	 if test -z "$_LT_TAGVAR(predep_objects, $1)"; then
	   _LT_TAGVAR(predep_objects, $1)=$p
	 else
	   _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p"
	 fi
       else
	 if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then
	   _LT_TAGVAR(postdep_objects, $1)=$p
	 else
	   _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p"
	 fi
       fi
       ;;

    *) ;; # Ignore the rest.

    esac
  done

  # Clean up.
  rm -f a.out a.exe
else
  echo "libtool.m4: error: problem compiling $1 test program"
fi

$RM -f confest.$objext
CFLAGS=$_lt_libdeps_save_CFLAGS

# PORTME: override above test on systems where it is broken
m4_if([$1], [CXX],
[case $host_os in
interix[[3-9]]*)
  # Interix 3.5 installs completely hosed .la files for C++, so rather than
  # hack all around it, let's just trust "g++" to DTRT.
  _LT_TAGVAR(predep_objects,$1)=
  _LT_TAGVAR(postdep_objects,$1)=
  _LT_TAGVAR(postdeps,$1)=
  ;;
esac
])

case " $_LT_TAGVAR(postdeps, $1) " in
*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;;
esac
 _LT_TAGVAR(compiler_lib_search_dirs, $1)=
if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then
 _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'`
fi
_LT_TAGDECL([], [compiler_lib_search_dirs], [1],
    [The directories searched by this compiler when creating a shared library])
_LT_TAGDECL([], [predep_objects], [1],
    [Dependencies to place before and after the objects being linked to
    create a shared library])
_LT_TAGDECL([], [postdep_objects], [1])
_LT_TAGDECL([], [predeps], [1])
_LT_TAGDECL([], [postdeps], [1])
_LT_TAGDECL([], [compiler_lib_search_path], [1],
    [The library search path used internally by the compiler when linking
    a shared library])
])# _LT_SYS_HIDDEN_LIBDEPS


# _LT_LANG_F77_CONFIG([TAG])
# --------------------------
# Ensure that the configuration variables for a Fortran 77 compiler are
# suitably defined.  These variables are subsequently used by _LT_CONFIG
# to write the compiler configuration to 'libtool'.
m4_defun([_LT_LANG_F77_CONFIG],
[AC_LANG_PUSH(Fortran 77)
if test -z "$F77" || test no = "$F77"; then
  _lt_disable_F77=yes
fi

_LT_TAGVAR(archive_cmds_need_lc, $1)=no
_LT_TAGVAR(allow_undefined_flag, $1)=
_LT_TAGVAR(always_export_symbols, $1)=no
_LT_TAGVAR(archive_expsym_cmds, $1)=
_LT_TAGVAR(export_dynamic_flag_spec, $1)=
_LT_TAGVAR(hardcode_direct, $1)=no
_LT_TAGVAR(hardcode_direct_absolute, $1)=no
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
_LT_TAGVAR(hardcode_libdir_separator, $1)=
_LT_TAGVAR(hardcode_minus_L, $1)=no
_LT_TAGVAR(hardcode_automatic, $1)=no
_LT_TAGVAR(inherit_rpath, $1)=no
_LT_TAGVAR(module_cmds, $1)=
_LT_TAGVAR(module_expsym_cmds, $1)=
_LT_TAGVAR(link_all_deplibs, $1)=unknown
_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
_LT_TAGVAR(reload_flag, $1)=$reload_flag
_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
_LT_TAGVAR(no_undefined_flag, $1)=
_LT_TAGVAR(whole_archive_flag_spec, $1)=
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no

# Source file extension for f77 test sources.
ac_ext=f

# Object file extension for compiled f77 test sources.
objext=o
_LT_TAGVAR(objext, $1)=$objext

# No sense in running all these tests if we already determined that
# the F77 compiler isn't working.  Some variables (like enable_shared)
# are currently assumed to apply to all compilers on this platform,
# and will be corrupted by setting them based on a non-working compiler.
if test yes != "$_lt_disable_F77"; then
  # Code to be used in simple compile tests
  lt_simple_compile_test_code="\
      subroutine t
      return
      end
"

  # Code to be used in simple link tests
  lt_simple_link_test_code="\
      program t
      end
"

  # ltmain only uses $CC for tagged configurations so make sure $CC is set.
  _LT_TAG_COMPILER

  # save warnings/boilerplate of simple test code
  _LT_COMPILER_BOILERPLATE
  _LT_LINKER_BOILERPLATE

  # Allow CC to be a program name with arguments.
  lt_save_CC=$CC
  lt_save_GCC=$GCC
  lt_save_CFLAGS=$CFLAGS
  CC=${F77-"f77"}
  CFLAGS=$FFLAGS
  compiler=$CC
  _LT_TAGVAR(compiler, $1)=$CC
  _LT_CC_BASENAME([$compiler])
  GCC=$G77
  if test -n "$compiler"; then
    AC_MSG_CHECKING([if libtool supports shared libraries])
    AC_MSG_RESULT([$can_build_shared])

    AC_MSG_CHECKING([whether to build shared libraries])
    test no = "$can_build_shared" && enable_shared=no

    # On AIX, shared libraries and static libraries use the same namespace, and
    # are all built from PIC.
    case $host_os in
      aix3*)
        test yes = "$enable_shared" && enable_static=no
        if test -n "$RANLIB"; then
          archive_cmds="$archive_cmds~\$RANLIB \$lib"
          postinstall_cmds='$RANLIB $lib'
        fi
        ;;
      aix[[4-9]]*)
	if test ia64 != "$host_cpu"; then
	  case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
	  yes,aix,yes) ;;		# shared object as lib.so file only
	  yes,svr4,*) ;;		# shared object as lib.so archive member only
	  yes,*) enable_static=no ;;	# shared object in lib.a archive as well
	  esac
	fi
        ;;
    esac
    AC_MSG_RESULT([$enable_shared])

    AC_MSG_CHECKING([whether to build static libraries])
    # Make sure either enable_shared or enable_static is yes.
    test yes = "$enable_shared" || enable_static=yes
    AC_MSG_RESULT([$enable_static])

    _LT_TAGVAR(GCC, $1)=$G77
    _LT_TAGVAR(LD, $1)=$LD

    ## CAVEAT EMPTOR:
    ## There is no encapsulation within the following macros, do not change
    ## the running order or otherwise move them around unless you know exactly
    ## what you are doing...
    _LT_COMPILER_PIC($1)
    _LT_COMPILER_C_O($1)
    _LT_COMPILER_FILE_LOCKS($1)
    _LT_LINKER_SHLIBS($1)
    _LT_SYS_DYNAMIC_LINKER($1)
    _LT_LINKER_HARDCODE_LIBPATH($1)

    _LT_CONFIG($1)
  fi # test -n "$compiler"

  GCC=$lt_save_GCC
  CC=$lt_save_CC
  CFLAGS=$lt_save_CFLAGS
fi # test yes != "$_lt_disable_F77"

AC_LANG_POP
])# _LT_LANG_F77_CONFIG


# _LT_LANG_FC_CONFIG([TAG])
# -------------------------
# Ensure that the configuration variables for a Fortran compiler are
# suitably defined.  These variables are subsequently used by _LT_CONFIG
# to write the compiler configuration to 'libtool'.
m4_defun([_LT_LANG_FC_CONFIG],
[AC_LANG_PUSH(Fortran)

if test -z "$FC" || test no = "$FC"; then
  _lt_disable_FC=yes
fi

_LT_TAGVAR(archive_cmds_need_lc, $1)=no
_LT_TAGVAR(allow_undefined_flag, $1)=
_LT_TAGVAR(always_export_symbols, $1)=no
_LT_TAGVAR(archive_expsym_cmds, $1)=
_LT_TAGVAR(export_dynamic_flag_spec, $1)=
_LT_TAGVAR(hardcode_direct, $1)=no
_LT_TAGVAR(hardcode_direct_absolute, $1)=no
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
_LT_TAGVAR(hardcode_libdir_separator, $1)=
_LT_TAGVAR(hardcode_minus_L, $1)=no
_LT_TAGVAR(hardcode_automatic, $1)=no
_LT_TAGVAR(inherit_rpath, $1)=no
_LT_TAGVAR(module_cmds, $1)=
_LT_TAGVAR(module_expsym_cmds, $1)=
_LT_TAGVAR(link_all_deplibs, $1)=unknown
_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
_LT_TAGVAR(reload_flag, $1)=$reload_flag
_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
_LT_TAGVAR(no_undefined_flag, $1)=
_LT_TAGVAR(whole_archive_flag_spec, $1)=
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no

# Source file extension for fc test sources.
ac_ext=${ac_fc_srcext-f}

# Object file extension for compiled fc test sources.
objext=o
_LT_TAGVAR(objext, $1)=$objext

# No sense in running all these tests if we already determined that
# the FC compiler isn't working.  Some variables (like enable_shared)
# are currently assumed to apply to all compilers on this platform,
# and will be corrupted by setting them based on a non-working compiler.
if test yes != "$_lt_disable_FC"; then
  # Code to be used in simple compile tests
  lt_simple_compile_test_code="\
      subroutine t
      return
      end
"

  # Code to be used in simple link tests
  lt_simple_link_test_code="\
      program t
      end
"

  # ltmain only uses $CC for tagged configurations so make sure $CC is set.
  _LT_TAG_COMPILER

  # save warnings/boilerplate of simple test code
  _LT_COMPILER_BOILERPLATE
  _LT_LINKER_BOILERPLATE

  # Allow CC to be a program name with arguments.
  lt_save_CC=$CC
  lt_save_GCC=$GCC
  lt_save_CFLAGS=$CFLAGS
  CC=${FC-"f95"}
  CFLAGS=$FCFLAGS
  compiler=$CC
  GCC=$ac_cv_fc_compiler_gnu

  _LT_TAGVAR(compiler, $1)=$CC
  _LT_CC_BASENAME([$compiler])

  if test -n "$compiler"; then
    AC_MSG_CHECKING([if libtool supports shared libraries])
    AC_MSG_RESULT([$can_build_shared])

    AC_MSG_CHECKING([whether to build shared libraries])
    test no = "$can_build_shared" && enable_shared=no

    # On AIX, shared libraries and static libraries use the same namespace, and
    # are all built from PIC.
    case $host_os in
      aix3*)
        test yes = "$enable_shared" && enable_static=no
        if test -n "$RANLIB"; then
          archive_cmds="$archive_cmds~\$RANLIB \$lib"
          postinstall_cmds='$RANLIB $lib'
        fi
        ;;
      aix[[4-9]]*)
	if test ia64 != "$host_cpu"; then
	  case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
	  yes,aix,yes) ;;		# shared object as lib.so file only
	  yes,svr4,*) ;;		# shared object as lib.so archive member only
	  yes,*) enable_static=no ;;	# shared object in lib.a archive as well
	  esac
	fi
        ;;
    esac
    AC_MSG_RESULT([$enable_shared])

    AC_MSG_CHECKING([whether to build static libraries])
    # Make sure either enable_shared or enable_static is yes.
    test yes = "$enable_shared" || enable_static=yes
    AC_MSG_RESULT([$enable_static])

    _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu
    _LT_TAGVAR(LD, $1)=$LD

    ## CAVEAT EMPTOR:
    ## There is no encapsulation within the following macros, do not change
    ## the running order or otherwise move them around unless you know exactly
    ## what you are doing...
    _LT_SYS_HIDDEN_LIBDEPS($1)
    _LT_COMPILER_PIC($1)
    _LT_COMPILER_C_O($1)
    _LT_COMPILER_FILE_LOCKS($1)
    _LT_LINKER_SHLIBS($1)
    _LT_SYS_DYNAMIC_LINKER($1)
    _LT_LINKER_HARDCODE_LIBPATH($1)

    _LT_CONFIG($1)
  fi # test -n "$compiler"

  GCC=$lt_save_GCC
  CC=$lt_save_CC
  CFLAGS=$lt_save_CFLAGS
fi # test yes != "$_lt_disable_FC"

AC_LANG_POP
])# _LT_LANG_FC_CONFIG


# _LT_LANG_GCJ_CONFIG([TAG])
# --------------------------
# Ensure that the configuration variables for the GNU Java Compiler compiler
# are suitably defined.  These variables are subsequently used by _LT_CONFIG
# to write the compiler configuration to 'libtool'.
m4_defun([_LT_LANG_GCJ_CONFIG],
[AC_REQUIRE([LT_PROG_GCJ])dnl
AC_LANG_SAVE

# Source file extension for Java test sources.
ac_ext=java

# Object file extension for compiled Java test sources.
objext=o
_LT_TAGVAR(objext, $1)=$objext

# Code to be used in simple compile tests
lt_simple_compile_test_code="class foo {}"

# Code to be used in simple link tests
lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }'

# ltmain only uses $CC for tagged configurations so make sure $CC is set.
_LT_TAG_COMPILER

# save warnings/boilerplate of simple test code
_LT_COMPILER_BOILERPLATE
_LT_LINKER_BOILERPLATE

# Allow CC to be a program name with arguments.
lt_save_CC=$CC
lt_save_CFLAGS=$CFLAGS
lt_save_GCC=$GCC
GCC=yes
CC=${GCJ-"gcj"}
CFLAGS=$GCJFLAGS
compiler=$CC
_LT_TAGVAR(compiler, $1)=$CC
_LT_TAGVAR(LD, $1)=$LD
_LT_CC_BASENAME([$compiler])

# GCJ did not exist at the time GCC didn't implicitly link libc in.
_LT_TAGVAR(archive_cmds_need_lc, $1)=no

_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
_LT_TAGVAR(reload_flag, $1)=$reload_flag
_LT_TAGVAR(reload_cmds, $1)=$reload_cmds

## CAVEAT EMPTOR:
## There is no encapsulation within the following macros, do not change
## the running order or otherwise move them around unless you know exactly
## what you are doing...
if test -n "$compiler"; then
  _LT_COMPILER_NO_RTTI($1)
  _LT_COMPILER_PIC($1)
  _LT_COMPILER_C_O($1)
  _LT_COMPILER_FILE_LOCKS($1)
  _LT_LINKER_SHLIBS($1)
  _LT_LINKER_HARDCODE_LIBPATH($1)

  _LT_CONFIG($1)
fi

AC_LANG_RESTORE

GCC=$lt_save_GCC
CC=$lt_save_CC
CFLAGS=$lt_save_CFLAGS
])# _LT_LANG_GCJ_CONFIG


# _LT_LANG_GO_CONFIG([TAG])
# --------------------------
# Ensure that the configuration variables for the GNU Go compiler
# are suitably defined.  These variables are subsequently used by _LT_CONFIG
# to write the compiler configuration to 'libtool'.
m4_defun([_LT_LANG_GO_CONFIG],
[AC_REQUIRE([LT_PROG_GO])dnl
AC_LANG_SAVE

# Source file extension for Go test sources.
ac_ext=go

# Object file extension for compiled Go test sources.
objext=o
_LT_TAGVAR(objext, $1)=$objext

# Code to be used in simple compile tests
lt_simple_compile_test_code="package main; func main() { }"

# Code to be used in simple link tests
lt_simple_link_test_code='package main; func main() { }'

# ltmain only uses $CC for tagged configurations so make sure $CC is set.
_LT_TAG_COMPILER

# save warnings/boilerplate of simple test code
_LT_COMPILER_BOILERPLATE
_LT_LINKER_BOILERPLATE

# Allow CC to be a program name with arguments.
lt_save_CC=$CC
lt_save_CFLAGS=$CFLAGS
lt_save_GCC=$GCC
GCC=yes
CC=${GOC-"gccgo"}
CFLAGS=$GOFLAGS
compiler=$CC
_LT_TAGVAR(compiler, $1)=$CC
_LT_TAGVAR(LD, $1)=$LD
_LT_CC_BASENAME([$compiler])

# Go did not exist at the time GCC didn't implicitly link libc in.
_LT_TAGVAR(archive_cmds_need_lc, $1)=no

_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
_LT_TAGVAR(reload_flag, $1)=$reload_flag
_LT_TAGVAR(reload_cmds, $1)=$reload_cmds

## CAVEAT EMPTOR:
## There is no encapsulation within the following macros, do not change
## the running order or otherwise move them around unless you know exactly
## what you are doing...
if test -n "$compiler"; then
  _LT_COMPILER_NO_RTTI($1)
  _LT_COMPILER_PIC($1)
  _LT_COMPILER_C_O($1)
  _LT_COMPILER_FILE_LOCKS($1)
  _LT_LINKER_SHLIBS($1)
  _LT_LINKER_HARDCODE_LIBPATH($1)

  _LT_CONFIG($1)
fi

AC_LANG_RESTORE

GCC=$lt_save_GCC
CC=$lt_save_CC
CFLAGS=$lt_save_CFLAGS
])# _LT_LANG_GO_CONFIG


# _LT_LANG_RC_CONFIG([TAG])
# -------------------------
# Ensure that the configuration variables for the Windows resource compiler
# are suitably defined.  These variables are subsequently used by _LT_CONFIG
# to write the compiler configuration to 'libtool'.
m4_defun([_LT_LANG_RC_CONFIG],
[AC_REQUIRE([LT_PROG_RC])dnl
AC_LANG_SAVE

# Source file extension for RC test sources.
ac_ext=rc

# Object file extension for compiled RC test sources.
objext=o
_LT_TAGVAR(objext, $1)=$objext

# Code to be used in simple compile tests
lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }'

# Code to be used in simple link tests
lt_simple_link_test_code=$lt_simple_compile_test_code

# ltmain only uses $CC for tagged configurations so make sure $CC is set.
_LT_TAG_COMPILER

# save warnings/boilerplate of simple test code
_LT_COMPILER_BOILERPLATE
_LT_LINKER_BOILERPLATE

# Allow CC to be a program name with arguments.
lt_save_CC=$CC
lt_save_CFLAGS=$CFLAGS
lt_save_GCC=$GCC
GCC=
CC=${RC-"windres"}
CFLAGS=
compiler=$CC
_LT_TAGVAR(compiler, $1)=$CC
_LT_CC_BASENAME([$compiler])
_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes

if test -n "$compiler"; then
  :
  _LT_CONFIG($1)
fi

GCC=$lt_save_GCC
AC_LANG_RESTORE
CC=$lt_save_CC
CFLAGS=$lt_save_CFLAGS
])# _LT_LANG_RC_CONFIG


# LT_PROG_GCJ
# -----------
AC_DEFUN([LT_PROG_GCJ],
[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ],
  [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ],
    [AC_CHECK_TOOL(GCJ, gcj,)
      test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2"
      AC_SUBST(GCJFLAGS)])])[]dnl
])

# Old name:
AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([LT_AC_PROG_GCJ], [])


# LT_PROG_GO
# ----------
AC_DEFUN([LT_PROG_GO],
[AC_CHECK_TOOL(GOC, gccgo,)
])


# LT_PROG_RC
# ----------
AC_DEFUN([LT_PROG_RC],
[AC_CHECK_TOOL(RC, windres,)
])

# Old name:
AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([LT_AC_PROG_RC], [])


# _LT_DECL_EGREP
# --------------
# If we don't have a new enough Autoconf to choose the best grep
# available, choose the one first in the user's PATH.
m4_defun([_LT_DECL_EGREP],
[AC_REQUIRE([AC_PROG_EGREP])dnl
AC_REQUIRE([AC_PROG_FGREP])dnl
test -z "$GREP" && GREP=grep
_LT_DECL([], [GREP], [1], [A grep program that handles long lines])
_LT_DECL([], [EGREP], [1], [An ERE matcher])
_LT_DECL([], [FGREP], [1], [A literal string matcher])
dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too
AC_SUBST([GREP])
])


# _LT_DECL_OBJDUMP
# --------------
# If we don't have a new enough Autoconf to choose the best objdump
# available, choose the one first in the user's PATH.
m4_defun([_LT_DECL_OBJDUMP],
[AC_CHECK_TOOL(OBJDUMP, objdump, false)
test -z "$OBJDUMP" && OBJDUMP=objdump
_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper])
AC_SUBST([OBJDUMP])
])

# _LT_DECL_DLLTOOL
# ----------------
# Ensure DLLTOOL variable is set.
m4_defun([_LT_DECL_DLLTOOL],
[AC_CHECK_TOOL(DLLTOOL, dlltool, false)
test -z "$DLLTOOL" && DLLTOOL=dlltool
_LT_DECL([], [DLLTOOL], [1], [DLL creation program])
AC_SUBST([DLLTOOL])
])

# _LT_DECL_SED
# ------------
# Check for a fully-functional sed program, that truncates
# as few characters as possible.  Prefer GNU sed if found.
m4_defun([_LT_DECL_SED],
[AC_PROG_SED
test -z "$SED" && SED=sed
Xsed="$SED -e 1s/^X//"
_LT_DECL([], [SED], [1], [A sed program that does not truncate output])
_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"],
    [Sed that helps us avoid accidentally triggering echo(1) options like -n])
])# _LT_DECL_SED

m4_ifndef([AC_PROG_SED], [
############################################################
# NOTE: This macro has been submitted for inclusion into   #
#  GNU Autoconf as AC_PROG_SED.  When it is available in   #
#  a released version of Autoconf we should remove this    #
#  macro and use it instead.                               #
############################################################

m4_defun([AC_PROG_SED],
[AC_MSG_CHECKING([for a sed that does not truncate output])
AC_CACHE_VAL(lt_cv_path_SED,
[# Loop through the user's path and test for sed and gsed.
# Then use that list of sed's as ones to test for truncation.
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  test -z "$as_dir" && as_dir=.
  for lt_ac_prog in sed gsed; do
    for ac_exec_ext in '' $ac_executable_extensions; do
      if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then
        lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
      fi
    done
  done
done
IFS=$as_save_IFS
lt_ac_max=0
lt_ac_count=0
# Add /usr/xpg4/bin/sed as it is typically found on Solaris
# along with /bin/sed that truncates output.
for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
  test ! -f "$lt_ac_sed" && continue
  cat /dev/null > conftest.in
  lt_ac_count=0
  echo $ECHO_N "0123456789$ECHO_C" >conftest.in
  # Check for GNU sed and select it if it is found.
  if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
    lt_cv_path_SED=$lt_ac_sed
    break
  fi
  while true; do
    cat conftest.in conftest.in >conftest.tmp
    mv conftest.tmp conftest.in
    cp conftest.in conftest.nl
    echo >>conftest.nl
    $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
    cmp -s conftest.out conftest.nl || break
    # 10000 chars as input seems more than enough
    test 10 -lt "$lt_ac_count" && break
    lt_ac_count=`expr $lt_ac_count + 1`
    if test "$lt_ac_count" -gt "$lt_ac_max"; then
      lt_ac_max=$lt_ac_count
      lt_cv_path_SED=$lt_ac_sed
    fi
  done
done
])
SED=$lt_cv_path_SED
AC_SUBST([SED])
AC_MSG_RESULT([$SED])
])#AC_PROG_SED
])#m4_ifndef

# Old name:
AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([LT_AC_PROG_SED], [])


# _LT_CHECK_SHELL_FEATURES
# ------------------------
# Find out whether the shell is Bourne or XSI compatible,
# or has some other useful features.
m4_defun([_LT_CHECK_SHELL_FEATURES],
[if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
  lt_unset=unset
else
  lt_unset=false
fi
_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl

# test EBCDIC or ASCII
case `echo X|tr X '\101'` in
 A) # ASCII based system
    # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
  lt_SP2NL='tr \040 \012'
  lt_NL2SP='tr \015\012 \040\040'
  ;;
 *) # EBCDIC based system
  lt_SP2NL='tr \100 \n'
  lt_NL2SP='tr \r\n \100\100'
  ;;
esac
_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl
_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl
])# _LT_CHECK_SHELL_FEATURES


# _LT_PATH_CONVERSION_FUNCTIONS
# -----------------------------
# Determine what file name conversion functions should be used by
# func_to_host_file (and, implicitly, by func_to_host_path).  These are needed
# for certain cross-compile configurations and native mingw.
m4_defun([_LT_PATH_CONVERSION_FUNCTIONS],
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
AC_REQUIRE([AC_CANONICAL_BUILD])dnl
AC_MSG_CHECKING([how to convert $build file names to $host format])
AC_CACHE_VAL(lt_cv_to_host_file_cmd,
[case $host in
  *-*-mingw* )
    case $build in
      *-*-mingw* ) # actually msys
        lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32
        ;;
      *-*-cygwin* )
        lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32
        ;;
      * ) # otherwise, assume *nix
        lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32
        ;;
    esac
    ;;
  *-*-cygwin* )
    case $build in
      *-*-mingw* ) # actually msys
        lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin
        ;;
      *-*-cygwin* )
        lt_cv_to_host_file_cmd=func_convert_file_noop
        ;;
      * ) # otherwise, assume *nix
        lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin
        ;;
    esac
    ;;
  * ) # unhandled hosts (and "normal" native builds)
    lt_cv_to_host_file_cmd=func_convert_file_noop
    ;;
esac
])
to_host_file_cmd=$lt_cv_to_host_file_cmd
AC_MSG_RESULT([$lt_cv_to_host_file_cmd])
_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd],
         [0], [convert $build file names to $host format])dnl

AC_MSG_CHECKING([how to convert $build file names to toolchain format])
AC_CACHE_VAL(lt_cv_to_tool_file_cmd,
[#assume ordinary cross tools, or native build.
lt_cv_to_tool_file_cmd=func_convert_file_noop
case $host in
  *-*-mingw* )
    case $build in
      *-*-mingw* ) # actually msys
        lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32
        ;;
    esac
    ;;
esac
])
to_tool_file_cmd=$lt_cv_to_tool_file_cmd
AC_MSG_RESULT([$lt_cv_to_tool_file_cmd])
_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd],
         [0], [convert $build files to toolchain format])dnl
])# _LT_PATH_CONVERSION_FUNCTIONS
ode-0.16/m4/ltversion.m40000644000175200017520000000127313403272661011752 00000000000000# ltversion.m4 -- version numbers			-*- Autoconf -*-
#
#   Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc.
#   Written by Scott James Remnant, 2004
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.

# @configure_input@

# serial 4179 ltversion.m4
# This file is part of GNU Libtool

m4_define([LT_PACKAGE_VERSION], [2.4.6])
m4_define([LT_PACKAGE_REVISION], [2.4.6])

AC_DEFUN([LTVERSION_VERSION],
[macro_version='2.4.6'
macro_revision='2.4.6'
_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
_LT_DECL(, macro_revision, 0)
])
ode-0.16/build/0000775000175200017520000000000013403272463010321 500000000000000ode-0.16/build/premake4.exe0000664000175200017520000077700013403272463012467 00000000000000MZÿÿ¸@€º´	Í!¸LÍ!This program cannot be run in DOS mode.

$PELæmâLà8Fú€`@@8Q 0Ì.text¤EF``.data`J@À.rdata°¥p¦L@@.bssà €À.idataÌ0ò@ÀU‰åƒì‰]ø‹U1Û‰uü‹1ö‹=‘ÀwC=Àr[¾Ç$1Ò‰T$èd>ƒøtz…ÀtÇ$ÿлÿÿÿÿ‰Ø‹uü‹]ø‰ì]Â=”ÀtÂwJ=“Àt´‰Ø‹uü‹]ø‰ì]Â=Àt[=ÀuÅÇ$1ö‰t$è>ƒøtj…ÀtªÇ$ÿÐëš=–ÀëÑÇ$¹‰L$èÐ=…ö„vÿÿÿè9élÿÿÿÇ$1ɉL$è¬=ƒøt0…À„RÿÿÿÇ$ÿÐé?ÿÿÿÇ$¸‰D$è|=é%ÿÿÿÇ$»‰\$èb=éÿÿÿ¶¼'U‰åSƒì$]øÇ$@èêBƒìèr7èm8ÇEø¸ DUô‰\$‹
À`A‰D$‰T$‰L$Ç$ Dè,=¡0 D…Àtc£Ð`A‹È2D…Ò…–ƒúàt ¡0 D‰D$‹È2D‹K0‰$èá<‹È2DƒúÀt&‹0 D‰\$‹
È2D‹QP‰$è»<t&¼'è›<‹Ð`A‰èŽ6ƒäðèf<‹‰L$‹ D‰T$¡ D‰$èç‰Ãè2<‰$è
B‰D$‹È2D‹B‰$èU<‹È2DéJÿÿÿv¼'U‰åƒìÇ$ÿ¸2Dè¸þÿÿ´&U‰åƒìÇ$ÿ¸2Dè˜þÿÿ´&U‹
ü2D‰å]ÿát&U‹
Ð2D‰å]ÿáU‰å]é·8U‰åV‹uSjjVè¾P‰ÃèfAƒÄ…ÀuVèqShpAVè_¸ë
jVè$¸eø[^]ÃU‰åW‹}VSjjWèmj‰ÃjWèaj‰ÆPSèAƒÄ…ÀuWèVh0pAWèÿ¸ë
jWèĸeô[^_]ÃU¸@‰åSè2:ü¿ÿÿSh@èÑ@1Ò…Àt-€½ü¿ÿÿ‰Øt€8\uÆ/@€8ëð…ü¿ÿÿPÿuè&º‹]ü‰ÐÉÃU‰åSƒì0‹]jjS謃Ä€8‰ÂujëEÌPRè4:Y…ÀZu·EÒ%@PëjSèX¸‹]üZÉÃU‰åEЃì0Pÿuèî9Z1Ò…ÀYu
·UÖÁêƒòƒâɉÐÃU‰åS‹]jjSè$Pè¾ÿÿÿ‰$Sè«‹]ü¸ÉÃU‰åW‹}VSjjWèíhH‰Æè:‰Ã@PVèµ?SW‰ÇCè|eô¸[^_]ÃU‰åSjÿuèñ
Z‰Ã‹YƒøÿtPè‰?Sè³9‹]ü1ÀÉÃU‰åS‹]jSèÄ
ƒÀ4PSèÆ‹]ü¸ÉÃU‰åS‹]jSè¡
‹@ÁèƒðƒàPSèÝ‹]ü¸ÉÃU‰åV‹uSjVèt
‰ÃX1Àƒ;ÿZt9ë1Àë3jV誸ë$ƒ{uCPÿ3èü>…ÀtØ€{4.ÇCuÏëÜeø[^]ÃU‰åV‹uSjjVèÎj‰ÃPèÔ>ƒÄ…ÀuVè
ShPpAVèm¸ë
jVè2¸eø[^]ÃU‰åWVSV‹}ÇEðé´ÿuðWèf	Y…À[„žjÿuðWè\‰ÃƒÄj;Sè8^…ÀZt‰Æ)ØPSWèS
ƒÄëS1öWè‚
Y[jÿWèëhppAWèm
jWèØjWèƒÄ jjÿWèBƒÄPè”ýÿÿZ…ÀtjþWè¸ë,jýWè
Y…ö[t	‰óC…rÿÿÿÿEðWèä9EðZŽ<ÿÿÿ1Àeô[^_]ÃU‰åV‹uSjjVèŽP‰Ãè¦=ƒÄ…ÀuVèASh€pAVè/
¸ë
jVèô
¸eø[^]ÃU‰åSƒì@ƒ= Duh pAèf=hªpAPèk=£ DEì]¼Pÿ D¶EûP¶EúP¶EùP¶EøP¶E÷P¶EöP¶EõP¶EôP¶EóP¶EòP¶EñP¶EðP¶EïP¶EîP¶EíP¶EìPh·pASè7ƒÄHSÿuè‹]ü¸ÉÃU‰åV‹uSjjV莶ƒÄ‰Ã€ù/”À€ù\”Â	Шu€ù$t
„Ét€{:ujVèó¸ë1Àeø[^]ÃU‰åWV‰ÖSìj=R‰…ðýÿÿèd6Y…À‰Ç[t/‰Ã)óûÿ~»ÿS…ôýÿÿVwPèŠ6Æ„+ôýÿÿƒÄëV…ôýÿÿ¾4rAPè[6XZVôýÿÿÿµðýÿÿèSjýÿµðýÿÿè»h5rASè6ƒÄ…Àu€>t‰5  Deô1À[^_]ÃU‰åW‹}V¾Sè?1è'$P‰ÃèRh$rAh=rASè8h qAhBrASè(hqAhErASèƒÄ(hLrASè‡
hurAhîØÿÿSè&h€rASèl
h„rAhîØÿÿSèƒÄ(h•rASèN
hÓrAhîØÿÿSèí
hærASè3
hîrAhîØÿÿSèÒ
ƒÄ(jjSè¦ƒÄjjSè™ƒÄ9þ}x‹U‹²¶€ú/uPë€ú-u€x-uP‰ØèGþÿÿëK‹Eÿ4°FSèË	YXhòrAhîØÿÿSèh
ƒÄ9þ}%‹Uÿ4²FSè¥	XZjþSèúZ@YPjþSèëÔFë„húrA1öhîØÿÿSè'
ƒÄhsAhîØÿÿSè
ƒÄƒ=`AtLÿ4µ`ASè5"Z…ÀYujjÿjS芃ąÀtj¾jÿSèƒÄPè(4XëKFƒ<µ`Aë²h	sA1öhîØÿÿSèÃ
ƒÄjjjSè<ƒÄ…Àtjf¾jÿSèɃÄPèÛ3_SèÝeô‰ð[^_]ÃU‰åWVSSjjjÿuè€jjjÿu‰EðèoƒÄ ƒ}ð‰Æ•À1Ò…ö•Â…ÐtIü‹}ðƒÊÿ1À‰Ñò®÷щ÷Yÿ‰Ñò®÷ÑQÿ9Ó|(V‹EðØ)ÐPèd3Z…À”À¶ÀYPÿuèw	¸ë1Àeô[^_]ÃU…Ò‰åS‰Á~ÁâP¸ÀDƒê;Qs~ëQúðØÿÿ~
‰ÐÁàAëjúïØÿÿt
úîØÿÿ@HtUë,úðØÿÿu$‹@ƒÀ`ëC‹@QX‹@‹‹@ÇB‰AX‰Ðë'‹A»ÀD‹@‹¸îØÿÿ)ЉÂ¶A9ÂÁâ\‰Ø[]ÃU‹P‰å;P(u‹@Hë‹B‹‹@]ÃU‰åV‹uS‹]‹N‹‹S‰‹C‰Q‰AƒÁ‰N[^]ÃU‰å‹UW¿ú@V‹uS‹N‰È+FÁøÐ=@~1ÿë+…Ò~'‹F‰ÓÁã)È9Ø	RVèµ_XZ‹F‹VØ9Bs‰Beô‰ø[^_]ÃU‰å‹E9EW‹UVSt=‹M‰ÐÁà)A…Ò~.1ÿ‰Ö‹U‹E‹J‹XAû‰B‹‹SƒÇN‰‹C‰Q‰AuÖ[^_]ÃU‰å‹E·P4‹Ef‰P4]ÃU‰å‹E‹U‹H‹AX‰QX]ÃU‰åS‹]‹S‹B@9BDrSè	{YSè¹Ø‹S‰ƒCÇB‹]üÉÃU‰å‹U]‹B+BÁøÃU‰å‹MWV‹uS…É‹Vx*‹~‰ÈÁà9ÚsÇBB9؉Ârð‰FÁáëÁáD
‰F[^_]ÃU‰å‹UV‹uS‰ðèýÿÿ‹^‰ÁƒÁ9Ùs‹‹Q‰Að‹A‰Qô‰AøƒÁëæCð‰F[^]ÃU‰å‹UWVS‹]‰Øè^ýÿÿ‹s‰Ç‰ó9Æv‹SðCð‹Kô9ø‰‹P‰K‰S‰Ãëä‹‹V‰‹F‰W‰G[^_]ÃU‰åW‹}V‹uÿïØÿÿSu‹F(9Fu
h}ëCVè¾Y[X‰ú‰ðèòüÿÿÿïØÿÿ‰Ã‹Nu*‹F‹@‹‹Að‰B‹Fƒxø~X‹@ðö@tOöBtIPRë<‹AðÿîØÿÿ‹Qô‰‹Aø‰S‰C},ƒyø~&‹IðöAt‹V‹B‹ö@tQ‹Bÿ0Vè@zƒÄƒneô[^_]ÃU‰å‹UV‹uS‰ðèXüÿÿ‹‹^‹H‹@‰‰K‰CƒÃ‰^[^]ÃU‰å‹U‹Eè-üÿÿƒÊÿ=ÀDt‹P]‰ÐÃU¸”ëC‰å‹Uƒúÿt‹•ÀD]ÃU‰å‹U‹Eèõûÿÿ1Òƒxu
‹€xt²]‰ÐÃU‰åSƒì1Û‹U‹EèËûÿÿƒx‰ÂtEìPRè)‰Â…ÒXYt»‰Ø‹]üÉÃU‰åÿuÿuè\ÿÿÿZƒèƒø–À¶ÀYÉÃU‰å‹U‹Eèyûÿÿ]‹@ƒø”ƒø”À	ЃàÃU‰åWVS‹]‹U‹u‰ØèMûÿÿ‰Ç‰ò‰ØèBûÿÿÿÀDt=ÀDt‰E‰}[^_]éeª[1À^_]ÃU‰å‹UW1ÿV‹uS‰ðèûÿÿ‹U‰Ã‰ðèüúÿÿûÀD‰Ât"=ÀDt‹@9CuRSVèJƒÄ…Àtf¿eô‰ø[^_]ÃU‰å‹UV‹uS‰ðè´úÿÿ‹U‰Ã‰ðè¨úÿÿûÀDt=ÀDt
PSV莃Äë1Àeø[^]ÃU‰åƒì‹U‹Eèrúÿÿƒx‰ÂtEðPRèÐ‰ÂX…ÒÙîYtÝØÝÉÃU‰åƒì‹U‹Eè?úÿÿƒx‰ÂtEðPRè‰ÂX1À…ÒYtÙ ëCÜÝ]è‹EèÉÃU‰å‹U‹Eèúÿÿ‹P1É…Òt
Juƒ8t¹]‰ÈÃU‰å‹UV‹uS‹]‰ØèÖùÿÿƒx‰Ât9PSè~Z…ÀYu…ötÇ1Àë.‹S‹B@9BDrSèƒvX‹U‰Øè—ùÿÿ‰Â…öt‹‹@‰‹ƒÀeø[^]ÃU‰åVS‹u‹U‰ðèlùÿÿ‰Ã‹@ƒøtƒøt,ëBƒøtƒøt	ë6‹‹@ë1‹‹@ë*‹‰Eeø[^]éüSVèß^Z1Ò…Àt‹‹P‰Ðë1Àeø[^]ÃU‰å‹E‹Uèùÿÿƒxu
‹€xt‹@ë1À]ÃU‰å‹U‹EèÛøÿÿ‹Pƒút1Ƀúu	‹ƒÁë‹]‰ÈÃU‰å‹U‹Eè±øÿÿ1Òƒxu‹]‰ÐÃU‰åVS‹u‹]‰ð‰Úèøÿÿ‹Pƒêƒúwÿ$•¤ëC‹ë
‰]‰u[^]ë…1À[^]ÃU‰å‹U‹BÇ@ƒÀ‰B]ÃU‰å‹EÝE‹P݃@ÇB]ÃU‰å‹EÛE‹PÇB݃@]ÃU‰åV‹uS‹V‹B@9BDrVèâtY‹^ÿuÿuVèeÕ‰ƒFÇCeø[^]ÃU‰åWS‹U‹]…Òueø[_]é[ÿÿÿü‰×1ÀƒÉÿò®÷ÑIQRSè”ÿÿÿƒÄeø[_]ÃU‰åWVS‹]‹}‹u‹S‹B@9BDrSèetX‰u‰}‰]eô[^_]éï§U‰åS‹]‹S‹B@9BDrSè7tXEPÿuSèɧ‹]üÉÃU‰åWVSƒì‹E‹u‹P‹B@9BDr	ÿuètX‹Eè¶÷ÿÿPVÿuè~d‰Eð‹EƒÄ‹Uð‹M‰B‹y‰ðÁàN)ljyƒþÿt1‰óÁãN‹‰Eì‹H‹Eð‰T‹Uì‰L‹Mð‹B‰D ƒëƒþÿuÔ‹U‹Mð‹B‰ƒBÇ@eô[^_]ÃU1À‰åƒ}‹U‹J•À‰ƒBÇA]ÃU‰å‹E‹U‹H‰ƒ@ÇA]ÃU‰å‹E‹P‰ÇB‹Pƒ@9Bp]”À¶ÀÃU‰å‹US‹]‰Øè)öÿÿ‹SƒêRRPSèÄ	‹]üÉÃU‰åWVSƒì‹]‹U‰Øèÿõÿÿü‹}‰ÆƒÉÿ1Àò®÷ÑIQÿuSèYÓ‰EäEäÿsÇEìPVSèw	ƒCeô[^_]ÃU‰å‹US‹]‰Øè°õÿÿ‹SƒêRÿ0èDó‹‹[‹H‹@‰Sð‰Kô‰Cø‹]üÉÃU‰å‹UV‹uS‰ðèwõÿÿÿuÿ0èwò‹‹^‹H‹@‰‰K‰CƒÃ‰^eø[^]ÃU‰åV‹uS‹V‹B@9BDrVèrX‹^ÿuÿuVèuñ‰ƒFÇCeø[^]ÃU‰å‹US‹]‰Øèÿôÿÿ‹Pƒútƒúu‹‹Pë
‹C‹”˜1À…Òt‹C‰ƒCÇ@¸[]ÃU‰å‹UV‹uS‰ðè±ôÿÿ‰Â‹@ƒøtƒøt	ë2ƒøtë+‹‹F‹RÇ@‰ë"‹
‹^‹AH‹QL‰‹AP‰S‰Cë
‹FÇ@ƒF[^]ÃU‰å‹US‹]‰ØèIôÿÿ‹SJðƒê QRPSèÛƒk ‹]üÉÃU‰åWVSƒì‹]‹U‹u‰Øèôÿÿ‰Eà‰÷ü1ÀƒÉÿò®÷ÑIQVSèqщEä‹CÇEìƒèPEäPÿuàS胃keô[^_]ÃU‰åWVSQ‹}‹U‰øè¿óÿÿ‰Eð‹_CàP‹Eðsðÿ0WèÕñ‹SðƒÄ‹Kô‰‹V‰H‰P‹Gƒxø~‹@ðö@t‹Uð‹ö@t	PWèjqXZƒo eô[^_]ÃU‰åWVSW‹}‹U‰øèMóÿÿ‰Eð‹_ÿusðÿ0Wèéõ‹SðƒÄ‹Kô‰‹V‰H‰P‹Gƒxø~‹@ðö@t‹Uð‹ö@t	PWèüp[^ƒoeô[^_]ÃU‰å‹UV‹uS‰ðèáòÿÿ‰Ã‹F1Ƀxøt‹Hð‹Sƒútƒút$ëG‹…ɉHtHöAtB‹ö@t:PVèŸpXZë/‹…ɉHt&öAt ‹ö@tQÿ3VèGpƒÄë
‹F‰Œ˜ƒneø¸[^]ÃU‰å‹UV¾S‹]‰ØèJòÿÿ‰Á‹@ƒøtƒøt	ë(ƒøtë!‹S‹‹Rð‰Pë‹S‹‹RðÇ@P‰PHë1öë ‹C‹PðöBt‹ö@tRÿ1SèµoƒÄƒkeø‰ð[^]ÃU‰å‹EV‹uÁàS‹V‹])ƒêSRVèIXƒÄCu‹V‹F;Br‰Beø[^]ÃU‰å‹Eÿpÿ0ÿuèXÉÃU‰åWVSQQ‹U1É‹u‹]…Ò‹}t‰ðèlñÿÿ‰Á+N ‰}ð‹FÁãQ)؃è‰Eì+F PEìPhN*@VèùYƒÄG‰Áu‹V‹F;Br‰Beô‰È[^_]ÃU‰åV‹uS‹]‰Øè®ñÿÿPjSèw^‹‰P‹S‰‹FÇB‹SJ‰K‰B‹CÇAPƒè‰SjPSèWWeø[^]ÃU‰åPP‹Ej‹U‰Eø‹E‰Eü‹B+B PEøPhÎ*@RèOYÉÃU‰åWVSƒì ‹u‹}…öu¾ÀëCÿu]ÔÿuSWèiVSWègZeô[^_]ÃU‰å‹M‹Qƒzøu"‹Bð€xujÿuÿu‹BðÿpQè?]ƒÄë¸ÉÃU‰å‹E]¶@ÃU‰å‹UW‹}‹EV1öƒúS‹_wÿ$•ÄëCÇC@ýÿÿÿër‹CD‰C@ëjWè5mXëa‹sDÁî
ëY‹sDæÿëN‹SDÁà
9Ðw‰Ñ)Á‰K@ë¾ë4ÇC@9S@w(Wè‚l€{Xtà‹CD9C@ëé‹sP‰CPë‹sT‰CTëƒÎÿeô‰ð[^_]ÃU‰åÿuè¢KÉ1ÀÃU‰å‹US‹]‰ØèUïÿÿ‹SƒêRÿ0SèéƒÄ…À‰Â‹CtƒÀëƒè‰C‹]ü‰ÐÉÃU‰åV‹uS‹]ƒû~4‹V‹B@9BDrVèèkX‹F+FÁøHPSÁãVèÿ‹F)؃À‰Fë!…Ûu ‹^jhäëCVèD̉ƒFÇCƒÄeø[^]ÃU‰å‹U‹M…Òt‹A‹@‰]‹A‹@ÃU‰å‹E‹P‹E‰B‹E‰B]ÃU‰åS‹]‹S‹B@9BDrSèNkX‰ØèïÿÿPÿuSèûÌ‹S‰ƒÀƒCÇB‹]üÉÃU1ɉåV‹uSƒxuG‹€yt…Ò~$¶A9ÂÁâD¹äëC‰ë#…Ò‹Y~;S$~1Éë‹D‘‹@‰‹C‹LüƒÁ[‰È^]ÃU‰åWVSR‹}‹U‰øèÒíÿÿUðR‹Uèƒÿÿÿ‰Æ…öXt‹]ð‹O‹‹S‰‹C‰Q‰AƒÁ‰Oeô‰ð[^_]ÃU‰åWVSSS‹U‹Eè†íÿÿ‹U‰ÇEðP‰øè3ÿÿÿ‰Eì…ÀYtD‹E‹]ð‹pNð‹Vô‰H‹Fð‰S‰‹A‰Cƒy~‹VðöBt‹ö@t
RPÿuèôjƒÄ‹Eìeô[^_]ÃU‰åVuˆSƒìp‹]VÿuSèœ=ƒÄ…Àt(VhðëCSè›E‹EœƒÄ…À~PE¬PhóëCSè]õÿÿë
jhûëCSè¢ôÿÿeø[^]ÃU‰åVuS‹]jSè’ÿÿÿVÿuSèôôÿÿjSèhýÿÿSèýÿÿeø[^]ÃU‰åWVu„Sƒìp‹}V‹]jWè=ƒÄ…ÀuÿuShüëCë.VhìCWèEhìCÿuŒè}ƒÄ…ÀuKuÿuÿuˆhìCWèmÿÿÿëƒ}ˆuÇEˆ9ìCÿuÿuˆSh;ìCWèLÿÿÿeô[^_]ÃU‰åWVS‹}‹]‹uWSè¨ïÿÿZYPSè¾ïÿÿZYPVhYìCSè]ôÿÿ‰EƒÄ‰}‰]eô[^_]é0ÿÿÿU‰åV‰ÖS‰ÃÿuPè…ïÿÿZYPVSèžÿÿÿeø[^]ÃU‰åV‹uS‹]VhðØÿÿSèdõÿÿjÿSè6ïÿÿƒÄ1Ò…Àu+jþSèeíÿÿjjSè	öÿÿjÿSèäîÿÿVhðØÿÿSè÷ÿÿºeø‰Ð[^]ÃU‰åWV‹uS‹]VSè8òÿÿ‰Ç…ÿXZt8VSèöÿÿZ…ÀYt+ÿuhðØÿÿSèéôÿÿjþjÿSè‘ïÿÿƒÄ…ÀtjýSèêìÿÿ‰øëÿuVSèÞþÿÿ1Àeô[^_]ÃU‰åVS‹]‹uÿuSè™ëÿÿY…ÀZu‰uÇEmìC‰]eø[^]éæýÿÿeø[^]ÃU‰åWVS‹u‹}‹]VWèCîÿÿY9ØZt‰]eô‰ò[‰ø^_]é²þÿÿeô[^_]ÃU‰åV‹uS‹]SVèîÿÿY@ZuhìCSVè·ýÿÿƒÄeø[^]ÃU‰åW‹}V‹uSÿuVWè/ðÿÿƒÄ…À‰Ãuj‰ò‰øèSþÿÿYeô‰Ø[^_]ÃU‰åWVSS‹E‹}‹u‹]‰EðWPè£íÿÿZ…ÀY…Ût/1À…öt
üƒÉÿ‰÷ò®÷ÑAÿ‰ë‰]‹Eð‰}‰Eeô[^_]éuÿÿÿeô‰ð[^_]ÃU‰åWVSSS‹E‹}‰Eð‹E‰Eì‹E…ÀtjPÿuìÿuðètÿÿÿƒÄëjÿuìÿuðè-ÿÿÿƒÄ1öƒ?‰ÃtSÿ4·èˆZ…ÀYt3Fƒ<·ëèShìCÿuðè¿ñÿÿ‰E‹EìƒÄ‰E‹Eð‰Eeô[^_]éŒüÿÿeô‰ð[^_]ÃU‰åVSQQ‹]‹uSVènîÿÿXÝ]ðÙîÝEðZÚéßàžuzSVèøìÿÿZ…ÀYuj‰ð‰Úèýÿÿ^ÝEðeø[^]ÃU‰åVSSS‹]‹uÝEÝ]ðSVèfìÿÿZ…ÀY~‰]‰ueø[^]ëˆÝEðeø[^]ÃU‰åWV‹uS‹]SVè îÿÿ‰Ç…ÿXZuSVè‚ìÿÿZ…ÀYuj‰ð‰Úèüÿÿ^eô‰ø[^_]ÃU‰åWVS‹]‹u‹}SVèôëÿÿY…ÀZ~‰]‰ueô[^_]ë—eô‰ø[^_]ÃU‰åS‹]ÿuSèðòÿÿYZ1Ò…Àt9ÿuSèðÿÿjþSè&òÿÿjÿSè¤ëÿÿƒÄ…ÀujýSèÕéÿÿ1Òë
jþSèêÿÿº‹]ü‰ÐÉÃU‰åW‹}V‹uS†'‰ó='wWè‹éÿÿY\0ÿuSWèxÿÿÿƒÄ1Ò…ÀtSWèëÿÿjjWèõÿÿºeô‰Ð[^_]ÃU‰å‹E‹UÇ@‰PP‰]ÃU‰åWV‹uS‹]ÿuVèÆêÿÿXZj.Sè6Y…À_‰Çuü‰ßƒÉÿ1Àò®÷Ñ|ÿ‰ø)ØPSVèèîÿÿjþVè9ñÿÿjÿVè·êÿÿƒÄ…ÀuBjþVèèèÿÿ€?.‹Eu¸PjVè€ñÿÿ‰ø)ØPSVè§îÿÿƒÄ jþVèLêÿÿjüVèTòÿÿƒÄëjÿVèfêÿÿYƒøZtjýVè—èÿÿ‰Øëjþ_VèÔèÿÿ€?.XZ„Jÿÿÿ1Àeô[^_]ÃU‰åWVSPP‹]‹E‹u…Û‹}‰Eð„–ÇEìƒ8tÿEìƒÀëójh¤ìChðØÿÿVèäþÿÿSjÿVèðÿÿjÿVèÝéÿÿƒÄ$ƒøtAjþVè
èÿÿÿuìShîØÿÿVè´þÿÿƒÄ…ÀtSh¬ìCVè1ùÿÿƒÄjÿVèqéÿÿSjýVè¤ñÿÿƒÄjþVèèÿÿ‰ø÷ÐPVèKèÿÿƒÄ‹Uðƒ:tC…ÿ~‰û‰ø÷ØPVè6éÿÿYKXuðW‹EðÿpVèKîÿÿ‹UðG÷Øÿ2PVèOñÿÿƒEðƒÄ‹Eðƒ8뻉u÷׉}eô[^_]é_çÿÿU‰åjÿuÿuÿuèÙþÿÿÉÃU1Ò‰åV‰ÆS‹)ðƒètP^SÿvèíÿÿÿFº‰eø‰Ð[^]ÃU‰åS‹]‰ØèÀÿÿÿÿsÿsèÒõÿÿÇC‹]üÉÃU‰åWV‰ÆSƒìƒx~jÇEð‹xjÿWèMëÿÿY‰ÃX‹Eð@‰Eì÷ØPWè9ëÿÿZ‰Á‹FZ‰Eè+Eð@ƒø	ŸÂ9Ë—À	Шt‹EìˉEð‹Eè9Eð|ÁÿuðWèWõÿÿ‹F+Eð@‰FXZeô[^_]ÃU‰åS‹]‰Øèÿÿÿ…Àt‰ØèdÿÿÿC[]ÃU‰åW‹}V‹uS‹]Kƒûÿt‡9rWè¼ÿÿÿX¶F‹ˆÿëÝeô[^_]ÃUü‰å1ÀW‹UƒÉÿ‰×ò®÷ÑIQRÿuè¨ÿÿÿ‹}üÉÃUü‰åW1ÀVƒÉÿSì‹}‹uò®…äýÿÿ÷ÑIPÿu‰àýÿÿè^üÿÿ[_ë!‰Ø)ðPVWèaÿÿÿÿuWè’ÿÿÿ‹…àýÿÿƒÄ4ÿu½äýÿÿVè‰Z…À‰ÃYuÈVWèhÿÿÿWèaþÿÿjjÿÿuè}éÿÿeô[^_]ÃU‰åEðWVSQ‹]‹sPjÿVè\éÿÿ‹‰Ç‰Ø‹UðƒÄ)È9ÂwRWQ蘋EðjþVè åÿÿƒÄë‰ØèÊýÿÿ…Àt
jþVè’åÿÿXZÿC‰Øè	þÿÿeô[^_]ÃU‰åW‹}VS‹]ƒ'='‰ÞwWèÂäÿÿ^tjÿWè†æÿÿY…À[u
jþWè¸äÿÿƒÈÿëNjVWèíÿÿjÿWèMèÿÿjþ‰ÃWè˜äÿÿƒÄ…ÛtSVWèûìÿÿjVWèïÿÿƒÄëVWèñèÿÿ‰ÃCXZSVWèïÿÿ‰Øeô[^_]ÃU‰åWVSQ‹E‹}‹]…À‰EðxRƒ'‰Þ='wWè äÿÿZtjVWè•ìÿÿÿuðVWè³îÿÿÿuðWèÖéÿÿÇEƒÄ ‰u‰}eô[^_]éŽîÿÿeô[^_]ÃU‰å‹MV‹uSƒ9tǸÊìCÇë+‹Q1ÀöBu RYhjS蘉ƒÄ…À‰Úu1Ò‰Ðeø[^]ÃU‰åW‰×VS‰ÃèSÿ0è\j‰ÆÿuSè„çÿÿV@PWhÌìCSèòéÿÿƒÄ$ÿuSè¥ãÿÿeô¸[^_]ÃU‰åWVSì‹uVè&ãÿÿÇ…äýÿÿ@ƒ}‰…àýÿÿXujhÝìCVèóèÿÿ¡È2DƒÄ‰…èýÿÿë8ÿuhäìCVèéÿÿhèìCÿuèò‰…èýÿÿƒÄ…ÀuÿµàýÿÿºêìCél‹•èýÿÿ‹BH‰B…Àx
‹¶@‰ë	RèÄ_‰Áƒù#ucÇ…äýÿÿ‹•èýÿÿ‹BH‰B…Àx
‹¶@‰ë	Rè‘[‰Áƒùÿtƒù
uÒëƒù
u$‹•èýÿÿ‹BH‰B…Àx
‹¶@‰ë	Rè\Y‰Áƒù”À1Òƒ}•Â…ÐthÿµèýÿÿhïìCÿuèÓ‰…èýÿÿƒÄ…ÀuÿµàýÿÿºòìCé‹•èýÿÿ‹BH‰B…Àx
‹¶@‰ë	RèõZ‰ÁƒùÿtƒùuÒÇ…äýÿÿÿµèýÿÿQèbjjÿVè½åÿÿƒÄP…äýÿÿPh	:@Vèüîÿÿ‰Ç‹…èýÿÿƒÄ‹Xƒã ƒ}tPèX…Ût ÿµàýÿÿVèiáÿÿÿµàýÿÿºùìC‰ðèÀýÿÿëÿµàýÿÿVè•áÿÿ‰øeô[^_]ÃU1À‰å‹M‹Q…Òt‹E‰‹ÇA]ÃU‰åPP‹Eÿu‰Eø‹E‰EüEøPh¶<@ÿuè`îÿÿÉÃUü‰åW‹U1ÀƒÉÿ‰×Rò®÷ÑIQRÿuèºÿÿÿ‹}üÉÃU‰å‹E‹U…Àt‰E‰UÉéGRè¡É1ÀÃU‰åjjÿÿuè³äÿÿƒÄP¡È2DhþìCƒÀ@PèÉ1ÀÃU‰åSjh =@è¹Y‰Ã…ÛXt
hC=@SèàÿÿXZ‰Ø‹]üÉÃU‰åW¿VSQ‹]Sè/àÿÿhuîChîØÿÿS‰EðèèÿÿƒÄ;}ðmjÿSè®áÿÿWSè§áÿÿjjSè)ìÿÿjjÿSèäÿÿƒÄ(…À‰Æu
hxïCSè4ñÿÿëFƒÿ~¡È2DƒÀ Pj	èXZ¡È2DGƒÀ PVèjþSè½ßÿÿƒÄ뎡È2DƒÀ Pj
èÓ1Àeô[^_]ÃU‰åWVSV‹uj
jVè@õÿÿƒÄƒø
‰Ãu*jVèóÿÿjVèŒáÿÿƒÄ…À„ŸjVèÕâÿÿY[é‚jjVèóÿÿ‰ÇCþƒÄƒø"vh£ïCjVèªðÿÿƒÄSEðPWè_ƒÄ;}ð‰ÃtTë@‰Eð‹E𶡬2Dƒ8u¡Ø2D‹·Pƒàë
jRèG_Z…À‹EðuË€8u1ÒRSß,$ƒÄƒìÝ$VèsäÿÿëVèSäÿÿeô¸[^_]ÃU‰åVS‹]jjSèWôÿÿj‰ÆSè—ÞÿÿjSèåàÿÿƒÄ…Àt…ö~VSèhïÿÿjSèàÿÿjSè@íÿÿƒÄ‰]eø[^]éâìÿÿU‰åS‹]jSèëñÿÿjSè0çÿÿƒÄ…ÀuSèËãÿÿë
hµïCjSèôÿÿ‹]ü¸ÉÃU‰åV‹uSjVèÏßÿÿj‰ÃjVèjñÿÿƒÄ…Û”ƒû”À	ШuhÁïCjVèZïÿÿƒÄhµïCjVè½óÿÿƒÄ…Àt
h×ïCVèïÿÿXZjVè¶ÝÿÿjVè¶èÿÿeø¸[^]ÃU‰åWV‰ÖSƒìp‰ÃjPèMßÿÿZƒøYujSèßÿÿ_Xë…ötjjSè"óÿÿƒÄë
jSè×òÿÿY^…À‰ÆyhûïCjSèÂîÿÿƒÄ}„WVSèÛ+ƒÄ…ÀuhðCjSè îÿÿƒÄWh$ðCSèÊ3jÿSèÑÞÿÿƒÄ…ÀuVh&ðCSèDîÿÿƒÄeô[^_]ÃUº‰åS‹]‰Øè>ÿÿÿjÿSèÐÞÿÿZ…ÀYt
hîØÿÿSèXÞÿÿëjÿSèõåÿÿ[‹]üX¸ÉÃU‰åS‹]jjSèðÿÿ1Ò‰ØèõþÿÿjSè ÞÿÿjSè£ÞÿÿƒÄ…Àt1jSèðßÿÿXÙîÙÉÚéßàžZuzSèäÿÿjþSèåÜÿÿjþSèíçÿÿ1Àë.jþSè?ÞÿÿZ…ÀYujþSèÓçÿÿZ…ÀYu
hXðCSèníÿÿ[X¸‹]üÉÃU‰åS‹]jSè«ïÿÿjSè£ïÿÿjjSè“ÞÿÿƒÄPSèRãÿÿ‹]ü¸ÉÃU‰åS‹]jjSè=ïÿÿjSèlïÿÿjSèÆÛÿÿjSèøãÿÿ‹]ü¸ÉÃU‰åS‹]jjSè
ïÿÿjSè9ïÿÿjSè1ïÿÿjSè‹ÛÿÿƒÄ$jSè¨åÿÿ‹]ü¸ÉÃU‰åS‹]jjSèFéÿÿƒÄPSè!áÿÿ‹]ü¸ÉÃU‰åW‹}VShÐðCh™ðCjWè–ïÿÿj‰ÃjWèàðÿÿPÿ4ððCWèýèÿÿ‰Æ‹ððCƒÄ(ƒøtƒøt#ë*jjWèÛèÿÿVÛ$‰$Û$ƒìØ
ñCÞÁëVWè=âÿÿëVÛ$ƒìÝ$Wèuàÿÿeô¸[^_]ÃU‰åS‹]jSèLîÿÿjSèfÜÿÿYZPSè|ÜÿÿYZPSè²àÿÿ‹]ü¸ÉÃU‰åS‹]jjSèàíÿÿjSèqÚÿÿjSèþèÿÿƒÄ…ÀºuSèêßÿÿº‹]ü‰ÐÉÃU‰åS‹]jjSè¡íÿÿhíØÿÿSèÀÛÿÿjSè¸ÛÿÿSè´ßÿÿ‹]ü¸ÉÃU‰åV‹uSjVèïÿÿj‰ÃCjVèaíÿÿSVè¹ßÿÿSjVè\âÿÿƒÄ(jÿVèŸÛÿÿYƒøÀ÷Ѓà[eø[^]ÃU‰åS‹]jjSè"íÿÿhíØÿÿSèAÛÿÿjSè9ÛÿÿjSèfßÿÿ‹]ü¸ÉÃU…Ò‰åS‰Ã¸tSèßÿÿjþSèÚÿÿ¸‹]üÉÃU‰åEôVSV‹]PjSè%íÿÿj‰ÆPjSèMíÿÿPÿuôVSè"øÿÿ‰ÂƒÄ‰Øè ÿÿÿeø[^]ÃU‰åS‹]jjjSèíÿÿƒÄPSèÆõÿÿZ‰Â‰ØY‹]üÉémÿÿÿU‰åVS‹]‹uhñCjSèìÿÿjSètÚÿÿjjSèöäÿÿƒÄ jÿSèŽÚÿÿY…ÀZuÇë=jÿSèÛÿÿY…ÀZt"jSèÙÿÿXZ‰uÇE‰]eø[^]é Üÿÿh*ñCSèËéÿÿ[^eø1À[^]ÃU‰åVS‹]jhOñCjSècìÿÿj‰ÆjSè¾ëÿÿjSèOØÿÿƒÄ$VjhòD@Sè£åÿÿƒÄeø‰Â‰Ø[^]é–þÿÿU‰åWV‹uSjjjVèìÿÿV‰Ãèþ×ÿÿS‰ÇVèºôÿÿƒÄ…ÀtVèæÿÿYjÿjVèäÿÿVè××ÿÿeô)ø[^_]ÃU‰åS‹]jSèmëÿÿjSè¯ÛÿÿƒÄ…Àt‰]‹]üÉé£×ÿÿjhWñCjSè¥ëÿÿƒÄPhiñCSèÜèÿÿ‹]üÉÃU‰åWVSjjÿuèæêÿÿjjÿuè)íÿÿƒÄ‰Ãjÿuè$ÙÿÿZ…ÀYjÿuèÑÛÿÿë
jÿuèÀìÿÿ^‰Æ1À_9ó@‰ð)Øx…ÿ~WÿuèÖÿÿZ…ÀYuhlñCÿuè]èÿÿëSjÿuè|ßÿÿ‰ØƒÄC9ð|ë‰øeô[^_]ÃU‰åW‹}VSWèÖÖÿÿj‰ÆWèØÿÿƒÄƒøu#jjWèÛÚÿÿƒÄ€8#uFÿPWèÜÿÿ¸ë2jWè"ìÿÿ‰Ã…ÛXZyóë9ó~‰ó…Ûh‡ñCjWèÿçÿÿƒÄ‰ð)Øeô[^_]ÃU‰åS‹]jSèêÿÿjjÿSèNÖÿÿH‰$SèÃâÿÿ…À”À¶ÀPSè§ÝÿÿƒÄ jSèÅÖÿÿYX‰]‹]üÉéÖÿÿU‰åS‹]jSè¼éÿÿjSèÖÿÿjSè˜ÖÿÿjjÿjSèpâÿÿƒÄ(…À”À¶ÀPSèQÝÿÿjSè¿Öÿÿ‰]ƒÄ‹]üÉéÈÕÿÿU‰åS‹]jSèhéÿÿhšñCjSèìÿÿƒÄ…À…ŸjSèj×ÿÿZƒøYt.…ÀtKë[ƒøtƒøtëOjjSè•ÙÿÿƒÄPë#jSè×ÿÿëjSèUÙÿÿZ…Àº¥ñCYuºªñCRSètÛÿÿ[Xë?jh°ñCSè&ÛÿÿƒÄë-jSèÚÿÿZYPjSèíÖÿÿZYPSè×ÿÿZYPh´ñCSè£ÛÿÿƒÄ‹]ü¸ÉÃU‰åV‹uSjVèùÔÿÿjVègäÿÿjVèÑØÿÿƒÄ…À„‹jVè–Öÿÿ[HZu*jjVèuÝÿÿjÿVèPÖÿÿjVèÜÿÿhíØÿÿVèÔÞÿÿƒÄ$ëLjVèŠÝÿÿZ…ÀYt$híØÿÿVèÈÜÿÿjÿVènØÿÿjþ‰ÃVè|ÔÿÿƒÄ…Ûuh»ñCjVèàåÿÿƒÄjVèHÝÿÿ[XjVè[ßÿÿeø¸[^]ÃU‰åS‰Óƒìp1Ò9ØtDSèâÿÿZ…Àt
Hºt1ë*EŒPjSè¶"ƒÄ…ÀºSèôÓÿÿYƒøÒƒâB뺋]ü‰ÐÉÃU‰åV‹uSjVèÙÿÿY‰Ã…ÛXuhÕñCjVè@åÿÿƒÄ‰Ú‰ðèuÿÿÿÿ4…ÀíCVèÍÙÿÿeø¸[^]ÃU‰åW‰×V‰ÆSèMÿÿÿÿu‰ÃWèdÒÿÿZ…ÀYu
hèñCVè¾äÿÿYXƒûtÿ4ÀíChòCVèìÙÿÿë]ÿuWVè”ÒÿÿWVèàÒÿÿÿuWè!9ƒÄƒøw2Wè$Óÿÿ‰Ã@PVèÒÿÿƒÄ…Àu
h òCVè]äÿÿXZSVWèNÒÿÿ‰ØëjVWèAÒÿÿƒÈÿeô[^_]ÃU‰åV‹uSjVè!Øÿÿ‰Ã…ÛXZuhÕñCjVèHäÿÿƒÄVè¶ÒÿÿH‰Ú‰$‰ðèÿÿÿ‰Ã…ÛXyjVèÚÿÿjþVè-Óÿÿ¸ëjCVèôÙÿÿ‰Ø÷ØPVèÓÿÿ‰Øeø[^]ÃU‰åV‹uShíØÿÿVè¨×ÿÿV‰ÃèSÒÿÿ‰$‰Ú‰ðèµþÿÿƒÄ…À‰Ãy0jÿVèÔÿÿZ…ÀYtjVè$ãÿÿjþVè»ÒÿÿjVèüàÿÿƒÄVè¦àÿÿYeø‰Ø[^]ÃU‰åVS‹]SèÃÑÿÿj‰ÆSè¾ÓÿÿƒÄƒøujSèæÓÿÿZ…ÀYth;òCjSèSãÿÿƒÄjSèaÓÿÿjVSèÑÿÿeø¸[^]ÃU‰åS‹]Sè˜ÿÿÿjhvK@SèYØÿÿ‹]ü¸ÉÃU‰åS‹]SèyÑÿÿ‰$Sèø7‹]üÉÃU‰åS‹]SèÙÿÿZ…ÀtSè÷Öÿÿ[‹]ü¸ÉÃU‰åV‰ÖS‰ÃjÿuPèý×ÿÿjÿuSèò×ÿÿVjþSèþÚÿÿeø[^]ÃU‰åS‹]hîØÿÿSè©ÒÿÿYXhQòChîØÿÿSèÓÚÿÿƒÄh°îChQòCSè”éÿÿƒÄjhTòCSèÄÖÿÿƒÄh\òChîØÿÿSèÚÿÿƒÄ‰ØºeòChÞC@h)D@è^ÿÿÿX‰ØZºlòChkC@hªC@èFÿÿÿYXjjSèAÙÿÿƒÄjÿSèÒÿÿXZjþSè†ÛÿÿYXjhròCSèPÖÿÿƒÄhuòCjþSè,ÚÿÿƒÄjhìH@Sè×ÿÿƒÄh|òChîØÿÿSè	ÚÿÿƒÄhpíCh…òCSèÊèÿÿ‹]ü¸ÉÃU1Ò‰åƒ8uƒxÿuƒxÿu²]‰ÐÃU‰Á‰åVS‹‹]‹@)Ó4Cÿ™1Ð)Ð=ÿÿ~hòCÿqè\XZ‹ƒþÿÁàâÿ?	‰eø[^]ÃU‰å‹U‹B‰B]ÃUƒÉÿ‹‰å‹@‹Áè-ÿÿƒøÿtL]‰ÈÃU‰åWVS‹u‹}‹Eƒþÿt-‹ƒúÿ‰Óu‰0ë ‰Ã‰Ú‰øè±ÿÿÿƒøÿuð‰u‰Ú‰ø[^_]é@ÿÿÿ[^_]ÃU…Ò‹‰å‹@~‹Aüƒà?€¸DyAüë‰È]ÃU‰åV‰ÆS‰Óƒûÿt'‰Ú‰ðèÂÿÿÿ‹ƒà?ƒøt¸ë‰Ú‰ðè?ÿÿÿ‰ÃëÔ1À[^]ÃU‰åV1öS‹]èÿÿÿ‹‰Á‰Ðƒà?ƒøu@ûÿt‰ÐÁè9ÃtÁãâ?ÀÿÿãÀ?	Ú‰ë‰ÐÁèâÀÁà	ЃÈ‰¾[‰ð^]ÃU‰åV‰ÆS‰Óƒûÿthÿ‰Ú‰ðèÿÿÿY‰Ú‰ðè¬þÿÿ‰Ãëßeø[^]ÃU‰åWV‰ÆS‰Óƒûÿt2‰Ú‰ðè‰þÿÿÿu‰Ú‰Ç‰ðèFÿÿÿZ…Àtÿuëÿu‰Ú‰ðè	þÿÿ[‰ûëÉeô[^_]ÃU‰åS‹]Sè=þÿÿÿuC PSèaþÿÿ‹]üÉÃU‰å‹E‹M‹U;Hu]ë͉MÇEÿ‰M]éqÿÿÿU‰åV‹uS‹‹^$]¶@K9Ã~ûù~h«òCÿvèÊYYX‹ˆXKeø[^]ÃU‰åV‹uS‹]VSè³ÿÿÿs$eø[^]ÃUöƉå‰Áu¶@29Â|ÿI$]ÃU‰åƒ:u]‹RëÛ]ÃU‰åWV‰ÆSƒì‹@Rÿv‰EèPè?ɃÄƒx‹‹{(u!ÝÙ}ò·Eò€Ìf‰EðÙmðÛ]ìÙmò‹EìéœÛF(Ç@Ý‹F(@;C(~!hÎòCC(hÿÿjPÿsÿuèè¨m‰CƒÄ;{(}‹S‰øÁàÇDGƒÀ;{(|ï‹F(‹}ÁàC‹‹O‰‹W‰H‰Pƒ~‹ö@töCt
PSÿuèèHƒÄ‹V(B‰F(‰Ðeô[^_]ÃU‰åƒìÇEø‹MUðR‹E‰MðèóþÿÿÉÃU‰åƒìÝEÇEø‹EUðRÝ]ðèÒþÿÿÉÃU‰åWVSP‹E‹u‹}‰Eð‹ƒø
u$‹‹^‹H‹Eð‹™@Áàâÿ?€ÿ%À	‰™ëRƒøuM‹‹^‹H‹Eð‹™@Áàâÿÿ	‰™‹^‹G$‹™Áà%À?â?Àÿÿ	‰™ÇE‰}X[^_]éýýÿÿX[^_]ÃU‰å‹ES‹]‹ƒú
uÇ‹‹S‹@‹Áè%ÿ‰Cë#ƒúuÇ‹‹K‹P‹Š%ÿÿ
‰Š[]ÃU‹R‰åè×ûÿÿ‰Á‹‰ÂÁèâ?Àÿÿ„ÀuƒÊ@‰]ÃU‰å‹E‹‹H‹E‹R‰DŠü]ÃU‰åW‰×VS‹0‰Ã‹P ÿphÿÿpè}üÿÿÇC ÿÿÿÿ‹CƒÄ@;F,~!hæòCF,hýÿÿjPÿvÿsè~k‰FƒÄ‹C‹V‰<‚‹C@;F0~!hæòCF0hýÿÿjPÿvÿsèKk‰FƒÄ‹K‹V‹E‰Š‹CP‰Seô[^_]ÃU‰å‹U‹M‹EÁâUÁá	Ê‹H‹I‰M]é7ÿÿÿU‰åVSP‹]‹s ÇC ÿÿÿÿhþÿjjSè¸ÿÿÿ‰EôEôVPSègúÿÿ‹Eôeø[^]ÃU‰åS‹U‹M‹EÁâ‹]UÁáÁã	Ê‹H	Ú‹I‰M[]éÍþÿÿU‰åS‰ÃÿuÿuÿuRPèºÿÿÿ‰]ƒÄ‹]üÉéqÿÿÿU‰åV‰ÆS‰ÓPèÈùÿÿÿuÿuSjVèÿÿÿeø[^]ÃU‰åVS‹]‹u‹ƒèƒøwxÿ$…üòCÇëijÿsjjë9ÿsjjVèêþÿÿ‰CƒÄÇëC‹S‰ðè±ûÿÿ‹S‰ðè§ûÿÿÿsÿsjjVèÿÿÿ‰CƒÄÇë‰]‰ueø[^]éeýÿÿeø[^]ÃU‰å‹Ej@PÿujÿuèÛþÿÿÉÃU‰åWV‹uS‹]‹V;V~X…Òu
¶F29Ã|Lë]‹‹@<‹Wü‰Ðƒà?ƒøu5‰Ð‰ÑÁè%ÿÁé9Ø"A9ËuD3ÿ9È~#âÿÿÁà	‰Wüëj‹UDÿPSjVèZþÿÿeô[^_]ÃU‰åW‹}V‰ÖS‰ÃRPè¸þÿÿXZ‹Bÿƒø‡Šÿ$… óCjWSèEÿÿÿƒÄëlj1Àƒú”ÀPWjëSÿvëÿvÿvSè­ûÿÿƒÄPWjSè‹ýÿÿƒÄë9‹‹N‹@ˆ‹‰øÁà%À?â?Àÿÿ	‰ë‹F9ÇtjPWjSè°ýÿÿƒÄ‰~Çeô[^_]ÃU‰åV‰ÖS‰Ãƒ:tjPèéùÿÿ‹C$‰òHP‰Øè&ÿÿÿƒÄeø[^]ÃU‰åW‹}V‰ÖS‰Ãƒ:u-‹‹R‹@‹‰Ðƒà?ƒøuÿK1À…ÿ”ÀÁêPjRºë ‰ò‰ØèŠÿÿÿ‰ò‰Øè³ùÿÿWºÿvhÿ‰Øè8ýÿÿeô[^_]ÃU‰åV‹uS‹]SVèhýÿÿX‹Zƒèƒøw"ÿ$…PóCƒÈÿë"Vè–üÿÿë‰ð‰Úè†ûÿÿ‹Cëj‰Ú‰ðèGÿÿÿYPCPVè÷ÿÿÿsVè‚øÿÿÇCÿÿÿÿeø[^]ÃU‰åW‰ÇVSVV‰Öÿuè,þÿÿƒ>
[uÿvFPWèÈöÿÿƒÄ‹V;V„‘ÇEðÿÿÿÿ‰øÇEìÿÿÿÿè÷ÿÿ…Àu‹V‰øè÷ÿÿ…Àt=ƒËÿƒ>
t	WèíûÿÿY‰Ãj‹U‰øjèküÿÿj‹Uj‰Eð‰øèZüÿÿSW‰EìèÝ÷ÿÿƒÄWèöÿÿÿuð‰Ã‹VÿuP‰øèx÷ÿÿÿuì‰ø‹VÿuSèg÷ÿÿƒÄÇFÿÿÿÿ‹EÇFÿÿÿÿÇ‰Feô[^_]ÃU‰åVS‹u‹]VSèüÿÿ‰ò‰Øè$øÿÿjSèé÷ÿÿ‹C$ƒÄ‰òH‰Eeø‰Ø[^]éÛþÿÿU‰åV‹uS‹]SVèÕûÿÿƒ;XZu#‹C‹S9Cu‰Ðë¶F29Â|R‰ð‰Úè¡þÿÿëSVèÿÿÿ‹Ceø[^]ÃU‰å‹U‹M‹B9Bt]량U‰M]ézûÿÿU‰åVSƒì0‹u‹]VSèËÿÿÿX‹Zƒøt}wƒø‚ëƒøuz{(ÿqƒøuÇEà‹CUèÇEð‰EèEØPë-ƒøuÿvÿvSèIøÿÿƒÄëÇEЃøUÈR”À¶À‰EȉØè÷ÿÿY‰FÇë
‹F=ÿ€ÌëVSèâþÿÿeø[^]ÃU‰åWVSƒì ‰Ã‰Uð‹E‹uèñóÿÿ…À„´‰ðèâóÿÿ…À„¥ÝF‹EÝ@‹Eðƒèƒøwtÿ$…tóCÞÁëqÞÉëmÙîÙÊÝâßàÝÚžztoÞñëZÙîÙÊÝâßàÝÚžzt\ÙÉÝUàƒìÙÁÝ]ÔÞùÝ$èþõÝEàXÝEÔÙÉÞÊZÞáë$ÙɃìÝ\$Ý$èíõƒÄëÝÙÙàëÝØÝØÙîë	Ýàßàžuz
‹UÝZëvÝØÝØƒ}ð•À1Òƒ}ð•Â1ÿ…ÐtVSèVþÿÿY_‰ÇÿuSèIþÿÿY9ø‰EìZ~‹U‰ØèÌõÿÿ‰òë‰ò‰Øè¿õÿÿ‹U‰ØèµõÿÿWÿuìjÿuðSèùÿÿ‹UƒÄ‰BÇeô[^_]ÃUÙî‰åVSƒì ‹EÇEìÿÿÿÿ‹u‹]ÇEèÿÿÿÿƒøÇEØÝ]àtYXuI‹‹V‹@‹ƒà?ƒøu6‰Ø‰úètóÿÿÇ‹‹^‹H‹G‹™Áàâÿÿ	‰™‹F‰GéåVSèûÿÿXZº‰u‰}ëL‰uº‰}ë?‰uº
‰}ë2‰uº‰}ë%‰uº‰}ë‰uº‰}ë‰uº‰}eô‰Ø[^_]éùûÿÿ‰u‰}ÇEë
‰u‰}ÇEºëD‰u‰}ÇEë‰u‰}ÇEë!‰u‰}ÇEºë‰u‰}ÇEºeô‰Ø[^_]éàýÿÿeô[^_]ÃU‰åVS‹E‹u‹]ƒø‡—ÿ$…ôC‰]‰ueø[^]镸ÿÿSVèöÿÿX‹ZƒøtwHtëƒøtƒø
tëƒÈÿëVè-õÿÿë‹Cëj‰Ú‰ðèç÷ÿÿYPCPVè¦ïÿÿƒÄÿsVèñÿÿXZÇCÿÿÿÿë-‰]‰ueø[^]éxùÿÿ‰ØèÜîÿÿ…Àu‰]‰ueø[^]éúÿÿeø[^]ÃU‰åS‹]ÿuÿuèìùÿÿ‰CÇ	‹]üÉÃU‰åWV‹uS‹]ÿuSè\ùÿÿ‹U‰ØèUñÿÿ‹{$jSèñÿÿVSè­ùÿÿYZP‹EÿpWjSè›ôÿÿ‰ØƒÄ$‰òè%ñÿÿ‹E‰xÇeô[^_]ÃU‰åWVS‹u‹]‹}‹ƒøt4wƒøtëmƒøt7ƒø	tJëa‰ú‰ØèÝðÿÿ‹F‰ú‰Eeô‰Ø[^_]éŸ÷ÿÿWSè½øÿÿjÿvPjë(WSè¬øÿÿÿvPjSè­óÿÿƒÄëWSèùÿÿPÿvÿvj	SèòóÿÿƒÄeô‰Ø‰ú[^_]éuðÿÿUº2‰åW‹E‰ÑV‹}‹uSH™÷ùX‹Eƒøÿu1ÀûÿSPWj"Vè¥óÿÿƒÄëjPWj"Vè”óÿÿ‹F‰Úÿp‰ðè‚òÿÿƒÄG‰F$eô[^_]ÃU‰åhðØÿÿÿuèÆ¾ÿÿɸÃU‰åS‹]jSè½ÐÿÿjSèÆÿÿƒÄ…ÀuSèÂÿÿX‹]ü¸ÉÃU‰åS‹]jSè°¾ÿÿZ…À”ƒø”À	ÐY¨uhYõCjSèHÎÿÿƒÄjSèżÿÿjSèÅÇÿÿZYPSèÄÿÿ‹]ü¸ÉÃU‰åjÿuèÕÅÿÿɸÃU‰åS‹]jjSèìÏÿÿjSè}¼ÿÿjSèÈÿÿƒÄ…Àu
hoõCSè©Íÿÿ[X‹]ü¸ÉÃU‰åV‰ÆS‰ÓÿuPècÂÿÿSjþVè	Æÿÿeø[^]ÃU‰åV‰ÆS‰ÓÿuPèéÁÿÿSjþVèçÅÿÿeø[^]ÃU‰åV‰ÖS‰ÃjPè½ÿÿZƒøYujÇSè)ÁÿÿëljØeø[^]ÃU9ЉåS‰ÃujþPè[½ÿÿjýSè¼ÿÿƒÄëjPRèõºÿÿƒÄÿujþSèsÅÿÿ‹]üÉÃU‰åU€WVSƒìt‹]‰Øèxÿÿÿj‰Ç‹E€h£õCƒÀPSèuÏÿÿ‰Æ‹E€@PS脽ÿÿƒÄ…À‹U€t)E„PBPSèû¾ÿÿZYPWèæ	ƒÄ…Àu[SèÍÀÿÿé…BPSèë¼ÿÿZƒøYu4Vh©õCSè¥ÁÿÿjjÿSè¿ÿÿ‰Æ‹E€@PSè’¼ÿÿƒÄ jWSè6ºÿÿƒÄëh­õC‹E€@ëE„PVW苃Ä…ÀuhÈõC‹E€ƒÀPSè9ÌÿÿéjjSè`ÃÿÿjSVèµëƒÄ…ÀtOÿu”º×õC‰Øè=þÿÿE¨ºÞõCP‰Øè-þÿÿÿu ºèõC‰Øè@þÿÿÿu¤ºôõC‰Øè1þÿÿÿuºöC‰ØèþÿÿƒÄjlVèWëZ…ÀYtÿu˜‰Øº	öCèþÿÿXjuVè9ëZ…ÀYtÿuœºöC‰ØèäýÿÿYjnVèëY…ÀZt ÿuˆºöC‰Øè¤ýÿÿÿuŒºöC‰Øè•ýÿÿXZjLVèíêZ…ÀYth(öC‰ú‰ØèòýÿÿYjfVèÐê^…ÀZth4öC‰Ø‰úèÕýÿÿ[¸eô[^_]ÃU‰åU€WVSƒìt]„‹u‰ðèwýÿÿS‰Ç‹E€@PVèôÎÿÿZYPWèƒÄ…À‹E€uh9öC@PVèÔÊÿÿëGƒÀPVèÈÎÿÿZYPSWèÔƒÄ…À‰ÃtjVWèu¸ÿÿSVèK¿ÿÿjþV趺ÿÿ¸ëV諾ÿÿ¸eô[^_]ÃU‰åU€W}„VSƒìt‹]‰ØèßüÿÿW‰Æ‹E€@PSè\ÎÿÿZYPVèzƒÄ…À‹E€uh9öC@PSè<ÊÿÿëFƒÀPSèVÌÿÿ‹E€ƒÀPS諸ÿÿjVSèã·ÿÿ‹E€ƒÀPSè
ÎÿÿZYPWVè[ƒÄPS蟾ÿÿ¸eô[^_]ÃU‰åW‰×V‰ÆSjPèÚÍÿÿj‰ÃjVè½ËÿÿjVèFºÿÿƒÄ1Ò…Àu8…ÿtSjVèMÈÿÿë	SjVèÈÿÿƒÄ1Ò…ÀtP_Vè8¾ÿÿ‰Ø÷ØPV虸ÿÿ‰Úeô‰Ð[^_]ÃUº‰å‹E]ëU‰åS‹]jSè„ËÿÿX‰Ø‹]üZ1ÒÉécÿÿÿU‰åV‹uS‹]hXõCSèC¿ÿÿhðØÿÿSèð¿ÿÿSSè1¿ÿÿjþSèá¿ÿÿƒÄ jÿSè\¹ÿÿZƒøYu7‹ÿ4…pöCS褽ÿÿZ‹FY…ÀxPSè<½ÿÿ^XëSèÿ¼ÿÿYjjSè~ÃÿÿƒÄeø[^]ÃU‰åS‰ÃhXõCPèȾÿÿhðØÿÿSèu¿ÿÿjÿSèó¸ÿÿƒÄƒøt5jþSè#·ÿÿjjSèÇ¿ÿÿhXõCSè¾ÿÿjþSè—¸ÿÿƒÄ$hðØÿÿSè Áÿÿ[X‹]üÉÃU‰åUðWVSƒì‹}‰øèÈúÿÿ‰Eä‹Eð@PWè¸ÿÿZ…À‹EðY@1ÛPW躶ÿÿ^ÇEèÇEìXëtjƒÀ1ÛPWèeÊÿÿj‰Æ‹Eð@PWèòÉÿÿj‹EðƒÀPWè2Ìÿÿ‰EìƒÄ$jcVÇEèf@èrçZ…ÀYt³jrVèbçZ…ÀYtƒËjlVèQçZ…ÀYtƒËƒ}ì~ƒË‰øèÖþÿÿÿuäW覽ÿÿ‹Eð@PW誷ÿÿjýWè9ÀÿÿjþWè	¶ÿÿƒÄ ÿuìSÿuèÿuäè8eô1À[^_]ÃU‰åUàWVSƒì‹]‰ØèÄùÿÿP‰ÇèWW‰ÆèDZ…ÀYt=f@tj
h„öCS莻ÿÿƒÄë!‰ØèJþÿÿWSè½ÿÿjþSè̽ÿÿjþSèÖµÿÿƒÄ1À÷ÆUätÆEäc°÷ÆtÆr@ƒætÆl@ÆRSèp»ÿÿWèà‰$Sè	»ÿÿeô¸[^_]ÃU‰åWVSì‹u¡È2DôþÿÿƒÀ@Ph’öCèYçÿ5È2DhúSèˆçƒÄ…À„ƒhžöCSè"æZ…ÀYtrh¤öC1ÀƒÉÿü‰ßò®÷ÑIQSVè§ÓÿÿƒÄ…ÀujjjVè"ÁÿÿƒÄ…Àt/¡È2DƒÀ@PjjÿV誸ÿÿƒÄPèÜæ¡È2DƒÀ@Pj
è¬æƒÄjVèv´ÿÿ[_éHÿÿÿeô1À[^_]ÃU‰åU€WVSƒì|‹]Ç…|ÿÿÿ‰Øè2øÿÿ‰…xÿÿÿ‹E€ƒÀPSèN¶ÿÿ^…À_t‹E€ƒÀPSèÊ·ÿÿjþ‰ÆSè´ÿÿƒÄë;xÿÿÿ”À¶ðSèí³ÿÿY‹U€9Ðu	jhµöCëBPSè9¶ÿÿY…À_„jh¶öCSè­¹ÿÿƒÄjh¸öCSè¹ÿÿƒÄé.ƒþŸÀ1Òƒ½|ÿÿÿ•Â…ÐtVWF
Pÿµxÿÿÿè-ƒÄ…ÀuNë-jhÉöCSèX¹ÿÿƒÄëFE„PF
PÿµxÿÿÿèýƒÄ…ÀuåÇ…|ÿÿÿéÂjhÏöCSè¹ÿÿW}¨hÒöCÿµxÿÿÿèØ	WhÖöCS訹ÿÿ‹E˜ƒÄ$…À~PhÚöCSè’¹ÿÿƒÄ‹EŒ€8tÿuˆhÞöCSèy¹ÿÿë9‹E¶€úmuhðöCSèa¹ÿÿXZë6€úC”À€út”Â	ШtjhÿöCSè’¸ÿÿƒÄëÿu Wh÷CSè*¹ÿÿƒÄS胲ÿÿ+E€‰$Sè[Áÿÿ_X}„WVFÿµxÿÿÿèƒÄ…À…¶þÿÿSèS²ÿÿ+E€‰$Sè+Áÿÿeô¸[^_]ÃU‰åhàôCh@ôCÿuè×ÊÿÿɸÃU‰Ñ‰åS‹R‰Ãƒzu‹€xtƒÈÿë;Ku‹C‰A‹‹P‹A+BÁøH[]ÃU‰åS‰Óèºÿÿÿ‰ÁƒÈÿ…Éx‹C‹‹@‹P1À…Òt‹Š[]ÃU‰å‹MW‹}…ÉV”À‹uS‹]…Û”Â	Шt1Û1ɉND¸‰~<‰~@ˆ^8[^_]ÃU‰å‹E]‹@DÃU‰å‹E]¶@8ÃU‰å‹E]‹@<ÃU‰å‹MW‹}…ÉV‹uS‹V~‹^(9Úv‹BI‹€xu+Jƒê…Éæ…Éu‹F(9Âv")±Áúi«ªªª‰G`ë}ÇG`¹ë1É[‰È^_]ÃU‹@‰åƒxu
‹€xu‹@ë1À]ÃU‰åWV‰Æ‰ÐS‰ÓèÒÿÿÿ…À‰Çt‰Ú‰ðè–þÿÿPÿuWèƒÄ…À‰Áu,;^u‹Fë‹C+¹ ÷CÁø;EÀ1Òƒ}ŸÂ…Ðu1Éeô‰È[^_]ÃU‰å‹EWVS‹]kp`‹Ep(S‰òèyÿÿÿY…À‰ÇtÁãCðPÿuèï®ÿÿXZeô‰ø[^_]ÃU‰åWVSV‹E‹}kp`‰øw(ÿu‰òè5ÿÿÿ‰Eð…À[t‹M‹_Áá‹Cð‹Sô‰Að‹Cø‰Qô‰Aøƒo‹Eðeô[^_]ÃU‰å‹U‰Ðƒà?Häƒùw¸Óà¨GtÁê1À…Ò”Àë1À]ÃU‰å‹Mƒùtw…Ét	ë4ƒùtë-1É…Òu,ë%¶@K1É9Â} ëöÆt€æþ;P(ë¶@K9Â|1Éë¹]‰ÈÃU‰åWVSƒì4‰Ã‰Uì‹x,Gÿ‰Eä¶CK<ú‡8¶KJ¶À¶SI‰Îƒæò9ÂöÁt…ö„¶CH9C$‹C09øt…À…õ…ÿŽí‹C‹D¸üƒà?ƒø…ÚÇEè‹Uì9UèÇEÔ‹K1ö‹Eè‰Mà‹‰Èƒà?‰E܉ÈÁè%ÿƒ}Ü%‰E؇“¶SK¶Â9E؈UÓ€‹Eܶ€DˆEÀƒàƒøt]r
ƒøttéÕ¶EÀ‰ÎÁéáÿÁî‰ò‰MÔÀèƒàP‰Øèþÿÿ_…À„1¶EÀ‹UÔÀèƒàP‰ØèqþÿÿY…À…‰é¶EÀ‰ÎÁîÀèƒàƒøup;s(|kéð¶EÀÁé±þÿÀèƒàƒøuN‹MèT1…ÒˆÉ;S,À…Ò~21ÿ9UÔ}"‹Eà‰Ñ)ù‹Lˆü‰Èƒà?ƒø"u
áÀuG9×ë܃ç…ŠöEÀ@t‹U9UØu‹Mè‰Mä€}Ày%‹EèƒÀ;C,a‹C‹Uè‹Dƒà?ƒø…K‹E܃èƒø#‡nÿ$…0÷Cƒ}Ô…]‹EèƒÀ;C,‹C‹Mè‹Tˆ‰Ðƒà?ƒø"…6âÀ…*éó‹E9EØžÀ1Ò9užÂ…Є‹Uè‰Uäé¶CH9Æéô‹CÁæƒ|„åé®¶EÓ‹UØB9ž9U…Çéæ;uÔ鸃}ÔŽ~‹EØ‹MÔT¶EÓ9Âh‹E؃À9EŒ‹‹Eè‰Eä逶EÓ‹U؃Â9Â<uè}ÿN•À1Ò9MèœÂ…ЄN;MìE‰uèé=…öt¶EÓ‹MØT1ÿ9ÂôÿMÔƒ}Ôÿu‹Uè‹CÿtèüÿÿZ…Àu!éÒƒ}Ôt‹EÔ‹MØTÿ¶CK9¶‹UØ9UŒÜ‹Mè‰MäéÑN…öŽÈ‹EØT0ÿé´…ö~
¶EÓ‹UØò9Â}yƒ}Ô…¡ÿEè‹C,H9Eèé;s4}[‹C‹°¶HH‹EèÈ;C,}G¾9Î$‹Eè‹C‹ƒà?ƒø•Â…À•À¶À…ÂuFëØ}ÿtCMèë>¶CJ¨t¨t	ÇEðëCNƒþÿu‹C‹Uèÿtè	ûÿÿ_…ÀtÝ‹MØT1ÿ¶EÓ9Â}ÎÿEè‹Eì9Eèéóûÿÿ‹C‹U䋉Eð‹Eðeô[^_]ÃU‰å‹E‹P,hÿè;ûÿÿZ…À•ÀɶÀÃUöƉå‰Át‰Ð‹Q€äþÁàƒ|u‹ƒÀë¸À÷C]ÃU‰åWVSƒì‹u‰Eð‹E‰Uì‰Eè‹Uì‹Bƒx…â‹€x…Ö‹X‹Eðèÿ÷ÿÿP‰ÇFPSèö‹UèƒÄ…À‰t
¸Â÷CéªV‰ú‰Øè™úÿÿY‰Âƒà?ƒø‡ÿ$…ä÷C‹CÁêÁâ‹‹UèƒÀ‰¸È÷CëoÁê¶ÂÁê9Â}`‰ÖégÿÿÿÁê‰Øâÿèÿÿÿ‹U艸Ï÷Cë?‹CÁê¹À÷C…Àt‹ƒÁ‹E艸Õ÷CëÁê‰Øâÿè×þÿÿ‹U艸Ý÷Cë1Àeô[^_]ÃU‰åWVSƒì‹EÇEð‹}ÇEì€8>uÿE‹U‹M‹BPð‹@ð‰Q‰Eðë‹G`…Àt‹UkÀ‹R(ЉEì‹@‹‰Eðƒ}ðÇEà‹E‰EèuWÇGøCG$ÇGøCÇGøCÇGÿÿÿÿÇGÿÿÿÿÇG ÿÿÿÿÇGøCjüÿÿëñ‹CHºd‰Ñ1Ò÷ñ¯CP‰C@[^]ÃU‰åS‹E‹]‹U‹H€yu	[‰È]é\óÿÿ¶C¶Q$ø€âЈC[]ÃU‰å‹U‹E‹H€bû‹A(‰B‰Q(]ÃU‰å‹E‹M‹@‹P‰‰H¶@$ˆA‹EˆA]ÃU‰åV‹uS‹]‹N‹A‰‰Y¶S¶Â¨uA¨u=€yu)‹C€ÊˆSƒx~(‹ö@t öÂtPSVè=ÿÿÿƒÄë¶A€âø$ˆSeø[^]ÃU‰åƒ=$úCV‹uS» úCt)jÿsVèì‰ÿÿÿ3ƒÃVèG‰ÿÿjjVè<ÿÿƒÄ ƒ{ëÕeø[^]ÃU‰åWV‰ÆS‰ÓèÁ´…Û‹8tjVèIŠÿÿ¸ëLVènˆÿÿƒ}XtWè©´‰$ÿuhÐûCVèJ‰ÿÿƒÄëWè´‰$h×ûCVè1‰ÿÿƒÄWVè`ˆÿÿ¸eô[^_]ÃU‰åV‰ÖS‰ÃèJ´ÿ0èS´‰$ÿuhÐûCSèôˆÿÿjjÿSèm†ÿÿƒÄPVSèÊ“ÿÿeø[^]ÃU‰åVS‹]jSèÙ•ÿÿjSèE‡ÿÿhÚûC‰ÆhðØÿÿSèŠÿÿƒÄ…ötjSèýŠÿÿY…ÀZtjÿjþSèš„ÿÿƒÄ…Àu	S與ÿÿZëƒ>u	jhàûCëjhìûCS踇ÿÿƒÄeø¸[^]ÃU‰åV‰ÆShÚûCjPè{”ÿÿƒÄƒ8‰Ãu
hñûCVèå’ÿÿY^‹eø[^]ÃU‰åVS‰ÃjPèûÿÿljÆhÚûChðØÿÿSèS‰ÿÿjþSèmŒÿÿeø‰ð[^]ÃU‰åS‹]Sèâ†ÿÿjhüCSè#‡ÿÿ‹]ü¸ÉÃU‰åVS‹uhÚûCjVèê“ÿÿÿ0‰Ãèu´ÇƒÄ1ÒÇEƒøÿ•Âeø‰ð[^]éðýÿÿU‰åVS‹uhÚûCjVè§“ÿÿÿ0‰Ãèr²ÇƒÄ1ÒÇE…À”Âeø‰ð[^]é®ýÿÿU‰åS‰ÃjPè݉ÿÿh)üCjÿSè~ˆÿÿjÿSè}…ÿÿZYSÿЋ]üÉÃU‰åS‹]jSè7‚ÿÿZ@YujhïØÿÿSè׈ÿÿƒÄ‰Øè“þÿÿ‰Ø‹]üÉë U‰åS‹]hÚûCjSè“ÿÿƒÄƒ8t‰Øè}ÿÿÿ‹]ü1ÀÉÃU‰åS‹]hÚûCjSèÜ’ÿÿ‹ƒÄ…Àuj
h1üCSèà…ÿÿëPh?üCSè~†ÿÿƒÄ‹]ü¸ÉÃU‰åWVSS‹}jjW蛓ÿÿ‰EðjhIüCjW输ÿÿ‰Ã‰øè!þÿÿS‰Æÿuðèµ±‰ƒÄ$…Àu‹Eð1Ò‰Eeô‰ø[^_]é†üÿÿeô¸[^_]ÃU‰åWVSV‹}jjWè5“ÿÿ‰EðjhIüCjWèX“ÿÿ‰Ã‰øè»ýÿÿS‰Æÿuð貉ƒÄ$…Àu‹Eð1Ò‰Eeô‰ø[^_]é üÿÿeô¸[^_]ÃU‰åVS‹u‰ðèuýÿÿ‰Ãè=²‰…ÀuÇE‰ð1Ò[^]éäûÿÿ[¸^]ÃU‰åW‰×VS‰ÃRhïØÿÿPè<‡ÿÿjÿSèÔƒÿÿ‹0ƒÄ…öuÿ4½<ûChKüCSèíÿÿƒÄeô‰ð[^_]ÃU‰åWV‰ÆSQjP‰UðèF€ÿÿ[…À_~^jjV膂ÿÿƒÄ…À‰Çt)‰ðèÒüÿÿÿu‰ÃWèf°‰…ÀZYu Wº‰ðè¹ûÿÿë‰ðèuüÿÿjVèÆÿÿ_XÿuðhïØÿÿV迈ÿÿƒÄÿuðhïØÿÿV膆ÿÿeô¸[^_]ÃUº‰å‹EÇEIüC]éUÿÿÿUº‰å‹EÇEfüC]é=ÿÿÿU‰åS‰ÃRPè[ÿÿÿuSè"…ÿÿjh@¤@Sèl„ÿÿ‹]üÉÃU‰å‹EèÜûÿÿj‹Eºè¾ÿÿÿɸÃU‰åWVS‹ujVè=ÿÿ_…ÀZjhïØÿÿVèÜ…ÿÿ‰uƒÄeô[^_]ë¬jjVè‘ÿÿ‰Ç‰ðè´ûÿÿhIüC‰ÃWèF¯‰ƒÄ…ÀuWº‰ðè˜úÿÿ[Vè
}ÿÿÇ$‰Â‰ðè7ÿÿÿeô¸[^_]ÃU‰åWVS쉅àýÿÿ…äýÿÿPÿµàýÿÿ‰•Üýÿÿès“ÿÿY[µäýÿÿVèY–ÿÿÿµÜýÿÿ‰ÃhPèA¯ƒÄ…Àu Vè‘•ÿÿjÿÿµàýÿÿèÿÿƒÄ…À•À¶Àë8ü1ÀƒÉÿ‰ßò®÷щÈHt€|ÿ
t…äýÿÿëš…äýÿÿVH‰…äýÿÿèD•ÿÿ¸eô[^_]ÃU‰åW‰Ç…äýÿÿV¾Sì‹]PW‰•àýÿÿèÂ’ÿÿYX…äýÿÿP訕ÿÿZ9Þv‰ÞÿµàýÿÿVjPèí­…äýÿÿƒÄ)ÕÂ9ð”À¶À…ÂuÄ…äýÿÿ1öPè”ÿÿY…ÛtjÿWèJ€ÿÿ_…ÀZt¾eô‰ð[^_]ÃU‰åW‰×V‰ÆSƒìPè”{ÿÿW‰Ã@ÿ‰Eèè²®ƒ}èXZu‰ú‰ðè…þÿÿ‹UB‰UäéJhhüCCƒëPVè–Žÿÿ‰]è‹UƒÄ¸C‰Uä„ ÿuäVè}ÿÿZƒøYu_ÿuäVèâ~ÿÿY…À[uA‹GH…À‰Gx
‹¶@‰ë	Wè1­Z‰ÃWSè·¬YXjjVèá€ÿÿ1ÀƒÄƒûÿ•Àé­P‰ú‰ðè—þÿÿé‹jÿuäVèæ~ÿÿƒÄ…À‰Ãt€8*th{üCÿuäVè2ŒÿÿƒÄ¾Cƒølt=ƒøatAëRƒønuMEìPhŠüCWè¼­ƒÄ1ÒHuÿuðÿuìVè(€ÿÿƒÄº‰Ðë.‰ú‰ðègýÿÿë#jÿ‰ú‰ðèþÿÿ¸ZëhŽüCÿuäV轋ÿÿëAÿMèÿEäƒ}èÿt…ÀéÚþÿÿöG t
j1Ò‰ðè÷ÿÿë…ÀujþVèzÿÿVèžÿÿƒÄ‹Eä+Eeô[^_]ÃUº‰åS‹]‰ØèûÿÿÇE‰Â‰Ø[]éþÿÿU‰åS‹]‰Øèÿ÷ÿÿÇE‰Â‰Ø[]éýýÿÿU‰åV‹uShíØÿÿVè´~ÿÿY‹X…Ûu
hüCVèÕŠÿÿXZ‰Ú‰ðèƒüÿÿöC ‰ÂtèB«ÿ0èK«‰$h×ûCV訊ÿÿë9…Ò¸u0hìØÿÿVè4}ÿÿY…À[tjVè>yÿÿhíØÿÿVèÄzÿÿ‰ðèyøÿÿƒÄ1Àeø[^]ÃU‰åW‰ÇV¾Sƒì‹]P‰UìèóxÿÿZƒè‰Eè@„‰SWè¯zÿÿZƒøYu5ÇEä…öt%SWèN|ÿÿÝ$h´üCÿuìèAªƒÄ…À~ÇEä‹uäë9EðPSWèsŒÿÿÇEàƒÄ…ötÿuìÿuðjPè—«ƒÄ;EðuÇEà‹uàÿMèCƒ}èÿéqÿÿÿj‰ò‰øè]õÿÿeô[^_]ÃUº‰åS‹]‰ØègùÿÿÇE‰Â‰Ø[]éÿÿÿU‰åS‹]‰Øè_öÿÿÇE‰Â‰Ø[]éõþÿÿU‰åWVS‹u‰ðè=öÿÿhÔüC‰ÇhÌüCjVèQŒÿÿj‰ÃjVè›ÿÿÿ4¼üCPWèÒªƒÄ(…ÀtÇEeô‰ð[1Ò^_]é´ôÿÿW螪‰$Vèp}ÿÿeô¸[^_]ÃU‰åWVS‹]‰ØèÅõÿÿhýC‰ÇjjSèÜ‹ÿÿh‰ÆjSè#ÿÿPÿ4µäüCjWè8ªÇEƒÄ,1Ò…À”Âeô‰Ø[^_]é9ôÿÿUº‰åS‹]‰ØèKøÿÿPèð©Y1Ò…ÀÇE‰Ø‹]üÉ”ÂéôÿÿU‰åS‹]‰Øè5õÿÿPè©Z1Ò…ÀÇE‰Ø‹]üÉ”ÂéØóÿÿU‰åW‹}V‰ÆS‰Óè7õÿÿ‰…ÿ~jÿVèNxÿÿWhïØÿÿVèKÿÿƒÄjþVè7xÿÿjþVè8‚ÿÿÿujýVè`€ÿÿeô[^_]ÃU‰åV‰ÖS‰ÃjjPè&ÿÿjVSè'}ÿÿh)üCjþSè/€ÿÿeø[^]ÃU‰åS‹]hÚûCSè´ˆÿÿXZjÿSèÐwÿÿYXhýCjþSèýÿÿƒÄh€ûCjSèÁŽÿÿƒÄ‰Øº@è†ÿÿÿhïØÿÿSèÝvÿÿhàúChýCSè—Žÿÿ‰Øº™œ@è_ÿÿÿhýC‹È2D‰Øjèùþÿÿh!ýC‹È2D‰ØjƒÂ èâþÿÿ‹È2DƒÄ$‰Øh(ýCjƒÂ@èÈþÿÿjþSèuÿÿh¤úCjÿSèv}ÿÿº½œ@‰ØèùþÿÿjþSèÿÿƒÄ$jþSèquÿÿ‹]ü¸ÉÃU‰åWVS1ÛP‹uü‹àýCƒÉÿ‰Eð‹}ð1Àò®÷ÑIQÿuðVè¦P€H ˆÚCþƒÄƒûˆP~Êeô[^_]ÃU‰åV‹uS‹]û@¡¬2Dƒ8u¡Ø2D‹·Xƒà ë
j SèA§ZY…ÀtSh`þCëShiþCÿv4èø$ë‹ÜùCeø[^]ÃU‰åWVSƒìP]¤jP‹u‹}‹F@ƒÀPSèÛ$WÿvShlþCÿv4èµ$ƒÄ ƒ}‰Çt:‹E-ƒøw‰ð1Òè6‹F<‹ëÿuVè;ÿÿÿ[ZPWhvþCÿv4ès$ƒÄjÿv4èÜÑÿÿeô[^_]ÃU‰åW‰ÇVSS‹X<‰Uð‹C‹S@9ÐvGúýÿÿvjhƒþCWèGÿÿÿƒÄ‹C4FƒøýwVÿsÿ3ÿw4èƒÄë	ÿw4è`Y‰‰s¶Mð‹C‹ˆÿCeô[^_]ÃU‰å‹EÿpÿuPèìþÿÿÉÃU‰åWVS‹]‹s4ÿuÿuVèûNP‰Ç‹C0ÿpVèœtƒÄƒxu
ÇÇ@eô‰ø[^_]ÃU‰åVS‹P8‰Ã‹0‹H‰@t‹B¶@‰Bë	RèœY‰Á‰ƒù
”Àƒù
”Â	Шt&9ñt"‹S8‹H‰@t‹B¶@‰Bë	R芜Z‰Á‰‹C@=üÿÿ‰C~
hœþCSè)ÿÿÿ^Xeø[^]ÃU‰å‹UV‹uS‹^<ÆFD.‹E‰V4ÇF ‰F8‹EÇF0ÇFÇF‰F@j ÿsÿ3Rè-‰‹F<ƒÄ‹V8Ç@ ‹H‰@t‹B¶@‰Bë	Rèí›[‰Á‰eø[^]ÃU‰åS‰Ãÿ0RèS£YZ1Ò…Àt0‹‰Øèþÿÿ‹S8‹H‰@t‹B¶@‰Bë	R襛Z‰Á‰º‹]ü‰ÐÉÃU‰åS‹@<ˆÓ¶U‹‹@Hƒøÿt
8uõˆëð[]ÃU‰åV‰ÖS‰Ã‹‰Øè¢ýÿÿ‹S8‹H‰@t‹B¶@‰Bë	Rè@›Y‰Á‰¡¬2Dƒ8u¡Ø2D‹·Hƒàë
jQèé£YZ…Àu­ƒ;.t¨ºµþC‰Øè!ÿÿÿ…Àt9º¸þC‰Øèÿÿÿë+‹‰Øè,ýÿÿ‹S8‹H‰@t‹B¶@‰Bë	RèÊšZ‰Á‰¡¬2D‹ƒ8u¡Ø2D‹·P%ë
hRèl£ZY…Àu¦ƒ;_t¡1Ò‰ØèÍüÿÿ¾CDº.P‰ØèãþÿÿV‹C<ÿ0èjƒÄ…Àu\è@¤¶SD‰Á…ɰ.t‹¶ˆCD¾À¾ÒP‰Øèªþÿÿ‰4$‹C<ÿ0è/Y…À^u"¾SDj.‰ØèŠþÿÿÇ$h»þCSèÇûÿÿƒÄeø[^]ÃU‰åWV1öS‹8‰Ã‰úè4üÿÿ‹S8‹H‰@t‹B¶@‰Bë	RèÒ™Y‰Á‰ƒù=u.‹‰Øèüÿÿ‹S8‹H‰@t‹B¶@‰Bë	R袙Z‰Á‰FëÍ9;‰ðt÷Ðeô[^_]ÃU‰åW‰×V‹uS‹‰Ãè»ûÿÿ‹S8‹H‰@t‹B¶@‰Bë‹B¶@‰BéHRèJ™Y‰Á‰ƒù
”Àƒù
”Â	Шt‰ØèDüÿÿ‹ƒø
„»ƒøÿtƒø
„«éЃø[t ƒø]tjéÁh…ÿ¸ÌþCu¸ãþCPëA‰ØèÞþÿÿ9ðu°‹‰Øèûÿÿ‹S8‹H‰@t‹B¶@‰Bë	R趘Z‰Á‰…öuj[hûþCSè[úÿÿƒÄélÿÿÿ‰Øèþÿÿ9ð…]ÿÿÿ‹‰ØèÅúÿÿ‹S8‹H‰@…ÿÿÿRèk˜Y‰Áë^º
‰ØèŸúÿÿ‰Øèkûÿÿ…ÿ…ÿÿÿ‹C<Ç@éÿÿÿ…ÿt	‹‰Øètúÿÿ‹S8‹H‰@t‹B¶@‰Bë	Rè˜Z‰Á‰éÜþÿÿ‰…ÿt‹S„Ý颃ÿ~„+锉ØèOúÿÿémÿÿÿ‹S8‹H‰@t‹B¶@‰Bë	Rè—Y‰Á‰ƒù-t
º-éÑ‹S8‹H‰@t‹B¶@‰Bë	Rèä–Z‰Á‰ƒù[u1‰ØèÑüÿÿ‰Â‹C<…ÒÇ@xR‰Ø1Òè/ýÿÿ‹C<Ç@_éäþÿÿ‹ƒù
•À1Òƒù
•…ЄÌþÿÿA„Åþÿÿ‹S8‹H‰@t‹B¶@‰Bë	Rèm–^‰Á‰뿉Øè]üÿÿ…ÀxP‹Uð‰ØèÆüÿÿéû@º[„hhÿCSèê÷ÿÿƒÄ‹S8‹H‰@t‹B¶@‰Bë	Rè–Y‰Á‰ƒù=º=…Ì‹S8‹H‰@t‹B¶@‰Bë	Rèß•Z‰Á‰ºé ‹S8‹H‰@t‹B¶@‰Bë	R賕_‰Á‰ƒù=º<…p‹S8‹H‰@t‹B¶@‰Bë	R胕^‰Á‰ºéD‹S8‹H‰@t‹B¶@‰Bë	RèW•Y‰Á‰ƒù=º>…‹S8‹H‰@t‹B¶@‰Bë	Rè'•Z‰Á‰ºéè‹S8‹H‰@t‹B¶@‰Bë	Rèû”_‰Á‰ƒù=º~…¸‹S8‹H‰@t‹B¶@‰Bë	RèË”^‰Á‰ºéŒ‰ú‰Øèøöÿÿ‹S8‹H‰@t‹B¶@‰Bë	Rè–”Y‰Á‰9ù„ò‹ƒø
t @t鯃ø
tƒø\t$é hëhh:ÿCSè
öÿÿƒÄ鬋K8‹H‰@t‹A¶@‰Aë	Qè-”Z‰Â‰ƒúbtJƒú
tB„u鉃ú
tlƒúat!ë}ƒúrtBƒúft'ƒúnt,ëjƒútt9ƒúvt>ë^¾é¾é¾éø¾
éî¾
éä¾	éÚ¾éЉغ
èÖõÿÿ‰Øè¢öÿÿé硬2D‹ƒ8u¡Ø2D‹·Pƒàë
jRè1œY^ÇEì1ö…À„…kÆ
‹S8pЋH‰@t‹B¶@‰Bë	Rè)“Z‰ÁÿE쉃}ì(¡¬2Dƒ8u¡Ø2D‹·Hƒàë
jQèÉ›ZY…Àu¥þÿ~hhLÿCSè–ôÿÿƒÄ‰ò‰Øèõÿÿë/‰ò닉Øèõÿÿ‹S8‹H‰@t‹B¶@‰Bë	R裒^‰Á‰9;éþÿÿ‹‰ØèÓôÿÿ‹S8‹H‰@t‹B¶@‰Bë	Rèq’Y‰Á‰‹S<‹BƒèP‹@PSè)õÿÿ‹UðƒÄ‰ºéº.‰Øèôÿÿ‹S8‹H‰@t‹B¶@‰Bë	Rè’Z‰Á‰ºfÿC‰Øè+öÿÿ…ÀtºfÿC‰ØèöÿÿƒøÒÂ鼡¬2D‹ƒ8u¡Ø2D‹·Pƒàë
jR蘚^_…Àº.„‰郺éz¡¬2Dƒ8u¡Ø2D‹·xƒàë
jWèXšZY…Àt'‹S8‹H‰@t‹B¶@‰Bë	Rèe‘_‰Á‰é–ùÿÿ¡¬2D‹ƒ8u¡Ø2D‹·Pƒàë
jRèšY^…Àt‹Uð‰Øè¸õÿÿºéí¡¬2D‹ƒ8u¡Ø2D‹·P%ë
hRèÄ™_Z…Àu‹3ƒþ_…‹‰Øèóÿÿ‹S8‹H‰@t‹B¶@‰Bë	Rè½^‰Á‰¡¬2Dƒ8u¡Ø2D‹·H%ë
hQèa™ZY…Àu¨ƒ;_t£‹C<ÿpÿ0SèIóÿÿ‰Â¶@ƒÄ„Àt¶Àë0‹Eð‰ºë$‹S8‹H‰@t‹B¶@‰Bë	Rè7_‰Á‰‰òeô‰Ð[^_]ÃU‰åS‹]‹C‰C‹C =t‰C‹C$ÇC ‰C‹C(‰C‹C,‰Cë
S‰Øèøÿÿ‰C[]ÃU‰åS‹]S(‰Øèô÷ÿÿ‰C []ÃU‰åS‹]jSè{ÿÿÙáÝ$SèÆkÿÿ‹]ü¸ÉÃU‰åS‹]jSèøzÿÿÝ$èUšÝ$Sèœkÿÿ‹]ü¸ÉÃU‰åS‹]jSèÎzÿÿÝ$苚Ý$Sèrkÿÿ‹]ü¸ÉÃU‰åS‹]jSè¤zÿÿÝ$èñ™Ý$SèHkÿÿ‹]ü¸ÉÃU‰åS‹]jSèzzÿÿÝ$è'šÝ$Sèkÿÿ‹]ü¸ÉÃU‰åS‹]jSèPzÿÿÝ$è™Ý$Sèôjÿÿ‹]ü¸ÉÃU‰åS‹]jSè&zÿÿÝ$èÙÝ$SèÊjÿÿ‹]ü¸ÉÃU‰åS‹]jSèüyÿÿÝ$è)™Ý$Sè jÿÿ‹]ü¸ÉÃU‰åS‹]jSèÒyÿÿÝ$èï˜Ý$Sèvjÿÿ‹]ü¸ÉÃU‰åS‹]jSè¨yÿÿÝ$赘Ý$SèLjÿÿ‹]ü¸ÉÃU‰åS‹]jSè~yÿÿÝ$jSèsyÿÿÝ$èp˜XZÝ$Sèjÿÿ‹]ü¸ÉÃU‰åS‹]jSèGyÿÿÝ$è4˜Ý$Sèëiÿÿ‹]ü¸ÉÃU‰åS‹]jSèyÿÿÝ$芖Ý$SèÁiÿÿ‹]ü¸ÉÃU‰åS‹]jSèóxÿÿÝ$jSèèxÿÿÝ$èÅ—YXÝ$SèŠiÿÿ‹]ü¸ÉÃU‰åEôSƒì‹]PjSèµxÿÿÝ$è‚—ÿuøÝ]ìÿuôSèSiÿÿÿuðÿuìSèGiÿÿ‹]ü¸ÉÃU‰åS‹]jSèyxÿÿÙúYXÝàßàžztÝØjSèbxÿÿÝ$è—XZƒìÝ$Sèiÿÿ‹]ü¸ÉÃU‰åS‹]jSè3xÿÿÝ$jSè(xÿÿÝ$襕XZÝ$SèÊhÿÿ‹]ü¸ÉÃU‰åS‹]jSèüwÿÿÝ$è©–Ý$Sè hÿÿ‹]ü¸ÉÃU‰åS‹]jSèÒwÿÿÝ$èo–Ý$Sèvhÿÿ‹]ü¸ÉÃU‰åS‹]jSè¨wÿÿÝ$è5—Ý$SèLhÿÿ‹]ü¸ÉÃU‰åS‹]jSè~wÿÿÜ5DÝ$Sè$hÿÿ‹]ü¸ÉÃU‰åS‹]jSèVwÿÿÜ
DÝ$Sèügÿÿ‹]ü¸ÉÃU‰åEøSS‹]PjSè)wÿÿÝ$視YÝ$SèÌgÿÿÿuøSèÞgÿÿ‹]ü¸ÉÃU‰åS‹]jSèwwÿÿZYPjSèêvÿÿÝ$èW–XÝ$Sègÿÿ‹]ü¸ÉÃU‰åWVS»QQ‹uVè±aÿÿj‰ÇVè®vÿÿƒÄÝ]ì9ûSVèvÿÿÝEìXÝéßàZžvÝ]ìëÝØCëßÿuðÿuìVè0gÿÿeô¸[^_]ÃU‰åWVS»QQ‹uVèQaÿÿj‰ÇVèNvÿÿƒÄÝ]ì9û!SVè=vÿÿÝEìÙÉXÝáßàÝÙZžvÝ]ìëÝØCëÛÿuðÿuìVèÌfÿÿeô¸[^_]ÃU‰åWVSSS‹}蔺ÿ‰Ñ™÷ùRÛ$Ø5DD‰<$Ý]ìèÔ`ÿÿYƒøt 	…Àt駃øtMéÿuðÿuìéŸjWè/vÿÿ‰Ã…ÛXZhDjWèrÿÿƒÄSÛ$ƒìÜMìÝUìÝ$èõ’ÜHDëPjWèòuÿÿj‰ÆWèèuÿÿƒÄ9ƉÃ~hDjWèÒqÿÿƒÄ)óCPÛ$ƒìÜMìÝ$Ý]ì訒[XVÛ$ƒìÞÁÝ$ë
h*DWèhqÿÿëWèÅeÿÿƒÄ¸eô[^_]ÃU‰åjÿuèuuÿÿZYPèp“É1ÀÃU‰åS‹]h DhPDSè{xÿÿhû!	@h-DTSèueÿÿhUDjþSèŠiÿÿƒÄ$hðjSèXeÿÿhXDjþSèmiÿÿhµÿCjÿSèygÿÿƒÄ$h]DjþSèPiÿÿ‹]ü¸ÉÃU‰åh€Dÿuè!ºÿÿÉ1ÀÃU‰å‹EWV‹uS‹XVÿuÿuÿsÿSƒÄ…À‰Ç”À1Ò…ö•Â…ÐtjÿuèʼÿÿXZ‹CD+Eð‰CDeô‰ø[^_]ÃU‰åWºVS‰ÓPP‹E‹}‹u™÷û‰Á‹E‹9Ê|;U|ÿuWè—¹ÿÿ[X‹]ë
ƒû»1Ò¸ýÿÿÿK÷ö9Áw‰Ø‹U¯ÆP‹¯ÆPÿuWè>ÿÿÿƒÄëWèÿÿÿY‹U‰eô[^_]ÃU‰åW½tÿÿÿV‰ÆSƒÄ€èŠ•j‰Ãh€WjPjhè•…ÀtWVèidÿÿXZëShDVèÈdÿÿƒÄeô[^_]ÃU‰åSh)Djÿuèäpÿÿ‰Ã‹ƒÄ…ÀtPèG•Ç1À‹]üÉÃU‰åWV‰ÖS‰ÃRh2Dh<DPèqdÿÿƒÄhðØÿÿSè—eÿÿY_jÿSèŒ_ÿÿ_…ÀZtjÿSèÐbÿÿZ‰ÇYëdjþSè°]ÿÿ_XjSèmÿÿZ‰ÇYÇh)DhðØÿÿSèreÿÿƒÄjþSè‰hÿÿYXVh2Dh<DSèûcÿÿƒÄjþSèô^ÿÿXZhðØÿÿSè÷fÿÿYXƒ?uVèD”…À‰Æu‰Øè·þÿÿ‰7‹¸…Òt&ÿuRè1”…Àu‰Øè–þÿÿ¸ëjPSèÃcÿÿ1Àeô[^_]ÃU‰åV‹uSjjVèºpÿÿj‰ÃjVè®pÿÿP‰Ú‰ðèÚþÿÿ‰ÃƒÄ…Û¸t'VèXbÿÿjþVèG]ÿÿK¸ADt¸FDPVèÇbÿÿ¸eø[^]ÃU‰åWVSQQ‹]hKDhMDRP‰Uì‰Eðè‡vÿÿShïØÿÿÿuð‰EìèPdÿÿjjÿÿuðèn`ÿÿƒÄ(…À‰ÆuShODÿuðèmÿÿƒÄjhmDÿuðèbÿÿƒÄ‰ó€;;uCëø1À€;t3j;Sè$^…À‰Æ_uü‰ßƒÉÿ1Àò®÷Ñtÿ‰ð)ØPSÿuðèÔaÿÿƒÄ‰ð…À‰ÆtuÿuìhnDjjÿÿuðèä_ÿÿƒÄPÿuðèÔuÿÿjþ‰Ãÿuðè\ÿÿƒÄhpDSè¹Z…ÀYu*ShrDÿuðè'bÿÿjþÿuðèÜ[ÿÿjÿuðèYjÿÿƒÄéLÿÿÿPèX‰Øë1Àeô[^_]ÃU‰åV‰ÖS‰ÃjjÿPèf_ÿÿƒÄPVjjSèW_ÿÿƒÄPhDSè~lÿÿeø[^]ÃU‰åV‹uSjjVèênÿÿh¯D‰Â‰ðètþÿÿƒÄ…À‰ÃtPVèµwÿÿZ…ÀYt	‰Ú‰ðè‰ÿÿÿeø¸[^]ÃU‰åV‰ÆS‰Ój-Rèà‹Z…ÀYtXh´DhMDSVèÇtÿÿPh¶DVè`ÿÿºeô‰Ð[^_]ÃU‰åVS‹]jjSè[mÿÿhåD‰ÆhïØÿÿSèdaÿÿjÿSè6[ÿÿƒÄ ƒøt
híDSè©jÿÿYXVjÿSè>aÿÿjÿSè[ÿÿƒÄ…ÀuVhDSèÊ_ÿÿƒÄeø¸[^]ÃU‰åWVS‹]jjSèælÿÿj‰ÆSèYÿÿh0DhðØÿÿSèç`ÿÿƒÄ VjSèÛ`ÿÿjÿSèÕ\ÿÿƒÄ…Àt)jÿSèð]ÿÿZ=DY…JVh8DSèjÿÿƒÄé6hcDhïØÿÿSè“`ÿÿjÿSèeZÿÿƒÄƒøt
hkDSèØiÿÿY_j¿hmDSè_^ÿÿƒÄWjþSèä`ÿÿjÿSè*ZÿÿƒÄ…ÀujjþSèi\ÿÿƒÄPVhDSèiÿÿƒÄVSè]^ÿÿjjSèRdÿÿjÿSèíYÿÿƒÄƒøt%jÿSèsZÿÿY…ÀZt
jSèâfÿÿëjþSèXÿÿXGZë…hDSèw_ÿÿVjSè¹aÿÿVSè^ÿÿjjSèøcÿÿƒÄ(jÿSèYÿÿZ…ÀYtVjSèŽaÿÿƒÄVjSè›_ÿÿjÿSè¿\ÿÿƒÄ=DujSèü^ÿÿjÿSè$YÿÿVjSèWaÿÿƒÄeô¸[^_]ÃU‰åWVSƒìp‹]jjSè/kÿÿS‰ÆèKWÿÿh0DxhðØÿÿSè/_ÿÿVWSè'_ÿÿƒÄ(jÿSèöXÿÿZƒøYtAjþSè'WÿÿjVhîØÿÿSèÏmÿÿƒÄ…ÀtVh¦DSèLhÿÿé@jÿSèŠXÿÿVWSè¾`ÿÿƒÄhÄDjÿSèÇ^ÿÿjÿSè™XÿÿƒÄ…ÀtjþSèÊVÿÿY^ëmjþSè¾VÿÿXZjÿSèEXÿÿYXhÊDjþSèr`ÿÿƒÄVSè¹\ÿÿXZhÄDjþSèY`ÿÿƒÄj.Vè\‹Z…ÀYu‰ðë@)ðPVSèM\ÿÿƒÄhÍDjþSè)`ÿÿƒÄjÿSèâWÿÿ^u„XVjSèâ¤ÿÿƒÄ…Àt!VhÖDSèá¬ÿÿƒÄ…ÀtjÿSèXÿÿZ…ÀYt
hØDSèVgÿÿY^jþOSè–WÿÿXZjþSè•aÿÿY^¾jþSèìUÿÿXZ9þ#VFSèoWÿÿYXjþSèeWÿÿXZjjSèåaÿÿƒÄëÙ1Àeô[^_]ÃU‰åS‹]jjSèiÿÿjSè‹^ÿÿƒÄ…ÀujjSè=^ÿÿjÿSèWÿÿjSè‡`ÿÿƒÄhîØÿÿSèWÿÿhDjþSè1_ÿÿ‹]ü1ÀÉÃU‰åW‰×VSì‰Ãÿu‹uè
ŠZ…Àu	VSèT[ÿÿë)hDhDPSè/oÿÿVhDPSè"oÿÿƒÄ jþSèWUÿÿ^µäþÿÿXhVjèAŒ…À”Â=”À	Шuj\V趉Z…ÀYu
hDSèfÿÿë(ÆVh.DjjÿSèÅXÿÿƒÄPSè·nÿÿƒÄjþSèìTÿÿ^XWjþSèb^ÿÿeô[^_]ÃU‰åV‹uS1Ûh)DVèãfÿÿjhÅ¿@Vè#[ÿÿh0DjþVè+^ÿÿƒÄ hüDh5DVèìlÿÿjÿVèÔUÿÿhïØÿÿVèUÿÿjjVèÜ\ÿÿƒÄ(ƒ=ØDt&jÿ4ØDCVèÊZÿÿSjþVè£^ÿÿƒÄƒ<ØDëØhcDjþVè¼]ÿÿh=D‰ðº¯DhwDè|þÿÿh€DºÁD‰ðhžDèfþÿÿj	h¨DVè—YÿÿƒÄ(h²DjþVès]ÿÿjh0DhðØÿÿVèJjÿÿh¹DjþVèT]ÿÿƒÄ(jjVè(\ÿÿhåDjþVè:]ÿÿhîØÿÿVèóTÿÿƒÄ hÀDjVèókÿÿjþVèJSÿÿeø¸[^]ÃU1ɉå‹Eƒøv@AÑèëõƒø‰Âv̓è	Â]‰ÐÃU‰å‹US‰Ð‰ÓÁøƒàtƒâHÿZÓã‰Ø[]ÃUƒÊÿ‰å‹E=ÿvƒÂÁèëñ¶€àD]ÃU1À‰åS‹]‹M‹S;Qu6ƒút'…Ò°t)ëƒútƒúuÝÝÚéßàž”À›Â Ðë‹9”À¶À[]ÃU‰åWVuðSS‹]V‹}Sè{‡‹EðÝZ1Ò9ØYtt¶TÿÿW耀‰$ÿuh€DVè!UÿÿWVèSTÿÿ¸eô[^_]ÃU‰åS‹]jjjSèmbÿÿƒÄPè?„‰$Sè!Tÿÿ‹]ü¸ÉÃU‰åVS‹ujjVè
bÿÿƒÄ‰ÃPèÿƒZ1Ò…À‰]”Âeø[‰ð^]éGÿÿÿU‰åVS‹]jjSèÕaÿÿj‰ÆjSèÉaÿÿƒÄPV诃YZ1Ò…À‰u”Âeø‰Ø[^]éÿÿÿU‰åVSƒì]èS‹uèrƒY…Àu
h‡DVèý^ÿÿëSVèÌSÿÿ¸eø[^]ÃU‰åS‹]jjSè\aÿÿƒÄPèS‚‰$SèSÿÿ‹]ü¸ÉÃU‰åèƒPÛ$ƒìØ5¬DÝ$ÿuèSÿÿɸÃU‰åV‰ÆS‰ÓÿuPèSÿÿSjþVèWÿÿeø[^]ÃU‰åW‰×V‰ÆSRjÿPèÿTÿÿjÿVè-OÿÿƒÄ…ÀtjÿVè­Pÿÿ_‰ÃXë‹]…ÛyWh°DVè/^ÿÿë
jþVèßLÿÿ‰Øeô[^_]ÃU‰åWVSìü‹]jhÑDjSè·`ÿÿƒÄ‰ÆjSèjNÿÿ_…ÀZ
jè(‚Yë9jSèˆaÿÿÙ½þüÿÿX·…þüÿÿZ€Ìf‰…üüÿÿÙ­üüÿÿÛøüÿÿÙ­þüÿÿ‹…øüÿÿ‰…ýÿÿ…ýÿÿ€>!u	PFèÄëP謉ÇX…ÿuSèÇQÿÿé`hÔDVè_}Z…ÀY…¼j	jSè¾Tÿÿÿ7º×D‰Øè´þÿÿÿwºÛD‰Øè¥þÿÿÿwºßD‰Øè–þÿÿÿwºäD‰Øè‡þÿÿ‹GºèD@P‰Øèvþÿÿ‹GƒÄ ºîDlP‰Øè^þÿÿ‹GºóD@P‰ØèMþÿÿ‹GºøD@P‰Øè<þÿÿ‹G ƒÄ…Àˆ®PSèÖRÿÿY^hýDjþSè3UÿÿƒÄéÆEä%…ÔýÿÿPSÆEæèåaÿÿXZ€>tg€>%u€~u+Eà•Ôýÿÿ9…ÔýÿÿrRè°dÿÿX¶‹…Ôýÿÿˆÿ…Ôýÿÿë.Fýÿÿ¶WˆEåEäPhÈSèJ€P…ÔýÿÿSPèdÿÿƒÄFë”…ÔýÿÿPè·cÿÿXeô¸[^_]ÃU‰åVSƒì0‹]jSènLÿÿ^…ÀZjè,€éÇjƒÎÿjSèö]ÿÿjSè‡Jÿÿjº×D‰ØèMýÿÿ‰EȺÛD‰Øjè<ýÿÿ‰E̺ßD‰Øjè+ýÿÿ‰EÐƒÄ ºäDjÿ‰Øèýÿÿ‰EÔºèD‰ØjÿèýÿÿjÿHºîD‰E؉ØèôüÿÿƒÄ-lhýDjÿS‰EÜèîQÿÿƒÄjÿSè½KÿÿZ…ÀYtjÿSè×MÿÿY^‰ÆjþSèãIÿÿXEȉuèZPè ^ƒøÿu	Sè\OÿÿYëPÛ$ƒìÝ$SèaOÿÿƒÄeø¸[^]ÃU‰åSPP‹]jjjSèÒ^ÿÿÙ}úƒÄ·Eú€Ìf‰EøÙmøÛ]ôÙmú‹EôPjSèb^ÿÿYÙ}úX·Eú€Ìf‰EøÙmøÛ]ôÙmú‹EôPè…~Ý$SèìNÿÿ‹]ü¸ÉÃU‰åVS‹]jjjSè#]ÿÿh@	D‰Æh	DjSèo]ÿÿƒÄ Vÿ4…	Dè*~ZYPSèOÿÿeø¸[^]ÃU‰åjjÿuè‘^ÿÿƒÄPè}{U‰åh Dh\	Dÿuè^aÿÿɸÃU‰åS‰ÃRPèÓÿÿZYPh~	Dÿs4èÆøÿÿƒÄPSèÖÔÿÿ‹]üÉÃU‰å‹MS‰Ã‹ƒx<uQRhŒ	Dÿsè—øÿÿƒÄëQRÿpX…tÿÿÿZSPÿw0è|ÿÿƒÄÿµ¬þÿÿÿw0èWoÿÿéBüÿÿW1Ûè ÓÿÿXº	‰øèïñÿÿ…À„‹‰ø‹_0è‘òÿÿj‰Â‰øèóÿÿXº…4ÿÿÿÿs$è•òÿÿÇ$Sè|lÿÿYº‰ø^µÿÿÿèµóÿÿÿw‰ò‰øjè¡X…4ÿÿÿZVPSèl{ÿÿ¶C2ƒÄ‹·„Cª‹J‹SkÀ‰T駉øè	òÿÿS‰Â‰øèòÿÿYº,‰øCè=ñÿÿ…Àuݺ=‰øè-ñÿÿ…Àt•ôþÿÿ‰øè
‰ÂëÇ…ôþÿÿ1Ò…ôþÿÿP‰øR‰ÚèkõÿÿX‰øZ‰Úèóÿÿé6W‹w0è†ÒÿÿX‹_‰Øè ùÿÿ…Àuƒû;uÇ…þÿÿ1Àé‘Ôþÿÿ‰ø‰Úè!
‰…þÿÿ‹…Ôþÿÿƒè
ƒøwMjÿSVèÏlÿÿƒÄƒ½Ôþÿÿ
”À1Òƒ½þÿÿ”Â…Ðt‹‹Üþÿÿ‹P‹ŠƒàÀƒÈ‰Š¶F2Ç…þÿÿÿÿÿÿë!ƒ½þÿÿuSVè8sÿÿY[ë
SVèñrÿÿX¶F2ZÿµþÿÿPVè•oÿÿƒÄëWè¸Ñÿÿ[‰øè|øÿÿ¸ëR•¼þÿÿ‰ø‹_0èÉ
ƒ½¼þÿÿ
µ´þÿÿu‹‹Äþÿÿ‹P‹Š%ÿ?€ÿ€Ì@‰Šëj‰ò‰øÇ…´þÿÿèžY1Àº;‰Ã‰øè¥ïÿÿ‹W0¶B2‰B$…Ûu‹_‰ØèÖ÷ÿÿ…À„wøÿÿ‹W4·B4Hf‰B4eô[^_]ÃUü‰åWƒÉÿVSì]¤‹U‹E‹u‰×‰Eà1Àò®÷ÑIQRVèïƒÄPÿuSVèšÄÿÿ•dýÿÿ‰Øè¨ôÿÿ‹…dýÿÿÆ@JSèºÐÿÿ‰Øèç÷ÿÿ‰Øºèïÿÿ‰ØèVõÿÿ‹…dýÿÿeô[^_]ÃU‰åWV‰ÆSìL‰•°ýÿÿ•´ýÿÿèQôÿÿ‹…´ýÿÿ‹U‰P<º(‰ðèàîÿÿƒ}t(jhDVè?ÃÿÿƒÄ‰Â‰ðjèÊïÿÿ‰ðºè¢ðÿÿX‹N01Û‹9‰¬ýÿÿÆGJƒ~)tv‹F=t=uB‰ðèïÿÿS‰Â‰ðè„ïÿÿXCë:VèêÏÿÿÇ$hDVèÏÂÿÿƒÄ‰Â‰ðSCèZïÿÿYÆGJë
h!DVè›ÂÿÿXZ€Juº,‰ðèîÿÿ…À눉ډðèðÿÿ¶WJ‹¬ýÿÿ€â¶A2(ЈGI¶A2PQèhÿÿYº)‰ð[èííÿÿ‰ðè•öÿÿ‹V‹…´ýÿÿ‰P@ºÿu‰ðh	èÜíÿÿ‰ðèðóÿÿX‹F0Z‹‰…¨ýÿÿ‹@,‹{4@9ø~!h:DC4hÿÿjPÿsÿv4è“Öÿÿ‰CƒÄ‹S49×}‹CǸG9×|ô‹¨ýÿÿ‹•´ýÿÿ‹A,‹K‰‹•¨ýÿÿ@‰B,‹…´ýÿÿö@töCt
PSÿv4è
±ÿÿƒÄ‹¨ýÿÿ1Û‹A,HPjj$QèújÿÿƒÄºP‹…°ýÿÿèµíÿÿ_‹…´ýÿÿ€xHt;¶„]èýÿÿ1Ò€¼]çýÿÿjP•ÂÁâjCRÿµ¨ýÿÿèkÿÿ‹…´ýÿÿƒÄ¶@H9Ã|Åeô[^_]ÃU‰åWVSƒì(‰EЉUÌèbñÿÿ‹UЋBƒø-tƒø#tëC=»të51Ûë»ÿuÐèëÍÿÿj‹UÌ‹EÐè¬ÿÿÿÿuÌ‹EÐSÿp0èšqÿÿƒÄé7=
„‰+=„Žƒø{„Ñéù=	„Îéé=tp=tUéÔ=t=t&éÁj‹E̺è‹ìÿÿX‹UЋEÌÝBÝXé­‹UЋEÐÿr‹UÌèƒìÿÿë]jºëLjºëCjºë:‹EЋX0‹€xJuhRDÿuÐèà¿ÿÿ^_‹€`Jûjjjj%Sè«iÿÿƒÄºP‹EÌè	ìÿÿ[ë:‹UÌ‹EÐèÁë6ÿuÐè¾ÌÿÿY‹UЋEÐÿr‹UÌjèüÿÿXZë‹UÌ‹EÐèËë	ÿuÐè‘ÌÿÿX‹EЋP¸ƒú^„ Eƒú-°„“ƒú*°„†°ƒú%ëm1Àƒú+ëfƒú<¸	tl°ƒú/ëS¸ƒú>ëIú¸tL#ú°t@
°
úë$¸úëú¸
t|°útë¸븉ÇëQ¶„?`	D;EvIÿuÐ]ÔèÀËÿÿÿuÌ‹UÐWÿr0è±rÿÿ¶„?a	D‰ÚP‹EÐèlýÿÿS‰Æ‹EÐÿuÌW‰÷ÿp0èåpÿÿƒÄ$ƒÿuª‹EЋP4·B4Hf‰B4eô‰ø[^_]ÃU‰åjè-ýÿÿÉÃU‰åVu؉òSƒì ‰Ãèàÿÿÿƒ}ØuÇEØVÿs0è÷jÿÿ‹Eìeø[^]ÃU‰åV‰ÖS‰ÃPèËÿÿ‰ò‰Øè¨ÿÿÿVÿs0è¬lÿÿƒÄeø‰Ø[º]^]éxéÿÿU‰åW‰ÇVSƒìL‹@0‰U°‹P$‰E¬‰U¨u+‹E°xýÿÿ~h}D‹E¬ºýÿÿèÄèÿÿ[UÔ‰øèêÿÿë
UÔ‰øèrÿÿÿ‹U°‰ø]´ÿBº=èéÿÿEÔPÿu¬è>lÿÿ‰Æ‰Ú‰øèÿÿÿSÿu¬è*lÿÿZ‹U°YPV‹Bÿpj	ÿu¬ègÿÿ‹U¨‹E¬‰P$eô[^_]ÃU‰åV‰ÆS‰ÓèÇþÿÿ{ ýÿÿ~‹F0ºýÿÿh}Dè'èÿÿ^ÿC ÿC$eø[^]ÃU‰åWV‰ÆSƒì8‰Ó‹x0‹@jjjj
W‰EÀè§fÿÿPº‰E¼‰ØÇEèÇEàÇEä‰]ÜèîèÿÿjEÄ1ÒèâèÿÿSÿv0èÁjÿÿƒÄ$º{‰ðèèÿÿƒ~}„™ƒ}ÄEÄt1PWè˜jÿÿƒ}è2XÇEÄZuj2‹EÜÿuäÿpWèBrÿÿÇEèƒÄ‹Fƒø[t=UÄuVè€Éÿÿƒ~ =UÄXuëUĉðè2þÿÿë‰ðèÞþÿÿº,‰ðèlçÿÿ…À…qÿÿÿº;‰ðèXçÿÿ…À…]ÿÿÿÿuÀº}‰ðj{è~çÿÿƒ}èYMÄ[tR‹UÄBóƒøw%jÿQWè^cÿÿƒÄ‹EÜjÿÿuäÿpWè•qÿÿÿMäƒÄë"…Òt	QWè¸iÿÿXZÿuè‹EÜÿuäÿpWènqÿÿƒÄ‹‹p‹E¼‹†ÿuäãÿÿèÓÛÿÿÁà	ËE¼‰†‹‹p‹E¼‹†ÿuàãÿ?€ÿè¯ÛÿÿÁà%À	ËE¼‰†eô[^_]ÃU‰åW¿V‰ÖS‰Ãè´üÿÿëVGÿs0è,iÿÿ‰Ø‰òèŸüÿÿYXº,‰ØèVæÿÿ…ÀuÛeô‰ø[^_]ÃU‰åWV‰ÆSƒì(‹x0‰UЋ@‰EÌ‹Fƒø{tk
ƒø(té‚=tdëy‹EÌ;Ft
h”DV舺ÿÿXZVèÇÿÿƒ~)Xu	ÇEÔë]Ô‰ð‰ÚèPÿÿÿjÿSWèbÿÿƒÄÿu̺)‰ðj(èÿåÿÿëUÔ‰ðèQýÿÿë$ÿvUÔ‰ðè—æÿÿVèCÇÿÿY[ë
hÅDVèºÿÿëZ‹EЃÊÿ‹MÔ‹XAóƒøv…ÉtEÔPWè+hÿÿXZ‰Ú÷ÒW$jBPSjWè¼cÿÿƒÄº
P‹EÐèæÿÿÿuÌWèˆbÿÿC‰G$eô[^_]ÃU‰åW‰×V‰ÆSƒìD‹@0‰E°‹Fƒø(t	=t1ë8V‹^è£ÆÿÿY‰ú‰ðè0ûÿÿS‰ðº)j(è%åÿÿXZWÿv0è½cÿÿë‰ðèéÿÿë
háDVèL¹ÿÿY[‹Fƒø:tWƒø(t}ƒø.t銃ø{tnƒø[të|=t^ës‰ú‰ðè•ìÿÿëÅW]Ôÿu°èwgÿÿ‰Ú‰ðèîúÿÿSWÿu°èÓmÿÿƒÄë¡V]´èÿÅÿÿ‰Ú‰ðègåÿÿSWÿu°èÒmÿÿ‰ú‰ðè÷ýÿÿƒÄétÿÿÿWÿu°èífÿÿ‰ú‰ðèÝýÿÿé[ÿÿÿeô[^_]ÃU‰åWV‰ÆSƒìH‹B‰U°ƒèƒøv
hóDVè{¸ÿÿY[º,‰ðèæãÿÿ…À„°‹E°}¼‰ú‰E´‰ðè þÿÿƒ}¼ue‹^01É‹U°‹C$…Ò‰E¬tSƒz	u&‹G9Bu‹E¬¹‰B‹G9Bu‹E¬¹‰B‹…ÒuÎ…Étjÿwÿs$jSèÖaÿÿƒÄjSè.^ÿÿXZ‹F4ºÈ·@4)Â9U~hD‹F0è÷âÿÿX‹EU´@P‰ðèÿÿÿXëIº=‰ð}ÔèHãÿÿ‰ú‰ðè‰üÿÿ;E‰ÃtW‹UP‰ðèsçÿÿ;]_X~+]‹F0)X$ëWÿv0è¼_ÿÿWë‹F0]Ôº‹@$HP‰Øè¥ãÿÿS‹E°ƒÀPÿv0è«lÿÿeô[^_]ÃU‰åWVuÔ‰òSƒì ‰ÃèÜøÿÿV‹}Ôÿs0èTeÿÿeô‰ø[^_]ÃU‰åUèVSƒì‰Ã‹p0j‰ðèƒçÿÿ‰ØèCëÿÿ‰ðèšçÿÿeø[^]ÃU‰åVS‰ÃPèôÃÿÿ‰Øèøÿÿ‰Æº‰Øèdâÿÿ‰Øè©ÿÿÿeø‰ð[^]ÃU‰åWV‰ÆSƒì‹X0‰Uàºè(äÿÿº‰ðè-âÿÿƒ}thþÿÿuàj Sèö_ÿÿƒÄëSè`ÿÿ_j‰ÇU䉨èåæÿÿ‹U‰ðèâãÿÿÿuSèŒ\ÿÿ‰ðè/ÿÿÿ‰ØèéæÿÿWSèö[ÿÿƒÄƒ}thþÿÿuàjSè›_ÿÿƒÄëÿujÿuàj!Sèæ_ÿÿƒÄÿu‰ÆSè¾^ÿÿƒ}GP‰ðuSèŒ_ÿÿ^PSè¿[ÿÿeô[^_]ÃU‰åV‰ÖS‰ÃhÀjjRèÊÿÿhÐj‰C(‰C¨jVÇC0‰C$èèÉÿÿ‰Cp‰S‹S‰C ÇC,-‰B‹CÇ@ƒÀ‰C‰‰C‹C@‰Beø[^]ÃU‰åV‰ÆS‰ÓjkB0Pÿr(VèŒÉÿÿj‹C,ÁàPÿs VèzÉÿÿeø[^]ÃU‰åWVSP‹]‹C‰ÚsH‰Eð‰Øè3ÿÿÿjjSèú"‰CHÇF‹sjj~`Sèà"‰F`ÇGj Sè=ƒÄ Sè2Sè³ÿÿjh DSèÕ€H ‹Uð‹BDÁà‰B@eô[^_]ÃU‰å]‰PÇ@ Ç@,Ç@pÇ@DÆ@8Ç@<Æ@9Ç@@Ç@hÇ@0fÇ@6fÇ@4Æ@Ç@Ç@(Ç@Ç@tÇ@PÃU‰åVS‹p‰Ãÿp Pè¹”ÿÿS轞ÿÿj‹S‹BÁàPÿ2SèEÈÿÿjÿv<ÿv4Sè7Èÿÿ‰F4ƒÄ,‰ÚÇF<‰Øè|þÿÿjhxSÿvÿVeø[^]ÃU‰åV‹uSjxjjVèøÇÿÿj‰ÃPVè_£ÿÿ‹V‰Øèöþÿÿ‰ò‰Øè¶ýÿÿ‹FH‹VL‰CH‹FP‰SL‰CP‹V<¶F8‰S<‰S@ˆC8‹FD‰CDeø‰Ø[^]ÃU‰åV‹uS‹]ÿs Sèï“ÿÿ‰Ú‰ðèçýÿÿjjxSVèÇÿÿeø[^]ÃU‰åWVShxjjÿuÿUƒÄ‰Ç1À…ÿ„ýÇ_x‰øÆG‰Ú‰þÆC!ÆGaèIþÿÿÇC@‹EÇCÇC‰C‹E‰{pÇGx‰C‡ð‰ƒˆ‰ƒŒ‹GÇC4ÇCXÇ@h‡”‰C 1ÀÇC<ÆC‰{ÇCÇC$ÇC(ÇC,ÇC0ÇCDxÇCPÈÇCTÈÇCLÇ„ƒ˜@ƒø~ïjh!õ@W蟂ÿÿƒÄ…Àt	‰ø1öèéýÿÿ‰ðeô[^_]ÃU‰å]éœÿÿU‰åS‹]‹C‹Xpÿs S茒ÿÿjSèV•ÿÿÇCtƒÄfÇC6‹C(fÇC4‰C‹‰C‰CjhCø@Sè-‚ÿÿƒÄ…Àu҉؋]üÉéuýÿÿU‰åWVSQQ‹U‹B€x„”‹E@=ÿÿÿ?w‹EÁàPjjRè°ÅÿÿƒÄë	ÿuèÅÿÿZ‰Eð‹E1ÿ‹p;}}
‹UðǺGëî1ÿ;~}(‹‹¸…Ût‹U‹J#S‰Eì‹Eð‹‰‰‹]ìëàGëÓj‹FÁàPÿ6ÿuèCÅÿÿ‹U‹Eð‰V‰eô[^_]ÃU‰åWV‹uS‰ð‰ñÁèX9Þr‹}‰ð‰òÁêÁàжTÿ)ÙÐ1Æ9Ùëà‹E‹x‹G‹H!ð‹‚…Ût?‹U9Su3RCPÿuèZƒÄ…Àu¶G¶S4 Ш„¨€òˆSé‹뽋E@ƒøív	ÿuè‚ÄÿÿX‹EƒÀPjjÿuè‚Äÿÿ‹}‰p‰Ã‹UƒÄ‰x‹B¶@ÆCÆC$ˆCCWÿuPèUÆD;ƒÄ‹}‹O‹Q‹J!ò‹‰‹‰‹A‹Q@9ЉAvúþÿÿ?PWè,þÿÿ^_eô‰Ø[^_]ÃU‰åV‹uS‹]ƒþåvSèÚÃÿÿXFPjjSèßÃÿÿ‹S¶RÆ@‰pÇ@€âˆP‹U‰P‹S‹Rp‹‰‹S‹Rp‰eø[^]ÃU‰åSP‹]EøPjSè¼6ÿÿÿuøSè®(ÿÿ‹]ü¸ÉÃU…À‰åyD]‰Â÷ÐÁø!ÐÃU‰åEðWVSSS‹}PjWè|6ÿÿjW‰Eìè8ÿÿZ‹UðYè¾ÿÿÿjÿ‰ÆjWèF8ÿÿ‹]ðƒÄ‰Úè¥ÿÿÿƒÄ…ö¾9Ø~‰Ø9Æ‹Uì)ð@PD2ÿPëjh 
DWè3(ÿÿƒÄeô¸[^_]ÃU‰å…äýÿÿVSì‹]PjSèð5ÿÿ‰Æ…èýÿÿPSè²8ÿÿƒÄ‹…äýÿÿH‰…äýÿÿ@t2Eô•èýÿÿ9…èýÿÿrRè|;ÿÿX‹…äýÿÿ¶0‹…èýÿÿˆÿ…èýÿÿë¾…èýÿÿPè­:ÿÿeø¸[^]ÃU‰å…àýÿÿWV1öSì‹]PjSèd5ÿÿ‰Ç…äýÿÿPSè&8ÿÿƒÄ;µàýÿÿs7Eð•äýÿÿ9…äýÿÿrRèø:ÿÿX‹äýÿÿC‰…äýÿÿ¶>FPèxWˆXëÁ…äýÿÿPè$:ÿÿeô¸[^_]ÃU‰å…àýÿÿWV1öSì‹]PjSèÚ4ÿÿ‰Ç…äýÿÿPSèœ7ÿÿƒÄ;µàýÿÿs7Eð•äýÿÿ9…äýÿÿrRèn:ÿÿX‹äýÿÿC‰…äýÿÿ¶>FPèÞVˆXëÁ…äýÿÿPèš9ÿÿeô¸[^_]ÃU‰å…àýÿÿWVSì‹]PjSèR4ÿÿj‰ÇSèõ5ÿÿ‰Æ…äýÿÿPSè
7ÿÿƒÄ‰ðN…À~ÿµàýÿÿ…äýÿÿWPè:ÿÿƒÄëá…äýÿÿPè(9ÿÿeô¸[^_]ÃU‰åEðWVSVVPjÿuèè3ÿÿjjÿu‰EìèÄ5ÿÿ‹UðƒÄè%ýÿÿP‰Æjÿuè¬5ÿÿ‹]ðƒÄ‰ÚèýÿÿƒÄ…ö‰Â¾9Úv‰Ú1À9ÖO‰Ð)ðx>9Ðh!
Dÿuèú0ÿÿY[h!
DWÿuèÒ2ÿÿƒÄ…ÿ~‹Eì‰ûtÿ¶FPÿuèM%ÿÿXKZuî‰øeô[^_]ÃU‰åWV¾Sì‹}WèMÿÿ‰…àýÿÿ…äýÿÿPWèç5ÿÿƒÄ;µàýÿÿJVWè±4ÿÿZ‰Ã¶À9ØYth7
DVWèš0ÿÿƒÄEð•äýÿÿ9…äýÿÿrRè˜8ÿÿX‹…äýÿÿFˆÿ…äýÿÿë®…äýÿÿPèÒ7ÿÿeô¸[^_]ÃU‰åÿuÿuÿuè{8ÿÿÉ1ÀÃU‰åVµèýÿÿSì‹]jjSè2ÿÿjSè¢ÿÿVSè75ÿÿVhÿ@Sè,,ÿÿƒÄ(…Àt
hE
DSèÃ/ÿÿ[XVè]7ÿÿeø¸[^]ÃU‰åV‰ÆS‰ÓC¾ƒø%tƒø[tëN€;uDhc
Dÿvè„/ÿÿY^ë31À€;^”ÀÀ;uh†
Dÿvèd/ÿÿXZ¶C<%u¶<ƒÛÿ€;]u×Cë‰Øeø[^]ÃU‰åV‰ÖS‰ÃRèTYƒèaƒø‡Vÿ$…¨
D¡¬2Dƒ8u¡Ø2D‹·X%é"h顬2Dƒ8u¡Ø2D‹·Xƒà éûj é졬2Dƒ8u¡Ø2D‹·Xƒàé×jéÈ¡¬2Dƒ8u¡Ø2D‹·Xƒàé³j餡¬2Dƒ8u¡Ø2D‹·Xƒàéj逡¬2Dƒ8u¡Ø2D‹·Xƒàënjëb¡¬2Dƒ8u¡Ø2D‹·XƒàëPjëD¡¬2Dƒ8u¡Ø2D‹·X%ë0hë!¡¬2Dƒ8u¡Ø2D‹·X%€ë
h€SèòN[Z‰Ãë…Û”À¶Øë	1À9Þ”Àë3¡¬2Dƒ8u¡Ø2D‹·pƒàë
jVè·NZY…À‰Úu1Ò…Û”‰Ðeø[^]ÃU‰åW¿V‰ÆS‰Ó€z^uf1ÿCC;]sD¶<%uC‰ð¶èþÿÿ…Àtäë(€{-uS;Us¶Bþ‰Ó9ðʶ9ÆÃë¶À9ðuº‰øë1À…ÿ”À[^_]ÃU‰åVS‰Ã¶‹u¾Èƒù.tƒù%të,ƒù[të%¸ë)¶R‰Ø[^]é¢ýÿÿFÿ‰E‰Ø[^]éGÿÿÿ¶À9Ø”À¶À[^]ÃU‰åW‰×VSƒì‹u‰Eð¾ƒø%„¤…À„*ƒø$„(é<ƒø(t
ƒø)t'é-€~)ujþFëjÿFP‹Eð‰úèæéÙ‹UðF‹BHx‹Mðƒ|ÁÿtëñhD‹Eðÿpè6,ÿÿ[Z‹Uð‰Ã‰ø+DÚ‰DÚ‹EðV‰úèXÿÿÿY…À…Ž‹MðÇDÙÿÿÿÿé~¶V¾Âƒøbt
ƒøft~éá€~^t€{uh(D‹EðÿpèÌ+ÿÿXZ¶1Ò:u=¾À¹W‰Eì‹Eð¾[‰]è‹X9Ús¾;EèuIuBë;Eì”À¶ÀÁBëà1Ò…Ò‰×„êƒÆéÁþÿÿƒÆ€>[th;D‹UðÿrèZ+ÿÿY[‹Eð‰òèŸûÿÿ‰Eä‹Mð1À;9t¶Gÿ‹]ä‰ò¶ÀKSè¥ýÿÿZ…À…–¶‰òSè‘ýÿÿ[…À„‚‹uäéYþÿÿ¡¬2D¶Òƒ8u¡Ø2D‹·Pƒàë
jRèúKZY…À„жFƒè1x‹Uð;B}‹Mð‰Âƒ|Áÿuh^D‹Eðÿpè®*ÿÿY‰Â[‹Mð‹A‹\Ñ)ø9ØrSWÿtÑè4OƒÄ…Àt1Ò…Ò‰×„éƒÆéÀýÿÿ‰øéç€~u‹Uð‰ø;z„ÓéÁ‹Eð‰ò1Ûè–úÿÿ‰Eà‹Mð;ys¶‰òÿuàèýÿÿZ…Àt³‹Uྃø+t=ƒø*t.ë~ƒø-tFƒø?ut…Ût‹EàW@P‹Eðè2ýÿÿY…Àul‹uàFé5ýÿÿÿuà‰úVë
1À…ÛtUÿuàWV‹EðèœëD‰û‹Eà‰Ú@P‹EðèôüÿÿZ…Àu.‹Mð;Ys¶‰òÿuàèüÿÿ_…ÀtCëÏ…Ûu1Àë	‹uàGéÒüÿÿeô[^_]ÃU‰åW‰×VS‹p‰Ãƒþ~htDÿpè\)ÿÿXZ‰|ó‹E‰ú‰DóFÿu‰C‰Øè{üÿÿY…ÀuÿKeô[^_]ÃU‰åW‰ÇV‰ÖS1ÛëC;Gs¶‹UÿuèíûÿÿZ…Àuä…Ûx‹E@P‰øè.üÿÿY…ÀuKëç1Àeô[^_]ÃU‰åW‰×VS‰Ã‹U;{‹E|#…ÿu)ÐPRëYÇE^D‹C‰Eeô[^_]é¦(ÿÿ‹tûƒþÿuh†Dÿsè(ÿÿYXë!ƒþþu‹Dû+@‰E‹C‰Eeô[^_]éëÿÿVÿtûÿsèùÿÿƒÄeô[^_]ÃU‰åW‰ÇVSQ‹H‰Uð…ɉË•ƒ}ð”À	Шu»htD1öSÿwè*ÿÿƒÄ9Þ}ÿu‰ò‰øFÿuðè&ÿÿÿXZëèeô‰Ø[^_]ÃU‰åWVSì4‰…Øþÿÿ…àþÿÿPjÿµØþÿÿ‰•ÔþÿÿèO*ÿÿ‰…Ðþÿÿ…ÜþÿÿPjÿµØþÿÿè5*ÿÿjjÿµØþÿÿ‰…Ìþÿÿè,ÿÿ‹àþÿÿƒÄ‰Úègóÿÿ‰ÇƒÄOy1ÿë9ßv‰ßƒ½Ôþÿÿ„÷jÿµØþÿÿèÿÿ[…À^uh™DÿµÌþÿÿèþKZ…ÀY…Ê‹…Ðþÿÿ‹µàþÿÿø‰…Èþÿÿ)þ‹½Üþÿÿ…ÿto9÷v
é‚‹…Äþÿÿë^O)þë'W‹…ÌþÿÿC@PSèžKƒÄ…Àt܉Ø+…Èþÿÿ‰Èþÿÿ)Æ…ö„F‹•Ìþÿÿ¾VPÿµÈþÿÿè‰K‰…ÄþÿÿƒÄ…À‰Ãu¬é…À„‰Ã+ÐþÿÿCPÿµØþÿÿèÿÿÜþÿÿSÿµØþÿÿèÿÿÿ¸éñÇ…Àþÿÿ‹…Ìþÿÿ€8^uMÇ…Àþÿÿ@‰…Ìþÿÿë:+ÐþÿÿCPÿµØþÿÿè¸ÿÿ+µÐþÿÿVÿµØþÿÿè¦ÿÿj1Ò‰øèÈýÿÿƒÀé‹…Ðþÿÿ‹Ðþÿÿ‹•Øþÿÿ‰…äþÿÿû…àþÿÿ‰•ìþÿÿ‰…èþÿÿÿµÌþÿÿ½äþÿÿ‰ÚÇ…ðþÿÿ‰øèùÿÿ‰Æ…öXtƒ½Ôþÿÿ…gÿÿÿV‰Ú‰øèWýÿÿë$‰ØC;…èþÿÿs	ƒ½Àþÿÿt­ÿµØþÿÿèÖÿÿ¸eô[^_]ÃUº‰å‹E]éuýÿÿU1Ò‰å‹E]égýÿÿU‰å…àþÿÿWVSìPhíØÿÿÿuèÿÿj‰ÇhìØÿÿÿuèöÿÿ‰…Üþÿÿ‹EhëØÿÿÿu‰…ìþÿÿ‰ø…àþÿÿ‰½äþÿÿ‰…èþÿÿèaÿÿƒÄ ;èþÿÿwZÿµÜþÿÿ‰Ú…äþÿÿÇ…ðþÿÿèøÿÿ‰Æ…öXt3‰ð1Ò)ø9Þ”ÂÐPÿuè4ÿÿhëØÿÿÿuè8ÿÿV‰Ú…äþÿÿèFüÿÿëCëž1Àeô[^_]ÃU‰åS‹]jjSèþ&ÿÿjjSèô&ÿÿjSè!ÿÿƒÄ jSèÜÿÿjhÞ	ASèÁÿÿ‹]ü¸ÉÃU‰åh¤Dÿuè5$ÿÿÉÃU‰å…ÐüÿÿWVSì@Pjÿuè›&ÿÿj‰Æjÿuè&ÿÿjÿu‰…Èüÿÿèrÿÿ‰Ã‹…ÐüÿÿƒÄ @PjÿuèQ(ÿÿ‰…Äüÿÿ‹…ÈüÿÿƒÄÇ…Àüÿÿ€8^uÇ…Àüÿÿ@‰…ÈüÿÿÇ…¼üÿÿCýƒø–ƒû”À	ШuƒûthÒDjÿuè±#ÿÿƒÄ…ÔüÿÿPÿuèÃ(ÿÿ_‰ð‰µäþÿÿ‹U…Ðüÿÿ‰•ìþÿÿ‰…èþÿÿX‹Äüÿÿ9¼üÿÿWÿµÈüÿÿ‰ò…äþÿÿÇ…ðþÿÿè]öÿÿ‰…¸üÿÿ…À[„Èj‹ìþÿÿ½Ôüÿÿÿ…¼üÿÿSèpÿÿZƒøY„"ƒøŒ7ëƒø„Üé'…Ìüÿÿ1ÛPjÿµìþÿÿè„ÿÿ‰…´üÿÿƒÄ;Ìüÿÿƒ]‹…´üÿÿ€<%u3‹…´üÿÿC¶¡¬2Dƒ8u¡Ø2D‹·Pƒàë
jRèCZY…Àu#‡9rWè *ÿÿY‹´üÿÿ‹¶ˆÿëD‹•´üÿÿ¶<0u‹…¸üÿÿ)ðPVWèŽ*ÿÿƒÄë!ÿµ¸üÿÿ¾Ðƒê1…äþÿÿVè*ùÿÿXZWèU+ÿÿXCéHÿÿÿjSè<ÿÿY‰òX…äþÿÿÿµ¸üÿÿè‰ùÿÿÇ$PSè¥ÿÿƒÄë ÿµ¸üÿÿ1Ò…äþÿÿVè×øÿÿXZjSè&ÿÿYXjÿSèCÿÿY…ÀZujþSèMÿÿX‹…¸üÿÿZ)ðPVSèÿÿë-jÿSè‡ÿÿZ…ÀYu"jÿSèãÿÿZYPSèùÿÿZYPhñDSèR!ÿÿƒÄWèž*ÿÿXƒ½¸üÿÿ•À1Ò9µ¸üÿÿ—Â…Ðt‹µ¸üÿÿë5;µèþÿÿs:…àþÿÿ•Ôüÿÿ9…ÔüÿÿrRèO)ÿÿX¶F‹…Ôüÿÿˆÿ…Ôüÿÿƒ½Àüÿÿ„—ýÿÿ‹…èþÿÿÔüÿÿ)ðPVSè8)ÿÿSèk(ÿÿÿµ¼üÿÿÿuè;ÿÿeô¸[^_]ÃU1Ò‰åWü‰ÇVƒÉÿS‰ÆˆÐò®÷ÑQÿ¶\ÿfÇDÿlˆ\ÿÆD[^_]ÃU‰å…ÀûÿÿWVSì`PjÿuÇ…¤ûÿÿèÙ"ÿÿ‰Æ‹…Àûÿÿð‰… ûÿÿ…äýÿÿPÿuè‹%ÿÿƒÄ;µ ûÿÿƒò€>%uF€>%u,Eð•äýÿÿ9…äýÿÿrRèN(ÿÿ[¶F‹…äýÿÿˆÿ…äýÿÿë½ÿ…¤ûÿÿ•Äýÿÿ‰÷‰•œûÿÿëG¶„Àt¾ÀPhDèˆ?Z…ÀYu䉸)ðƒøvhDÿuè§ÿÿY[¶¡¬2Dƒ8u¡Ø2D‹·Pƒàë
jRè•@[Zƒø¡¬2Dƒßÿ¶ƒ8u¡Ø2D‹·Pƒàë
jRèh@ZYƒøƒßÿ€?.u[¡¬2DG¶ƒ8u¡Ø2D‹·Pƒàë
jRè5@Y[ƒø¡¬2Dƒßÿ¶ƒ8u¡Ø2D‹·Pƒàë
jRè@[Zƒøƒßÿ¶¡¬2Dƒ8u¡Ø2D‹·Pƒàë
jRèÛ?ZY…Àth8Dÿuè³ÿÿY[‹œûÿÿ‰û)óCÆ%APV‰þFQ‰œûÿÿè¤>‹…œûÿÿƒÄÆD¾ƒøg>ƒøeWƒøX„ûƒøE„CƒøG„:é݃øctJƒød„†éʃøq„E
ƒøitqƒøoëƒøu„±ƒøs„7霃øx„˜éŽÿµ¤ûÿÿÿuè¡!ÿÿÙ½¶ûÿÿX·…¶ûÿÿZ€Ìf‰…´ûÿÿÙ­´ûÿÿÛ¨ûÿÿÙ­¶ûÿÿ‹…¨ûÿÿPé1Äýÿÿ‰Øèÿüÿÿÿµ¤ûÿÿÿuèO!ÿÿ_Ù½¶ûÿÿX·…¶ûÿÿ€Ìf‰…´ûÿÿÙ­´ûÿÿÛ¨ûÿÿÙ­¶ûÿÿ‹…¨ûÿÿëLÄýÿÿ‰Øè±üÿÿÿµ¤ûÿÿÿuè!ÿÿÙ½¶ûÿÿ·…¶ûÿÿZ€Ìf‰…´ûÿÿÙ­´ûÿÿß½¬ûÿÿÙ­¶ûÿÿY‹…¬ûÿÿPSé—ÿµ¤ûÿÿÿuè» ÿÿ…ÄýÿÿÝ$P…ÄûÿÿPèÊ<ƒÄé…¼ûÿÿäýÿÿPÿµ¤ûÿÿÿuèWÿÿ‰…˜ûÿÿEðƒÄ9…äýÿÿrSè%ÿÿX‹…äýÿÿÆ"ÿ…äýÿÿ‹…¼ûÿÿH‰…¼ûÿÿ@„œ‹•˜ûÿÿ¾ƒø
tH	…ÀtKƒø
ëƒø"tƒø\uN»9;rSè«$ÿÿX‹Æ\‹@‰9ørSè–$ÿÿX‹˜ûÿÿ‹¶ë7jheDëjhhDSè‘$ÿÿƒÄë ƒ9rSè]$ÿÿX‹½˜ûÿÿ‹¶ˆÿÿ…˜ûÿÿéPÿÿÿƒ9rSè2$ÿÿX‹Æ"ÿé©ûÿÿ…¸ûÿÿPÿµ¤ûÿÿÿuèKÿÿj.‰Ã…ÄýÿÿPè{;ƒÄ…Àu%ƒ½¸ûÿÿcvÿµ¤ûÿÿÿuèãÿÿ…äýÿÿPèá$ÿÿëNS…ÄýÿÿP…ÄûÿÿPèK;ƒÄë¾FÿPhmDÿuè_ÿÿë:ü1À•ÄûÿÿƒÉÿ‰×ò®÷Ñ…äýÿÿIQRPè¥#ÿÿƒÄéûÿÿ…äýÿÿPèÊ"ÿÿ¸eô[^_]ÃU‰åS‹]h DhDSè_"ÿÿhaDjÿSè—ÿÿh[DjþSèqÿÿƒÄ$jjSèEÿÿƒÄjh 
DSèhÿÿƒÄjþSè
ÿÿXZjþSèzÿÿYXjþSèh	ÿÿXZjþSèï
ÿÿYXh–DjþSèÿÿƒÄjþSèD	ÿÿX¸‹]üZÉÃUÙî‰åSSS‰ÃÝEÚéßàžuz‹Së'¶Kº‹E‰EøÓâJEƒÊ‰Ñ1Ò‰Eô÷ñÁâS‰ÐZY[]ÃU‰åVS‰ÃQQ‹BƒøtIƒøt5ë@ƒøtƒøtë4ÿr‰Øÿ2è…ÿÿÿ^‰ÁZëC¶K¸‹ÓàHÿ#Jë(¶KÓàHÿ#
ë¶K¸‹21ÒÓàHÿƒÉ‰ð÷ñ‰ÑÁáKeø‰È[^]ÃU‰åRRƒxu"ÝÙÀDØÁÝ]ø‹Eø‰ÂPÛ$ƒÄÚéßàžztƒÊÿɉÐÃUƒÈÿ‰åWVSS‹u‹}ƒ~„°‰ðè«ÿÿÿ…À~R;GMHéšPÛ$ƒÄÇFÝOë‹Uð‹A‹Q‰‹A‰V‰F‹‹Q‰F‹A‰V‰F¸鿉ò‰øèÈþÿÿ‰ÃVCPèä´ÿÿZ…ÀYuƒ{uƒ~~‹9Cu
‰Ø+GÁøGë‹[…ÛuÉhÄDÿuè*bÿÿY1À[‹_P9Ú}‰ÑÁá‹Gƒ|B…FÿÿÿƒÁ9؉Â|æ¶_¸+WˆÙÓà9Â}-‰ÐÁà‰Eð‹G‹Mðƒ|…%ÿÿÿƒÁ ¸B‰MðˆÙÓà9Â|Û1Àeô[^_]ÃU‰åS‰ÓèƒþÿÿH1Ò=ÿÿÿwPèó³ÿÿÿDƒº‹]ü‰ÐÉÃU‰Á‰åV‹uS‰ÓF=ÿÿÿw‰ðÁàP‹BÁàPÿrQè>§ÿÿƒÄëQè§ÿÿZ‰C‹S9ò}‰ÑÁáÇDBƒÁ9ò|ð‰seø[^]ÃU‰åW‰×V‰ÆSQ‹]…ÛuÇB DÇEðë|CÿPèW³ÿÿZ@ƒø‰Eð~
hÚDVèæ`ÿÿ[X¶Mð»ÓãC=ÿÿÿw‰ØÁàPjjV袦ÿÿƒÄëV胦ÿÿY‰G…Û~$1ɉڋGȃÁ Ç@JÇ@Ç@uà¶EðÁã_ˆG‰_eô[^_]ÃU‰åV‹uSj jjVè?¦ÿÿj‰ÃPVè¦ÿÿÆCÿ‰Ú‰ðÆCÇCÇCÇCÇC DÿuèšþÿÿƒÄ ‰ð‰Úÿuèìþÿÿeø‰Ø[^]ÃU‰åV‹uS‹]‹Sú Dtj¸ ¶KÓàPRVèÁ¥ÿÿƒÄj‹CÁàPÿsV謥ÿÿjj SVè¡¥ÿÿeø[^]ÃU‰åPP‹U‹MBÿ;AsÁâQBðë?‰Ðë;R‰ÈÛ$ƒìÝ$Ý]øèûÿÿZ‰ÂYƒzuÝBÝEøÙÉÚéßàžztÍ‹R…Òuâ¸ÀDÉÃU¸‰åS‹U‹]¶JÓàH#CÁàBƒxu9Xt‹@…Àuî¸ÀD[]ÃU‰åVSSS‹u‹M‹Vƒút…Ò¸ÀDteë<ƒúu7ÿ6Qè˜ÿÿÿëTÝÙìDØÁÝ]ð‹UðRÛ$ƒÄÚéßàžuz
RQèÿÿÿë+‰Øë'‰ò‰Èèûÿÿ‰ÃVCPè,±ÿÿZ…ÀYuá‹[…Ûué¸ÀDeø[^]ÃU‰åWVS‹]‹u‹}SVè^ÿÿÿÆF=ÀDYZu>‹C…ÀuhðDëƒøuÝÝèßàžzt
hDWèG^ÿÿXZ‰]eô‰ò[‰ø^_]éSeô[^_]ÃU‰åWVSƒì‹}‰Eð‹B‰Uì‹Mì9ljEè‹I¶R‰Mà‰Uä~
W‹Uì‹Eðèküÿÿ^ÿu‹Uì‹Eðè½üÿÿ;}è[„‹Eì‰ú‰þÁâ‰U܉x‹Mì‹UÜ‹Aƒ|t#FPQÿuð蘋ƒÄ‹K‰‹S‰H‰PƒEÜF;uè|ÃG=ÿÿÿwÁeèÁç‹MìWÿuèÿqÿuðèL£ÿÿƒÄë	ÿuðè+£ÿÿY‹Uì‰B¶Mä¸Óà‰ÆNx9‹Uà‰ðÁàƒ{t"CPÿuìÿuðè’þÿÿ‹ƒÄ‹K‰‹S‰H‰Pƒë NyÒ}à Dt¶Mä¸ jÓàPÿuàÿuðèÍ¢ÿÿƒÄeô[^_]ÃU‰åW‰×VS줋U‰…|ÿÿÿ‰øèùÿÿƒx‰Ãu= D…]‹W‹OBà‰G9Êv‹WƒztBà‰Gëë…Ò‰Ö…ð1ÀÇD…„@ƒø~òÇ…pÿÿÿ»Ç…xÿÿÿÇ…tÿÿÿ‹tÿÿÿ1ö‹G9Á~9ÉÁGë;tÿÿÿ‰ÚÁâ‰ÐG‹@øƒøƒÞÿCƒÂ9Ë~êµpÿÿÿ‹…xÿÿÿÑ¥tÿÿÿt…„@ƒø‰…xÿÿÿ~¤Ç…lÿÿÿ»‹•pÿÿÿÇ…hÿÿÿ¶O‰U€ÓãKƒûÿt0‰ÞÁæ‹GðƒxtƒÀU„èùùÿÿ…hÿÿÿÿ…lÿÿÿKƒî ƒûÿuÕ‹EU„‹hÿÿÿM€‹µpÿÿÿµlÿÿÿèÄùÿÿE€Ç…\ÿÿÿ¹F9…\ÿÿÿ‰E€Ç…`ÿÿÿÇ…XÿÿÿÇ…dÿÿÿ}v‹dÿÿÿ‹D„…À~2…`ÿÿÿº‰È‰Ó™÷û9…`ÿÿÿ‰…Pÿÿÿ~‰Xÿÿÿ‹…`ÿÿÿ‰…\ÿÿÿ‹U€9•`ÿÿÿ‰•Pÿÿÿt%ÿ…dÿÿÿ	º‰Ó™‰Á÷û‹•Pÿÿÿ9Љ…Tÿÿÿëˆ+µ\ÿÿÿ‰ú‹Xÿÿÿ‹…|ÿÿÿVQ‰M€è|üÿÿXZÿuWÿµ|ÿÿÿèüÿÿëzS‰øèáöÿÿ9Øt)9Xt‹@ëö‰pj SVè1ÇCƒÄÇCë‹C‰F‰s‰ó‹M‹‹Q‰C‰S‹A‰Cƒy~‹ö@töGtWÿµ|ÿÿÿèW{ÿÿ_X‰Øeô[^_]ÃU‰åVSƒì‹u‹]VSèEúÿÿY=ÀDZuVEè‰ÚÛ$‰$‹EÇEðÝ]èèöüÿÿeø[^]ÃU1À‰åVS‹U‹u‹]z Dt¶J°Óà‰E‰ð‰][^]ésûÿÿU‰åVSƒì‹u‹]VSè0úÿÿY=ÀDZu‰uèEè‰ÚP‹EÇEðèˆüÿÿeø[^]ÃU‰å‹EWVS‹H…Ét:‹p‰ÈÁàƒ|øu+1Ûƒùv Ñê‰ÐÁàƒ|øu‰Ñë‰Ó‰È)؃øëÞ‰Øëz‹U‰È‰Îyz Du-ëe‰þÑëSÿuè÷øÿÿƒxYZu‰ßë݉ÞëÙ‰ðeô[^_]ÃU‰åWV¾S‹]jjSè$ÿÿjSè2ÿÿj‰ÇjSèÿÿƒÄ 9þGjSè+ÿþÿVSèYÿÿVjSèüÿÿjjSè	ÿÿƒÄ(jÿSè5ÿþÿY…ÀZt¸ëjþFSè_ýþÿXZëµ1Àeô[^_]ÃU‰åS‹]jjSè§ÿÿjjSèÿÿSèÃÿÿƒÄëDjSè´þþÿjýSè¬þþÿjýSè¤þþÿjjSè&	ÿÿƒÄ$jÿSè¾þþÿZ…ÀYt¸ëjýSèéüþÿYXjSètÿÿY…ÀZu®‹]üÉÃU‰åSÙîQQ‹]jjSÝ]ôè#ÿÿSèIÿÿƒÄë7jþSè©üþÿjÿSèaþþÿƒÄƒøujÿSè	ÿÿÝEôÙÉXÝáßàÝÙZžvÝ]ôëÝØjSèÿÿZ…ÀYu»ÿuøÿuôSèÿÿ‹]ü¸ÉÃU‰åS‹]jjSè¬ÿÿƒÄjSè·ÿÿZYPSè÷ÿÿ‹]ü¸ÉÃU‰åS‹]jjSè}ÿÿh°DSèQ
ÿÿjSè”ýþÿ‹]ü¸ÉÃU‰åWVSjjÿuèNÿÿjÿuèZÿÿƒÄXÿuè¾ûþÿZƒøtƒøtë<‰ßëGjÿuè,ÿÿ^‰Ç9ßX~‰û9û‰Þ~-[ÿSjÿuèÿÿVjÿuè%ÿÿƒÄëÜhÃDÿuè¿ÿÿë
Wjÿuèÿÿ1Àeô[^_]ÃU‰åWVSjjÿuè·ÿÿjÿuèÃÿþÿP‰Çjÿuèïÿÿ‰ÆƒÄ …ÀžÀ9þŸÂ	Ð1Ò¨uJVjÿuè‰ÿÿƒÄ9þ} ^SjÿuètÿÿV‰ÞjÿuèÿÿƒÄëÜÿuè{ÿÿWjÿuèwÿÿºeô‰Ð[^_]ÃU‰åW‰×VS‹u‰ÃVjPè*ÿÿjÿSèýþÿƒÄ…Àu#VjÿSè`üþÿZYPSèvüþÿY^PhéDSèÏÿÿƒÄ‰}eô[^_]éÿÿU‰å…àýÿÿWVSì‹}PhDjWèTÿÿjjW‰…Üýÿÿè«
ÿÿjjWèðÿÿƒÄ(‰ÆjWèíûþÿZ…ÀY
jWèœþþÿëjWèÿÿY[‰Ã…äýÿÿPWè ÿÿXZ9Þ},V•äýÿÿ‰øè"ÿÿÿÿµàýÿÿ…äýÿÿFÿµÜýÿÿPè†ÿÿƒÄëÐ9ÞuV•äýÿÿ‰øèòþÿÿ[…äýÿÿPè›ÿÿeô¸[^_]ÃU‰åS‰ÃRjPè1ÿÿÿujSè&ÿÿ‹]üÉÃU‰åW‹}V‰ÆS‰ÓjPè2ûþÿZ…ÀYt?jVèõúþÿCÿPVèëúþÿGþPVèáúþÿjjVècÿÿƒÄ$jÿVè#ýþÿjþ‰ÃVè1ùþÿ‰ØëWSVèZüþÿeô[^_]ÃU‰åWV‰ÆSQQ‹E‰Uð9Â	ÿuðjVèlÿÿÿujVèaÿÿjþƒÊÿ‰ðè\ÿÿÿƒÄ…Àtÿu‰ð‹Uðè)ÿÿÿXë
jýVèÄøþÿ[_‹E+EðH„¹‹Uð¹U‰Ð™÷ù‰ÇPjV‰Eìè	ÿÿÿuðjVèþÿÿjÿºþÿÿÿ‰ðè÷þÿÿƒÄ…Àtÿuðë)jþVèjøþÿÿujVèÑÿÿjþƒÊÿ‰ðèÌþÿÿƒÄ…Àtÿu‰ú‰ðèšþÿÿYë
jýVè5øþÿXZ‹E+Eðƒø„(ÿuìjVè‹ÿÿjÿVè¢ùþÿ‹]KSjVèvÿÿ‹UìƒÄ ‰ðSèPþÿÿ‹}ðé†;}~
hDVè$	ÿÿYXjþVèÔ÷þÿXZGWjVè:ÿÿƒÄƒÊÿ‰ðjþè2þÿÿY…ÀuÆë;]ð}
hDVèèÿÿXZjþVè˜÷þÿYXKSjVèþÿþÿƒÄºýÿÿÿ‰ðjÿèôýÿÿZ…ÀuÄ9û|
S‰ú‰ðèÂýÿÿYë“jüVè]÷þÿX‹]ZKSjVèÀÿþÿWjVè·ÿþÿW‰Ú‰ðè•ýÿÿ‰ú‹EƒÄ+Uð)ø9Â}‹]ðOG‰Eðë_Cþ‹}‰EW‰Ú‰ðèëýÿÿ[‹E9Eðéñýÿÿeô[^_]ÃU‰åVS‹]jjSèI
ÿÿjSèWûþÿhD‰Æj(Sèù	ÿÿƒÄ jSè€øþÿZ…ÀY~
jjSè
ÿÿƒÄjSè¥öþÿV‰Øºè{ýÿÿeø1À[^]ÃU‰åh`DhBDÿuèÿÿɸÃU‰åWV1öSPü‹µ`DƒÉÿ‹E‰×‹X‰Uð1Àò®÷ÑIQRÿuè¤Ñÿÿ‰„³¼‹UƒÄ‹B‹„°¼F€H ƒþ~¸eô[^_]ÃU‰åS‹]ÿuSè`ñÿÿƒxZYu¶M¸ÓàC1À‹]üÉÃU‰åS‹E‹M‹]‹Pƒútƒúu‹‹Pë
‹A‹”˜…Òt‹A‹„˜¼‰U‰E[]éýðÿÿ[¸ÀD]ÃU‰åS‰ÃRÿphÀDÿ0è¥ÿÿjÿ3è
Sÿÿ‹]üÉÃU‰åS‰ÃÿuRÿpèlƒÄ…Àt
‰Ø‹]üºÜDÉë¶‹]üÉÃU‰åRUÿjèÇÿÿÿ¾EÿÉÃU‰åUøSS‰Ãjè°ÿÿÿƒ}øYyºëD‰Øèyÿÿÿ‹Eø‹]üÉÃU‰åV‰ÆSRUôjèƒÿÿÿX1À‹Uô…Òt&Rÿvÿ6è9ÿuô‰Ã‰Â‰ðè`ÿÿÿ‹EôHPSÿ6è#Ðÿÿeø[^]ÃU‰åWVSƒì‰Ó‰Eè‹·B4@f=Èf‰B4v
‹Eèº÷Dèüþÿÿ‹Eèÿ0èòaÿÿ‰Eä‹Uè‹Mä‹‹@‰Ç@	‹EèY‹‹B+Bƒø
jRè!Sÿÿ_X‹U苃@‰Ðè?ÿÿÿ‹Mä…À‰A u‰Y ‹Eèèþþÿÿ‹Uä‰B<‹Eèèðþÿÿ‹Mä‰A@‹EèèÎþÿÿ‹UäˆBH‹EèèÀþÿÿ‹MäˆAI‹Eèè²þÿÿ‹UäˆBJ‹Eèè¤þÿÿ‹MäˆAK‹Eèèªþÿÿ‰Ã@=ÿÿÿ?wP‹Eèjjÿ0èI”ÿÿƒÄë‹Uèÿ2è&”ÿÿ^‹Mä‰Â‰A‰Y,P‹EèèþÿÿY‹EèèTþÿÿ‰Ç@=ÿÿÿw‰øÁàP‹Eèjjÿ0èõ“ÿÿƒÄë‹Uèÿ2èÒ“ÿÿZ‹Mä…ÿ‰A‰y(ޏ1Ò‰þÇDƒÂNuò…ÿŽžÇEà‰þ‹Eä‹]àX‹EèèËýÿÿƒøt…Àtë_ƒøt+ƒøtBëSÇCëW‹Eèè¡ýÿÿÇC…À•À¶À‰ë‹L>ÿE¼‹E¸‰‹U¸‰L‹D>‹M˜‰DƒÆ9xÿÿÿrÌÁe¼‹E¸‹UE¼ÿCƒj‰B‰C‹B‰CéKôÿÿ‹M‹I‰MÌégôÿÿ‰ðÁèt
‹]ÁàDð‰C‹EƒxhtÿuÌPèGÿÿ^X‹MÄ‹U‰JWRèw:ÿÿÿMY[„ú…À„òóÿÿ‹]‹C‹@‰CéáóÿÿÝG ÙîÝÙÊÝáßàÝÙÝGÙÊžÞÁvÙÉÝéßàëÝáßàÝÙž‚ÛóÿÿÇG‹UÄÁîÇG8”²øÿ‰UÄÝÝ_0éµóÿÿƒO ‹UĉM´‹E_‰PtWWèTêÿÿY…ÀZuhÒDë@ƒ{tGPSè7êÿÿ‰Ã…ÛXZuh÷Dë!‹M´ƒyt"G PQèêÿÿY…À‰E´[uhDÿuèP4ÿÿXZÇG‹]´ÁîÝÜ/Ý‹EÄ„°øÿ‰EÄéóÿÿ‹G O0‹W$‹]ĉGP‹G(‰WT‹W‰GX‹G‰WD‹W‰G@‹G‰W4‹U‰GH‹‰Z‰G0‹G‰AG`‰B‰ðÁè%ÿÁîæðPQRè’=ÿÿ‹EƒÄ‹U‹@‰EÌ‹MÌ‹Bñ‹Y8‹@…Û‰Bt!‰Y(‹A0‹Q4‰A ‰Q$‹MÄ‹ÁèŒøÿ‰MăEÄéjòÿÿ‰òÁêâÿÁîu‹]‹C)øÁøpÿ‹C‹@‰C…Òu
‹UÄ‹ƒÂ‰Uĉƒ…(òÿÿkÂ2‹‰M¬D0Î;A‰E°~
PQÿuèKÙÿÿƒÄ…öŽÿñÿÿ‰ðÁà8ÿu°ÿM°ÿu¬ÿuèäØÿÿ‹ƒÄ‹K‰‹S‰H‰Pƒ{~‹ö@t‹E¬ö@tPÿuèüSÿÿ_XNƒë…ö²é¤ñÿÿWÿuèçDÿÿY[é”ñÿÿ‹UÐÁî‹B‹@‹°¶KHÿr‰M¨QÿuèqCÿÿ‰X‰Æ1ÛƒÄ;]¨}@‹EÄ‹‰Ðƒà?ƒøu‹MÐÁê‹D‘‰Džë‹EÌÁêÁâÐPÿuè·Cÿÿ‰DžXZƒEÄC뻉7‹]‹EÄÇG‹S‰C‹B@9BDrSè/RÿÿY‹U‹R‰UÌéñðÿÿ‹M‰ð‹]ÐÁè‹IH‰E¤‹S‹+A‰M ¶RIÁø)ÐHƒ}¤ÿ‰EœuK‹E‹UÄ‹]œ‰Á‰P‹@Áã+A9ØÿuœQèÊ5ÿÿXZ‹EÁîæð‹Uœ‹@‹M‰U¤‰Ç÷‰ẺA1ö;u¤kðÿÿ1Û;uœ}$‹U ‹Eœ‹
Áà)ÁÙ‹‹Q‰;‹A‰T;‰D;ëÇD;FƒÃ;u¤|Æé*ðÿÿeô[^_]ÃU‰åSP‹]EøPÿsÿsÿSƒÄ…À‰Át‹Eø…ÀuƒÈÿë‰KH‰A¶‰C‰Ð‹]üÉÃU‰åS‹]ƒ;uSè®ÿÿÿZƒÊÿ@tÿÿK‹C¶‹]ü‰ÐÉÃU‰å‹U‹EljB‹EÇB‰B‹E‰B]ÃU‰åW‹}V‹uS…öt3Wè˜ÿÿÿY@u‰ðë'‹‰ó9Æv‰ÃSÿwÿuè)ƒÄ_])ÞëË1Àeô[^_]ÃU‰å‹MV‹uS‹]‹V9Óv-ƒûw» CƒøýwSRÿ6QèvÿÿƒÄëQèåuÿÿZ‰‰^‹eø[^]ÃU¹°D‰åë¶‹Q‹ƒÁ‚@ù°Drê]ÃU‰åSœœX‰Â5 PœX1Щ „À1À¢…À„´¸¢öÆ…§‰Óã€f…Ûtƒ
@ D÷€tƒ
@ D÷Âtƒ
@ D÷Âtƒ
@ Dâtƒ
@ D öÁtƒ
@ D@öÅ t

@ D€¸€¢=€v+¸€¢¡@ D‰ÁÉâ@t
£@ Dt&[]Ã
@ DéMÿÿÿ[‰
@ D]ÃU‰åÛã]ÃU‰åƒì¡à`Aƒ8tÿ‹
à`A‹QA£à`A…ÒuéÉô&U‰åSƒì¡UAƒøÿt)…À‰Ãt‰ö¼'ÿUAKuöÇ$ðIAèjÈþÿY[]Ã1Àƒ=”UAë
@‹…”UA…Ûuôë¾¶¼'U‰åSƒì‹P D…Ûu5¡UA¹‰
P Dƒøÿt$…À‰Ãtt&ÿUAKuöÇ$ðIAèúÇþÿX[]Ã1Àƒ=”UAë
@‹…”UA…ÒuôëÃU¡  D‰å]‹Hÿá‰öUºB‰åS·Àƒìd‰T$U¨1Û‰T$‰$ÿp2Dº¹ƒì…ÀuëFÉJx€|*¨Auô	ËÉJyòƒ; 1 then i = i - 1 end
return p:sub(1, i)
else
return "."
end
end
function path.getdrive(p)
local ch1 = p:sub(1,1)
local ch2 = p:sub(2,2)
if ch2 == ":" then
return ch1
end
end
function path.getextension(p)
local i = p:findlast(".", true)
if (i) then
return p:sub(i)
else
return ""
end
end
function path.getname(p)
local i = p:findlast("[/\\]")
if (i) then
return p:sub(i + 1)
else
return p
end
end
function path.getrelative(src, dst)
src = path.getabsolute(src)
dst = path.getabsolute(dst)
if (src == dst) then
return "."
end
if dst:startswith("$") then
return dst
end
src = src .. "/"
dst = dst .. "/"
local idx = 0
while (true) do
local tst = src:find("/", idx + 1, true)
if tst then
if src:sub(1,tst) == dst:sub(1,tst) then
idx = tst
else
break
end
else
break
end
end
local first = src:find("/", 0, true)
if idx <= first then
return dst:sub(1, -2)
end
src = src:sub(idx + 1)
dst = dst:sub(idx + 1)
local result = ""
idx = src:find("/")
while (idx) do
result = result .. "../"
idx = src:find("/", idx + 1)
end
result = result .. dst
return result:sub(1, -2)
end
function path.iscfile(fname)
local extensions = { ".c", ".s", ".m" }
local ext = path.getextension(fname):lower()
return table.contains(extensions, ext)
end
function path.iscppfile(fname)
local extensions = { ".cc", ".cpp", ".cxx", ".c", ".s", ".m", ".mm" }
local ext = path.getextension(fname):lower()
return table.contains(extensions, ext)
end
function path.isresourcefile(fname)
local extensions = { ".rc" }
local ext = path.getextension(fname):lower()
return table.contains(extensions, ext)
end
function path.join(leading, trailing)
leading = leading or ""
if (not trailing) then
return leading
end
if (path.isabsolute(trailing)) then
return trailing
end
if (leading == ".") then
leading = ""
end
if (leading:len() > 0 and not leading:endswith("/")) then
leading = leading .. "/"
end
return leading .. trailing
end
function path.rebase(p, oldbase, newbase)
p = path.getabsolute(path.join(oldbase, p))
p = path.getrelative(newbase, p)
return p
end
function path.translate(p, sep)
if (type(p) == "table") then
local result = { }
for _, value in ipairs(p) do
table.insert(result, path.translate(value))
end
return result
else
if (not sep) then
if (os.is("windows")) then
sep = "\\"
else
sep = "/"
end
end
local result = p:gsub("[/\\]", sep)
return result
end
end
function path.wildcards(pattern)
pattern = pattern:gsub("([%+%.%-%^%$%(%)%%])", "%%%1")
pattern = pattern:gsub("%*%*", "\001")
pattern = pattern:gsub("%*", "\002")
pattern = pattern:gsub("\001", ".*")
pattern = pattern:gsub("\002", "[^/]*")
return pattern
end
function string.explode(s, pattern, plain)
if (pattern == '') then return false end
local pos = 0
local arr = { }
for st,sp in function() return s:find(pattern, pos, plain) end do
table.insert(arr, s:sub(pos, st-1))
pos = sp + 1
end
table.insert(arr, s:sub(pos))
return arr
end
function string.findlast(s, pattern, plain)
local curr = 0
repeat
local next = s:find(pattern, curr + 1, plain)
if (next) then curr = next end
until (not next)
if (curr > 0) then
return curr
end
end
function string.startswith(haystack, needle)
return (haystack:find(needle, 1, true) == 1)
end
function table.contains(t, value)
for _,v in pairs(t) do
if (v == value) then
return true
end
end
return false
end
function table.extract(arr, fname)
local result = { }
for _,v in ipairs(arr) do
table.insert(result, v[fname])
end
return result
end
function table.flatten(arr)
local result = { }
local function flatten(arr)
for _, v in ipairs(arr) do
if type(v) == "table" then
flatten(v)
else
table.insert(result, v)
end
end
end
flatten(arr)
return result
end
function table.implode(arr, before, after, between)
local result = ""
for _,v in ipairs(arr) do
if (result ~= "" and between) then
result = result .. between
end
result = result .. before .. v .. after
end
return result
end
function table.isempty(t)
return not next(t)
end
function table.join(...)
local result = { }
for _,t in ipairs(arg) do
if type(t) == "table" then
for _,v in ipairs(t) do
table.insert(result, v)
end
else
table.insert(result, t)
end
end
return result
end
function table.keys(tbl)
local keys = {}
for k, _ in pairs(tbl) do
table.insert(keys, k)
end
return keys
end
function table.translate(arr, translation)
local result = { }
for _, value in ipairs(arr) do
local tvalue
if type(translation) == "function" then
tvalue = translation(value)
else
tvalue = translation[value]
end
if (tvalue) then
table.insert(result, tvalue)
end
end
return result
end
function io.capture()
io.captured = ''
end
function io.endcapture()
local captured = io.captured
io.captured = nil
return captured
end
local builtin_open = io.open
function io.open(fname, mode)
if (mode) then
if (mode:find("w")) then
local dir = path.getdirectory(fname)
ok, err = os.mkdir(dir)
if (not ok) then
error(err, 0)
end
end
end
return builtin_open(fname, mode)
end
function io.printf(msg, ...)
if (not io.eol) then
io.eol = "\n"
end
local s
if type(msg) == "number" then
s = string.rep("\t", msg) .. string.format(unpack(arg))
else
s = string.format(msg, unpack(arg))
end
if io.captured then
io.captured = io.captured .. s .. io.eol
else
io.write(s)
io.write(io.eol)
end
end
_p = io.printf
premake = { }
premake.platforms = 
{
Native = 
{ 
cfgsuffix       = "",
},
x32 = 
{ 
cfgsuffix       = "32",
},
x64 = 
{ 
cfgsuffix       = "64",
},
Universal = 
{ 
cfgsuffix       = "univ",
},
Universal32 = 
{ 
cfgsuffix       = "univ32",
},
Universal64 = 
{ 
cfgsuffix       = "univ64",
},
PS3 = 
{ 
cfgsuffix       = "ps3",
iscrosscompiler = true,
nosharedlibs    = true,
namestyle       = "PS3",
},
Xbox360 = 
{ 
cfgsuffix       = "xbox360",
iscrosscompiler = true,
namestyle       = "windows",
},
}
local builtin_dofile = dofile
function dofile(fname)
local oldcwd = os.getcwd()
local oldfile = _SCRIPT
if (not os.isfile(fname)) then
local path = os.pathsearch(fname, _OPTIONS["scripts"], os.getenv("PREMAKE_PATH"))
if (path) then
fname = path.."/"..fname
end
end
_SCRIPT = path.getabsolute(fname)
local newcwd = path.getdirectory(_SCRIPT)
os.chdir(newcwd)
local a, b, c, d, e, f = builtin_dofile(_SCRIPT)
_SCRIPT = oldfile
os.chdir(oldcwd)
return a, b, c, d, e, f
end
function iif(expr, trueval, falseval)
if (expr) then
return trueval
else
return falseval
end
end
function include(fname)
return dofile(fname .. "/premake4.lua")
end
function printf(msg, ...)
print(string.format(msg, unpack(arg)))
end
local builtin_type = type
function type(t)
local mt = getmetatable(t)
if (mt) then
if (mt.__type) then
return mt.__type
end
end
return builtin_type(t)
end
premake.action = { }
premake.action.list = { }
function premake.action.add(a)
local missing
for _, field in ipairs({"description", "trigger"}) do
if (not a[field]) then
missing = field
end
end
if (missing) then
error("action needs a " .. missing, 3)
end
premake.action.list[a.trigger] = a
end
function premake.action.call(name)
local a = premake.action.list[name]
for sln in premake.solution.each() do
if a.onsolution then
a.onsolution(sln)
end
for prj in premake.solution.eachproject(sln) do
if a.onproject then
a.onproject(prj)
end
end
end
if a.execute then
a.execute()
end
end
function premake.action.current()
return premake.action.get(_ACTION)
end
function premake.action.get(name)
return premake.action.list[name]
end
function premake.action.each()
local keys = { }
for _, action in pairs(premake.action.list) do
table.insert(keys, action.trigger)
end
table.sort(keys)
local i = 0
return function()
i = i + 1
return premake.action.list[keys[i]]
end
end
function premake.action.set(name)
_ACTION = name
local action = premake.action.get(name)
if action then
_OS = action.os or _OS
end
end
function premake.action.supports(action, feature)
if not action then
return false
end
if action.valid_languages then
if table.contains(action.valid_languages, feature) then
return true
end
end
if action.valid_kinds then
if table.contains(action.valid_kinds, feature) then
return true
end
end
return false
end
premake.option = { }
premake.option.list = { }
function premake.option.add(opt)
local missing
for _, field in ipairs({ "description", "trigger" }) do
if (not opt[field]) then
missing = field
end
end
if (missing) then
error("option needs a " .. missing, 3)
end
premake.option.list[opt.trigger] = opt
end
function premake.option.get(name)
return premake.option.list[name]
end
function premake.option.each()
local keys = { }
for _, option in pairs(premake.option.list) do
table.insert(keys, option.trigger)
end
table.sort(keys)
local i = 0
return function()
i = i + 1
return premake.option.list[keys[i]]
end
end
function premake.option.validate(values)
for key, value in pairs(values) do
local opt = premake.option.get(key)
if (not opt) then
return false, "invalid option '" .. key .. "'"
end
if (opt.value and value == "") then
return false, "no value specified for option '" .. key .. "'"
end
if (opt.allowed) then
for _, match in ipairs(opt.allowed) do
if (match[1] == value) then return true end
end
return false, "invalid value '" .. value .. "' for option '" .. key .. "'"
end
end
return true
end
premake.tree = { }
local tree = premake.tree
function premake.tree.new(n)
local t = {
name = n,
children = { }
}
return t
end
function premake.tree.add(tr, p)
if p == "." then
return tr
end
local parentnode = tree.add(tr, path.getdirectory(p))
local childname = path.getname(p)
if childname == ".." then
return parentnode
end
local childnode = parentnode.children[childname]
if not childnode or childnode.path ~= p then
childnode = tree.insert(parentnode, tree.new(childname))
childnode.path = p
end
return childnode
end
function premake.tree.insert(parent, child)
table.insert(parent.children, child)
if child.name then
parent.children[child.name] = child
end
child.parent = parent
return child
end
function premake.tree.getlocalpath(node)
if node.parent.path then
return node.name
else
return node.path
end
end
function premake.tree.remove(node)
local children = node.parent.children
for i = 1, #children do
if children[i] == node then
table.remove(children, i)
end
end
node.children = {}
end
function premake.tree.sort(tr)
tree.traverse(tr, {
onnode = function(node)
table.sort(node.children, function(a,b)
return a.name < b.name
end)
end
}, true)
end
function premake.tree.traverse(t, fn, includeroot)
local donode, dochildren
donode = function(node, fn, depth)
if node.isremoved then 
return 
end
if fn.onnode then 
fn.onnode(node, depth) 
end
if #node.children > 0 then
if fn.onbranch then 
fn.onbranch(node, depth) 
end
dochildren(node, fn, depth + 1)
else
if fn.onleaf then 
fn.onleaf(node, depth) 
end
end
end
dochildren = function(parent, fn, depth)
local i = 1
while i <= #parent.children do
local node = parent.children[i]
donode(node, fn, depth)
if node == parent.children[i] then
i = i + 1
end
end
end
if includeroot then
donode(t, fn, 0)
else
dochildren(t, fn, 0)
end
end
premake.solution = { }
premake.solution.list = { }
function premake.solution.new(name)
local sln = { }
table.insert(premake.solution.list, sln)
premake.solution.list[name] = sln
setmetatable(sln, { __type="solution" })
sln.name           = name
sln.basedir        = os.getcwd()
sln.projects       = { }
sln.blocks         = { }
sln.configurations = { }
return sln
end
function premake.solution.each()
local i = 0
return function ()
i = i + 1
if i <= #premake.solution.list then
return premake.solution.list[i]
end
end
end
function premake.solution.eachproject(sln)
local i = 0
return function ()
i = i + 1
if (i <= #sln.projects) then
return premake.solution.getproject(sln, i)
end
end
end
function premake.solution.get(key)
return premake.solution.list[key]
end
function premake.solution.getproject(sln, idx)
local prj = sln.projects[idx]
local cfg = premake.getconfig(prj)
cfg.name = prj.name
return cfg
end
premake.project = { }
function premake.project.buildsourcetree(prj)
local tr = premake.tree.new(prj.name)
for _, fname in ipairs(prj.files) do
local node = premake.tree.add(tr, fname)
end
premake.tree.sort(tr)
tr.project = prj
return tr
end
function premake.eachconfig(prj, platform)
if prj.project then prj = prj.project end
local cfgs = prj.solution.configurations
local i = 0
return function ()
i = i + 1
if i <= #cfgs then
return premake.getconfig(prj, cfgs[i], platform)
end
end
end
function premake.eachfile(prj)
if not prj.project then prj = premake.getconfig(prj) end
local i = 0
local t = prj.files
return function ()
i = i + 1
if (i <= #t) then
return prj.__fileconfigs[t[i]]
end
end
end
function premake.esc(value)
if (type(value) == "table") then
local result = { }
for _,v in ipairs(value) do
table.insert(result, premake.esc(v))
end
return result
else
value = value:gsub('&',  "&")
value = value:gsub('"',  """)
value = value:gsub("'",  "'")
value = value:gsub('<',  "<")
value = value:gsub('>',  ">")
value = value:gsub('\r', "
")
value = value:gsub('\n', "
")
return value
end
end
function premake.filterplatforms(sln, map, default)
local result = { }
local keys = { }
if sln.platforms then
for _, p in ipairs(sln.platforms) do
if map[p] and not table.contains(keys, map[p]) then
table.insert(result, p)
table.insert(keys, map[p])
end
end
end
if #result == 0 and default then
table.insert(result, default)
end
return result
end
function premake.findproject(name)
for sln in premake.solution.each() do
for prj in premake.solution.eachproject(sln) do
if (prj.name == name) then
return  prj
end
end
end
end
function premake.findfile(prj, extension)
for _, fname in ipairs(prj.files) do
if fname:endswith(extension) then return fname end
end
end
function premake.getconfig(prj, cfgname, pltname)
prj = prj.project or prj
if pltname == "Native" or not table.contains(prj.solution.platforms or {}, pltname) then
pltname = nil
end
local key = (cfgname or "")
if pltname then key = key .. pltname end
return prj.__configs[key]
end
function premake.getconfigname(cfgname, platform, useshortname)
if cfgname then
local name = cfgname
if platform and platform ~= "Native" then
if useshortname then
name = name .. premake.platforms[platform].cfgsuffix
else
name = name .. "|" .. platform
end
end
return iif(useshortname, name:lower(), name)
end
end
function premake.getdependencies(prj)
prj = prj.project or prj
local results = { }
for _, cfg in pairs(prj.__configs) do
for _, link in ipairs(cfg.links) do
local dep = premake.findproject(link)
if dep and not table.contains(results, dep) then
table.insert(results, dep)
end
end
end
return results
end
function premake.project.getfilename(prj, pattern)
local fname = pattern:gsub("%%%%", prj.name)
fname = path.join(prj.location, fname)
return path.getrelative(os.getcwd(), fname)
end
 function premake.getlinks(cfg, kind, part)
local result = iif (part == "directory" and kind == "all", cfg.libdirs, {})
local cfgname = iif(cfg.name == cfg.project.name, "", cfg.name)
local pathstyle = premake.getpathstyle(cfg)
local namestyle = premake.getnamestyle(cfg)
local function canlink(source, target)
if (target.kind ~= "SharedLib" and target.kind ~= "StaticLib") then 
return false
end
if premake.iscppproject(source) then
return premake.iscppproject(target)
elseif premake.isdotnetproject(source) then
return premake.isdotnetproject(target)
end
end
for _, link in ipairs(cfg.links) do
local item
local prj = premake.findproject(link)
if prj and kind ~= "system" then
local prjcfg = premake.getconfig(prj, cfgname, cfg.platform)
if kind == "dependencies" or canlink(cfg, prjcfg) then
if (part == "directory") then
item = path.rebase(prjcfg.linktarget.directory, prjcfg.location, cfg.location)
elseif (part == "basename") then
item = prjcfg.linktarget.basename
elseif (part == "fullpath") then
item = path.rebase(prjcfg.linktarget.fullpath, prjcfg.location, cfg.location)
elseif (part == "object") then
item = prjcfg
end
end
elseif not prj and (kind == "system" or kind == "all") then
if (part == "directory") then
local dir = path.getdirectory(link)
if (dir ~= ".") then
item = dir
end
elseif (part == "fullpath") then
item = link
if namestyle == "windows" then
if premake.iscppproject(cfg) then
item = item .. ".lib"
elseif premake.isdotnetproject(cfg) then
item = item .. ".dll"
end
end
if item:find("/", nil, true) then
item = path.getrelative(cfg.basedir, item)
end
else
item = link
end
end
if item then
if pathstyle == "windows" and part ~= "object" then
item = path.translate(item, "\\")
end
if not table.contains(result, item) then
table.insert(result, item)
end
end
end
return result
end
function premake.getnamestyle(cfg)
return premake.platforms[cfg.platform].namestyle or premake.gettool(cfg).namestyle or "posix"
end
function premake.getpathstyle(cfg)
if premake.action.current().os == "windows" then
return "windows"
else
return "posix"
end
end
function premake.gettarget(cfg, direction, pathstyle, namestyle, system)
if system == "bsd" or system == "solaris" then 
system = "linux" 
end
local kind = cfg.kind
if premake.iscppproject(cfg) then
if (namestyle == "windows" or system == "windows") and kind == "SharedLib" and direction == "link" then
kind = "StaticLib"
end
if namestyle == "posix" and system == "windows" and kind ~= "StaticLib" then
namestyle = "windows"
end
end
local field   = iif(direction == "build", "target", "implib")
local name    = cfg[field.."name"] or cfg.targetname or cfg.project.name
local dir     = cfg[field.."dir"] or cfg.targetdir or path.getrelative(cfg.location, cfg.basedir)
local prefix  = ""
local suffix  = ""
local ext     = ""
local bundlepath, bundlename
if namestyle == "windows" then
if kind == "ConsoleApp" or kind == "WindowedApp" then
ext = ".exe"
elseif kind == "SharedLib" then
ext = ".dll"
elseif kind == "StaticLib" then
ext = ".lib"
end
elseif namestyle == "posix" then
if kind == "WindowedApp" and system == "macosx" then
bundlename = name .. ".app"
bundlepath = path.join(dir, bundlename)
dir = path.join(bundlepath, "Contents/MacOS")
elseif kind == "SharedLib" then
prefix = "lib"
ext = iif(system == "macosx", ".dylib", ".so")
elseif kind == "StaticLib" then
prefix = "lib"
ext = ".a"
end
elseif namestyle == "PS3" then
if kind == "ConsoleApp" or kind == "WindowedApp" then
ext = ".elf"
elseif kind == "StaticLib" then
prefix = "lib"
ext = ".a"
end
end
prefix = cfg[field.."prefix"] or cfg.targetprefix or prefix
suffix = cfg[field.."suffix"] or cfg.targetsuffix or suffix
ext    = cfg[field.."extension"] or cfg.targetextension or ext
local result = { }
result.basename   = name .. suffix
result.name       = prefix .. name .. suffix .. ext
result.directory  = dir
result.prefix     = prefix
result.suffix     = suffix
result.fullpath   = path.join(result.directory, result.name)
result.bundlepath = bundlepath or result.fullpath
if pathstyle == "windows" then
result.directory = path.translate(result.directory, "\\")
result.fullpath  = path.translate(result.fullpath,  "\\")
end
return result
end
function premake.gettool(cfg)
if premake.iscppproject(cfg) then
if _OPTIONS.cc then
return premake[_OPTIONS.cc]
end
local action = premake.action.current()
if action.valid_tools then
return premake[action.valid_tools.cc[1]]
end
return premake.gcc
else
return premake.dotnet
end
end
function premake.hascppproject(sln)
for prj in premake.solution.eachproject(sln) do
if premake.iscppproject(prj) then
return true
end
end
end
function premake.hasdotnetproject(sln)
for prj in premake.solution.eachproject(sln) do
if premake.isdotnetproject(prj) then
return true
end
end
end
function premake.iscppproject(prj)
return (prj.language == "C" or prj.language == "C++")
end
function premake.isdotnetproject(prj)
return (prj.language == "C#")
end
local function walksources(cfg, fn, group, nestlevel, finished)
local grouplen = group:len()
local gname = iif(group:endswith("/"), group:sub(1, -2), group)
if (nestlevel >= 0) then
fn(cfg, gname, "GroupStart", nestlevel)
end
for _,fname in ipairs(cfg.files) do
if (fname:startswith(group)) then
local _,split = fname:find("[^\.]/", grouplen + 1)
if (split) then
local subgroup = fname:sub(1, split)
if (not finished[subgroup]) then
finished[subgroup] = true
walksources(cfg, fn, subgroup, nestlevel + 1, finished)
end
end
end
end
for _,fname in ipairs(cfg.files) do
if (fname:startswith(group) and not fname:find("[^\.]/", grouplen + 1)) then
fn(cfg, fname, "GroupItem", nestlevel + 1)
end
end
if (nestlevel >= 0) then
fn(cfg, gname, "GroupEnd", nestlevel)
end
end
function premake.walksources(cfg, fn)
walksources(cfg, fn, "", -1, {})
end
premake.config = { }
function premake.config.isdebugbuild(cfg)
if cfg.flags.Optimize or cfg.flags.OptimizeSize or cfg.flags.OptimizeSpeed then
return false
end
if not cfg.flags.Symbols then
return false
end
return true
end
local nocopy = 
{
blocks    = true,
keywords  = true,
projects  = true,
__configs = true,
}
local nofixup =
{
basedir  = true,
location = true,
}
function premake.getactiveterms()
local terms = { _ACTION:lower(), os.get() }
for key, value in pairs(_OPTIONS) do
if value ~= "" then
table.insert(terms, value:lower())
else
table.insert(terms, key:lower())
end
end
return terms
end
function premake.iskeywordmatch(keyword, terms)
if keyword:startswith("not ") then
return not premake.iskeywordmatch(keyword:sub(5), terms)
end
for _, pattern in ipairs(keyword:explode(" or ")) do
for termkey, term in pairs(terms) do
if term:match(pattern) == term then
return termkey
end
end
end
end
function premake.iskeywordsmatch(keywords, terms)
local hasrequired = false
for _, keyword in ipairs(keywords) do
local matched = premake.iskeywordmatch(keyword, terms)
if not matched then
return false
end
if matched == "required" then
hasrequired = true
end
end
if terms.required and not hasrequired then
return false
else
return true
end
end
local function adjustpaths(location, obj)
for name, value in pairs(obj) do
local field = premake.fields[name]
if field and value and not nofixup[name] then
if field.kind == "path" then
obj[name] = path.getrelative(location, value) 
elseif field.kind == "dirlist" or field.kind == "filelist" then
for i, p in ipairs(value) do
value[i] = path.getrelative(location, p) 
end
end
end
end
end
local function mergeobject(dest, src)
if not src then return end
for field, value in pairs(src) do
if not nocopy[field] then
if type(value) == "table" then
local tbl = dest[field] or { }
for _, item in ipairs(value) do
if not tbl[item] then
table.insert(tbl, item)
tbl[item] = item
end
end
dest[field] = tbl
else
dest[field] = value
end
end
end
end
local function merge(dest, obj, basis, terms, cfgname, pltname)
local key = cfgname or ""
pltname = pltname or "Native"
if pltname ~= "Native" then
key = key .. pltname
end
terms.config = (cfgname or ""):lower()
terms.platform = pltname:lower()
local cfg = {}
mergeobject(cfg, basis[key])
adjustpaths(obj.location, cfg)
mergeobject(cfg, obj)
for _, blk in ipairs(obj.blocks) do
if (premake.iskeywordsmatch(blk.keywords, terms)) then
mergeobject(cfg, blk)
end
end
cfg.name      = cfgname
cfg.platform  = pltname
cfg.terms     = terms
dest[key] = cfg
end
local function collapse(obj, basis)
local result = {}
basis = basis or {}
local sln = obj.solution or obj
local terms = premake.getactiveterms()
merge(result, obj, basis, terms)
if result[""].kind then
terms.kind = result[""].kind:lower()
end
for _, cfgname in ipairs(sln.configurations) do
merge(result, obj, basis, terms, cfgname, "Native")
for _, pltname in ipairs(sln.platforms or {}) do
if pltname ~= "Native" then
merge(result, obj, basis, terms, cfgname, pltname)
end
end
end
return result
end
local function postprocess(prj, cfg)
cfg.project   = prj
cfg.shortname = premake.getconfigname(cfg.name, cfg.platform, true)
cfg.longname  = premake.getconfigname(cfg.name, cfg.platform)
cfg.location = cfg.location or cfg.basedir
local platform = premake.platforms[cfg.platform]
if platform.iscrosscompiler then
cfg.system = cfg.platform
else
cfg.system = os.get()
end
if cfg.kind == "SharedLib" and platform.nosharedlibs then
cfg.kind = "StaticLib"
end
local files = { }
for _, fname in ipairs(cfg.files) do
local excluded = false
for _, exclude in ipairs(cfg.excludes) do
excluded = (fname == exclude)
if (excluded) then break end
end
if (not excluded) then
table.insert(files, fname)
end
end
cfg.files = files
for name, field in pairs(premake.fields) do
if field.isflags then
local values = cfg[name]
for _, flag in ipairs(values) do values[flag] = true end
end
end
cfg.__fileconfigs = { }
for _, fname in ipairs(cfg.files) do
cfg.terms.required = fname:lower()
local fcfg = {}
for _, blk in ipairs(cfg.project.blocks) do
if (premake.iskeywordsmatch(blk.keywords, cfg.terms)) then
mergeobject(fcfg, blk)
end
end
fcfg.name = fname
cfg.__fileconfigs[fname] = fcfg
table.insert(cfg.__fileconfigs, fcfg)
end
end
local function builduniquedirs()
local num_variations = 4
local cfg_dirs = {}
local hit_counts = {}
for sln in premake.solution.each() do
for _, prj in ipairs(sln.projects) do
for _, cfg in pairs(prj.__configs) do
local dirs = { }
dirs[1] = path.getabsolute(path.join(cfg.location, cfg.objdir or cfg.project.objdir or "obj"))
dirs[2] = path.join(dirs[1], iif(cfg.platform == "Native", "", cfg.platform))
dirs[3] = path.join(dirs[2], cfg.name)
dirs[4] = path.join(dirs[3], cfg.project.name)
cfg_dirs[cfg] = dirs
local start = iif(cfg.name, 2, 1)
for v = start, num_variations do
local d = dirs[v]
hit_counts[d] = (hit_counts[d] or 0) + 1
end
end
end
end
for sln in premake.solution.each() do
for _, prj in ipairs(sln.projects) do
for _, cfg in pairs(prj.__configs) do
local dir
local start = iif(cfg.name, 2, 1)
for v = start, num_variations do
dir = cfg_dirs[cfg][v]
if hit_counts[dir] == 1 then break end
end
cfg.objectsdir = path.getrelative(cfg.location, dir)
end
end
end
end
local function buildtargets()
for sln in premake.solution.each() do
for _, prj in ipairs(sln.projects) do
for _, cfg in pairs(prj.__configs) do
local pathstyle = premake.getpathstyle(cfg)
local namestyle = premake.getnamestyle(cfg)
cfg.buildtarget = premake.gettarget(cfg, "build", pathstyle, namestyle, cfg.system)
cfg.linktarget  = premake.gettarget(cfg, "link",  pathstyle, namestyle, cfg.system)
if pathstyle == "windows" then
cfg.objectsdir = path.translate(cfg.objectsdir, "\\")
end
end
end
end
end
function premake.buildconfigs()
for sln in premake.solution.each() do
for _, prj in ipairs(sln.projects) do
prj.location = prj.location or sln.location or prj.basedir
adjustpaths(prj.location, prj)
for _, blk in ipairs(prj.blocks) do
adjustpaths(prj.location, blk)
end
end
sln.location = sln.location or sln.basedir
end
for sln in premake.solution.each() do
local basis = collapse(sln)
for _, prj in ipairs(sln.projects) do
prj.__configs = collapse(prj, basis)
for _, cfg in pairs(prj.__configs) do
postprocess(prj, cfg)
end
end
end
builduniquedirs()
buildtargets(cfg)
end
premake.fields = 
{
basedir =
{
kind  = "path",
scope = "container",
},
buildaction =
{
kind  = "string",
scope = "config",
allowed = {
"Compile",
"Copy",
"Embed",
"None"
}
},
buildoptions =
{
kind  = "list",
scope = "config",
},
configurations = 
{
kind  = "list",
scope = "solution",
},
defines =
{
kind  = "list",
scope = "config",
},
deploymentoptions =
{
kind  = "list",
scope = "config",
},
excludes =
{
kind  = "filelist",
scope = "config",
},
files =
{
kind  = "filelist",
scope = "config",
},
flags =
{
kind  = "list",
scope = "config",
isflags = true,
allowed = {
"EnableSSE",
"EnableSSE2",
"ExtraWarnings",
"FatalWarnings",
"FloatFast",
"FloatStrict",
"Managed",
"MFC",
"NativeWChar",
"No64BitChecks",
"NoEditAndContinue",
"NoExceptions",
"NoFramePointer",
"NoImportLib",
"NoManifest",
"NoMinimalRebuild",
"NoNativeWChar",
"NoPCH",
"NoRTTI",
"Optimize",
"OptimizeSize",
"OptimizeSpeed",
"SEH",
"StaticRuntime",
"Symbols",
"Unicode",
"Unsafe",
"WinMain"
}
},
framework =
{
kind = "string",
scope = "container",
allowed = {
"1.0",
"1.1",
"2.0",
"3.0",
"3.5",
"4.0"
}
},
imagepath = 
{
kind = "path",
scope = "config",
},
imageoptions =
{
kind  = "list",
scope = "config",
},
implibdir =
{
kind  = "path",
scope = "config",
},
implibextension =
{
kind  = "string",
scope = "config",
},
implibname =
{
kind  = "string",
scope = "config",
},
implibprefix =
{
kind  = "string",
scope = "config",
},
implibsuffix =
{
kind  = "string",
scope = "config",
},
includedirs =
{
kind  = "dirlist",
scope = "config",
},
kind =
{
kind  = "string",
scope = "config",
allowed = {
"ConsoleApp",
"WindowedApp",
"StaticLib",
"SharedLib"
}
},
language =
{
kind  = "string",
scope = "container",
allowed = {
"C",
"C++",
"C#"
}
},
libdirs =
{
kind  = "dirlist",
scope = "config",
},
linkoptions =
{
kind  = "list",
scope = "config",
},
links =
{
kind  = "list",
scope = "config",
allowed = function(value)
if value:find('/', nil, true) then
value = path.getabsolute(value)
end
return value
end
},
location =
{
kind  = "path",
scope = "container",
},
objdir =
{
kind  = "path",
scope = "config",
},
pchheader =
{
kind  = "string",
scope = "config",
},
pchsource =
{
kind  = "path",
scope = "config",
},
platforms = 
{
kind  = "list",
scope = "solution",
allowed = table.keys(premake.platforms),
},
postbuildcommands =
{
kind  = "list",
scope = "config",
},
prebuildcommands =
{
kind  = "list",
scope = "config",
},
prelinkcommands =
{
kind  = "list",
scope = "config",
},
resdefines =
{
kind  = "list",
scope = "config",
},
resincludedirs =
{
kind  = "dirlist",
scope = "config",
},
resoptions =
{
kind  = "list",
scope = "config",
},
targetdir =
{
kind  = "path",
scope = "config",
},
targetextension =
{
kind  = "string",
scope = "config",
},
targetname =
{
kind  = "string",
scope = "config",
},
targetprefix =
{
kind  = "string",
scope = "config",
},
targetsuffix =
{
kind  = "string",
scope = "config",
},
trimpaths =
{
kind = "dirlist",
scope = "config",
},
uuid =
{
kind  = "string",
scope = "container",
allowed = function(value)
local ok = true
if (#value ~= 36) then ok = false end
for i=1,36 do
local ch = value:sub(i,i)
if (not ch:find("[ABCDEFabcdef0123456789-]")) then ok = false end
end
if (value:sub(9,9) ~= "-")   then ok = false end
if (value:sub(14,14) ~= "-") then ok = false end
if (value:sub(19,19) ~= "-") then ok = false end
if (value:sub(24,24) ~= "-") then ok = false end
if (not ok) then
return nil, "invalid UUID"
end
return value:upper()
end
},
}
function premake.checkvalue(value, allowed)
if (allowed) then
if (type(allowed) == "function") then
return allowed(value)
else
for _,v in ipairs(allowed) do
if (value:lower() == v:lower()) then
return v
end
end
return nil, "invalid value '" .. value .. "'"
end
else
return value
end
end
function premake.getobject(t)
local container
if (t == "container" or t == "solution") then
container = premake.CurrentContainer
else
container = premake.CurrentConfiguration
end
if t == "solution" then
if type(container) == "project" then
container = container.solution
end
if type(container) ~= "solution" then
container = nil
end
end
local msg
if (not container) then
if (t == "container") then
msg = "no active solution or project"
elseif (t == "solution") then
msg = "no active solution"
else
msg = "no active solution, project, or configuration"
end
end
return container, msg
end
function premake.setarray(ctype, fieldname, value, allowed)
local container, err = premake.getobject(ctype)
if (not container) then
error(err, 4)
end
if (not container[fieldname]) then
container[fieldname] = { }
end
local function doinsert(value, depth)
if (type(value) == "table") then
for _,v in ipairs(value) do
doinsert(v, depth + 1)
end
else
value, err = premake.checkvalue(value, allowed)
if (not value) then
error(err, depth)
end
table.insert(container[fieldname], value)
end
end
if (value) then
doinsert(value, 5)
end
return container[fieldname]
end
local function domatchedarray(ctype, fieldname, value, matchfunc)
local result = { }
function makeabsolute(value, depth)
if (type(value) == "table") then
for _, item in ipairs(value) do
makeabsolute(item, depth + 1)
end
elseif type(value) == "string" then
if value:find("*") then
makeabsolute(matchfunc(value), depth + 1)
else
table.insert(result, path.getabsolute(value))
end
else
error("Invalid value in list: expected string, got " .. type(value), depth)
end
end
makeabsolute(value, 3)
return premake.setarray(ctype, fieldname, result)
end
function premake.setdirarray(ctype, fieldname, value)
return domatchedarray(ctype, fieldname, value, os.matchdirs)
end
function premake.setfilearray(ctype, fieldname, value)
return domatchedarray(ctype, fieldname, value, os.matchfiles)
end
function premake.setstring(ctype, fieldname, value, allowed)
local container, err = premake.getobject(ctype)
if (not container) then
error(err, 4)
end
if (value) then
value, err = premake.checkvalue(value, allowed)
if (not value) then 
error(err, 4)
end
container[fieldname] = value
end
return container[fieldname]
end
local function accessor(name, value)
local kind    = premake.fields[name].kind
local scope   = premake.fields[name].scope
local allowed = premake.fields[name].allowed
if ((kind == "string" or kind == "path") and value) then
if type(value) ~= "string" then
error("string value expected", 3)
end
end
if (kind == "string") then
return premake.setstring(scope, name, value, allowed)
elseif (kind == "path") then
if value then value = path.getabsolute(value) end
return premake.setstring(scope, name, value)
elseif (kind == "list") then
return premake.setarray(scope, name, value, allowed)
elseif (kind == "dirlist") then
return premake.setdirarray(scope, name, value)
elseif (kind == "filelist") then
return premake.setfilearray(scope, name, value)
end
end
for name,_ in pairs(premake.fields) do
_G[name] = function(value)
return accessor(name, value)
end
end
function configuration(terms)
if not terms then
return premake.CurrentConfiguration
end
local container, err = premake.getobject("container")
if (not container) then
error(err, 2)
end
local cfg = { }
cfg.terms = table.flatten({terms})
table.insert(container.blocks, cfg)
premake.CurrentConfiguration = cfg
cfg.keywords = { }
for _, word in ipairs(cfg.terms) do
table.insert(cfg.keywords, path.wildcards(word):lower())
end
for name, field in pairs(premake.fields) do
if (field.kind ~= "string" and field.kind ~= "path") then
cfg[name] = { }
end
end
return cfg
end
function project(name)
if not name then
return iif(type(premake.CurrentContainer) == "project", premake.CurrentContainer, nil)
end
local sln
if (type(premake.CurrentContainer) == "project") then
sln = premake.CurrentContainer.solution
else
sln = premake.CurrentContainer
end
if (type(sln) ~= "solution") then
error("no active solution", 2)
end
premake.CurrentContainer = sln.projects[name]
if (not premake.CurrentContainer) then
local prj = { }
premake.CurrentContainer = prj
table.insert(sln.projects, prj)
sln.projects[name] = prj
setmetatable(prj, {
__type = "project",
})
prj.solution       = sln
prj.name           = name
prj.basedir        = os.getcwd()
prj.uuid           = os.uuid()
prj.blocks         = { }
end
configuration { }
return premake.CurrentContainer
end
function solution(name)
if not name then
if type(premake.CurrentContainer) == "project" then
return premake.CurrentContainer.solution
else
return premake.CurrentContainer
end
end
premake.CurrentContainer = premake.solution.get(name)
if (not premake.CurrentContainer) then
premake.CurrentContainer = premake.solution.new(name)
end
configuration { }
return premake.CurrentContainer
end
function newaction(a)
premake.action.add(a)
end
function newoption(opt)
premake.option.add(opt)
end
newoption 
{
trigger     = "cc",
value       = "VALUE",
description = "Choose a C/C++ compiler set",
allowed = {
{ "gcc", "GNU GCC (gcc/g++)" },
{ "ow",  "OpenWatcom"        },
}
}
newoption
{
trigger     = "dotnet",
value       = "VALUE",
description = "Choose a .NET compiler set",
allowed = {
{ "msnet",   "Microsoft .NET (csc)" },
{ "mono",    "Novell Mono (mcs)"    },
{ "pnet",    "Portable.NET (cscc)"  },
}
}
newoption
{
trigger     = "file",
value       = "FILE",
description = "Read FILE as a Premake script; default is 'premake4.lua'"
}
newoption
{
trigger     = "help",
description = "Display this information"
}
newoption
{
trigger     = "os",
value       = "VALUE",
description = "Generate files for a different operating system",
allowed = {
{ "bsd",      "OpenBSD, NetBSD, or FreeBSD" },
{ "linux",    "Linux" },
{ "macosx",   "Apple Mac OS X" },
{ "solaris",  "Solaris" },
{ "windows",  "Microsoft Windows" },
}
}
newoption
{
trigger     = "platform",
value       = "VALUE",
description = "Add target architecture (if supported by action)",
allowed = {
{ "x32",         "32-bit" },
{ "x64",         "64-bit" },
{ "universal",   "Mac OS X Universal, 32- and 64-bit" },
{ "universal32", "Mac OS X Universal, 32-bit only" },
{ "universal64", "Mac OS X Universal, 64-bit only" },
{ "ps3",         "Playstation 3 (experimental)" },
{ "xbox360",     "Xbox 360 (experimental)" },
}
}
newoption
{
trigger     = "scripts",
value       = "path",
description = "Search for additional scripts on the given path"
}
newoption
{
trigger     = "version",
description = "Display version information"
}
premake.dotnet = { }
premake.dotnet.namestyle = "windows"
local flags =
{
FatalWarning   = "/warnaserror",
Optimize       = "/optimize",
OptimizeSize   = "/optimize",
OptimizeSpeed  = "/optimize",
Symbols        = "/debug",
Unsafe         = "/unsafe"
}
function premake.dotnet.getbuildaction(fcfg)
local ext = path.getextension(fcfg.name):lower()
if fcfg.buildaction == "Compile" or ext == ".cs" then
return "Compile"
elseif fcfg.buildaction == "Embed" or ext == ".resx" then
return "EmbeddedResource"
elseif fcfg.buildaction == "Copy" or ext == ".asax" or ext == ".aspx" then
return "Content"
else
return "None"
end
end
function premake.dotnet.getcompilervar(cfg)
if (_OPTIONS.dotnet == "msnet") then
return "csc"
elseif (_OPTIONS.dotnet == "mono") then
if (cfg.framework <= "1.1") then
return "mcs"
elseif (cfg.framework >= "4.0") then
return "dmcs"
else 
return "gmcs"
end
else
return "cscc"
end
end
function premake.dotnet.getflags(cfg)
local result = table.translate(cfg.flags, flags)
return result
end
function premake.dotnet.getkind(cfg)
if (cfg.kind == "ConsoleApp") then
return "Exe"
elseif (cfg.kind == "WindowedApp") then
return "WinExe"
elseif (cfg.kind == "SharedLib") then
return "Library"
end
endpremake.gcc = { }
premake.gcc.cc     = "gcc"
premake.gcc.cxx    = "g++"
premake.gcc.ar     = "ar"
local cflags =
{
EnableSSE      = "-msse",
EnableSSE2     = "-msse2",
ExtraWarnings  = "-Wall",
FatalWarnings  = "-Werror",
FloatFast      = "-ffast-math",
FloatStrict    = "-ffloat-store",
NoFramePointer = "-fomit-frame-pointer",
Optimize       = "-O2",
OptimizeSize   = "-Os",
OptimizeSpeed  = "-O3",
Symbols        = "-g",
}
local cxxflags =
{
NoExceptions   = "-fno-exceptions",
NoRTTI         = "-fno-rtti",
}
premake.gcc.platforms = 
{
Native = { 
cppflags = "-MMD -MP",
},
x32 = { 
cppflags = "-MMD -MP",
flags    = "-m32",
ldflags  = "-L/usr/lib32", 
},
x64 = { 
cppflags = "-MMD -MP",
flags    = "-m64",
ldflags  = "-L/usr/lib64",
},
Universal = { 
cppflags = "",
flags    = "-arch i386 -arch x86_64 -arch ppc -arch ppc64",
},
Universal32 = { 
cppflags = "",
flags    = "-arch i386 -arch ppc",
},
Universal64 = { 
cppflags = "",
flags    = "-arch x86_64 -arch ppc64",
},
PS3 = {
cc         = "ppu-lv2-g++",
cxx        = "ppu-lv2-g++",
ar         = "ppu-lv2-ar",
cppflags   = "-MMD -MP",
}
}
local platforms = premake.gcc.platforms
function premake.gcc.getcppflags(cfg)
local result = { }
table.insert(result, platforms[cfg.platform].cppflags)
return result
end
function premake.gcc.getcflags(cfg)
local result = table.translate(cfg.flags, cflags)
table.insert(result, platforms[cfg.platform].flags)
if cfg.system ~= "windows" and cfg.kind == "SharedLib" then
table.insert(result, "-fPIC")
end
return result
end
function premake.gcc.getcxxflags(cfg)
local result = table.translate(cfg.flags, cxxflags)
return result
end
function premake.gcc.getldflags(cfg)
local result = { }
if not cfg.flags.Symbols then
if cfg.system == "macosx" then
table.insert(result, "-Wl,-x")
else
table.insert(result, "-s")
end
end
if cfg.kind == "SharedLib" then
if cfg.system == "macosx" then
result = table.join(result, { "-dynamiclib", "-flat_namespace" })
else
table.insert(result, "-shared")
end
if cfg.system == "windows" and not cfg.flags.NoImportLib then
table.insert(result, '-Wl,--out-implib="' .. cfg.linktarget.fullpath .. '"')
end
end
if cfg.kind == "WindowedApp" and cfg.system == "windows" then
table.insert(result, "-mwindows")
end
local platform = platforms[cfg.platform]
table.insert(result, platform.flags)
table.insert(result, platform.ldflags)
return result
end
function premake.gcc.getlibdirflags(cfg)
local result = { }
for _, value in ipairs(premake.getlinks(cfg, "all", "directory")) do
table.insert(result, '-L' .. _MAKE.esc(value))
end
return result
end
function premake.gcc.getlinkflags(cfg)
local result = { }
for _, value in ipairs(premake.getlinks(cfg, "all", "basename")) do
if path.getextension(value) == ".framework" then
table.insert(result, '-framework ' .. _MAKE.esc(path.getbasename(value)))
else
table.insert(result, '-l' .. _MAKE.esc(value))
end
end
return result
end
function premake.gcc.getdefines(defines)
local result = { }
for _,def in ipairs(defines) do
table.insert(result, '-D' .. def)
end
return result
end
function premake.gcc.getincludedirs(includedirs)
local result = { }
for _,dir in ipairs(includedirs) do
table.insert(result, "-I" .. _MAKE.esc(dir))
end
return result
end
premake.msc = { }
premake.msc.namestyle = "windows"
premake.ow = { }
premake.ow.namestyle = "windows"
premake.ow.cc     = "WCL386"
premake.ow.cxx    = "WCL386"
premake.ow.ar     = "ar"
local cflags =
{
ExtraWarnings  = "-wx",
FatalWarning   = "-we",
FloatFast      = "-omn",
FloatStrict    = "-op",
Optimize       = "-ox",
OptimizeSize   = "-os",
OptimizeSpeed  = "-ot",
Symbols        = "-d2",
}
local cxxflags =
{
NoExceptions   = "-xd",
NoRTTI         = "-xr",
}
premake.ow.platforms = 
{
Native = { 
flags = "" 
},
}
function premake.ow.getcppflags(cfg)
return {}
end
function premake.ow.getcflags(cfg)
local result = table.translate(cfg.flags, cflags)
if (cfg.flags.Symbols) then
table.insert(result, "-hw")   -- Watcom debug format for Watcom debugger
end
return result
end
function premake.ow.getcxxflags(cfg)
local result = table.translate(cfg.flags, cxxflags)
return result
end
function premake.ow.getldflags(cfg)
local result = { }
if (cfg.flags.Symbols) then
table.insert(result, "op symf")
end
return result
end
function premake.ow.getlinkflags(cfg)
local result = { }
return result
end
function premake.ow.getdefines(defines)
local result = { }
for _,def in ipairs(defines) do
table.insert(result, '-D' .. def)
end
return result
end
function premake.ow.getincludedirs(includedirs)
local result = { }
for _,dir in ipairs(includedirs) do
table.insert(result, '-I "' .. dir .. '"')
end
return result
end
function premake.checkprojects()
local action = premake.action.current()
for sln in premake.solution.each() do
if (#sln.projects == 0) then
return nil, "solution '" .. sln.name .. "' needs at least one project"
end
if (#sln.configurations == 0) then
return nil, "solution '" .. sln.name .. "' needs configurations"
end
for prj in premake.solution.eachproject(sln) do
if (not prj.language) then
return nil, "project '" ..prj.name .. "' needs a language"
end
if (action.valid_languages) then
if (not table.contains(action.valid_languages, prj.language)) then
return nil, "the " .. action.shortname .. " action does not support " .. prj.language .. " projects"
end
end
for cfg in premake.eachconfig(prj) do
if (not cfg.kind) then
return nil, "project '" ..prj.name .. "' needs a kind in configuration '" .. cfg.name .. "'"
end
if (action.valid_kinds) then
if (not table.contains(action.valid_kinds, cfg.kind)) then
return nil, "the " .. action.shortname .. " action does not support " .. cfg.kind .. " projects"
end
end
end
if action.oncheckproject then
action.oncheckproject(prj)
end
end
end
return true
end
function premake.checktools()
local action = premake.action.current()
if (not action.valid_tools) then 
return true 
end
for tool, values in pairs(action.valid_tools) do
if (_OPTIONS[tool]) then
if (not table.contains(values, _OPTIONS[tool])) then
return nil, "the " .. action.shortname .. " action does not support /" .. tool .. "=" .. _OPTIONS[tool] .. " (yet)"
end
else
_OPTIONS[tool] = values[1]
end
end
return true
end
function premake.showhelp()
printf("Premake %s, a build script generator", _PREMAKE_VERSION)
printf(_PREMAKE_COPYRIGHT)
printf("%s %s", _VERSION, _COPYRIGHT)
printf("")
printf("Usage: premake4 [options] action [arguments]")
printf("")
printf("OPTIONS")
printf("")
for option in premake.option.each() do
local trigger = option.trigger
local description = option.description
if (option.value) then trigger = trigger .. "=" .. option.value end
if (option.allowed) then description = description .. "; one of:" end
printf(" --%-15s %s", trigger, description) 
if (option.allowed) then
for _, value in ipairs(option.allowed) do
printf("     %-14s %s", value[1], value[2])
end
end
printf("")
end
printf("ACTIONS")
printf("")
for action in premake.action.each() do
printf(" %-17s %s", action.trigger, action.description)
end
printf("")
printf("For additional information, see http://industriousone.com/premake")
end
function premake.generate(obj, filename, callback)
filename = premake.project.getfilename(obj, filename)
printf("Generating %s...", filename)
local f, err = io.open(filename, "wb")
if (not f) then
error(err, 0)
end
io.output(f)
callback(obj)
f:close()
end
newaction {
trigger         = "codeblocks",
shortname       = "Code::Blocks",
description     = "Generate Code::Blocks project files",
valid_kinds     = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib" },
valid_languages = { "C", "C++" },
valid_tools     = {
cc   = { "gcc", "ow" },
},
onsolution = function(sln)
premake.generate(sln, "%%.workspace", premake.codeblocks_workspace)
end,
onproject = function(prj)
premake.generate(prj, "%%.cbp", premake.codeblocks_cbp)
end,
oncleansolution = function(sln)
premake.clean.file(sln, "%%.workspace")
end,
oncleanproject = function(prj)
premake.clean.file(prj, "%%.cbp")
premake.clean.file(prj, "%%.depend")
premake.clean.file(prj, "%%.layout")
end
}
function premake.codeblocks_workspace(sln)
_p('')
_p('')
_p(1,'', sln.name)
for prj in premake.solution.eachproject(sln) do
local fname = path.join(path.getrelative(sln.location, prj.location), prj.name)
local active = iif(prj.project == sln.projects[1], ' active="1"', '')
_p(2,'', fname, active)
for _,dep in ipairs(premake.getdependencies(prj)) do
_p(3,'', path.join(path.getrelative(sln.location, dep.location), dep.name))
end
_p(2,'')
end
_p(1,'')
_p('')
end
function premake.codeblocks_cbp(prj)
local cc = premake.gettool(prj)
_p('')
_p('')
_p(1,'')
_p(1,'')
_p(2,'')
_p('')
_p('')
end
newaction {
trigger         = "codelite",
shortname       = "CodeLite",
description     = "Generate CodeLite project files",
valid_kinds     = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib" },
valid_languages = { "C", "C++" },
valid_tools     = {
cc   = { "gcc" },
},
onsolution = function(sln)
premake.generate(sln, "%%.workspace", premake.codelite_workspace)
end,
onproject = function(prj)
premake.generate(prj, "%%.project", premake.codelite_project)
end,
oncleansolution = function(sln)
premake.clean.file(sln, "%%.workspace")
premake.clean.file(sln, "%%_wsp.mk")
premake.clean.file(sln, "%%.tags")
end,
oncleanproject = function(prj)
premake.clean.file(prj, "%%.project")
premake.clean.file(prj, "%%.mk")
premake.clean.file(prj, "%%.list")
premake.clean.file(prj, "%%.out")
end
}
function premake.codelite_workspace(sln)
_p('')
_p('', premake.esc(sln.name), premake.esc(sln.name))
for i,prj in ipairs(sln.projects) do
local name = premake.esc(prj.name)
local fname = path.join(path.getrelative(sln.location, prj.location), prj.name)
local active = iif(i==1, "Yes", "No")
_p('  ', name, fname, active)
end
local platforms = premake.filterplatforms(sln, premake[_OPTIONS.cc].platforms, "Native")
for i = #platforms, 1, -1 do
if premake.platforms[platforms[i]].iscrosscompiler then
table.remove(platforms, i)
end
end 
_p('  ')
for _, platform in ipairs(platforms) do
for _, cfgname in ipairs(sln.configurations) do
local name = premake.getconfigname(cfgname, platform)
_p('    ', name)
for _,prj in ipairs(sln.projects) do
_p('      ', prj.name, name)
end
_p('    ')
end
end
_p('  ')
_p('')
end
function premake.codelite_project(prj)
_p('')
_p('', premake.esc(prj.name))
premake.walksources(prj, premake.codelite_files)
local types = { 
ConsoleApp  = "Executable", 
WindowedApp = "Executable", 
StaticLib   = "Static Library",
SharedLib   = "Dynamic Library",
}
_p('  ', types[prj.kind])
local platforms = premake.filterplatforms(prj.solution, premake[_OPTIONS.cc].platforms, "Native")
for i = #platforms, 1, -1 do
if premake.platforms[platforms[i]].iscrosscompiler then
table.remove(platforms, i)
end
end 
for _, platform in ipairs(platforms) do
for cfg in premake.eachconfig(prj, platform) do
local name = premake.esc(cfg.longname)
local compiler = iif(cfg.language == "C", "gcc", "g++")
_p('    ', name, compiler, types[cfg.kind])
local fname  = premake.esc(cfg.buildtarget.fullpath)
local objdir = premake.esc(cfg.objectsdir)
local runcmd = cfg.buildtarget.name
local rundir = cfg.buildtarget.directory
local pause  = iif(cfg.kind == "WindowedApp", "no", "yes")
_p('      ', fname, objdir, runcmd, rundir, pause)
local flags = premake.esc(table.join(premake.gcc.getcflags(cfg), premake.gcc.getcxxflags(cfg), cfg.buildoptions))
_p('      ', table.concat(flags, ";"))
for _,v in ipairs(cfg.includedirs) do
_p('        ', premake.esc(v))
end
for _,v in ipairs(cfg.defines) do
_p('        ', premake.esc(v))
end
_p('      ')
flags = premake.esc(table.join(premake.gcc.getldflags(cfg), cfg.linkoptions))
_p('      ', table.concat(flags, ";"))
for _,v in ipairs(premake.getlinks(cfg, "all", "directory")) do
_p('        ', premake.esc(v))
end
for _,v in ipairs(premake.getlinks(cfg, "all", "basename")) do
_p('        ', premake.esc(v))
end
_p('      ')
if premake.findfile(cfg, ".rc") then
local defines = table.implode(table.join(cfg.defines, cfg.resdefines), "-D", ";", "")
local options = table.concat(cfg.resoptions, ";")
_p('      ', defines, options)
for _,v in ipairs(table.join(cfg.includedirs, cfg.resincludedirs)) do
_p('        ', premake.esc(v))
end
_p('      ')
else
_p('      ')
end
if #cfg.prebuildcommands > 0 then
_p('      ')
for _,v in ipairs(cfg.prebuildcommands) do
_p('        %s', premake.esc(v))
end
_p('      ')
end
if #cfg.postbuildcommands > 0 then
_p('      ')
for _,v in ipairs(cfg.postbuildcommands) do
_p('        %s', premake.esc(v))
end
_p('      ')
end
_p('      ')
_p('        ')
_p('        ')
_p('        ')
_p('        ')
_p('        None')
_p('        ')
_p('      ')
_p('      ')
_p('        ')
_p('        ')
_p('      ')
_p('    ')
end
end
_p('  ')
for _, platform in ipairs(platforms) do
for cfg in premake.eachconfig(prj, platform) do
_p('  ', cfg.longname)
for _,dep in ipairs(premake.getdependencies(prj)) do
_p('    ', dep.name)
end
_p('  ')
end
end
_p('')
end
function premake.codelite_files(prj, fname, state, nestlevel)
local indent = string.rep("  ", nestlevel + 1)
if (state == "GroupStart") then
io.write(indent .. '\n')
elseif (state == "GroupEnd") then
io.write(indent .. '\n')
else
io.write(indent .. '\n')
end
end
_MAKE = { }
premake.make = { }
function _MAKE.esc(value)
local result
if (type(value) == "table") then
result = { }
for _,v in ipairs(value) do
table.insert(result, _MAKE.esc(v))
end
return result
else
result = value:gsub("\\", "\\\\")
result = result:gsub(" ", "\\ ")
result = result:gsub("%(", "\\%(")
result = result:gsub("%)", "\\%)")
result = result:gsub("$\\%((.-)\\%)", "$%(%1%)")
return result
end
end
function premake.make_copyrule(source, target)
_p('%s: %s', target, source)
_p('\t@echo Copying $(notdir %s)', target)
_p('ifeq (posix,$(SHELLTYPE))')
_p('\t$(SILENT) cp -fR %s %s', source, target)
_p('else')
_p('\t$(SILENT) copy /Y $(subst /,\\\\,%s) $(subst /,\\\\,%s)', source, target)
_p('endif')
end
function premake.make_mkdirrule(var)
_p('\t@echo Creating %s', var)
_p('ifeq (posix,$(SHELLTYPE))')
_p('\t$(SILENT) mkdir -p %s', var)
_p('else')
_p('\t$(SILENT) mkdir $(subst /,\\\\,%s)', var)
_p('endif')
_p('')
end
function _MAKE.getmakefilename(this, searchprjs)
local count = 0
for sln in premake.solution.each() do
if (sln.location == this.location) then count = count + 1 end
if (searchprjs) then
for _,prj in ipairs(sln.projects) do
if (prj.location == this.location) then count = count + 1 end
end
end
end
if (count == 1) then
return "Makefile"
else
return this.name .. ".make"
end
end
function _MAKE.getnames(tbl)
local result = table.extract(tbl, "name")
for k,v in pairs(result) do
result[k] = _MAKE.esc(v)
end
return result
end
newaction {
trigger         = "gmake",
shortname       = "GNU Make",
description     = "Generate GNU makefiles for POSIX, MinGW, and Cygwin",
valid_kinds     = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib" },
valid_languages = { "C", "C++", "C#" },
valid_tools     = {
cc     = { "gcc" },
dotnet = { "mono", "msnet", "pnet" },
},
onsolution = function(sln)
premake.generate(sln, _MAKE.getmakefilename(sln, false), premake.make_solution)
end,
onproject = function(prj)
local makefile = _MAKE.getmakefilename(prj, true)
if premake.isdotnetproject(prj) then
premake.generate(prj, makefile, premake.make_csharp)
else
premake.generate(prj, makefile, premake.make_cpp)
end
end,
oncleansolution = function(sln)
premake.clean.file(sln, _MAKE.getmakefilename(sln, false))
end,
oncleanproject = function(prj)
premake.clean.file(prj, _MAKE.getmakefilename(prj, true))
end
}
function premake.make_solution(sln)
local cc = premake[_OPTIONS.cc]
local platforms = premake.filterplatforms(sln, cc.platforms, "Native")
_p('# %s solution makefile autogenerated by Premake', premake.action.current().shortname)
_p('# Type "make help" for usage help')
_p('')
_p('ifndef config')
_p('  config=%s', _MAKE.esc(premake.getconfigname(sln.configurations[1], platforms[1], true)))
_p('endif')
_p('export config')
_p('')
_p('PROJECTS := %s', table.concat(_MAKE.esc(table.extract(sln.projects, "name")), " "))
_p('')
_p('.PHONY: all clean help $(PROJECTS)')
_p('')
_p('all: $(PROJECTS)')
_p('')
for _, prj in ipairs(sln.projects) do
_p('%s: %s', _MAKE.esc(prj.name), table.concat(_MAKE.esc(table.extract(premake.getdependencies(prj), "name")), " "))
_p('\t@echo "==== Building %s ($(config)) ===="', prj.name)
_p('\t@${MAKE} --no-print-directory -C %s -f %s', _MAKE.esc(path.getrelative(sln.location, prj.location)), _MAKE.esc(_MAKE.getmakefilename(prj, true)))
_p('')
end
_p('clean:')
for _ ,prj in ipairs(sln.projects) do
_p('\t@${MAKE} --no-print-directory -C %s -f %s clean', _MAKE.esc(path.getrelative(sln.location, prj.location)), _MAKE.esc(_MAKE.getmakefilename(prj, true)))
end
_p('')
_p('help:')
_p(1,'@echo "Usage: make [config=name] [target]"')
_p(1,'@echo ""')
_p(1,'@echo "CONFIGURATIONS:"')
local cfgpairs = { }
for _, platform in ipairs(platforms) do
for _, cfgname in ipairs(sln.configurations) do
_p(1,'@echo "   %s"', premake.getconfigname(cfgname, platform, true))
end
end
_p(1,'@echo ""')
_p(1,'@echo "TARGETS:"')
_p(1,'@echo "   all (default)"')
_p(1,'@echo "   clean"')
for _, prj in ipairs(sln.projects) do
_p(1,'@echo "   %s"', prj.name)
end
_p(1,'@echo ""')
_p(1,'@echo "For more information, see http://industriousone.com/premake/quick-start"')
end
premake.make.cpp = { }
local _ = premake.make.cpp
function premake.make_cpp(prj)
local cc = premake.gettool(prj)
local platforms = premake.filterplatforms(prj.solution, cc.platforms, "Native")
premake.gmake_cpp_header(prj, cc, platforms)
for _, platform in ipairs(platforms) do
for cfg in premake.eachconfig(prj, platform) do
premake.gmake_cpp_config(cfg, cc)
end
end
_p('OBJECTS := \\')
for _, file in ipairs(prj.files) do
if path.iscppfile(file) then
_p('\t$(OBJDIR)/%s.o \\', _MAKE.esc(path.getbasename(file)))
end
end
_p('')
 
_p('RESOURCES := \\')
for _, file in ipairs(prj.files) do
if path.isresourcefile(file) then
_p('\t$(OBJDIR)/%s.res \\', _MAKE.esc(path.getbasename(file)))
end
end
_p('')
 
_p('SHELLTYPE := msdos')
_p('ifeq (,$(ComSpec)$(COMSPEC))')
_p('  SHELLTYPE := posix')
_p('endif')
_p('ifeq (/bin,$(findstring /bin,$(SHELL)))')
_p('  SHELLTYPE := posix')
_p('endif')
_p('')
_p('.PHONY: clean prebuild prelink')
_p('')
if os.is("MacOSX") and prj.kind == "WindowedApp" then
_p('all: $(TARGETDIR) $(OBJDIR) prebuild prelink $(TARGET) $(dir $(TARGETDIR))PkgInfo $(dir $(TARGETDIR))Info.plist')
else
_p('all: $(TARGETDIR) $(OBJDIR) prebuild prelink $(TARGET)')
end
_p('\t@:')
_p('')
_p('$(TARGET): $(GCH) $(OBJECTS) $(LDDEPS) $(RESOURCES)')
_p('\t@echo Linking %s', prj.name)
_p('\t$(SILENT) $(LINKCMD)')
_p('\t$(POSTBUILDCMDS)')
_p('')
_p('$(TARGETDIR):')
premake.make_mkdirrule("$(TARGETDIR)")
_p('$(OBJDIR):')
premake.make_mkdirrule("$(OBJDIR)")
if os.is("MacOSX") and prj.kind == "WindowedApp" then
_p('$(dir $(TARGETDIR))PkgInfo:')
_p('$(dir $(TARGETDIR))Info.plist:')
_p('')
end
_p('clean:')
_p('\t@echo Cleaning %s', prj.name)
_p('ifeq (posix,$(SHELLTYPE))')
_p('\t$(SILENT) rm -f  $(TARGET)')
_p('\t$(SILENT) rm -rf $(OBJDIR)')
_p('else')
_p('\t$(SILENT) if exist $(subst /,\\\\,$(TARGET)) del $(subst /,\\\\,$(TARGET))')
_p('\t$(SILENT) if exist $(subst /,\\\\,$(OBJDIR)) rmdir /s /q $(subst /,\\\\,$(OBJDIR))')
_p('endif')
_p('')
_p('prebuild:')
_p('\t$(PREBUILDCMDS)')
_p('')
_p('prelink:')
_p('\t$(PRELINKCMDS)')
_p('')
_.pchrules(prj)
for _, file in ipairs(prj.files) do
if path.iscppfile(file) then
_p('$(OBJDIR)/%s.o: %s', _MAKE.esc(path.getbasename(file)), _MAKE.esc(file))
_p('\t@echo $(notdir $<)')
if (path.iscfile(file)) then
_p('\t$(SILENT) $(CC) $(CFLAGS) -o "$@" -c "$<"')
else
_p('\t$(SILENT) $(CXX) $(CXXFLAGS) -o "$@" -c "$<"')
end
elseif (path.getextension(file) == ".rc") then
_p('$(OBJDIR)/%s.res: %s', _MAKE.esc(path.getbasename(file)), _MAKE.esc(file))
_p('\t@echo $(notdir $<)')
_p('\t$(SILENT) windres $< -O coff -o "$@" $(RESFLAGS)')
end
end
_p('')
_p('-include $(OBJECTS:%%.o=%%.d)')
end
function premake.gmake_cpp_header(prj, cc, platforms)
_p('# %s project makefile autogenerated by Premake', premake.action.current().shortname)
_p('ifndef config')
_p('  config=%s', _MAKE.esc(premake.getconfigname(prj.solution.configurations[1], platforms[1], true)))
_p('endif')
_p('')
_p('ifndef verbose')
_p('  SILENT = @')
_p('endif')
_p('')
_p('ifndef CC')
_p('  CC = %s', cc.cc)
_p('endif')
_p('')
_p('ifndef CXX')
_p('  CXX = %s', cc.cxx)
_p('endif')
_p('')
_p('ifndef AR')
_p('  AR = %s', cc.ar)
_p('endif')
_p('')
end
function premake.gmake_cpp_config(cfg, cc)
_p('ifeq ($(config),%s)', _MAKE.esc(cfg.shortname))
local platform = cc.platforms[cfg.platform]
if platform.cc then
_p('  CC         = %s', platform.cc)
end
if platform.cxx then
_p('  CXX        = %s', platform.cxx)
end
if platform.ar then
_p('  AR         = %s', platform.ar)
end
_p('  OBJDIR     = %s', _MAKE.esc(cfg.objectsdir))
_p('  TARGETDIR  = %s', _MAKE.esc(cfg.buildtarget.directory))
_p('  TARGET     = $(TARGETDIR)/%s', _MAKE.esc(cfg.buildtarget.name))
_p('  DEFINES   += %s', table.concat(cc.getdefines(cfg.defines), " "))
_p('  INCLUDES  += %s', table.concat(cc.getincludedirs(cfg.includedirs), " "))
_p('  CPPFLAGS  += %s $(DEFINES) $(INCLUDES)', table.concat(cc.getcppflags(cfg), " "))
_.pchconfig(cfg)
_p('  CFLAGS    += $(CPPFLAGS) $(ARCH) %s', table.concat(table.join(cc.getcflags(cfg), cfg.buildoptions), " "))
_p('  CXXFLAGS  += $(CFLAGS) %s', table.concat(cc.getcxxflags(cfg), " "))
_p('  LDFLAGS   += %s', table.concat(table.join(cc.getldflags(cfg), cfg.linkoptions, cc.getlibdirflags(cfg)), " "))
_p('  LIBS      += %s', table.concat(cc.getlinkflags(cfg), " "))
_p('  RESFLAGS  += $(DEFINES) $(INCLUDES) %s', table.concat(table.join(cc.getdefines(cfg.resdefines), cc.getincludedirs(cfg.resincludedirs), cfg.resoptions), " "))
_p('  LDDEPS    += %s', table.concat(_MAKE.esc(premake.getlinks(cfg, "siblings", "fullpath")), " "))
if cfg.kind == "StaticLib" then
if cfg.platform:startswith("Universal") then
_p('  LINKCMD    = libtool -o $(TARGET) $(OBJECTS)')
else
_p('  LINKCMD    = $(AR) -rcs $(TARGET) $(OBJECTS)')
end
else
_p('  LINKCMD    = $(%s) -o $(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(ARCH) $(LIBS)', iif(cfg.language == "C", "CC", "CXX"))
end
_p('  define PREBUILDCMDS')
if #cfg.prebuildcommands > 0 then
_p('\t@echo Running pre-build commands')
_p('\t%s', table.implode(cfg.prebuildcommands, "", "", "\n\t"))
end
_p('  endef')
_p('  define PRELINKCMDS')
if #cfg.prelinkcommands > 0 then
_p('\t@echo Running pre-link commands')
_p('\t%s', table.implode(cfg.prelinkcommands, "", "", "\n\t"))
end
_p('  endef')
_p('  define POSTBUILDCMDS')
if #cfg.postbuildcommands > 0 then
_p('\t@echo Running post-build commands')
_p('\t%s', table.implode(cfg.postbuildcommands, "", "", "\n\t"))
end
_p('  endef')
_p('endif')
_p('')
end
function _.pchconfig(cfg)
if not cfg.flags.NoPCH and cfg.pchheader then
_p('  PCH        = %s', _MAKE.esc(path.getrelative(cfg.location, cfg.pchheader)))
_p('  GCH        = $(OBJDIR)/%s.gch', _MAKE.esc(path.getname(cfg.pchheader))) 
_p('  CPPFLAGS  += -I$(OBJDIR) -include $(OBJDIR)/%s', _MAKE.esc(path.getname(cfg.pchheader)))
end
end
function _.pchrules(prj)
_p('ifneq (,$(PCH))')
_p('$(GCH): $(PCH)')
_p('\t@echo $(notdir $<)')
_p('\t-$(SILENT) cp $< $(OBJDIR)')
if prj.language == "C" then
_p('\t$(SILENT) $(CC) $(CFLAGS) -o "$@" -c "$<"')
else
_p('\t$(SILENT) $(CXX) $(CXXFLAGS) -o "$@" -c "$<"')
end
_p('endif')
_p('')
end
local function getresourcefilename(cfg, fname)
if path.getextension(fname) == ".resx" then
    local name = cfg.buildtarget.basename .. "."
    local dir = path.getdirectory(fname)
    if dir ~= "." then 
name = name .. path.translate(dir, ".") .. "."
end
return "$(OBJDIR)/" .. _MAKE.esc(name .. path.getbasename(fname)) .. ".resources"
else
return fname
end
end
function premake.make_csharp(prj)
local csc = premake.dotnet
local cfglibs = { }
local cfgpairs = { }
local anycfg
for cfg in premake.eachconfig(prj) do
anycfg = cfg
cfglibs[cfg] = premake.getlinks(cfg, "siblings", "fullpath")
cfgpairs[cfg] = { }
for _, fname in ipairs(cfglibs[cfg]) do
if path.getdirectory(fname) ~= cfg.buildtarget.directory then
cfgpairs[cfg]["$(TARGETDIR)/" .. _MAKE.esc(path.getname(fname))] = _MAKE.esc(fname)
end
end
end
local sources = {}
local embedded = { }
local copypairs = { }
for fcfg in premake.eachfile(prj) do
local action = csc.getbuildaction(fcfg)
if action == "Compile" then
table.insert(sources, fcfg.name)
elseif action == "EmbeddedResource" then
table.insert(embedded, fcfg.name)
elseif action == "Content" then
copypairs["$(TARGETDIR)/" .. _MAKE.esc(path.getname(fcfg.name))] = _MAKE.esc(fcfg.name)
elseif path.getname(fcfg.name):lower() == "app.config" then
copypairs["$(TARGET).config"] = _MAKE.esc(fcfg.name)
end
end
local paths = table.translate(prj.libdirs, function(v) return path.join(prj.basedir, v) end)
paths = table.join({prj.basedir}, paths)
for _, libname in ipairs(premake.getlinks(prj, "system", "fullpath")) do
local libdir = os.pathsearch(libname..".dll", unpack(paths))
if (libdir) then
local target = "$(TARGETDIR)/" .. _MAKE.esc(path.getname(libname))
local source = path.getrelative(prj.basedir, path.join(libdir, libname))..".dll"
copypairs[target] = _MAKE.esc(source)
end
end
_p('# %s project makefile autogenerated by Premake', premake.action.current().shortname)
_p('')
_p('ifndef config')
_p('  config=%s', _MAKE.esc(prj.configurations[1]:lower()))
_p('endif')
_p('')
_p('ifndef verbose')
_p('  SILENT = @')
_p('endif')
_p('')
_p('ifndef CSC')
_p('  CSC=%s', csc.getcompilervar(prj))
_p('endif')
_p('')
_p('ifndef RESGEN')
_p('  RESGEN=resgen')
_p('endif')
_p('')
local platforms = premake.filterplatforms(prj.solution, premake[_OPTIONS.cc].platforms)
table.insert(platforms, 1, "")
for cfg in premake.eachconfig(prj) do
premake.gmake_cs_config(cfg, csc, cfglibs)
end
_p('# To maintain compatibility with VS.NET, these values must be set at the project level')
_p('TARGET     := $(TARGETDIR)/%s', _MAKE.esc(prj.buildtarget.name))
_p('FLAGS      += /t:%s %s', csc.getkind(prj):lower(), table.implode(_MAKE.esc(prj.libdirs), "/lib:", "", " "))
_p('REFERENCES += %s', table.implode(_MAKE.esc(premake.getlinks(prj, "system", "basename")), "/r:", ".dll", " "))
_p('')
_p('SOURCES := \\')
for _, fname in ipairs(sources) do
_p('\t%s \\', _MAKE.esc(path.translate(fname)))
end
_p('')
_p('EMBEDFILES := \\')
for _, fname in ipairs(embedded) do
_p('\t%s \\', getresourcefilename(prj, fname))
end
_p('')
_p('COPYFILES += \\')
for target, source in pairs(cfgpairs[anycfg]) do
_p('\t%s \\', target)
end
for target, source in pairs(copypairs) do
_p('\t%s \\', target)
end
_p('')
_p('SHELLTYPE := msdos')
_p('ifeq (,$(ComSpec)$(COMSPEC))')
_p('  SHELLTYPE := posix')
_p('endif')
_p('ifeq (/bin,$(findstring /bin,$(SHELL)))')
_p('  SHELLTYPE := posix')
_p('endif')
_p('')
_p('.PHONY: clean prebuild prelink')
_p('')
_p('all: $(TARGETDIR) $(OBJDIR) prebuild $(EMBEDFILES) $(COPYFILES) prelink $(TARGET)')
_p('')
_p('$(TARGET): $(SOURCES) $(EMBEDFILES) $(DEPENDS)')
_p('\t$(SILENT) $(CSC) /nologo /out:$@ $(FLAGS) $(REFERENCES) $(SOURCES) $(patsubst %%,/resource:%%,$(EMBEDFILES))')
_p('\t$(POSTBUILDCMDS)')
_p('')
_p('$(TARGETDIR):')
premake.make_mkdirrule("$(TARGETDIR)")
_p('$(OBJDIR):')
premake.make_mkdirrule("$(OBJDIR)")
_p('clean:')
_p('\t@echo Cleaning %s', prj.name)
_p('ifeq (posix,$(SHELLTYPE))')
_p('\t$(SILENT) rm -f $(TARGETDIR)/%s.* $(COPYFILES)', prj.buildtarget.basename)
_p('\t$(SILENT) rm -rf $(OBJDIR)')
_p('else')
_p('\t$(SILENT) if exist $(subst /,\\\\,$(TARGETDIR)/%s.*) del $(subst /,\\\\,$(TARGETDIR)/%s.*)', prj.buildtarget.basename, prj.buildtarget.basename)
for target, source in pairs(cfgpairs[anycfg]) do
_p('\t$(SILENT) if exist $(subst /,\\\\,%s) del $(subst /,\\\\,%s)', target, target)
end
for target, source in pairs(copypairs) do
_p('\t$(SILENT) if exist $(subst /,\\\\,%s) del $(subst /,\\\\,%s)', target, target)
end
_p('\t$(SILENT) if exist $(subst /,\\\\,$(OBJDIR)) rmdir /s /q $(subst /,\\\\,$(OBJDIR))')
_p('endif')
_p('')
_p('prebuild:')
_p('\t$(PREBUILDCMDS)')
_p('')
_p('prelink:')
_p('\t$(PRELINKCMDS)')
_p('')
_p('# Per-configuration copied file rules')
for cfg in premake.eachconfig(prj) do
_p('ifneq (,$(findstring %s,$(config)))', _MAKE.esc(cfg.name:lower()))
for target, source in pairs(cfgpairs[cfg]) do
premake.make_copyrule(source, target)
end
_p('endif')
_p('')
end
_p('# Copied file rules')
for target, source in pairs(copypairs) do
premake.make_copyrule(source, target)
end
_p('# Embedded file rules')
for _, fname in ipairs(embedded) do 
if path.getextension(fname) == ".resx" then
_p('%s: %s', getresourcefilename(prj, fname), _MAKE.esc(fname))
_p('\t$(SILENT) $(RESGEN) $^ $@')
end
_p('')
end
end
function premake.gmake_cs_config(cfg, csc, cfglibs)
_p('ifneq (,$(findstring %s,$(config)))', _MAKE.esc(cfg.name:lower()))
_p('  TARGETDIR  := %s', _MAKE.esc(cfg.buildtarget.directory))
_p('  OBJDIR     := %s', _MAKE.esc(cfg.objectsdir))
_p('  DEPENDS    := %s', table.concat(_MAKE.esc(premake.getlinks(cfg, "dependencies", "fullpath")), " "))
_p('  REFERENCES := %s', table.implode(_MAKE.esc(cfglibs[cfg]), "/r:", "", " "))
_p('  FLAGS      += %s %s', table.implode(cfg.defines, "/d:", "", " "), table.concat(table.join(csc.getflags(cfg), cfg.buildoptions), " "))
_p('  define PREBUILDCMDS')
if #cfg.prebuildcommands > 0 then
_p('\t@echo Running pre-build commands')
_p('\t%s', table.implode(cfg.prebuildcommands, "", "", "\n\t"))
end
_p('  endef')
_p('  define PRELINKCMDS')
if #cfg.prelinkcommands > 0 then
_p('\t@echo Running pre-link commands')
_p('\t%s', table.implode(cfg.prelinkcommands, "", "", "\n\t"))
end
_p('  endef')
_p('  define POSTBUILDCMDS')
if #cfg.postbuildcommands > 0 then
_p('\t@echo Running post-build commands')
_p('\t%s', table.implode(cfg.postbuildcommands, "", "", "\n\t"))
end
_p('  endef')
_p('endif')
_p('')
end
_VS = { }  -- deprecated, will remove eventually
premake.vstudio = { }
local vstudio = premake.vstudio
premake.vstudio_platforms = { 
any     = "Any CPU", 
mixed   = "Mixed Platforms", 
Native  = "Win32",
x32     = "Win32", 
x64     = "x64",
PS3     = "PS3",
Xbox360 = "Xbox 360",
}
function _VS.arch(prj)
if (prj.language == "C#") then
if (_ACTION < "vs2005") then
return ".NET"
else
return "Any CPU"
end
else
return "Win32"
end
end
function _VS.bool(value)
if (_ACTION < "vs2005") then
return iif(value, "TRUE", "FALSE")
else
return iif(value, "true", "false")
end
end
function premake.vstudio_buildconfigs(sln)
local cfgs = { }
local platforms = premake.filterplatforms(sln, premake.vstudio_platforms, "Native")
local hascpp    = premake.hascppproject(sln)
local hasdotnet = premake.hasdotnetproject(sln)
if hasdotnet then
table.insert(platforms, 1, "any")
end
if hasdotnet and hascpp then
table.insert(platforms, 2, "mixed")
end
for _, buildcfg in ipairs(sln.configurations) do
for _, platform in ipairs(platforms) do
local entry = { }
entry.src_buildcfg = buildcfg
entry.src_platform = platform
if platform ~= "PS3" then
entry.buildcfg = buildcfg
entry.platform = premake.vstudio_platforms[platform]
else
entry.buildcfg = platform .. " " .. buildcfg
entry.platform = "Win32"
end
entry.name = entry.buildcfg .. "|" .. entry.platform
entry.isreal = (platform ~= "any" and platform ~= "mixed")
table.insert(cfgs, entry)
end
end
return cfgs
end
function _VS.cfgtype(cfg)
if (cfg.kind == "SharedLib") then
return 2
elseif (cfg.kind == "StaticLib") then
return 4
else
return 1
end
end
function premake.vstudio.cleansolution(sln)
premake.clean.file(sln, "%%.sln")
premake.clean.file(sln, "%%.suo")
premake.clean.file(sln, "%%.ncb")
premake.clean.file(sln, "%%.userprefs")
premake.clean.file(sln, "%%.usertasks")
end
function premake.vstudio.cleanproject(prj)
local fname = premake.project.getfilename(prj, "%%")
os.remove(fname .. ".vcproj")
os.remove(fname .. ".vcproj.user")
os.remove(fname .. ".vcxproj")
os.remove(fname .. ".vcxproj.user")
os.remove(fname .. ".vcxproj.filters")
os.remove(fname .. ".csproj")
os.remove(fname .. ".csproj.user")
os.remove(fname .. ".pidb")
os.remove(fname .. ".sdf")
end
function premake.vstudio.cleantarget(name)
os.remove(name .. ".pdb")
os.remove(name .. ".idb")
os.remove(name .. ".ilk")
os.remove(name .. ".vshost.exe")
os.remove(name .. ".exe.manifest")
end
local function output(indent, value)
_p(indent .. value)
end
local function attrib(indent, name, value)
_p(indent .. "\t" .. name .. '="' .. value .. '"')
end
function _VS.files(prj, fname, state, nestlevel)
local indent = string.rep("\t", nestlevel + 2)
if (state == "GroupStart") then
output(indent, "")
elseif (state == "GroupEnd") then
output(indent, "")
else
output(indent, "")
if (not prj.flags.NoPCH and prj.pchsource == fname) then
for _, cfginfo in ipairs(prj.solution.vstudio_configs) do
if cfginfo.isreal then
local cfg = premake.getconfig(prj, cfginfo.src_buildcfg, cfginfo.src_platform)
output(indent, "\t")
output(indent, "\t\t")
output(indent, "\t")
end
end
end
output(indent, "")
end
end
function _VS.optimization(cfg)
local result = 0
for _, value in ipairs(cfg.flags) do
if (value == "Optimize") then
result = 3
elseif (value == "OptimizeSize") then
result = 1
elseif (value == "OptimizeSpeed") then
result = 2
end
end
return result
end
function _VS.projectfile(prj)
local extension
if (prj.language == "C#") then
extension = ".csproj"
elseif (_ACTION == "vs2010"  and prj.language == "C++" )then
extension = ".vcxproj"
elseif (_ACTION == "vs2010"  and prj.language == "C" )then
extension = ".vcxproj"
else
extension = ".vcproj"
end
local fname = path.join(prj.location, prj.name)
return fname..extension
end
function _VS.tool(prj)
if (prj.language == "C#") then
return "FAE04EC0-301F-11D3-BF4B-00C04F79EFBC"
else
return "8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942"
end
end
newaction {
trigger         = "vs2002",
shortname       = "Visual Studio 2002",
description     = "Generate Microsoft Visual Studio 2002 project files",
os              = "windows",
valid_kinds     = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib" },
valid_languages = { "C", "C++", "C#" },
valid_tools     = {
cc     = { "msc"   },
dotnet = { "msnet" },
},
onsolution = function(sln)
premake.generate(sln, "%%.sln", premake.vs2002_solution)
end,
onproject = function(prj)
if premake.isdotnetproject(prj) then
premake.generate(prj, "%%.csproj", premake.vs2002_csproj)
premake.generate(prj, "%%.csproj.user", premake.vs2002_csproj_user)
else
premake.generate(prj, "%%.vcproj", premake.vs200x_vcproj)
end
end,
oncleansolution = premake.vstudio.cleansolution,
oncleanproject  = premake.vstudio.cleanproject,
oncleantarget   = premake.vstudio.cleantarget
}
newaction {
trigger         = "vs2003",
shortname       = "Visual Studio 2003",
description     = "Generate Microsoft Visual Studio 2003 project files",
os              = "windows",
valid_kinds     = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib" },
valid_languages = { "C", "C++", "C#" },
valid_tools     = {
cc     = { "msc"   },
dotnet = { "msnet" },
},
onsolution = function(sln)
premake.generate(sln, "%%.sln", premake.vs2003_solution)
end,
onproject = function(prj)
if premake.isdotnetproject(prj) then
premake.generate(prj, "%%.csproj", premake.vs2002_csproj)
premake.generate(prj, "%%.csproj.user", premake.vs2002_csproj_user)
else
premake.generate(prj, "%%.vcproj", premake.vs200x_vcproj)
end
end,
oncleansolution = premake.vstudio.cleansolution,
oncleanproject  = premake.vstudio.cleanproject,
oncleantarget   = premake.vstudio.cleantarget
}
newaction {
trigger         = "vs2005",
shortname       = "Visual Studio 2005",
description     = "Generate Microsoft Visual Studio 2005 project files",
os              = "windows",
valid_kinds     = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib" },
valid_languages = { "C", "C++", "C#" },
valid_tools     = {
cc     = { "msc"   },
dotnet = { "msnet" },
},
onsolution = function(sln)
premake.generate(sln, "%%.sln", premake.vs2005_solution)
end,
onproject = function(prj)
if premake.isdotnetproject(prj) then
premake.generate(prj, "%%.csproj", premake.vs2005_csproj)
premake.generate(prj, "%%.csproj.user", premake.vs2005_csproj_user)
else
premake.generate(prj, "%%.vcproj", premake.vs200x_vcproj)
end
end,
oncleansolution = premake.vstudio.cleansolution,
oncleanproject  = premake.vstudio.cleanproject,
oncleantarget   = premake.vstudio.cleantarget
}
newaction {
trigger         = "vs2008",
shortname       = "Visual Studio 2008",
description     = "Generate Microsoft Visual Studio 2008 project files",
os              = "windows",
valid_kinds     = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib" },
valid_languages = { "C", "C++", "C#" },
valid_tools     = {
cc     = { "msc"   },
dotnet = { "msnet" },
},
onsolution = function(sln)
premake.generate(sln, "%%.sln", premake.vs2005_solution)
end,
onproject = function(prj)
if premake.isdotnetproject(prj) then
premake.generate(prj, "%%.csproj", premake.vs2005_csproj)
premake.generate(prj, "%%.csproj.user", premake.vs2005_csproj_user)
else
premake.generate(prj, "%%.vcproj", premake.vs200x_vcproj)
end
end,
oncleansolution = premake.vstudio.cleansolution,
oncleanproject  = premake.vstudio.cleanproject,
oncleantarget   = premake.vstudio.cleantarget
}
newaction 
{
trigger         = "vs2010",
shortname       = "Visual Studio 2010",
description     = "Generate Visual Studio 2010 project files (experimental)",
os              = "windows",
valid_kinds     = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib" },
valid_languages = { "C++","C"},
valid_tools     = {
cc     = { "msc"   },
},
onsolution = function(sln)
premake.generate(sln, "%%.sln", premake.vs_generic_solution)
end,
onproject = function(prj)
premake.generate(prj, "%%.vcxproj", premake.vs2010_vcxproj)
premake.generate(prj, "%%.vcxproj.user", premake.vs2010_vcxproj_user)
premake.generate(prj, "%%.vcxproj.filters", premake.vs2010_vcxproj_filters)
end,
oncleansolution = premake.vstudio.cleansolution,
oncleanproject  = premake.vstudio.cleanproject,
oncleantarget   = premake.vstudio.cleantarget
}function premake.vs2002_solution(sln)
io.eol = '\r\n'
sln.vstudio_configs = premake.vstudio_buildconfigs(sln)
_p('Microsoft Visual Studio Solution File, Format Version 7.00')
for prj in premake.solution.eachproject(sln) do
local projpath = path.translate(path.getrelative(sln.location, _VS.projectfile(prj)))
_p('Project("{%s}") = "%s", "%s", "{%s}"', _VS.tool(prj), prj.name, projpath, prj.uuid)
_p('EndProject')
end
_p('Global')
_p(1,'GlobalSection(SolutionConfiguration) = preSolution')
for i, cfgname in ipairs(sln.configurations) do
_p(2,'ConfigName.%d = %s', i - 1, cfgname)
end
_p(1,'EndGlobalSection')
_p(1,'GlobalSection(ProjectDependencies) = postSolution')
_p(1,'EndGlobalSection')
_p(1,'GlobalSection(ProjectConfiguration) = postSolution')
for prj in premake.solution.eachproject(sln) do
for _, cfgname in ipairs(sln.configurations) do
_p(2,'{%s}.%s.ActiveCfg = %s|%s', prj.uuid, cfgname, cfgname, _VS.arch(prj))
_p(2,'{%s}.%s.Build.0 = %s|%s', prj.uuid, cfgname, cfgname, _VS.arch(prj))
end
end
_p(1,'EndGlobalSection')
_p(1,'GlobalSection(ExtensibilityGlobals) = postSolution')
_p(1,'EndGlobalSection')
_p(1,'GlobalSection(ExtensibilityAddIns) = postSolution')
_p(1,'EndGlobalSection')
_p('EndGlobal')
end
local function getelements(prj, action, fname)
if action == "Compile" and fname:endswith(".cs") then
return "SubTypeCode"
end
if action == "EmbeddedResource" and fname:endswith(".resx") then
local basename = fname:sub(1, -6)
local testname = path.getname(basename .. ".cs")
if premake.findfile(prj, testname) then
return "Dependency", testname
end
end
return "None"
end
function premake.vs2002_csproj(prj)
io.eol = "\r\n"
_p('')
_p(1,'')
_p(2,'')
_p(3,'')
for cfg in premake.eachconfig(prj) do
_p(4,'')
end
_p(3,'')
_p(3,'')
for _, ref in ipairs(premake.getlinks(prj, "siblings", "object")) do
_p(4,'')
end
for _, linkname in ipairs(premake.getlinks(prj, "system", "fullpath")) do
_p(4,'')
end
_p(3,'')
_p(2,'')
_p(2,'')
_p(3,'')
for fcfg in premake.eachfile(prj) do
local action = premake.dotnet.getbuildaction(fcfg)
local fname  = path.translate(premake.esc(fcfg.name), "\\")
local elements, dependency = getelements(prj, action, fcfg.name)
_p(4,'')
end
_p(3,'')
_p(2,'')
_p(1,'')
_p('')
end
function premake.vs2002_csproj_user(prj)
io.eol = "\r\n"
_p('')
_p(1,'')
_p(2,'')
local refpaths = table.translate(prj.libdirs, function(v) return path.getabsolute(prj.location .. "/" .. v) end)
_p(3,'', path.translate(table.concat(refpaths, ";"), "\\"))
for cfg in premake.eachconfig(prj) do
_p(4,'')
end
_p(3,'')
_p(2,'')
_p(2,'')
_p(1,'')
_p('')
end
premake.vstudio.vcproj = { }
local vcproj = premake.vstudio.vcproj
function vcproj.Configuration(name, cfg)
_p(2,'')
end
function premake.vs200x_vcproj_platforms(prj)
local used = { }
_p(1,'')
for _, cfg in ipairs(prj.solution.vstudio_configs) do
if cfg.isreal and not table.contains(used, cfg.platform) then
table.insert(used, cfg.platform)
_p(2,'')
end
end
_p(1,'')
end
function premake.vs200x_vcproj_symbols(cfg)
if (not cfg.flags.Symbols) then
return 0
else
if cfg.flags.NoEditAndContinue or 
   _VS.optimization(cfg) ~= 0 or 
   cfg.flags.Managed or 
   cfg.platform == "x64" then
return 3
else
return 4
end
end
end
function premake.vs200x_vcproj_VCCLCompilerTool(cfg)
_p(3,' 0 then
_p(4,'AdditionalOptions="%s"', table.concat(premake.esc(cfg.buildoptions), " "))
end
_p(4,'Optimization="%s"', _VS.optimization(cfg))
if cfg.flags.NoFramePointer then
_p(4,'OmitFramePointers="%s"', _VS.bool(true))
end
if #cfg.includedirs > 0 then
_p(4,'AdditionalIncludeDirectories="%s"', premake.esc(path.translate(table.concat(cfg.includedirs, ";"), '\\')))
end
if #cfg.defines > 0 then
_p(4,'PreprocessorDefinitions="%s"', premake.esc(table.concat(cfg.defines, ";")))
end
if premake.config.isdebugbuild(cfg) and not cfg.flags.NoMinimalRebuild and not cfg.flags.Managed then
_p(4,'MinimalRebuild="%s"', _VS.bool(true))
end
if cfg.flags.NoExceptions then
_p(4,'ExceptionHandling="%s"', iif(_ACTION < "vs2005", "FALSE", 0))
elseif cfg.flags.SEH and _ACTION > "vs2003" then
_p(4,'ExceptionHandling="2"')
end
if _VS.optimization(cfg) == 0 and not cfg.flags.Managed then
_p(4,'BasicRuntimeChecks="3"')
end
if _VS.optimization(cfg) ~= 0 then
_p(4,'StringPooling="%s"', _VS.bool(true))
end
local runtime
if premake.config.isdebugbuild(cfg) then
runtime = iif(cfg.flags.StaticRuntime, 1, 3)
else
runtime = iif(cfg.flags.StaticRuntime, 0, 2)
end
_p(4,'RuntimeLibrary="%s"', runtime)
_p(4,'EnableFunctionLevelLinking="%s"', _VS.bool(true))
if _ACTION > "vs2003" and cfg.platform ~= "Xbox360" and cfg.platform ~= "x64" then
if cfg.flags.EnableSSE then
_p(4,'EnableEnhancedInstructionSet="1"')
elseif cfg.flags.EnableSSE2 then
_p(4,'EnableEnhancedInstructionSet="2"')
end
end
if _ACTION < "vs2005" then
if cfg.flags.FloatFast then
_p(4,'ImproveFloatingPointConsistency="%s"', _VS.bool(false))
elseif cfg.flags.FloatStrict then
_p(4,'ImproveFloatingPointConsistency="%s"', _VS.bool(true))
end
else
if cfg.flags.FloatFast then
_p(4,'FloatingPointModel="2"')
elseif cfg.flags.FloatStrict then
_p(4,'FloatingPointModel="1"')
end
end
if _ACTION < "vs2005" and not cfg.flags.NoRTTI then
_p(4,'RuntimeTypeInfo="%s"', _VS.bool(true))
elseif _ACTION > "vs2003" and cfg.flags.NoRTTI then
_p(4,'RuntimeTypeInfo="%s"', _VS.bool(false))
end
if cfg.flags.NativeWChar then
_p(4,'TreatWChar_tAsBuiltInType="%s"', _VS.bool(true))
elseif cfg.flags.NoNativeWChar then
_p(4,'TreatWChar_tAsBuiltInType="%s"', _VS.bool(false))
end
if not cfg.flags.NoPCH and cfg.pchheader then
_p(4,'UsePrecompiledHeader="%s"', iif(_ACTION < "vs2005", 3, 2))
_p(4,'PrecompiledHeaderThrough="%s"', path.getname(cfg.pchheader))
else
_p(4,'UsePrecompiledHeader="%s"', iif(_ACTION > "vs2003" or cfg.flags.NoPCH, 0, 2))
end
_p(4,'WarningLevel="%s"', iif(cfg.flags.ExtraWarnings, 4, 3))
if cfg.flags.FatalWarnings then
_p(4,'WarnAsError="%s"', _VS.bool(true))
end
if _ACTION < "vs2008" and not cfg.flags.Managed then
_p(4,'Detect64BitPortabilityProblems="%s"', _VS.bool(not cfg.flags.No64BitChecks))
end
_p(4,'ProgramDataBaseFileName="$(OutDir)\\%s.pdb"', path.getbasename(cfg.buildtarget.name))
_p(4,'DebugInformationFormat="%s"', premake.vs200x_vcproj_symbols(cfg))
if cfg.language == "C" then
_p(4, 'CompileAs="1"')
end
_p(3,'/>')
end
function premake.vs200x_vcproj_VCLinkerTool(cfg)
_p(3,' 0 then
_p(4,'AdditionalOptions="%s"', table.concat(premake.esc(cfg.linkoptions), " "))
end
if #cfg.links > 0 then
_p(4,'AdditionalDependencies="%s"', table.concat(premake.getlinks(cfg, "all", "fullpath"), " "))
end
_p(4,'OutputFile="$(OutDir)\\%s"', cfg.buildtarget.name)
_p(4,'LinkIncremental="%s"', iif(_VS.optimization(cfg) == 0, 2, 1))
_p(4,'AdditionalLibraryDirectories="%s"', table.concat(premake.esc(path.translate(cfg.libdirs, '\\')) , ";"))
local deffile = premake.findfile(cfg, ".def")
if deffile then
_p(4,'ModuleDefinitionFile="%s"', deffile)
end
if cfg.flags.NoManifest then
_p(4,'GenerateManifest="%s"', _VS.bool(false))
end
_p(4,'GenerateDebugInformation="%s"', _VS.bool(premake.vs200x_vcproj_symbols(cfg) ~= 0))
if premake.vs200x_vcproj_symbols(cfg) ~= 0 then
_p(4,'ProgramDataBaseFileName="$(OutDir)\\%s.pdb"', path.getbasename(cfg.buildtarget.name))
end
_p(4,'SubSystem="%s"', iif(cfg.kind == "ConsoleApp", 1, 2))
if _VS.optimization(cfg) ~= 0 then
_p(4,'OptimizeReferences="2"')
_p(4,'EnableCOMDATFolding="2"')
end
if (cfg.kind == "ConsoleApp" or cfg.kind == "WindowedApp") and not cfg.flags.WinMain then
_p(4,'EntryPointSymbol="mainCRTStartup"')
end
if cfg.kind == "SharedLib" then
local implibname = cfg.linktarget.fullpath
_p(4,'ImportLibrary="%s"', iif(cfg.flags.NoImportLib, cfg.objectsdir .. "\\" .. path.getname(implibname), implibname))
end
_p(4,'TargetMachine="%d"', iif(cfg.platform == "x64", 17, 1))
else
_p(4,'Name="VCLibrarianTool"')
if #cfg.links > 0 then
_p(4,'AdditionalDependencies="%s"', table.concat(premake.getlinks(cfg, "all", "fullpath"), " "))
end
_p(4,'OutputFile="$(OutDir)\\%s"', cfg.buildtarget.name)
if #cfg.libdirs > 0 then
_p(4,'AdditionalLibraryDirectories="%s"', premake.esc(path.translate(table.concat(cfg.libdirs , ";"))))
end
if #cfg.linkoptions > 0 then
_p(4,'AdditionalOptions="%s"', table.concat(premake.esc(cfg.linkoptions), " "))
end
end
_p(3,'/>')
end
function premake.vs200x_vcproj_VCCLCompilerTool_GCC(cfg)
_p(3,' 0 then
_p(4,'AdditionalOptions="%s"', premake.esc(table.concat(buildoptions, " ")))
end
if #cfg.includedirs > 0 then
_p(4,'AdditionalIncludeDirectories="%s"', premake.esc(path.translate(table.concat(cfg.includedirs, ";"), '\\')))
end
if #cfg.defines > 0 then
_p(4,'PreprocessorDefinitions="%s"', table.concat(premake.esc(cfg.defines), ";"))
end
_p(4,'ProgramDataBaseFileName="$(OutDir)\\%s.pdb"', path.getbasename(cfg.buildtarget.name))
_p(4,'DebugInformationFormat="0"')
_p(4,'CompileAs="0"')
_p(3,'/>')
end
function premake.vs200x_vcproj_VCLinkerTool_GCC(cfg)
_p(3,' 0 then
_p(4,'AdditionalOptions="%s"', premake.esc(table.concat(buildoptions, " ")))
end
if #cfg.links > 0 then
_p(4,'AdditionalDependencies="%s"', table.concat(premake.getlinks(cfg, "all", "fullpath"), " "))
end
_p(4,'OutputFile="$(OutDir)\\%s"', cfg.buildtarget.name)
_p(4,'LinkIncremental="0"')
_p(4,'AdditionalLibraryDirectories="%s"', table.concat(premake.esc(path.translate(cfg.libdirs, '\\')) , ";"))
_p(4,'GenerateManifest="%s"', _VS.bool(false))
_p(4,'ProgramDatabaseFile=""')
_p(4,'RandomizedBaseAddress="1"')
_p(4,'DataExecutionPrevention="0"')
else
_p(4,'Name="VCLibrarianTool"')
local buildoptions = table.join(premake.gcc.getldflags(cfg), cfg.linkoptions)
if #buildoptions > 0 then
_p(4,'AdditionalOptions="%s"', premake.esc(table.concat(buildoptions, " ")))
end
if #cfg.links > 0 then
_p(4,'AdditionalDependencies="%s"', table.concat(premake.getlinks(cfg, "all", "fullpath"), " "))
end
_p(4,'OutputFile="$(OutDir)\\%s"', cfg.buildtarget.name)
if #cfg.libdirs > 0 then
_p(4,'AdditionalLibraryDirectories="%s"', premake.esc(path.translate(table.concat(cfg.libdirs , ";"))))
end
end
_p(3,'/>')
end
function premake.vs200x_vcproj_VCResourceCompilerTool(cfg)
_p(3,' 0 then
_p(4,'AdditionalOptions="%s"', table.concat(premake.esc(cfg.resoptions), " "))
end
if #cfg.defines > 0 or #cfg.resdefines > 0 then
_p(4,'PreprocessorDefinitions="%s"', table.concat(premake.esc(table.join(cfg.defines, cfg.resdefines)), ";"))
end
if #cfg.includedirs > 0 or #cfg.resincludedirs > 0 then
local dirs = table.join(cfg.includedirs, cfg.resincludedirs)
_p(4,'AdditionalIncludeDirectories="%s"', premake.esc(path.translate(table.concat(dirs, ";"), '\\')))
end
_p(3,'/>')
end
function premake.vs200x_vcproj_VCManifestTool(cfg)
local manifests = { }
for _, fname in ipairs(cfg.files) do
if path.getextension(fname) == ".manifest" then
table.insert(manifests, fname)
end
end
_p(3,' 0 then
_p(4,'AdditionalManifestFiles="%s"', premake.esc(table.concat(manifests, ";")))
end
_p(3,'/>')
end
function premake.vs200x_vcproj_VCMIDLTool(cfg)
_p(3,'')
end
function premake.vs200x_vcproj_buildstepsblock(name, steps)
_p(3,' 0 then
_p(4,'CommandLine="%s"', premake.esc(table.implode(steps, "", "", "\r\n")))
end
_p(3,'/>')
end
local blockmap = 
{
VCCLCompilerTool       = premake.vs200x_vcproj_VCCLCompilerTool,
VCCLCompilerTool_GCC   = premake.vs200x_vcproj_VCCLCompilerTool_GCC,
VCLinkerTool           = premake.vs200x_vcproj_VCLinkerTool,
VCLinkerTool_GCC       = premake.vs200x_vcproj_VCLinkerTool_GCC,
VCManifestTool         = premake.vs200x_vcproj_VCManifestTool,
VCMIDLTool             = premake.vs200x_vcproj_VCMIDLTool,
VCResourceCompilerTool = premake.vs200x_vcproj_VCResourceCompilerTool,
}
local function getsections(version, platform)
if version == "vs2002" then
return {
"VCCLCompilerTool",
"VCCustomBuildTool",
"VCLinkerTool",
"VCMIDLTool",
"VCPostBuildEventTool",
"VCPreBuildEventTool",
"VCPreLinkEventTool",
"VCResourceCompilerTool",
"VCWebServiceProxyGeneratorTool",
"VCWebDeploymentTool"
}
end
if version == "vs2003" then
return {
"VCCLCompilerTool",
"VCCustomBuildTool",
"VCLinkerTool",
"VCMIDLTool",
"VCPostBuildEventTool",
"VCPreBuildEventTool",
"VCPreLinkEventTool",
"VCResourceCompilerTool",
"VCWebServiceProxyGeneratorTool",
"VCXMLDataGeneratorTool",
"VCWebDeploymentTool",
"VCManagedWrapperGeneratorTool",
"VCAuxiliaryManagedWrapperGeneratorTool"
}
end
if platform == "Xbox360" then
return {
"VCPreBuildEventTool",
"VCCustomBuildTool",
"VCXMLDataGeneratorTool",
"VCWebServiceProxyGeneratorTool",
"VCMIDLTool",
"VCCLCompilerTool",
"VCManagedResourceCompilerTool",
"VCResourceCompilerTool",
"VCPreLinkEventTool",
"VCLinkerTool",
"VCALinkTool",
"VCX360ImageTool",
"VCBscMakeTool",
"VCX360DeploymentTool",
"VCPostBuildEventTool",
"DebuggerTool",
}
end
if platform == "PS3" then
return {
"VCPreBuildEventTool",
"VCCustomBuildTool",
"VCXMLDataGeneratorTool",
"VCWebServiceProxyGeneratorTool",
"VCMIDLTool",
"VCCLCompilerTool_GCC",
"VCManagedResourceCompilerTool",
"VCResourceCompilerTool",
"VCPreLinkEventTool",
"VCLinkerTool_GCC",
"VCALinkTool",
"VCManifestTool",
"VCXDCMakeTool",
"VCBscMakeTool",
"VCFxCopTool",
"VCAppVerifierTool",
"VCWebDeploymentTool",
"VCPostBuildEventTool"
}
else
return {
"VCPreBuildEventTool",
"VCCustomBuildTool",
"VCXMLDataGeneratorTool",
"VCWebServiceProxyGeneratorTool",
"VCMIDLTool",
"VCCLCompilerTool",
"VCManagedResourceCompilerTool",
"VCResourceCompilerTool",
"VCPreLinkEventTool",
"VCLinkerTool",
"VCALinkTool",
"VCManifestTool",
"VCXDCMakeTool",
"VCBscMakeTool",
"VCFxCopTool",
"VCAppVerifierTool",
"VCWebDeploymentTool",
"VCPostBuildEventTool"
}
end
end
function premake.vs200x_vcproj(prj)
io.eol = "\r\n"
_p('')
_p(' "vs2003" then
_p(1,'RootNamespace="%s"', prj.name)
end
_p(1,'Keyword="%s"', iif(prj.flags.Managed, "ManagedCProj", "Win32Proj"))
_p(1,'>')
premake.vs200x_vcproj_platforms(prj)
if _ACTION > "vs2003" then
_p(1,'')
_p(1,'')
end
_p(1,'')
for _, cfginfo in ipairs(prj.solution.vstudio_configs) do
if cfginfo.isreal then
local cfg = premake.getconfig(prj, cfginfo.src_buildcfg, cfginfo.src_platform)
vcproj.Configuration(cfginfo.name, cfg)
for _, block in ipairs(getsections(_ACTION, cfginfo.src_platform)) do
if blockmap[block] then
blockmap[block](cfg)
elseif block == "VCPreBuildEventTool" then
premake.vs200x_vcproj_buildstepsblock("VCPreBuildEventTool", cfg.prebuildcommands)
elseif block == "VCPreLinkEventTool" then
premake.vs200x_vcproj_buildstepsblock("VCPreLinkEventTool", cfg.prelinkcommands)
elseif block == "VCPostBuildEventTool" then
premake.vs200x_vcproj_buildstepsblock("VCPostBuildEventTool", cfg.postbuildcommands)
elseif block == "VCX360DeploymentTool" then
_p(3,' 0 then
_p(4,'AdditionalOptions="%s"', table.concat(premake.esc(cfg.deploymentoptions), " "))
end
_p(3,'/>')
elseif block == "VCX360ImageTool" then
_p(3,' 0 then
_p(4,'AdditionalOptions="%s"', table.concat(premake.esc(cfg.imageoptions), " "))
end
if cfg.imagepath ~= nil then
_p(4,'OutputFileName="%s"', premake.esc(path.translate(cfg.imagepath)))
end
_p(3,'/>')
elseif block == "DebuggerTool" then
_p(3,'')
else
_p(3,'')
end
end
_p(2,'')
end
end
_p(1,'')
_p(1,'')
_p(1,'')
_p(1,'')
premake.walksources(prj, _VS.files)
_p(1,'')
_p(1,'')
_p(1,'')
_p('')
end
function premake.vs2003_solution(sln)
io.eol = '\r\n'
sln.vstudio_configs = premake.vstudio_buildconfigs(sln)
_p('Microsoft Visual Studio Solution File, Format Version 8.00')
for prj in premake.solution.eachproject(sln) do
local projpath = path.translate(path.getrelative(sln.location, _VS.projectfile(prj)))
_p('Project("{%s}") = "%s", "%s", "{%s}"', _VS.tool(prj), prj.name, projpath, prj.uuid)
local deps = premake.getdependencies(prj)
if #deps > 0 then
_p('\tProjectSection(ProjectDependencies) = postProject')
for _, dep in ipairs(deps) do
_p('\t\t{%s} = {%s}', dep.uuid, dep.uuid)
end
_p('\tEndProjectSection')
end
_p('EndProject')
end
_p('Global')
_p('\tGlobalSection(SolutionConfiguration) = preSolution')
for _, cfgname in ipairs(sln.configurations) do
_p('\t\t%s = %s', cfgname, cfgname)
end
_p('\tEndGlobalSection')
_p('\tGlobalSection(ProjectDependencies) = postSolution')
_p('\tEndGlobalSection')
_p('\tGlobalSection(ProjectConfiguration) = postSolution')
for prj in premake.solution.eachproject(sln) do
for _, cfgname in ipairs(sln.configurations) do
_p('\t\t{%s}.%s.ActiveCfg = %s|%s', prj.uuid, cfgname, cfgname, _VS.arch(prj))
_p('\t\t{%s}.%s.Build.0 = %s|%s', prj.uuid, cfgname, cfgname, _VS.arch(prj))
end
end
_p('\tEndGlobalSection')
_p('\tGlobalSection(ExtensibilityGlobals) = postSolution')
_p('\tEndGlobalSection')
_p('\tGlobalSection(ExtensibilityAddIns) = postSolution')
_p('\tEndGlobalSection')
_p('EndGlobal')
end
function premake.vs2005_solution(sln)
io.eol = '\r\n'
sln.vstudio_configs = premake.vstudio_buildconfigs(sln)
_p('\239\187\191')
_p('Microsoft Visual Studio Solution File, Format Version %s', iif(_ACTION == 'vs2005', '9.00', '10.00'))
_p('# Visual Studio %s', iif(_ACTION == 'vs2005', '2005', '2008'))
for prj in premake.solution.eachproject(sln) do
local projpath = path.translate(path.getrelative(sln.location, _VS.projectfile(prj)), "\\")
_p('Project("{%s}") = "%s", "%s", "{%s}"', _VS.tool(prj), prj.name, projpath, prj.uuid)
local deps = premake.getdependencies(prj)
if #deps > 0 then
_p('\tProjectSection(ProjectDependencies) = postProject')
for _, dep in ipairs(deps) do
_p('\t\t{%s} = {%s}', dep.uuid, dep.uuid)
end
_p('\tEndProjectSection')
end
_p('EndProject')
end
_p('Global')
premake.vs2005_solution_platforms(sln)
premake.vs2005_solution_project_platforms(sln)
premake.vs2005_solution_properties(sln)
_p('EndGlobal')
end
function premake.vs2005_solution_platforms(sln)
_p('\tGlobalSection(SolutionConfigurationPlatforms) = preSolution')
for _, cfg in ipairs(sln.vstudio_configs) do
_p('\t\t%s = %s', cfg.name, cfg.name)
end
_p('\tEndGlobalSection')
end
function premake.vs2005_solution_project_platforms(sln)
_p('\tGlobalSection(ProjectConfigurationPlatforms) = postSolution')
for prj in premake.solution.eachproject(sln) do
for _, cfg in ipairs(sln.vstudio_configs) do
local mapped
if premake.isdotnetproject(prj) then
mapped = "Any CPU"
else
if cfg.platform == "Any CPU" or cfg.platform == "Mixed Platforms" then
mapped = sln.vstudio_configs[3].platform
else
mapped = cfg.platform
end
end
_p('\t\t{%s}.%s.ActiveCfg = %s|%s', prj.uuid, cfg.name, cfg.buildcfg, mapped)
if mapped == cfg.platform or cfg.platform == "Mixed Platforms" then
_p('\t\t{%s}.%s.Build.0 = %s|%s',  prj.uuid, cfg.name, cfg.buildcfg, mapped)
end
end
end
_p('\tEndGlobalSection')
end
function premake.vs2005_solution_properties(sln)
_p('\tGlobalSection(SolutionProperties) = preSolution')
_p('\t\tHideSolutionNode = FALSE')
_p('\tEndGlobalSection')
end
premake.vstudio.cs2005 = { }
local vstudio = premake.vstudio
local cs2005  = premake.vstudio.cs2005
local function getelements(prj, action, fname)
if action == "Compile" and fname:endswith(".cs") then
if fname:endswith(".Designer.cs") then
local basename = fname:sub(1, -13)
local testname = basename .. ".cs"
if premake.findfile(prj, testname) then
return "Dependency", testname
end
testname = basename .. ".resx"
if premake.findfile(prj, testname) then
return "AutoGen", testname
end
else
local basename = fname:sub(1, -4)
local testname = basename .. ".Designer.cs"
if premake.findfile(prj, testname) then
return "SubTypeForm"
end
end
end
if action == "EmbeddedResource" and fname:endswith(".resx") then
local basename = fname:sub(1, -6)
local testname = path.getname(basename .. ".cs")
if premake.findfile(prj, testname) then
if premake.findfile(prj, basename .. ".Designer.cs") then
return "DesignerType", testname
else
return "Dependency", testname
end
else
testname = path.getname(basename .. ".Designer.cs")
if premake.findfile(prj, testname) then
return "AutoGenerated"
end
end
end
if action == "Content" then
return "CopyNewest"
end
return "None"
end
function cs2005.projectelement(prj)
_p('', iif(_ACTION == 'vs2005', '', ' ToolsVersion="3.5"'))
end
function cs2005.projectsettings(prj)
_p('  ')
_p('    %s', premake.esc(prj.solution.configurations[1]))
_p('    AnyCPU')
_p('    %s', iif(_ACTION == "vs2005", "8.0.50727", "9.0.21022"))
_p('    2.0')
_p('    {%s}', prj.uuid)
_p('    %s', premake.dotnet.getkind(prj))
_p('    Properties')
_p('    %s', prj.buildtarget.basename)
_p('    %s', prj.buildtarget.basename)
if prj.framework then
_p('    v%s', prj.framework)
end
_p('  ')
end
function premake.vs2005_csproj(prj)
io.eol = "\r\n"
local vsversion, toolversion
if _ACTION == "vs2005" then
vsversion   = "8.0.50727"
toolversion = nil
elseif _ACTION == "vs2008" then
vsversion   = "9.0.21022"
toolversion = "3.5"
end
if toolversion then
_p('', toolversion)
else
_p('')
end
_p('  ')
_p('    %s', premake.esc(prj.solution.configurations[1]))
_p('    AnyCPU')
_p('    %s', vsversion)
_p('    2.0')
_p('    {%s}', prj.uuid)
_p('    %s', premake.dotnet.getkind(prj))
_p('    Properties')
_p('    %s', prj.buildtarget.basename)
_p('    %s', prj.buildtarget.basename)
_p('  ')
for cfg in premake.eachconfig(prj) do
_p('  ', premake.esc(cfg.name))
if cfg.flags.Symbols then
_p('    true')
_p('    full')
else
_p('    pdbonly')
end
_p('    %s', iif(cfg.flags.Optimize or cfg.flags.OptimizeSize or cfg.flags.OptimizeSpeed, "true", "false"))
_p('    %s', cfg.buildtarget.directory)
_p('    %s', table.concat(premake.esc(cfg.defines), ";"))
_p('    prompt')
_p('    4')
if cfg.flags.Unsafe then
_p('    true')
end
if cfg.flags.FatalWarnings then
_p('    true')
end
_p('  ')
end
_p('  ')
for _, ref in ipairs(premake.getlinks(prj, "siblings", "object")) do
_p('    ', path.translate(path.getrelative(prj.location, _VS.projectfile(ref)), "\\"))
_p('      {%s}', ref.uuid)
_p('      %s', premake.esc(ref.name))
_p('    ')
end
for _, linkname in ipairs(premake.getlinks(prj, "system", "basename")) do
_p('    ', premake.esc(linkname))
end
_p('  ')
_p('  ')
for fcfg in premake.eachfile(prj) do
local action = premake.dotnet.getbuildaction(fcfg)
local fname  = path.translate(premake.esc(fcfg.name), "\\")
local elements, dependency = getelements(prj, action, fcfg.name)
if elements == "None" then
_p('    <%s Include="%s" />', action, fname)
else
_p('    <%s Include="%s">', action, fname)
if elements == "AutoGen" then
_p('      True')
elseif elements == "AutoGenerated" then
_p('      Designer')
_p('      ResXFileCodeGenerator')
_p('      %s.Designer.cs', premake.esc(path.getbasename(fcfg.name)))
elseif elements == "SubTypeDesigner" then
_p('      Designer')
elseif elements == "SubTypeForm" then
_p('      Form')
elseif elements == "PreserveNewest" then
_p('      PreserveNewest')
end
if dependency then
_p('      %s', path.translate(premake.esc(dependency), "\\"))
end
_p('    ', action)
end
end
_p('  ')
_p('  ')
_p('  ')
_p('')
end
function premake.vs2005_csproj_user(prj)
io.eol = "\r\n"
_p('')
_p('  ')
local refpaths = table.translate(prj.libdirs, function(v) return path.getabsolute(prj.location .. "/" .. v) end)
_p('    %s', path.translate(table.concat(refpaths, ";"), "\\"))
_p('  ')
_p('')
end

local vs_format_version = function()
local t =
{
vs2005 = '9.00',
    vs2008 = '10.00',
    vs2010 = '11.00'
}
return t[_ACTION]
end
local vs_version = function()
local t =
{
vs2005 = '2005',
    vs2008 = '2008',
    vs2010 = '2010'
}
return t[_ACTION]
end
local vs_write_version_info = function()
_p('Microsoft Visual Studio Solution File, Format Version %s', vs_format_version())
_p('# Visual Studio %s', vs_version() )
end
local vs_write_projects = function(sln)
for prj in premake.solution.eachproject(sln) do
local projpath = path.translate(path.getrelative(sln.location, _VS.projectfile(prj)), "\\")
_p('Project("{%s}") = "%s", "%s", "{%s}"', _VS.tool(prj), prj.name, projpath, prj.uuid)
local deps = premake.getdependencies(prj)
if #deps > 0 then
_p('\tProjectSection(ProjectDependencies) = postProject')
for _, dep in ipairs(deps) do
_p('\t\t{%s} = {%s}', dep.uuid, dep.uuid)
end
_p('\tEndProjectSection')
end
_p('EndProject')
end
end
local vs_write_pre_version = function(sln)
io.eol = '\r\n'
sln.vstudio_configs = premake.vstudio_buildconfigs(sln)
_p('\239\187\191')
end
function premake.vs_generic_solution(sln)
vs_write_pre_version(sln)
vs_write_version_info()
vs_write_projects(sln)
_p('Global')
premake.vs2005_solution_platforms(sln)
premake.vs2005_solution_project_platforms(sln)
premake.vs2005_solution_properties(sln)
_p('EndGlobal')
end
premake.vstudio.vs10_helpers = { }
local vs10_helpers = premake.vstudio.vs10_helpers
function vs10_helpers.remove_relative_path(file)
file = file:gsub("%.%.\\",'')
file = file:gsub("%.\\",'')
return file
end
function vs10_helpers.file_path(file)
file = vs10_helpers.remove_relative_path(file)
local path = string.find(file,'\\[%w%.%_%-]+$')
if path then
return string.sub(file,1,path-1)
else
return nil
end
end
function vs10_helpers.list_of_directories_in_path(path)
local list={}
path = vs10_helpers.remove_relative_path(path)
if path then
for dir in string.gmatch(path,"[%w%-%_%.]+\\")do
if #list == 0 then
list[1] = dir:sub(1,#dir-1)
else
list[#list +1] = list[#list] .."\\" ..dir:sub(1,#dir-1)
end
end
end
return list
end
function vs10_helpers.table_of_file_filters(files)
local filters ={}
for _, valueTable in pairs(files) do
for _, entry in ipairs(valueTable) do
local result = vs10_helpers.list_of_directories_in_path(entry)
for __,dir in ipairs(result) do
if table.contains(filters,dir) ~= true then
filters[#filters +1] = dir
end
end
end
end
return filters
end
function vs10_helpers.get_file_extension(file)
local ext_start,ext_end = string.find(file,"%.[%w_%-]+$")
if ext_start then
return  string.sub(file,ext_start+1,ext_end)
end
end
function vs10_helpers.sort_input_files(files,sorted_container)
local types = 
{
h= "ClInclude",
hpp= "ClInclude",
hxx= "ClInclude",
c= "ClCompile",
cpp= "ClCompile",
cxx= "ClCompile",
cc= "ClCompile",
rc  = "ResourceCompile"
}
for _, current_file in ipairs(files) do
local translated_path = path.translate(current_file, '\\')
local ext = vs10_helpers.get_file_extension(translated_path)
if ext then
local type = types[ext]
if type then
table.insert(sorted_container[type],translated_path)
else
table.insert(sorted_container.None,translated_path)
end
end
end
end
local function vs2010_config(prj)
_p(1,'')
for _, cfginfo in ipairs(prj.solution.vstudio_configs) do
_p(2,'', premake.esc(cfginfo.name))
_p(3,'%s',cfginfo.buildcfg)
_p(3,'%s',cfginfo.platform)
_p(2,'')
end
_p(1,'')
end
local function vs2010_globals(prj)
_p(1,'')
_p(2,'{%s}',prj.uuid)
_p(2,'%s',prj.name)
_p(2,'Win32Proj')
_p(1,'')
end
function vs10_helpers.config_type(config)
local t =
{
SharedLib = "DynamicLibrary",
StaticLib = "StaticLibrary",
ConsoleApp = "Application",
WindowedApp = "Application"
}
return t[config.kind]
end
local function if_config_and_platform()
return 'Condition="\'$(Configuration)|$(Platform)\'==\'%s\'"'
end
local function optimisation(cfg)
local result = "Disabled"
for _, value in ipairs(cfg.flags) do
if (value == "Optimize") then
result = "Full"
elseif (value == "OptimizeSize") then
result = "MinSpace"
elseif (value == "OptimizeSpeed") then
result = "MaxSpeed"
end
end
return result
end
local function config_type_block(prj)
for _, cfginfo in ipairs(prj.solution.vstudio_configs) do
local cfg = premake.getconfig(prj, cfginfo.src_buildcfg, cfginfo.src_platform)
_p(1,''
, premake.esc(cfginfo.name))
_p(2,'%s',vs10_helpers.config_type(cfg))
_p(2,'%s',iif(cfg.flags.Unicode,"Unicode","MultiByte"))
if cfg.flags.MFC then
_p(2,'Dynamic')
end
local use_debug = "false"
if optimisation(cfg) == "Disabled" then 
use_debug = "true" 
else
_p(2,'true')
end
_p(2,'%s',use_debug)
_p(1,'')
end
end
local function import_props(prj)
for _, cfginfo in ipairs(prj.solution.vstudio_configs) do
local cfg = premake.getconfig(prj, cfginfo.src_buildcfg, cfginfo.src_platform)
_p(1,''
,premake.esc(cfginfo.name))
_p(2,'')
_p(1,'')
end
end
local function incremental_link(cfg,cfginfo)
if cfg.kind ~= "StaticLib" then
ShoudLinkIncrementally = 'false'
if optimisation(cfg) == "Disabled" then
ShoudLinkIncrementally = 'true'
end
_p(2,'%s'
,premake.esc(cfginfo.name),ShoudLinkIncrementally)
end
end
local function ignore_import_lib(cfg,cfginfo)
if cfg.kind == "SharedLib" then
local shouldIgnore = "false"
if cfg.flags.NoImportLib then shouldIgnore = "true" end
 _p(2,'%s'
,premake.esc(cfginfo.name),shouldIgnore)
end
end
local function intermediate_and_out_dirs(prj)
_p(1,'')
_p(2,'<_ProjectFileVersion>10.0.30319.1')
for _, cfginfo in ipairs(prj.solution.vstudio_configs) do
local cfg = premake.getconfig(prj, cfginfo.src_buildcfg, cfginfo.src_platform)
_p(2,'%s\\'
, premake.esc(cfginfo.name),premake.esc(cfg.buildtarget.directory) )
_p(2,'%s\\'
, premake.esc(cfginfo.name), premake.esc(cfg.objectsdir))
_p(2,'%s'
,premake.esc(cfginfo.name),path.getbasename(cfg.buildtarget.name))
ignore_import_lib(cfg,cfginfo)
incremental_link(cfg,cfginfo)
if cfg.flags.NoManifest then
_p(2,'false'
,premake.esc(cfginfo.name))
end
end
_p(1,'')
end
local function runtime(cfg)
local runtime
if premake.config.isdebugbuild(cfg) then
runtime = iif(cfg.flags.StaticRuntime,"MultiThreadedDebug", "MultiThreadedDebugDLL")
else
runtime = iif(cfg.flags.StaticRuntime, "MultiThreaded", "MultiThreadedDLL")
end
return runtime
end
local function precompiled_header(cfg)
      if not cfg.flags.NoPCH and cfg.pchheader then
_p(3,'Use')
_p(3,'%s', path.getname(cfg.pchheader))
else
_p(3,'')
end
end
local function preprocessor(indent,cfg)
if #cfg.defines > 0 then
_p(indent,'%s;%%(PreprocessorDefinitions)'
,premake.esc(table.concat(cfg.defines, ";")))
else
_p(indent,'')
end
end
local function include_dirs(indent,cfg)
if #cfg.includedirs > 0 then
_p(indent,'%s;%%(AdditionalIncludeDirectories)'
,premake.esc(path.translate(table.concat(cfg.includedirs, ";"), '\\')))
end
end
local function resource_compile(cfg)
_p(2,'')
preprocessor(3,cfg)
include_dirs(3,cfg)
_p(2,'')
end
local function exceptions(cfg)
if cfg.flags.NoExceptions then
_p(2,'false')
elseif cfg.flags.SEH then
_p(2,'Async')
end
end
local function rtti(cfg)
if cfg.flags.NoRTTI then
_p(3,'false')
end
end
local function wchar_t_buildin(cfg)
if cfg.flags.NativeWChar then
_p(3,'true')
elseif cfg.flags.NoNativeWChar then
_p(3,'false')
end
end
local function sse(cfg)
if cfg.flags.EnableSSE then
_p(3,'StreamingSIMDExtensions')
elseif cfg.flags.EnableSSE2 then
_p(3,'StreamingSIMDExtensions2')
end
end
local function floating_point(cfg)
     if cfg.flags.FloatFast then
_p(3,'Fast')
elseif cfg.flags.FloatStrict then
_p(3,'Strict')
end
end
local function debug_info(cfg)
local debug_info = ''
if cfg.flags.Symbols then
if optimisation(cfg) ~= "Disabled" or cfg.flags.NoEditAndContinue then
debug_info = "ProgramDatabase"
elseif cfg.platform ~= "x64" then
debug_info = "EditAndContinue"
else
debug_info = "OldStyle"
end
end
_p(3,'%s',debug_info)
end
local function minimal_build(cfg)
if premake.config.isdebugbuild(cfg) and not cfg.flags.NoMinimalRebuild then
_p(3,'true')
else
_p(3,'false')
end
end
local function compile_language(cfg)
if cfg.language == "C" then
_p(3,'CompileAsC')
end
end
local function vs10_clcompile(cfg)
_p(2,'')
if #cfg.buildoptions > 0 then
_p(3,'%s %%(AdditionalOptions)',
table.concat(premake.esc(cfg.buildoptions), " "))
end
_p(3,'%s',optimisation(cfg))
include_dirs(3,cfg)
preprocessor(3,cfg)
minimal_build(cfg)
if optimisation(cfg) == "Disabled" then
_p(3,'EnableFastChecks')
if cfg.flags.ExtraWarnings then
_p(3,'true')
end
else
_p(3,'true')
end
_p(3,'%s', runtime(cfg))
_p(3,'true')
precompiled_header(cfg)
if cfg.flags.ExtraWarnings then
_p(3,'Level4')
else
_p(3,'Level3')
end
if cfg.flags.FatalWarnings then
_p(3,'true')
end
exceptions(cfg)
rtti(cfg)
wchar_t_buildin(cfg)
sse(cfg)
floating_point(cfg)
debug_info(cfg)
if cfg.flags.NoFramePointer then
_p(3,'true')
end
compile_language(cfg)
_p(2,'')
end
local function event_hooks(cfg)
if #cfg.postbuildcommands> 0 then
    _p(2,'')
_p(3,'%s',premake.esc(table.implode(cfg.postbuildcommands, "", "", "\r\n")))
_p(2,'')
end
if #cfg.prebuildcommands> 0 then
    _p(2,'')
_p(3,'%s',premake.esc(table.implode(cfg.prebuildcommands, "", "", "\r\n")))
_p(2,'')
end
if #cfg.prelinkcommands> 0 then
    _p(2,'')
_p(3,'%s',premake.esc(table.implode(cfg.prelinkcommands, "", "", "\r\n")))
_p(2,'')
end
end
local function additional_options(indent,cfg)
if #cfg.linkoptions > 0 then
_p(indent,'%s %%(AdditionalOptions)',
table.concat(premake.esc(cfg.linkoptions), " "))
end
end
local function item_def_lib(cfg)
if cfg.kind == 'StaticLib' then
_p(1,'')
_p(2,'$(OutDir)%s',cfg.buildtarget.name)
additional_options(2,cfg)
_p(1,'')
end
end
local function link_target_machine(cfg)
local target
if cfg.platform == nil or cfg.platform == "x32" then target ="MachineX86"
elseif cfg.platform == "x64" then target ="MachineX64"
end
_p(3,'%s', target)
end
local function import_lib(cfg)
if cfg.kind == "SharedLib" then
local implibname = cfg.linktarget.fullpath
_p(3,'%s',iif(cfg.flags.NoImportLib, cfg.objectsdir .. "\\" .. path.getname(implibname), implibname))
end
end
local function common_link_section(cfg)
_p(3,'%s',iif(cfg.kind == "ConsoleApp","Console", "Windows"))
if cfg.flags.Symbols then 
_p(3,'true')
else
_p(3,'false')
end
if optimisation(cfg) ~= "Disabled" then
_p(3,'true')
_p(3,'true')
end
if cfg.flags.Symbols then
_p(3,'$(OutDir)%s.pdb'
, path.getbasename(cfg.buildtarget.name))
end
end
local function item_link(cfg)
_p(2,'')
if cfg.kind ~= 'StaticLib' then
if #cfg.links > 0 then
_p(3,'%s;%%(AdditionalDependencies)',
table.concat(premake.getlinks(cfg, "all", "fullpath"), ";"))
end
_p(3,'$(OutDir)%s', cfg.buildtarget.name)
_p(3,'%s%s%%(AdditionalLibraryDirectories)',
table.concat(premake.esc(path.translate(cfg.libdirs, '\\')) , ";"),
iif(cfg.libdirs and #cfg.libdirs >0,';',''))
common_link_section(cfg)
if vs10_helpers.config_type(cfg) == 'Application' and not cfg.flags.WinMain then
_p(3,'mainCRTStartup')
end
import_lib(cfg)
_p(3,'%s', iif(cfg.platform == "x64", "MachineX64", "MachineX86"))
additional_options(3,cfg)
else
common_link_section(cfg)
end
_p(2,'')
end
local function item_definitions(prj)
for _, cfginfo in ipairs(prj.solution.vstudio_configs) do
local cfg = premake.getconfig(prj, cfginfo.src_buildcfg, cfginfo.src_platform)
_p(1,''
,premake.esc(cfginfo.name))
vs10_clcompile(cfg)
resource_compile(cfg)
item_def_lib(cfg)
item_link(cfg)
event_hooks(cfg)
_p(1,'')
end
end
  --     
  --       {8fd826f8-3739-44e6-8cc8-997122e53b8d}
  --     
  --   
local function write_file_type_block(files,group_type)
if #files > 0  then
_p(1,'')
for _, current_file in ipairs(files) do
_p(2,'<%s Include=\"%s\" />', group_type,current_file)
end
_p(1,'')
end
end
local function write_file_compile_block(files,prj,configs)
if #files > 0  then
local config_mappings = {}
for _, cfginfo in ipairs(configs) do
local cfg = premake.getconfig(prj, cfginfo.src_buildcfg, cfginfo.src_platform)
if cfg.pchheader and cfg.pchsource and not cfg.flags.NoPCH then
config_mappings[cfginfo] = path.translate(cfg.pchsource, "\\")
end
end
_p(1,'')
for _, current_file in ipairs(files) do
_p(2,'', current_file)
for _, cfginfo in ipairs(configs) do
if config_mappings[cfginfo] and current_file == config_mappings[cfginfo] then 
_p(3,'Create'
,premake.esc(cfginfo.name))
config_mappings[cfginfo] = nil
_p(2,'')
end
end
_p(2,'')
end
_p(1,'')
end
end
local function vcxproj_files(prj)
local sorted =
{
ClCompile={},
ClInclude={},
None={},
ResourceCompile ={}
}
cfg = premake.getconfig(prj)
vs10_helpers.sort_input_files(cfg.files,sorted)
write_file_type_block(sorted.ClInclude,"ClInclude")
write_file_compile_block(sorted.ClCompile,prj,prj.solution.vstudio_configs)
write_file_type_block(sorted.None,'None')
write_file_type_block(sorted.ResourceCompile,'ResourceCompile')
end
local function write_filter_includes(sorted_table)
local directories = vs10_helpers.table_of_file_filters(sorted_table)
if #directories >0 then
_p(1,'')
for _, dir in pairs(directories) do
_p(2,'',dir)
_p(3,'{%s}',os.uuid())
_p(2,'')
end
_p(1,'')
end
end
local function write_file_filter_block(files,group_type)
if #files > 0  then
_p(1,'')
for _, current_file in ipairs(files) do
local path_to_file = vs10_helpers.file_path(current_file)
if path_to_file then
_p(2,'<%s Include=\"%s\">', group_type,path.translate(current_file, "\\"))
_p(3,'%s',path_to_file)
_p(2,'',group_type)
else
_p(2,'<%s Include=\"%s\" />', group_type,path.translate(current_file, "\\"))
end
end
_p(1,'')
end
end
local tool_version_and_xmlns = 'ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"'
local xml_version_and_encoding = ''
local function vcxproj_filter_files(prj)
local sorted =
{
ClCompile={},
ClInclude={},
None={},
ResourceCompile ={}
}
cfg = premake.getconfig(prj)
vs10_helpers.sort_input_files(cfg.files,sorted)
io.eol = "\r\n"
_p(xml_version_and_encoding)
_p('')
write_filter_includes(sorted)
write_file_filter_block(sorted.ClInclude,"ClInclude")
write_file_filter_block(sorted.ClCompile,"ClCompile")
write_file_filter_block(sorted.None,"None")
write_file_filter_block(sorted.ResourceCompile,"ResourceCompile")
_p('')
end
function premake.vs2010_vcxproj(prj)
io.eol = "\r\n"
_p(xml_version_and_encoding)
_p('')
vs2010_config(prj)
vs2010_globals(prj)
_p(1,'')
config_type_block(prj)
_p(1,'')
_p(1,'')
_p(1,'')
import_props(prj)
_p(1,'')
intermediate_and_out_dirs(prj)
item_definitions(prj)
vcxproj_files(prj)
_p(1,'')
_p(1,'')
_p(1,'')
_p('')
end
function premake.vs2010_vcxproj_user(prj)
_p(xml_version_and_encoding)
_p('')
_p('')
end
function premake.vs2010_vcxproj_filters(prj)
vcxproj_filter_files(prj)
end
premake.xcode = { }
newaction 
{
trigger         = "xcode3",
shortname       = "Xcode 3",
description     = "Generate Apple Xcode 3 project files (experimental)",
os              = "macosx",
valid_kinds     = { "ConsoleApp", "WindowedApp", "SharedLib", "StaticLib" },
valid_languages = { "C", "C++" },
valid_tools     = {
cc     = { "gcc" },
},
valid_platforms = { 
Native = "Native", 
x32 = "Native 32-bit", 
x64 = "Native 64-bit", 
Universal32 = "32-bit Universal", 
Universal64 = "64-bit Universal", 
Universal = "Universal",
},
default_platform = "Universal",
onsolution = function(sln)
premake.xcode.preparesolution(sln)
end,
onproject = function(prj)
premake.generate(prj, "%%.xcodeproj/project.pbxproj", premake.xcode.project)
end,
oncleanproject = function(prj)
premake.clean.directory(prj, "%%.xcodeproj")
end,
oncheckproject = function(prj)
local last
for cfg in premake.eachconfig(prj) do
if last and last ~= cfg.kind then
error("Project '" .. prj.name .. "' uses more than one target kind; not supported by Xcode", 0)
end
last = cfg.kind
end
end,
}
local xcode = premake.xcode
local tree  = premake.tree
function xcode.getbuildcategory(node)
local categories = {
[".a"] = "Frameworks",
[".c"] = "Sources",
[".cc"] = "Sources",
[".cpp"] = "Sources",
[".cxx"] = "Sources",
[".dylib"] = "Frameworks",
[".framework"] = "Frameworks",
[".m"] = "Sources",
[".mm"] = "Sources",
[".strings"] = "Resources",
[".nib"] = "Resources",
[".xib"] = "Resources",
[".icns"] = "Resources",
}
return categories[path.getextension(node.name)]
end
function xcode.getconfigname(cfg)
local name = cfg.name
if #cfg.project.solution.xcode.platforms > 1 then
name = name .. " " .. premake.action.current().valid_platforms[cfg.platform]
end
return name
end
function xcode.getfiletype(node)
local types = {
[".c"]         = "sourcecode.c.c",
[".cc"]        = "sourcecode.cpp.cpp",
[".cpp"]       = "sourcecode.cpp.cpp",
[".css"]       = "text.css",
[".cxx"]       = "sourcecode.cpp.cpp",
[".framework"] = "wrapper.framework",
[".gif"]       = "image.gif",
[".h"]         = "sourcecode.c.h",
[".html"]      = "text.html",
[".lua"]       = "sourcecode.lua",
[".m"]         = "sourcecode.c.objc",
[".mm"]        = "sourcecode.cpp.objc",
[".nib"]       = "wrapper.nib",
[".pch"]       = "sourcecode.c.h",
[".plist"]     = "text.plist.xml",
[".strings"]   = "text.plist.strings",
[".xib"]       = "file.xib",
[".icns"]      = "image.icns",
}
return types[path.getextension(node.path)] or "text"
end
function xcode.getproducttype(node)
local types = {
ConsoleApp  = "com.apple.product-type.tool",
WindowedApp = "com.apple.product-type.application",
StaticLib   = "com.apple.product-type.library.static",
SharedLib   = "com.apple.product-type.library.dynamic",
}
return types[node.cfg.kind]
end
function xcode.gettargettype(node)
local types = {
ConsoleApp  = "\"compiled.mach-o.executable\"",
WindowedApp = "wrapper.application",
StaticLib   = "archive.ar",
SharedLib   = "\"compiled.mach-o.dylib\"",
}
return types[node.cfg.kind]
end
function xcode.getxcodeprojname(prj)
local fname = premake.project.getfilename(prj, "%%.xcodeproj")
return fname
end
function xcode.isframework(fname)
return (path.getextension(fname) == ".framework")
end
function xcode.newid()
return string.format("%04X%04X%04X%04X%04X%04X",
math.random(0, 32767),
math.random(0, 32767),
math.random(0, 32767),
math.random(0, 32767),
math.random(0, 32767),
math.random(0, 32767))
end
function xcode.preparesolution(sln)
sln.xcode = { }
sln.xcode.platforms = premake.filterplatforms(sln, premake.action.current().valid_platforms, "Universal")
for prj in premake.solution.eachproject(sln) do
local cfg = premake.getconfig(prj, prj.configurations[1], sln.xcode.platforms[1])
local node = premake.tree.new(path.getname(cfg.buildtarget.bundlepath))
node.cfg = cfg
node.id = premake.xcode.newid(node, "product")
node.targetid = premake.xcode.newid(node, "target")
prj.xcode = {}
prj.xcode.projectnode = node
end
end
function xcode.printlist(list, tag)
if #list > 0 then
_p(4,'%s = (', tag)
for _, item in ipairs(list) do
_p(5, '"%s",', item)
end
_p(4,');')
end
end
function xcode.Header()
_p('// !$*UTF8*$!')
_p('{')
_p(1,'archiveVersion = 1;')
_p(1,'classes = {')
_p(1,'};')
_p(1,'objectVersion = 45;')
_p(1,'objects = {')
_p('')
end
function xcode.PBXBuildFile(tr)
_p('/* Begin PBXBuildFile section */')
tree.traverse(tr, {
onnode = function(node)
if node.buildid then
_p(2,'%s /* %s in %s */ = {isa = PBXBuildFile; fileRef = %s /* %s */; };', 
node.buildid, node.name, xcode.getbuildcategory(node), node.id, node.name)
end
end
})
_p('/* End PBXBuildFile section */')
_p('')
end
function xcode.PBXContainerItemProxy(tr)
if #tr.projects.children > 0 then
_p('/* Begin PBXContainerItemProxy section */')
for _, node in ipairs(tr.projects.children) do
_p(2,'%s /* PBXContainerItemProxy */ = {', node.productproxyid)
_p(3,'isa = PBXContainerItemProxy;')
_p(3,'containerPortal = %s /* %s */;', node.id, path.getname(node.path))
_p(3,'proxyType = 2;')
_p(3,'remoteGlobalIDString = %s;', node.project.xcode.projectnode.id)
_p(3,'remoteInfo = "%s";', node.project.xcode.projectnode.name)
_p(2,'};')
_p(2,'%s /* PBXContainerItemProxy */ = {', node.targetproxyid)
_p(3,'isa = PBXContainerItemProxy;')
_p(3,'containerPortal = %s /* %s */;', node.id, path.getname(node.path))
_p(3,'proxyType = 1;')
_p(3,'remoteGlobalIDString = %s;', node.project.xcode.projectnode.targetid)
_p(3,'remoteInfo = "%s";', node.project.xcode.projectnode.name)
_p(2,'};')
end
_p('/* End PBXContainerItemProxy section */')
_p('')
end
end
function xcode.PBXFileReference(tr)
_p('/* Begin PBXFileReference section */')
tree.traverse(tr, {
onleaf = function(node)
if not node.path then
return
end
if node.kind == "product" then
_p(2,'%s /* %s */ = {isa = PBXFileReference; explicitFileType = %s; includeInIndex = 0; name = "%s"; path = "%s"; sourceTree = BUILT_PRODUCTS_DIR; };',
node.id, node.name, xcode.gettargettype(node), node.name, path.getname(node.cfg.buildtarget.bundlepath))
elseif node.parent.parent == tr.projects then
local relpath = path.getrelative(tr.project.location, node.parent.project.location)
_p(2,'%s /* %s */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "%s"; path = "%s"; sourceTree = SOURCE_ROOT; };',
node.parent.id, node.parent.name, node.parent.name, path.join(relpath, node.parent.name))
else
local pth, src
if xcode.isframework(node.path) then
pth = "/System/Library/Frameworks/" .. node.path
src = "absolute"
else
pth = tree.getlocalpath(node)
src = "group"
end
_p(2,'%s /* %s */ = {isa = PBXFileReference; lastKnownFileType = %s; name = "%s"; path = "%s"; sourceTree = "<%s>"; };',
node.id, node.name, xcode.getfiletype(node), node.name, pth, src)
end
end
})
_p('/* End PBXFileReference section */')
_p('')
end
function xcode.PBXFrameworksBuildPhase(tr)
_p('/* Begin PBXFrameworksBuildPhase section */')
_p(2,'%s /* Frameworks */ = {', tr.products.children[1].fxstageid)
_p(3,'isa = PBXFrameworksBuildPhase;')
_p(3,'buildActionMask = 2147483647;')
_p(3,'files = (')
tree.traverse(tr.frameworks, {
onleaf = function(node)
_p(4,'%s /* %s in Frameworks */,', node.buildid, node.name)
end
})
tree.traverse(tr.projects, {
onleaf = function(node)
_p(4,'%s /* %s in Frameworks */,', node.buildid, node.name)
end
})
_p(3,');')
_p(3,'runOnlyForDeploymentPostprocessing = 0;')
_p(2,'};')
_p('/* End PBXFrameworksBuildPhase section */')
_p('')
end
function xcode.PBXGroup(tr)
_p('/* Begin PBXGroup section */')
tree.traverse(tr, {
onnode = function(node)
if (node.path and #node.children == 0) or node.kind == "vgroup" then
return
end
if node.parent == tr.projects then
_p(2,'%s /* Products */ = {', node.productgroupid)
else
_p(2,'%s /* %s */ = {', node.id, node.name)
end
_p(3,'isa = PBXGroup;')
_p(3,'children = (')
for _, childnode in ipairs(node.children) do
_p(4,'%s /* %s */,', childnode.id, childnode.name)
end
_p(3,');')
if node.parent == tr.projects then
_p(3,'name = Products;')
else
_p(3,'name = "%s";', node.name)
if node.path then
local p = node.path
if node.parent.path then
p = path.getrelative(node.parent.path, node.path)
end
_p(3,'path = %s;', p)
end
end
_p(3,'sourceTree = "";')
_p(2,'};')
end
}, true)
_p('/* End PBXGroup section */')
_p('')
end
function xcode.PBXNativeTarget(tr)
_p('/* Begin PBXNativeTarget section */')
for _, node in ipairs(tr.products.children) do
local name = tr.project.name
_p(2,'%s /* %s */ = {', node.targetid, name)
_p(3,'isa = PBXNativeTarget;')
_p(3,'buildConfigurationList = %s /* Build configuration list for PBXNativeTarget "%s" */;', node.cfgsection, name)
_p(3,'buildPhases = (')
if #tr.project.prebuildcommands > 0 then
_p(4,'9607AE1010C857E500CD1376 /* Prebuild */,')
end
_p(4,'%s /* Resources */,', node.resstageid)
_p(4,'%s /* Sources */,', node.sourcesid)
if #tr.project.prelinkcommands > 0 then
_p(4,'9607AE3510C85E7E00CD1376 /* Prelink */,')
end
_p(4,'%s /* Frameworks */,', node.fxstageid)
if #tr.project.postbuildcommands > 0 then
_p(4,'9607AE3710C85E8F00CD1376 /* Postbuild */,')
end
_p(3,');')
_p(3,'buildRules = (')
_p(3,');')
_p(3,'dependencies = (')
for _, node in ipairs(tr.projects.children) do
_p(4,'%s /* PBXTargetDependency */,', node.targetdependid)
end
_p(3,');')
_p(3,'name = "%s";', name)
local p
if node.cfg.kind == "ConsoleApp" then
p = "$(HOME)/bin"
elseif node.cfg.kind == "WindowedApp" then
p = "$(HOME)/Applications"
end
if p then
_p(3,'productInstallPath = "%s";', p)
end
_p(3,'productName = "%s";', name)
_p(3,'productReference = %s /* %s */;', node.id, node.name)
_p(3,'productType = "%s";', xcode.getproducttype(node))
_p(2,'};')
end
_p('/* End PBXNativeTarget section */')
_p('')
end
function xcode.PBXProject(tr)
_p('/* Begin PBXProject section */')
_p(2,'08FB7793FE84155DC02AAC07 /* Project object */ = {')
_p(3,'isa = PBXProject;')
_p(3,'buildConfigurationList = 1DEB928908733DD80010E9CD /* Build configuration list for PBXProject "%s" */;', tr.name)
_p(3,'compatibilityVersion = "Xcode 3.1";')
_p(3,'hasScannedForEncodings = 1;')
_p(3,'mainGroup = %s /* %s */;', tr.id, tr.name)
_p(3,'projectDirPath = "";')
if #tr.projects.children > 0 then
_p(3,'projectReferences = (')
for _, node in ipairs(tr.projects.children) do
_p(4,'{')
_p(5,'ProductGroup = %s /* Products */;', node.productgroupid)
_p(5,'ProjectRef = %s /* %s */;', node.id, path.getname(node.path))
_p(4,'},')
end
_p(3,');')
end
_p(3,'projectRoot = "";')
_p(3,'targets = (')
for _, node in ipairs(tr.products.children) do
_p(4,'%s /* %s */,', node.targetid, node.name)
end
_p(3,');')
_p(2,'};')
_p('/* End PBXProject section */')
_p('')
end
function xcode.PBXReferenceProxy(tr)
if #tr.projects.children > 0 then
_p('/* Begin PBXReferenceProxy section */')
tree.traverse(tr.projects, {
onleaf = function(node)
_p(2,'%s /* %s */ = {', node.id, node.name)
_p(3,'isa = PBXReferenceProxy;')
_p(3,'fileType = %s;', xcode.gettargettype(node))
_p(3,'path = "%s";', node.path)
_p(3,'remoteRef = %s /* PBXContainerItemProxy */;', node.parent.productproxyid)
_p(3,'sourceTree = BUILT_PRODUCTS_DIR;')
_p(2,'};')
end
})
_p('/* End PBXReferenceProxy section */')
_p('')
end
end
function xcode.PBXResourcesBuildPhase(tr)
_p('/* Begin PBXResourcesBuildPhase section */')
for _, target in ipairs(tr.products.children) do
_p(2,'%s /* Resources */ = {', target.resstageid)
_p(3,'isa = PBXResourcesBuildPhase;')
_p(3,'buildActionMask = 2147483647;')
_p(3,'files = (')
tree.traverse(tr, {
onnode = function(node)
if xcode.getbuildcategory(node) == "Resources" then
_p(4,'%s /* %s in Resources */,', node.buildid, node.name)
end
end
})
_p(3,');')
_p(3,'runOnlyForDeploymentPostprocessing = 0;')
_p(2,'};')
end
_p('/* End PBXResourcesBuildPhase section */')
_p('')
end
function xcode.PBXShellScriptBuildPhase(tr)
local wrapperWritten = false
local function doblock(id, name, which)
local prjcmds = tr.project[which]
local commands = table.join(prjcmds, {})
for _, cfg in ipairs(tr.configs) do
local cfgcmds = cfg[which]
if #cfgcmds > #prjcmds then
table.insert(commands, 'if [ "${CONFIGURATION}" = "' .. xcode.getconfigname(cfg) .. '" ]; then')
for i = #prjcmds + 1, #cfgcmds do
table.insert(commands, cfgcmds[i])
end
table.insert(commands, 'fi')
end
end
if #commands > 0 then
if not wrapperWritten then
_p('/* Begin PBXShellScriptBuildPhase section */')
wrapperWritten = true
end
_p(2,'%s /* %s */ = {', id, name)
_p(3,'isa = PBXShellScriptBuildPhase;')
_p(3,'buildActionMask = 2147483647;')
_p(3,'files = (')
_p(3,');')
_p(3,'inputPaths = (');
_p(3,');');
_p(3,'name = %s;', name);
_p(3,'outputPaths = (');
_p(3,');');
_p(3,'runOnlyForDeploymentPostprocessing = 0;');
_p(3,'shellPath = /bin/sh;');
_p(3,'shellScript = "%s";', table.concat(commands, "\\n"):gsub('"', '\\"'))
_p(2,'};')
end
end
doblock("9607AE1010C857E500CD1376", "Prebuild", "prebuildcommands")
doblock("9607AE3510C85E7E00CD1376", "Prelink", "prelinkcommands")
doblock("9607AE3710C85E8F00CD1376", "Postbuild", "postbuildcommands")
if wrapperWritten then
_p('/* End PBXShellScriptBuildPhase section */')
end
end
function xcode.PBXSourcesBuildPhase(tr)
_p('/* Begin PBXSourcesBuildPhase section */')
for _, target in ipairs(tr.products.children) do
_p(2,'%s /* Sources */ = {', target.sourcesid)
_p(3,'isa = PBXSourcesBuildPhase;')
_p(3,'buildActionMask = 2147483647;')
_p(3,'files = (')
tree.traverse(tr, {
onleaf = function(node)
if xcode.getbuildcategory(node) == "Sources" then
_p(4,'%s /* %s in Sources */,', node.buildid, node.name)
end
end
})
_p(3,');')
_p(3,'runOnlyForDeploymentPostprocessing = 0;')
_p(2,'};')
end
_p('/* End PBXSourcesBuildPhase section */')
_p('')
end
function xcode.PBXVariantGroup(tr)
_p('/* Begin PBXVariantGroup section */')
tree.traverse(tr, {
onbranch = function(node)
if node.kind == "vgroup" then
_p(2,'%s /* %s */ = {', node.id, node.name)
_p(3,'isa = PBXVariantGroup;')
_p(3,'children = (')
for _, lang in ipairs(node.children) do
_p(4,'%s /* %s */,', lang.id, lang.name)
end
_p(3,');')
_p(3,'name = %s;', node.name)
_p(3,'sourceTree = "";')
_p(2,'};')
end
end
})
_p('/* End PBXVariantGroup section */')
_p('')
end
function xcode.PBXTargetDependency(tr)
if #tr.projects.children > 0 then
_p('/* Begin PBXTargetDependency section */')
tree.traverse(tr.projects, {
onleaf = function(node)
_p(2,'%s /* PBXTargetDependency */ = {', node.parent.targetdependid)
_p(3,'isa = PBXTargetDependency;')
_p(3,'name = "%s";', node.name)
_p(3,'targetProxy = %s /* PBXContainerItemProxy */;', node.parent.targetproxyid)
_p(2,'};')
end
})
_p('/* End PBXTargetDependency section */')
_p('')
end
end
function xcode.XCBuildConfiguration_Target(tr, target, cfg)
local cfgname = xcode.getconfigname(cfg)
_p(2,'%s /* %s */ = {', cfg.xcode.targetid, cfgname)
_p(3,'isa = XCBuildConfiguration;')
_p(3,'buildSettings = {')
_p(4,'ALWAYS_SEARCH_USER_PATHS = NO;')
if not cfg.flags.Symbols then
_p(4,'DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";')
end
if cfg.kind ~= "StaticLib" and cfg.buildtarget.prefix ~= "" then
_p(4,'EXECUTABLE_PREFIX = %s;', cfg.buildtarget.prefix)
end
local outdir = path.getdirectory(cfg.buildtarget.bundlepath)
if outdir ~= "." then
_p(4,'CONFIGURATION_BUILD_DIR = %s;', outdir)
end
_p(4,'GCC_DYNAMIC_NO_PIC = NO;')
_p(4,'GCC_MODEL_TUNING = G5;')
if tr.infoplist then
_p(4,'INFOPLIST_FILE = "%s";', tr.infoplist.path)
end
installpaths = {
ConsoleApp = '/usr/local/bin',
WindowedApp = '"$(HOME)/Applications"',
SharedLib = '/usr/local/lib',
StaticLib = '/usr/local/lib',
}
_p(4,'INSTALL_PATH = %s;', installpaths[cfg.kind])
_p(4,'PRODUCT_NAME = "%s";', cfg.buildtarget.basename)
_p(3,'};')
_p(3,'name = "%s";', cfgname)
_p(2,'};')
end
function xcode.XCBuildConfiguration_Project(tr, cfg)
local cfgname = xcode.getconfigname(cfg)
_p(2,'%s /* %s */ = {', cfg.xcode.projectid, cfgname)
_p(3,'isa = XCBuildConfiguration;')
_p(3,'buildSettings = {')
local archs = {
Native = "$(NATIVE_ARCH_ACTUAL)",
x32    = "i386",
x64    = "x86_64",
Universal32 = "$(ARCHS_STANDARD_32_BIT)",
Universal64 = "$(ARCHS_STANDARD_64_BIT)",
Universal = "$(ARCHS_STANDARD_32_64_BIT)",
}
_p(4,'ARCHS = "%s";', archs[cfg.platform])
local targetdir = path.getdirectory(cfg.buildtarget.bundlepath)
if targetdir ~= "." then
_p(4,'CONFIGURATION_BUILD_DIR = "$(SYMROOT)";');
end
_p(4,'CONFIGURATION_TEMP_DIR = "$(OBJROOT)";')
if cfg.flags.Symbols then
_p(4,'COPY_PHASE_STRIP = NO;')
end
_p(4,'GCC_C_LANGUAGE_STANDARD = gnu99;')
if cfg.flags.NoExceptions then
_p(4,'GCC_ENABLE_CPP_EXCEPTIONS = NO;')
end
if cfg.flags.NoRTTI then
_p(4,'GCC_ENABLE_CPP_RTTI = NO;')
end
if cfg.flags.Symbols and not cfg.flags.NoEditAndContinue then
_p(4,'GCC_ENABLE_FIX_AND_CONTINUE = YES;')
end
if cfg.flags.NoExceptions then
_p(4,'GCC_ENABLE_OBJC_EXCEPTIONS = NO;')
end
if cfg.flags.Optimize or cfg.flags.OptimizeSize then
_p(4,'GCC_OPTIMIZATION_LEVEL = s;')
elseif cfg.flags.OptimizeSpeed then
_p(4,'GCC_OPTIMIZATION_LEVEL = 3;')
else
_p(4,'GCC_OPTIMIZATION_LEVEL = 0;')
end
if cfg.pchheader and not cfg.flags.NoPCH then
_p(4,'GCC_PRECOMPILE_PREFIX_HEADER = YES;')
_p(4,'GCC_PREFIX_HEADER = "%s";', cfg.pchheader)
end
xcode.printlist(cfg.defines, 'GCC_PREPROCESSOR_DEFINITIONS')
if cfg.flags.FatalWarnings then
_p(4,'GCC_TREAT_WARNINGS_AS_ERRORS = YES;')
end
_p(4,'GCC_WARN_ABOUT_RETURN_TYPE = YES;')
_p(4,'GCC_WARN_UNUSED_VARIABLE = YES;')
xcode.printlist(cfg.includedirs, 'HEADER_SEARCH_PATHS')
xcode.printlist(cfg.libdirs, 'LIBRARY_SEARCH_PATHS')
_p(4,'OBJROOT = "%s";', cfg.objectsdir)
_p(4,'ONLY_ACTIVE_ARCH = NO;')
local checks = {
["-ffast-math"]          = cfg.flags.FloatFast,
["-ffloat-store"]        = cfg.flags.FloatStrict,
["-fomit-frame-pointer"] = cfg.flags.NoFramePointer,
}
local flags = { }
for flag, check in pairs(checks) do
if check then
table.insert(flags, flag)
end
end
xcode.printlist(table.join(flags, cfg.buildoptions), 'OTHER_CFLAGS')
flags = { }
for _, lib in ipairs(premake.getlinks(cfg, "system")) do
if not xcode.isframework(lib) then
table.insert(flags, "-l" .. lib)
end
end
flags = table.join(flags, cfg.linkoptions)
xcode.printlist(flags, 'OTHER_LDFLAGS')
_p(4,'PREBINDING = NO;')
if cfg.flags.StaticRuntime then
_p(4,'STANDARD_C_PLUS_PLUS_LIBRARY_TYPE = static;')
end
if targetdir ~= "." then
_p(4,'SYMROOT = "%s";', targetdir)
end
if cfg.flags.ExtraWarnings then
_p(4,'WARNING_CFLAGS = "-Wall";')
end
_p(3,'};')
_p(3,'name = "%s";', cfgname)
_p(2,'};')
end
function xcode.XCBuildConfiguration(tr)
_p('/* Begin XCBuildConfiguration section */')
for _, target in ipairs(tr.products.children) do
for _, cfg in ipairs(tr.configs) do
xcode.XCBuildConfiguration_Target(tr, target, cfg)
end
end
for _, cfg in ipairs(tr.configs) do
xcode.XCBuildConfiguration_Project(tr, cfg)
end
_p('/* End XCBuildConfiguration section */')
_p('')
end
function xcode.XCBuildConfigurationList(tr)
local sln = tr.project.solution
_p('/* Begin XCConfigurationList section */')
for _, target in ipairs(tr.products.children) do
_p(2,'%s /* Build configuration list for PBXNativeTarget "%s" */ = {', target.cfgsection, target.name)
_p(3,'isa = XCConfigurationList;')
_p(3,'buildConfigurations = (')
for _, cfg in ipairs(tr.configs) do
_p(4,'%s /* %s */,', cfg.xcode.targetid, xcode.getconfigname(cfg))
end
_p(3,');')
_p(3,'defaultConfigurationIsVisible = 0;')
_p(3,'defaultConfigurationName = "%s";', xcode.getconfigname(tr.configs[1]))
_p(2,'};')
end
_p(2,'1DEB928908733DD80010E9CD /* Build configuration list for PBXProject "%s" */ = {', tr.name)
_p(3,'isa = XCConfigurationList;')
_p(3,'buildConfigurations = (')
for _, cfg in ipairs(tr.configs) do
_p(4,'%s /* %s */,', cfg.xcode.projectid, xcode.getconfigname(cfg))
end
_p(3,');')
_p(3,'defaultConfigurationIsVisible = 0;')
_p(3,'defaultConfigurationName = "%s";', xcode.getconfigname(tr.configs[1]))
_p(2,'};')
_p('/* End XCConfigurationList section */')
_p('')
end
function xcode.Footer()
_p(1,'};')
_p('\trootObject = 08FB7793FE84155DC02AAC07 /* Project object */;')
_p('}')
end
local xcode = premake.xcode
local tree = premake.tree
function xcode.buildprjtree(prj)
local tr = premake.project.buildsourcetree(prj)
tr.configs = {}
for _, cfgname in ipairs(prj.solution.configurations) do
for _, platform in ipairs(prj.solution.xcode.platforms) do
local cfg = premake.getconfig(prj, cfgname, platform)
cfg.xcode = {}
cfg.xcode.targetid = xcode.newid(prj.xcode.projectnode, cfgname)
cfg.xcode.projectid = xcode.newid(tr, cfgname)
table.insert(tr.configs, cfg)
end
end
tree.traverse(tr, {
onbranch = function(node)
if path.getextension(node.name) == ".lproj" then
local lang = path.getbasename(node.name)  -- "English", "French", etc.
for _, filenode in ipairs(node.children) do
local grpnode = node.parent.children[filenode.name]
if not grpnode then
grpnode = tree.insert(node.parent, tree.new(filenode.name))
grpnode.kind = "vgroup"
end
filenode.name = path.getbasename(lang)
tree.insert(grpnode, filenode)
end
tree.remove(node)
end
end
})
tr.frameworks = tree.new("Frameworks")
for cfg in premake.eachconfig(prj) do
for _, link in ipairs(premake.getlinks(cfg, "system", "fullpath")) do
local name = path.getname(link)
if xcode.isframework(name) and not tr.frameworks.children[name] then
node = tree.insert(tr.frameworks, tree.new(name))
node.path = link
end
end
end
if #tr.frameworks.children > 0 then 
tree.insert(tr, tr.frameworks)
end
tr.products = tree.insert(tr, tree.new("Products"))
tr.projects = tree.new("Projects")
for _, dep in ipairs(premake.getdependencies(prj, "sibling", "object")) do
local xcpath = xcode.getxcodeprojname(dep)
local xcnode = tree.insert(tr.projects, tree.new(path.getname(xcpath)))
xcnode.path = xcpath
xcnode.project = dep
xcnode.productgroupid = xcode.newid(xcnode, "prodgrp")
xcnode.productproxyid = xcode.newid(xcnode, "prodprox")
xcnode.targetproxyid  = xcode.newid(xcnode, "targprox")
xcnode.targetdependid = xcode.newid(xcnode, "targdep")
local cfg = premake.getconfig(dep, prj.configurations[1])
node = tree.insert(xcnode, tree.new(cfg.linktarget.name))
node.path = cfg.linktarget.fullpath
node.cfg = cfg
end
if #tr.projects.children > 0 then
tree.insert(tr, tr.projects)
end
tree.traverse(tr, {
onnode = function(node)
node.id = xcode.newid(node)
if xcode.getbuildcategory(node) then
node.buildid = xcode.newid(node, "build")
end
if string.endswith(node.name, "Info.plist") then
tr.infoplist = node
end
end
}, true)
node = tree.insert(tr.products, prj.xcode.projectnode)
node.kind = "product"
node.path = node.cfg.buildtarget.fullpath
node.cfgsection = xcode.newid(node, "cfg")
node.resstageid = xcode.newid(node, "rez")
node.sourcesid  = xcode.newid(node, "src")
node.fxstageid  = xcode.newid(node, "fxs")
return tr
end
function premake.xcode.project(prj)
local tr = xcode.buildprjtree(prj)
xcode.Header(tr)
xcode.PBXBuildFile(tr)
xcode.PBXContainerItemProxy(tr)
xcode.PBXFileReference(tr)
xcode.PBXFrameworksBuildPhase(tr)
xcode.PBXGroup(tr)
xcode.PBXNativeTarget(tr)
xcode.PBXProject(tr)
xcode.PBXReferenceProxy(tr)
xcode.PBXResourcesBuildPhase(tr)
xcode.PBXShellScriptBuildPhase(tr)
xcode.PBXSourcesBuildPhase(tr)
xcode.PBXVariantGroup(tr)
xcode.PBXTargetDependency(tr)
xcode.XCBuildConfiguration(tr)
xcode.XCBuildConfigurationList(tr)
xcode.Footer(tr)
end
premake.clean = { }
function premake.clean.directory(obj, pattern)
local fname = premake.project.getfilename(obj, pattern)
os.rmdir(fname)
end
function premake.clean.file(obj, pattern)
local fname = premake.project.getfilename(obj, pattern)
os.remove(fname)
end
newaction {
trigger     = "clean",
description = "Remove all binaries and generated files",
onsolution = function(sln)
for action in premake.action.each() do
if action.oncleansolution then
action.oncleansolution(sln)
end
end
end,
onproject = function(prj)
for action in premake.action.each() do
if action.oncleanproject then
action.oncleanproject(prj)
end
end
if (prj.objectsdir) then
premake.clean.directory(prj, prj.objectsdir)
end
local platforms = prj.solution.platforms or { }
if not table.contains(platforms, "Native") then
platforms = table.join(platforms, { "Native" })
end
for _, platform in ipairs(platforms) do
for cfg in premake.eachconfig(prj, platform) do
premake.clean.directory(prj, cfg.objectsdir)
premake.clean.file(prj, premake.gettarget(cfg, "build", "posix", "windows", "windows").fullpath)
premake.clean.file(prj, premake.gettarget(cfg, "build", "posix", "posix", "linux").fullpath)
premake.clean.file(prj, premake.gettarget(cfg, "build", "posix", "posix", "macosx").fullpath)
premake.clean.file(prj, premake.gettarget(cfg, "build", "posix", "PS3", "windows").fullpath)
if cfg.kind == "WindowedApp" then
premake.clean.directory(prj, premake.gettarget(cfg, "build", "posix", "posix", "linux").fullpath .. ".app")
end
premake.clean.file(prj, premake.gettarget(cfg, "link", "windows", "windows", "windows").fullpath)
premake.clean.file(prj, premake.gettarget(cfg, "link", "posix", "posix", "linux").fullpath)
local target = path.join(premake.project.getfilename(prj, cfg.buildtarget.directory), cfg.buildtarget.basename)
for action in premake.action.each() do
if action.oncleantarget then
action.oncleantarget(target)
end
end
end
end
end
}
local scriptfile    = "premake4.lua"
local shorthelp     = "Type 'premake4 --help' for help"
local versionhelp   = "premake4 (Premake Build Script Generator) %s"
local function injectplatform(platform)
if not platform then return true end
platform = premake.checkvalue(platform, premake.fields.platforms.allowed)
for sln in premake.solution.each() do
local platforms = sln.platforms or { }
if #platforms == 0 then
table.insert(platforms, "Native")
end
if not table.contains(platforms, "Native") then
return false, sln.name .. " does not target native platform\nNative platform settings are required for the --platform feature."
end
if not table.contains(platforms, platform) then
table.insert(platforms, platform)
end
sln.platforms = platforms
end
return true
end
function _premake_main(scriptpath)
if (scriptpath) then
local scripts  = dofile(scriptpath .. "/_manifest.lua")
for _,v in ipairs(scripts) do
dofile(scriptpath .. "/" .. v)
end
end
premake.action.set(_ACTION)
math.randomseed(os.time())
local fname = _OPTIONS["file"] or scriptfile
if (os.isfile(fname)) then
dofile(fname)
end
if (_OPTIONS["version"]) then
printf(versionhelp, _PREMAKE_VERSION)
return 1
end
if (_OPTIONS["help"]) then
premake.showhelp()
return 1
end
if (not _ACTION) then
print(shorthelp)
return 1
end
if (not os.isfile(fname)) then
error("No Premake script ("..scriptfile..") found!", 2)
end
action = premake.action.current()
if (not action) then
error("Error: no such action '" .. _ACTION .. "'", 0)
end
ok, err = premake.option.validate(_OPTIONS)
if (not ok) then error("Error: " .. err, 0) end
ok, err = premake.checktools()
if (not ok) then error("Error: " .. err, 0) end
ok, err = injectplatform(_OPTIONS["platform"])
if (not ok) then error("Error: " .. err, 0) end
print("Building configurations...")
premake.buildconfigs()
ok, err = premake.checkprojects()
if (not ok) then error("Error: " .. err, 0) end
printf("Running action '%s'...", action.trigger)
premake.action.call(action.trigger)
print("Done.")
return 0
end
$Lua: Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio $
$Authors: R. Ierusalimschy, L. H. de Figueiredo & W. Celes $
$URL: www.lua.org $
no calling environmentno valueÀYw#@‚#@‚#@s#@s#@w#@s#@?ö+@ÿ+@,@,@,@#,@^,@f,@Sl%s:%d: bad argument #%d (%s)nmethodcalling '%s' on bad self (%s)?bad argument #%d to '%s' (%s)%s expected, got %sstack overflow (%s)value expectedinvalid option '%s'_LOADEDname conflict for module '%s'
cannot %s %s: %s=stdin@%sropenrbreopenreadPANIC: unprotected error in call to Lua API (%s)
createresumerunningstatuswrapyield0íCßK@7íCK@>íCyL@FíCJ@MíC:L@RíC^L@suspendednormaldead>íC¨íC²íC¹íCassertcollectgarbagedofileerrorgcinfogetfenvgetmetatableloadfileloadloadstringnextpcallprintrawequalrawgetrawsetselectsetfenvsetmetatabletonumbertostringtypeunpackxpcallÐíCF@×íC¤B@æíCÉE@ííCB?@óíCB@úíCA@îC™?@îCÆD@îC{E@îC†D@(îCkC@-îC}G@3îC =@9îCÙA@BîCB@IîCAB@PîCÿF@WîCDA@_îCÖ?@lîCW>@uîCH@~îC8C@ƒîCdF@ŠîCÈG@'tostring' must return a string to 'print'base out of range__metatablenil or table expectedcannot change a protected metatablelevel must be non-negativeinvalid levelfno function environment for tail call at level %d'setfenv' cannot change environment of given objectstoprestartcollectcountstepsetpausesetstepmulŒðC‘ðC™ðC¡ðC§ðC¬ðCµðC€:too many nested functionsreader function must return a string=(load)assertion failed!%stoo many results to unpackindex out of range__tostringtruefalsenil%s: %pboolean or proxy expectedcoroutine expectedtoo many arguments to resumecannot resume %s coroutinetoo many results to resumeLua function expected_GLua 5.1_VERSIONipairspairskv__modenewproxycoroutinecontrol structure too longfunction or expression too complexconstant table overflowcode size overflow´T@¼T@ÇT@âT@%U@%U@%U@U@U@÷U@V@V@V@V@zV@zV@zV@zV@zV@8V@[V@CW@HW@CW@CW@^W@^W@^W@^W@PW@!Z@nZ@%Z@)Z@%sfunction or level expectedinvalid optionsourceshort_srclinedefinedlastlinedefinedwhatcurrentlinenupsnamenamewhatactivelinesfunclevel out of rangecallreturnlinecounttail returnLöCQöCXöC]öCcöCexternal hooklua_debug> cont
=(debug command)
stack traceback:
	...
	Snl%s:%d: in function '%s' in main chunk ? in function <%s:%d>(*temporary)½p@ÿp@#q@.q@$s@.q@#q@$s@$s@Dq@$s@$s@$s@$s@$s@$s@$s@$s@$s@bq@¶q@$s@$s@$s@$s@$s@çq@çq@Sr@¤q@¤q@jq@hr@$s@’r@ær@?localglobalfieldupvaluemethod/t@œt@œt@œt@_t@t@Ct@œt@œt@œt@œt@€t@tail=(tail call)=[C]CmainLua%s:%d: %sattempt to compare two %s valuesattempt to compare %s with %sattempt to %s %s '%s' (a %s value)attempt to %s a %s valueperform arithmetic onconcatenatenot enough memoryerror in error handlingstack overflowcallnC stack overflowcannot resume non-suspended coroutineattempt to yield across metamethod/C-call boundary¼@£@›@R@«@³@u@À“@¬“@š“@Г@µ“@‘“@£“@ÿ•@–@À—@ö—@™˜@packagetableioosstringmathdebugàùCËL@áùChÉ@éùCf'AïùCš§@òùC#Õ@õùC AüùC¾@úCªk@closeflushinputlinesopenoutputpopenreadtmpfiletypewrite€úCo@†úC·¦@ŒúCîŸ@’úCg @˜úCž@úC @¤úCwž@ªúCû£@¯úCÝž@·úCª›@¼úC›¥@ŒúCúCseeksetvbuf__gc__tostring€úCo@†úCê¦@’úCF @ªúC ¤@HûCà¥@MûCX¦@¼úCÀ¥@UûC¢@ZûCÌ@%s: %s%sFILE*closed filefileattempt to use a closed filecannot close standard file__closefile (closed)file (%p)rstandard %s file is closedwtoo many argumentsinvalid option%lfinvalid formatfile is already closed%.14gsetcurendÈüCÌüCÐüC@nofulllineðüCóüCøüC__indexiostdinstdoutstderrandbreakdoelseelseifendfalseforfunctionifinlocalnilnotorrepeatreturnthentrueuntilwhile.....==>=<=~=@ýCDýCJýCMýCRýCYýC]ýCcýCgýCpýCsýCvýC|ýC€ýC„ýC‡ýCŽýC•ýCšýCŸýC¥ýC«ýC®ýC²ýCµýC¸ýC»ýC¾ýCÇýCÎýC×ýCchar(%d)%c%s:%d: %s%s near '%s'lexical element too longchunk has too many linesEe+-malformed numberunfinished long stringunfinished long commentnesting of [[...]] is deprecatedinvalid long string delimiterunfinished stringescape sequence too large.absacosasinatan2atanceilcoshcosdegexpfloorfmodfrexpldexplog10logmaxminmodfpowradrandomrandomseedsinhsinsqrttanhtan€ÿCÀ·@„ÿC
¹@‰ÿCà¸@ŽÿC^¹@”ÿC4¹@™ÿC•¹@žÿCb¸@£ÿC8¸@§ÿC^»@«ÿC4»@¯ÿC¿¹@µÿCé¹@ºÿC®»@ÀÿCç»@ÆÿC
»@ÌÿCàº@ÐÿC}¼@ÔÿC¼@ØÿC º@ÝÿC©º@áÿC†»@åÿCá¼@ìÿCë½@÷ÿC¸@üÿCä·@Dcº@D¶¸@
DŒ¸@9R¢Fß‘?9R¢Fß‘?interval is emptywrong number of argumentsþÿFð?mathpihugemodmemory allocation error: block too bigmodulerequire°D{Æ@·DÇÄ@SÄ@ÄÂ@YÃ@³Ã@loadlibseeallìDôÀ@ôD<È@system error %d
_LOADLIBLOADLIB: %s%sopeninit\.'package.%s' must be a string?r
	no file '%s'error loading module '%s' from file '%s':
	%spath_luaopen_%scpath
	no module '%s' in file '%s'preload'package.preload' must be a table
	no field package.preload['%s']_LOADEDloop or previous error loading module '%s'loaders'package.loaders' must be a tablemodule '%s' not found:%sname conflict for module '%s'_NAME_M_PACKAGEf'module' not called from a Lua function__index;;;;unable to get ModuleFileName!__gcpackage.\?.lua;!\lua\?.lua;!\lua\?\init.lua;!\?.lua;!\?\init.luaLUA_PATH.\?.dll;!\?.dll;!\loadall.dllLUA_CPATH\
;
?
!
-configloaded%(null)%p...

"]`qT`Pql1 or '...' expectedconstant table overflowcannot use '...' outside a vararg functionitems in a constructorambiguous syntax (function call x new statement)function arguments expectedunexpected symbolsyntax errorvariables in assignmentnot enough memorybytechardumpfindformatgfindgmatchgsublenlowermatchrepreversesubupper@DÂý@ED}þ@JD-ÿ@OD¿	ATDÀA[Dö
AaD±
AhDAmDðú@qD<ü@wDÐ	A}DPý@D³û@‰D-û@DÆü@string slice too longinvalid valueunable to dump given functionmalformed pattern (ends with '%%')malformed pattern (missing ']')AnAHAlAnAnAnAnAnAnAnAAnAnAnA´AnAnAØAnAöAnAA7AnAdAinvalid pattern captureunbalanced patternmissing '[' after '%%f' in patterninvalid capture indextoo many capturesunfinished capture^$*+?.([%-'string.gfind' was renamed to 'string.gmatch'string/function/table expectedinvalid replacement value (a %s)-+ #0invalid format (repeated flags)invalid format (width or precision too long)\r\000invalid option '%%%c' to 'format'string__indexÀYinvalid key to 'next'table overflowÀYtable index is niltable index is NaNconcatforeachforeachigetnmaxninsertremovesetnsort D~#A'D¤ A/D  A8DŸ!A=D!!ABDü!AID“"APDÎ!AUD'A'setn' is obsoletewrong number of arguments to 'insert'invalid value (%s) at index %d in table for 'concat'invalid order function for sortingtablenilbooleanuserdatanumberstringtablefunctionthreadprotoupval`DdDlDuD|DƒD‰DlD’D™DŸD__index__newindex__gc__mode__eq__add__sub__mul__div__mod__pow__unm__len__lt__le__concat__callìDôDÿDDDDDD"D(D.D4D:D@DEDJDSD%s: %s in precompiled chunkunexpected endbad integercode too deepbad constantbad codebinary stringbad header=?%.14gindexloop in gettableloop in settable}4A¦4A¦4A„4A¦4A—4A¦4A—4Astring length overflowÜ6A	7Aà6Aä6Aè6A
7A,7Aget length of'for' initial value must be a number'for' limit must be a number'for' step must be a number¬8A´8AÎ8Aí8A9A-9Ak9A´9Aì9A8:A›:Aõ:AZ;AÊ;A,AO>A€>A	?At?A‰?Aÿ?Ah@ASAA‘AAéAAOBA;CA—CAíCAˆDA8EAþEAFA±FA-LIBGCCW32-EH-2-SJLJ-GTHR-MINGW32w32_sharedptr->size == sizeof(W32_EH_SHARED)%s:%u: failed assertion `%s'
../../gcc/gcc/config/i386/w32-shared-ptr.cGetAtomNameA (atom, s, sizeof(s)) != 0T0:H2¨0(:œ2´0À;¨284D4P4d4t4€4Œ4 4°4Ä4Ô4ä4ü45$585H5\5t5”5œ5¬5¼5Ì5Ü5ð5ü5666(646@6L6X6d6p6x6€6ˆ66˜6¤6¬6¸6À6È6Ð6Ü6ä6ì6ø67777$70787@7H7P7\7d7p7x7€7Œ7˜7¤7¬7¼7È7Ð7Ø7ä7ð7ü788 8(80888@8L8X8d8p8|8ˆ88˜8¤8¬8´8À8Ì8Ø8ä8ð8ü899 9,989D9P9\9h9t9|9„9Œ9˜9¤9°9¼984D4P4d4t4€4Œ4 4°4Ä4Ô4ä4ü45$585H5\5t5”5œ5¬5¼5Ì5Ü5ð5ü5666(646@6L6X6d6p6x6€6ˆ66˜6¤6¬6¸6À6È6Ð6Ü6ä6ì6ø67777$70787@7H7P7\7d7p7x7€7Œ7˜7¤7¬7¼7È7Ð7Ø7ä7ð7ü788 8(80888@8L8X8d8p8|8ˆ88˜8¤8¬8´8À8Ì8Ø8ä8ð8ü899 9,989D9P9\9h9t9|9„9Œ9˜9¤9°9¼9AddAtomA5CopyFileA<CreateDirectoryA›ExitProcess¯FindAtomA±FindCloseµFindFirstFileA¾FindNextFileAÐFormatMessageAÕFreeLibraryÜGetAtomNameAGetCurrentDirectoryACGetLastErrorMGetModuleFileNameAjGetProcAddress
LoadLibraryAtRemoveDirectoryA­SetCurrentDirectoryAàSetUnhandledExceptionFilterO_stat'__getmainargs0__mb_cur_max<__p__environ>__p__fmodeP__set_app_typey_cexit˜_errnoª_filbufé_iobë_isctype^_onexitf_pcloseg_pctypej_popen€_setjmp„_setmodeabortacosasinatanatan2atexit"ceil#clearerr$clock%cos&cosh(difftime*exit+exp-fclose0fflush3fgets6floor7fmod8fopen9fprintf:fputc;fputs>fread?free@freopenAfrexpBfscanfCfseekEftellGfwriteKgetenvOgmtimekldexpmlocaleconvnlocaltimeologplog10qlongjmprmallocvmemchrwmemcmpxmemcpy{mktime|modf~pow‚puts‡randˆrealloc‰removeŠrenameŽsetlocalesetvbufsignal‘sin’sinh“sprintf”sqrt•srand—strcat˜strchr™strcmpšstrcoll›strcpyœstrcspnstrerroržstrftime strncat¢strncpy£strpbrk¤strrchr¦strstr§strtodªstrtoul®system¯tan°tanh±time²tmpfile³tmpnam´tolowerµtoupper¸ungetc0000000000000000000KERNEL32.dll0msvcrt.dll(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0msvcrt.dllode-0.16/build/config-default.h0000664000175200017520000000723113403272463013304 00000000000000/* This file was autogenerated by Premake */
#ifndef _ODE_CONFIG_H_
#define _ODE_CONFIG_H_


/******************************************************************
 * CONFIGURATON SETTINGS - you can change these, and then rebuild
 *   ODE to modify the behavior of the library.
 *
 *   dTRIMESH_ENABLED  - enable/disable trimesh support
 *   dTRIMESH_OPCODE   - use the OPCODE trimesh engine
 *   dTRIMESH_GIMPACT  - use the GIMPACT trimesh engine
 *                       Only one trimesh engine should be enabled.
 *
 *   dTRIMESH_16BIT_INDICES (todo: opcode only)
 *                       Setup the trimesh engine to use 16 bit
 *                       triangle indices. The default is to use
 *                       32 bit indices. Use the dTriIndex type to
 *                       detect the correct index size.
 *
 *   dTRIMESH_OPCODE_USE_NEWOLD_TRIMESH_TRIMESH_COLLIDER
 *                       Use old implementation of trimesh-trimesh collider
 *                       (for backward compatibility only)
 *
 *   dOU_ENABLED       
 *   dATOMICS_ENABLED
 *   dTLS_ENABLED
 *                       Use generic features of OU library, atomic API
 *                       and TLS API respectively.
 *                       Generic features and atomic API are always enabled, 
 *                       unless threading interface support is disabled.
 *                       Using TLS for global variables allows calling ODE 
 *                       collision detection functions from multiple threads.
 *
 *   dBUILTIN_THREADING_IMPL_ENABLED
 *                       Include built-in multithreaded threading 
 *                       implementation (still must be created and assigned
 *                       to be used).
 *
 ******************************************************************/

#define dTRIMESH_ENABLED 1
#define dTRIMESH_OPCODE 1
#define dTRIMESH_16BIT_INDICES 0

#define dTRIMESH_OPCODE_USE_OLD_TRIMESH_TRIMESH_COLLIDER 0

/* #define dOU_ENABLED 1 */
/* #define dATOMICS_ENABLED 1 */
/* #define dTLS_ENABLED 1 */

/* #define dTHREADING_INTF_DISABLED 1 */
/* #define dBUILTIN_THREADING_IMPL_ENABLED 1 */


/******************************************************************
 * SYSTEM SETTINGS - you shouldn't need to change these. If you
 *   run into an issue with these settings, please report it to
 *   the ODE bug tracker at:
 *      http://sf.net/tracker/?group_id=24884&atid=382799
 ******************************************************************/

/* Try to identify the platform */
#if defined(_XENON)
  #define ODE_PLATFORM_XBOX360
#elif defined(SN_TARGET_PSP_HW)
  #define ODE_PLATFORM_PSP
#elif defined(SN_TARGET_PS3)
  #define ODE_PLATFORM_PS3
#elif defined(_MSC_VER) || defined(__CYGWIN32__) || defined(__MINGW32__)
  #define ODE_PLATFORM_WINDOWS
#elif defined(__linux__)
  #define ODE_PLATFORM_LINUX
#elif defined(__APPLE__) && defined(__MACH__)
  #define ODE_PLATFORM_OSX
#else
  #error "Need some help identifying the platform!"
#endif

/* Additional platform defines used in the code */
#if defined(ODE_PLATFORM_WINDOWS) && !defined(WIN32)
  #define WIN32
#endif

#if defined(__CYGWIN32__) || defined(__MINGW32__)
  #define CYGWIN
#endif

#if defined(ODE_PLATFORM_OSX)
  #define macintosh
#endif

#if !defined(ODE_PLATFORM_OSX) && !defined(ODE_PLATFORM_PS3)
  #include 
#endif

#if !defined(ODE_PLATFORM_WINDOWS)
  #include 
#endif


/* Basic OU functionality is required if either atomic API or TLS support
 * is enabled. */
#if (dATOMICS_ENABLED || dTLS_ENABLED) && !dOU_ENABLED
#undef dOU_ENABLED
#define dOU_ENABLED 1
#endif


#include "typedefs.h"


#endif
ode-0.16/build/premake4.lua0000664000175200017520000004157413403272463012467 00000000000000----------------------------------------------------------------------
-- Premake4 configuration script for OpenDE
-- Contributed by Jason Perkins (starkos@industriousone.com)
-- For more information on Premake: http://industriousone.com/premake
----------------------------------------------------------------------

  ode_version = "0.16"

----------------------------------------------------------------------
-- Demo list: add/remove demos from here and the rest of the build
-- should just work.
----------------------------------------------------------------------

  local demos = {
    "boxstack",
    "buggy",
    "cards",
    "chain1",
    "chain2",
    "collision",
    "convex",
    "crash",
    "cylvssphere",
    "dball",
    "dhinge",
    "feedback",
    "friction",
    "gyroscopic",
    "gyro2",
    "heightfield",
    "hinge",
    "I",
    "jointPR",
    "jointPU",
    "joints",
    "kinematic",
    "motion",
    "motor",
    "ode",
    "piston",
    "plane2d",
    "rfriction",
    "slider",
    "space",
    "space_stress",
    "step",
    "transmission"
  }

  local trimesh_demos = {
    "basket",
    "cyl",
    "moving_convex",
    "moving_trimesh",
    "tracks",
    "trimesh"
  }
  
  if not _OPTIONS["no-trimesh"] then
    demos = table.join(demos, trimesh_demos)
  end



----------------------------------------------------------------------
-- Configuration options
----------------------------------------------------------------------

  newoption {
    trigger     = "with-demos",
    description = "Builds the demo applications and DrawStuff library"
  }
  
  newoption {
    trigger     = "with-tests",
    description = "Builds the unit test application"
  }
  
  newoption {
    trigger     = "with-gimpact",
    description = "Use GIMPACT for trimesh collisions (experimental)"
  }
  
  newoption {
    trigger     = "all-collis-libs",
    description = "Include sources of all collision libraries into the project"
  }
  
  newoption {
    trigger     = "with-libccd",
    description = "Uses libccd for handling some collision tests absent in ODE."
  }
  
  newoption {
    trigger     = "no-dif",
    description = "Exclude DIF (Dynamics Interchange Format) exports"
  }
  
  newoption {
    trigger     = "no-trimesh",
    description = "Exclude trimesh collision geometry"
  }
  
  newoption {
    trigger     = "with-ou",
    description = "Use TLS for global caches (allows threaded collision checks for separated spaces)"
  }

  newoption {
    trigger     = "no-builtin-threading-impl",
    description = "Disable built-in multithreaded threading implementation"
  }

  newoption {
    trigger     = "no-threading-intf",
    description = "Disable threading interface support (external implementations cannot be assigned)"
  }

  newoption {
    trigger     = "16bit-indices",
    description = "Use 16-bit indices for trimeshes (default is 32-bit)"
  }

  newoption {
    trigger     = "old-trimesh",
    description = "Use old OPCODE trimesh-trimesh collider"
  }
  
  newoption {
    trigger     = "to",
    value       = "path",
    description = "Set the output location for the generated project files"
  }
  
  newoption {
    trigger     = "only-shared",
	description = "Only build shared (DLL) version of the library"
  }
  
  newoption {
    trigger     = "only-static",
	description = "Only build static versions of the library"
  }

  newoption {
    trigger     = "only-single",
	description = "Only use single-precision math"
  }
  
  newoption {
    trigger     = "only-double",
	description = "Only use double-precision math"
  }
  
  -- always clean all of the optional components and toolsets
  if _ACTION == "clean" then
    _OPTIONS["with-demos"] = ""
    _OPTIONS["with-tests"] = ""
    for action in premake.action.each() do
      os.rmdir(action.trigger)
    end
    os.remove("../ode/src/config.h")
    os.remove("../include/ode/version.h")
    os.remove("../include/ode/precision.h")
    os.remove("../libccd/src/ccd/precision.h")
  end
  
  -- special validation for Xcode  
  if _ACTION == "xcode3" and (not _OPTIONS["only-static"] and not _OPTIONS["only-shared"]) then
    error(
	  "Xcode does not support different library types in a single project.\n" ..
	  "Please use one of the flags: --only-static or --only-shared", 0)
  end

  -- build the list of configurations, based on the flags. Ends up
  -- with configurations like "Debug", "DebugSingle" or "DebugSingleShared"
  local configs = { "Debug", "Release" }
  
  local function addconfigs(...)
	local newconfigs = { }
	for _, root in ipairs(configs) do
	  for _, suffix in ipairs(arg) do
		table.insert(newconfigs, root .. suffix)
	  end
	end
	configs = newconfigs
  end
  
  
  if not _OPTIONS["only-single"] and not _OPTIONS["only-double"] then
    addconfigs("Single", "Double")
  end
  
  if not _OPTIONS["only-shared"] and not _OPTIONS["only-static"] then
    addconfigs("DLL", "Lib")
  end

  
----------------------------------------------------------------------
-- The solution, and solution-wide settings
----------------------------------------------------------------------

  solution "ode"

    language "C++"
    uuid     "4DA77C12-15E5-497B-B1BB-5100D5161E15"
    location ( _OPTIONS["to"] or _ACTION )

    includedirs {
      "../include",
      "../ode/src"
    }
    
    defines { "_MT" }
    
    -- apply the configuration list built above
    configurations (configs)
    
    configuration { "Debug*" }
      defines { "_DEBUG" }
      flags   { "Symbols" }
      
    configuration { "Release*" }
      defines { "NDEBUG", "dNODEBUG" }
      flags   { "OptimizeSpeed", "NoFramePointer" }

    configuration { "*Single*" }
      defines { "dIDESINGLE", "CCD_IDESINGLE" }
      
    configuration { "*Double*" }
      defines { "dIDEDOUBLE", "CCD_IDEDOUBLE" }
    
    configuration { "Windows" }
      defines { "WIN32" }

    configuration { "MacOSX" }
      linkoptions { "-framework Carbon" }
      
    -- give each configuration a unique output directory
    for _, name in ipairs(configurations()) do
      configuration { name }
        targetdir ( "../lib/" .. name )
    end
      
    -- disable Visual Studio security warnings
    configuration { "vs*" }
      defines { "_CRT_SECURE_NO_DEPRECATE", "_SCL_SECURE_NO_WARNINGS" }

    -- enable M_* macros from math.h
    configuration { "vs*" }
      defines { "_USE_MATH_DEFINES" }

    -- don't remember why we had to do this	
    configuration { "vs2002 or vs2003", "*Lib" }
      flags  { "StaticRuntime" }



----------------------------------------------------------------------
-- The demo projects, automated from list above. These go first so
-- they will be selected as the active project automatically in IDEs
----------------------------------------------------------------------

  if _OPTIONS["with-demos"] then
    for _, name in ipairs(demos) do
    
      project ( "demo_" .. name )
      
        kind      "ConsoleApp"
        location  ( _OPTIONS["to"] or _ACTION )
        files     { "../ode/demo/demo_" .. name .. ".*" }
		links     { "ode", "drawstuff" }        
        
        configuration { "Windows" }
          files   { "../drawstuff/src/resources.rc" }
          links   { "user32", "winmm", "gdi32", "opengl32", "glu32" }

        configuration { "MacOSX" }
          linkoptions { "-framework Carbon -framework OpenGL -framework AGL" }

        configuration { "not Windows", "not MacOSX" }
          links   { "GL", "GLU" }
        
    end
  end
  


----------------------------------------------------------------------
-- The ODE library project
----------------------------------------------------------------------

  project "ode"

    -- kind     "StaticLib"
    location ( _OPTIONS["to"] or _ACTION )

    includedirs {
      "../ode/src/joints",
      "../OPCODE",
      "../GIMPACT/include",
      "../libccd/src/custom",
      "../libccd/src"
    }

    files {
      "../include/ode/*.h",
      "../ode/src/joints/*.h", 
      "../ode/src/joints/*.cpp",
      "../ode/src/*.h", 
      "../ode/src/*.c", 
      "../ode/src/*.cpp",
    }

    excludes {
      "../ode/src/collision_std.cpp",
    }

    includedirs { "../ou/include" }
    files   { "../ou/include/**.h", "../ou/src/**.h", "../ou/src/**.cpp" }
    defines { "_OU_NAMESPACE=odeou" }

    if _OPTIONS["with-ou"] then
      defines { "_OU_FEATURE_SET=_OU_FEATURE_SET_TLS" }
    elseif not _OPTIONS["no-threading-intf"] then
      defines { "_OU_FEATURE_SET=_OU_FEATURE_SET_ATOMICS" }
    else
      defines { "_OU_FEATURE_SET=_OU_FEATURE_SET_BASICS" }
    end

    if _OPTIONS["with-ou"] or not _OPTIONS["no-threading-intf"] then
      if _ACTION == "gmake" then
        if os.get() == "windows" then
          buildoptions { "-mthreads" }
          linkoptions { "-mthreads" }
        else
          buildoptions { "-pthread" }
          linkoptions { "-pthread" }
        end
      end
    end

      
    configuration { "no-dif" }
      excludes { "../ode/src/export-dif.cpp" }

    configuration { "no-trimesh" }
      excludes {
        "../ode/src/collision_trimesh_colliders.h",
        "../ode/src/gimpact_contact_export_helper.cpp",
        "../ode/src/gimpact_contact_export_helper.h",
        "../ode/src/gimpact_gim_contact_accessor.h",
        "../ode/src/gimpact_plane_contact_accessor.h",
        "../ode/src/collision_trimesh_internal.cpp",
        "../ode/src/collision_trimesh_opcode.cpp",
        "../ode/src/collision_trimesh_gimpact.cpp",
        "../ode/src/collision_trimesh_box.cpp",
        "../ode/src/collision_trimesh_ccylinder.cpp",
        "../ode/src/collision_cylinder_trimesh.cpp",
        "../ode/src/collision_trimesh_ray.cpp",
        "../ode/src/collision_trimesh_sphere.cpp",
        "../ode/src/collision_trimesh_trimesh.cpp",
        "../ode/src/collision_trimesh_trimesh_old.cpp",
        "../ode/src/collision_trimesh_plane.cpp",
        "../ode/src/collision_convex_trimesh.cpp"
      }

    configuration { "not no-trimesh", "with-gimpact or all-collis-libs" }
      files   { "../GIMPACT/**.h", "../GIMPACT/**.cpp" }
    
    configuration { "not no-trimesh", "not with-gimpact" }
      files   { "../OPCODE/**.h", "../OPCODE/**.cpp" }

    configuration { "not no-trimesh", "not all-collis-libs", "with-gimpact" }
      excludes {
        "../ode/src/collision_trimesh_opcode.cpp"
      }
    
    configuration { "not no-trimesh", "not all-collis-libs", "not with-gimpact" }
      excludes {
        "../ode/src/gimpact_contact_export_helper.cpp",
        "../ode/src/gimpact_contact_export_helper.h",
        "../ode/src/gimpact_gim_contact_accessor.h",
        "../ode/src/gimpact_plane_contact_accessor.h",
        "../ode/src/collision_trimesh_gimpact.cpp"
      }
 
    configuration { "with-libccd" }
      files   { "../libccd/src/custom/ccdcustom/*.h", "../libccd/src/ccd/*.h", "../libccd/src/*.c" }
      defines { "dLIBCCD_ENABLED", "dLIBCCD_INTERNAL", 
        "dLIBCCD_BOX_CYL", "dLIBCCD_CYL_CYL", "dLIBCCD_CAP_CYL", "dLIBCCD_CONVEX_BOX",
        "dLIBCCD_CONVEX_CAP", "dLIBCCD_CONVEX_CYL", "dLIBCCD_CONVEX_SPHERE", "dLIBCCD_CONVEX_CONVEX" }

    configuration { "not with-libccd" }
      excludes { "../ode/src/collision_libccd.cpp", "../ode/src/collision_libccd.h" }

    configuration { "windows" }
      links   { "user32" }
            
    configuration { "only-static or *Lib" }
      kind    "StaticLib"
      defines "ODE_LIB"
      
    configuration { "only-shared or *DLL" }
      kind    "SharedLib"
      defines "ODE_DLL"

    configuration { "*DLL" }
      defines "_DLL"

    configuration { "Debug" }
      targetname "oded"
	  
    configuration { "Release" }
      targetname "ode"
	  
    configuration { "DebugSingle*" }
      targetname "ode_singled"
      
    configuration { "ReleaseSingle*" }
      targetname "ode_single"
      
    configuration { "DebugDouble*" }
      targetname "ode_doubled"
      
    configuration { "ReleaseDouble*" }
      targetname "ode_double"


----------------------------------------------------------------------
-- Write a custom  to build, based on the supplied flags
----------------------------------------------------------------------

  if _ACTION and _ACTION ~= "clean" then
    local infile = io.open("config-default.h", "r")
    local text = infile:read("*a")

    if _OPTIONS["no-trimesh"] then
      text = string.gsub(text, "#define dTRIMESH_ENABLED 1", "/* #define dTRIMESH_ENABLED 1 */")
      text = string.gsub(text, "#define dTRIMESH_OPCODE 1", "/* #define dTRIMESH_OPCODE 1 */")
    elseif (_OPTIONS["with-gimpact"]) then
      text = string.gsub(text, "#define dTRIMESH_OPCODE 1", "#define dTRIMESH_GIMPACT 1")
    end

    text = string.gsub(text, "/%* #define dOU_ENABLED 1 %*/", "#define dOU_ENABLED 1")
    if _OPTIONS["with-ou"] or not _OPTIONS["no-threading-intf"] then
      text = string.gsub(text, "/%* #define dATOMICS_ENABLED 1 %*/", "#define dATOMICS_ENABLED 1")
    end

    if _OPTIONS["with-ou"] then
      text = string.gsub(text, "/%* #define dTLS_ENABLED 1 %*/", "#define dTLS_ENABLED 1")
    end

    if _OPTIONS["no-threading-intf"] then
      text = string.gsub(text, "/%* #define dTHREADING_INTF_DISABLED 1 %*/", "#define dTHREADING_INTF_DISABLED 1")
    elseif not _OPTIONS["no-builtin-threading-impl"] then
      text = string.gsub(text, "/%* #define dBUILTIN_THREADING_IMPL_ENABLED 1 %*/", "#define dBUILTIN_THREADING_IMPL_ENABLED 1")
    end

    if _OPTIONS["16bit-indices"] then
      text = string.gsub(text, "#define dTRIMESH_16BIT_INDICES 0", "#define dTRIMESH_16BIT_INDICES 1")
    end
  
    if _OPTIONS["old-trimesh"] then
      text = string.gsub(text, "#define dTRIMESH_OPCODE_USE_OLD_TRIMESH_TRIMESH_COLLIDER 0", "#define dTRIMESH_OPCODE_USE_OLD_TRIMESH_TRIMESH_COLLIDER 1")
    end
    
    local outfile = io.open("../ode/src/config.h", "w")
    outfile:write(text)
    outfile:close()
  end

----------------------------
-- Write precision headers
----------------------------
  if _ACTION and _ACTION ~= "clean" then
    function generateheader(headerfile, placeholder, precstr)
      local outfile = io.open(headerfile, "w")
      for i in io.lines(headerfile .. ".in")
      do
        local j,_ = string.gsub(i, placeholder, precstr)
        --print("writing " .. j .. " into " .. headerfile)
        outfile:write(j .. "\n")
      end
      outfile:close()
    end
    
    function generate(precstr)
      generateheader("../include/ode/precision.h", "@ODE_PRECISION@", "d" .. precstr)
      generateheader("../libccd/src/ccd/precision.h", "@CCD_PRECISION@", "CCD_" .. precstr)
    end
    
    if _OPTIONS["only-single"] then
      generate("SINGLE")
    elseif _OPTIONS["only-double"] then
      generate("DOUBLE")
    else 
      generate("UNDEFINEDPRECISION")
    end

    generateheader("../include/ode/version.h", "@ODE_VERSION@", ode_version)

  end


----------------------------------------------------------------------
-- The DrawStuff library project
----------------------------------------------------------------------

  if _OPTIONS["with-demos"] then

    project "drawstuff"

      location ( _OPTIONS["to"] or _ACTION )

      files {
        "../include/drawstuff/*.h",
        "../drawstuff/src/internal.h",
        "../drawstuff/src/drawstuff.cpp"
      }
      
      configuration { "Debug*" }
        targetname "drawstuffd"
            
      configuration { "only-static or *Lib" }
        kind    "StaticLib"
        defines { "DS_LIB" }
      
      configuration { "only-shared or *DLL" }
        kind    "SharedLib"
        defines { "DS_DLL", "USRDLL" }
      
      configuration { "Windows" }
        files   { "../drawstuff/src/resource.h", "../drawstuff/src/resources.rc", "../drawstuff/src/windows.cpp" }
        links   { "user32", "opengl32", "glu32", "winmm", "gdi32" }

      configuration { "MacOSX" }
	    defines     { "HAVE_APPLE_OPENGL_FRAMEWORK" }
        files       { "../drawstuff/src/osx.cpp" }
        linkoptions { "-framework Carbon -framework OpenGL -framework AGL" }

      configuration { "not Windows", "not MacOSX" }
        files   { "../drawstuff/src/x11.cpp" }
        links   { "X11", "GL", "GLU" }

  end


----------------------------------------------------------------------
-- The automated test application
----------------------------------------------------------------------


  if _OPTIONS["with-tests"] then
  
    project "tests"
  
      kind     "ConsoleApp"
      location ( _OPTIONS["to"] or _ACTION )

      includedirs { 
        "../tests/UnitTest++/src" 
      }
    
      files { 
        "../tests/*.cpp", 
        "../tests/joints/*.cpp", 
        "../tests/UnitTest++/src/*" 
      }

      links { "ode" }
    
      configuration { "Windows" }
        files { "../tests/UnitTest++/src/Win32/*" }
      
      configuration { "not Windows" }
        files { "../tests/UnitTest++/src/Posix/*" }

      -- add post-build step to automatically run test executable
      local path_to_lib = path.getrelative(location(), "../lib")
      local command = path.translate(path.join(path_to_lib, "%s/tests"))
      
      for _, name in ipairs(configurations()) do
        configuration { name }
          postbuildcommands { command:format(name) }
      end

  end

ode-0.16/README.md0000664000175200017520000000247213403272463010426 00000000000000The Open Dynamics Engine (ODE)
==============================

![ODE logo](http://bitbucket.org/odedevs/ode/raw/default/web/ODElogo.png)

Copyright (C) 2001-2007 Russell L. Smith.


ODE is a free, industrial quality library for simulating articulated
rigid body dynamics - for example ground vehicles, legged creatures,
and moving objects in VR environments. It is fast, flexible, robust
and platform independent, with advanced joints, contact with friction,
and built-in collision detection.

This library is free software; you can redistribute it and/or
modify it under the terms of EITHER:

 * The GNU Lesser General Public License version 2.1 or any later.

 * The BSD-style License.

See the [COPYING](http://bitbucket.org/odedevs/ode/raw/default/COPYING) file for more details.

 * Installation instructions are in the [INSTALL.txt](http://bitbucket.org/odedevs/ode/raw/default/INSTALL.txt) file.

 * The ODE web pages are at [ode.org](http://www.ode.org/).

 * An online manual is at [the Wiki](http://ode-wiki.org/wiki/index.php?title=Manual).

 * API documentation is in the file ode/docs/index.html, or you
   can view it on the web at [opende.sf.net/docs/index.html](http://opende.sf.net/docs/index.html).

 * Coding style requirements can be found in the [CSR.txt](http://bitbucket.org/odedevs/ode/raw/default/CSR.txt) file.

ode-0.16/COPYING0000664000175200017520000000162213403272463010176 00000000000000ODE is dual-licensed under either:

    * GNU Lesser General Public License v 2.1 or later.
        see LICENSE.TXT

    * Modified 3-clause BSD license.
        see LICENSE-BSD.TXT


Third-party libraries bundled with ODE:

    * GIMPACT: dual-licensed under either:
        - GNU Lesser General Public License v 2.1 or later.
            see GIMPACT-LICENSE-LGPL.TXT
        - Modified 3-clause BSD license.
            see GIMPACT/GIMPACT-LICENSE-BSD.TXT

    * libccd: Modified 3-clause BSD License
        see libccd/BSD-LICENSE

    * OU/ODER: triple-licensed under either:
        - GNU Lesser General Public License v 3 or later.
            see ou/LICENSE.TXT
            see ou/LICENSE-LESSER.TXT
        - Modified 3-clause BSD license.
            see ou/LICENSE-BSD.TXT
        - ZLIB license.
            see ou/LICENSE-ZLIB.TXT

    * OPCODE: under the same terms as ODE
        see OPCODE/COPYING

ode-0.16/install-sh0000755000175200017520000003452313403272662011154 00000000000000#!/bin/sh
# install - install a program, script, or datafile

scriptversion=2013-12-25.23; # UTC

# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
# following copyright and license.
#
# Copyright (C) 1994 X Consortium
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name of the X Consortium shall not
# be used in advertising or otherwise to promote the sale, use or other deal-
# ings in this Software without prior written authorization from the X Consor-
# tium.
#
#
# FSF changes to this file are in the public domain.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# 'make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch.

tab='	'
nl='
'
IFS=" $tab$nl"

# Set DOITPROG to "echo" to test this script.

doit=${DOITPROG-}
doit_exec=${doit:-exec}

# Put in absolute file names if you don't have them in your path;
# or use environment vars.

chgrpprog=${CHGRPPROG-chgrp}
chmodprog=${CHMODPROG-chmod}
chownprog=${CHOWNPROG-chown}
cmpprog=${CMPPROG-cmp}
cpprog=${CPPROG-cp}
mkdirprog=${MKDIRPROG-mkdir}
mvprog=${MVPROG-mv}
rmprog=${RMPROG-rm}
stripprog=${STRIPPROG-strip}

posix_mkdir=

# Desired mode of installed file.
mode=0755

chgrpcmd=
chmodcmd=$chmodprog
chowncmd=
mvcmd=$mvprog
rmcmd="$rmprog -f"
stripcmd=

src=
dst=
dir_arg=
dst_arg=

copy_on_change=false
is_target_a_directory=possibly

usage="\
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
   or: $0 [OPTION]... SRCFILES... DIRECTORY
   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
   or: $0 [OPTION]... -d DIRECTORIES...

In the 1st form, copy SRCFILE to DSTFILE.
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
In the 4th, create DIRECTORIES.

Options:
     --help     display this help and exit.
     --version  display version info and exit.

  -c            (ignored)
  -C            install only if different (preserve the last data modification time)
  -d            create directories instead of installing files.
  -g GROUP      $chgrpprog installed files to GROUP.
  -m MODE       $chmodprog installed files to MODE.
  -o USER       $chownprog installed files to USER.
  -s            $stripprog installed files.
  -t DIRECTORY  install into DIRECTORY.
  -T            report an error if DSTFILE is a directory.

Environment variables override the default commands:
  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
  RMPROG STRIPPROG
"

while test $# -ne 0; do
  case $1 in
    -c) ;;

    -C) copy_on_change=true;;

    -d) dir_arg=true;;

    -g) chgrpcmd="$chgrpprog $2"
        shift;;

    --help) echo "$usage"; exit $?;;

    -m) mode=$2
        case $mode in
          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
            echo "$0: invalid mode: $mode" >&2
            exit 1;;
        esac
        shift;;

    -o) chowncmd="$chownprog $2"
        shift;;

    -s) stripcmd=$stripprog;;

    -t)
        is_target_a_directory=always
        dst_arg=$2
        # Protect names problematic for 'test' and other utilities.
        case $dst_arg in
          -* | [=\(\)!]) dst_arg=./$dst_arg;;
        esac
        shift;;

    -T) is_target_a_directory=never;;

    --version) echo "$0 $scriptversion"; exit $?;;

    --) shift
        break;;

    -*) echo "$0: invalid option: $1" >&2
        exit 1;;

    *)  break;;
  esac
  shift
done

# We allow the use of options -d and -T together, by making -d
# take the precedence; this is for compatibility with GNU install.

if test -n "$dir_arg"; then
  if test -n "$dst_arg"; then
    echo "$0: target directory not allowed when installing a directory." >&2
    exit 1
  fi
fi

if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
  # When -d is used, all remaining arguments are directories to create.
  # When -t is used, the destination is already specified.
  # Otherwise, the last argument is the destination.  Remove it from $@.
  for arg
  do
    if test -n "$dst_arg"; then
      # $@ is not empty: it contains at least $arg.
      set fnord "$@" "$dst_arg"
      shift # fnord
    fi
    shift # arg
    dst_arg=$arg
    # Protect names problematic for 'test' and other utilities.
    case $dst_arg in
      -* | [=\(\)!]) dst_arg=./$dst_arg;;
    esac
  done
fi

if test $# -eq 0; then
  if test -z "$dir_arg"; then
    echo "$0: no input file specified." >&2
    exit 1
  fi
  # It's OK to call 'install-sh -d' without argument.
  # This can happen when creating conditional directories.
  exit 0
fi

if test -z "$dir_arg"; then
  if test $# -gt 1 || test "$is_target_a_directory" = always; then
    if test ! -d "$dst_arg"; then
      echo "$0: $dst_arg: Is not a directory." >&2
      exit 1
    fi
  fi
fi

if test -z "$dir_arg"; then
  do_exit='(exit $ret); exit $ret'
  trap "ret=129; $do_exit" 1
  trap "ret=130; $do_exit" 2
  trap "ret=141; $do_exit" 13
  trap "ret=143; $do_exit" 15

  # Set umask so as not to create temps with too-generous modes.
  # However, 'strip' requires both read and write access to temps.
  case $mode in
    # Optimize common cases.
    *644) cp_umask=133;;
    *755) cp_umask=22;;

    *[0-7])
      if test -z "$stripcmd"; then
        u_plus_rw=
      else
        u_plus_rw='% 200'
      fi
      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
    *)
      if test -z "$stripcmd"; then
        u_plus_rw=
      else
        u_plus_rw=,u+rw
      fi
      cp_umask=$mode$u_plus_rw;;
  esac
fi

for src
do
  # Protect names problematic for 'test' and other utilities.
  case $src in
    -* | [=\(\)!]) src=./$src;;
  esac

  if test -n "$dir_arg"; then
    dst=$src
    dstdir=$dst
    test -d "$dstdir"
    dstdir_status=$?
  else

    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
    # might cause directories to be created, which would be especially bad
    # if $src (and thus $dsttmp) contains '*'.
    if test ! -f "$src" && test ! -d "$src"; then
      echo "$0: $src does not exist." >&2
      exit 1
    fi

    if test -z "$dst_arg"; then
      echo "$0: no destination specified." >&2
      exit 1
    fi
    dst=$dst_arg

    # If destination is a directory, append the input filename; won't work
    # if double slashes aren't ignored.
    if test -d "$dst"; then
      if test "$is_target_a_directory" = never; then
        echo "$0: $dst_arg: Is a directory" >&2
        exit 1
      fi
      dstdir=$dst
      dst=$dstdir/`basename "$src"`
      dstdir_status=0
    else
      dstdir=`dirname "$dst"`
      test -d "$dstdir"
      dstdir_status=$?
    fi
  fi

  obsolete_mkdir_used=false

  if test $dstdir_status != 0; then
    case $posix_mkdir in
      '')
        # Create intermediate dirs using mode 755 as modified by the umask.
        # This is like FreeBSD 'install' as of 1997-10-28.
        umask=`umask`
        case $stripcmd.$umask in
          # Optimize common cases.
          *[2367][2367]) mkdir_umask=$umask;;
          .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;

          *[0-7])
            mkdir_umask=`expr $umask + 22 \
              - $umask % 100 % 40 + $umask % 20 \
              - $umask % 10 % 4 + $umask % 2
            `;;
          *) mkdir_umask=$umask,go-w;;
        esac

        # With -d, create the new directory with the user-specified mode.
        # Otherwise, rely on $mkdir_umask.
        if test -n "$dir_arg"; then
          mkdir_mode=-m$mode
        else
          mkdir_mode=
        fi

        posix_mkdir=false
        case $umask in
          *[123567][0-7][0-7])
            # POSIX mkdir -p sets u+wx bits regardless of umask, which
            # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
            ;;
          *)
            tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
            trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0

            if (umask $mkdir_umask &&
                exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
            then
              if test -z "$dir_arg" || {
                   # Check for POSIX incompatibilities with -m.
                   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
                   # other-writable bit of parent directory when it shouldn't.
                   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
                   ls_ld_tmpdir=`ls -ld "$tmpdir"`
                   case $ls_ld_tmpdir in
                     d????-?r-*) different_mode=700;;
                     d????-?--*) different_mode=755;;
                     *) false;;
                   esac &&
                   $mkdirprog -m$different_mode -p -- "$tmpdir" && {
                     ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
                     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
                   }
                 }
              then posix_mkdir=:
              fi
              rmdir "$tmpdir/d" "$tmpdir"
            else
              # Remove any dirs left behind by ancient mkdir implementations.
              rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
            fi
            trap '' 0;;
        esac;;
    esac

    if
      $posix_mkdir && (
        umask $mkdir_umask &&
        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
      )
    then :
    else

      # The umask is ridiculous, or mkdir does not conform to POSIX,
      # or it failed possibly due to a race condition.  Create the
      # directory the slow way, step by step, checking for races as we go.

      case $dstdir in
        /*) prefix='/';;
        [-=\(\)!]*) prefix='./';;
        *)  prefix='';;
      esac

      oIFS=$IFS
      IFS=/
      set -f
      set fnord $dstdir
      shift
      set +f
      IFS=$oIFS

      prefixes=

      for d
      do
        test X"$d" = X && continue

        prefix=$prefix$d
        if test -d "$prefix"; then
          prefixes=
        else
          if $posix_mkdir; then
            (umask=$mkdir_umask &&
             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
            # Don't fail if two instances are running concurrently.
            test -d "$prefix" || exit 1
          else
            case $prefix in
              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
              *) qprefix=$prefix;;
            esac
            prefixes="$prefixes '$qprefix'"
          fi
        fi
        prefix=$prefix/
      done

      if test -n "$prefixes"; then
        # Don't fail if two instances are running concurrently.
        (umask $mkdir_umask &&
         eval "\$doit_exec \$mkdirprog $prefixes") ||
          test -d "$dstdir" || exit 1
        obsolete_mkdir_used=true
      fi
    fi
  fi

  if test -n "$dir_arg"; then
    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
  else

    # Make a couple of temp file names in the proper directory.
    dsttmp=$dstdir/_inst.$$_
    rmtmp=$dstdir/_rm.$$_

    # Trap to clean up those temp files at exit.
    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0

    # Copy the file name to the temp name.
    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&

    # and set any options; do chmod last to preserve setuid bits.
    #
    # If any of these fail, we abort the whole thing.  If we want to
    # ignore errors from any of these, just make sure not to ignore
    # errors from the above "$doit $cpprog $src $dsttmp" command.
    #
    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&

    # If -C, don't bother to copy if it wouldn't change the file.
    if $copy_on_change &&
       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
       set -f &&
       set X $old && old=:$2:$4:$5:$6 &&
       set X $new && new=:$2:$4:$5:$6 &&
       set +f &&
       test "$old" = "$new" &&
       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
    then
      rm -f "$dsttmp"
    else
      # Rename the file to the real destination.
      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||

      # The rename failed, perhaps because mv can't rename something else
      # to itself, or perhaps because mv is so ancient that it does not
      # support -f.
      {
        # Now remove or move aside any old file at destination location.
        # We try this two ways since rm can't unlink itself on some
        # systems and the destination file might be busy for other
        # reasons.  In this case, the final cleanup might fail but the new
        # file should still install successfully.
        {
          test ! -f "$dst" ||
          $doit $rmcmd -f "$dst" 2>/dev/null ||
          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
            { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
          } ||
          { echo "$0: cannot unlink or rename $dst" >&2
            (exit 1); exit 1
          }
        } &&

        # Now rename the file to the real destination.
        $doit $mvcmd "$dsttmp" "$dst"
      }
    fi || exit 1

    trap '' 0
  fi
done

# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:
ode-0.16/LICENSE.TXT0000664000175200017520000006347413403272463010643 00000000000000		  GNU LESSER GENERAL PUBLIC LICENSE
		       Version 2.1, February 1999

 Copyright (C) 1991, 1999 Free Software Foundation, Inc.
     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

[This is the first released version of the Lesser GPL.  It also counts
 as the successor of the GNU Library Public License, version 2, hence
 the version number 2.1.]

			    Preamble

  The licenses for most software are designed to take away your
freedom to share and change it.  By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.

  This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it.  You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.

  When we speak of free software, we are referring to freedom of use,
not price.  Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.

  To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights.  These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.

  For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you.  You must make sure that they, too, receive or can get the source
code.  If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it.  And you must show them these terms so they know their rights.

  We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.

  To protect each distributor, we want to make it very clear that
there is no warranty for the free library.  Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.

  Finally, software patents pose a constant threat to the existence of
any free program.  We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder.  Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.

  Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License.  This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License.  We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.

  When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library.  The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom.  The Lesser General
Public License permits more lax criteria for linking other code with
the library.

  We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License.  It also provides other free software developers Less
of an advantage over competing non-free programs.  These disadvantages
are the reason we use the ordinary General Public License for many
libraries.  However, the Lesser license provides advantages in certain
special circumstances.

  For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard.  To achieve this, non-free programs must be
allowed to use the library.  A more frequent case is that a free
library does the same job as widely used non-free libraries.  In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.

  In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software.  For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.

  Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.

  The precise terms and conditions for copying, distribution and
modification follow.  Pay close attention to the difference between a
"work based on the library" and a "work that uses the library".  The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.

		  GNU LESSER GENERAL PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".

  A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.

  The "Library", below, refers to any such software library or work
which has been distributed under these terms.  A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language.  (Hereinafter, translation is
included without limitation in the term "modification".)

  "Source code" for a work means the preferred form of the work for
making modifications to it.  For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.

  Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it).  Whether that is true depends on what the Library does
and what the program that uses the Library does.
  
  1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.

  You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.

  2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

    a) The modified work must itself be a software library.

    b) You must cause the files modified to carry prominent notices
    stating that you changed the files and the date of any change.

    c) You must cause the whole of the work to be licensed at no
    charge to all third parties under the terms of this License.

    d) If a facility in the modified Library refers to a function or a
    table of data to be supplied by an application program that uses
    the facility, other than as an argument passed when the facility
    is invoked, then you must make a good faith effort to ensure that,
    in the event an application does not supply such function or
    table, the facility still operates, and performs whatever part of
    its purpose remains meaningful.

    (For example, a function in a library to compute square roots has
    a purpose that is entirely well-defined independent of the
    application.  Therefore, Subsection 2d requires that any
    application-supplied function or table used by this function must
    be optional: if the application does not supply it, the square
    root function must still compute square roots.)

These requirements apply to the modified work as a whole.  If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works.  But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.

In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

  3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library.  To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License.  (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.)  Do not make any other change in
these notices.

  Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.

  This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.

  4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.

  If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.

  5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library".  Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.

  However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library".  The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.

  When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library.  The
threshold for this to be true is not precisely defined by law.

  If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work.  (Executables containing this object code plus portions of the
Library will still fall under Section 6.)

  Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.

  6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.

  You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License.  You must supply a copy of this License.  If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License.  Also, you must do one
of these things:

    a) Accompany the work with the complete corresponding
    machine-readable source code for the Library including whatever
    changes were used in the work (which must be distributed under
    Sections 1 and 2 above); and, if the work is an executable linked
    with the Library, with the complete machine-readable "work that
    uses the Library", as object code and/or source code, so that the
    user can modify the Library and then relink to produce a modified
    executable containing the modified Library.  (It is understood
    that the user who changes the contents of definitions files in the
    Library will not necessarily be able to recompile the application
    to use the modified definitions.)

    b) Use a suitable shared library mechanism for linking with the
    Library.  A suitable mechanism is one that (1) uses at run time a
    copy of the library already present on the user's computer system,
    rather than copying library functions into the executable, and (2)
    will operate properly with a modified version of the library, if
    the user installs one, as long as the modified version is
    interface-compatible with the version that the work was made with.

    c) Accompany the work with a written offer, valid for at
    least three years, to give the same user the materials
    specified in Subsection 6a, above, for a charge no more
    than the cost of performing this distribution.

    d) If distribution of the work is made by offering access to copy
    from a designated place, offer equivalent access to copy the above
    specified materials from the same place.

    e) Verify that the user has already received a copy of these
    materials or that you have already sent this user a copy.

  For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it.  However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.

  It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system.  Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.

  7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:

    a) Accompany the combined library with a copy of the same work
    based on the Library, uncombined with any other library
    facilities.  This must be distributed under the terms of the
    Sections above.

    b) Give prominent notice with the combined library of the fact
    that part of it is a work based on the Library, and explaining
    where to find the accompanying uncombined form of the same work.

  8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License.  Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License.  However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.

  9. You are not required to accept this License, since you have not
signed it.  However, nothing else grants you permission to modify or
distribute the Library or its derivative works.  These actions are
prohibited by law if you do not accept this License.  Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.

  10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions.  You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.

  11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all.  For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.

If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices.  Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

  12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded.  In such case, this License incorporates the limitation as if
written in the body of this License.

  13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.

Each version is given a distinguishing version number.  If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation.  If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.

  14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission.  For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this.  Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.

			    NO WARRANTY

  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.

		     END OF TERMS AND CONDITIONS

           How to Apply These Terms to Your New Libraries

  If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change.  You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).

  To apply these terms, attach the following notices to the library.  It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.

    
    Copyright (C)   

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

Also add information on how to contact you by electronic and paper mail.

You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary.  Here is a sample; alter the names:

  Yoyodyne, Inc., hereby disclaims all copyright interest in the
  library `Frob' (a library for tweaking knobs) written by James Random Hacker.

  , 1 April 1990
  Ty Coon, President of Vice

That's all there is to it!
ode-0.16/include/0000775000175200017520000000000013403273060010637 500000000000000ode-0.16/include/Makefile.am0000664000175200017520000000003013403272463012612 00000000000000SUBDIRS = ode drawstuff
ode-0.16/include/drawstuff/0000775000175200017520000000000013403273060012644 500000000000000ode-0.16/include/drawstuff/Makefile.am0000664000175200017520000000005013403272463014621 00000000000000noinst_HEADERS = drawstuff.h version.h

ode-0.16/include/drawstuff/version.h0000664000175200017520000000326013403272463014431 00000000000000/*************************************************************************
 *                                                                       *
 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
 * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
 *                                                                       *
 * This library is free software; you can redistribute it and/or         *
 * modify it under the terms of EITHER:                                  *
 *   (1) The GNU Lesser General Public License as published by the Free  *
 *       Software Foundation; either version 2.1 of the License, or (at  *
 *       your option) any later version. The text of the GNU Lesser      *
 *       General Public License is included with this library in the     *
 *       file LICENSE.TXT.                                               *
 *   (2) The BSD-style license that is included with this library in     *
 *       the file LICENSE-BSD.TXT.                                       *
 *                                                                       *
 * This library is distributed in the hope that it will be useful,       *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
 * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
 *                                                                       *
 *************************************************************************/

#ifndef __VERSION_H
#define __VERSION_H

/* high byte is major version, low byte is minor version */
#define DS_VERSION 0x0002

#endif
ode-0.16/include/drawstuff/drawstuff.h0000664000175200017520000002434613403272463014761 00000000000000/*************************************************************************
 *                                                                       *
 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
 * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
 *                                                                       *
 * This library is free software; you can redistribute it and/or         *
 * modify it under the terms of EITHER:                                  *
 *   (1) The GNU Lesser General Public License as published by the Free  *
 *       Software Foundation; either version 2.1 of the License, or (at  *
 *       your option) any later version. The text of the GNU Lesser      *
 *       General Public License is included with this library in the     *
 *       file LICENSE.TXT.                                               *
 *   (2) The BSD-style license that is included with this library in     *
 *       the file LICENSE-BSD.TXT.                                       *
 *                                                                       *
 * This library is distributed in the hope that it will be useful,       *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
 * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
 *                                                                       *
 *************************************************************************/

/** @defgroup drawstuff DrawStuff

DrawStuff is a library for rendering simple 3D objects in a virtual 
environment, for the purposes of demonstrating the features of ODE.
It is provided for demonstration purposes and is not intended for
production use.

@section Notes

In the virtual world, the z axis is "up" and z=0 is the floor.

The user is able to click+drag in the main window to move the camera:
  * left button - pan and tilt.
  * right button - forward and sideways.
  * left + right button (or middle button) - sideways and up.
*/


#ifndef __DRAWSTUFF_H__
#define __DRAWSTUFF_H__

/* Define a DLL export symbol for those platforms that need it */
#if defined(ODE_PLATFORM_WINDOWS)
  #if defined(DS_DLL)
    #define DS_API __declspec(dllexport)
  #elif !defined(DS_LIB)
    #define DS_DLL_API __declspec(dllimport)
  #endif
#endif
    
#if !defined(DS_API)
  #define DS_API
#endif

#ifdef __cplusplus
extern "C" {
#endif


#include 


/* texture numbers */
  enum DS_TEXTURE_NUMBER
  {
    DS_NONE = 0,       /* uses the current color instead of a texture */
    DS_WOOD,
    DS_CHECKERED,
    DS_GROUND,
    DS_SKY
  };

/* draw modes */

#define DS_POLYFILL  0
#define DS_WIREFRAME 1

/**
 * @struct dsFunctions
 * @brief Set of functions to be used as callbacks by the simulation loop.
 * @ingroup drawstuff
 */
typedef struct dsFunctions {
  int version;			/* put DS_VERSION here */
  /* version 1 data */
  void (*start)();		/* called before sim loop starts */
  void (*step) (int pause);	/* called before every frame */
  void (*command) (int cmd);	/* called if a command key is pressed */
  void (*stop)();		/* called after sim loop exits */
  /* version 2 data */
  const char *path_to_textures;	/* if nonzero, path to texture files */
} dsFunctions;


/**
 * @brief Does the complete simulation.
 * @ingroup drawstuff
 * This function starts running the simulation, and only exits when the simulation is done.
 * Function pointers should be provided for the callbacks.
 * @param argv supports flags like '-notex' '-noshadow' '-pause'
 * @param fn Callback functions.
 */
DS_API void dsSimulationLoop (int argc, char **argv,
		       int window_width, int window_height,
		       struct dsFunctions *fn);

/**
 * @brief exit with error message.
 * @ingroup drawstuff
 * This function displays an error message then exit.
 * @param msg format strin, like printf, without the newline character.
 */
DS_API void dsError (const char *msg, ...);

/**
 * @brief exit with error message and core dump.
 * @ingroup drawstuff
 * this functions tries to dump core or start the debugger.
 * @param msg format strin, like printf, without the newline character.
 */
DS_API void dsDebug (const char *msg, ...);

/**
 * @brief print log message
 * @ingroup drawstuff
 * @param msg format string, like printf, without the \n.
 */
DS_API void dsPrint (const char *msg, ...);

/**
 * @brief Sets the viewpoint
 * @ingroup drawstuff
 * @param xyz camera position.
 * @param hpr contains heading, pitch and roll numbers in degrees. heading=0
 * points along the x axis, pitch=0 is looking towards the horizon, and
 * roll 0 is "unrotated".
 */
DS_API void dsSetViewpoint (float xyz[3], float hpr[3]);


/**
 * @brief Gets the viewpoint
 * @ingroup drawstuff
 * @param xyz position
 * @param hpr heading,pitch,roll.
 */
DS_API void dsGetViewpoint (float xyz[3], float hpr[3]);

/**
 * @brief Stop the simulation loop.
 * @ingroup drawstuff
 * Calling this from within dsSimulationLoop()
 * will cause it to exit and return to the caller. it is the same as if the
 * user used the exit command. using this outside the loop will have no
 * effect.
 */
DS_API void dsStop();

/**
 * @brief Get the elapsed time (on wall-clock)
 * @ingroup drawstuff
 * It returns the nr of seconds since the last call to this function.
 */
DS_API double dsElapsedTime();

/**
 * @brief Toggle the rendering of textures.
 * @ingroup drawstuff
 * It changes the way objects are drawn. these changes will apply to all further
 * dsDrawXXX() functions. 
 * @param the texture number must be a DS_xxx texture constant.
 * The current texture is colored according to the current color.
 * At the start of each frame, the texture is reset to none and the color is
 * reset to white.
 */
DS_API void dsSetTexture (int texture_number);

/**
 * @brief Set the color with which geometry is drawn.
 * @ingroup drawstuff
 * @param red Red component from 0 to 1
 * @param green Green component from 0 to 1
 * @param blue Blue component from 0 to 1
 */
DS_API void dsSetColor (float red, float green, float blue);

/**
 * @brief Set the color and transparency with which geometry is drawn.
 * @ingroup drawstuff
 * @param alpha Note that alpha transparency is a misnomer: it is alpha opacity.
 * 1.0 means fully opaque, and 0.0 means fully transparent.
 */
DS_API void dsSetColorAlpha (float red, float green, float blue, float alpha);

/**
 * @brief Draw a box.
 * @ingroup drawstuff
 * @param pos is the x,y,z of the center of the object.
 * @param R is a 3x3 rotation matrix for the object, stored by row like this:
 *        [ R11 R12 R13 0 ]
 *        [ R21 R22 R23 0 ]
 *        [ R31 R32 R33 0 ]
 * @param sides[] is an array of x,y,z side lengths.
 */
DS_API void dsDrawBox (const float pos[3], const float R[12], const float sides[3]);

/**
 * @brief Draw a sphere.
 * @ingroup drawstuff
 * @param pos Position of center.
 * @param R orientation.
 * @param radius
 */
DS_API void dsDrawSphere (const float pos[3], const float R[12], float radius);

/**
 * @brief Draw a triangle.
 * @ingroup drawstuff
 * @param pos Position of center
 * @param R orientation
 * @param v0 first vertex
 * @param v1 second
 * @param v2 third vertex
 * @param solid set to 0 for wireframe
 */
DS_API void dsDrawTriangle (const float pos[3], const float R[12],
		     const float *v0, const float *v1, const float *v2, int solid);

/**
 * @brief Draw triangles.
 * @ingroup drawstuff
 * @param pos Position of center
 * @param R orientation
 * @param v list of vertices (x0, y0, z0, x1, y1, z1, ...)
 * @param n number of vertices
 * @param solid set to 0 for wireframe
 */
DS_API void dsDrawTriangles (const float pos[3], const float R[12],
		     const float *v, const int n, int solid);

/**
 * @brief Draw a z-aligned cylinder
 * @ingroup drawstuff
 */
DS_API void dsDrawCylinder (const float pos[3], const float R[12],
		     float length, float radius);

/**
 * @brief Draw a z-aligned capsule
 * @ingroup drawstuff
 */
DS_API void dsDrawCapsule (const float pos[3], const float R[12],
		    float length, float radius);

/**
 * @brief Draw a line.
 * @ingroup drawstuff
 */
DS_API void dsDrawLine (const float pos1[3], const float pos2[3]);

/**
 * @brief Draw a convex shape.
 * @ingroup drawstuff
 */
DS_API void dsDrawConvex(const float pos[3], const float R[12],
		  const float *_planes,
		  unsigned int _planecount,
		  const float *_points,
		  unsigned int _pointcount,
		  const unsigned int *_polygons);

 /* these drawing functions are identical to the ones above, except they take
 * double arrays for `pos' and `R'.
 */
DS_API void dsDrawBoxD (const double pos[3], const double R[12],
		 const double sides[3]);
DS_API void dsDrawSphereD (const double pos[3], const double R[12],
		    const float radius);
DS_API void dsDrawTriangleD (const double pos[3], const double R[12],
		      const double *v0, const double *v1, const double *v2, int solid);
DS_API void dsDrawTrianglesD (const double pos[3], const double R[12],
		      const double *v, const int n, int solid);
DS_API void dsDrawCylinderD (const double pos[3], const double R[12],
		      float length, float radius);
DS_API void dsDrawCapsuleD (const double pos[3], const double R[12],
		     float length, float radius);
DS_API void dsDrawLineD (const double pos1[3], const double pos2[3]);
DS_API void dsDrawConvexD(const double pos[3], const double R[12],
		  const double *_planes,
		  unsigned int _planecount,
		  const double *_points,
		  unsigned int _pointcount,
		  const unsigned int *_polygons);

/**
 * @brief Set the quality with which curved objects are rendered.
 * @ingroup drawstuff
 * Higher numbers are higher quality, but slower to draw. 
 * This must be set before the first objects are drawn to be effective.
 * Default sphere quality is 1, default capsule quality is 3.
 */
DS_API void dsSetSphereQuality (int n);		/* default = 1 */
DS_API void dsSetCapsuleQuality (int n);		/* default = 3 */

/**
 * @brief Set Drawmode 0=Polygon Fill,1=Wireframe).
 * Use the DS_POLYFILL and DS_WIREFRAME macros.
 * @ingroup drawstuff
 */
DS_API void dsSetDrawMode(int mode);

/* Backwards compatible API */
#define dsDrawCappedCylinder dsDrawCapsule
#define dsDrawCappedCylinderD dsDrawCapsuleD
#define dsSetCappedCylinderQuality dsSetCapsuleQuality

/* closing bracket for extern "C" */
#ifdef __cplusplus
}
#endif

#endif

ode-0.16/include/drawstuff/Makefile.in0000664000175200017520000003463313403272663014652 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am.
# @configure_input@

# Copyright (C) 1994-2014 Free Software Foundation, Inc.

# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.

@SET_MAKE@

VPATH = @srcdir@
am__is_gnu_make = { \
  if test -z '$(MAKELEVEL)'; then \
    false; \
  elif test -n '$(MAKE_HOST)'; then \
    true; \
  elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
    true; \
  else \
    false; \
  fi; \
}
am__make_running_with_option = \
  case $${target_option-} in \
      ?) ;; \
      *) echo "am__make_running_with_option: internal error: invalid" \
              "target option '$${target_option-}' specified" >&2; \
         exit 1;; \
  esac; \
  has_opt=no; \
  sane_makeflags=$$MAKEFLAGS; \
  if $(am__is_gnu_make); then \
    sane_makeflags=$$MFLAGS; \
  else \
    case $$MAKEFLAGS in \
      *\\[\ \	]*) \
        bs=\\; \
        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
    esac; \
  fi; \
  skip_next=no; \
  strip_trailopt () \
  { \
    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
  }; \
  for flg in $$sane_makeflags; do \
    test $$skip_next = yes && { skip_next=no; continue; }; \
    case $$flg in \
      *=*|--*) continue;; \
        -*I) strip_trailopt 'I'; skip_next=yes;; \
      -*I?*) strip_trailopt 'I';; \
        -*O) strip_trailopt 'O'; skip_next=yes;; \
      -*O?*) strip_trailopt 'O';; \
        -*l) strip_trailopt 'l'; skip_next=yes;; \
      -*l?*) strip_trailopt 'l';; \
      -[dEDm]) skip_next=yes;; \
      -[JT]) skip_next=yes;; \
    esac; \
    case $$flg in \
      *$$target_option*) has_opt=yes; break;; \
    esac; \
  done; \
  test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
subdir = include/drawstuff
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
	$(top_srcdir)/m4/pkg.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
	$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \
	$(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/ode/src/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo "  GEN     " $@;
am__v_GEN_1 = 
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 = 
SOURCES =
DIST_SOURCES =
am__can_run_installinfo = \
  case $$AM_UPDATE_INFO_DIR in \
    n|no|NO) false;; \
    *) (install-info --version) >/dev/null 2>&1;; \
  esac
HEADERS = $(noinst_HEADERS)
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates.  Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
  BEGIN { nonempty = 0; } \
  { items[$$0] = 1; nonempty = 1; } \
  END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique.  This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
  list='$(am__tagged_files)'; \
  unique=`for i in $$list; do \
    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
  done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
am__DIST_COMMON = $(srcdir)/Makefile.in
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
ALLOCA = @ALLOCA@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
AS = @AS@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CCD_CFLAGS = @CCD_CFLAGS@
CCD_LIBS = @CCD_LIBS@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
DOXYGEN = @DOXYGEN@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
EXTRA_LIBTOOL_LDFLAGS = @EXTRA_LIBTOOL_LDFLAGS@
FGREP = @FGREP@
GL_LIBS = @GL_LIBS@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBSTDCXX = @LIBSTDCXX@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
ODE_PRECISION = @ODE_PRECISION@
ODE_VERSION = @ODE_VERSION@
ODE_VERSION_INFO = @ODE_VERSION_INFO@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
WINDRES = @WINDRES@
X11_CFLAGS = @X11_CFLAGS@
X11_LIBS = @X11_LIBS@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
ac_ct_WINDRES = @ac_ct_WINDRES@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
subdirs = @subdirs@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
noinst_HEADERS = drawstuff.h version.h
all: all-am

.SUFFIXES:
$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
	@for dep in $?; do \
	  case '$(am__configure_deps)' in \
	    *$$dep*) \
	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
	        && { if test -f $@; then exit 0; else break; fi; }; \
	      exit 1;; \
	  esac; \
	done; \
	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign include/drawstuff/Makefile'; \
	$(am__cd) $(top_srcdir) && \
	  $(AUTOMAKE) --foreign include/drawstuff/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
	@case '$?' in \
	  *config.status*) \
	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
	  *) \
	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
	esac;

$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh

$(top_srcdir)/configure:  $(am__configure_deps)
	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):

mostlyclean-libtool:
	-rm -f *.lo

clean-libtool:
	-rm -rf .libs _libs

ID: $(am__tagged_files)
	$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-am
TAGS: tags

tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
	set x; \
	here=`pwd`; \
	$(am__define_uniq_tagged_files); \
	shift; \
	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
	  test -n "$$unique" || unique=$$empty_fix; \
	  if test $$# -gt 0; then \
	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
	      "$$@" $$unique; \
	  else \
	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
	      $$unique; \
	  fi; \
	fi
ctags: ctags-am

CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
	$(am__define_uniq_tagged_files); \
	test -z "$(CTAGS_ARGS)$$unique" \
	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
	     $$unique

GTAGS:
	here=`$(am__cd) $(top_builddir) && pwd` \
	  && $(am__cd) $(top_srcdir) \
	  && gtags -i $(GTAGS_ARGS) "$$here"
cscopelist: cscopelist-am

cscopelist-am: $(am__tagged_files)
	list='$(am__tagged_files)'; \
	case "$(srcdir)" in \
	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
	  *) sdir=$(subdir)/$(srcdir) ;; \
	esac; \
	for i in $$list; do \
	  if test -f "$$i"; then \
	    echo "$(subdir)/$$i"; \
	  else \
	    echo "$$sdir/$$i"; \
	  fi; \
	done >> $(top_builddir)/cscope.files

distclean-tags:
	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags

distdir: $(DISTFILES)
	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
	list='$(DISTFILES)'; \
	  dist_files=`for file in $$list; do echo $$file; done | \
	  sed -e "s|^$$srcdirstrip/||;t" \
	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
	case $$dist_files in \
	  */*) $(MKDIR_P) `echo "$$dist_files" | \
			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
			   sort -u` ;; \
	esac; \
	for file in $$dist_files; do \
	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
	  if test -d $$d/$$file; then \
	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
	    if test -d "$(distdir)/$$file"; then \
	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
	    fi; \
	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
	    fi; \
	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
	  else \
	    test -f "$(distdir)/$$file" \
	    || cp -p $$d/$$file "$(distdir)/$$file" \
	    || exit 1; \
	  fi; \
	done
check-am: all-am
check: check-am
all-am: Makefile $(HEADERS)
installdirs:
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am

install-am: all-am
	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am

installcheck: installcheck-am
install-strip:
	if test -z '$(STRIP)'; then \
	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
	      install; \
	else \
	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
	fi
mostlyclean-generic:

clean-generic:

distclean-generic:
	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)

maintainer-clean-generic:
	@echo "This command is intended for maintainers to use"
	@echo "it deletes files that may require special tools to rebuild."
clean: clean-am

clean-am: clean-generic clean-libtool mostlyclean-am

distclean: distclean-am
	-rm -f Makefile
distclean-am: clean-am distclean-generic distclean-tags

dvi: dvi-am

dvi-am:

html: html-am

html-am:

info: info-am

info-am:

install-data-am:

install-dvi: install-dvi-am

install-dvi-am:

install-exec-am:

install-html: install-html-am

install-html-am:

install-info: install-info-am

install-info-am:

install-man:

install-pdf: install-pdf-am

install-pdf-am:

install-ps: install-ps-am

install-ps-am:

installcheck-am:

maintainer-clean: maintainer-clean-am
	-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic

mostlyclean: mostlyclean-am

mostlyclean-am: mostlyclean-generic mostlyclean-libtool

pdf: pdf-am

pdf-am:

ps: ps-am

ps-am:

uninstall-am:

.MAKE: install-am install-strip

.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
	clean-libtool cscopelist-am ctags ctags-am distclean \
	distclean-generic distclean-libtool distclean-tags distdir dvi \
	dvi-am html html-am info info-am install install-am \
	install-data install-data-am install-dvi install-dvi-am \
	install-exec install-exec-am install-html install-html-am \
	install-info install-info-am install-man install-pdf \
	install-pdf-am install-ps install-ps-am install-strip \
	installcheck installcheck-am installdirs maintainer-clean \
	maintainer-clean-generic mostlyclean mostlyclean-generic \
	mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
	uninstall-am

.PRECIOUS: Makefile


# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
ode-0.16/include/ode/0000775000175200017520000000000013403273060011406 500000000000000ode-0.16/include/ode/objects.h0000664000175200017520000032244613403272463013151 00000000000000/*************************************************************************
 *                                                                       *
 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
 * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
 *                                                                       *
 * This library is free software; you can redistribute it and/or         *
 * modify it under the terms of EITHER:                                  *
 *   (1) The GNU Lesser General Public License as published by the Free  *
 *       Software Foundation; either version 2.1 of the License, or (at  *
 *       your option) any later version. The text of the GNU Lesser      *
 *       General Public License is included with this library in the     *
 *       file LICENSE.TXT.                                               *
 *   (2) The BSD-style license that is included with this library in     *
 *       the file LICENSE-BSD.TXT.                                       *
 *                                                                       *
 * This library is distributed in the hope that it will be useful,       *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
 * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
 *                                                                       *
 *************************************************************************/

#ifndef _ODE_OBJECTS_H_
#define _ODE_OBJECTS_H_

#include 
#include 
#include 
#include 

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @defgroup world World
 *
 * The world object is a container for rigid bodies and joints. Objects in
 * different worlds can not interact, for example rigid bodies from two
 * different worlds can not collide.
 *
 * All the objects in a world exist at the same point in time, thus one
 * reason to use separate worlds is to simulate systems at different rates.
 * Most applications will only need one world.
 */

/**
 * @brief Create a new, empty world and return its ID number.
 * @return an identifier
 * @ingroup world
 */
ODE_API dWorldID dWorldCreate(void);


/**
 * @brief Destroy a world and everything in it.
 *
 * This includes all bodies, and all joints that are not part of a joint
 * group. Joints that are part of a joint group will be deactivated, and
 * can be destroyed by calling, for example, dJointGroupEmpty().
 * @ingroup world
 * @param world the identifier for the world the be destroyed.
 */
ODE_API void dWorldDestroy (dWorldID world);


/**
 * @brief Set the user-data pointer
 * @param world the world to set the data on
 * @param data
 * @ingroup world
 */
ODE_API void dWorldSetData (dWorldID world, void* data);


/**
 * @brief Get the user-data pointer
 * @param world the world to set the data on
 * @param data
 * @ingroup world
 */
ODE_API void* dWorldGetData (dWorldID world);


/**
 * @brief Set the world's global gravity vector.
 *
 * The units are m/s^2, so Earth's gravity vector would be (0,0,-9.81),
 * assuming that +z is up. The default is no gravity, i.e. (0,0,0).
 *
 * @ingroup world
 */
ODE_API void dWorldSetGravity (dWorldID, dReal x, dReal y, dReal z);


/**
 * @brief Get the gravity vector for a given world.
 * @ingroup world
 */
ODE_API void dWorldGetGravity (dWorldID, dVector3 gravity);


/**
 * @brief Set the global ERP value, that controls how much error
 * correction is performed in each time step.
 * @ingroup world
 * @param dWorldID the identifier of the world.
 * @param erp Typical values are in the range 0.1--0.8. The default is 0.2.
 */
ODE_API void dWorldSetERP (dWorldID, dReal erp);

/**
 * @brief Get the error reduction parameter.
 * @ingroup world
 * @return ERP value
 */
ODE_API dReal dWorldGetERP (dWorldID);


/**
 * @brief Set the global CFM (constraint force mixing) value.
 * @ingroup world
 * @param cfm Typical values are in the range @m{10^{-9}} -- 1.
 * The default is 10^-5 if single precision is being used, or 10^-10
 * if double precision is being used.
 */
ODE_API void dWorldSetCFM (dWorldID, dReal cfm);

/**
 * @brief Get the constraint force mixing value.
 * @ingroup world
 * @return CFM value
 */
ODE_API dReal dWorldGetCFM (dWorldID);


#define dWORLDSTEP_THREADCOUNT_UNLIMITED	dTHREADING_THREAD_COUNT_UNLIMITED

/**
 * @brief Set maximum threads to be used for island stepping
 *
 * The actual number of threads that is going to be used will be the minimum
 * of this limit and number of threads in the threading pool. By default 
 * there is no limit (@c dWORLDSTEP_THREADCOUNT_UNLIMITED).
 *
 * @warning
 * WARNING! Running island stepping in multiple threads requires allocating 
 * individual stepping memory buffer for each of those threads. The size of buffers
 * allocated is the size needed to handle the largest island in the world.
 *
 * Note: Setting a limit for island stepping does not affect threading at lower
 * levels in stepper functions. The sub-calls scheduled from them can be executed
 * in as many threads as there are available in the pool.
 *
 * @param w The world affected
 * @param count Thread count limit value for island stepping
 * @ingroup world
 * @see dWorldGetStepIslandsProcessingMaxThreadCount
 */
ODE_API void dWorldSetStepIslandsProcessingMaxThreadCount(dWorldID w, unsigned count);
/**
 * @brief Get maximum threads that are allowed to be used for island stepping.
 *
 * Please read commentaries to @c dWorldSetStepIslandsProcessingMaxThreadCount for 
 * important information regarding the value returned.
 *
 * @param w The world queried
 * @returns Current thread count limit value for island stepping
 * @ingroup world
 * @see dWorldSetStepIslandsProcessingMaxThreadCount
 */
ODE_API unsigned dWorldGetStepIslandsProcessingMaxThreadCount(dWorldID w);

/**
 * @brief Set the world to use shared working memory along with another world.
 *
 * The worlds allocate working memory internally for simulation stepping. This
 * memory is cached among the calls to @c dWordStep and @c dWorldQuickStep. 
 * Similarly, several worlds can be set up to share this memory caches thus 
 * reducing overall memory usage by cost of making worlds inappropriate for 
 * simultaneous simulation in multiple threads.
 *
 * If null value is passed for @a from_world parameter the world is detached from 
 * sharing and returns to defaults for working memory, reservation policy and 
 * memory manager as if just created. This can also be used to enable use of shared 
 * memory for a world that has already had working memory allocated privately.
 * Normally using shared memory after a world has its private working memory allocated
 * is prohibited.
 *
 * Allocation policy used can only increase world's internal reserved memory size
 * and never decreases it. @c dWorldCleanupWorkingMemory can be used to release 
 * working memory for a world in case if number of objects/joint decreases 
 * significantly in it.
 *
 * With sharing working memory worlds also automatically share memory reservation 
 * policy and memory manager. Thus, these parameters need to be customized for
 * initial world to be used as sharing source only.
 *
 * If worlds share working memory they must also use compatible threading implementations
 * (i.e. it is illegal for one world to perform stepping with self-threaded implementation
 * when the other world is assigned a multi-threaded implementation). 
 * For more information read section about threading approaches in ODE.
 *
 * Failure result status means a memory allocation failure.
 *
 * @param w The world to use the shared memory with.
 * @param from_world Null or the world the shared memory is to be used from.
 * @returns 1 for success and 0 for failure.
 *
 * @ingroup world
 * @see dWorldCleanupWorkingMemory
 * @see dWorldSetStepMemoryReservationPolicy
 * @see dWorldSetStepMemoryManager
 */
ODE_API int dWorldUseSharedWorkingMemory(dWorldID w, dWorldID from_world/*=NULL*/);

/**
 * @brief Release internal working memory allocated for world
 *
 * The worlds allocate working memory internally for simulation stepping. This 
 * function can be used to free world's internal memory cache in case if number of
 * objects/joints in the world decreases significantly. By default, internal 
 * allocation policy is used to only increase cache size as necessary and never 
 * decrease it.
 *
 * If a world shares its working memory with other worlds the cache deletion 
 * affects all the linked worlds. However the shared status itself remains intact.
 *
 * The function call does affect neither memory reservation policy nor memory manager.
 *
 * @param w The world to release working memory for.
 *
 * @ingroup world
 * @see dWorldUseSharedWorkingMemory
 * @see dWorldSetStepMemoryReservationPolicy
 * @see dWorldSetStepMemoryManager
 */
ODE_API void dWorldCleanupWorkingMemory(dWorldID w);


#define dWORLDSTEP_RESERVEFACTOR_DEFAULT    1.2f
#define dWORLDSTEP_RESERVESIZE_DEFAULT      65536U

/**
 * @struct dWorldStepReserveInfo
 * @brief Memory reservation policy descriptor structure for world stepping functions.
 *
 * @c struct_size should be assigned the size of the structure.
 *
 * @c reserve_factor is a quotient that is multiplied by required memory size
 *  to allocate extra reserve whenever reallocation is needed.
 *
 * @c reserve_minimum is a minimum size that is checked against whenever reallocation 
 * is needed to allocate expected working memory minimum at once without extra 
 * reallocations as number of bodies/joints grows.
 *
 * @ingroup world
 * @see dWorldSetStepMemoryReservationPolicy
 */
typedef struct
{
  unsigned struct_size;
  float reserve_factor; /* Use float as precision does not matter here*/
  unsigned reserve_minimum;

} dWorldStepReserveInfo;

/**
 * @brief Set memory reservation policy for world to be used with simulation stepping functions
 *
 * The function allows to customize reservation policy to be used for internal
 * memory which is allocated to aid simulation for a world. By default, values
 * of @c dWORLDSTEP_RESERVEFACTOR_DEFAULT and @c dWORLDSTEP_RESERVESIZE_DEFAULT
 * are used.
 *
 * Passing @a policyinfo argument as NULL results in reservation policy being
 * reset to defaults as if the world has been just created. The content of 
 * @a policyinfo structure is copied internally and does not need to remain valid
 * after the call returns.
 *
 * If the world uses working memory sharing, changing memory reservation policy
 * affects all the worlds linked together.
 *
 * Failure result status means a memory allocation failure.
 *
 * @param w The world to change memory reservation policy for.
 * @param policyinfo Null or a pointer to policy descriptor structure.
 * @returns 1 for success and 0 for failure.
 *
 * @ingroup world
 * @see dWorldUseSharedWorkingMemory
 */
ODE_API int dWorldSetStepMemoryReservationPolicy(dWorldID w, const dWorldStepReserveInfo *policyinfo/*=NULL*/);

/**
* @struct dWorldStepMemoryFunctionsInfo
* @brief World stepping memory manager descriptor structure
*
* This structure is intended to define the functions of memory manager to be used
* with world stepping functions.
*
* @c struct_size should be assigned the size of the structure
*
* @c alloc_block is a function to allocate memory block of given size.
*
* @c shrink_block is a function to shrink existing memory block to a smaller size.
* It must preserve the contents of block head while shrinking. The new block size
* is guaranteed to be always less than the existing one.
*
* @c free_block is a function to delete existing memory block.
*
* @ingroup init
* @see dWorldSetStepMemoryManager
*/
typedef struct 
{
  unsigned struct_size;
  void *(*alloc_block)(dsizeint block_size);
  void *(*shrink_block)(void *block_pointer, dsizeint block_current_size, dsizeint block_smaller_size);
  void (*free_block)(void *block_pointer, dsizeint block_current_size);

} dWorldStepMemoryFunctionsInfo;

/**
* @brief Set memory manager for world to be used with simulation stepping functions
*
* The function allows to customize memory manager to be used for internal
* memory allocation during simulation for a world. By default, @c dAlloc/@c dRealloc/@c dFree
* based memory manager is used.
*
* Passing @a memfuncs argument as NULL results in memory manager being
* reset to default one as if the world has been just created. The content of 
* @a memfuncs structure is copied internally and does not need to remain valid
* after the call returns.
*
* If the world uses working memory sharing, changing memory manager
* affects all the worlds linked together. 
*
* Failure result status means a memory allocation failure.
*
* @param w The world to change memory reservation policy for.
* @param memfuncs Null or a pointer to memory manager descriptor structure.
* @returns 1 for success and 0 for failure.
*
* @ingroup world
* @see dWorldUseSharedWorkingMemory
*/
ODE_API int dWorldSetStepMemoryManager(dWorldID w, const dWorldStepMemoryFunctionsInfo *memfuncs);

/**
 * @brief Assign threading implementation to be used for [quick]stepping the world.
 *
 * @warning It is not recommended to assign the same threading implementation to
 * different worlds if they are going to be called in parallel. In particular this
 * makes resources preallocation for threaded calls to lose its sense. 
 * Built-in threading implementation is likely to crash if misused this way.
 * 
 * @param w The world to change threading implementation for.
 * @param functions_info Pointer to threading functions structure
 * @param threading_impl ID of threading implementation object
 * 
 * @ingroup world
 */
ODE_API void dWorldSetStepThreadingImplementation(dWorldID w, const dThreadingFunctionsInfo *functions_info, dThreadingImplementationID threading_impl);

/**
 * @brief Step the world.
 *
 * This uses a "big matrix" method that takes time on the order of m^3
 * and memory on the order of m^2, where m is the total number of constraint
 * rows. For large systems this will use a lot of memory and can be very slow,
 * but this is currently the most accurate method.
 *
 * Failure result status means that the memory allocation has failed for operation.
 * In such a case all the objects remain in unchanged state and simulation can be
 * retried as soon as more memory is available.
 *
 * @param w The world to be stepped
 * @param stepsize The number of seconds that the simulation has to advance.
 * @returns 1 for success and 0 for failure
 *
 * @ingroup world
 */
ODE_API int dWorldStep (dWorldID w, dReal stepsize);

/**
 * @brief Quick-step the world.
 *
 * This uses an iterative method that takes time on the order of m*N
 * and memory on the order of m, where m is the total number of constraint
 * rows N is the number of iterations.
 * For large systems this is a lot faster than dWorldStep(),
 * but it is less accurate.
 *
 * QuickStep is great for stacks of objects especially when the
 * auto-disable feature is used as well.
 * However, it has poor accuracy for near-singular systems.
 * Near-singular systems can occur when using high-friction contacts, motors,
 * or certain articulated structures. For example, a robot with multiple legs
 * sitting on the ground may be near-singular.
 *
 * There are ways to help overcome QuickStep's inaccuracy problems:
 *
 * \li Increase CFM.
 * \li Reduce the number of contacts in your system (e.g. use the minimum
 *     number of contacts for the feet of a robot or creature).
 * \li Don't use excessive friction in the contacts.
 * \li Use contact slip if appropriate
 * \li Avoid kinematic loops (however, kinematic loops are inevitable in
 *     legged creatures).
 * \li Don't use excessive motor strength.
 * \liUse force-based motors instead of velocity-based motors.
 *
 * Increasing the number of QuickStep iterations may help a little bit, but
 * it is not going to help much if your system is really near singular.
 *
 * Failure result status means that the memory allocation has failed for operation.
 * In such a case all the objects remain in unchanged state and simulation can be
 * retried as soon as more memory is available.
 *
 * @param w The world to be stepped
 * @param stepsize The number of seconds that the simulation has to advance.
 * @returns 1 for success and 0 for failure
 *
 * @ingroup world
 */
ODE_API int dWorldQuickStep (dWorldID w, dReal stepsize);


/**
* @brief Converts an impulse to a force.
* @ingroup world
* @remarks
* If you want to apply a linear or angular impulse to a rigid body,
* instead of a force or a torque, then you can use this function to convert
* the desired impulse into a force/torque vector before calling the
* BodyAdd... function.
* The current algorithm simply scales the impulse by 1/stepsize,
* where stepsize is the step size for the next step that will be taken.
* This function is given a dWorldID because, in the future, the force
* computation may depend on integrator parameters that are set as
* properties of the world.
*/
ODE_API void dWorldImpulseToForce
(
 dWorldID, dReal stepsize,
 dReal ix, dReal iy, dReal iz, dVector3 force
 );


/**
 * @brief Set the number of iterations that the QuickStep method performs per
 *        step.
 * @ingroup world
 * @remarks
 * More iterations will give a more accurate solution, but will take
 * longer to compute.
 * @param num The default is 20 iterations.
 */
ODE_API void dWorldSetQuickStepNumIterations (dWorldID, int num);


/**
 * @brief Get the number of iterations that the QuickStep method performs per
 *        step.
 * @ingroup world
 * @return nr of iterations
 */
ODE_API int dWorldGetQuickStepNumIterations (dWorldID);

/**
 * @brief Set the SOR over-relaxation parameter
 * @ingroup world
 * @param over_relaxation value to use by SOR
 */
ODE_API void dWorldSetQuickStepW (dWorldID, dReal over_relaxation);

/**
 * @brief Get the SOR over-relaxation parameter
 * @ingroup world
 * @returns the over-relaxation setting
 */
ODE_API dReal dWorldGetQuickStepW (dWorldID);

/* World contact parameter functions */

/**
 * @brief Set the maximum correcting velocity that contacts are allowed
 * to generate.
 * @ingroup world
 * @param vel The default value is infinity (i.e. no limit).
 * @remarks
 * Reducing this value can help prevent "popping" of deeply embedded objects.
 */
ODE_API void dWorldSetContactMaxCorrectingVel (dWorldID, dReal vel);

/**
 * @brief Get the maximum correcting velocity that contacts are allowed
 * to generated.
 * @ingroup world
 */
ODE_API dReal dWorldGetContactMaxCorrectingVel (dWorldID);

/**
 * @brief Set the depth of the surface layer around all geometry objects.
 * @ingroup world
 * @remarks
 * Contacts are allowed to sink into the surface layer up to the given
 * depth before coming to rest.
 * @param depth The default value is zero.
 * @remarks
 * Increasing this to some small value (e.g. 0.001) can help prevent
 * jittering problems due to contacts being repeatedly made and broken.
 */
ODE_API void dWorldSetContactSurfaceLayer (dWorldID, dReal depth);

/**
 * @brief Get the depth of the surface layer around all geometry objects.
 * @ingroup world
 * @returns the depth
 */
ODE_API dReal dWorldGetContactSurfaceLayer (dWorldID);


/**
 * @defgroup disable Automatic Enabling and Disabling
 * @ingroup world bodies
 *
 * Every body can be enabled or disabled. Enabled bodies participate in the
 * simulation, while disabled bodies are turned off and do not get updated
 * during a simulation step. New bodies are always created in the enabled state.
 *
 * A disabled body that is connected through a joint to an enabled body will be
 * automatically re-enabled at the next simulation step.
 *
 * Disabled bodies do not consume CPU time, therefore to speed up the simulation
 * bodies should be disabled when they come to rest. This can be done automatically
 * with the auto-disable feature.
 *
 * If a body has its auto-disable flag turned on, it will automatically disable
 * itself when
 *   @li It has been idle for a given number of simulation steps.
 *   @li It has also been idle for a given amount of simulation time.
 *
 * A body is considered to be idle when the magnitudes of both its
 * linear average velocity and angular average velocity are below given thresholds.
 * The sample size for the average defaults to one and can be disabled by setting
 * to zero with 
 *
 * Thus, every body has six auto-disable parameters: an enabled flag, a idle step
 * count, an idle time, linear/angular average velocity thresholds, and the
 * average samples count.
 *
 * Newly created bodies get these parameters from world.
 */

/**
 * @brief Get auto disable linear average threshold for newly created bodies.
 * @ingroup disable
 * @return the threshold
 */
ODE_API dReal dWorldGetAutoDisableLinearThreshold (dWorldID);

/**
 * @brief Set auto disable linear average threshold for newly created bodies.
 * @param linear_average_threshold default is 0.01
 * @ingroup disable
 */
ODE_API void  dWorldSetAutoDisableLinearThreshold (dWorldID, dReal linear_average_threshold);

/**
 * @brief Get auto disable angular average threshold for newly created bodies.
 * @ingroup disable
 * @return the threshold
 */
ODE_API dReal dWorldGetAutoDisableAngularThreshold (dWorldID);

/**
 * @brief Set auto disable angular average threshold for newly created bodies.
 * @param linear_average_threshold default is 0.01
 * @ingroup disable
 */
ODE_API void dWorldSetAutoDisableAngularThreshold (dWorldID, dReal angular_average_threshold);

/**
 * @brief Get auto disable sample count for newly created bodies.
 * @ingroup disable
 * @return number of samples used
 */
ODE_API int dWorldGetAutoDisableAverageSamplesCount (dWorldID);

/**
 * @brief Set auto disable average sample count for newly created bodies.
 * @ingroup disable
 * @param average_samples_count Default is 1, meaning only instantaneous velocity is used.
 * Set to zero to disable sampling and thus prevent any body from auto-disabling.
 */
ODE_API void dWorldSetAutoDisableAverageSamplesCount (dWorldID, unsigned int average_samples_count );

/**
 * @brief Get auto disable steps for newly created bodies.
 * @ingroup disable
 * @return nr of steps
 */
ODE_API int dWorldGetAutoDisableSteps (dWorldID);

/**
 * @brief Set auto disable steps for newly created bodies.
 * @ingroup disable
 * @param steps default is 10
 */
ODE_API void dWorldSetAutoDisableSteps (dWorldID, int steps);

/**
 * @brief Get auto disable time for newly created bodies.
 * @ingroup disable
 * @return nr of seconds
 */
ODE_API dReal dWorldGetAutoDisableTime (dWorldID);

/**
 * @brief Set auto disable time for newly created bodies.
 * @ingroup disable
 * @param time default is 0 seconds
 */
ODE_API void dWorldSetAutoDisableTime (dWorldID, dReal time);

/**
 * @brief Get auto disable flag for newly created bodies.
 * @ingroup disable
 * @return 0 or 1
 */
ODE_API int dWorldGetAutoDisableFlag (dWorldID);

/**
 * @brief Set auto disable flag for newly created bodies.
 * @ingroup disable
 * @param do_auto_disable default is false.
 */
ODE_API void dWorldSetAutoDisableFlag (dWorldID, int do_auto_disable);


/**
 * @defgroup damping Damping
 * @ingroup bodies world
 *
 * Damping serves two purposes: reduce simulation instability, and to allow
 * the bodies to come to rest (and possibly auto-disabling them).
 *
 * Bodies are constructed using the world's current damping parameters. Setting
 * the scales to 0 disables the damping.
 *
 * Here is how it is done: after every time step linear and angular
 * velocities are tested against the corresponding thresholds. If they
 * are above, they are multiplied by (1 - scale). So a negative scale value
 * will actually increase the speed, and values greater than one will
 * make the object oscillate every step; both can make the simulation unstable.
 *
 * To disable damping just set the damping scale to zero.
 *
 * You can also limit the maximum angular velocity. In contrast to the damping
 * functions, the angular velocity is affected before the body is moved.
 * This means that it will introduce errors in joints that are forcing the body
 * to rotate too fast. Some bodies have naturally high angular velocities
 * (like cars' wheels), so you may want to give them a very high (like the default,
 * dInfinity) limit.
 *
 * @note The velocities are damped after the stepper function has moved the
 * object. Otherwise the damping could introduce errors in joints. First the
 * joint constraints are processed by the stepper (moving the body), then
 * the damping is applied.
 *
 * @note The damping happens right after the moved callback is called; this way 
 * it still possible use the exact velocities the body has acquired during the
 * step. You can even use the callback to create your own customized damping.
 */

/**
 * @brief Get the world's linear damping threshold.
 * @ingroup damping
 */
ODE_API dReal dWorldGetLinearDampingThreshold (dWorldID w);

/**
 * @brief Set the world's linear damping threshold.
 * @param threshold The damping won't be applied if the linear speed is
 *        below this threshold. Default is 0.01.
 * @ingroup damping
 */
ODE_API void dWorldSetLinearDampingThreshold(dWorldID w, dReal threshold);

/**
 * @brief Get the world's angular damping threshold.
 * @ingroup damping
 */
ODE_API dReal dWorldGetAngularDampingThreshold (dWorldID w);

/**
 * @brief Set the world's angular damping threshold.
 * @param threshold The damping won't be applied if the angular speed is
 *        below this threshold. Default is 0.01.
 * @ingroup damping
 */
ODE_API void dWorldSetAngularDampingThreshold(dWorldID w, dReal threshold);

/**
 * @brief Get the world's linear damping scale.
 * @ingroup damping
 */
ODE_API dReal dWorldGetLinearDamping (dWorldID w);

/**
 * @brief Set the world's linear damping scale.
 * @param scale The linear damping scale that is to be applied to bodies.
 * Default is 0 (no damping). Should be in the interval [0, 1].
 * @ingroup damping
 */
ODE_API void dWorldSetLinearDamping (dWorldID w, dReal scale);

/**
 * @brief Get the world's angular damping scale.
 * @ingroup damping
 */
ODE_API dReal dWorldGetAngularDamping (dWorldID w);

/**
 * @brief Set the world's angular damping scale.
 * @param scale The angular damping scale that is to be applied to bodies.
 * Default is 0 (no damping). Should be in the interval [0, 1].
 * @ingroup damping
 */
ODE_API void dWorldSetAngularDamping(dWorldID w, dReal scale);

/**
 * @brief Convenience function to set body linear and angular scales.
 * @param linear_scale The linear damping scale that is to be applied to bodies.
 * @param angular_scale The angular damping scale that is to be applied to bodies.
 * @ingroup damping
 */
ODE_API void dWorldSetDamping(dWorldID w,
                                dReal linear_scale,
                                dReal angular_scale);

/**
 * @brief Get the default maximum angular speed.
 * @ingroup damping
 * @sa dBodyGetMaxAngularSpeed()
 */
ODE_API dReal dWorldGetMaxAngularSpeed (dWorldID w);


/**
 * @brief Set the default maximum angular speed for new bodies.
 * @ingroup damping
 * @sa dBodySetMaxAngularSpeed()
 */
ODE_API void dWorldSetMaxAngularSpeed (dWorldID w, dReal max_speed);



/**
 * @defgroup bodies Rigid Bodies
 *
 * A rigid body has various properties from the point of view of the
 * simulation. Some properties change over time:
 *
 *  @li Position vector (x,y,z) of the body's point of reference.
 *      Currently the point of reference must correspond to the body's center of mass.
 *  @li Linear velocity of the point of reference, a vector (vx,vy,vz).
 *  @li Orientation of a body, represented by a quaternion (qs,qx,qy,qz) or
 *      a 3x3 rotation matrix.
 *  @li Angular velocity vector (wx,wy,wz) which describes how the orientation
 *      changes over time.
 *
 * Other body properties are usually constant over time:
 *
 *  @li Mass of the body.
 *  @li Position of the center of mass with respect to the point of reference.
 *      In the current implementation the center of mass and the point of
 *      reference must coincide.
 *  @li Inertia matrix. This is a 3x3 matrix that describes how the body's mass
 *      is distributed around the center of mass. Conceptually each body has an
 *      x-y-z coordinate frame embedded in it that moves and rotates with the body.
 *
 * The origin of this coordinate frame is the body's point of reference. Some values
 * in ODE (vectors, matrices etc) are relative to the body coordinate frame, and others
 * are relative to the global coordinate frame.
 *
 * Note that the shape of a rigid body is not a dynamical property (except insofar as
 * it influences the various mass properties). It is only collision detection that cares
 * about the detailed shape of the body.
 */


/**
 * @brief Get auto disable linear average threshold.
 * @ingroup bodies disable
 * @return the threshold
 */
ODE_API dReal dBodyGetAutoDisableLinearThreshold (dBodyID);

/**
 * @brief Set auto disable linear average threshold.
 * @ingroup bodies disable
 * @return the threshold
 */
ODE_API void  dBodySetAutoDisableLinearThreshold (dBodyID, dReal linear_average_threshold);

/**
 * @brief Get auto disable angular average threshold.
 * @ingroup bodies disable
 * @return the threshold
 */
ODE_API dReal dBodyGetAutoDisableAngularThreshold (dBodyID);

/**
 * @brief Set auto disable angular average threshold.
 * @ingroup bodies disable
 * @return the threshold
 */
ODE_API void  dBodySetAutoDisableAngularThreshold (dBodyID, dReal angular_average_threshold);

/**
 * @brief Get auto disable average size (samples count).
 * @ingroup bodies disable
 * @return the nr of steps/size.
 */
ODE_API int dBodyGetAutoDisableAverageSamplesCount (dBodyID);

/**
 * @brief Set auto disable average buffer size (average steps).
 * @ingroup bodies disable
 * @param average_samples_count the nr of samples to review.
 */
ODE_API void dBodySetAutoDisableAverageSamplesCount (dBodyID, unsigned int average_samples_count);


/**
 * @brief Get auto steps a body must be thought of as idle to disable
 * @ingroup bodies disable
 * @return the nr of steps
 */
ODE_API int dBodyGetAutoDisableSteps (dBodyID);

/**
 * @brief Set auto disable steps.
 * @ingroup bodies disable
 * @param steps the nr of steps.
 */
ODE_API void dBodySetAutoDisableSteps (dBodyID, int steps);

/**
 * @brief Get auto disable time.
 * @ingroup bodies disable
 * @return nr of seconds
 */
ODE_API dReal dBodyGetAutoDisableTime (dBodyID);

/**
 * @brief Set auto disable time.
 * @ingroup bodies disable
 * @param time nr of seconds.
 */
ODE_API void  dBodySetAutoDisableTime (dBodyID, dReal time);

/**
 * @brief Get auto disable flag.
 * @ingroup bodies disable
 * @return 0 or 1
 */
ODE_API int dBodyGetAutoDisableFlag (dBodyID);

/**
 * @brief Set auto disable flag.
 * @ingroup bodies disable
 * @param do_auto_disable 0 or 1
 */
ODE_API void dBodySetAutoDisableFlag (dBodyID, int do_auto_disable);

/**
 * @brief Set auto disable defaults.
 * @remarks
 * Set the values for the body to those set as default for the world.
 * @ingroup bodies disable
 */
ODE_API void  dBodySetAutoDisableDefaults (dBodyID);


/**
 * @brief Retrieves the world attached to te given body.
 * @remarks
 * 
 * @ingroup bodies
 */
ODE_API dWorldID dBodyGetWorld (dBodyID);

/**
 * @brief Create a body in given world.
 * @remarks
 * Default mass parameters are at position (0,0,0).
 * @ingroup bodies
 */
ODE_API dBodyID dBodyCreate (dWorldID);

/**
 * @brief Destroy a body.
 * @remarks
 * All joints that are attached to this body will be put into limbo:
 * i.e. unattached and not affecting the simulation, but they will NOT be
 * deleted.
 * @ingroup bodies
 */
ODE_API void dBodyDestroy (dBodyID);

/**
 * @brief Set the body's user-data pointer.
 * @ingroup bodies
 * @param data arbitraty pointer
 */
ODE_API void  dBodySetData (dBodyID, void *data);

/**
 * @brief Get the body's user-data pointer.
 * @ingroup bodies
 * @return a pointer to the user's data.
 */
ODE_API void *dBodyGetData (dBodyID);

/**
 * @brief Set position of a body.
 * @remarks
 * After setting, the outcome of the simulation is undefined
 * if the new configuration is inconsistent with the joints/constraints
 * that are present.
 * @ingroup bodies
 */
ODE_API void dBodySetPosition   (dBodyID, dReal x, dReal y, dReal z);

/**
 * @brief Set the orientation of a body.
 * @ingroup bodies
 * @remarks
 * After setting, the outcome of the simulation is undefined
 * if the new configuration is inconsistent with the joints/constraints
 * that are present.
 */
ODE_API void dBodySetRotation   (dBodyID, const dMatrix3 R);

/**
 * @brief Set the orientation of a body.
 * @ingroup bodies
 * @remarks
 * After setting, the outcome of the simulation is undefined
 * if the new configuration is inconsistent with the joints/constraints
 * that are present.
 */
ODE_API void dBodySetQuaternion (dBodyID, const dQuaternion q);

/**
 * @brief Set the linear velocity of a body.
 * @ingroup bodies
 */
ODE_API void dBodySetLinearVel  (dBodyID, dReal x, dReal y, dReal z);

/**
 * @brief Set the angular velocity of a body.
 * @ingroup bodies
 */
ODE_API void dBodySetAngularVel (dBodyID, dReal x, dReal y, dReal z);

/**
 * @brief Get the position of a body.
 * @ingroup bodies
 * @remarks
 * When getting, the returned values are pointers to internal data structures,
 * so the vectors are valid until any changes are made to the rigid body
 * system structure.
 * @sa dBodyCopyPosition
 */
ODE_API const dReal * dBodyGetPosition (dBodyID);


/**
 * @brief Copy the position of a body into a vector.
 * @ingroup bodies
 * @param body  the body to query
 * @param pos   a copy of the body position
 * @sa dBodyGetPosition
 */
ODE_API void dBodyCopyPosition (dBodyID body, dVector3 pos);


/**
 * @brief Get the rotation of a body.
 * @ingroup bodies
 * @return pointer to a 4x3 rotation matrix.
 */
ODE_API const dReal * dBodyGetRotation (dBodyID);


/**
 * @brief Copy the rotation of a body.
 * @ingroup bodies
 * @param body   the body to query
 * @param R      a copy of the rotation matrix
 * @sa dBodyGetRotation
 */
ODE_API void dBodyCopyRotation (dBodyID, dMatrix3 R);


/**
 * @brief Get the rotation of a body.
 * @ingroup bodies
 * @return pointer to 4 scalars that represent the quaternion.
 */
ODE_API const dReal * dBodyGetQuaternion (dBodyID);


/**
 * @brief Copy the orientation of a body into a quaternion.
 * @ingroup bodies
 * @param body  the body to query
 * @param quat  a copy of the orientation quaternion
 * @sa dBodyGetQuaternion
 */
ODE_API void dBodyCopyQuaternion(dBodyID body, dQuaternion quat);


/**
 * @brief Get the linear velocity of a body.
 * @ingroup bodies
 */
ODE_API const dReal * dBodyGetLinearVel (dBodyID);

/**
 * @brief Get the angular velocity of a body.
 * @ingroup bodies
 */
ODE_API const dReal * dBodyGetAngularVel (dBodyID);

/**
 * @brief Set the mass of a body.
 * @ingroup bodies
 */
ODE_API void dBodySetMass (dBodyID, const dMass *mass);

/**
 * @brief Get the mass of a body.
 * @ingroup bodies
 */
ODE_API void dBodyGetMass (dBodyID, dMass *mass);

/**
 * @brief Add force at centre of mass of body in absolute coordinates.
 * @ingroup bodies
 */
ODE_API void dBodyAddForce            (dBodyID, dReal fx, dReal fy, dReal fz);

/**
 * @brief Add torque at centre of mass of body in absolute coordinates.
 * @ingroup bodies
 */
ODE_API void dBodyAddTorque           (dBodyID, dReal fx, dReal fy, dReal fz);

/**
 * @brief Add force at centre of mass of body in coordinates relative to body.
 * @ingroup bodies
 */
ODE_API void dBodyAddRelForce         (dBodyID, dReal fx, dReal fy, dReal fz);

/**
 * @brief Add torque at centre of mass of body in coordinates relative to body.
 * @ingroup bodies
 */
ODE_API void dBodyAddRelTorque        (dBodyID, dReal fx, dReal fy, dReal fz);

/**
 * @brief Add force at specified point in body in global coordinates.
 * @ingroup bodies
 */
ODE_API void dBodyAddForceAtPos       (dBodyID, dReal fx, dReal fy, dReal fz,
			                dReal px, dReal py, dReal pz);
/**
 * @brief Add force at specified point in body in local coordinates.
 * @ingroup bodies
 */
ODE_API void dBodyAddForceAtRelPos    (dBodyID, dReal fx, dReal fy, dReal fz,
			                dReal px, dReal py, dReal pz);
/**
 * @brief Add force at specified point in body in global coordinates.
 * @ingroup bodies
 */
ODE_API void dBodyAddRelForceAtPos    (dBodyID, dReal fx, dReal fy, dReal fz,
			                dReal px, dReal py, dReal pz);
/**
 * @brief Add force at specified point in body in local coordinates.
 * @ingroup bodies
 */
ODE_API void dBodyAddRelForceAtRelPos (dBodyID, dReal fx, dReal fy, dReal fz,
			                dReal px, dReal py, dReal pz);

/**
 * @brief Return the current accumulated force vector.
 * @return points to an array of 3 reals.
 * @remarks
 * The returned values are pointers to internal data structures, so
 * the vectors are only valid until any changes are made to the rigid
 * body system.
 * @ingroup bodies
 */
ODE_API const dReal * dBodyGetForce (dBodyID);

/**
 * @brief Return the current accumulated torque vector.
 * @return points to an array of 3 reals.
 * @remarks
 * The returned values are pointers to internal data structures, so
 * the vectors are only valid until any changes are made to the rigid
 * body system.
 * @ingroup bodies
 */
ODE_API const dReal * dBodyGetTorque (dBodyID);

/**
 * @brief Set the body force accumulation vector.
 * @remarks
 * This is mostly useful to zero the force and torque for deactivated bodies
 * before they are reactivated, in the case where the force-adding functions
 * were called on them while they were deactivated.
 * @ingroup bodies
 */
ODE_API void dBodySetForce  (dBodyID b, dReal x, dReal y, dReal z);

/**
 * @brief Set the body torque accumulation vector.
 * @remarks
 * This is mostly useful to zero the force and torque for deactivated bodies
 * before they are reactivated, in the case where the force-adding functions
 * were called on them while they were deactivated.
 * @ingroup bodies
 */
ODE_API void dBodySetTorque (dBodyID b, dReal x, dReal y, dReal z);

/**
 * @brief Get world position of a relative point on body.
 * @ingroup bodies
 * @param result will contain the result.
 */
ODE_API void dBodyGetRelPointPos
(
  dBodyID, dReal px, dReal py, dReal pz,
  dVector3 result
);

/**
 * @brief Get velocity vector in global coords of a relative point on body.
 * @ingroup bodies
 * @param result will contain the result.
 */
ODE_API void dBodyGetRelPointVel
(
  dBodyID, dReal px, dReal py, dReal pz,
  dVector3 result
);

/**
 * @brief Get velocity vector in global coords of a globally
 * specified point on a body.
 * @ingroup bodies
 * @param result will contain the result.
 */
ODE_API void dBodyGetPointVel
(
  dBodyID, dReal px, dReal py, dReal pz,
  dVector3 result
);

/**
 * @brief takes a point in global coordinates and returns
 * the point's position in body-relative coordinates.
 * @remarks
 * This is the inverse of dBodyGetRelPointPos()
 * @ingroup bodies
 * @param result will contain the result.
 */
ODE_API void dBodyGetPosRelPoint
(
  dBodyID, dReal px, dReal py, dReal pz,
  dVector3 result
);

/**
 * @brief Convert from local to world coordinates.
 * @ingroup bodies
 * @param result will contain the result.
 */
ODE_API void dBodyVectorToWorld
(
  dBodyID, dReal px, dReal py, dReal pz,
  dVector3 result
);

/**
 * @brief Convert from world to local coordinates.
 * @ingroup bodies
 * @param result will contain the result.
 */
ODE_API void dBodyVectorFromWorld
(
  dBodyID, dReal px, dReal py, dReal pz,
  dVector3 result
);

/**
 * @brief controls the way a body's orientation is updated at each timestep.
 * @ingroup bodies
 * @param mode can be 0 or 1:
 * \li 0: An ``infinitesimal'' orientation update is used.
 * This is fast to compute, but it can occasionally cause inaccuracies
 * for bodies that are rotating at high speed, especially when those
 * bodies are joined to other bodies.
 * This is the default for every new body that is created.
 * \li 1: A ``finite'' orientation update is used.
 * This is more costly to compute, but will be more accurate for high
 * speed rotations.
 * @remarks
 * Note however that high speed rotations can result in many types of
 * error in a simulation, and the finite mode will only fix one of those
 * sources of error.
 */
ODE_API void dBodySetFiniteRotationMode (dBodyID, int mode);

/**
 * @brief sets the finite rotation axis for a body.
 * @ingroup bodies
 * @remarks
 * This is axis only has meaning when the finite rotation mode is set
 * If this axis is zero (0,0,0), full finite rotations are performed on
 * the body.
 * If this axis is nonzero, the body is rotated by performing a partial finite
 * rotation along the axis direction followed by an infinitesimal rotation
 * along an orthogonal direction.
 * @remarks
 * This can be useful to alleviate certain sources of error caused by quickly
 * spinning bodies. For example, if a car wheel is rotating at high speed
 * you can call this function with the wheel's hinge axis as the argument to
 * try and improve its behavior.
 */
ODE_API void dBodySetFiniteRotationAxis (dBodyID, dReal x, dReal y, dReal z);

/**
 * @brief Get the way a body's orientation is updated each timestep.
 * @ingroup bodies
 * @return the mode 0 (infitesimal) or 1 (finite).
 */
ODE_API int dBodyGetFiniteRotationMode (dBodyID);

/**
 * @brief Get the finite rotation axis.
 * @param result will contain the axis.
 * @ingroup bodies
 */
ODE_API void dBodyGetFiniteRotationAxis (dBodyID, dVector3 result);

/**
 * @brief Get the number of joints that are attached to this body.
 * @ingroup bodies
 * @return nr of joints
 */
ODE_API int dBodyGetNumJoints (dBodyID b);

/**
 * @brief Return a joint attached to this body, given by index.
 * @ingroup bodies
 * @param index valid range is  0 to n-1 where n is the value returned by
 * dBodyGetNumJoints().
 */
ODE_API dJointID dBodyGetJoint (dBodyID, int index);




/**
 * @brief Set rigid body to dynamic state (default).
 * @param dBodyID identification of body.
 * @ingroup bodies
 */
ODE_API void dBodySetDynamic (dBodyID);

/**
 * @brief Set rigid body to kinematic state.
 * When in kinematic state the body isn't simulated as a dynamic
 * body (it's "unstoppable", doesn't respond to forces),
 * but can still affect dynamic bodies (e.g. in joints).
 * Kinematic bodies can be controlled by position and velocity.
 * @note A kinematic body has infinite mass. If you set its mass
 * to something else, it loses the kinematic state and behaves
 * as a normal dynamic body.
 * @param dBodyID identification of body.
 * @ingroup bodies
 */
ODE_API void dBodySetKinematic (dBodyID);

/**
 * @brief Check wether a body is in kinematic state.
 * @ingroup bodies
 * @return 1 if a body is kinematic or 0 if it is dynamic.
 */
ODE_API int dBodyIsKinematic (dBodyID);

/**
 * @brief Manually enable a body.
 * @param dBodyID identification of body.
 * @ingroup bodies
 */
ODE_API void dBodyEnable (dBodyID);

/**
 * @brief Manually disable a body.
 * @ingroup bodies
 * @remarks
 * A disabled body that is connected through a joint to an enabled body will
 * be automatically re-enabled at the next simulation step.
 */
ODE_API void dBodyDisable (dBodyID);

/**
 * @brief Check wether a body is enabled.
 * @ingroup bodies
 * @return 1 if a body is currently enabled or 0 if it is disabled.
 */
ODE_API int dBodyIsEnabled (dBodyID);

/**
 * @brief Set whether the body is influenced by the world's gravity or not.
 * @ingroup bodies
 * @param mode when nonzero gravity affects this body.
 * @remarks
 * Newly created bodies are always influenced by the world's gravity.
 */
ODE_API void dBodySetGravityMode (dBodyID b, int mode);

/**
 * @brief Get whether the body is influenced by the world's gravity or not.
 * @ingroup bodies
 * @return nonzero means gravity affects this body.
 */
ODE_API int dBodyGetGravityMode (dBodyID b);

/**
 * @brief Set the 'moved' callback of a body.
 *
 * Whenever a body has its position or rotation changed during the
 * timestep, the callback will be called (with body as the argument).
 * Use it to know which body may need an update in an external
 * structure (like a 3D engine).
 *
 * @param b the body that needs to be watched.
 * @param callback the callback to be invoked when the body moves. Set to zero
 * to disable.
 * @ingroup bodies
 */
ODE_API void dBodySetMovedCallback(dBodyID b, void (*callback)(dBodyID));


/**
 * @brief Return the first geom associated with the body.
 * 
 * You can traverse through the geoms by repeatedly calling
 * dBodyGetNextGeom().
 *
 * @return the first geom attached to this body, or 0.
 * @ingroup bodies
 */
ODE_API dGeomID dBodyGetFirstGeom (dBodyID b);


/**
 * @brief returns the next geom associated with the same body.
 * @param g a geom attached to some body.
 * @return the next geom attached to the same body, or 0.
 * @sa dBodyGetFirstGeom
 * @ingroup bodies
 */
ODE_API dGeomID dBodyGetNextGeom (dGeomID g);


/**
 * @brief Resets the damping settings to the current world's settings.
 * @ingroup bodies damping
 */
ODE_API void dBodySetDampingDefaults(dBodyID b);

/**
 * @brief Get the body's linear damping scale.
 * @ingroup bodies damping
 */
ODE_API dReal dBodyGetLinearDamping (dBodyID b);

/**
 * @brief Set the body's linear damping scale.
 * @param scale The linear damping scale. Should be in the interval [0, 1].
 * @ingroup bodies damping
 * @remarks From now on the body will not use the world's linear damping
 * scale until dBodySetDampingDefaults() is called.
 * @sa dBodySetDampingDefaults()
 */
ODE_API void dBodySetLinearDamping(dBodyID b, dReal scale);

/**
 * @brief Get the body's angular damping scale.
 * @ingroup bodies damping
 * @remarks If the body's angular damping scale was not set, this function
 * returns the world's angular damping scale.
 */
ODE_API dReal dBodyGetAngularDamping (dBodyID b);

/**
 * @brief Set the body's angular damping scale.
 * @param scale The angular damping scale. Should be in the interval [0, 1].
 * @ingroup bodies damping
 * @remarks From now on the body will not use the world's angular damping
 * scale until dBodyResetAngularDamping() is called.
 * @sa dBodyResetAngularDamping()
 */
ODE_API void dBodySetAngularDamping(dBodyID b, dReal scale);

/**
 * @brief Convenience function to set linear and angular scales at once.
 * @param linear_scale The linear damping scale. Should be in the interval [0, 1].
 * @param angular_scale The angular damping scale. Should be in the interval [0, 1].
 * @ingroup bodies damping
 * @sa dBodySetLinearDamping() dBodySetAngularDamping()
 */
ODE_API void dBodySetDamping(dBodyID b, dReal linear_scale, dReal angular_scale);

/**
 * @brief Get the body's linear damping threshold.
 * @ingroup bodies damping
 */
ODE_API dReal dBodyGetLinearDampingThreshold (dBodyID b);

/**
 * @brief Set the body's linear damping threshold.
 * @param threshold The linear threshold to be used. Damping
 *      is only applied if the linear speed is above this limit.
 * @ingroup bodies damping
 */
ODE_API void dBodySetLinearDampingThreshold(dBodyID b, dReal threshold);

/**
 * @brief Get the body's angular damping threshold.
 * @ingroup bodies damping
 */
ODE_API dReal dBodyGetAngularDampingThreshold (dBodyID b);

/**
 * @brief Set the body's angular damping threshold.
 * @param threshold The angular threshold to be used. Damping is
 *      only used if the angular speed is above this limit.
 * @ingroup bodies damping
 */
ODE_API void dBodySetAngularDampingThreshold(dBodyID b, dReal threshold);

/**
 * @brief Get the body's maximum angular speed.
 * @ingroup damping bodies
 * @sa dWorldGetMaxAngularSpeed()
 */
ODE_API dReal dBodyGetMaxAngularSpeed (dBodyID b);

/**
 * @brief Set the body's maximum angular speed.
 * @ingroup damping bodies
 * @sa dWorldSetMaxAngularSpeed() dBodyResetMaxAngularSpeed()
 * The default value is dInfinity, but it's a good idea to limit
 * it at less than 500 if the body has the gyroscopic term
 * enabled.
 */
ODE_API void dBodySetMaxAngularSpeed(dBodyID b, dReal max_speed);



/**
 * @brief Get the body's gyroscopic state.
 *
 * @return nonzero if gyroscopic term computation is enabled (default),
 * zero otherwise.
 * @ingroup bodies
 */
ODE_API int dBodyGetGyroscopicMode(dBodyID b);


/**
 * @brief Enable/disable the body's gyroscopic term.
 *
 * Disabling the gyroscopic term of a body usually improves
 * stability. It also helps turning spining objects, like cars'
 * wheels.
 *
 * @param enabled   nonzero (default) to enable gyroscopic term, 0
 * to disable.
 * @ingroup bodies
 */
ODE_API void dBodySetGyroscopicMode(dBodyID b, int enabled);




/**
 * @defgroup joints Joints
 *
 * In real life a joint is something like a hinge, that is used to connect two
 * objects.
 * In ODE a joint is very similar: It is a relationship that is enforced between
 * two bodies so that they can only have certain positions and orientations
 * relative to each other.
 * This relationship is called a constraint -- the words joint and
 * constraint are often used interchangeably.
 *
 * A joint has a set of parameters that can be set. These include:
 *
 *
 * \li  dParamLoStop Low stop angle or position. Setting this to
 *	-dInfinity (the default value) turns off the low stop.
 *	For rotational joints, this stop must be greater than -pi to be
 *	effective.
 * \li  dParamHiStop High stop angle or position. Setting this to
 *	dInfinity (the default value) turns off the high stop.
 *	For rotational joints, this stop must be less than pi to be
 *	effective.
 *	If the high stop is less than the low stop then both stops will
 *	be ineffective.
 * \li  dParamVel Desired motor velocity (this will be an angular or
 *	linear velocity).
 * \li  dParamFMax The maximum force or torque that the motor will use to
 *	achieve the desired velocity.
 *	This must always be greater than or equal to zero.
 *	Setting this to zero (the default value) turns off the motor.
 * \li  dParamFudgeFactor The current joint stop/motor implementation has
 *	a small problem:
 *	when the joint is at one stop and the motor is set to move it away
 *	from the stop, too much force may be applied for one time step,
 *	causing a ``jumping'' motion.
 *	This fudge factor is used to scale this excess force.
 *	It should have a value between zero and one (the default value).
 *	If the jumping motion is too visible in a joint, the value can be
 *	reduced.
 *	Making this value too small can prevent the motor from being able to
 *	move the joint away from a stop.
 * \li  dParamBounce The bouncyness of the stops.
 *	This is a restitution parameter in the range 0..1.
 *	0 means the stops are not bouncy at all, 1 means maximum bouncyness.
 * \li  dParamCFM The constraint force mixing (CFM) value used when not
 *	at a stop.
 * \li  dParamStopERP The error reduction parameter (ERP) used by the
 *	stops.
 * \li  dParamStopCFM The constraint force mixing (CFM) value used by the
 *	stops. Together with the ERP value this can be used to get spongy or
 *	soft stops.
 *	Note that this is intended for unpowered joints, it does not really
 *	work as expected when a powered joint reaches its limit.
 * \li  dParamSuspensionERP Suspension error reduction parameter (ERP).
 *	Currently this is only implemented on the hinge-2 joint.
 * \li  dParamSuspensionCFM Suspension constraint force mixing (CFM) value.
 *	Currently this is only implemented on the hinge-2 joint.
 *
 * If a particular parameter is not implemented by a given joint, setting it
 * will have no effect.
 * These parameter names can be optionally followed by a digit (2 or 3)
 * to indicate the second or third set of parameters, e.g. for the second axis
 * in a hinge-2 joint, or the third axis in an AMotor joint.
 */


/**
 * @brief Create a new joint of the ball type.
 * @ingroup joints
 * @remarks
 * The joint is initially in "limbo" (i.e. it has no effect on the simulation)
 * because it does not connect to any bodies.
 * @param dJointGroupID set to 0 to allocate the joint normally.
 * If it is nonzero the joint is allocated in the given joint group.
 */
ODE_API dJointID dJointCreateBall (dWorldID, dJointGroupID);

/**
 * @brief Create a new joint of the hinge type.
 * @ingroup joints
 * @param dJointGroupID set to 0 to allocate the joint normally.
 * If it is nonzero the joint is allocated in the given joint group.
 */
ODE_API dJointID dJointCreateHinge (dWorldID, dJointGroupID);

/**
 * @brief Create a new joint of the slider type.
 * @ingroup joints
 * @param dJointGroupID set to 0 to allocate the joint normally.
 * If it is nonzero the joint is allocated in the given joint group.
 */
ODE_API dJointID dJointCreateSlider (dWorldID, dJointGroupID);

/**
 * @brief Create a new joint of the contact type.
 * @ingroup joints
 * @param dJointGroupID set to 0 to allocate the joint normally.
 * If it is nonzero the joint is allocated in the given joint group.
 */
ODE_API dJointID dJointCreateContact (dWorldID, dJointGroupID, const dContact *);

/**
 * @brief Create a new joint of the hinge2 type.
 * @ingroup joints
 * @param dJointGroupID set to 0 to allocate the joint normally.
 * If it is nonzero the joint is allocated in the given joint group.
 */
ODE_API dJointID dJointCreateHinge2 (dWorldID, dJointGroupID);

/**
 * @brief Create a new joint of the universal type.
 * @ingroup joints
 * @param dJointGroupID set to 0 to allocate the joint normally.
 * If it is nonzero the joint is allocated in the given joint group.
 */
ODE_API dJointID dJointCreateUniversal (dWorldID, dJointGroupID);

/**
 * @brief Create a new joint of the PR (Prismatic and Rotoide) type.
 * @ingroup joints
 * @param dJointGroupID set to 0 to allocate the joint normally.
 * If it is nonzero the joint is allocated in the given joint group.
 */
ODE_API dJointID dJointCreatePR (dWorldID, dJointGroupID);

/**
 * @brief Create a new joint of the PU (Prismatic and Universal) type.
 * @ingroup joints
 * @param dJointGroupID set to 0 to allocate the joint normally.
 * If it is nonzero the joint is allocated in the given joint group.
 */
ODE_API dJointID dJointCreatePU (dWorldID, dJointGroupID);

/**
 * @brief Create a new joint of the Piston type.
 * @ingroup joints
 * @param dJointGroupID set to 0 to allocate the joint normally.
 *                      If it is nonzero the joint is allocated in the given
 *                      joint group.
 */
ODE_API dJointID dJointCreatePiston (dWorldID, dJointGroupID);

/**
 * @brief Create a new joint of the fixed type.
 * @ingroup joints
 * @param dJointGroupID set to 0 to allocate the joint normally.
 * If it is nonzero the joint is allocated in the given joint group.
 */
ODE_API dJointID dJointCreateFixed (dWorldID, dJointGroupID);

ODE_API dJointID dJointCreateNull (dWorldID, dJointGroupID);

/**
 * @brief Create a new joint of the A-motor type.
 * @ingroup joints
 * @param dJointGroupID set to 0 to allocate the joint normally.
 * If it is nonzero the joint is allocated in the given joint group.
 */
ODE_API dJointID dJointCreateAMotor (dWorldID, dJointGroupID);

/**
 * @brief Create a new joint of the L-motor type.
 * @ingroup joints
 * @param dJointGroupID set to 0 to allocate the joint normally.
 * If it is nonzero the joint is allocated in the given joint group.
 */
ODE_API dJointID dJointCreateLMotor (dWorldID, dJointGroupID);

/**
 * @brief Create a new joint of the plane-2d type.
 * @ingroup joints
 * @param dJointGroupID set to 0 to allocate the joint normally.
 * If it is nonzero the joint is allocated in the given joint group.
 */
ODE_API dJointID dJointCreatePlane2D (dWorldID, dJointGroupID);

/**
 * @brief Create a new joint of the double ball type.
 * @ingroup joints
 * @param dJointGroupID set to 0 to allocate the joint normally.
 * If it is nonzero the joint is allocated in the given joint group.
 */
ODE_API dJointID dJointCreateDBall (dWorldID, dJointGroupID);

/**
 * @brief Create a new joint of the double hinge type.
 * @ingroup joints
 * @param dJointGroupID set to 0 to allocate the joint normally.
 * If it is nonzero the joint is allocated in the given joint group.
 */
ODE_API dJointID dJointCreateDHinge (dWorldID, dJointGroupID);

/**
 * @brief Create a new joint of the Transmission type.
 * @ingroup joints
 * @param dJointGroupID set to 0 to allocate the joint normally.
 * If it is nonzero the joint is allocated in the given joint group.
 */
ODE_API dJointID dJointCreateTransmission (dWorldID, dJointGroupID);


/**
 * @brief Destroy a joint.
 * @ingroup joints
 *
 * disconnects it from its attached bodies and removing it from the world.
 * However, if the joint is a member of a group then this function has no
 * effect - to destroy that joint the group must be emptied or destroyed.
 */
ODE_API void dJointDestroy (dJointID);


/**
 * @brief Create a joint group
 * @ingroup joints
 * @param max_size deprecated. Set to 0.
 */
ODE_API dJointGroupID dJointGroupCreate (int max_size);

/**
 * @brief Destroy a joint group.
 * @ingroup joints
 *
 * All joints in the joint group will be destroyed.
 */
ODE_API void dJointGroupDestroy (dJointGroupID);

/**
 * @brief Empty a joint group.
 * @ingroup joints
 *
 * All joints in the joint group will be destroyed,
 * but the joint group itself will not be destroyed.
 */
ODE_API void dJointGroupEmpty (dJointGroupID);

/**
 * @brief Return the number of bodies attached to the joint
 * @ingroup joints
 */
ODE_API int dJointGetNumBodies(dJointID);

/**
 * @brief Attach the joint to some new bodies.
 * @ingroup joints
 *
 * If the joint is already attached, it will be detached from the old bodies
 * first.
 * To attach this joint to only one body, set body1 or body2 to zero - a zero
 * body refers to the static environment.
 * Setting both bodies to zero puts the joint into "limbo", i.e. it will
 * have no effect on the simulation.
 * @remarks
 * Some joints, like hinge-2 need to be attached to two bodies to work.
 */
ODE_API void dJointAttach (dJointID, dBodyID body1, dBodyID body2);

/**
 * @brief Manually enable a joint.
 * @param dJointID identification of joint.
 * @ingroup joints
 */
ODE_API void dJointEnable (dJointID);

/**
 * @brief Manually disable a joint.
 * @ingroup joints
 * @remarks
 * A disabled joint will not affect the simulation, but will maintain the anchors and
 * axes so it can be enabled later.
 */
ODE_API void dJointDisable (dJointID);

/**
 * @brief Check wether a joint is enabled.
 * @ingroup joints
 * @return 1 if a joint is currently enabled or 0 if it is disabled.
 */
ODE_API int dJointIsEnabled (dJointID);

/**
 * @brief Set the user-data pointer
 * @ingroup joints
 */
ODE_API void dJointSetData (dJointID, void *data);

/**
 * @brief Get the user-data pointer
 * @ingroup joints
 */
ODE_API void *dJointGetData (dJointID);

/**
 * @brief Get the type of the joint
 * @ingroup joints
 * @return the type, being one of these:
 * \li dJointTypeBall
 * \li dJointTypeHinge
 * \li dJointTypeSlider
 * \li dJointTypeContact
 * \li dJointTypeUniversal
 * \li dJointTypeHinge2
 * \li dJointTypeFixed
 * \li dJointTypeNull
 * \li dJointTypeAMotor
 * \li dJointTypeLMotor
 * \li dJointTypePlane2D
 * \li dJointTypePR
 * \li dJointTypePU
 * \li dJointTypePiston
 */
ODE_API dJointType dJointGetType (dJointID);

/**
 * @brief Return the bodies that this joint connects.
 * @ingroup joints
 * @param index return the first (0) or second (1) body.
 * @remarks
 * If one of these returned body IDs is zero, the joint connects the other body
 * to the static environment.
 * If both body IDs are zero, the joint is in ``limbo'' and has no effect on
 * the simulation.
 */
ODE_API dBodyID dJointGetBody (dJointID, int index);

/**
 * @brief Sets the datastructure that is to receive the feedback.
 *
 * The feedback can be used by the user, so that it is known how
 * much force an individual joint exerts.
 * @ingroup joints
 */
ODE_API void dJointSetFeedback (dJointID, dJointFeedback *);

/**
 * @brief Gets the datastructure that is to receive the feedback.
 * @ingroup joints
 */
ODE_API dJointFeedback *dJointGetFeedback (dJointID);

/**
 * @brief Set the joint anchor point.
 * @ingroup joints
 *
 * The joint will try to keep this point on each body
 * together. The input is specified in world coordinates.
 */
ODE_API void dJointSetBallAnchor (dJointID, dReal x, dReal y, dReal z);

/**
 * @brief Set the joint anchor point.
 * @ingroup joints
 */
ODE_API void dJointSetBallAnchor2 (dJointID, dReal x, dReal y, dReal z);

/**
 * @brief Param setting for Ball joints
 * @ingroup joints
 */
ODE_API void dJointSetBallParam (dJointID, int parameter, dReal value);

/**
 * @brief Set hinge anchor parameter.
 * @ingroup joints
 */
ODE_API void dJointSetHingeAnchor (dJointID, dReal x, dReal y, dReal z);

ODE_API void dJointSetHingeAnchorDelta (dJointID, dReal x, dReal y, dReal z, dReal ax, dReal ay, dReal az);

/**
 * @brief Set hinge axis.
 * @ingroup joints
 */
ODE_API void dJointSetHingeAxis (dJointID, dReal x, dReal y, dReal z);

/**
 * @brief Set the Hinge axis as if the 2 bodies were already at angle appart.
 * @ingroup joints
 *
 * This function initialize the Axis and the relative orientation of each body
 * as if body1 was rotated around the axis by the angle value. \br
 * Ex:
 * 
 * dJointSetHingeAxis(jId, 1, 0, 0);
 * // If you request the position you will have: dJointGetHingeAngle(jId) == 0
 * dJointSetHingeAxisDelta(jId, 1, 0, 0, 0.23);
 * // If you request the position you will have: dJointGetHingeAngle(jId) == 0.23
 * 
* @param j The Hinge joint ID for which the axis will be set * @param x The X component of the axis in world frame * @param y The Y component of the axis in world frame * @param z The Z component of the axis in world frame * @param angle The angle for the offset of the relative orientation. * As if body1 was rotated by angle when the Axis was set (see below). * The rotation is around the new Hinge axis. * * @note Usually the function dJointSetHingeAxis set the current position of body1 * and body2 as the zero angle position. This function set the current position * as the if the 2 bodies where \b angle appart. * @warning Calling dJointSetHingeAnchor or dJointSetHingeAxis will reset the "zero" * angle position. */ ODE_API void dJointSetHingeAxisOffset (dJointID j, dReal x, dReal y, dReal z, dReal angle); /** * @brief set joint parameter * @ingroup joints */ ODE_API void dJointSetHingeParam (dJointID, int parameter, dReal value); /** * @brief Applies the torque about the hinge axis. * * That is, it applies a torque with specified magnitude in the direction * of the hinge axis, to body 1, and with the same magnitude but in opposite * direction to body 2. This function is just a wrapper for dBodyAddTorque()} * @ingroup joints */ ODE_API void dJointAddHingeTorque(dJointID joint, dReal torque); /** * @brief set the joint axis * @ingroup joints */ ODE_API void dJointSetSliderAxis (dJointID, dReal x, dReal y, dReal z); /** * @ingroup joints */ ODE_API void dJointSetSliderAxisDelta (dJointID, dReal x, dReal y, dReal z, dReal ax, dReal ay, dReal az); /** * @brief set joint parameter * @ingroup joints */ ODE_API void dJointSetSliderParam (dJointID, int parameter, dReal value); /** * @brief Applies the given force in the slider's direction. * * That is, it applies a force with specified magnitude, in the direction of * slider's axis, to body1, and with the same magnitude but opposite * direction to body2. This function is just a wrapper for dBodyAddForce(). * @ingroup joints */ ODE_API void dJointAddSliderForce(dJointID joint, dReal force); /** * @brief set anchor * @ingroup joints */ ODE_API void dJointSetHinge2Anchor (dJointID, dReal x, dReal y, dReal z); /** * @brief set both axes (optionally) * * This can change both axes at once avoiding transitions via invalid states * while changing axes one by one and having the first changed axis coincide * with the other axis existing direction. * * At least one of the axes must be not NULL. If NULL is passed, the corresponding * axis retains its existing value. * * @ingroup joints */ ODE_API void dJointSetHinge2Axes (dJointID j, const dReal *axis1/*=[dSA__MAX],=NULL*/, const dReal *axis2/*=[dSA__MAX],=NULL*/); /** * @brief set axis * * Deprecated. Use @fn dJointSetHinge2Axes instead. * * @ingroup joints * @see dJointSetHinge2Axes */ ODE_API_DEPRECATED ODE_API void dJointSetHinge2Axis1 (dJointID j, dReal x, dReal y, dReal z); /** * @brief set axis * * Deprecated. Use @fn dJointSetHinge2Axes instead. * * @ingroup joints * @see dJointSetHinge2Axes */ ODE_API_DEPRECATED ODE_API void dJointSetHinge2Axis2 (dJointID j, dReal x, dReal y, dReal z); /** * @brief set joint parameter * @ingroup joints */ ODE_API void dJointSetHinge2Param (dJointID, int parameter, dReal value); /** * @brief Applies torque1 about the hinge2's axis 1, torque2 about the * hinge2's axis 2. * @remarks This function is just a wrapper for dBodyAddTorque(). * @ingroup joints */ ODE_API void dJointAddHinge2Torques(dJointID joint, dReal torque1, dReal torque2); /** * @brief set anchor * @ingroup joints */ ODE_API void dJointSetUniversalAnchor (dJointID, dReal x, dReal y, dReal z); /** * @brief set axis * @ingroup joints */ ODE_API void dJointSetUniversalAxis1 (dJointID, dReal x, dReal y, dReal z); /** * @brief Set the Universal axis1 as if the 2 bodies were already at * offset1 and offset2 appart with respect to axis1 and axis2. * @ingroup joints * * This function initialize the axis1 and the relative orientation of * each body as if body1 was rotated around the new axis1 by the offset1 * value and as if body2 was rotated around the axis2 by offset2. \br * Ex: *
 * dJointSetHuniversalAxis1(jId, 1, 0, 0);
 * // If you request the position you will have: dJointGetUniversalAngle1(jId) == 0
 * // If you request the position you will have: dJointGetUniversalAngle2(jId) == 0
 * dJointSetHuniversalAxis1Offset(jId, 1, 0, 0, 0.2, 0.17);
 * // If you request the position you will have: dJointGetUniversalAngle1(jId) == 0.2
 * // If you request the position you will have: dJointGetUniversalAngle2(jId) == 0.17
 * 
* * @param j The Hinge joint ID for which the axis will be set * @param x The X component of the axis in world frame * @param y The Y component of the axis in world frame * @param z The Z component of the axis in world frame * @param angle The angle for the offset of the relative orientation. * As if body1 was rotated by angle when the Axis was set (see below). * The rotation is around the new Hinge axis. * * @note Usually the function dJointSetHingeAxis set the current position of body1 * and body2 as the zero angle position. This function set the current position * as the if the 2 bodies where \b offsets appart. * * @note Any previous offsets are erased. * * @warning Calling dJointSetUniversalAnchor, dJointSetUnivesalAxis1, * dJointSetUniversalAxis2, dJointSetUniversalAxis2Offset * will reset the "zero" angle position. */ ODE_API void dJointSetUniversalAxis1Offset (dJointID, dReal x, dReal y, dReal z, dReal offset1, dReal offset2); /** * @brief set axis * @ingroup joints */ ODE_API void dJointSetUniversalAxis2 (dJointID, dReal x, dReal y, dReal z); /** * @brief Set the Universal axis2 as if the 2 bodies were already at * offset1 and offset2 appart with respect to axis1 and axis2. * @ingroup joints * * This function initialize the axis2 and the relative orientation of * each body as if body1 was rotated around the axis1 by the offset1 * value and as if body2 was rotated around the new axis2 by offset2. \br * Ex: *
 * dJointSetHuniversalAxis2(jId, 0, 1, 0);
 * // If you request the position you will have: dJointGetUniversalAngle1(jId) == 0
 * // If you request the position you will have: dJointGetUniversalAngle2(jId) == 0
 * dJointSetHuniversalAxis2Offset(jId, 0, 1, 0, 0.2, 0.17);
 * // If you request the position you will have: dJointGetUniversalAngle1(jId) == 0.2
 * // If you request the position you will have: dJointGetUniversalAngle2(jId) == 0.17
 * 
* @param j The Hinge joint ID for which the axis will be set * @param x The X component of the axis in world frame * @param y The Y component of the axis in world frame * @param z The Z component of the axis in world frame * @param angle The angle for the offset of the relative orientation. * As if body1 was rotated by angle when the Axis was set (see below). * The rotation is around the new Hinge axis. * * @note Usually the function dJointSetHingeAxis set the current position of body1 * and body2 as the zero angle position. This function set the current position * as the if the 2 bodies where \b offsets appart. * * @note Any previous offsets are erased. * * @warning Calling dJointSetUniversalAnchor, dJointSetUnivesalAxis1, * dJointSetUniversalAxis2, dJointSetUniversalAxis2Offset * will reset the "zero" angle position. */ ODE_API void dJointSetUniversalAxis2Offset (dJointID, dReal x, dReal y, dReal z, dReal offset1, dReal offset2); /** * @brief set joint parameter * @ingroup joints */ ODE_API void dJointSetUniversalParam (dJointID, int parameter, dReal value); /** * @brief Applies torque1 about the universal's axis 1, torque2 about the * universal's axis 2. * @remarks This function is just a wrapper for dBodyAddTorque(). * @ingroup joints */ ODE_API void dJointAddUniversalTorques(dJointID joint, dReal torque1, dReal torque2); /** * @brief set anchor * @ingroup joints */ ODE_API void dJointSetPRAnchor (dJointID, dReal x, dReal y, dReal z); /** * @brief set the axis for the prismatic articulation * @ingroup joints */ ODE_API void dJointSetPRAxis1 (dJointID, dReal x, dReal y, dReal z); /** * @brief set the axis for the rotoide articulation * @ingroup joints */ ODE_API void dJointSetPRAxis2 (dJointID, dReal x, dReal y, dReal z); /** * @brief set joint parameter * @ingroup joints * * @note parameterX where X equal 2 refer to parameter for the rotoide articulation */ ODE_API void dJointSetPRParam (dJointID, int parameter, dReal value); /** * @brief Applies the torque about the rotoide axis of the PR joint * * That is, it applies a torque with specified magnitude in the direction * of the rotoide axis, to body 1, and with the same magnitude but in opposite * direction to body 2. This function is just a wrapper for dBodyAddTorque()} * @ingroup joints */ ODE_API void dJointAddPRTorque (dJointID j, dReal torque); /** * @brief set anchor * @ingroup joints */ ODE_API void dJointSetPUAnchor (dJointID, dReal x, dReal y, dReal z); /** * @brief set anchor * @ingroup joints */ ODE_API_DEPRECATED ODE_API void dJointSetPUAnchorDelta (dJointID, dReal x, dReal y, dReal z, dReal dx, dReal dy, dReal dz); /** * @brief Set the PU anchor as if the 2 bodies were already at [dx, dy, dz] appart. * @ingroup joints * * This function initialize the anchor and the relative position of each body * as if the position between body1 and body2 was already the projection of [dx, dy, dz] * along the Piston axis. (i.e as if the body1 was at its current position - [dx,dy,dy] when the * axis is set). * Ex: *
 * dReal offset = 3;
 * dVector3 axis;
 * dJointGetPUAxis(jId, axis);
 * dJointSetPUAnchor(jId, 0, 0, 0);
 * // If you request the position you will have: dJointGetPUPosition(jId) == 0
 * dJointSetPUAnchorOffset(jId, 0, 0, 0, axis[X]*offset, axis[Y]*offset, axis[Z]*offset);
 * // If you request the position you will have: dJointGetPUPosition(jId) == offset
 * 
* @param j The PU joint for which the anchor point will be set * @param x The X position of the anchor point in world frame * @param y The Y position of the anchor point in world frame * @param z The Z position of the anchor point in world frame * @param dx A delta to be substracted to the X position as if the anchor was set * when body1 was at current_position[X] - dx * @param dx A delta to be substracted to the Y position as if the anchor was set * when body1 was at current_position[Y] - dy * @param dx A delta to be substracted to the Z position as if the anchor was set * when body1 was at current_position[Z] - dz */ ODE_API void dJointSetPUAnchorOffset (dJointID, dReal x, dReal y, dReal z, dReal dx, dReal dy, dReal dz); /** * @brief set the axis for the first axis or the universal articulation * @ingroup joints */ ODE_API void dJointSetPUAxis1 (dJointID, dReal x, dReal y, dReal z); /** * @brief set the axis for the second axis or the universal articulation * @ingroup joints */ ODE_API void dJointSetPUAxis2 (dJointID, dReal x, dReal y, dReal z); /** * @brief set the axis for the prismatic articulation * @ingroup joints */ ODE_API void dJointSetPUAxis3 (dJointID, dReal x, dReal y, dReal z); /** * @brief set the axis for the prismatic articulation * @ingroup joints * @note This function was added for convenience it is the same as * dJointSetPUAxis3 */ ODE_API void dJointSetPUAxisP (dJointID id, dReal x, dReal y, dReal z); /** * @brief set joint parameter * @ingroup joints * * @note parameterX where X equal 2 refer to parameter for second axis of the * universal articulation * @note parameterX where X equal 3 refer to parameter for prismatic * articulation */ ODE_API void dJointSetPUParam (dJointID, int parameter, dReal value); /** * @brief Applies the torque about the rotoide axis of the PU joint * * That is, it applies a torque with specified magnitude in the direction * of the rotoide axis, to body 1, and with the same magnitude but in opposite * direction to body 2. This function is just a wrapper for dBodyAddTorque()} * @ingroup joints */ ODE_API void dJointAddPUTorque (dJointID j, dReal torque); /** * @brief set the joint anchor * @ingroup joints */ ODE_API void dJointSetPistonAnchor (dJointID, dReal x, dReal y, dReal z); /** * @brief Set the Piston anchor as if the 2 bodies were already at [dx,dy, dz] appart. * @ingroup joints * * This function initialize the anchor and the relative position of each body * as if the position between body1 and body2 was already the projection of [dx, dy, dz] * along the Piston axis. (i.e as if the body1 was at its current position - [dx,dy,dy] when the * axis is set). * Ex: *
 * dReal offset = 3;
 * dVector3 axis;
 * dJointGetPistonAxis(jId, axis);
 * dJointSetPistonAnchor(jId, 0, 0, 0);
 * // If you request the position you will have: dJointGetPistonPosition(jId) == 0
 * dJointSetPistonAnchorOffset(jId, 0, 0, 0, axis[X]*offset, axis[Y]*offset, axis[Z]*offset);
 * // If you request the position you will have: dJointGetPistonPosition(jId) == offset
 * 
* @param j The Piston joint for which the anchor point will be set * @param x The X position of the anchor point in world frame * @param y The Y position of the anchor point in world frame * @param z The Z position of the anchor point in world frame * @param dx A delta to be substracted to the X position as if the anchor was set * when body1 was at current_position[X] - dx * @param dx A delta to be substracted to the Y position as if the anchor was set * when body1 was at current_position[Y] - dy * @param dx A delta to be substracted to the Z position as if the anchor was set * when body1 was at current_position[Z] - dz */ ODE_API void dJointSetPistonAnchorOffset(dJointID j, dReal x, dReal y, dReal z, dReal dx, dReal dy, dReal dz); /** * @brief set the joint axis * @ingroup joints */ ODE_API void dJointSetPistonAxis (dJointID, dReal x, dReal y, dReal z); /** * This function set prismatic axis of the joint and also set the position * of the joint. * * @ingroup joints * @param j The joint affected by this function * @param x The x component of the axis * @param y The y component of the axis * @param z The z component of the axis * @param dx The Initial position of the prismatic join in the x direction * @param dy The Initial position of the prismatic join in the y direction * @param dz The Initial position of the prismatic join in the z direction */ ODE_API_DEPRECATED ODE_API void dJointSetPistonAxisDelta (dJointID j, dReal x, dReal y, dReal z, dReal ax, dReal ay, dReal az); /** * @brief set joint parameter * @ingroup joints */ ODE_API void dJointSetPistonParam (dJointID, int parameter, dReal value); /** * @brief Applies the given force in the slider's direction. * * That is, it applies a force with specified magnitude, in the direction of * prismatic's axis, to body1, and with the same magnitude but opposite * direction to body2. This function is just a wrapper for dBodyAddForce(). * @ingroup joints */ ODE_API void dJointAddPistonForce (dJointID joint, dReal force); /** * @brief Call this on the fixed joint after it has been attached to * remember the current desired relative offset and desired relative * rotation between the bodies. * @ingroup joints */ ODE_API void dJointSetFixed (dJointID); /* * @brief Sets joint parameter * * @ingroup joints */ ODE_API void dJointSetFixedParam (dJointID, int parameter, dReal value); /** * @brief set the nr of axes * @param num 0..3 * @ingroup joints */ ODE_API void dJointSetAMotorNumAxes (dJointID, int num); /** * @brief set axis * @ingroup joints */ ODE_API void dJointSetAMotorAxis (dJointID, int anum, int rel, dReal x, dReal y, dReal z); /** * @brief Tell the AMotor what the current angle is along axis anum. * * This function should only be called in dAMotorUser mode, because in this * mode the AMotor has no other way of knowing the joint angles. * The angle information is needed if stops have been set along the axis, * but it is not needed for axis motors. * @ingroup joints */ ODE_API void dJointSetAMotorAngle (dJointID, int anum, dReal angle); /** * @brief set joint parameter * @ingroup joints */ ODE_API void dJointSetAMotorParam (dJointID, int parameter, dReal value); /** * @brief set mode * @ingroup joints */ ODE_API void dJointSetAMotorMode (dJointID, int mode); /** * @brief Applies torque0 about the AMotor's axis 0, torque1 about the * AMotor's axis 1, and torque2 about the AMotor's axis 2. * @remarks * If the motor has fewer than three axes, the higher torques are ignored. * This function is just a wrapper for dBodyAddTorque(). * @ingroup joints */ ODE_API void dJointAddAMotorTorques (dJointID, dReal torque1, dReal torque2, dReal torque3); /** * @brief Set the number of axes that will be controlled by the LMotor. * @param num can range from 0 (which effectively deactivates the joint) to 3. * @ingroup joints */ ODE_API void dJointSetLMotorNumAxes (dJointID, int num); /** * @brief Set the AMotor axes. * @param anum selects the axis to change (0,1 or 2). * @param rel Each axis can have one of three ``relative orientation'' modes * \li 0: The axis is anchored to the global frame. * \li 1: The axis is anchored to the first body. * \li 2: The axis is anchored to the second body. * @remarks The axis vector is always specified in global coordinates * regardless of the setting of rel. * @ingroup joints */ ODE_API void dJointSetLMotorAxis (dJointID, int anum, int rel, dReal x, dReal y, dReal z); /** * @brief set joint parameter * @ingroup joints */ ODE_API void dJointSetLMotorParam (dJointID, int parameter, dReal value); /** * @ingroup joints */ ODE_API void dJointSetPlane2DXParam (dJointID, int parameter, dReal value); /** * @ingroup joints */ ODE_API void dJointSetPlane2DYParam (dJointID, int parameter, dReal value); /** * @ingroup joints */ ODE_API void dJointSetPlane2DAngleParam (dJointID, int parameter, dReal value); /** * @brief Get the joint anchor point, in world coordinates. * * This returns the point on body 1. If the joint is perfectly satisfied, * this will be the same as the point on body 2. */ ODE_API void dJointGetBallAnchor (dJointID, dVector3 result); /** * @brief Get the joint anchor point, in world coordinates. * * This returns the point on body 2. You can think of a ball and socket * joint as trying to keep the result of dJointGetBallAnchor() and * dJointGetBallAnchor2() the same. If the joint is perfectly satisfied, * this function will return the same value as dJointGetBallAnchor() to * within roundoff errors. dJointGetBallAnchor2() can be used, along with * dJointGetBallAnchor(), to see how far the joint has come apart. */ ODE_API void dJointGetBallAnchor2 (dJointID, dVector3 result); /** * @brief get joint parameter * @ingroup joints */ ODE_API dReal dJointGetBallParam (dJointID, int parameter); /** * @brief Get the hinge anchor point, in world coordinates. * * This returns the point on body 1. If the joint is perfectly satisfied, * this will be the same as the point on body 2. * @ingroup joints */ ODE_API void dJointGetHingeAnchor (dJointID, dVector3 result); /** * @brief Get the joint anchor point, in world coordinates. * @return The point on body 2. If the joint is perfectly satisfied, * this will return the same value as dJointGetHingeAnchor(). * If not, this value will be slightly different. * This can be used, for example, to see how far the joint has come apart. * @ingroup joints */ ODE_API void dJointGetHingeAnchor2 (dJointID, dVector3 result); /** * @brief get axis * @ingroup joints */ ODE_API void dJointGetHingeAxis (dJointID, dVector3 result); /** * @brief get joint parameter * @ingroup joints */ ODE_API dReal dJointGetHingeParam (dJointID, int parameter); /** * @brief Get the hinge angle. * * The angle is measured between the two bodies, or between the body and * the static environment. * The angle will be between -pi..pi. * Give the relative rotation with respect to the Hinge axis of Body 1 with * respect to Body 2. * When the hinge anchor or axis is set, the current position of the attached * bodies is examined and that position will be the zero angle. * @ingroup joints */ ODE_API dReal dJointGetHingeAngle (dJointID); /** * @brief Get the hinge angle time derivative. * @ingroup joints */ ODE_API dReal dJointGetHingeAngleRate (dJointID); /** * @brief Get the slider linear position (i.e. the slider's extension) * * When the axis is set, the current position of the attached bodies is * examined and that position will be the zero position. * The position is the distance, with respect to the zero position, * along the slider axis of body 1 with respect to * body 2. (A NULL body is replaced by the world). * @ingroup joints */ ODE_API dReal dJointGetSliderPosition (dJointID); /** * @brief Get the slider linear position's time derivative. * @ingroup joints */ ODE_API dReal dJointGetSliderPositionRate (dJointID); /** * @brief Get the slider axis * @ingroup joints */ ODE_API void dJointGetSliderAxis (dJointID, dVector3 result); /** * @brief get joint parameter * @ingroup joints */ ODE_API dReal dJointGetSliderParam (dJointID, int parameter); /** * @brief Get the joint anchor point, in world coordinates. * @return the point on body 1. If the joint is perfectly satisfied, * this will be the same as the point on body 2. * @ingroup joints */ ODE_API void dJointGetHinge2Anchor (dJointID, dVector3 result); /** * @brief Get the joint anchor point, in world coordinates. * This returns the point on body 2. If the joint is perfectly satisfied, * this will return the same value as dJointGetHinge2Anchor. * If not, this value will be slightly different. * This can be used, for example, to see how far the joint has come apart. * @ingroup joints */ ODE_API void dJointGetHinge2Anchor2 (dJointID, dVector3 result); /** * @brief Get joint axis * @ingroup joints */ ODE_API void dJointGetHinge2Axis1 (dJointID, dVector3 result); /** * @brief Get joint axis * @ingroup joints */ ODE_API void dJointGetHinge2Axis2 (dJointID, dVector3 result); /** * @brief get joint parameter * @ingroup joints */ ODE_API dReal dJointGetHinge2Param (dJointID, int parameter); /** * @brief Get angle * @ingroup joints */ ODE_API dReal dJointGetHinge2Angle1 (dJointID); /** * @brief Get angle * @ingroup joints */ ODE_API dReal dJointGetHinge2Angle2 (dJointID); /** * @brief Get time derivative of angle * @ingroup joints */ ODE_API dReal dJointGetHinge2Angle1Rate (dJointID); /** * @brief Get time derivative of angle * @ingroup joints */ ODE_API dReal dJointGetHinge2Angle2Rate (dJointID); /** * @brief Get the joint anchor point, in world coordinates. * @return the point on body 1. If the joint is perfectly satisfied, * this will be the same as the point on body 2. * @ingroup joints */ ODE_API void dJointGetUniversalAnchor (dJointID, dVector3 result); /** * @brief Get the joint anchor point, in world coordinates. * @return This returns the point on body 2. * @remarks * You can think of the ball and socket part of a universal joint as * trying to keep the result of dJointGetBallAnchor() and * dJointGetBallAnchor2() the same. If the joint is * perfectly satisfied, this function will return the same value * as dJointGetUniversalAnchor() to within roundoff errors. * dJointGetUniversalAnchor2() can be used, along with * dJointGetUniversalAnchor(), to see how far the joint has come apart. * @ingroup joints */ ODE_API void dJointGetUniversalAnchor2 (dJointID, dVector3 result); /** * @brief Get axis * @ingroup joints */ ODE_API void dJointGetUniversalAxis1 (dJointID, dVector3 result); /** * @brief Get axis * @ingroup joints */ ODE_API void dJointGetUniversalAxis2 (dJointID, dVector3 result); /** * @brief get joint parameter * @ingroup joints */ ODE_API dReal dJointGetUniversalParam (dJointID, int parameter); /** * @brief Get both angles at the same time. * @ingroup joints * * @param joint The universal joint for which we want to calculate the angles * @param angle1 The angle between the body1 and the axis 1 * @param angle2 The angle between the body2 and the axis 2 * * @note This function combine getUniversalAngle1 and getUniversalAngle2 together * and try to avoid redundant calculation */ ODE_API void dJointGetUniversalAngles (dJointID, dReal *angle1, dReal *angle2); /** * @brief Get angle * @ingroup joints */ ODE_API dReal dJointGetUniversalAngle1 (dJointID); /** * @brief Get angle * @ingroup joints */ ODE_API dReal dJointGetUniversalAngle2 (dJointID); /** * @brief Get time derivative of angle * @ingroup joints */ ODE_API dReal dJointGetUniversalAngle1Rate (dJointID); /** * @brief Get time derivative of angle * @ingroup joints */ ODE_API dReal dJointGetUniversalAngle2Rate (dJointID); /** * @brief Get the joint anchor point, in world coordinates. * @return the point on body 1. If the joint is perfectly satisfied, * this will be the same as the point on body 2. * @ingroup joints */ ODE_API void dJointGetPRAnchor (dJointID, dVector3 result); /** * @brief Get the PR linear position (i.e. the prismatic's extension) * * When the axis is set, the current position of the attached bodies is * examined and that position will be the zero position. * * The position is the "oriented" length between the * position = (Prismatic axis) dot_product [(body1 + offset) - (body2 + anchor2)] * * @ingroup joints */ ODE_API dReal dJointGetPRPosition (dJointID); /** * @brief Get the PR linear position's time derivative * * @ingroup joints */ ODE_API dReal dJointGetPRPositionRate (dJointID); /** * @brief Get the PR angular position (i.e. the twist between the 2 bodies) * * When the axis is set, the current position of the attached bodies is * examined and that position will be the zero position. * @ingroup joints */ ODE_API dReal dJointGetPRAngle (dJointID); /** * @brief Get the PR angular position's time derivative * * @ingroup joints */ ODE_API dReal dJointGetPRAngleRate (dJointID); /** * @brief Get the prismatic axis * @ingroup joints */ ODE_API void dJointGetPRAxis1 (dJointID, dVector3 result); /** * @brief Get the Rotoide axis * @ingroup joints */ ODE_API void dJointGetPRAxis2 (dJointID, dVector3 result); /** * @brief get joint parameter * @ingroup joints */ ODE_API dReal dJointGetPRParam (dJointID, int parameter); /** * @brief Get the joint anchor point, in world coordinates. * @return the point on body 1. If the joint is perfectly satisfied, * this will be the same as the point on body 2. * @ingroup joints */ ODE_API void dJointGetPUAnchor (dJointID, dVector3 result); /** * @brief Get the PU linear position (i.e. the prismatic's extension) * * When the axis is set, the current position of the attached bodies is * examined and that position will be the zero position. * * The position is the "oriented" length between the * position = (Prismatic axis) dot_product [(body1 + offset) - (body2 + anchor2)] * * @ingroup joints */ ODE_API dReal dJointGetPUPosition (dJointID); /** * @brief Get the PR linear position's time derivative * * @ingroup joints */ ODE_API dReal dJointGetPUPositionRate (dJointID); /** * @brief Get the first axis of the universal component of the joint * @ingroup joints */ ODE_API void dJointGetPUAxis1 (dJointID, dVector3 result); /** * @brief Get the second axis of the Universal component of the joint * @ingroup joints */ ODE_API void dJointGetPUAxis2 (dJointID, dVector3 result); /** * @brief Get the prismatic axis * @ingroup joints */ ODE_API void dJointGetPUAxis3 (dJointID, dVector3 result); /** * @brief Get the prismatic axis * @ingroup joints * * @note This function was added for convenience it is the same as * dJointGetPUAxis3 */ ODE_API void dJointGetPUAxisP (dJointID id, dVector3 result); /** * @brief Get both angles at the same time. * @ingroup joints * * @param joint The Prismatic universal joint for which we want to calculate the angles * @param angle1 The angle between the body1 and the axis 1 * @param angle2 The angle between the body2 and the axis 2 * * @note This function combine dJointGetPUAngle1 and dJointGetPUAngle2 together * and try to avoid redundant calculation */ ODE_API void dJointGetPUAngles (dJointID, dReal *angle1, dReal *angle2); /** * @brief Get angle * @ingroup joints */ ODE_API dReal dJointGetPUAngle1 (dJointID); /** * @brief * @brief Get time derivative of angle1 * * @ingroup joints */ ODE_API dReal dJointGetPUAngle1Rate (dJointID); /** * @brief Get angle * @ingroup joints */ ODE_API dReal dJointGetPUAngle2 (dJointID); /** * @brief * @brief Get time derivative of angle2 * * @ingroup joints */ ODE_API dReal dJointGetPUAngle2Rate (dJointID); /** * @brief get joint parameter * @ingroup joints */ ODE_API dReal dJointGetPUParam (dJointID, int parameter); /** * @brief Get the Piston linear position (i.e. the piston's extension) * * When the axis is set, the current position of the attached bodies is * examined and that position will be the zero position. * @ingroup joints */ ODE_API dReal dJointGetPistonPosition (dJointID); /** * @brief Get the piston linear position's time derivative. * @ingroup joints */ ODE_API dReal dJointGetPistonPositionRate (dJointID); /** * @brief Get the Piston angular position (i.e. the twist between the 2 bodies) * * When the axis is set, the current position of the attached bodies is * examined and that position will be the zero position. * @ingroup joints */ ODE_API dReal dJointGetPistonAngle (dJointID); /** * @brief Get the piston angular position's time derivative. * @ingroup joints */ ODE_API dReal dJointGetPistonAngleRate (dJointID); /** * @brief Get the joint anchor * * This returns the point on body 1. If the joint is perfectly satisfied, * this will be the same as the point on body 2 in direction perpendicular * to the prismatic axis. * * @ingroup joints */ ODE_API void dJointGetPistonAnchor (dJointID, dVector3 result); /** * @brief Get the joint anchor w.r.t. body 2 * * This returns the point on body 2. You can think of a Piston * joint as trying to keep the result of dJointGetPistonAnchor() and * dJointGetPistonAnchor2() the same in the direction perpendicular to the * pirsmatic axis. If the joint is perfectly satisfied, * this function will return the same value as dJointGetPistonAnchor() to * within roundoff errors. dJointGetPistonAnchor2() can be used, along with * dJointGetPistonAnchor(), to see how far the joint has come apart. * * @ingroup joints */ ODE_API void dJointGetPistonAnchor2 (dJointID, dVector3 result); /** * @brief Get the prismatic axis (This is also the rotoide axis. * @ingroup joints */ ODE_API void dJointGetPistonAxis (dJointID, dVector3 result); /** * @brief get joint parameter * @ingroup joints */ ODE_API dReal dJointGetPistonParam (dJointID, int parameter); /** * @brief Get the number of angular axes that will be controlled by the * AMotor. * @param num can range from 0 (which effectively deactivates the * joint) to 3. * This is automatically set to 3 in dAMotorEuler mode. * @ingroup joints */ ODE_API int dJointGetAMotorNumAxes (dJointID); /** * @brief Get the AMotor axes. * @param anum selects the axis to change (0,1 or 2). * @param rel Each axis can have one of three ``relative orientation'' modes. * \li 0: The axis is anchored to the global frame. * \li 1: The axis is anchored to the first body. * \li 2: The axis is anchored to the second body. * @ingroup joints */ ODE_API void dJointGetAMotorAxis (dJointID, int anum, dVector3 result); /** * @brief Get axis * @remarks * The axis vector is always specified in global coordinates regardless * of the setting of rel. * There are two GetAMotorAxis functions, one to return the axis and one to * return the relative mode. * * For dAMotorEuler mode: * \li Only axes 0 and 2 need to be set. Axis 1 will be determined automatically at each time step. * \li Axes 0 and 2 must be perpendicular to each other. * \li Axis 0 must be anchored to the first body, axis 2 must be anchored to the second body. * @ingroup joints */ ODE_API int dJointGetAMotorAxisRel (dJointID, int anum); /** * @brief Get the current angle for axis. * @remarks * In dAMotorUser mode this is simply the value that was set with * dJointSetAMotorAngle(). * In dAMotorEuler mode this is the corresponding euler angle. * @ingroup joints */ ODE_API dReal dJointGetAMotorAngle (dJointID, int anum); /** * @brief Get the current angle rate for axis anum. * @remarks * In dAMotorUser mode this is always zero, as not enough information is * available. * In dAMotorEuler mode this is the corresponding euler angle rate. * @ingroup joints */ ODE_API dReal dJointGetAMotorAngleRate (dJointID, int anum); /** * @brief get joint parameter * @ingroup joints */ ODE_API dReal dJointGetAMotorParam (dJointID, int parameter); /** * @brief Get the angular motor mode. * @param mode must be one of the following constants: * \li dAMotorUser The AMotor axes and joint angle settings are entirely * controlled by the user. This is the default mode. * \li dAMotorEuler Euler angles are automatically computed. * The axis a1 is also automatically computed. * The AMotor axes must be set correctly when in this mode, * as described below. * When this mode is initially set the current relative orientations * of the bodies will correspond to all euler angles at zero. * @ingroup joints */ ODE_API int dJointGetAMotorMode (dJointID); /** * @brief Get nr of axes. * @ingroup joints */ ODE_API int dJointGetLMotorNumAxes (dJointID); /** * @brief Get axis. * @ingroup joints */ ODE_API void dJointGetLMotorAxis (dJointID, int anum, dVector3 result); /** * @brief get joint parameter * @ingroup joints */ ODE_API dReal dJointGetLMotorParam (dJointID, int parameter); /** * @brief get joint parameter * @ingroup joints */ ODE_API dReal dJointGetFixedParam (dJointID, int parameter); /** * @brief get the contact point of the first wheel of the Transmission joint. * @ingroup joints */ ODE_API void dJointGetTransmissionContactPoint1(dJointID, dVector3 result); /** * @brief get contact point of the second wheel of the Transmission joint. * @ingroup joints */ ODE_API void dJointGetTransmissionContactPoint2(dJointID, dVector3 result); /** * @brief set the first axis for the Transmission joint * @remarks This is the axis around which the first body is allowed to * revolve and is attached to it. It is given in global coordinates * and can only be set explicitly in intersecting-axes mode. For the * parallel-axes and chain modes which share one common axis of * revolution for both gears dJointSetTransmissionAxis should be used. * @ingroup joints */ ODE_API void dJointSetTransmissionAxis1(dJointID, dReal x, dReal y, dReal z); /** * @brief get first axis for the Transmission joint * @remarks In parallel-axes and chain mode the common axis with * respect to the first body is returned. If the joint constraint is * satisfied it should be the same as the axis return with * dJointGetTransmissionAxis2 or dJointGetTransmissionAxis. * @ingroup joints */ ODE_API void dJointGetTransmissionAxis1(dJointID, dVector3 result); /** * @brief set second axis for the Transmission joint * @remarks This is the axis around which the second body is allowed * to revolve and is attached to it. It is given in global * coordinates and can only be set explicitly in intersecting-axes * mode. For the parallel-axes and chain modes which share one common * axis of revolution for both gears dJointSetTransmissionAxis should * be used. * @ingroup joints */ ODE_API void dJointSetTransmissionAxis2(dJointID, dReal x, dReal y, dReal z); /** * @brief get second axis for the Transmission joint * @remarks In parallel-axes and chain mode the common axis with * respect to the second body is returned. If the joint constraint is * satisfied it should be the same as the axis return with * dJointGetTransmissionAxis1 or dJointGetTransmissionAxis. * @ingroup joints */ ODE_API void dJointGetTransmissionAxis2(dJointID, dVector3 result); /** * @brief set the first anchor for the Transmission joint * @remarks This is the point of attachment of the wheel on the * first body. It is given in global coordinates. * @ingroup joints */ ODE_API void dJointSetTransmissionAnchor1(dJointID, dReal x, dReal y, dReal z); /** * @brief get the first anchor of the Transmission joint * @ingroup joints */ ODE_API void dJointGetTransmissionAnchor1(dJointID, dVector3 result); /** * @brief set the second anchor for the Transmission joint * @remarks This is the point of attachment of the wheel on the * second body. It is given in global coordinates. * @ingroup joints */ ODE_API void dJointSetTransmissionAnchor2(dJointID, dReal x, dReal y, dReal z); /** * @brief get the second anchor for the Transmission joint * @ingroup joints */ ODE_API void dJointGetTransmissionAnchor2(dJointID, dVector3 result); /** * @brief set a Transmission joint parameter * @ingroup joints */ ODE_API void dJointSetTransmissionParam(dJointID, int parameter, dReal value); /** * @brief get a Transmission joint parameter * @ingroup joints */ ODE_API dReal dJointGetTransmissionParam(dJointID, int parameter); /** * @brief set the Transmission joint mode * @remarks The mode can be one of dTransmissionParallelAxes, * dTransmissionIntersectingAxes and dTransmissionChainDrive simulating a * set of parallel-axes gears, intersecting-axes beveled gears or * chain and sprockets respectively. * @ingroup joints */ ODE_API void dJointSetTransmissionMode( dJointID j, int mode ); /** * @brief get the Transmission joint mode * @ingroup joints */ ODE_API int dJointGetTransmissionMode( dJointID j ); /** * @brief set the Transmission ratio * @remarks This is the ratio of the angular speed of the first gear * to that of the second gear. It can only be set explicitly in * parallel-axes mode. In intersecting-axes mode the ratio is defined * implicitly by the initial configuration of the wheels and in chain * mode it is defined implicitly be the wheel radii. * @ingroup joints */ ODE_API void dJointSetTransmissionRatio( dJointID j, dReal ratio ); /** * @brief get the Transmission joint ratio * @ingroup joints */ ODE_API dReal dJointGetTransmissionRatio( dJointID j ); /** * @brief set the common axis for both wheels of the Transmission joint * @remarks This sets the common axis of revolution for both wheels * and should only be used in parallel-axes or chain mode. For * intersecting-axes mode where each wheel axis needs to be specified * individually dJointSetTransmissionAxis1 and * dJointSetTransmissionAxis2 should be used. The axis is given in * global coordinates * @ingroup joints */ ODE_API void dJointSetTransmissionAxis( dJointID j, dReal x, dReal y, dReal z ); /** * @brief get the common axis for both wheels of the Transmission joint * @ingroup joints */ ODE_API void dJointGetTransmissionAxis( dJointID j, dVector3 result ); /** * @brief get the phase, that is the traversed angle for the first * wheel of the Transmission joint * @ingroup joints */ ODE_API dReal dJointGetTransmissionAngle1( dJointID j ); /** * @brief get the phase, that is the traversed angle for the second * wheel of the Transmission joint * @ingroup joints */ ODE_API dReal dJointGetTransmissionAngle2( dJointID j ); /** * @brief get the radius of the first wheel of the Transmission joint * @ingroup joints */ ODE_API dReal dJointGetTransmissionRadius1( dJointID j ); /** * @brief get the radius of the second wheel of the Transmission joint * @ingroup joints */ ODE_API dReal dJointGetTransmissionRadius2( dJointID j ); /** * @brief set the radius of the first wheel of the Transmission joint * @remarks The wheel radii can only be set explicitly in chain mode. * In the other modes they're defined implicitly by the initial * configuration and ratio of the wheels. * @ingroup joints */ ODE_API void dJointSetTransmissionRadius1( dJointID j, dReal radius ); /** * @brief set the radius of the second wheel of the Transmission joint * @remarks The wheel radii can only be set explicitly in chain mode. * In the other modes they're defined implicitly by the initial * configuration and ratio of the wheels. * @ingroup joints */ ODE_API void dJointSetTransmissionRadius2( dJointID j, dReal radius ); /** * @brief get the backlash of the Transmission joint * @ingroup joints */ ODE_API dReal dJointGetTransmissionBacklash( dJointID j ); /** * @brief set the backlash of the Transmission joint * @remarks Backlash is the clearance in the mesh of the wheels of the * transmission and is defined as the maximum distance that the * geometric contact point can travel without any actual contact or * transfer of power between the wheels. This can be converted in * degrees of revolution for each wheel by dividing by the wheel's * radius. To further illustrate this consider the situation where a * wheel of radius r_1 is driving another wheel of radius r_2 and * there is an amount of backlash equal to b in their mesh. If the * driving wheel were to instantaneously stop there would be no * contact and hence the driven wheel would continue to turn for * another b / r_2 radians until all the backlash in the mesh was take * up and contact restored with the relationship of driving and driven * wheel reversed. The backlash is therefore given in untis of * length. * @ingroup joints */ ODE_API void dJointSetTransmissionBacklash( dJointID j, dReal backlash ); /** * @brief set anchor1 for double ball joint * @ingroup joints */ ODE_API void dJointSetDBallAnchor1(dJointID, dReal x, dReal y, dReal z); /** * @brief set anchor2 for double ball joint * @ingroup joints */ ODE_API void dJointSetDBallAnchor2(dJointID, dReal x, dReal y, dReal z); /** * @brief get anchor1 from double ball joint * @ingroup joints */ ODE_API void dJointGetDBallAnchor1(dJointID, dVector3 result); /** * @brief get anchor2 from double ball joint * @ingroup joints */ ODE_API void dJointGetDBallAnchor2(dJointID, dVector3 result); /** * @brief get the target distance from double ball joint * @ingroup joints */ ODE_API dReal dJointGetDBallDistance(dJointID); /** * @brief set the target distance for the double ball joint * @ingroup joints */ ODE_API void dJointSetDBallDistance(dJointID, dReal dist); /** * @brief set double ball joint parameter * @ingroup joints */ ODE_API void dJointSetDBallParam(dJointID, int parameter, dReal value); /** * @brief get double ball joint parameter * @ingroup joints */ ODE_API dReal dJointGetDBallParam(dJointID, int parameter); /** * @brief set axis for double hinge joint * @ingroup joints */ ODE_API void dJointSetDHingeAxis(dJointID, dReal x, dReal y, dReal z); /** * @brief get axis for double hinge joint * @ingroup joints */ ODE_API void dJointGetDHingeAxis(dJointID, dVector3 result); /** * @brief set anchor1 for double hinge joint * @ingroup joints */ ODE_API void dJointSetDHingeAnchor1(dJointID, dReal x, dReal y, dReal z); /** * @brief set anchor2 for double hinge joint * @ingroup joints */ ODE_API void dJointSetDHingeAnchor2(dJointID, dReal x, dReal y, dReal z); /** * @brief get anchor1 from double hinge joint * @ingroup joints */ ODE_API void dJointGetDHingeAnchor1(dJointID, dVector3 result); /** * @brief get anchor2 from double hinge joint * @ingroup joints */ ODE_API void dJointGetDHingeAnchor2(dJointID, dVector3 result); /** * @brief get the set distance from double hinge joint * @ingroup joints */ ODE_API dReal dJointGetDHingeDistance(dJointID); /** * @brief set double hinge joint parameter * @ingroup joints */ ODE_API void dJointSetDHingeParam(dJointID, int parameter, dReal value); /** * @brief get double hinge joint parameter * @ingroup joints */ ODE_API dReal dJointGetDHingeParam(dJointID, int parameter); /** * @ingroup joints */ ODE_API dJointID dConnectingJoint (dBodyID, dBodyID); /** * @ingroup joints */ ODE_API int dConnectingJointList (dBodyID, dBodyID, dJointID*); /** * @brief Utility function * @return 1 if the two bodies are connected together by * a joint, otherwise return 0. * @ingroup joints */ ODE_API int dAreConnected (dBodyID, dBodyID); /** * @brief Utility function * @return 1 if the two bodies are connected together by * a joint that does not have type @arg{joint_type}, otherwise return 0. * @param body1 A body to check. * @param body2 A body to check. * @param joint_type is a dJointTypeXXX constant. * This is useful for deciding whether to add contact joints between two bodies: * if they are already connected by non-contact joints then it may not be * appropriate to add contacts, however it is okay to add more contact between- * bodies that already have contacts. * @ingroup joints */ ODE_API int dAreConnectedExcluding (dBodyID body1, dBodyID body2, int joint_type); #ifdef __cplusplus } #endif #endif ode-0.16/include/ode/common.h0000664000175200017520000003514513403272463013005 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_COMMON_H_ #define _ODE_COMMON_H_ #include #include #ifdef __cplusplus extern "C" { #endif /* configuration stuff */ /* constants */ /* pi and 1/sqrt(2) are defined here if necessary because they don't get * defined in on some platforms (like MS-Windows) */ #ifndef M_PI #define M_PI REAL(3.1415926535897932384626433832795029) #endif #ifndef M_PI_2 #define M_PI_2 REAL(1.5707963267948966192313216916398) #endif #ifndef M_SQRT1_2 #define M_SQRT1_2 REAL(0.7071067811865475244008443621048490) #endif /* floating point data type, vector, matrix and quaternion types */ #if defined(dSINGLE) typedef float dReal; #ifdef dDOUBLE #error You can only #define dSINGLE or dDOUBLE, not both. #endif /* dDOUBLE */ #elif defined(dDOUBLE) typedef double dReal; #else #error You must #define dSINGLE or dDOUBLE #endif /* Detect if we've got both trimesh engines enabled. */ #if dTRIMESH_ENABLED #if dTRIMESH_OPCODE && dTRIMESH_GIMPACT #error You can only #define dTRIMESH_OPCODE or dTRIMESH_GIMPACT, not both. #endif #endif /* dTRIMESH_ENABLED */ /* * Define a type for indices, either 16 or 32 bit, based on build option * TODO: Currently GIMPACT only supports 32 bit indices. */ #if dTRIMESH_16BIT_INDICES #if dTRIMESH_GIMPACT typedef duint32 dTriIndex; #else /* dTRIMESH_GIMPACT */ typedef duint16 dTriIndex; #endif /* dTRIMESH_GIMPACT */ #else /* dTRIMESH_16BIT_INDICES */ typedef duint32 dTriIndex; #endif /* dTRIMESH_16BIT_INDICES */ /* round an integer up to a multiple of 4, except that 0 and 1 are unmodified * (used to compute matrix leading dimensions) */ #define dPAD(a) (((a) > 1) ? (((a) + 3) & (int)(~3)) : (a)) typedef enum { dSA__MIN, dSA_X = dSA__MIN, dSA_Y, dSA_Z, dSA__MAX, } dSpaceAxis; typedef enum { dMD__MIN, dMD_LINEAR = dMD__MIN, dMD_ANGULAR, dMD__MAX, } dMotionDynamics; typedef enum { dDA__MIN, dDA__L_MIN = dDA__MIN + dMD_LINEAR * dSA__MAX, dDA_LX = dDA__L_MIN + dSA_X, dDA_LY = dDA__L_MIN + dSA_Y, dDA_LZ = dDA__L_MIN + dSA_Z, dDA__L_MAX = dDA__L_MIN + dSA__MAX, dDA__A_MIN = dDA__MIN + dMD_ANGULAR * dSA__MAX, dDA_AX = dDA__A_MIN + dSA_X, dDA_AY = dDA__A_MIN + dSA_Y, dDA_AZ = dDA__A_MIN + dSA_Z, dDA__A_MAX = dDA__A_MIN + dSA__MAX, dDA__MAX = dDA__MIN + dMD__MAX * dSA__MAX, } dDynamicsAxis; typedef enum { dV3E__MIN, dV3E__AXES_MIN = dV3E__MIN, dV3E_X = dV3E__AXES_MIN + dSA_X, dV3E_Y = dV3E__AXES_MIN + dSA_Y, dV3E_Z = dV3E__AXES_MIN + dSA_Z, dV3E__AXES_MAX = dV3E__AXES_MIN + dSA__MAX, dV3E_PAD = dV3E__AXES_MAX, dV3E__MAX, dV3E__AXES_COUNT = dV3E__AXES_MAX - dV3E__AXES_MIN, } dVec3Element; typedef enum { dV4E__MIN, dV4E_X = dV4E__MIN + dSA_X, dV4E_Y = dV4E__MIN + dSA_Y, dV4E_Z = dV4E__MIN + dSA_Z, dV4E_O = dV4E__MIN + dSA__MAX, dV4E__MAX, } dVec4Element; typedef enum { dM3E__MIN, dM3E__X_MIN = dM3E__MIN + dSA_X * dV3E__MAX, dM3E__X_AXES_MIN = dM3E__X_MIN + dV3E__AXES_MIN, dM3E_XX = dM3E__X_MIN + dV3E_X, dM3E_XY = dM3E__X_MIN + dV3E_Y, dM3E_XZ = dM3E__X_MIN + dV3E_Z, dM3E__X_AXES_MAX = dM3E__X_MIN + dV3E__AXES_MAX, dM3E_XPAD = dM3E__X_MIN + dV3E_PAD, dM3E__X_MAX = dM3E__X_MIN + dV3E__MAX, dM3E__Y_MIN = dM3E__MIN + dSA_Y * dV3E__MAX, dM3E__Y_AXES_MIN = dM3E__Y_MIN + dV3E__AXES_MIN, dM3E_YX = dM3E__Y_MIN + dV3E_X, dM3E_YY = dM3E__Y_MIN + dV3E_Y, dM3E_YZ = dM3E__Y_MIN + dV3E_Z, dM3E__Y_AXES_MAX = dM3E__Y_MIN + dV3E__AXES_MAX, dM3E_YPAD = dM3E__Y_MIN + dV3E_PAD, dM3E__Y_MAX = dM3E__Y_MIN + dV3E__MAX, dM3E__Z_MIN = dM3E__MIN + dSA_Z * dV3E__MAX, dM3E__Z_AXES_MIN = dM3E__Z_MIN + dV3E__AXES_MIN, dM3E_ZX = dM3E__Z_MIN + dV3E_X, dM3E_ZY = dM3E__Z_MIN + dV3E_Y, dM3E_ZZ = dM3E__Z_MIN + dV3E_Z, dM3E__Z_AXES_MAX = dM3E__Z_MIN + dV3E__AXES_MAX, dM3E_ZPAD = dM3E__Z_MIN + dV3E_PAD, dM3E__Z_MAX = dM3E__Z_MIN + dV3E__MAX, dM3E__MAX = dM3E__MIN + dSA__MAX * dV3E__MAX, } dMat3Element; typedef enum { dM4E__MIN, dM4E__X_MIN = dM4E__MIN + dV4E_X * dV4E__MAX, dM4E_XX = dM4E__X_MIN + dV4E_X, dM4E_XY = dM4E__X_MIN + dV4E_Y, dM4E_XZ = dM4E__X_MIN + dV4E_Z, dM4E_XO = dM4E__X_MIN + dV4E_O, dM4E__X_MAX = dM4E__X_MIN + dV4E__MAX, dM4E__Y_MIN = dM4E__MIN + dV4E_Y * dV4E__MAX, dM4E_YX = dM4E__Y_MIN + dV4E_X, dM4E_YY = dM4E__Y_MIN + dV4E_Y, dM4E_YZ = dM4E__Y_MIN + dV4E_Z, dM4E_YO = dM4E__Y_MIN + dV4E_O, dM4E__Y_MAX = dM4E__Y_MIN + dV4E__MAX, dM4E__Z_MIN = dM4E__MIN + dV4E_Z * dV4E__MAX, dM4E_ZX = dM4E__Z_MIN + dV4E_X, dM4E_ZY = dM4E__Z_MIN + dV4E_Y, dM4E_ZZ = dM4E__Z_MIN + dV4E_Z, dM4E_ZO = dM4E__Z_MIN + dV4E_O, dM4E__Z_MAX = dM4E__Z_MIN + dV4E__MAX, dM4E__O_MIN = dM4E__MIN + dV4E_O * dV4E__MAX, dM4E_OX = dM4E__O_MIN + dV4E_X, dM4E_OY = dM4E__O_MIN + dV4E_Y, dM4E_OZ = dM4E__O_MIN + dV4E_Z, dM4E_OO = dM4E__O_MIN + dV4E_O, dM4E__O_MAX = dM4E__O_MIN + dV4E__MAX, dM4E__MAX = dM4E__MIN + dV4E__MAX * dV4E__MAX, } dMat4Element; typedef enum { dQUE__MIN, dQUE_R = dQUE__MIN, dQUE__AXIS_MIN, dQUE_I = dQUE__AXIS_MIN + dSA_X, dQUE_J = dQUE__AXIS_MIN + dSA_Y, dQUE_K = dQUE__AXIS_MIN + dSA_Z, dQUE__AXIS_MAX = dQUE__AXIS_MIN + dSA__MAX, dQUE__MAX = dQUE__AXIS_MAX, } dQuatElement; /* these types are mainly just used in headers */ typedef dReal dVector3[dV3E__MAX]; typedef dReal dVector4[dV4E__MAX]; typedef dReal dMatrix3[dM3E__MAX]; typedef dReal dMatrix4[dM4E__MAX]; typedef dReal dMatrix6[(dMD__MAX * dV3E__MAX) * (dMD__MAX * dSA__MAX)]; typedef dReal dQuaternion[dQUE__MAX]; /* precision dependent scalar math functions */ #if defined(dSINGLE) #define REAL(x) (x##f) /* form a constant */ #define dRecip(x) ((1.0f/(x))) /* reciprocal */ #define dSqrt(x) (sqrtf(x)) /* square root */ #define dRecipSqrt(x) ((1.0f/sqrtf(x))) /* reciprocal square root */ #define dSin(x) (sinf(x)) /* sine */ #define dCos(x) (cosf(x)) /* cosine */ #define dFabs(x) (fabsf(x)) /* absolute value */ #define dAtan2(y,x) (atan2f(y,x)) /* arc tangent with 2 args */ #define dAsin(x) (asinf(x)) #define dAcos(x) (acosf(x)) #define dFMod(a,b) (fmodf(a,b)) /* modulo */ #define dFloor(x) floorf(x) /* floor */ #define dCeil(x) ceilf(x) /* ceil */ #define dCopySign(a,b) _ode_copysignf(a, b) /* copy value sign */ #define dNextAfter(x, y) _ode_nextafterf(x, y) /* next value after */ #ifdef HAVE___ISNANF #define dIsNan(x) (__isnanf(x)) #elif defined(HAVE__ISNANF) #define dIsNan(x) (_isnanf(x)) #elif defined(HAVE_ISNANF) #define dIsNan(x) (isnanf(x)) #else /* fall back to _isnan which is the VC way, this may seem redundant since we already checked for _isnan before, but if isnan is detected by configure but is not found during compilation we should always make sure we check for __isnanf, _isnanf and isnanf in that order before falling back to a default */ #define dIsNan(x) (_isnan(x)) #endif #elif defined(dDOUBLE) #define REAL(x) (x) #define dRecip(x) (1.0/(x)) #define dSqrt(x) sqrt(x) #define dRecipSqrt(x) (1.0/sqrt(x)) #define dSin(x) sin(x) #define dCos(x) cos(x) #define dFabs(x) fabs(x) #define dAtan2(y,x) atan2((y),(x)) #define dAsin(x) asin(x) #define dAcos(x) acos(x) #define dFMod(a,b) (fmod((a),(b))) #define dFloor(x) floor(x) #define dCeil(x) ceil(x) #define dCopySign(a,b) _ode_copysign(a, b) #define dNextAfter(x, y) _ode_nextafter(x, y) #ifdef HAVE___ISNAN #define dIsNan(x) (__isnan(x)) #elif defined(HAVE__ISNAN) #define dIsNan(x) (_isnan(x)) #elif defined(HAVE_ISNAN) #define dIsNan(x) (isnan(x)) #else #define dIsNan(x) (_isnan(x)) #endif #else #error You must #define dSINGLE or dDOUBLE #endif ODE_PURE_INLINE dReal dMin(dReal x, dReal y) { return x <= y ? x : y; } ODE_PURE_INLINE dReal dMax(dReal x, dReal y) { return x <= y ? y : x; } /* internal object types (all prefixed with `dx') */ struct dxWorld; /* dynamics world */ struct dxSpace; /* collision space */ struct dxBody; /* rigid body (dynamics object) */ struct dxGeom; /* geometry (collision object) */ struct dxJoint; /* joint */ struct dxJointGroup;/* joint group */ typedef struct dxWorld *dWorldID; typedef struct dxSpace *dSpaceID; typedef struct dxBody *dBodyID; typedef struct dxGeom *dGeomID; typedef struct dxJoint *dJointID; typedef struct dxJointGroup *dJointGroupID; /* error numbers */ enum { d_ERR_UNKNOWN = 0, /* unknown error */ d_ERR_IASSERT, /* internal assertion failed */ d_ERR_UASSERT, /* user assertion failed */ d_ERR_LCP /* user assertion failed */ }; /* joint type numbers */ typedef enum { dJointTypeNone = 0, /* or "unknown" */ dJointTypeBall, dJointTypeHinge, dJointTypeSlider, dJointTypeContact, dJointTypeUniversal, dJointTypeHinge2, dJointTypeFixed, dJointTypeNull, dJointTypeAMotor, dJointTypeLMotor, dJointTypePlane2D, dJointTypePR, dJointTypePU, dJointTypePiston, dJointTypeDBall, dJointTypeDHinge, dJointTypeTransmission, } dJointType; /* an alternative way of setting joint parameters, using joint parameter * structures and member constants. we don't actually do this yet. */ /* typedef struct dLimot { int mode; dReal lostop, histop; dReal vel, fmax; dReal fudge_factor; dReal bounce, soft; dReal suspension_erp, suspension_cfm; } dLimot; enum { dLimotLoStop = 0x0001, dLimotHiStop = 0x0002, dLimotVel = 0x0004, dLimotFMax = 0x0008, dLimotFudgeFactor = 0x0010, dLimotBounce = 0x0020, dLimotSoft = 0x0040 }; */ /* standard joint parameter names. why are these here? - because we don't want * to include all the joint function definitions in joint.cpp. hmmmm. * MSVC complains if we call D_ALL_PARAM_NAMES_X with a blank second argument, * which is why we have the D_ALL_PARAM_NAMES macro as well. please copy and * paste between these two. */ #define D_ALL_PARAM_NAMES(start) \ /* parameters for limits and motors */ \ dParamLoStop = start, \ dParamHiStop, \ dParamVel, \ dParamLoVel, \ dParamHiVel, \ dParamFMax, \ dParamFudgeFactor, \ dParamBounce, \ dParamCFM, \ dParamStopERP, \ dParamStopCFM, \ /* parameters for suspension */ \ dParamSuspensionERP, \ dParamSuspensionCFM, \ dParamERP, \ /* * \enum D_ALL_PARAM_NAMES_X * * \var dParamGroup This is the starting value of the different group * (i.e. dParamGroup1, dParamGroup2, dParamGroup3) * It also helps in the use of parameter * (dParamGroup2 | dParamFMax) == dParamFMax2 */ #define D_ALL_PARAM_NAMES_X(start,x) \ dParamGroup ## x = start, \ /* parameters for limits and motors */ \ dParamLoStop ## x = start, \ dParamHiStop ## x, \ dParamVel ## x, \ dParamLoVel ## x, \ dParamHiVel ## x, \ dParamFMax ## x, \ dParamFudgeFactor ## x, \ dParamBounce ## x, \ dParamCFM ## x, \ dParamStopERP ## x, \ dParamStopCFM ## x, \ /* parameters for suspension */ \ dParamSuspensionERP ## x, \ dParamSuspensionCFM ## x, \ dParamERP ## x, enum { D_ALL_PARAM_NAMES(0) dParamsInGroup, /* < Number of parameter in a group */ D_ALL_PARAM_NAMES_X(0x000,1) D_ALL_PARAM_NAMES_X(0x100,2) D_ALL_PARAM_NAMES_X(0x200,3) /* add a multiple of this constant to the basic parameter numbers to get * the parameters for the second, third etc axes. */ dParamGroup=0x100 }; /* angular motor mode numbers */ enum { dAMotorUser = 0, dAMotorEuler = 1 }; /* transmission joint mode numbers */ enum { dTransmissionParallelAxes = 0, dTransmissionIntersectingAxes = 1, dTransmissionChainDrive = 2 }; /* joint force feedback information */ typedef struct dJointFeedback { dVector3 f1; /* force applied to body 1 */ dVector3 t1; /* torque applied to body 1 */ dVector3 f2; /* force applied to body 2 */ dVector3 t2; /* torque applied to body 2 */ } dJointFeedback; /* private functions that must be implemented by the collision library: * (1) indicate that a geom has moved, (2) get the next geom in a body list. * these functions are called whenever the position of geoms connected to a * body have changed, e.g. with dBodySetPosition(), dBodySetRotation(), or * when the ODE step function updates the body state. */ void dGeomMoved (dGeomID); dGeomID dGeomGetBodyNext (dGeomID); /** * dGetConfiguration returns the specific ODE build configuration as * a string of tokens. The string can be parsed in a similar way to * the OpenGL extension mechanism, the naming convention should be * familiar too. The following extensions are reported: * * ODE * ODE_single_precision * ODE_double_precision * ODE_EXT_no_debug * ODE_EXT_trimesh * ODE_EXT_opcode * ODE_EXT_gimpact * ODE_OPC_16bit_indices * ODE_OPC_new_collider * ODE_EXT_mt_collisions * ODE_EXT_threading * ODE_THR_builtin_impl */ ODE_API const char* dGetConfiguration (void); /** * Helper to check for a token in the ODE configuration string. * Caution, this function is case sensitive. * * @param token A configuration token, see dGetConfiguration for details * * @return 1 if exact token is present, 0 if not present */ ODE_API int dCheckConfiguration( const char* token ); #ifdef __cplusplus } #endif #endif ode-0.16/include/ode/odemath_legacy.h0000664000175200017520000001335113403272463014455 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_ODEMATH_LEGACY_H_ #define _ODE_ODEMATH_LEGACY_H_ /* * These macros are not used any more inside of ODE * They are kept for backward compatibility with external code that * might still be using them. */ /* * General purpose vector operations with other vectors or constants. */ #define dOP(a,op,b,c) do { \ (a)[0] = ((b)[0]) op ((c)[0]); \ (a)[1] = ((b)[1]) op ((c)[1]); \ (a)[2] = ((b)[2]) op ((c)[2]); \ } while (0) #define dOPC(a,op,b,c) do { \ (a)[0] = ((b)[0]) op (c); \ (a)[1] = ((b)[1]) op (c); \ (a)[2] = ((b)[2]) op (c); \ } while (0) #define dOPE(a,op,b) do {\ (a)[0] op ((b)[0]); \ (a)[1] op ((b)[1]); \ (a)[2] op ((b)[2]); \ } while (0) #define dOPEC(a,op,c) do { \ (a)[0] op (c); \ (a)[1] op (c); \ (a)[2] op (c); \ } while (0) /* Define an equation with operators * For example this function can be used to replace *
 * for (int i=0; i<3; ++i)
 *   a[i] += b[i] + c[i];
 * 
*/ #define dOPE2(a,op1,b,op2,c) do { \ (a)[0] op1 ((b)[0]) op2 ((c)[0]); \ (a)[1] op1 ((b)[1]) op2 ((c)[1]); \ (a)[2] op1 ((b)[2]) op2 ((c)[2]); \ } while (0) #define dLENGTHSQUARED(a) dCalcVectorLengthSquare3(a) #define dLENGTH(a) dCalcVectorLength3(a) #define dDISTANCE(a, b) dCalcPointsDistance3(a, b) #define dDOT(a, b) dCalcVectorDot3(a, b) #define dDOT13(a, b) dCalcVectorDot3_13(a, b) #define dDOT31(a, b) dCalcVectorDot3_31(a, b) #define dDOT33(a, b) dCalcVectorDot3_33(a, b) #define dDOT14(a, b) dCalcVectorDot3_14(a, b) #define dDOT41(a, b) dCalcVectorDot3_41(a, b) #define dDOT44(a, b) dCalcVectorDot3_44(a, b) /* * cross product, set a = b x c. dCROSSpqr means that elements of `a', `b' * and `c' are spaced p, q and r indexes apart respectively. * dCROSS() means dCROSS111. `op' is normally `=', but you can set it to * +=, -= etc to get other effects. */ #define dCROSS(a,op,b,c) \ do { \ (a)[0] op ((b)[1]*(c)[2] - (b)[2]*(c)[1]); \ (a)[1] op ((b)[2]*(c)[0] - (b)[0]*(c)[2]); \ (a)[2] op ((b)[0]*(c)[1] - (b)[1]*(c)[0]); \ } while(0) #define dCROSSpqr(a,op,b,c,p,q,r) \ do { \ (a)[ 0] op ((b)[ q]*(c)[2*r] - (b)[2*q]*(c)[ r]); \ (a)[ p] op ((b)[2*q]*(c)[ 0] - (b)[ 0]*(c)[2*r]); \ (a)[2*p] op ((b)[ 0]*(c)[ r] - (b)[ q]*(c)[ 0]); \ } while(0) #define dCROSS114(a,op,b,c) dCROSSpqr(a,op,b,c,1,1,4) #define dCROSS141(a,op,b,c) dCROSSpqr(a,op,b,c,1,4,1) #define dCROSS144(a,op,b,c) dCROSSpqr(a,op,b,c,1,4,4) #define dCROSS411(a,op,b,c) dCROSSpqr(a,op,b,c,4,1,1) #define dCROSS414(a,op,b,c) dCROSSpqr(a,op,b,c,4,1,4) #define dCROSS441(a,op,b,c) dCROSSpqr(a,op,b,c,4,4,1) #define dCROSS444(a,op,b,c) dCROSSpqr(a,op,b,c,4,4,4) /* * set a 3x3 submatrix of A to a matrix such that submatrix(A)*b = a x b. * A is stored by rows, and has `skip' elements per row. the matrix is * assumed to be already zero, so this does not write zero elements! * if (plus,minus) is (+,-) then a positive version will be written. * if (plus,minus) is (-,+) then a negative version will be written. */ #define dCROSSMAT(A,a,skip,plus,minus) \ do { \ (A)[1] = minus (a)[2]; \ (A)[2] = plus (a)[1]; \ (A)[(skip)+0] = plus (a)[2]; \ (A)[(skip)+2] = minus (a)[0]; \ (A)[2*(skip)+0] = minus (a)[1]; \ (A)[2*(skip)+1] = plus (a)[0]; \ } while(0) /* Note: NEVER call any of these functions/macros with the same variable for A and C, it is not equivalent to A*=B. */ #define dMULTIPLY0_331(A, B, C) dMultiply0_331(A, B, C) #define dMULTIPLY1_331(A, B, C) dMultiply1_331(A, B, C) #define dMULTIPLY0_133(A, B, C) dMultiply0_133(A, B, C) #define dMULTIPLY0_333(A, B, C) dMultiply0_333(A, B, C) #define dMULTIPLY1_333(A, B, C) dMultiply1_333(A, B, C) #define dMULTIPLY2_333(A, B, C) dMultiply2_333(A, B, C) #define dMULTIPLYADD0_331(A, B, C) dMultiplyAdd0_331(A, B, C) #define dMULTIPLYADD1_331(A, B, C) dMultiplyAdd1_331(A, B, C) #define dMULTIPLYADD0_133(A, B, C) dMultiplyAdd0_133(A, B, C) #define dMULTIPLYADD0_333(A, B, C) dMultiplyAdd0_333(A, B, C) #define dMULTIPLYADD1_333(A, B, C) dMultiplyAdd1_333(A, B, C) #define dMULTIPLYADD2_333(A, B, C) dMultiplyAdd2_333(A, B, C) /* * These macros are not used any more inside of ODE * They are kept for backward compatibility with external code that * might still be using them. */ #endif /* #ifndef _ODE_ODEMATH_LEGACY_H_ */ ode-0.16/include/ode/odemath.h0000664000175200017520000004603513403272463013136 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_ODEMATH_H_ #define _ODE_ODEMATH_H_ #include /* * macro to access elements i,j in an NxM matrix A, independent of the * matrix storage convention. */ #define dACCESS33(A,i,j) ((A)[(i)*4+(j)]) /* * Macro to test for valid floating point values */ #define dVALIDVEC3(v) (!(dIsNan(v[0]) || dIsNan(v[1]) || dIsNan(v[2]))) #define dVALIDVEC4(v) (!(dIsNan(v[0]) || dIsNan(v[1]) || dIsNan(v[2]) || dIsNan(v[3]))) #define dVALIDMAT3(m) (!(dIsNan(m[0]) || dIsNan(m[1]) || dIsNan(m[2]) || dIsNan(m[3]) || dIsNan(m[4]) || dIsNan(m[5]) || dIsNan(m[6]) || dIsNan(m[7]) || dIsNan(m[8]) || dIsNan(m[9]) || dIsNan(m[10]) || dIsNan(m[11]))) #define dVALIDMAT4(m) (!(dIsNan(m[0]) || dIsNan(m[1]) || dIsNan(m[2]) || dIsNan(m[3]) || dIsNan(m[4]) || dIsNan(m[5]) || dIsNan(m[6]) || dIsNan(m[7]) || dIsNan(m[8]) || dIsNan(m[9]) || dIsNan(m[10]) || dIsNan(m[11]) || dIsNan(m[12]) || dIsNan(m[13]) || dIsNan(m[14]) || dIsNan(m[15]) )) ODE_PURE_INLINE void dZeroVector3(dVector3 res) { res[dV3E_X] = REAL(0.0); res[dV3E_Y] = REAL(0.0); res[dV3E_Z] = REAL(0.0); } ODE_PURE_INLINE void dAssignVector3(dVector3 res, dReal x, dReal y, dReal z) { res[dV3E_X] = x; res[dV3E_Y] = y; res[dV3E_Z] = z; } ODE_PURE_INLINE void dZeroMatrix3(dMatrix3 res) { res[dM3E_XX] = REAL(0.0); res[dM3E_XY] = REAL(0.0); res[dM3E_XZ] = REAL(0.0); res[dM3E_YX] = REAL(0.0); res[dM3E_YY] = REAL(0.0); res[dM3E_YZ] = REAL(0.0); res[dM3E_ZX] = REAL(0.0); res[dM3E_ZY] = REAL(0.0); res[dM3E_ZZ] = REAL(0.0); } ODE_PURE_INLINE void dZeroMatrix4(dMatrix4 res) { res[dM4E_XX] = REAL(0.0); res[dM4E_XY] = REAL(0.0); res[dM4E_XZ] = REAL(0.0); res[dM4E_XO] = REAL(0.0); res[dM4E_YX] = REAL(0.0); res[dM4E_YY] = REAL(0.0); res[dM4E_YZ] = REAL(0.0); res[dM4E_YO] = REAL(0.0); res[dM4E_ZX] = REAL(0.0); res[dM4E_ZY] = REAL(0.0); res[dM4E_ZZ] = REAL(0.0); res[dM4E_ZO] = REAL(0.0); res[dM4E_OX] = REAL(0.0); res[dM4E_OY] = REAL(0.0); res[dM4E_OZ] = REAL(0.0); res[dM4E_OO] = REAL(0.0); } /* Some vector math */ ODE_PURE_INLINE void dAddVectors3(dReal *res, const dReal *a, const dReal *b) { const dReal res_0 = a[0] + b[0]; const dReal res_1 = a[1] + b[1]; const dReal res_2 = a[2] + b[2]; /* Only assign after all the calculations are over to avoid incurring memory aliasing*/ res[0] = res_0; res[1] = res_1; res[2] = res_2; } ODE_PURE_INLINE void dSubtractVectors3(dReal *res, const dReal *a, const dReal *b) { const dReal res_0 = a[0] - b[0]; const dReal res_1 = a[1] - b[1]; const dReal res_2 = a[2] - b[2]; /* Only assign after all the calculations are over to avoid incurring memory aliasing*/ res[0] = res_0; res[1] = res_1; res[2] = res_2; } ODE_PURE_INLINE void dAddVectorScaledVector3(dReal *res, const dReal *a, const dReal *b, dReal b_scale) { const dReal res_0 = a[0] + b_scale * b[0]; const dReal res_1 = a[1] + b_scale * b[1]; const dReal res_2 = a[2] + b_scale * b[2]; /* Only assign after all the calculations are over to avoid incurring memory aliasing*/ res[0] = res_0; res[1] = res_1; res[2] = res_2; } ODE_PURE_INLINE void dAddScaledVectors3(dReal *res, const dReal *a, const dReal *b, dReal a_scale, dReal b_scale) { const dReal res_0 = a_scale * a[0] + b_scale * b[0]; const dReal res_1 = a_scale * a[1] + b_scale * b[1]; const dReal res_2 = a_scale * a[2] + b_scale * b[2]; /* Only assign after all the calculations are over to avoid incurring memory aliasing*/ res[0] = res_0; res[1] = res_1; res[2] = res_2; } ODE_PURE_INLINE void dAddThreeScaledVectors3(dReal *res, const dReal *a, const dReal *b, const dReal *c, dReal a_scale, dReal b_scale, dReal c_scale) { const dReal res_0 = a_scale * a[0] + b_scale * b[0] + c_scale * c[0]; const dReal res_1 = a_scale * a[1] + b_scale * b[1] + c_scale * c[1]; const dReal res_2 = a_scale * a[2] + b_scale * b[2] + c_scale * c[2]; /* Only assign after all the calculations are over to avoid incurring memory aliasing*/ res[0] = res_0; res[1] = res_1; res[2] = res_2; } ODE_PURE_INLINE void dScaleVector3(dReal *res, dReal nScale) { res[0] *= nScale ; res[1] *= nScale ; res[2] *= nScale ; } ODE_PURE_INLINE void dNegateVector3(dReal *res) { res[0] = -res[0]; res[1] = -res[1]; res[2] = -res[2]; } ODE_PURE_INLINE void dCopyVector3(dReal *res, const dReal *a) { const dReal res_0 = a[0]; const dReal res_1 = a[1]; const dReal res_2 = a[2]; /* Only assign after all the calculations are over to avoid incurring memory aliasing*/ res[0] = res_0; res[1] = res_1; res[2] = res_2; } ODE_PURE_INLINE void dCopyScaledVector3(dReal *res, const dReal *a, dReal nScale) { const dReal res_0 = a[0] * nScale; const dReal res_1 = a[1] * nScale; const dReal res_2 = a[2] * nScale; /* Only assign after all the calculations are over to avoid incurring memory aliasing*/ res[0] = res_0; res[1] = res_1; res[2] = res_2; } ODE_PURE_INLINE void dCopyNegatedVector3(dReal *res, const dReal *a) { const dReal res_0 = -a[0]; const dReal res_1 = -a[1]; const dReal res_2 = -a[2]; /* Only assign after all the calculations are over to avoid incurring memory aliasing*/ res[0] = res_0; res[1] = res_1; res[2] = res_2; } ODE_PURE_INLINE void dCopyVector4(dReal *res, const dReal *a) { const dReal res_0 = a[0]; const dReal res_1 = a[1]; const dReal res_2 = a[2]; const dReal res_3 = a[3]; /* Only assign after all the calculations are over to avoid incurring memory aliasing*/ res[0] = res_0; res[1] = res_1; res[2] = res_2; res[3] = res_3; } ODE_PURE_INLINE void dCopyMatrix4x4(dReal *res, const dReal *a) { dCopyVector4(res + 0, a + 0); dCopyVector4(res + 4, a + 4); dCopyVector4(res + 8, a + 8); } ODE_PURE_INLINE void dCopyMatrix4x3(dReal *res, const dReal *a) { dCopyVector3(res + 0, a + 0); dCopyVector3(res + 4, a + 4); dCopyVector3(res + 8, a + 8); } ODE_PURE_INLINE void dGetMatrixColumn3(dReal *res, const dReal *a, unsigned n) { const dReal res_0 = a[n + 0]; const dReal res_1 = a[n + 4]; const dReal res_2 = a[n + 8]; /* Only assign after all the calculations are over to avoid incurring memory aliasing*/ res[0] = res_0; res[1] = res_1; res[2] = res_2; } ODE_PURE_INLINE dReal dCalcVectorLength3(const dReal *a) { return dSqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]); } ODE_PURE_INLINE dReal dCalcVectorLengthSquare3(const dReal *a) { return (a[0] * a[0] + a[1] * a[1] + a[2] * a[2]); } ODE_PURE_INLINE dReal dCalcPointDepth3(const dReal *test_p, const dReal *plane_p, const dReal *plane_n) { return (plane_p[0] - test_p[0]) * plane_n[0] + (plane_p[1] - test_p[1]) * plane_n[1] + (plane_p[2] - test_p[2]) * plane_n[2]; } /* * 3-way dot product. _dCalcVectorDot3 means that elements of `a' and `b' are spaced * step_a and step_b indexes apart respectively. dCalcVectorDot3() means dDot311. */ ODE_PURE_INLINE dReal _dCalcVectorDot3(const dReal *a, const dReal *b, unsigned step_a, unsigned step_b) { return a[0] * b[0] + a[step_a] * b[step_b] + a[2 * step_a] * b[2 * step_b]; } ODE_PURE_INLINE dReal dCalcVectorDot3 (const dReal *a, const dReal *b) { return _dCalcVectorDot3(a,b,1,1); } ODE_PURE_INLINE dReal dCalcVectorDot3_13 (const dReal *a, const dReal *b) { return _dCalcVectorDot3(a,b,1,3); } ODE_PURE_INLINE dReal dCalcVectorDot3_31 (const dReal *a, const dReal *b) { return _dCalcVectorDot3(a,b,3,1); } ODE_PURE_INLINE dReal dCalcVectorDot3_33 (const dReal *a, const dReal *b) { return _dCalcVectorDot3(a,b,3,3); } ODE_PURE_INLINE dReal dCalcVectorDot3_14 (const dReal *a, const dReal *b) { return _dCalcVectorDot3(a,b,1,4); } ODE_PURE_INLINE dReal dCalcVectorDot3_41 (const dReal *a, const dReal *b) { return _dCalcVectorDot3(a,b,4,1); } ODE_PURE_INLINE dReal dCalcVectorDot3_44 (const dReal *a, const dReal *b) { return _dCalcVectorDot3(a,b,4,4); } /* * cross product, set res = a x b. _dCalcVectorCross3 means that elements of `res', `a' * and `b' are spaced step_res, step_a and step_b indexes apart respectively. * dCalcVectorCross3() means dCross3111. */ ODE_PURE_INLINE void _dCalcVectorCross3(dReal *res, const dReal *a, const dReal *b, unsigned step_res, unsigned step_a, unsigned step_b) { const dReal res_0 = a[ step_a]*b[2*step_b] - a[2*step_a]*b[ step_b]; const dReal res_1 = a[2*step_a]*b[ 0] - a[ 0]*b[2*step_b]; const dReal res_2 = a[ 0]*b[ step_b] - a[ step_a]*b[ 0]; /* Only assign after all the calculations are over to avoid incurring memory aliasing*/ res[ 0] = res_0; res[ step_res] = res_1; res[2*step_res] = res_2; } ODE_PURE_INLINE void dCalcVectorCross3 (dReal *res, const dReal *a, const dReal *b) { _dCalcVectorCross3(res, a, b, 1, 1, 1); } ODE_PURE_INLINE void dCalcVectorCross3_114(dReal *res, const dReal *a, const dReal *b) { _dCalcVectorCross3(res, a, b, 1, 1, 4); } ODE_PURE_INLINE void dCalcVectorCross3_141(dReal *res, const dReal *a, const dReal *b) { _dCalcVectorCross3(res, a, b, 1, 4, 1); } ODE_PURE_INLINE void dCalcVectorCross3_144(dReal *res, const dReal *a, const dReal *b) { _dCalcVectorCross3(res, a, b, 1, 4, 4); } ODE_PURE_INLINE void dCalcVectorCross3_411(dReal *res, const dReal *a, const dReal *b) { _dCalcVectorCross3(res, a, b, 4, 1, 1); } ODE_PURE_INLINE void dCalcVectorCross3_414(dReal *res, const dReal *a, const dReal *b) { _dCalcVectorCross3(res, a, b, 4, 1, 4); } ODE_PURE_INLINE void dCalcVectorCross3_441(dReal *res, const dReal *a, const dReal *b) { _dCalcVectorCross3(res, a, b, 4, 4, 1); } ODE_PURE_INLINE void dCalcVectorCross3_444(dReal *res, const dReal *a, const dReal *b) { _dCalcVectorCross3(res, a, b, 4, 4, 4); } ODE_PURE_INLINE void dAddVectorCross3(dReal *res, const dReal *a, const dReal *b) { dReal tmp[3]; dCalcVectorCross3(tmp, a, b); dAddVectors3(res, res, tmp); } ODE_PURE_INLINE void dSubtractVectorCross3(dReal *res, const dReal *a, const dReal *b) { dReal tmp[3]; dCalcVectorCross3(tmp, a, b); dSubtractVectors3(res, res, tmp); } /* * set a 3x3 submatrix of A to a matrix such that submatrix(A)*b = a x b. * A is stored by rows, and has `skip' elements per row. the matrix is * assumed to be already zero, so this does not write zero elements! * if (plus,minus) is (+,-) then a positive version will be written. * if (plus,minus) is (-,+) then a negative version will be written. */ ODE_PURE_INLINE void dSetCrossMatrixPlus(dReal *res, const dReal *a, unsigned skip) { const dReal a_0 = a[0], a_1 = a[1], a_2 = a[2]; res[1] = -a_2; res[2] = +a_1; res[skip+0] = +a_2; res[skip+2] = -a_0; res[2*skip+0] = -a_1; res[2*skip+1] = +a_0; } ODE_PURE_INLINE void dSetCrossMatrixMinus(dReal *res, const dReal *a, unsigned skip) { const dReal a_0 = a[0], a_1 = a[1], a_2 = a[2]; res[1] = +a_2; res[2] = -a_1; res[skip+0] = -a_2; res[skip+2] = +a_0; res[2*skip+0] = +a_1; res[2*skip+1] = -a_0; } /* * compute the distance between two 3D-vectors */ ODE_PURE_INLINE dReal dCalcPointsDistance3(const dReal *a, const dReal *b) { dReal res; dReal tmp[3]; dSubtractVectors3(tmp, a, b); res = dCalcVectorLength3(tmp); return res; } /* * special case matrix multiplication, with operator selection */ ODE_PURE_INLINE void dMultiplyHelper0_331(dReal *res, const dReal *a, const dReal *b) { const dReal res_0 = dCalcVectorDot3(a, b); const dReal res_1 = dCalcVectorDot3(a + 4, b); const dReal res_2 = dCalcVectorDot3(a + 8, b); /* Only assign after all the calculations are over to avoid incurring memory aliasing*/ res[0] = res_0; res[1] = res_1; res[2] = res_2; } ODE_PURE_INLINE void dMultiplyHelper1_331(dReal *res, const dReal *a, const dReal *b) { const dReal res_0 = dCalcVectorDot3_41(a, b); const dReal res_1 = dCalcVectorDot3_41(a + 1, b); const dReal res_2 = dCalcVectorDot3_41(a + 2, b); /* Only assign after all the calculations are over to avoid incurring memory aliasing*/ res[0] = res_0; res[1] = res_1; res[2] = res_2; } ODE_PURE_INLINE void dMultiplyHelper0_133(dReal *res, const dReal *a, const dReal *b) { dMultiplyHelper1_331(res, b, a); } ODE_PURE_INLINE void dMultiplyHelper1_133(dReal *res, const dReal *a, const dReal *b) { const dReal res_0 = dCalcVectorDot3_44(a, b); const dReal res_1 = dCalcVectorDot3_44(a + 1, b); const dReal res_2 = dCalcVectorDot3_44(a + 2, b); /* Only assign after all the calculations are over to avoid incurring memory aliasing*/ res[0] = res_0; res[1] = res_1; res[2] = res_2; } /* Note: NEVER call any of these functions/macros with the same variable for A and C, it is not equivalent to A*=B. */ ODE_PURE_INLINE void dMultiply0_331(dReal *res, const dReal *a, const dReal *b) { dMultiplyHelper0_331(res, a, b); } ODE_PURE_INLINE void dMultiply1_331(dReal *res, const dReal *a, const dReal *b) { dMultiplyHelper1_331(res, a, b); } ODE_PURE_INLINE void dMultiply0_133(dReal *res, const dReal *a, const dReal *b) { dMultiplyHelper0_133(res, a, b); } ODE_PURE_INLINE void dMultiply0_333(dReal *res, const dReal *a, const dReal *b) { dMultiplyHelper0_133(res + 0, a + 0, b); dMultiplyHelper0_133(res + 4, a + 4, b); dMultiplyHelper0_133(res + 8, a + 8, b); } ODE_PURE_INLINE void dMultiply1_333(dReal *res, const dReal *a, const dReal *b) { dMultiplyHelper1_133(res + 0, b, a + 0); dMultiplyHelper1_133(res + 4, b, a + 1); dMultiplyHelper1_133(res + 8, b, a + 2); } ODE_PURE_INLINE void dMultiply2_333(dReal *res, const dReal *a, const dReal *b) { dMultiplyHelper0_331(res + 0, b, a + 0); dMultiplyHelper0_331(res + 4, b, a + 4); dMultiplyHelper0_331(res + 8, b, a + 8); } ODE_PURE_INLINE void dMultiplyAdd0_331(dReal *res, const dReal *a, const dReal *b) { dReal tmp[3]; dMultiplyHelper0_331(tmp, a, b); dAddVectors3(res, res, tmp); } ODE_PURE_INLINE void dMultiplyAdd1_331(dReal *res, const dReal *a, const dReal *b) { dReal tmp[3]; dMultiplyHelper1_331(tmp, a, b); dAddVectors3(res, res, tmp); } ODE_PURE_INLINE void dMultiplyAdd0_133(dReal *res, const dReal *a, const dReal *b) { dReal tmp[3]; dMultiplyHelper0_133(tmp, a, b); dAddVectors3(res, res, tmp); } ODE_PURE_INLINE void dMultiplyAdd0_333(dReal *res, const dReal *a, const dReal *b) { dReal tmp[3]; dMultiplyHelper0_133(tmp, a + 0, b); dAddVectors3(res+ 0, res + 0, tmp); dMultiplyHelper0_133(tmp, a + 4, b); dAddVectors3(res + 4, res + 4, tmp); dMultiplyHelper0_133(tmp, a + 8, b); dAddVectors3(res + 8, res + 8, tmp); } ODE_PURE_INLINE void dMultiplyAdd1_333(dReal *res, const dReal *a, const dReal *b) { dReal tmp[3]; dMultiplyHelper1_133(tmp, b, a + 0); dAddVectors3(res + 0, res + 0, tmp); dMultiplyHelper1_133(tmp, b, a + 1); dAddVectors3(res + 4, res + 4, tmp); dMultiplyHelper1_133(tmp, b, a + 2); dAddVectors3(res + 8, res + 8, tmp); } ODE_PURE_INLINE void dMultiplyAdd2_333(dReal *res, const dReal *a, const dReal *b) { dReal tmp[3]; dMultiplyHelper0_331(tmp, b, a + 0); dAddVectors3(res + 0, res + 0, tmp); dMultiplyHelper0_331(tmp, b, a + 4); dAddVectors3(res + 4, res + 4, tmp); dMultiplyHelper0_331(tmp, b, a + 8); dAddVectors3(res + 8, res + 8, tmp); } ODE_PURE_INLINE dReal dCalcMatrix3Det( const dReal* mat ) { dReal det; det = mat[0] * ( mat[5]*mat[10] - mat[9]*mat[6] ) - mat[1] * ( mat[4]*mat[10] - mat[8]*mat[6] ) + mat[2] * ( mat[4]*mat[9] - mat[8]*mat[5] ); return( det ); } /** Closed form matrix inversion, copied from collision_util.h for use in the stepper. Returns the determinant. returns 0 and does nothing if the matrix is singular. */ ODE_PURE_INLINE dReal dInvertMatrix3(dReal *dst, const dReal *ma) { dReal det; dReal detRecip; det = dCalcMatrix3Det( ma ); /* Setting an arbitrary non-zero threshold for the determinant doesn't do anyone any favors. The condition number is the important thing. If all the eigen-values of the matrix are small, so is the determinant, but it can still be well conditioned. A single extremely large eigen-value could push the determinant over threshold, but produce a very unstable result if the other eigen-values are small. So we just say that the determinant must be non-zero and trust the caller to provide well-conditioned matrices. */ if ( det == 0 ) { return 0; } detRecip = dRecip(det); dst[0] = ( ma[5]*ma[10] - ma[6]*ma[9] ) * detRecip; dst[1] = ( ma[9]*ma[2] - ma[1]*ma[10] ) * detRecip; dst[2] = ( ma[1]*ma[6] - ma[5]*ma[2] ) * detRecip; dst[4] = ( ma[6]*ma[8] - ma[4]*ma[10] ) * detRecip; dst[5] = ( ma[0]*ma[10] - ma[8]*ma[2] ) * detRecip; dst[6] = ( ma[4]*ma[2] - ma[0]*ma[6] ) * detRecip; dst[8] = ( ma[4]*ma[9] - ma[8]*ma[5] ) * detRecip; dst[9] = ( ma[8]*ma[1] - ma[0]*ma[9] ) * detRecip; dst[10] = ( ma[0]*ma[5] - ma[1]*ma[4] ) * detRecip; return det; } /* Include legacy macros here */ #include #ifdef __cplusplus extern "C" { #endif /* * normalize 3x1 and 4x1 vectors (i.e. scale them to unit length) */ /* For DLL export*/ ODE_API int dSafeNormalize3 (dVector3 a); ODE_API int dSafeNormalize4 (dVector4 a); ODE_API void dNormalize3 (dVector3 a); /* Potentially asserts on zero vec*/ ODE_API void dNormalize4 (dVector4 a); /* Potentially asserts on zero vec*/ /* * given a unit length "normal" vector n, generate vectors p and q vectors * that are an orthonormal basis for the plane space perpendicular to n. * i.e. this makes p,q such that n,p,q are all perpendicular to each other. * q will equal n x p. if n is not unit length then p will be unit length but * q wont be. */ ODE_API void dPlaneSpace (const dVector3 n, dVector3 p, dVector3 q); /* Makes sure the matrix is a proper rotation, returns a boolean status */ ODE_API int dOrthogonalizeR(dMatrix3 m); #ifdef __cplusplus } #endif #endif ode-0.16/include/ode/threading.h0000664000175200017520000004167013403272463013462 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * Threading support header file. * * Copyright (C) 2011-2012 Oleh Derevenko. All rights reserved. * * e-mail: odar@eleks.com (change all "a" to "e") * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* * ODE threading support interfaces */ #ifndef _ODE_THREADING_H_ #define _ODE_THREADING_H_ #include // Include since time_t is used and it is not available by default in some OSes #include #ifdef __cplusplus extern "C" { #endif struct dxThreadingImplementation; typedef struct dxThreadingImplementation *dThreadingImplementationID; typedef unsigned dmutexindex_t; struct dxMutexGroup; typedef struct dxMutexGroup *dMutexGroupID; #define dTHREADING_THREAD_COUNT_UNLIMITED 0U /** * @brief Allocates a group of muteces. * * The Mutex allocated do not need to support recursive locking. * * The Mutex names are provided to aid in debugging and thread state tracking. * * @param impl Threading implementation ID * @param Mutex_count Number of Mutex to create * @Mutex_names_ptr Pointer to optional Mutex names array to be associated with individual Mutex * @returns MutexGroup ID or NULL if error occurred. * * @ingroup threading * @see dMutexGroupFreeFunction * @see dMutexGroupMutexLockFunction * @see dMutexGroupMutexUnlockFunction */ typedef dMutexGroupID dMutexGroupAllocFunction (dThreadingImplementationID impl, dmutexindex_t Mutex_count, const char *const *Mutex_names_ptr/*=NULL*/); /** * @brief Deletes a group of muteces. * * @param impl Threading implementation ID * @param mutex_group Mutex group to deallocate * * @ingroup threading * @see dMutexGroupAllocFunction * @see dMutexGroupMutexLockFunction * @see dMutexGroupMutexUnlockFunction */ typedef void dMutexGroupFreeFunction (dThreadingImplementationID impl, dMutexGroupID mutex_group); /** * @brief Locks a mutex in a group of muteces. * * The function is to block execution until requested mutex can be locked. * * Note: Mutex provided may not support recursive locking. Calling this function * while mutex is already locked by current thread will result in unpredictable behavior. * * @param impl Threading implementation ID * @param mutex_group Mutex group to use for locking * @param mutex_index The index of mutex to be locked (0..Mutex_count - 1) * * @ingroup threading * @see dMutexGroupAllocFunction * @see dMutexGroupFreeFunction * @see dMutexGroupMutexUnlockFunction */ typedef void dMutexGroupMutexLockFunction (dThreadingImplementationID impl, dMutexGroupID mutex_group, dmutexindex_t mutex_index); /** * @brief Attempts to lock a mutex in a group of muteces. * * The function is to lock the requested mutex if it is unoccupied or * immediately return failure if mutex is already locked by other thread. * * Note: Mutex provided may not support recursive locking. Calling this function * while mutex is already locked by current thread will result in unpredictable behavior. * * @param impl Threading implementation ID * @param mutex_group Mutex group to use for locking * @param mutex_index The index of mutex to be locked (0..Mutex_count - 1) * @returns 1 for success (mutex is locked) and 0 for failure (mutex is not locked) * * @ingroup threading * @see dMutexGroupAllocFunction * @see dMutexGroupFreeFunction * @see dMutexGroupMutexLockFunction * @see dMutexGroupMutexUnlockFunction */ /* typedef int dMutexGroupMutexTryLockFunction (dThreadingImplementationID impl, dMutexGroupID mutex_group, dmutexindex_t mutex_index);*/ /** * @brief Unlocks a mutex in a group of muteces. * * The function is to unlock the given mutex provided it had been locked before. * * @param impl Threading implementation ID * @param mutex_group Mutex group to use for unlocking * @param mutex_index The index of mutex to be unlocked (0..Mutex_count - 1) * * @ingroup threading * @see dMutexGroupAllocFunction * @see dMutexGroupFreeFunction * @see dMutexGroupMutexLockFunction */ typedef void dMutexGroupMutexUnlockFunction (dThreadingImplementationID impl, dMutexGroupID mutex_group, dmutexindex_t mutex_index); struct dxCallReleasee; typedef struct dxCallReleasee *dCallReleaseeID; struct dxCallWait; typedef struct dxCallWait *dCallWaitID; typedef dsizeint ddependencycount_t; typedef ddiffint ddependencychange_t; typedef dsizeint dcallindex_t; typedef int dThreadedCallFunction(void *call_context, dcallindex_t instance_index, dCallReleaseeID this_releasee); typedef struct dxThreadedWaitTime { time_t wait_sec; unsigned long wait_nsec; } dThreadedWaitTime; /** * @brief Allocates a Wait ID that can be used to wait for a call. * * @param impl Threading implementation ID * @returns Wait ID or NULL if error occurred * * @ingroup threading * @see dThreadedCallWaitResetFunction * @see dThreadedCallWaitFreeFunction * @see dThreadedCallPostFunction * @see dThreadedCallWaitFunction */ typedef dCallWaitID dThreadedCallWaitAllocFunction(dThreadingImplementationID impl); /** * @brief Resets a Wait ID so that it could be used to wait for another call. * * @param impl Threading implementation ID * @param call_wait Wait ID to reset * * @ingroup threading * @see dThreadedCallWaitAllocFunction * @see dThreadedCallWaitFreeFunction * @see dThreadedCallPostFunction * @see dThreadedCallWaitFunction */ typedef void dThreadedCallWaitResetFunction(dThreadingImplementationID impl, dCallWaitID call_wait); /** * @brief Frees a Wait ID. * * @param impl Threading implementation ID * @param call_wait Wait ID to delete * * @ingroup threading * @see dThreadedCallWaitAllocFunction * @see dThreadedCallPostFunction * @see dThreadedCallWaitFunction */ typedef void dThreadedCallWaitFreeFunction(dThreadingImplementationID impl, dCallWaitID call_wait); /** * @brief Post a function to be called in another thread. * * A call is scheduled to be executed asynchronously. * * A @a out_summary_fault variable can be provided for call to accumulate any * possible faults from its execution and execution of any possible sub-calls. * This variable gets result that @a call_func returns. Also, if dependent calls * are executed after the call already exits, the variable is also going to be * updated with results of all those calls before control is released to master. * * @a out_post_releasee parameter receives a value of @c dCallReleaseeID that can * later be used for @a dependent_releasee while scheduling sub-calls to make * current call depend on them. The value is only returned if @a dependencies_count * is not zero (i.e. if any dependencies are expected at all). The call is not going * to start until all its dependencies complete. * * In case if number of dependencies is unknown in advance 1 can be passed on call * scheduling. Then @c dThreadedCallDependenciesCountAlterFunction can be used to * add one more extra dependencies before scheduling each subcall. And then, after * all sub-calls had been scheduled, @c dThreadedCallDependenciesCountAlterFunction * can be used again to subtract initial extra dependency from total number. * Adding one dependency in advance is necessary to obtain releasee ID and to make * sure the call will not start and will not terminate before all sub-calls are scheduled. * * Extra dependencies can also be added from the call itself after it has already * been started (with parameter received in @c dThreadedCallFunction). * In that case those dependencies will start immediately or after call returns * but the call's master will not be released/notified until all additional * dependencies complete. This can be used to schedule sub-calls from a call and * then pass own job to another sub-call dependent on those initial sub-calls. * * By using @ call_wait it is possible to assign a Wait ID that can later * be passed into @c dThreadedCallWaitFunction to wait for call completion. * * If @a call_name is available (and it should!) the string must remain valid until * after call completion. In most cases this should be a static string literal. * * Since the function is an analogue of normal method call it is not supposed to fail. * Any complications with resource allocation on call scheduling should be * anticipated, avoided and worked around by implementation. * * @param impl Threading implementation ID * @param out_summary_fault Optional pointer to variable to be set to 1 if function * call (or any sub-call) fails internally, or 0 if all calls return success * @param out_post_releasee Optional pointer to variable to receive releasee ID * associated with the call * @param dependencies_count Number of dependencies that are going to reference * this call as dependent releasee * @param dependent_releasee Optional releasee ID to reference with this call * @param call_wait Optional Wait ID that can later be used to wait for the call * @param call_func Pointer to function to be called * @param call_context Context parameter to be passed into the call * @param instance_index Index parameter to be passed into the call * @param call_name Optional name to be associated with the call (for debugging and state tracking) * * @ingroup threading * @see dThreadedCallWaitFunction * @see dThreadedCallDependenciesCountAlterFunction * @see dThreadingImplResourcesForCallsPreallocateFunction */ typedef void dThreadedCallPostFunction(dThreadingImplementationID impl, int *out_summary_fault/*=NULL*/, dCallReleaseeID *out_post_releasee/*=NULL*/, ddependencycount_t dependencies_count, dCallReleaseeID dependent_releasee/*=NULL*/, dCallWaitID call_wait/*=NULL*/, dThreadedCallFunction *call_func, void *call_context, dcallindex_t instance_index, const char *call_name/*=NULL*/); /** * @brief Add or remove extra dependencies from call that has been scheduled * or is in process of execution. * * Extra dependencies can be added to a call if exact number of sub-calls is * not known in advance at the moment the call is scheduled. Also, some dependencies * can be removed if sub-calls were planned but then dropped. * * In case if total dependency count of a call reaches zero by result of invoking * this function, the call is free to start executing immediately. * * After the call execution had been started, any additional dependencies can only * be added from the call function itself! * * @param impl Threading implementation ID * @param target_releasee ID of releasee to apply dependencies count change to * @param dependencies_count_change Number of dependencies to add or remove * * @ingroup threading * @see dThreadedCallPostFunction */ typedef void dThreadedCallDependenciesCountAlterFunction(dThreadingImplementationID impl, dCallReleaseeID target_releasee, ddependencychange_t dependencies_count_change); /** * @brief Wait for a posted call to complete. * * Function blocks until a call identified by @a call_wait completes or * timeout elapses. * * IT IS ILLEGAL TO INVOKE THIS FUNCTION FROM WITHIN A THREADED CALL! * This is because doing so will block a physical thread and will require * increasing worker thread count to avoid starvation. Use call dependencies * if it is necessary make sure sub-calls have been completed instead! * * If @a timeout_time_ptr is NULL, the function waits without time limit. If @a timeout_time_ptr * points to zero value, the function only checks status and does not block. * * If @a wait_name is available (and it should!) the string must remain valid for * the duration of wait. In most cases this should be a static string literal. * * Function is not expected to return failures caused by system call faults as * those are hardly ever possible to be handled in this case anyway. In event of * system call fault the function is supposed to terminate application. * * @param impl Threading implementation ID * @param out_wait_status Optional pointer to variable to receive 1 if waiting succeeded * or 0 in case of timeout * @param call_wait Wait ID that had been passed to scheduling a call that needs to be waited for * @param timeout_time_ptr Optional pointer to time specification the wait must not * last longer than (pass NULL for infinite timeout) * @param wait_name Optional name to be associated with the wait (for debugging and state tracking) * * @ingroup threading * @see dThreadedCallPostFunction */ typedef void dThreadedCallWaitFunction(dThreadingImplementationID impl, int *out_wait_status/*=NULL*/, dCallWaitID call_wait, const dThreadedWaitTime *timeout_time_ptr/*=NULL*/, const char *wait_name/*=NULL*/); /** * @brief Retrieve number of active threads that serve the implementation. * * @param impl Threading implementation ID * @returns Number of active threads * * @ingroup threading */ typedef unsigned dThreadingImplThreadCountRetrieveFunction(dThreadingImplementationID impl); /** * @brief Preallocate resources to handle posted calls. * * The function is intended to make sure enough resources is preallocated for the * implementation to be able to handle posted calls. Then @c max_simultaneous_calls_estimate * is an estimate of how many posted calls can potentially be active or scheduled * at the same time. The value is usually derived from the way the calls are posted * in library code and dependencies between them. * * @warning While working on an implementation be prepared that the estimate provided * yet rarely but theoretically can be exceeded due to unpredictability of thread execution. * * This function is normally going to be invoked by library each time it is entered * from outside to do the job but before any threaded calls are going to be posted. * * @param impl Threading implementation ID * @param max_simultaneous_calls_estimate An estimated number of calls that can be posted simultaneously * @returns 1 or 0 to indicate success or failure * * @ingroup threading * @see dThreadedCallPostFunction */ typedef int dThreadingImplResourcesForCallsPreallocateFunction(dThreadingImplementationID impl, ddependencycount_t max_simultaneous_calls_estimate); /** * @brief An interface structure with function pointers to be provided by threading implementation. */ typedef struct dxThreadingFunctionsInfo { unsigned struct_size; dMutexGroupAllocFunction *alloc_mutex_group; dMutexGroupFreeFunction *free_mutex_group; dMutexGroupMutexLockFunction *lock_group_mutex; dMutexGroupMutexUnlockFunction *unlock_group_mutex; dThreadedCallWaitAllocFunction *alloc_call_wait; dThreadedCallWaitResetFunction *reset_call_wait; dThreadedCallWaitFreeFunction *free_call_wait; dThreadedCallPostFunction *post_call; dThreadedCallDependenciesCountAlterFunction *alter_call_dependencies_count; dThreadedCallWaitFunction *wait_call; dThreadingImplThreadCountRetrieveFunction *retrieve_thread_count; dThreadingImplResourcesForCallsPreallocateFunction *preallocate_resources_for_calls; /* * Beware of Jon Watte's anger if you dare to uncomment this! * May cryptic text below be you a warning! * Стародавні легенди розказують, що кожного ÑміливцÑ, хто наважитьÑÑ Ð¿Ð¾Ñ€ÑƒÑˆÐ¸Ñ‚Ð¸ табу * Ñ– відкрити заборонений код, Ñпіткає Ñтрашне проклÑÑ‚Ñ‚Ñ Ñ– він відразу почне робити * одні лиш помилки. * * dMutexGroupMutexTryLockFunction *trylock_group_mutex; */ } dThreadingFunctionsInfo; #ifdef __cplusplus } #endif #endif /* #ifndef _ODE_THREADING_H_ */ ode-0.16/include/ode/Makefile.am0000664000175200017520000000117213403272463013371 00000000000000libode_la_includedir = $(includedir)/ode libode_la_include_HEADERS = \ collision.h \ collision_space.h \ collision_trimesh.h \ common.h \ compatibility.h \ contact.h \ cooperative.h \ error.h \ export-dif.h \ mass.h \ matrix.h matrix_coop.h \ memory.h \ misc.h \ objects.h \ ode.h \ odeconfig.h \ odecpp.h \ odecpp_collision.h \ odeinit.h \ odemath.h \ odemath_legacy.h \ rotation.h \ threading.h \ threading_impl.h \ timer.h EXTRA_DIST = README precision.h.in version.h.in dist_libode_la_include_HEADERS = precision.h version.h ode-0.16/include/ode/odecpp.h0000664000175200017520000014576013403272463012774 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* C++ interface for non-collision stuff */ #ifndef _ODE_ODECPP_H_ #define _ODE_ODECPP_H_ #ifdef __cplusplus //namespace ode { class dWorldSimpleIDContainer { protected: dWorldID _id; dWorldSimpleIDContainer(): _id(0) {} ~dWorldSimpleIDContainer() { destroy(); } void destroy() { if (_id) { dWorldDestroy(_id); _id = 0; } } }; class dWorldDynamicIDContainer: public dWorldSimpleIDContainer { protected: virtual ~dWorldDynamicIDContainer() {} }; template class dWorldTemplate: public dWorldTemplateBase { // intentionally undefined, don't use these dWorldTemplate (const dWorldTemplate &); void operator= (const dWorldTemplate &); protected: dWorldID get_id() const { return dWorldTemplateBase::_id; } void set_id(dWorldID value) { dWorldTemplateBase::_id = value; } public: dWorldTemplate() { set_id(dWorldCreate()); } dWorldID id() const { return get_id(); } operator dWorldID() const { return get_id(); } void setGravity (dReal x, dReal y, dReal z) { dWorldSetGravity (get_id(), x, y, z); } void setGravity (const dVector3 g) { setGravity (g[0], g[1], g[2]); } void getGravity (dVector3 g) const { dWorldGetGravity (get_id(), g); } void setERP (dReal erp) { dWorldSetERP(get_id(), erp); } dReal getERP() const { return dWorldGetERP(get_id()); } void setCFM (dReal cfm) { dWorldSetCFM(get_id(), cfm); } dReal getCFM() const { return dWorldGetCFM(get_id()); } void step (dReal stepsize) { dWorldStep (get_id(), stepsize); } void quickStep(dReal stepsize) { dWorldQuickStep (get_id(), stepsize); } void setQuickStepNumIterations(int num) { dWorldSetQuickStepNumIterations (get_id(), num); } int getQuickStepNumIterations() const { return dWorldGetQuickStepNumIterations (get_id()); } void setQuickStepW(dReal over_relaxation) { dWorldSetQuickStepW (get_id(), over_relaxation); } dReal getQuickStepW() const { return dWorldGetQuickStepW (get_id()); } void setAutoDisableLinearThreshold (dReal threshold) { dWorldSetAutoDisableLinearThreshold (get_id(), threshold); } dReal getAutoDisableLinearThreshold() const { return dWorldGetAutoDisableLinearThreshold (get_id()); } void setAutoDisableAngularThreshold (dReal threshold) { dWorldSetAutoDisableAngularThreshold (get_id(), threshold); } dReal getAutoDisableAngularThreshold() const { return dWorldGetAutoDisableAngularThreshold (get_id()); } void setAutoDisableSteps (int steps) { dWorldSetAutoDisableSteps (get_id(), steps); } int getAutoDisableSteps() const { return dWorldGetAutoDisableSteps (get_id()); } void setAutoDisableTime (dReal time) { dWorldSetAutoDisableTime (get_id(), time); } dReal getAutoDisableTime() const { return dWorldGetAutoDisableTime (get_id()); } void setAutoDisableFlag (int do_auto_disable) { dWorldSetAutoDisableFlag (get_id(), do_auto_disable); } int getAutoDisableFlag() const { return dWorldGetAutoDisableFlag (get_id()); } dReal getLinearDampingThreshold() const { return dWorldGetLinearDampingThreshold(get_id()); } void setLinearDampingThreshold(dReal threshold) { dWorldSetLinearDampingThreshold(get_id(), threshold); } dReal getAngularDampingThreshold() const { return dWorldGetAngularDampingThreshold(get_id()); } void setAngularDampingThreshold(dReal threshold) { dWorldSetAngularDampingThreshold(get_id(), threshold); } dReal getLinearDamping() const { return dWorldGetLinearDamping(get_id()); } void setLinearDamping(dReal scale) { dWorldSetLinearDamping(get_id(), scale); } dReal getAngularDamping() const { return dWorldGetAngularDamping(get_id()); } void setAngularDamping(dReal scale) { dWorldSetAngularDamping(get_id(), scale); } void setDamping(dReal linear_scale, dReal angular_scale) { dWorldSetDamping(get_id(), linear_scale, angular_scale); } dReal getMaxAngularSpeed() const { return dWorldGetMaxAngularSpeed(get_id()); } void setMaxAngularSpeed(dReal max_speed) { dWorldSetMaxAngularSpeed(get_id(), max_speed); } void setContactSurfaceLayer(dReal depth) { dWorldSetContactSurfaceLayer (get_id(), depth); } dReal getContactSurfaceLayer() const { return dWorldGetContactSurfaceLayer (get_id()); } void impulseToForce (dReal stepsize, dReal ix, dReal iy, dReal iz, dVector3 force) { dWorldImpulseToForce (get_id(), stepsize, ix, iy, iz, force); } }; class dBodySimpleIDContainer { protected: dBodyID _id; dBodySimpleIDContainer(): _id(0) {} ~dBodySimpleIDContainer() { destroy(); } void destroy() { if (_id) { dBodyDestroy(_id); _id = 0; } } }; class dBodyDynamicIDContainer: public dBodySimpleIDContainer { protected: virtual ~dBodyDynamicIDContainer() {} }; template class dBodyTemplate: public dBodyTemplateBase { // intentionally undefined, don't use these dBodyTemplate (const dBodyTemplate &); void operator= (const dBodyTemplate &); protected: dBodyID get_id() const { return dBodyTemplateBase::_id; } void set_id(dBodyID value) { dBodyTemplateBase::_id = value; } void destroy() { dBodyTemplateBase::destroy(); } public: dBodyTemplate() { } dBodyTemplate (dWorldID world) { set_id(dBodyCreate(world)); } dBodyTemplate (dWorldTemplate& world) { set_id(dBodyCreate(world.id())); } void create (dWorldID world) { destroy(); set_id(dBodyCreate(world)); } void create (dWorldTemplate& world) { create(world.id()); } dBodyID id() const { return get_id(); } operator dBodyID() const { return get_id(); } void setData (void *data) { dBodySetData (get_id(), data); } void *getData() const { return dBodyGetData (get_id()); } void setPosition (dReal x, dReal y, dReal z) { dBodySetPosition (get_id(), x, y, z); } void setPosition (const dVector3 p) { setPosition(p[0], p[1], p[2]); } void setRotation (const dMatrix3 R) { dBodySetRotation (get_id(), R); } void setQuaternion (const dQuaternion q) { dBodySetQuaternion (get_id(), q); } void setLinearVel (dReal x, dReal y, dReal z) { dBodySetLinearVel (get_id(), x, y, z); } void setLinearVel (const dVector3 v) { setLinearVel(v[0], v[1], v[2]); } void setAngularVel (dReal x, dReal y, dReal z) { dBodySetAngularVel (get_id(), x, y, z); } void setAngularVel (const dVector3 v) { setAngularVel (v[0], v[1], v[2]); } const dReal * getPosition() const { return dBodyGetPosition (get_id()); } const dReal * getRotation() const { return dBodyGetRotation (get_id()); } const dReal * getQuaternion() const { return dBodyGetQuaternion (get_id()); } const dReal * getLinearVel() const { return dBodyGetLinearVel (get_id()); } const dReal * getAngularVel() const { return dBodyGetAngularVel (get_id()); } void setMass (const dMass *mass) { dBodySetMass (get_id(), mass); } void setMass (const dMass &mass) { setMass (&mass); } dMass getMass () const { dMass mass; dBodyGetMass (get_id(), &mass); return mass; } void addForce (dReal fx, dReal fy, dReal fz) { dBodyAddForce (get_id(), fx, fy, fz); } void addForce (const dVector3 f) { addForce (f[0], f[1], f[2]); } void addTorque (dReal fx, dReal fy, dReal fz) { dBodyAddTorque (get_id(), fx, fy, fz); } void addTorque (const dVector3 t) { addTorque(t[0], t[1], t[2]); } void addRelForce (dReal fx, dReal fy, dReal fz) { dBodyAddRelForce (get_id(), fx, fy, fz); } void addRelForce (const dVector3 f) { addRelForce (f[0], f[1], f[2]); } void addRelTorque (dReal fx, dReal fy, dReal fz) { dBodyAddRelTorque (get_id(), fx, fy, fz); } void addRelTorque (const dVector3 t) { addRelTorque (t[0], t[1], t[2]); } void addForceAtPos (dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz) { dBodyAddForceAtPos (get_id(), fx, fy, fz, px, py, pz); } void addForceAtPos (const dVector3 f, const dVector3 p) { addForceAtPos (f[0], f[1], f[2], p[0], p[1], p[2]); } void addForceAtRelPos (dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz) { dBodyAddForceAtRelPos (get_id(), fx, fy, fz, px, py, pz); } void addForceAtRelPos (const dVector3 f, const dVector3 p) { addForceAtRelPos (f[0], f[1], f[2], p[0], p[1], p[2]); } void addRelForceAtPos (dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz) { dBodyAddRelForceAtPos (get_id(), fx, fy, fz, px, py, pz); } void addRelForceAtPos (const dVector3 f, const dVector3 p) { addRelForceAtPos (f[0], f[1], f[2], p[0], p[1], p[2]); } void addRelForceAtRelPos (dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz) { dBodyAddRelForceAtRelPos (get_id(), fx, fy, fz, px, py, pz); } void addRelForceAtRelPos (const dVector3 f, const dVector3 p) { addRelForceAtRelPos (f[0], f[1], f[2], p[0], p[1], p[2]); } const dReal * getForce() const { return dBodyGetForce(get_id()); } const dReal * getTorque() const { return dBodyGetTorque(get_id()); } void setForce (dReal x, dReal y, dReal z) { dBodySetForce (get_id(), x, y, z); } void setForce (const dVector3 f) { setForce (f[0], f[1], f[2]); } void setTorque (dReal x, dReal y, dReal z) { dBodySetTorque (get_id(), x, y, z); } void setTorque (const dVector3 t) { setTorque (t[0], t[1], t[2]); } void setDynamic() { dBodySetDynamic (get_id()); } void setKinematic() { dBodySetKinematic (get_id()); } bool isKinematic() const { return dBodyIsKinematic (get_id()) != 0; } void enable() { dBodyEnable (get_id()); } void disable() { dBodyDisable (get_id()); } bool isEnabled() const { return dBodyIsEnabled (get_id()) != 0; } void getRelPointPos (dReal px, dReal py, dReal pz, dVector3 result) const { dBodyGetRelPointPos (get_id(), px, py, pz, result); } void getRelPointPos (const dVector3 p, dVector3 result) const { getRelPointPos (p[0], p[1], p[2], result); } void getRelPointVel (dReal px, dReal py, dReal pz, dVector3 result) const { dBodyGetRelPointVel (get_id(), px, py, pz, result); } void getRelPointVel (const dVector3 p, dVector3 result) const { getRelPointVel (p[0], p[1], p[2], result); } void getPointVel (dReal px, dReal py, dReal pz, dVector3 result) const { dBodyGetPointVel (get_id(), px, py, pz, result); } void getPointVel (const dVector3 p, dVector3 result) const { getPointVel (p[0], p[1], p[2], result); } void getPosRelPoint (dReal px, dReal py, dReal pz, dVector3 result) const { dBodyGetPosRelPoint (get_id(), px, py, pz, result); } void getPosRelPoint (const dVector3 p, dVector3 result) const { getPosRelPoint (p[0], p[1], p[2], result); } void vectorToWorld (dReal px, dReal py, dReal pz, dVector3 result) const { dBodyVectorToWorld (get_id(), px, py, pz, result); } void vectorToWorld (const dVector3 p, dVector3 result) const { vectorToWorld (p[0], p[1], p[2], result); } void vectorFromWorld (dReal px, dReal py, dReal pz, dVector3 result) const { dBodyVectorFromWorld (get_id(), px, py, pz, result); } void vectorFromWorld (const dVector3 p, dVector3 result) const { vectorFromWorld (p[0], p[1], p[2], result); } void setFiniteRotationMode (bool mode) { dBodySetFiniteRotationMode (get_id(), mode); } void setFiniteRotationAxis (dReal x, dReal y, dReal z) { dBodySetFiniteRotationAxis (get_id(), x, y, z); } void setFiniteRotationAxis (const dVector3 a) { setFiniteRotationAxis (a[0], a[1], a[2]); } bool getFiniteRotationMode() const { return dBodyGetFiniteRotationMode (get_id()) != 0; } void getFiniteRotationAxis (dVector3 result) const { dBodyGetFiniteRotationAxis (get_id(), result); } int getNumJoints() const { return dBodyGetNumJoints (get_id()); } dJointID getJoint (int index) const { return dBodyGetJoint (get_id(), index); } void setGravityMode (bool mode) { dBodySetGravityMode (get_id(), mode); } bool getGravityMode() const { return dBodyGetGravityMode (get_id()) != 0; } bool isConnectedTo (dBodyID body) const { return dAreConnected (get_id(), body) != 0; } void setAutoDisableLinearThreshold (dReal threshold) { dBodySetAutoDisableLinearThreshold (get_id(), threshold); } dReal getAutoDisableLinearThreshold() const { return dBodyGetAutoDisableLinearThreshold (get_id()); } void setAutoDisableAngularThreshold (dReal threshold) { dBodySetAutoDisableAngularThreshold (get_id(), threshold); } dReal getAutoDisableAngularThreshold() const { return dBodyGetAutoDisableAngularThreshold (get_id()); } void setAutoDisableSteps (int steps) { dBodySetAutoDisableSteps (get_id(), steps); } int getAutoDisableSteps() const { return dBodyGetAutoDisableSteps (get_id()); } void setAutoDisableTime (dReal time) { dBodySetAutoDisableTime (get_id(), time); } dReal getAutoDisableTime() const { return dBodyGetAutoDisableTime (get_id()); } void setAutoDisableFlag (bool do_auto_disable) { dBodySetAutoDisableFlag (get_id(), do_auto_disable); } bool getAutoDisableFlag() const { return dBodyGetAutoDisableFlag (get_id()) != 0; } dReal getLinearDamping() const { return dBodyGetLinearDamping(get_id()); } void setLinearDamping(dReal scale) { dBodySetLinearDamping(get_id(), scale); } dReal getAngularDamping() const { return dBodyGetAngularDamping(get_id()); } void setAngularDamping(dReal scale) { dBodySetAngularDamping(get_id(), scale); } void setDamping(dReal linear_scale, dReal angular_scale) { dBodySetDamping(get_id(), linear_scale, angular_scale); } dReal getLinearDampingThreshold() const { return dBodyGetLinearDampingThreshold(get_id()); } void setLinearDampingThreshold(dReal threshold) const { dBodySetLinearDampingThreshold(get_id(), threshold); } dReal getAngularDampingThreshold() const { return dBodyGetAngularDampingThreshold(get_id()); } void setAngularDampingThreshold(dReal threshold) { dBodySetAngularDampingThreshold(get_id(), threshold); } void setDampingDefaults() { dBodySetDampingDefaults(get_id()); } dReal getMaxAngularSpeed() const { return dBodyGetMaxAngularSpeed(get_id()); } void setMaxAngularSpeed(dReal max_speed) { dBodySetMaxAngularSpeed(get_id(), max_speed); } bool getGyroscopicMode() const { return dBodyGetGyroscopicMode(get_id()) != 0; } void setGyroscopicMode(bool mode) { dBodySetGyroscopicMode(get_id(), mode); } }; class dJointGroupSimpleIDContainer { protected: dJointGroupID _id; dJointGroupSimpleIDContainer(): _id(0) {} ~dJointGroupSimpleIDContainer() { destroy(); } void destroy() { if (_id) { dJointGroupDestroy(_id); _id = 0; } } }; class dJointGroupDynamicIDContainer: public dJointGroupSimpleIDContainer { protected: virtual ~dJointGroupDynamicIDContainer() {} }; template class dJointGroupTemplate: public dJointGroupTemplateBase { // intentionally undefined, don't use these dJointGroupTemplate (const dJointGroupTemplate &); void operator= (const dJointGroupTemplate &); protected: dJointGroupID get_id() const { return dJointGroupTemplateBase::_id; } void set_id(dJointGroupID value) { dJointGroupTemplateBase::_id = value; } void destroy() { dJointGroupTemplateBase::destroy(); } public: dJointGroupTemplate () { set_id(dJointGroupCreate(0)); } void create () { destroy(); set_id(dJointGroupCreate(0)); } dJointGroupID id() const { return get_id(); } operator dJointGroupID() const { return get_id(); } void empty() { dJointGroupEmpty (get_id()); } void clear() { empty(); } }; class dJointSimpleIDContainer { protected: dJointID _id; dJointSimpleIDContainer(): _id(0) {} ~dJointSimpleIDContainer() { destroy(); } void destroy() { if (_id) { dJointDestroy (_id); _id = 0; } } }; class dJointDynamicIDContainer: public dJointSimpleIDContainer { protected: virtual ~dJointDynamicIDContainer() {} }; template class dJointTemplate: public dJointTemplateBase { private: // intentionally undefined, don't use these dJointTemplate (const dJointTemplate &) ; void operator= (const dJointTemplate &); protected: dJointID get_id() const { return dJointTemplateBase::_id; } void set_id(dJointID value) { dJointTemplateBase::_id = value; } void destroy() { dJointTemplateBase::destroy(); } protected: dJointTemplate() // don't let user construct pure dJointTemplate objects { } public: dJointID id() const { return get_id(); } operator dJointID() const { return get_id(); } int getNumBodies() const { return dJointGetNumBodies(get_id()); } void attach (dBodyID body1, dBodyID body2) { dJointAttach (get_id(), body1, body2); } void attach (dBodyTemplate& body1, dBodyTemplate& body2) { attach(body1.id(), body2.id()); } void enable() { dJointEnable (get_id()); } void disable() { dJointDisable (get_id()); } bool isEnabled() const { return dJointIsEnabled (get_id()) != 0; } void setData (void *data) { dJointSetData (get_id(), data); } void *getData() const { return dJointGetData (get_id()); } dJointType getType() const { return dJointGetType (get_id()); } dBodyID getBody (int index) const { return dJointGetBody (get_id(), index); } void setFeedback(dJointFeedback *fb) { dJointSetFeedback(get_id(), fb); } dJointFeedback *getFeedback() const { return dJointGetFeedback(get_id()); } // If not implemented it will do nothing as describe in the doc virtual void setParam (int, dReal) {}; virtual dReal getParam (int) const { return 0; } }; template class dBallJointTemplate : public dJointTemplate { private: // intentionally undefined, don't use these dBallJointTemplate (const dBallJointTemplate &); void operator= (const dBallJointTemplate &); protected: typedef dJointTemplate dBaseTemplate; dJointID get_id() const { return dBaseTemplate::get_id(); } void set_id(dJointID value) { dBaseTemplate::set_id(value); } void destroy() { dBaseTemplate::destroy(); } public: dBallJointTemplate() { } dBallJointTemplate (dWorldID world, dJointGroupID group=0) { set_id(dJointCreateBall(world, group)); } dBallJointTemplate (dWorldTemplate& world, dJointGroupID group=0) { set_id(dJointCreateBall(world.id(), group)); } void create (dWorldID world, dJointGroupID group=0) { destroy(); set_id(dJointCreateBall(world, group)); } void create (dWorldTemplate& world, dJointGroupID group=0) { create(world.id(), group); } void setAnchor (dReal x, dReal y, dReal z) { dJointSetBallAnchor (get_id(), x, y, z); } void setAnchor (const dVector3 a) { setAnchor (a[0], a[1], a[2]); } void getAnchor (dVector3 result) const { dJointGetBallAnchor (get_id(), result); } void getAnchor2 (dVector3 result) const { dJointGetBallAnchor2 (get_id(), result); } virtual void setParam (int parameter, dReal value) { dJointSetBallParam (get_id(), parameter, value); } virtual dReal getParam (int parameter) const { return dJointGetBallParam (get_id(), parameter); } // TODO: expose params through methods } ; template class dHingeJointTemplate : public dJointTemplate { private: // intentionally undefined, don't use these dHingeJointTemplate (const dHingeJointTemplate &); void operator = (const dHingeJointTemplate &); protected: typedef dJointTemplate dBaseTemplate; dJointID get_id() const { return dBaseTemplate::get_id(); } void set_id(dJointID value) { dBaseTemplate::set_id(value); } void destroy() { dBaseTemplate::destroy(); } public: dHingeJointTemplate() { } dHingeJointTemplate (dWorldID world, dJointGroupID group=0) { set_id(dJointCreateHinge(world, group)); } dHingeJointTemplate (dWorldTemplate& world, dJointGroupID group=0) { set_id(dJointCreateHinge(world.id(), group)); } void create (dWorldID world, dJointGroupID group=0) { destroy(); set_id(dJointCreateHinge (world, group)); } void create (dWorldTemplate& world, dJointGroupID group=0) { create(world.id(), group); } void setAnchor (dReal x, dReal y, dReal z) { dJointSetHingeAnchor (get_id(), x, y, z); } void setAnchor (const dVector3 a) { setAnchor (a[0], a[1], a[2]); } void getAnchor (dVector3 result) const { dJointGetHingeAnchor (get_id(), result); } void getAnchor2 (dVector3 result) const { dJointGetHingeAnchor2 (get_id(), result); } void setAxis (dReal x, dReal y, dReal z) { dJointSetHingeAxis (get_id(), x, y, z); } void setAxis (const dVector3 a) { setAxis(a[0], a[1], a[2]); } void getAxis (dVector3 result) const { dJointGetHingeAxis (get_id(), result); } dReal getAngle() const { return dJointGetHingeAngle (get_id()); } dReal getAngleRate() const { return dJointGetHingeAngleRate (get_id()); } virtual void setParam (int parameter, dReal value) { dJointSetHingeParam (get_id(), parameter, value); } virtual dReal getParam (int parameter) const { return dJointGetHingeParam (get_id(), parameter); } // TODO: expose params through methods void addTorque (dReal torque) { dJointAddHingeTorque(get_id(), torque); } }; template class dSliderJointTemplate : public dJointTemplate { private: // intentionally undefined, don't use these dSliderJointTemplate (const dSliderJointTemplate &); void operator = (const dSliderJointTemplate &); protected: typedef dJointTemplate dBaseTemplate; dJointID get_id() const { return dBaseTemplate::get_id(); } void set_id(dJointID value) { dBaseTemplate::set_id(value); } void destroy() { dBaseTemplate::destroy(); } public: dSliderJointTemplate() { } dSliderJointTemplate (dWorldID world, dJointGroupID group=0) { set_id(dJointCreateSlider(world, group)); } dSliderJointTemplate (dWorldTemplate& world, dJointGroupID group=0) { set_id(dJointCreateSlider(world.id(), group)); } void create (dWorldID world, dJointGroupID group=0) { destroy(); set_id(dJointCreateSlider(world, group)); } void create (dWorldTemplate& world, dJointGroupID group=0) { create(world.id(), group); } void setAxis (dReal x, dReal y, dReal z) { dJointSetSliderAxis (get_id(), x, y, z); } void setAxis (const dVector3 a) { setAxis (a[0], a[1], a[2]); } void getAxis (dVector3 result) const { dJointGetSliderAxis (get_id(), result); } dReal getPosition() const { return dJointGetSliderPosition (get_id()); } dReal getPositionRate() const { return dJointGetSliderPositionRate (get_id()); } virtual void setParam (int parameter, dReal value) { dJointSetSliderParam (get_id(), parameter, value); } virtual dReal getParam (int parameter) const { return dJointGetSliderParam (get_id(), parameter); } // TODO: expose params through methods void addForce (dReal force) { dJointAddSliderForce(get_id(), force); } }; template class dUniversalJointTemplate : public dJointTemplate { private: // intentionally undefined, don't use these dUniversalJointTemplate (const dUniversalJointTemplate &); void operator = (const dUniversalJointTemplate &); protected: typedef dJointTemplate dBaseTemplate; dJointID get_id() const { return dBaseTemplate::get_id(); } void set_id(dJointID value) { dBaseTemplate::set_id(value); } void destroy() { dBaseTemplate::destroy(); } public: dUniversalJointTemplate() { } dUniversalJointTemplate (dWorldID world, dJointGroupID group=0) { set_id(dJointCreateUniversal(world, group)); } dUniversalJointTemplate (dWorldTemplate& world, dJointGroupID group=0) { set_id(dJointCreateUniversal(world.id(), group)); } void create (dWorldID world, dJointGroupID group=0) { destroy(); set_id(dJointCreateUniversal(world, group)); } void create (dWorldTemplate& world, dJointGroupID group=0) { create(world.id(), group); } void setAnchor (dReal x, dReal y, dReal z) { dJointSetUniversalAnchor (get_id(), x, y, z); } void setAnchor (const dVector3 a) { setAnchor(a[0], a[1], a[2]); } void setAxis1 (dReal x, dReal y, dReal z) { dJointSetUniversalAxis1 (get_id(), x, y, z); } void setAxis1 (const dVector3 a) { setAxis1 (a[0], a[1], a[2]); } void setAxis2 (dReal x, dReal y, dReal z) { dJointSetUniversalAxis2 (get_id(), x, y, z); } void setAxis2 (const dVector3 a) { setAxis2 (a[0], a[1], a[2]); } void getAnchor (dVector3 result) const { dJointGetUniversalAnchor (get_id(), result); } void getAnchor2 (dVector3 result) const { dJointGetUniversalAnchor2 (get_id(), result); } void getAxis1 (dVector3 result) const { dJointGetUniversalAxis1 (get_id(), result); } void getAxis2 (dVector3 result) const { dJointGetUniversalAxis2 (get_id(), result); } virtual void setParam (int parameter, dReal value) { dJointSetUniversalParam (get_id(), parameter, value); } virtual dReal getParam (int parameter) const { return dJointGetUniversalParam (get_id(), parameter); } // TODO: expose params through methods void getAngles(dReal *angle1, dReal *angle2) const { dJointGetUniversalAngles (get_id(), angle1, angle2); } dReal getAngle1() const { return dJointGetUniversalAngle1 (get_id()); } dReal getAngle1Rate() const { return dJointGetUniversalAngle1Rate (get_id()); } dReal getAngle2() const { return dJointGetUniversalAngle2 (get_id()); } dReal getAngle2Rate() const { return dJointGetUniversalAngle2Rate (get_id()); } void addTorques (dReal torque1, dReal torque2) { dJointAddUniversalTorques(get_id(), torque1, torque2); } }; template class dHinge2JointTemplate : public dJointTemplate { private: // intentionally undefined, don't use these dHinge2JointTemplate (const dHinge2JointTemplate &); void operator = (const dHinge2JointTemplate &); protected: typedef dJointTemplate dBaseTemplate; dJointID get_id() const { return dBaseTemplate::get_id(); } void set_id(dJointID value) { dBaseTemplate::set_id(value); } void destroy() { dBaseTemplate::destroy(); } public: dHinge2JointTemplate() { } dHinge2JointTemplate (dWorldID world, dJointGroupID group=0) { set_id(dJointCreateHinge2(world, group)); } dHinge2JointTemplate (dWorldTemplate& world, dJointGroupID group=0) { set_id(dJointCreateHinge2(world.id(), group)); } void create (dWorldID world, dJointGroupID group=0) { destroy(); set_id(dJointCreateHinge2(world, group)); } void create (dWorldTemplate& world, dJointGroupID group=0) { create(world.id(), group); } void setAnchor (dReal x, dReal y, dReal z) { dJointSetHinge2Anchor (get_id(), x, y, z); } void setAnchor (const dVector3 a) { setAnchor(a[0], a[1], a[2]); } void setAxes (const dReal *axis1/*=NULL*/, const dReal *axis2/*=NULL*/) { dJointSetHinge2Axes (get_id(), axis1, axis2); } ODE_API_DEPRECATED void setAxis1 (dReal x, dReal y, dReal z) { dVector3 a = { x, y, z }; dJointSetHinge2Axes (get_id(), a, NULL); } ODE_API_DEPRECATED void setAxis1 (const dVector3 a) { dJointSetHinge2Axes (get_id(), a, NULL); } ODE_API_DEPRECATED void setAxis2 (dReal x, dReal y, dReal z) { dVector3 a = { x, y, z }; dJointSetHinge2Axes (get_id(), NULL, a); } ODE_API_DEPRECATED void setAxis2 (const dVector3 a) { dJointSetHinge2Axes (get_id(), NULL, a); } void getAnchor (dVector3 result) const { dJointGetHinge2Anchor (get_id(), result); } void getAnchor2 (dVector3 result) const { dJointGetHinge2Anchor2 (get_id(), result); } void getAxis1 (dVector3 result) const { dJointGetHinge2Axis1 (get_id(), result); } void getAxis2 (dVector3 result) const { dJointGetHinge2Axis2 (get_id(), result); } dReal getAngle1() const { return dJointGetHinge2Angle1 (get_id()); } dReal getAngle1Rate() const { return dJointGetHinge2Angle1Rate (get_id()); } dReal getAngle2Rate() const { return dJointGetHinge2Angle2Rate (get_id()); } virtual void setParam (int parameter, dReal value) { dJointSetHinge2Param (get_id(), parameter, value); } virtual dReal getParam (int parameter) const { return dJointGetHinge2Param (get_id(), parameter); } // TODO: expose params through methods void addTorques(dReal torque1, dReal torque2) { dJointAddHinge2Torques(get_id(), torque1, torque2); } }; template class dPRJointTemplate : public dJointTemplate { private: // intentionally undefined, don't use these dPRJointTemplate (const dPRJointTemplate &); void operator = (const dPRJointTemplate &); protected: typedef dJointTemplate dBaseTemplate; dJointID get_id() const { return dBaseTemplate::get_id(); } void set_id(dJointID value) { dBaseTemplate::set_id(value); } void destroy() { dBaseTemplate::destroy(); } public: dPRJointTemplate() { } dPRJointTemplate (dWorldID world, dJointGroupID group=0) { set_id(dJointCreatePR(world, group)); } dPRJointTemplate (dWorldTemplate& world, dJointGroupID group=0) { set_id(dJointCreatePR(world.id(), group)); } void create (dWorldID world, dJointGroupID group=0) { destroy(); set_id(dJointCreatePR(world, group)); } void create (dWorldTemplate& world, dJointGroupID group=0) { create(world.id(), group); } void setAnchor (dReal x, dReal y, dReal z) { dJointSetPRAnchor (get_id(), x, y, z); } void setAnchor (const dVector3 a) { setAnchor (a[0], a[1], a[2]); } void setAxis1 (dReal x, dReal y, dReal z) { dJointSetPRAxis1 (get_id(), x, y, z); } void setAxis1 (const dVector3 a) { setAxis1(a[0], a[1], a[2]); } void setAxis2 (dReal x, dReal y, dReal z) { dJointSetPRAxis2 (get_id(), x, y, z); } void setAxis2 (const dVector3 a) { setAxis2(a[0], a[1], a[2]); } void getAnchor (dVector3 result) const { dJointGetPRAnchor (get_id(), result); } void getAxis1 (dVector3 result) const { dJointGetPRAxis1 (get_id(), result); } void getAxis2 (dVector3 result) const { dJointGetPRAxis2 (get_id(), result); } dReal getPosition() const { return dJointGetPRPosition (get_id()); } dReal getPositionRate() const { return dJointGetPRPositionRate (get_id()); } dReal getAngle() const { return dJointGetPRAngle (get_id()); } dReal getAngleRate() const { return dJointGetPRAngleRate (get_id()); } virtual void setParam (int parameter, dReal value) { dJointSetPRParam (get_id(), parameter, value); } virtual dReal getParam (int parameter) const { return dJointGetPRParam (get_id(), parameter); } }; template class dPUJointTemplate : public dJointTemplate { private: // intentionally undefined, don't use these dPUJointTemplate (const dPUJointTemplate &); void operator = (const dPUJointTemplate &); protected: typedef dJointTemplate dBaseTemplate; dJointID get_id() const { return dBaseTemplate::get_id(); } void set_id(dJointID value) { dBaseTemplate::set_id(value); } void destroy() { dBaseTemplate::destroy(); } public: dPUJointTemplate() { } dPUJointTemplate (dWorldID world, dJointGroupID group=0) { set_id(dJointCreatePU(world, group)); } dPUJointTemplate (dWorldTemplate& world, dJointGroupID group=0) { set_id(dJointCreatePU(world.id(), group)); } void create (dWorldID world, dJointGroupID group=0) { destroy(); set_id(dJointCreatePU(world, group)); } void create (dWorldTemplate& world, dJointGroupID group=0) { create(world.id(), group); } void setAnchor (dReal x, dReal y, dReal z) { dJointSetPUAnchor (get_id(), x, y, z); } void setAnchor (const dVector3 a) { setAnchor (a[0], a[1], a[2]); } void setAxis1 (dReal x, dReal y, dReal z) { dJointSetPUAxis1 (get_id(), x, y, z); } void setAxis1 (const dVector3 a) { setAxis1(a[0], a[1], a[2]); } void setAxis2 (dReal x, dReal y, dReal z) { dJointSetPUAxis2 (get_id(), x, y, z); } void setAxis3 (dReal x, dReal y, dReal z) { dJointSetPUAxis3 (get_id(), x, y, z); } void setAxis3 (const dVector3 a) { setAxis3(a[0], a[1], a[2]); } void setAxisP (dReal x, dReal y, dReal z) { dJointSetPUAxis3 (get_id(), x, y, z); } void setAxisP (const dVector3 a) { setAxisP(a[0], a[1], a[2]); } virtual void getAnchor (dVector3 result) const { dJointGetPUAnchor (get_id(), result); } void getAxis1 (dVector3 result) const { dJointGetPUAxis1 (get_id(), result); } void getAxis2 (dVector3 result) const { dJointGetPUAxis2 (get_id(), result); } void getAxis3 (dVector3 result) const { dJointGetPUAxis3 (get_id(), result); } void getAxisP (dVector3 result) const { dJointGetPUAxis3 (get_id(), result); } dReal getAngle1() const { return dJointGetPUAngle1 (get_id()); } dReal getAngle1Rate() const { return dJointGetPUAngle1Rate (get_id()); } dReal getAngle2() const { return dJointGetPUAngle2 (get_id()); } dReal getAngle2Rate() const { return dJointGetPUAngle2Rate (get_id()); } dReal getPosition() const { return dJointGetPUPosition (get_id()); } dReal getPositionRate() const { return dJointGetPUPositionRate (get_id()); } virtual void setParam (int parameter, dReal value) { dJointSetPUParam (get_id(), parameter, value); } virtual dReal getParam (int parameter) const { return dJointGetPUParam (get_id(), parameter); } // TODO: expose params through methods }; template class dPistonJointTemplate : public dJointTemplate { private: // intentionally undefined, don't use these dPistonJointTemplate (const dPistonJointTemplate &); void operator = (const dPistonJointTemplate &); protected: typedef dJointTemplate dBaseTemplate; dJointID get_id() const { return dBaseTemplate::get_id(); } void set_id(dJointID value) { dBaseTemplate::set_id(value); } void destroy() { dBaseTemplate::destroy(); } public: dPistonJointTemplate() { } dPistonJointTemplate (dWorldID world, dJointGroupID group=0) { set_id(dJointCreatePiston(world, group)); } dPistonJointTemplate (dWorldTemplate& world, dJointGroupID group=0) { set_id(dJointCreatePiston(world, group)); } void create (dWorldID world, dJointGroupID group=0) { destroy(); set_id(dJointCreatePiston(world, group)); } void create (dWorldTemplate& world, dJointGroupID group=0) { create(world.id(), group); } void setAnchor (dReal x, dReal y, dReal z) { dJointSetPistonAnchor (get_id(), x, y, z); } void setAnchor (const dVector3 a) { setAnchor (a[0], a[1], a[2]); } void getAnchor (dVector3 result) const { dJointGetPistonAnchor (get_id(), result); } void getAnchor2 (dVector3 result) const { dJointGetPistonAnchor2 (get_id(), result); } void setAxis (dReal x, dReal y, dReal z) { dJointSetPistonAxis (get_id(), x, y, z); } void setAxis (const dVector3 a) { setAxis(a[0], a[1], a[2]); } void getAxis (dVector3 result) const { dJointGetPistonAxis (get_id(), result); } dReal getPosition() const { return dJointGetPistonPosition (get_id()); } dReal getPositionRate() const { return dJointGetPistonPositionRate (get_id()); } virtual void setParam (int parameter, dReal value) { dJointSetPistonParam (get_id(), parameter, value); } virtual dReal getParam (int parameter) const { return dJointGetPistonParam (get_id(), parameter); } // TODO: expose params through methods void addForce (dReal force) { dJointAddPistonForce (get_id(), force); } }; template class dFixedJointTemplate : public dJointTemplate { private: // intentionally undefined, don't use these dFixedJointTemplate (const dFixedJointTemplate &); void operator = (const dFixedJointTemplate &); protected: typedef dJointTemplate dBaseTemplate; dJointID get_id() const { return dBaseTemplate::get_id(); } void set_id(dJointID value) { dBaseTemplate::set_id(value); } void destroy() { dBaseTemplate::destroy(); } public: dFixedJointTemplate() { } dFixedJointTemplate (dWorldID world, dJointGroupID group=0) { set_id(dJointCreateFixed(world, group)); } dFixedJointTemplate (dWorldTemplate& world, dJointGroupID group=0) { set_id(dJointCreateFixed(world, group)); } void create (dWorldID world, dJointGroupID group=0) { destroy(); set_id(dJointCreateFixed(world, group)); } void create (dWorldTemplate& world, dJointGroupID group=0) { create(world.id(), group); } void set() { dJointSetFixed (get_id()); } virtual void setParam (int parameter, dReal value) { dJointSetFixedParam (get_id(), parameter, value); } virtual dReal getParam (int parameter) const { return dJointGetFixedParam (get_id(), parameter); } // TODO: expose params through methods }; template class dContactJointTemplate : public dJointTemplate { private: // intentionally undefined, don't use these dContactJointTemplate (const dContactJointTemplate &); void operator = (const dContactJointTemplate &); protected: typedef dJointTemplate dBaseTemplate; dJointID get_id() const { return dBaseTemplate::get_id(); } void set_id(dJointID value) { dBaseTemplate::set_id(value); } void destroy() { dBaseTemplate::destroy(); } public: dContactJointTemplate() { } dContactJointTemplate (dWorldID world, dJointGroupID group, dContact *contact) { set_id(dJointCreateContact(world, group, contact)); } dContactJointTemplate (dWorldTemplate& world, dJointGroupID group, dContact *contact) { set_id(dJointCreateContact(world.id(), group, contact)); } void create (dWorldID world, dJointGroupID group, dContact *contact) { destroy(); set_id(dJointCreateContact(world, group, contact)); } void create (dWorldTemplate& world, dJointGroupID group, dContact *contact) { create(world.id(), group, contact); } }; template class dNullJointTemplate : public dJointTemplate { private: // intentionally undefined, don't use these dNullJointTemplate (const dNullJointTemplate &); void operator = (const dNullJointTemplate &); protected: typedef dJointTemplate dBaseTemplate; dJointID get_id() const { return dBaseTemplate::get_id(); } void set_id(dJointID value) { dBaseTemplate::set_id(value); } void destroy() { dBaseTemplate::destroy(); } public: dNullJointTemplate() { } dNullJointTemplate (dWorldID world, dJointGroupID group=0) { set_id(dJointCreateNull(world, group)); } dNullJointTemplate (dWorldTemplate& world, dJointGroupID group=0) { set_id(dJointCreateNull (world.id(), group)); } void create (dWorldID world, dJointGroupID group=0) { destroy(); set_id(dJointCreateNull(world, group)); } void create (dWorldTemplate& world, dJointGroupID group=0) { create(world.id(), group); } }; template class dAMotorJointTemplate : public dJointTemplate { private: // intentionally undefined, don't use these dAMotorJointTemplate (const dAMotorJointTemplate &); void operator = (const dAMotorJointTemplate &); protected: typedef dJointTemplate dBaseTemplate; dJointID get_id() const { return dBaseTemplate::get_id(); } void set_id(dJointID value) { dBaseTemplate::set_id(value); } void destroy() { dBaseTemplate::destroy(); } public: dAMotorJointTemplate() { } dAMotorJointTemplate (dWorldID world, dJointGroupID group=0) { set_id(dJointCreateAMotor(world, group)); } dAMotorJointTemplate (dWorldTemplate& world, dJointGroupID group=0) { set_id(dJointCreateAMotor(world.id(), group)); } void create (dWorldID world, dJointGroupID group=0) { destroy(); set_id(dJointCreateAMotor(world, group)); } void create (dWorldTemplate& world, dJointGroupID group=0) { create(world.id(), group); } void setMode (int mode) { dJointSetAMotorMode (get_id(), mode); } int getMode() const { return dJointGetAMotorMode (get_id()); } void setNumAxes (int num) { dJointSetAMotorNumAxes (get_id(), num); } int getNumAxes() const { return dJointGetAMotorNumAxes (get_id()); } void setAxis (int anum, int rel, dReal x, dReal y, dReal z) { dJointSetAMotorAxis (get_id(), anum, rel, x, y, z); } void setAxis (int anum, int rel, const dVector3 a) { setAxis(anum, rel, a[0], a[1], a[2]); } void getAxis (int anum, dVector3 result) const { dJointGetAMotorAxis (get_id(), anum, result); } int getAxisRel (int anum) const { return dJointGetAMotorAxisRel (get_id(), anum); } void setAngle (int anum, dReal angle) { dJointSetAMotorAngle (get_id(), anum, angle); } dReal getAngle (int anum) const { return dJointGetAMotorAngle (get_id(), anum); } dReal getAngleRate (int anum) { return dJointGetAMotorAngleRate (get_id(), anum); } void setParam (int parameter, dReal value) { dJointSetAMotorParam (get_id(), parameter, value); } dReal getParam (int parameter) const { return dJointGetAMotorParam (get_id(), parameter); } // TODO: expose params through methods void addTorques(dReal torque1, dReal torque2, dReal torque3) { dJointAddAMotorTorques(get_id(), torque1, torque2, torque3); } }; template class dLMotorJointTemplate : public dJointTemplate { private: // intentionally undefined, don't use these dLMotorJointTemplate (const dLMotorJointTemplate &); void operator = (const dLMotorJointTemplate &); protected: typedef dJointTemplate dBaseTemplate; dJointID get_id() const { return dBaseTemplate::get_id(); } void set_id(dJointID value) { dBaseTemplate::set_id(value); } void destroy() { dBaseTemplate::destroy(); } public: dLMotorJointTemplate() { } dLMotorJointTemplate (dWorldID world, dJointGroupID group=0) { set_id(dJointCreateLMotor(world, group)); } dLMotorJointTemplate (dWorldTemplate& world, dJointGroupID group=0) { set_id(dJointCreateLMotor(world.id(), group)); } void create (dWorldID world, dJointGroupID group=0) { destroy(); set_id(dJointCreateLMotor(world, group)); } void create (dWorldTemplate& world, dJointGroupID group=0) { create(world.id(), group); } void setNumAxes (int num) { dJointSetLMotorNumAxes (get_id(), num); } int getNumAxes() const { return dJointGetLMotorNumAxes (get_id()); } void setAxis (int anum, int rel, dReal x, dReal y, dReal z) { dJointSetLMotorAxis (get_id(), anum, rel, x, y, z); } void setAxis (int anum, int rel, const dVector3 a) { setAxis(anum, rel, a[0], a[1], a[2]); } void getAxis (int anum, dVector3 result) const { dJointGetLMotorAxis (get_id(), anum, result); } void setParam (int parameter, dReal value) { dJointSetLMotorParam (get_id(), parameter, value); } dReal getParam (int parameter) const { return dJointGetLMotorParam (get_id(), parameter); } // TODO: expose params through methods }; //} #if !defined(dODECPP_WORLD_TEMPLATE_BASE) #if defined(dODECPP_BODY_TEMPLATE_BASE) || defined(dODECPP_JOINTGROUP_TEMPLATE_BASE) || defined(dODECPP_JOINT_TEMPLATE_BASE) #error All the odecpp template bases must be defined or not defined together #endif #define dODECPP_WORLD_TEMPLATE_BASE dWorldDynamicIDContainer #define dODECPP_BODY_TEMPLATE_BASE dBodyDynamicIDContainer #define dODECPP_JOINTGROUP_TEMPLATE_BASE dJointGroupDynamicIDContainer #define dODECPP_JOINT_TEMPLATE_BASE dJointDynamicIDContainer #else // #if defined(dODECPP_WORLD_TEMPLATE_BASE) #if !defined(dODECPP_BODY_TEMPLATE_BASE) || !defined(dODECPP_JOINTGROUP_TEMPLATE_BASE) || !defined(dODECPP_JOINT_TEMPLATE_BASE) #error All the odecpp template bases must be defined or not defined together #endif #endif // #if defined(dODECPP_WORLD_TEMPLATE_BASE) typedef dWorldTemplate dWorld; typedef dBodyTemplate dBody; typedef dJointGroupTemplate dJointGroup; typedef dJointTemplate dJoint; typedef dBallJointTemplate dBallJoint; typedef dHingeJointTemplate dHingeJoint; typedef dSliderJointTemplate dSliderJoint; typedef dUniversalJointTemplate dUniversalJoint; typedef dHinge2JointTemplate dHinge2Joint; typedef dPRJointTemplate dPRJoint; typedef dPUJointTemplate dPUJoint; typedef dPistonJointTemplate dPistonJoint; typedef dFixedJointTemplate dFixedJoint; typedef dContactJointTemplate dContactJoint; typedef dNullJointTemplate dNullJoint; typedef dAMotorJointTemplate dAMotorJoint; typedef dLMotorJointTemplate dLMotorJoint; #endif #endif // Local variables: // mode:c++ // c-basic-offset:2 // End: ode-0.16/include/ode/export-dif.h0000664000175200017520000000342313403272463013570 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_EXPORT_DIF_ #define _ODE_EXPORT_DIF_ #include #ifdef __cplusplus extern "C" { #endif ODE_API void dWorldExportDIF (dWorldID w, FILE *file, const char *world_name); #ifdef __cplusplus } #endif #endif ode-0.16/include/ode/precision.h0000664000175200017520000000041213403272677013504 00000000000000#ifndef _ODE_PRECISION_H_ #define _ODE_PRECISION_H_ /* Define dSINGLE for single precision, dDOUBLE for double precision, * but never both! */ #if defined(dIDESINGLE) #define dSINGLE #elif defined(dIDEDOUBLE) #define dDOUBLE #else #define dDOUBLE #endif #endif ode-0.16/include/ode/timer.h0000664000175200017520000000556313403272463012636 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_TIMER_H_ #define _ODE_TIMER_H_ #include #ifdef __cplusplus extern "C" { #endif /* stop watch objects */ typedef struct dStopwatch { double time; /* total clock count */ unsigned long cc[2]; /* clock count since last `start' */ } dStopwatch; ODE_API void dStopwatchReset (dStopwatch *); ODE_API void dStopwatchStart (dStopwatch *); ODE_API void dStopwatchStop (dStopwatch *); ODE_API double dStopwatchTime (dStopwatch *); /* returns total time in secs */ /* code timers */ ODE_API void dTimerStart (const char *description); /* pass a static string here */ ODE_API void dTimerNow (const char *description); /* pass a static string here */ ODE_API void dTimerEnd(void); /* print out a timer report. if `average' is nonzero, print out the average * time for each slot (this is only meaningful if the same start-now-end * calls are being made repeatedly. */ ODE_API void dTimerReport (FILE *fout, int average); /* resolution */ /* returns the timer ticks per second implied by the timing hardware or API. * the actual timer resolution may not be this great. */ ODE_API double dTimerTicksPerSecond(void); /* returns an estimate of the actual timer resolution, in seconds. this may * be greater than 1/ticks_per_second. */ ODE_API double dTimerResolution(void); #ifdef __cplusplus } #endif #endif ode-0.16/include/ode/contact.h0000664000175200017520000001021313403272463013135 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_CONTACT_H_ #define _ODE_CONTACT_H_ #include #ifdef __cplusplus extern "C" { #endif enum { dContactMu2 = 0x001, /**< Use axis dependent friction */ dContactAxisDep = 0x001, /**< Same as above */ dContactFDir1 = 0x002, /**< Use FDir for the first friction value */ dContactBounce = 0x004, /**< Restore collision energy anti-parallel to the normal */ dContactSoftERP = 0x008, /**< Don't use global erp for penetration reduction */ dContactSoftCFM = 0x010, /**< Don't use global cfm for penetration constraint */ dContactMotion1 = 0x020, /**< Use a non-zero target velocity for the constraint */ dContactMotion2 = 0x040, dContactMotionN = 0x080, dContactSlip1 = 0x100, /**< Force-dependent slip. */ dContactSlip2 = 0x200, dContactRolling = 0x400, /**< Rolling/Angular friction */ dContactApprox0 = 0x0000, dContactApprox1_1 = 0x1000, dContactApprox1_2 = 0x2000, dContactApprox1_N = 0x4000, /**< For rolling friction */ dContactApprox1 = 0x7000 }; typedef struct dSurfaceParameters { /* must always be defined */ int mode; dReal mu; /* only defined if the corresponding flag is set in mode */ dReal mu2; dReal rho; /**< Rolling friction */ dReal rho2; dReal rhoN; /**< Spinning friction */ dReal bounce; /**< Coefficient of restitution */ dReal bounce_vel; /**< Bouncing threshold */ dReal soft_erp; dReal soft_cfm; dReal motion1,motion2,motionN; dReal slip1,slip2; } dSurfaceParameters; /** * @brief Describe the contact point between two geoms. * * If two bodies touch, or if a body touches a static feature in its * environment, the contact is represented by one or more "contact * points", described by dContactGeom. * * The convention is that if body 1 is moved along the normal vector by * a distance depth (or equivalently if body 2 is moved the same distance * in the opposite direction) then the contact depth will be reduced to * zero. This means that the normal vector points "in" to body 1. * * @ingroup collide */ typedef struct dContactGeom { dVector3 pos; /*< contact position*/ dVector3 normal; /*< normal vector*/ dReal depth; /*< penetration depth*/ dGeomID g1,g2; /*< the colliding geoms*/ int side1,side2; /*< (to be documented)*/ } dContactGeom; /* contact info used by contact joint */ typedef struct dContact { dSurfaceParameters surface; dContactGeom geom; dVector3 fdir1; } dContact; #ifdef __cplusplus } #endif #endif ode-0.16/include/ode/collision.h0000664000175200017520000014721013403272463013505 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_COLLISION_H_ #define _ODE_COLLISION_H_ #include #include #include #ifdef __cplusplus extern "C" { #endif /** * @defgroup collide Collision Detection * * ODE has two main components: a dynamics simulation engine and a collision * detection engine. The collision engine is given information about the * shape of each body. At each time step it figures out which bodies touch * each other and passes the resulting contact point information to the user. * The user in turn creates contact joints between bodies. * * Using ODE's collision detection is optional - an alternative collision * detection system can be used as long as it can supply the right kinds of * contact information. */ /* ************************************************************************ */ /* general functions */ /** * @brief Destroy a geom, removing it from any space. * * Destroy a geom, removing it from any space it is in first. This one * function destroys a geom of any type, but to create a geom you must call * a creation function for that type. * * When a space is destroyed, if its cleanup mode is 1 (the default) then all * the geoms in that space are automatically destroyed as well. * * @param geom the geom to be destroyed. * @ingroup collide */ ODE_API void dGeomDestroy (dGeomID geom); /** * @brief Set the user-defined data pointer stored in the geom. * * @param geom the geom to hold the data * @param data the data pointer to be stored * @ingroup collide */ ODE_API void dGeomSetData (dGeomID geom, void* data); /** * @brief Get the user-defined data pointer stored in the geom. * * @param geom the geom containing the data * @ingroup collide */ ODE_API void *dGeomGetData (dGeomID geom); /** * @brief Set the body associated with a placeable geom. * * Setting a body on a geom automatically combines the position vector and * rotation matrix of the body and geom, so that setting the position or * orientation of one will set the value for both objects. Setting a body * ID of zero gives the geom its own position and rotation, independent * from any body. If the geom was previously connected to a body then its * new independent position/rotation is set to the current position/rotation * of the body. * * Calling these functions on a non-placeable geom results in a runtime * error in the debug build of ODE. * * @param geom the geom to connect * @param body the body to attach to the geom * @ingroup collide */ ODE_API void dGeomSetBody (dGeomID geom, dBodyID body); /** * @brief Get the body associated with a placeable geom. * @param geom the geom to query. * @sa dGeomSetBody * @ingroup collide */ ODE_API dBodyID dGeomGetBody (dGeomID geom); /** * @brief Set the position vector of a placeable geom. * * If the geom is attached to a body, the body's position will also be changed. * Calling this function on a non-placeable geom results in a runtime error in * the debug build of ODE. * * @param geom the geom to set. * @param x the new X coordinate. * @param y the new Y coordinate. * @param z the new Z coordinate. * @sa dBodySetPosition * @ingroup collide */ ODE_API void dGeomSetPosition (dGeomID geom, dReal x, dReal y, dReal z); /** * @brief Set the rotation matrix of a placeable geom. * * If the geom is attached to a body, the body's rotation will also be changed. * Calling this function on a non-placeable geom results in a runtime error in * the debug build of ODE. * * @param geom the geom to set. * @param R the new rotation matrix. * @sa dBodySetRotation * @ingroup collide */ ODE_API void dGeomSetRotation (dGeomID geom, const dMatrix3 R); /** * @brief Set the rotation of a placeable geom. * * If the geom is attached to a body, the body's rotation will also be changed. * * Calling this function on a non-placeable geom results in a runtime error in * the debug build of ODE. * * @param geom the geom to set. * @param Q the new rotation. * @sa dBodySetQuaternion * @ingroup collide */ ODE_API void dGeomSetQuaternion (dGeomID geom, const dQuaternion Q); /** * @brief Get the position vector of a placeable geom. * * If the geom is attached to a body, the body's position will be returned. * * Calling this function on a non-placeable geom results in a runtime error in * the debug build of ODE. * * @param geom the geom to query. * @returns A pointer to the geom's position vector. * @remarks The returned value is a pointer to the geom's internal * data structure. It is valid until any changes are made * to the geom. * @sa dBodyGetPosition * @ingroup collide */ ODE_API const dReal * dGeomGetPosition (dGeomID geom); /** * @brief Copy the position of a geom into a vector. * @ingroup collide * @param geom the geom to query * @param pos a copy of the geom position * @sa dGeomGetPosition */ ODE_API void dGeomCopyPosition (dGeomID geom, dVector3 pos); /** * @brief Get the rotation matrix of a placeable geom. * * If the geom is attached to a body, the body's rotation will be returned. * * Calling this function on a non-placeable geom results in a runtime error in * the debug build of ODE. * * @param geom the geom to query. * @returns A pointer to the geom's rotation matrix. * @remarks The returned value is a pointer to the geom's internal * data structure. It is valid until any changes are made * to the geom. * @sa dBodyGetRotation * @ingroup collide */ ODE_API const dReal * dGeomGetRotation (dGeomID geom); /** * @brief Get the rotation matrix of a placeable geom. * * If the geom is attached to a body, the body's rotation will be returned. * * Calling this function on a non-placeable geom results in a runtime error in * the debug build of ODE. * * @param geom the geom to query. * @param R a copy of the geom rotation * @sa dGeomGetRotation * @ingroup collide */ ODE_API void dGeomCopyRotation(dGeomID geom, dMatrix3 R); /** * @brief Get the rotation quaternion of a placeable geom. * * If the geom is attached to a body, the body's quaternion will be returned. * * Calling this function on a non-placeable geom results in a runtime error in * the debug build of ODE. * * @param geom the geom to query. * @param result a copy of the rotation quaternion. * @sa dBodyGetQuaternion * @ingroup collide */ ODE_API void dGeomGetQuaternion (dGeomID geom, dQuaternion result); /** * @brief Return the axis-aligned bounding box. * * Return in aabb an axis aligned bounding box that surrounds the given geom. * The aabb array has elements (minx, maxx, miny, maxy, minz, maxz). If the * geom is a space, a bounding box that surrounds all contained geoms is * returned. * * This function may return a pre-computed cached bounding box, if it can * determine that the geom has not moved since the last time the bounding * box was computed. * * @param geom the geom to query * @param aabb the returned bounding box * @ingroup collide */ ODE_API void dGeomGetAABB (dGeomID geom, dReal aabb[6]); /** * @brief Determing if a geom is a space. * @param geom the geom to query * @returns Non-zero if the geom is a space, zero otherwise. * @ingroup collide */ ODE_API int dGeomIsSpace (dGeomID geom); /** * @brief Query for the space containing a particular geom. * @param geom the geom to query * @returns The space that contains the geom, or NULL if the geom is * not contained by a space. * @ingroup collide */ ODE_API dSpaceID dGeomGetSpace (dGeomID); /** * @brief Given a geom, this returns its class. * * The ODE classes are: * @li dSphereClass * @li dBoxClass * @li dCylinderClass * @li dPlaneClass * @li dRayClass * @li dConvexClass * @li dGeomTransformClass * @li dTriMeshClass * @li dSimpleSpaceClass * @li dHashSpaceClass * @li dQuadTreeSpaceClass * @li dFirstUserClass * @li dLastUserClass * * User-defined class will return their own number. * * @param geom the geom to query * @returns The geom class ID. * @ingroup collide */ ODE_API int dGeomGetClass (dGeomID geom); /** * @brief Set the "category" bitfield for the given geom. * * The category bitfield is used by spaces to govern which geoms will * interact with each other. The bitfield is guaranteed to be at least * 32 bits wide. The default category values for newly created geoms * have all bits set. * * @param geom the geom to set * @param bits the new bitfield value * @ingroup collide */ ODE_API void dGeomSetCategoryBits (dGeomID geom, unsigned long bits); /** * @brief Set the "collide" bitfield for the given geom. * * The collide bitfield is used by spaces to govern which geoms will * interact with each other. The bitfield is guaranteed to be at least * 32 bits wide. The default category values for newly created geoms * have all bits set. * * @param geom the geom to set * @param bits the new bitfield value * @ingroup collide */ ODE_API void dGeomSetCollideBits (dGeomID geom, unsigned long bits); /** * @brief Get the "category" bitfield for the given geom. * * @param geom the geom to set * @param bits the new bitfield value * @sa dGeomSetCategoryBits * @ingroup collide */ ODE_API unsigned long dGeomGetCategoryBits (dGeomID); /** * @brief Get the "collide" bitfield for the given geom. * * @param geom the geom to set * @param bits the new bitfield value * @sa dGeomSetCollideBits * @ingroup collide */ ODE_API unsigned long dGeomGetCollideBits (dGeomID); /** * @brief Enable a geom. * * Disabled geoms are completely ignored by dSpaceCollide and dSpaceCollide2, * although they can still be members of a space. New geoms are created in * the enabled state. * * @param geom the geom to enable * @sa dGeomDisable * @sa dGeomIsEnabled * @ingroup collide */ ODE_API void dGeomEnable (dGeomID geom); /** * @brief Disable a geom. * * Disabled geoms are completely ignored by dSpaceCollide and dSpaceCollide2, * although they can still be members of a space. New geoms are created in * the enabled state. * * @param geom the geom to disable * @sa dGeomDisable * @sa dGeomIsEnabled * @ingroup collide */ ODE_API void dGeomDisable (dGeomID geom); /** * @brief Check to see if a geom is enabled. * * Disabled geoms are completely ignored by dSpaceCollide and dSpaceCollide2, * although they can still be members of a space. New geoms are created in * the enabled state. * * @param geom the geom to query * @returns Non-zero if the geom is enabled, zero otherwise. * @sa dGeomDisable * @sa dGeomIsEnabled * @ingroup collide */ ODE_API int dGeomIsEnabled (dGeomID geom); enum { dGeomCommonControlClass = 0, dGeomColliderControlClass = 1 }; enum { dGeomCommonAnyControlCode = 0, dGeomColliderSetMergeSphereContactsControlCode = 1, dGeomColliderGetMergeSphereContactsControlCode = 2 }; enum { dGeomColliderMergeContactsValue__Default = 0, /* Used with Set... to restore default value*/ dGeomColliderMergeContactsValue_None = 1, dGeomColliderMergeContactsValue_Normals = 2, dGeomColliderMergeContactsValue_Full = 3 }; /** * @brief Execute low level control operation for geometry. * * The variable the dataSize points to must be initialized before the call. * If the size does not match the one expected for the control class/code function * changes it to the size expected and returns failure. This implies the function * can be called with NULL data and zero size to test if control class/code is supported * and obtain required data size for it. * * dGeomCommonAnyControlCode applies to any control class and returns success if * at least one control code is available for the given class with given geom. * * Currently there are the folliwing control classes supported: * @li dGeomColliderControlClass * * For dGeomColliderControlClass there are the following codes available: * @li dGeomColliderSetMergeSphereContactsControlCode (arg of type int, dGeomColliderMergeContactsValue_*) * @li dGeomColliderGetMergeSphereContactsControlCode (arg of type int, dGeomColliderMergeContactsValue_*) * * @param geom the geom to control * @param controlClass the control class * @param controlCode the control code for the class * @param dataValue the control argument pointer * @param dataSize the control argument size provided or expected * @returns Boolean execution status * @ingroup collide */ ODE_API int dGeomLowLevelControl (dGeomID geom, int controlClass, int controlCode, void *dataValue, int *dataSize); /** * @brief Get world position of a relative point on geom. * * Calling this function on a non-placeable geom results in the same point being * returned. * * @ingroup collide * @param result will contain the result. */ ODE_API void dGeomGetRelPointPos ( dGeomID geom, dReal px, dReal py, dReal pz, dVector3 result ); /** * @brief takes a point in global coordinates and returns * the point's position in geom-relative coordinates. * * Calling this function on a non-placeable geom results in the same point being * returned. * * @remarks * This is the inverse of dGeomGetRelPointPos() * @ingroup collide * @param result will contain the result. */ ODE_API void dGeomGetPosRelPoint ( dGeomID geom, dReal px, dReal py, dReal pz, dVector3 result ); /** * @brief Convert from geom-local to world coordinates. * * Calling this function on a non-placeable geom results in the same vector being * returned. * * @ingroup collide * @param result will contain the result. */ ODE_API void dGeomVectorToWorld ( dGeomID geom, dReal px, dReal py, dReal pz, dVector3 result ); /** * @brief Convert from world to geom-local coordinates. * * Calling this function on a non-placeable geom results in the same vector being * returned. * * @ingroup collide * @param result will contain the result. */ ODE_API void dGeomVectorFromWorld ( dGeomID geom, dReal px, dReal py, dReal pz, dVector3 result ); /* ************************************************************************ */ /* geom offset from body */ /** * @brief Set the local offset position of a geom from its body. * * Sets the geom's positional offset in local coordinates. * After this call, the geom will be at a new position determined from the * body's position and the offset. * The geom must be attached to a body. * If the geom did not have an offset, it is automatically created. * * @param geom the geom to set. * @param x the new X coordinate. * @param y the new Y coordinate. * @param z the new Z coordinate. * @ingroup collide */ ODE_API void dGeomSetOffsetPosition (dGeomID geom, dReal x, dReal y, dReal z); /** * @brief Set the local offset rotation matrix of a geom from its body. * * Sets the geom's rotational offset in local coordinates. * After this call, the geom will be at a new position determined from the * body's position and the offset. * The geom must be attached to a body. * If the geom did not have an offset, it is automatically created. * * @param geom the geom to set. * @param R the new rotation matrix. * @ingroup collide */ ODE_API void dGeomSetOffsetRotation (dGeomID geom, const dMatrix3 R); /** * @brief Set the local offset rotation of a geom from its body. * * Sets the geom's rotational offset in local coordinates. * After this call, the geom will be at a new position determined from the * body's position and the offset. * The geom must be attached to a body. * If the geom did not have an offset, it is automatically created. * * @param geom the geom to set. * @param Q the new rotation. * @ingroup collide */ ODE_API void dGeomSetOffsetQuaternion (dGeomID geom, const dQuaternion Q); /** * @brief Set the offset position of a geom from its body. * * Sets the geom's positional offset to move it to the new world * coordinates. * After this call, the geom will be at the world position passed in, * and the offset will be the difference from the current body position. * The geom must be attached to a body. * If the geom did not have an offset, it is automatically created. * * @param geom the geom to set. * @param x the new X coordinate. * @param y the new Y coordinate. * @param z the new Z coordinate. * @ingroup collide */ ODE_API void dGeomSetOffsetWorldPosition (dGeomID geom, dReal x, dReal y, dReal z); /** * @brief Set the offset rotation of a geom from its body. * * Sets the geom's rotational offset to orient it to the new world * rotation matrix. * After this call, the geom will be at the world orientation passed in, * and the offset will be the difference from the current body orientation. * The geom must be attached to a body. * If the geom did not have an offset, it is automatically created. * * @param geom the geom to set. * @param R the new rotation matrix. * @ingroup collide */ ODE_API void dGeomSetOffsetWorldRotation (dGeomID geom, const dMatrix3 R); /** * @brief Set the offset rotation of a geom from its body. * * Sets the geom's rotational offset to orient it to the new world * rotation matrix. * After this call, the geom will be at the world orientation passed in, * and the offset will be the difference from the current body orientation. * The geom must be attached to a body. * If the geom did not have an offset, it is automatically created. * * @param geom the geom to set. * @param Q the new rotation. * @ingroup collide */ ODE_API void dGeomSetOffsetWorldQuaternion (dGeomID geom, const dQuaternion); /** * @brief Clear any offset from the geom. * * If the geom has an offset, it is eliminated and the geom is * repositioned at the body's position. If the geom has no offset, * this function does nothing. * This is more efficient than calling dGeomSetOffsetPosition(zero) * and dGeomSetOffsetRotation(identiy), because this function actually * eliminates the offset, rather than leaving it as the identity transform. * * @param geom the geom to have its offset destroyed. * @ingroup collide */ ODE_API void dGeomClearOffset(dGeomID geom); /** * @brief Check to see whether the geom has an offset. * * This function will return non-zero if the offset has been created. * Note that there is a difference between a geom with no offset, * and a geom with an offset that is the identity transform. * In the latter case, although the observed behaviour is identical, * there is a unnecessary computation involved because the geom will * be applying the transform whenever it needs to recalculate its world * position. * * @param geom the geom to query. * @returns Non-zero if the geom has an offset, zero otherwise. * @ingroup collide */ ODE_API int dGeomIsOffset(dGeomID geom); /** * @brief Get the offset position vector of a geom. * * Returns the positional offset of the geom in local coordinates. * If the geom has no offset, this function returns the zero vector. * * @param geom the geom to query. * @returns A pointer to the geom's offset vector. * @remarks The returned value is a pointer to the geom's internal * data structure. It is valid until any changes are made * to the geom. * @ingroup collide */ ODE_API const dReal * dGeomGetOffsetPosition (dGeomID geom); /** * @brief Copy the offset position vector of a geom. * * Returns the positional offset of the geom in local coordinates. * If the geom has no offset, this function returns the zero vector. * * @param geom the geom to query. * @param pos returns the offset position * @ingroup collide */ ODE_API void dGeomCopyOffsetPosition (dGeomID geom, dVector3 pos); /** * @brief Get the offset rotation matrix of a geom. * * Returns the rotational offset of the geom in local coordinates. * If the geom has no offset, this function returns the identity * matrix. * * @param geom the geom to query. * @returns A pointer to the geom's offset rotation matrix. * @remarks The returned value is a pointer to the geom's internal * data structure. It is valid until any changes are made * to the geom. * @ingroup collide */ ODE_API const dReal * dGeomGetOffsetRotation (dGeomID geom); /** * @brief Copy the offset rotation matrix of a geom. * * Returns the rotational offset of the geom in local coordinates. * If the geom has no offset, this function returns the identity * matrix. * * @param geom the geom to query. * @param R returns the rotation matrix. * @ingroup collide */ ODE_API void dGeomCopyOffsetRotation (dGeomID geom, dMatrix3 R); /** * @brief Get the offset rotation quaternion of a geom. * * Returns the rotation offset of the geom as a quaternion. * If the geom has no offset, the identity quaternion is returned. * * @param geom the geom to query. * @param result a copy of the rotation quaternion. * @ingroup collide */ ODE_API void dGeomGetOffsetQuaternion (dGeomID geom, dQuaternion result); /* ************************************************************************ */ /* collision detection */ /* * Just generate any contacts (disables any contact refining). */ #define CONTACTS_UNIMPORTANT 0x80000000 /** * * @brief Given two geoms o1 and o2 that potentially intersect, * generate contact information for them. * * Internally, this just calls the correct class-specific collision * functions for o1 and o2. * * @param o1 The first geom to test. * @param o2 The second geom to test. * * @param flags The flags specify how contacts should be generated if * the geoms touch. The lower 16 bits of flags is an integer that * specifies the maximum number of contact points to generate. You must * ask for at least one contact. * Additionally, following bits may be set: * CONTACTS_UNIMPORTANT -- just generate any contacts (skip contact refining). * All other bits in flags must be set to zero. In the future the other bits * may be used to select from different contact generation strategies. * * @param contact Points to an array of dContactGeom structures. The array * must be able to hold at least the maximum number of contacts. These * dContactGeom structures may be embedded within larger structures in the * array -- the skip parameter is the byte offset from one dContactGeom to * the next in the array. If skip is sizeof(dContactGeom) then contact * points to a normal (C-style) array. It is an error for skip to be smaller * than sizeof(dContactGeom). * * @returns If the geoms intersect, this function returns the number of contact * points generated (and updates the contact array), otherwise it returns 0 * (and the contact array is not touched). * * @remarks If a space is passed as o1 or o2 then this function will collide * all objects contained in o1 with all objects contained in o2, and return * the resulting contact points. This method for colliding spaces with geoms * (or spaces with spaces) provides no user control over the individual * collisions. To get that control, use dSpaceCollide or dSpaceCollide2 instead. * * @remarks If o1 and o2 are the same geom then this function will do nothing * and return 0. Technically speaking an object intersects with itself, but it * is not useful to find contact points in this case. * * @remarks This function does not care if o1 and o2 are in the same space or not * (or indeed if they are in any space at all). * * @ingroup collide */ ODE_API int dCollide (dGeomID o1, dGeomID o2, int flags, dContactGeom *contact, int skip); /** * @brief Determines which pairs of geoms in a space may potentially intersect, * and calls the callback function for each candidate pair. * * @param space The space to test. * * @param data Passed from dSpaceCollide directly to the callback * function. Its meaning is user defined. The o1 and o2 arguments are the * geoms that may be near each other. * * @param callback A callback function is of type @ref dNearCallback. * * @remarks Other spaces that are contained within the colliding space are * not treated specially, i.e. they are not recursed into. The callback * function may be passed these contained spaces as one or both geom * arguments. * * @remarks dSpaceCollide() is guaranteed to pass all intersecting geom * pairs to the callback function, but may also pass close but * non-intersecting pairs. The number of these calls depends on the * internal algorithms used by the space. Thus you should not expect * that dCollide will return contacts for every pair passed to the * callback. * * @sa dSpaceCollide2 * @ingroup collide */ ODE_API void dSpaceCollide (dSpaceID space, void *data, dNearCallback *callback); /** * @brief Determines which geoms from one space may potentially intersect with * geoms from another space, and calls the callback function for each candidate * pair. * * @param space1 The first space to test. * * @param space2 The second space to test. * * @param data Passed from dSpaceCollide directly to the callback * function. Its meaning is user defined. The o1 and o2 arguments are the * geoms that may be near each other. * * @param callback A callback function is of type @ref dNearCallback. * * @remarks This function can also test a single non-space geom against a * space. This function is useful when there is a collision hierarchy, i.e. * when there are spaces that contain other spaces. * * @remarks Other spaces that are contained within the colliding space are * not treated specially, i.e. they are not recursed into. The callback * function may be passed these contained spaces as one or both geom * arguments. * * @remarks Sublevel value of space affects how the spaces are iterated. * Both spaces are recursed only if their sublevels match. Otherwise, only * the space with greater sublevel is recursed and the one with lesser sublevel * is used as a geom itself. * * @remarks dSpaceCollide2() is guaranteed to pass all intersecting geom * pairs to the callback function, but may also pass close but * non-intersecting pairs. The number of these calls depends on the * internal algorithms used by the space. Thus you should not expect * that dCollide will return contacts for every pair passed to the * callback. * * @sa dSpaceCollide * @sa dSpaceSetSublevel * @ingroup collide */ ODE_API void dSpaceCollide2 (dGeomID space1, dGeomID space2, void *data, dNearCallback *callback); /* ************************************************************************ */ /* standard classes */ /* the maximum number of user classes that are supported */ enum { dMaxUserClasses = 4 }; /* class numbers - each geometry object needs a unique number */ enum { dSphereClass = 0, dBoxClass, dCapsuleClass, dCylinderClass, dPlaneClass, dRayClass, dConvexClass, dGeomTransformClass, dTriMeshClass, dHeightfieldClass, dFirstSpaceClass, dSimpleSpaceClass = dFirstSpaceClass, dHashSpaceClass, dSweepAndPruneSpaceClass, /* SAP */ dQuadTreeSpaceClass, dLastSpaceClass = dQuadTreeSpaceClass, dFirstUserClass, dLastUserClass = dFirstUserClass + dMaxUserClasses - 1, dGeomNumClasses }; /** * @defgroup collide_sphere Sphere Class * @ingroup collide */ /** * @brief Create a sphere geom of the given radius, and return its ID. * * @param space a space to contain the new geom. May be null. * @param radius the radius of the sphere. * * @returns A new sphere geom. * * @remarks The point of reference for a sphere is its center. * * @sa dGeomDestroy * @sa dGeomSphereSetRadius * @ingroup collide_sphere */ ODE_API dGeomID dCreateSphere (dSpaceID space, dReal radius); /** * @brief Set the radius of a sphere geom. * * @param sphere the sphere to set. * @param radius the new radius. * * @sa dGeomSphereGetRadius * @ingroup collide_sphere */ ODE_API void dGeomSphereSetRadius (dGeomID sphere, dReal radius); /** * @brief Retrieves the radius of a sphere geom. * * @param sphere the sphere to query. * * @sa dGeomSphereSetRadius * @ingroup collide_sphere */ ODE_API dReal dGeomSphereGetRadius (dGeomID sphere); /** * @brief Calculate the depth of the a given point within a sphere. * * @param sphere the sphere to query. * @param x the X coordinate of the point. * @param y the Y coordinate of the point. * @param z the Z coordinate of the point. * * @returns The depth of the point. Points inside the sphere will have a * positive depth, points outside it will have a negative depth, and points * on the surface will have a depth of zero. * * @ingroup collide_sphere */ ODE_API dReal dGeomSpherePointDepth (dGeomID sphere, dReal x, dReal y, dReal z); /*--> Convex Functions*/ ODE_API dGeomID dCreateConvex (dSpaceID space, const dReal *_planes, unsigned int _planecount, const dReal *_points, unsigned int _pointcount, const unsigned int *_polygons); ODE_API void dGeomSetConvex (dGeomID g, const dReal *_planes, unsigned int _count, const dReal *_points, unsigned int _pointcount, const unsigned int *_polygons); /*<-- Convex Functions*/ /** * @defgroup collide_box Box Class * @ingroup collide */ /** * @brief Create a box geom with the provided side lengths. * * @param space a space to contain the new geom. May be null. * @param lx the length of the box along the X axis * @param ly the length of the box along the Y axis * @param lz the length of the box along the Z axis * * @returns A new box geom. * * @remarks The point of reference for a box is its center. * * @sa dGeomDestroy * @sa dGeomBoxSetLengths * @ingroup collide_box */ ODE_API dGeomID dCreateBox (dSpaceID space, dReal lx, dReal ly, dReal lz); /** * @brief Set the side lengths of the given box. * * @param box the box to set * @param lx the length of the box along the X axis * @param ly the length of the box along the Y axis * @param lz the length of the box along the Z axis * * @sa dGeomBoxGetLengths * @ingroup collide_box */ ODE_API void dGeomBoxSetLengths (dGeomID box, dReal lx, dReal ly, dReal lz); /** * @brief Get the side lengths of a box. * * @param box the box to query * @param result the returned side lengths * * @sa dGeomBoxSetLengths * @ingroup collide_box */ ODE_API void dGeomBoxGetLengths (dGeomID box, dVector3 result); /** * @brief Return the depth of a point in a box. * * @param box the box to query * @param x the X coordinate of the point to test. * @param y the Y coordinate of the point to test. * @param z the Z coordinate of the point to test. * * @returns The depth of the point. Points inside the box will have a * positive depth, points outside it will have a negative depth, and points * on the surface will have a depth of zero. */ ODE_API dReal dGeomBoxPointDepth (dGeomID box, dReal x, dReal y, dReal z); ODE_API dGeomID dCreatePlane (dSpaceID space, dReal a, dReal b, dReal c, dReal d); ODE_API void dGeomPlaneSetParams (dGeomID plane, dReal a, dReal b, dReal c, dReal d); ODE_API void dGeomPlaneGetParams (dGeomID plane, dVector4 result); ODE_API dReal dGeomPlanePointDepth (dGeomID plane, dReal x, dReal y, dReal z); ODE_API dGeomID dCreateCapsule (dSpaceID space, dReal radius, dReal length); ODE_API void dGeomCapsuleSetParams (dGeomID ccylinder, dReal radius, dReal length); ODE_API void dGeomCapsuleGetParams (dGeomID ccylinder, dReal *radius, dReal *length); ODE_API dReal dGeomCapsulePointDepth (dGeomID ccylinder, dReal x, dReal y, dReal z); /* For now we want to have a backwards compatible C-API, note: C++ API is not.*/ #define dCreateCCylinder dCreateCapsule #define dGeomCCylinderSetParams dGeomCapsuleSetParams #define dGeomCCylinderGetParams dGeomCapsuleGetParams #define dGeomCCylinderPointDepth dGeomCapsulePointDepth #define dCCylinderClass dCapsuleClass ODE_API dGeomID dCreateCylinder (dSpaceID space, dReal radius, dReal length); ODE_API void dGeomCylinderSetParams (dGeomID cylinder, dReal radius, dReal length); ODE_API void dGeomCylinderGetParams (dGeomID cylinder, dReal *radius, dReal *length); ODE_API dGeomID dCreateRay (dSpaceID space, dReal length); ODE_API void dGeomRaySetLength (dGeomID ray, dReal length); ODE_API dReal dGeomRayGetLength (dGeomID ray); ODE_API void dGeomRaySet (dGeomID ray, dReal px, dReal py, dReal pz, dReal dx, dReal dy, dReal dz); ODE_API void dGeomRayGet (dGeomID ray, dVector3 start, dVector3 dir); /* * Set/get ray flags that influence ray collision detection. * These flags are currently only noticed by the trimesh collider, because * they can make a major differences there. */ ODE_API_DEPRECATED ODE_API void dGeomRaySetParams (dGeomID g, int FirstContact, int BackfaceCull); ODE_API_DEPRECATED ODE_API void dGeomRayGetParams (dGeomID g, int *FirstContact, int *BackfaceCull); ODE_API void dGeomRaySetFirstContact (dGeomID g, int firstContact); ODE_API int dGeomRayGetFirstContact (dGeomID g); ODE_API void dGeomRaySetBackfaceCull (dGeomID g, int backfaceCull); ODE_API int dGeomRayGetBackfaceCull (dGeomID g); ODE_API void dGeomRaySetClosestHit (dGeomID g, int closestHit); ODE_API int dGeomRayGetClosestHit (dGeomID g); #include "collision_trimesh.h" ODE_API_DEPRECATED ODE_API dGeomID dCreateGeomTransform (dSpaceID space); ODE_API_DEPRECATED ODE_API void dGeomTransformSetGeom (dGeomID g, dGeomID obj); ODE_API_DEPRECATED ODE_API dGeomID dGeomTransformGetGeom (dGeomID g); ODE_API_DEPRECATED ODE_API void dGeomTransformSetCleanup (dGeomID g, int mode); ODE_API_DEPRECATED ODE_API int dGeomTransformGetCleanup (dGeomID g); ODE_API_DEPRECATED ODE_API void dGeomTransformSetInfo (dGeomID g, int mode); ODE_API_DEPRECATED ODE_API int dGeomTransformGetInfo (dGeomID g); /* ************************************************************************ */ /* heightfield functions */ /* Data storage for heightfield data.*/ struct dxHeightfieldData; typedef struct dxHeightfieldData* dHeightfieldDataID; /** * @brief Callback prototype * * Used by the callback heightfield data type to sample a height for a * given cell position. * * @param p_user_data User data specified when creating the dHeightfieldDataID * @param x The index of a sample in the local x axis. It is a value * in the range zero to ( nWidthSamples - 1 ). * @param x The index of a sample in the local z axis. It is a value * in the range zero to ( nDepthSamples - 1 ). * * @return The sample height which is then scaled and offset using the * values specified when the heightfield data was created. * * @ingroup collide */ typedef dReal dHeightfieldGetHeight( void* p_user_data, int x, int z ); /** * @brief Creates a heightfield geom. * * Uses the information in the given dHeightfieldDataID to construct * a geom representing a heightfield in a collision space. * * @param space The space to add the geom to. * @param data The dHeightfieldDataID created by dGeomHeightfieldDataCreate and * setup by dGeomHeightfieldDataBuildCallback, dGeomHeightfieldDataBuildByte, * dGeomHeightfieldDataBuildShort or dGeomHeightfieldDataBuildFloat. * @param bPlaceable If non-zero this geom can be transformed in the world using the * usual functions such as dGeomSetPosition and dGeomSetRotation. If the geom is * not set as placeable, then it uses a fixed orientation where the global y axis * represents the dynamic 'height' of the heightfield. * * @return A geom id to reference this geom in other calls. * * @ingroup collide */ ODE_API dGeomID dCreateHeightfield( dSpaceID space, dHeightfieldDataID data, int bPlaceable ); /** * @brief Creates a new empty dHeightfieldDataID. * * Allocates a new dHeightfieldDataID and returns it. You must call * dGeomHeightfieldDataDestroy to destroy it after the geom has been removed. * The dHeightfieldDataID value is used when specifying a data format type. * * @return A dHeightfieldDataID for use with dGeomHeightfieldDataBuildCallback, * dGeomHeightfieldDataBuildByte, dGeomHeightfieldDataBuildShort or * dGeomHeightfieldDataBuildFloat. * @ingroup collide */ ODE_API dHeightfieldDataID dGeomHeightfieldDataCreate(void); /** * @brief Destroys a dHeightfieldDataID. * * Deallocates a given dHeightfieldDataID and all managed resources. * * @param d A dHeightfieldDataID created by dGeomHeightfieldDataCreate * @ingroup collide */ ODE_API void dGeomHeightfieldDataDestroy( dHeightfieldDataID d ); /** * @brief Configures a dHeightfieldDataID to use a callback to * retrieve height data. * * Before a dHeightfieldDataID can be used by a geom it must be * configured to specify the format of the height data. * This call specifies that the heightfield data is computed by * the user and it should use the given callback when determining * the height of a given element of it's shape. * * @param d A new dHeightfieldDataID created by dGeomHeightfieldDataCreate * * @param width Specifies the total 'width' of the heightfield along * the geom's local x axis. * @param depth Specifies the total 'depth' of the heightfield along * the geom's local z axis. * * @param widthSamples Specifies the number of vertices to sample * along the width of the heightfield. Each vertex has a corresponding * height value which forms the overall shape. * Naturally this value must be at least two or more. * @param depthSamples Specifies the number of vertices to sample * along the depth of the heightfield. * * @param scale A uniform scale applied to all raw height data. * @param offset An offset applied to the scaled height data. * * @param thickness A value subtracted from the lowest height * value which in effect adds an additional cuboid to the base of the * heightfield. This is used to prevent geoms from looping under the * desired terrain and not registering as a collision. Note that the * thickness is not affected by the scale or offset parameters. * * @param bWrap If non-zero the heightfield will infinitely tile in both * directions along the local x and z axes. If zero the heightfield is * bounded from zero to width in the local x axis, and zero to depth in * the local z axis. * * @ingroup collide */ ODE_API void dGeomHeightfieldDataBuildCallback( dHeightfieldDataID d, void* pUserData, dHeightfieldGetHeight* pCallback, dReal width, dReal depth, int widthSamples, int depthSamples, dReal scale, dReal offset, dReal thickness, int bWrap ); /** * @brief Configures a dHeightfieldDataID to use height data in byte format. * * Before a dHeightfieldDataID can be used by a geom it must be * configured to specify the format of the height data. * This call specifies that the heightfield data is stored as a rectangular * array of bytes (8 bit unsigned) representing the height at each sample point. * * @param d A new dHeightfieldDataID created by dGeomHeightfieldDataCreate * * @param pHeightData A pointer to the height data. * @param bCopyHeightData When non-zero the height data is copied to an * internal store. When zero the height data is accessed by reference and * so must persist throughout the lifetime of the heightfield. * * @param width Specifies the total 'width' of the heightfield along * the geom's local x axis. * @param depth Specifies the total 'depth' of the heightfield along * the geom's local z axis. * * @param widthSamples Specifies the number of vertices to sample * along the width of the heightfield. Each vertex has a corresponding * height value which forms the overall shape. * Naturally this value must be at least two or more. * @param depthSamples Specifies the number of vertices to sample * along the depth of the heightfield. * * @param scale A uniform scale applied to all raw height data. * @param offset An offset applied to the scaled height data. * * @param thickness A value subtracted from the lowest height * value which in effect adds an additional cuboid to the base of the * heightfield. This is used to prevent geoms from looping under the * desired terrain and not registering as a collision. Note that the * thickness is not affected by the scale or offset parameters. * * @param bWrap If non-zero the heightfield will infinitely tile in both * directions along the local x and z axes. If zero the heightfield is * bounded from zero to width in the local x axis, and zero to depth in * the local z axis. * * @ingroup collide */ ODE_API void dGeomHeightfieldDataBuildByte( dHeightfieldDataID d, const unsigned char* pHeightData, int bCopyHeightData, dReal width, dReal depth, int widthSamples, int depthSamples, dReal scale, dReal offset, dReal thickness, int bWrap ); /** * @brief Configures a dHeightfieldDataID to use height data in short format. * * Before a dHeightfieldDataID can be used by a geom it must be * configured to specify the format of the height data. * This call specifies that the heightfield data is stored as a rectangular * array of shorts (16 bit signed) representing the height at each sample point. * * @param d A new dHeightfieldDataID created by dGeomHeightfieldDataCreate * * @param pHeightData A pointer to the height data. * @param bCopyHeightData When non-zero the height data is copied to an * internal store. When zero the height data is accessed by reference and * so must persist throughout the lifetime of the heightfield. * * @param width Specifies the total 'width' of the heightfield along * the geom's local x axis. * @param depth Specifies the total 'depth' of the heightfield along * the geom's local z axis. * * @param widthSamples Specifies the number of vertices to sample * along the width of the heightfield. Each vertex has a corresponding * height value which forms the overall shape. * Naturally this value must be at least two or more. * @param depthSamples Specifies the number of vertices to sample * along the depth of the heightfield. * * @param scale A uniform scale applied to all raw height data. * @param offset An offset applied to the scaled height data. * * @param thickness A value subtracted from the lowest height * value which in effect adds an additional cuboid to the base of the * heightfield. This is used to prevent geoms from looping under the * desired terrain and not registering as a collision. Note that the * thickness is not affected by the scale or offset parameters. * * @param bWrap If non-zero the heightfield will infinitely tile in both * directions along the local x and z axes. If zero the heightfield is * bounded from zero to width in the local x axis, and zero to depth in * the local z axis. * * @ingroup collide */ ODE_API void dGeomHeightfieldDataBuildShort( dHeightfieldDataID d, const short* pHeightData, int bCopyHeightData, dReal width, dReal depth, int widthSamples, int depthSamples, dReal scale, dReal offset, dReal thickness, int bWrap ); /** * @brief Configures a dHeightfieldDataID to use height data in * single precision floating point format. * * Before a dHeightfieldDataID can be used by a geom it must be * configured to specify the format of the height data. * This call specifies that the heightfield data is stored as a rectangular * array of single precision floats representing the height at each * sample point. * * @param d A new dHeightfieldDataID created by dGeomHeightfieldDataCreate * * @param pHeightData A pointer to the height data. * @param bCopyHeightData When non-zero the height data is copied to an * internal store. When zero the height data is accessed by reference and * so must persist throughout the lifetime of the heightfield. * * @param width Specifies the total 'width' of the heightfield along * the geom's local x axis. * @param depth Specifies the total 'depth' of the heightfield along * the geom's local z axis. * * @param widthSamples Specifies the number of vertices to sample * along the width of the heightfield. Each vertex has a corresponding * height value which forms the overall shape. * Naturally this value must be at least two or more. * @param depthSamples Specifies the number of vertices to sample * along the depth of the heightfield. * * @param scale A uniform scale applied to all raw height data. * @param offset An offset applied to the scaled height data. * * @param thickness A value subtracted from the lowest height * value which in effect adds an additional cuboid to the base of the * heightfield. This is used to prevent geoms from looping under the * desired terrain and not registering as a collision. Note that the * thickness is not affected by the scale or offset parameters. * * @param bWrap If non-zero the heightfield will infinitely tile in both * directions along the local x and z axes. If zero the heightfield is * bounded from zero to width in the local x axis, and zero to depth in * the local z axis. * * @ingroup collide */ ODE_API void dGeomHeightfieldDataBuildSingle( dHeightfieldDataID d, const float* pHeightData, int bCopyHeightData, dReal width, dReal depth, int widthSamples, int depthSamples, dReal scale, dReal offset, dReal thickness, int bWrap ); /** * @brief Configures a dHeightfieldDataID to use height data in * double precision floating point format. * * Before a dHeightfieldDataID can be used by a geom it must be * configured to specify the format of the height data. * This call specifies that the heightfield data is stored as a rectangular * array of double precision floats representing the height at each * sample point. * * @param d A new dHeightfieldDataID created by dGeomHeightfieldDataCreate * * @param pHeightData A pointer to the height data. * @param bCopyHeightData When non-zero the height data is copied to an * internal store. When zero the height data is accessed by reference and * so must persist throughout the lifetime of the heightfield. * * @param width Specifies the total 'width' of the heightfield along * the geom's local x axis. * @param depth Specifies the total 'depth' of the heightfield along * the geom's local z axis. * * @param widthSamples Specifies the number of vertices to sample * along the width of the heightfield. Each vertex has a corresponding * height value which forms the overall shape. * Naturally this value must be at least two or more. * @param depthSamples Specifies the number of vertices to sample * along the depth of the heightfield. * * @param scale A uniform scale applied to all raw height data. * @param offset An offset applied to the scaled height data. * * @param thickness A value subtracted from the lowest height * value which in effect adds an additional cuboid to the base of the * heightfield. This is used to prevent geoms from looping under the * desired terrain and not registering as a collision. Note that the * thickness is not affected by the scale or offset parameters. * * @param bWrap If non-zero the heightfield will infinitely tile in both * directions along the local x and z axes. If zero the heightfield is * bounded from zero to width in the local x axis, and zero to depth in * the local z axis. * * @ingroup collide */ ODE_API void dGeomHeightfieldDataBuildDouble( dHeightfieldDataID d, const double* pHeightData, int bCopyHeightData, dReal width, dReal depth, int widthSamples, int depthSamples, dReal scale, dReal offset, dReal thickness, int bWrap ); /** * @brief Manually set the minimum and maximum height bounds. * * This call allows you to set explicit min / max values after initial * creation typically for callback heightfields which default to +/- infinity, * or those whose data has changed. This must be set prior to binding with a * geom, as the the AABB is not recomputed after it's first generation. * * @remarks The minimum and maximum values are used to compute the AABB * for the heightfield which is used for early rejection of collisions. * A close fit will yield a more efficient collision check. * * @param d A dHeightfieldDataID created by dGeomHeightfieldDataCreate * @param min_height The new minimum height value. Scale, offset and thickness is then applied. * @param max_height The new maximum height value. Scale and offset is then applied. * @ingroup collide */ ODE_API void dGeomHeightfieldDataSetBounds( dHeightfieldDataID d, dReal minHeight, dReal maxHeight ); /** * @brief Assigns a dHeightfieldDataID to a heightfield geom. * * Associates the given dHeightfieldDataID with a heightfield geom. * This is done without affecting the GEOM_PLACEABLE flag. * * @param g A geom created by dCreateHeightfield * @param d A dHeightfieldDataID created by dGeomHeightfieldDataCreate * @ingroup collide */ ODE_API void dGeomHeightfieldSetHeightfieldData( dGeomID g, dHeightfieldDataID d ); /** * @brief Gets the dHeightfieldDataID bound to a heightfield geom. * * Returns the dHeightfieldDataID associated with a heightfield geom. * * @param g A geom created by dCreateHeightfield * @return The dHeightfieldDataID which may be NULL if none was assigned. * @ingroup collide */ ODE_API dHeightfieldDataID dGeomHeightfieldGetHeightfieldData( dGeomID g ); /* ************************************************************************ */ /* utility functions */ ODE_API void dClosestLineSegmentPoints (const dVector3 a1, const dVector3 a2, const dVector3 b1, const dVector3 b2, dVector3 cp1, dVector3 cp2); ODE_API int dBoxTouchesBox (const dVector3 _p1, const dMatrix3 R1, const dVector3 side1, const dVector3 _p2, const dMatrix3 R2, const dVector3 side2); /* The meaning of flags parameter is the same as in dCollide()*/ ODE_API int dBoxBox (const dVector3 p1, const dMatrix3 R1, const dVector3 side1, const dVector3 p2, const dMatrix3 R2, const dVector3 side2, dVector3 normal, dReal *depth, int *return_code, int flags, dContactGeom *contact, int skip); ODE_API void dInfiniteAABB (dGeomID geom, dReal aabb[6]); /* ************************************************************************ */ /* custom classes */ typedef void dGetAABBFn (dGeomID, dReal aabb[6]); typedef int dColliderFn (dGeomID o1, dGeomID o2, int flags, dContactGeom *contact, int skip); typedef dColliderFn * dGetColliderFnFn (int num); typedef void dGeomDtorFn (dGeomID o); typedef int dAABBTestFn (dGeomID o1, dGeomID o2, dReal aabb[6]); typedef struct dGeomClass { int bytes; dGetColliderFnFn *collider; dGetAABBFn *aabb; dAABBTestFn *aabb_test; dGeomDtorFn *dtor; } dGeomClass; ODE_API int dCreateGeomClass (const dGeomClass *classptr); ODE_API void * dGeomGetClassData (dGeomID); ODE_API dGeomID dCreateGeom (int classnum); /** * @brief Sets a custom collider function for two geom classes. * * @param i The first geom class handled by this collider * @param j The second geom class handled by this collider * @param fn The collider function to use to determine collisions. * @ingroup collide */ ODE_API void dSetColliderOverride (int i, int j, dColliderFn *fn); /* ************************************************************************ */ #ifdef __cplusplus } #endif #endif ode-0.16/include/ode/odeinit.h0000664000175200017520000002273413403272463013150 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* Library initialization/finalization functions. */ #ifndef _ODE_ODEINIT_H_ #define _ODE_ODEINIT_H_ #include #ifdef __cplusplus extern "C" { #endif /* ************************************************************************ */ /* Library initialization */ /** * @defgroup init Library Initialization * * Library initialization functions prepare ODE internal data structures for use * and release allocated resources after ODE is not needed any more. */ /** * @brief Library initialization flags. * * These flags define ODE library initialization options. * * @c dInitFlagManualThreadCleanup indicates that resources allocated in TLS for threads * using ODE are to be cleared by library client with explicit call to @c dCleanupODEAllDataForThread. * If this flag is not specified the automatic resource tracking algorithm is used. * * With automatic resource tracking, On Windows, memory allocated for a thread may * remain not freed for some time after the thread exits. The resources may be * released when one of other threads calls @c dAllocateODEDataForThread. Ultimately, * the resources are released when library is closed with @c dCloseODE. On other * operating systems resources are always released by the thread itself on its exit * or on library closure with @c dCloseODE. * * With manual thread data cleanup mode every collision space object must be * explicitly switched to manual cleanup mode with @c dSpaceSetManualCleanup * after creation. See description of the function for more details. * * If @c dInitFlagManualThreadCleanup was not specified during initialization, * calls to @c dCleanupODEAllDataForThread are not allowed. * * @see dInitODE2 * @see dAllocateODEDataForThread * @see dSpaceSetManualCleanup * @see dCloseODE * @ingroup init */ enum dInitODEFlags { dInitFlagManualThreadCleanup = 0x00000001 /*@< Thread local data is to be cleared explicitly on @c dCleanupODEAllDataForThread function call*/ }; /** * @brief Initializes ODE library. * * @c dInitODE is obsolete. @c dInitODE2 is to be used for library initialization. * * A call to @c dInitODE is equal to the following initialization sequence * @code * dInitODE2(0); * dAllocateODEDataForThread(dAllocateMaskAll); * @endcode * * @see dInitODE2 * @see dAllocateODEDataForThread * @ingroup init */ ODE_API void dInitODE(void); /** * @brief Initializes ODE library. * @param uiInitFlags Initialization options bitmask * @return A nonzero if initialization succeeded and zero otherwise. * * This function must be called to initialize ODE library before first use. If * initialization succeeds the function may not be called again until library is * closed with a call to @c dCloseODE. * * The @a uiInitFlags parameter specifies initialization options to be used. These * can be combination of zero or more @c dInitODEFlags flags. * * @note * If @c dInitFlagManualThreadCleanup flag is used for initialization, * @c dSpaceSetManualCleanup must be called to set manual cleanup mode for every * space object right after creation. Failure to do so may lead to resource leaks. * * @see dInitODEFlags * @see dCloseODE * @see dSpaceSetManualCleanup * @ingroup init */ ODE_API int dInitODE2(unsigned int uiInitFlags/*=0*/); /** * @brief ODE data allocation flags. * * These flags are used to indicate which data is to be pre-allocated in call to * @c dAllocateODEDataForThread. * * @c dAllocateFlagBasicData tells to allocate the basic data set required for * normal library operation. This flag is equal to zero and is always implicitly * included. * * @c dAllocateFlagCollisionData tells that collision detection data is to be allocated. * Collision detection functions may not be called if the data has not be allocated * in advance. If collision detection is not going to be used, it is not necessary * to specify this flag. * * @c dAllocateMaskAll is a mask that can be used for for allocating all possible * data in cases when it is not known what exactly features of ODE will be used. * The mask may not be used in combination with other flags. It is guaranteed to * include all the current and future legal allocation flags. However, mature * applications should use explicit flags they need rather than allocating everything. * * @see dAllocateODEDataForThread * @ingroup init */ enum dAllocateODEDataFlags { dAllocateFlagBasicData = 0, /*@< Allocate basic data required for library to operate*/ dAllocateFlagCollisionData = 0x00000001, /*@< Allocate data for collision detection*/ dAllocateMaskAll = ~0 /*@< Allocate all the possible data that is currently defined or will be defined in the future.*/ }; /** * @brief Allocate thread local data to allow the thread calling ODE. * @param uiAllocateFlags Allocation options bitmask. * @return A nonzero if allocation succeeded and zero otherwise. * * The function is required to be called for every thread that is going to use * ODE. This function allocates the data that is required for accessing ODE from * current thread along with optional data required for particular ODE subsystems. * * @a uiAllocateFlags parameter can contain zero or more flags from @c dAllocateODEDataFlags * enumerated type. Multiple calls with different allocation flags are allowed. * The flags that are already allocated are ignored in subsequent calls. If zero * is passed as the parameter, it means to only allocate the set of most important * data the library can not operate without. * * If the function returns failure status it means that none of the requested * data has been allocated. The client may retry allocation attempt with the same * flags when more system resources are available. * * @see dAllocateODEDataFlags * @see dCleanupODEAllDataForThread * @ingroup init */ ODE_API int dAllocateODEDataForThread(unsigned int uiAllocateFlags); /** * @brief Free thread local data that was allocated for current thread. * * If library was initialized with @c dInitFlagManualThreadCleanup flag the function * is required to be called on exit of every thread that was calling @c dAllocateODEDataForThread. * Failure to call @c dCleanupODEAllDataForThread may result in some resources remaining * not freed until program exit. The function may also be called when ODE is still * being used to release resources allocated for all the current subsystems and * possibly proceed with data pre-allocation for other subsystems. * * The function can safely be called several times in a row. The function can be * called without prior invocation of @c dAllocateODEDataForThread. The function * may not be called before ODE is initialized with @c dInitODE2 or after library * has been closed with @c dCloseODE. A call to @c dCloseODE implicitly releases * all the thread local resources that might be allocated for all the threads that * were using ODE. * * If library was initialized without @c dInitFlagManualThreadCleanup flag * @c dCleanupODEAllDataForThread must not be called. * * @see dAllocateODEDataForThread * @see dInitODE2 * @see dCloseODE * @ingroup init */ ODE_API void dCleanupODEAllDataForThread(); /** * @brief Close ODE after it is not needed any more. * * The function is required to be called when program does not need ODE features any more. * The call to @c dCloseODE releases all the resources allocated for library * including all the thread local data that might be allocated for all the threads * that were using ODE. * * @c dCloseODE is a paired function for @c dInitODE2 and must only be called * after successful library initialization. * * @note Important! * Make sure that all the threads that were using ODE have already terminated * before calling @c dCloseODE. In particular it is not allowed to call * @c dCleanupODEAllDataForThread after @c dCloseODE. * * @see dInitODE2 * @see dCleanupODEAllDataForThread * @ingroup init */ ODE_API void dCloseODE(void); #ifdef __cplusplus } /* extern "C" */ #endif #endif /* _ODE_ODEINIT_H_ */ ode-0.16/include/ode/error.h0000664000175200017520000000531513403272463012642 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* this comes from the `reuse' library. copy any changes back to the source */ #ifndef _ODE_ERROR_H_ #define _ODE_ERROR_H_ #include #ifdef __cplusplus extern "C" { #endif /* all user defined error functions have this type. error and debug functions * should not return. */ typedef void dMessageFunction (int errnum, const char *msg, va_list ap); /* set a new error, debug or warning handler. if fn is 0, the default handlers * are used. */ ODE_API void dSetErrorHandler (dMessageFunction *fn); ODE_API void dSetDebugHandler (dMessageFunction *fn); ODE_API void dSetMessageHandler (dMessageFunction *fn); /* return the current error, debug or warning handler. if the return value is * 0, the default handlers are in place. */ ODE_API dMessageFunction *dGetErrorHandler(void); ODE_API dMessageFunction *dGetDebugHandler(void); ODE_API dMessageFunction *dGetMessageHandler(void); /* generate a fatal error, debug trap or a message. */ ODE_API void ODE_NORETURN dError (int num, const char *msg, ...); ODE_API void ODE_NORETURN dDebug (int num, const char *msg, ...); ODE_API void dMessage (int num, const char *msg, ...); #ifdef __cplusplus } #endif #endif ode-0.16/include/ode/version.h0000664000175200017520000000012513403272677013177 00000000000000#ifndef _ODE_VERSION_H_ #define _ODE_VERSION_H_ #define dODE_VERSION "0.16" #endif ode-0.16/include/ode/cooperative.h0000664000175200017520000002144213403272463014030 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_COOPERATIVE_H_ #define _ODE_COOPERATIVE_H_ #include #include #ifdef __cplusplus extern "C" { #endif /** * @defgroup coop Cooperative Algorithms * * Algorithms implemented as multiple threads doing work cooperatively. */ struct dxCooperative; struct dxResourceRequirements; struct dxResourceContainer; /** * @brief A container for cooperative algorithms shared context * * The Cooperative is a container for cooperative algorithms shared context. * At present it contains threading object (either a real one or a defaulted * self-threading). * * Cooperative use in functions performing computations must be serialized. That is, * functions referring to a single instance of Cooperative object must not be called in * parallel. */ typedef struct dxCooperative *dCooperativeID; /** * @brief A container for resource requirements information * * The ResourceRequirements object is a container for descriptive information * regarding what resources (memory, synchronization objects, etc.) need to be * allocated for particular computations. The object can be used for accumulating * resource requirement maxima over multiple functions and then allocating resources * that would suffice for any of those function calls. * * ResourceRequirements objects maintain relations to Cooperative objects since * amounts of resources that could be required can depend on characteristics of * shared context, e.g. on maximal number of threads in the threading object. * * @ingroup coop * @see dCooperativeID * @see dResourceContainerID */ typedef struct dxResourceRequirements *dResourceRequirementsID; /** * @brief A container for algorithm allocated resources * * The ResourceContainer object can contain resources allocated according to information * in a ResourceRequirements. The resources inherit link to the threading object * from the requirements they are allocated according to. * * @ingroup coop * @see dResourceRequirementsID * @see dCooperativeID */ typedef struct dxResourceContainer *dResourceContainerID; /** * @brief Creates a Cooperative object related to the specified threading. * * NULL's are allowed for the threading. In this case the default (global) self-threading * object will be used. * * Use @c dCooperativeDestroy to destroy the object. The Cooperative object must exist * until after all the objects referencing it are destroyed. * * @param functionInfo The threading functions to use * @param threadingImpl The threading implementation object to use * @returns The Cooperative object instance or NULL if allocation fails. * @ingroup coop * @see dCooperativeDestroy */ ODE_API dCooperativeID dCooperativeCreate(const dThreadingFunctionsInfo *functionInfo/*=NULL*/, dThreadingImplementationID threadingImpl/*=NULL*/); /** * @brief Destroys Cooperative object. * * The Cooperative object can only be destroyed after all the objects referencing it. * * @param cooperative A Cooperative object to be deleted (NULL is allowed) * @ingroup coop * @see dCooperativeCreate */ ODE_API void dCooperativeDestroy(dCooperativeID cooperative); /** * @brief Creates a ResourceRequirements object related to a Cooperative. * * The object is purely descriptive and does not contain any resources by itself. * The actual resources are allocated by means of ResourceContainer object. * * The object is created with empty requirements. It can be then used to accumulate * requirements for one or more function calls and can be cloned or merged with others. * The actual requirements information is added to the object by computation related * functions. * * Use @c dResourceRequirementsDestroy to delete the object when it is no longer needed. * * @param cooperative A Cooperative object to be used * @returns The ResourceRequirements object instance or NULL if allocation fails * @ingroup coop * @see dResourceRequirementsDestroy * @see dResourceRequirementsClone * @see dResourceRequirementsMergeIn * @see dCooperativeCreate * @see dResourceContainerAcquire */ ODE_API dResourceRequirementsID dResourceRequirementsCreate(dCooperativeID cooperative); /** * @brief Destroys ResourceRequirements object. * * The ResourceRequirements object can be destroyed at any time with no regards * to other objects' lifetime. * * @param requirements A ResourceRequirements object to be deleted (NULL is allowed) * @ingroup coop * @see dResourceRequirementsCreate */ ODE_API void dResourceRequirementsDestroy(dResourceRequirementsID requirements); /** * @brief Clones ResourceRequirements object. * * The function creates a copy of the ResourceRequirements object with all the * contents and the relation to Cooperative matching. The object passed in * the parameter is not changed. * * The object created with the function must later be destroyed with @c dResourceRequirementsDestroy. * * @param requirements A ResourceRequirements object to be cloned * @returns A handle to the new object or NULL if allocation fails * @ingroup coop * @see dResourceRequirementsCreate * @see dResourceRequirementsDestroy * @see dResourceRequirementsMergeIn */ ODE_API dResourceRequirementsID dResourceRequirementsClone(/*const */dResourceRequirementsID requirements); /** * @brief Merges one ResourceRequirements object into another ResourceRequirements object. * * The function updates @a summaryRequirements requirements to be also sufficient * for the purposes @a extraRequirements could be used for. The @a extraRequirements * object is not changed. The both objects should normally have had been created * with the same Cooperative object. * * @param summaryRequirements A ResourceRequirements object to be changed * @param extraRequirements A ResourceRequirements the requirements to be taken from * @ingroup coop * @see dResourceRequirementsCreate * @see dResourceRequirementsDestroy * @see dResourceRequirementsClone */ ODE_API void dResourceRequirementsMergeIn(dResourceRequirementsID summaryRequirements, /*const */dResourceRequirementsID extraRequirements); /** * @brief Allocates resources as specified in ResourceRequirements object. * * The ResourceContainer object can be used in cooperative computation algorithms. * * The same @a requirements object can be passed to many resource allocations * (with or without modifications) and can be deleted immediately, without waiting * for the ResourceContainer object destruction. * * Use @c dResourceContainerDestroy to delete the object and release the resources * when they are no longer needed. * * @param requirements The ResourceRequirements object to allocate resources according to * @returns A ResourceContainer object instance with the resources allocated or NULL if allocation fails * @ingroup coop * @see dResourceContainerDestroy * @see dResourceRequirementsCreate */ ODE_API dResourceContainerID dResourceContainerAcquire(/*const */dResourceRequirementsID requirements); /** * @brief Destroys ResourceContainer object and releases resources allocated in it. * * @param resources A ResourceContainer object to be deleted (NULL is allowed) * @ingroup coop * @see dResourceContainerAcquire */ ODE_API void dResourceContainerDestroy(dResourceContainerID resources); #ifdef __cplusplus } // extern "C" #endif #endif // #ifndef _ODE_COOPERATIVE_H_ ode-0.16/include/ode/odeconfig.h0000664000175200017520000001425613403272463013452 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_ODECONFIG_H_ #define _ODE_ODECONFIG_H_ /* Pull in the standard headers */ #include #include #include #include #include #include #include #include #include #if defined(ODE_DLL) || defined(ODE_LIB) #define __ODE__ #endif /* Define a DLL export symbol for those platforms that need it */ #if defined(_MSC_VER) || (defined(__GNUC__) && defined(_WIN32)) #if defined(ODE_DLL) #define ODE_API __declspec(dllexport) #else #define ODE_API #endif #endif #if !defined(ODE_API) #define ODE_API #endif #if defined(_MSC_VER) # define ODE_API_DEPRECATED __declspec(deprecated) #elif defined (__GNUC__) && ( (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)) ) # define ODE_API_DEPRECATED __attribute__((__deprecated__)) #else # define ODE_API_DEPRECATED #endif #define ODE_PURE_INLINE static __inline #define ODE_INLINE __inline #if defined(__cplusplus) #define ODE_EXTERN_C extern "C" #else #define ODE_EXTERN_C #endif #if defined(__GNUC__) #define ODE_NORETURN __attribute__((noreturn)) #elif defined(_MSC_VER) #define ODE_NORETURN __declspec(noreturn) #else // #if !defined(_MSC_VER) #define ODE_NORETURN #endif // #if !defined(__GNUC__) /* Well-defined common data types...need to define for 64 bit systems */ #if defined(__aarch64__) #include typedef int64_t dint64; typedef uint64_t duint64; typedef int32_t dint32; typedef uint32_t duint32; typedef int16_t dint16; typedef uint16_t duint16; typedef int8_t dint8; typedef uint8_t duint8; typedef intptr_t dintptr; typedef uintptr_t duintptr; typedef ptrdiff_t ddiffint; typedef size_t dsizeint; #elif defined(_M_IA64) || defined(__ia64__) || defined(_M_AMD64) || defined(__x86_64__) #define X86_64_SYSTEM 1 #if defined(_MSC_VER) typedef __int64 dint64; typedef unsigned __int64 duint64; #else #if defined(_LP64) typedef long dint64; typedef unsigned long duint64; #else typedef long long dint64; typedef unsigned long long duint64; #endif #endif typedef int dint32; typedef unsigned int duint32; typedef short dint16; typedef unsigned short duint16; typedef signed char dint8; typedef unsigned char duint8; typedef dint64 dintptr; typedef duint64 duintptr; typedef dint64 ddiffint; typedef duint64 dsizeint; #else #if defined(_MSC_VER) typedef __int64 dint64; typedef unsigned __int64 duint64; #else typedef long long dint64; typedef unsigned long long duint64; #endif typedef int dint32; typedef unsigned int duint32; typedef short dint16; typedef unsigned short duint16; typedef signed char dint8; typedef unsigned char duint8; typedef dint32 dintptr; typedef duint32 duintptr; typedef dint32 ddiffint; typedef duint32 dsizeint; #endif /* Define the dInfinity macro */ #ifdef INFINITY #ifdef dSINGLE #define dInfinity ((float)INFINITY) #else #define dInfinity ((double)INFINITY) #endif #elif defined(HUGE_VAL) #ifdef dSINGLE #ifdef HUGE_VALF #define dInfinity HUGE_VALF #else #define dInfinity ((float)HUGE_VAL) #endif #else #define dInfinity HUGE_VAL #endif #else #ifdef dSINGLE #define dInfinity ((float)(1.0/0.0)) #else #define dInfinity (1.0/0.0) #endif #endif /* Define the dNaN macro */ #if defined(NAN) #define dNaN NAN #elif defined(__GNUC__) #define dNaN ({ union { duint32 m_ui; float m_f; } un; un.m_ui = 0x7FC00000; un.m_f; }) #elif defined(__cplusplus) union _dNaNUnion { _dNaNUnion(): m_ui(0x7FC00000) {} duint32 m_ui; float m_f; }; #define dNaN (_dNaNUnion().m_f) #else #ifdef dSINGLE #define dNaN ((float)(dInfinity - dInfinity)) #else #define dNaN (dInfinity - dInfinity) #endif #endif /* Visual C does not define these functions */ #if defined(_MSC_VER) #define _ode_copysignf(x, y) ((float)_copysign(x, y)) #define _ode_copysign(x, y) _copysign(x, y) #define _ode_nextafterf(x, y) _nextafterf(x, y) #define _ode_nextafter(x, y) _nextafter(x, y) #if !defined(_WIN64) && defined(dSINGLE) #define _ODE__NEXTAFTERF_REQUIRED ODE_EXTERN_C float _nextafterf(float x, float y); #endif #else #define _ode_copysignf(x, y) copysignf(x, y) #define _ode_copysign(x, y) copysign(x, y) #define _ode_nextafterf(x, y) nextafterf(x, y) #define _ode_nextafter(x, y) nextafter(x, y) #endif #endif ode-0.16/include/ode/precision.h.in0000664000175200017520000000042213403272463014103 00000000000000#ifndef _ODE_PRECISION_H_ #define _ODE_PRECISION_H_ /* Define dSINGLE for single precision, dDOUBLE for double precision, * but never both! */ #if defined(dIDESINGLE) #define dSINGLE #elif defined(dIDEDOUBLE) #define dDOUBLE #else #define @ODE_PRECISION@ #endif #endif ode-0.16/include/ode/matrix_coop.h0000664000175200017520000003322313403272463014034 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_MATRIX_COOP_H_ #define _ODE_MATRIX_COOP_H_ #include #include #include #ifdef __cplusplus extern "C" { #endif /** * @defgroup matrix_coop Matrix Cooperative Algorithms * * Cooperative algorithms operating on matrices and vectors. * * @ingroup coop */ /** * @brief Estimates resource requirements for a @c dCooperativelyFactorLDLT call * * The function updates the contents of @a requirements to also suffice for calling * @c dCooperativelyFactorLDLT with the given parameters. * * Note: The requirements that could have already been in the @a requirements parameter * are never decreased. * * @param requirements The ResourceRequirements object to update * @param maximalAllowedThreadCount Maximal value of allowedThreadCount parameter that is going to be used * @param maximalRowCount Maximal value of rowCount parameter that is going to be used * @ingroup matrix_coop * @see dCooperativelyFactorLDLT * @see dResourceRequirementsCreate */ ODE_API void dEstimateCooperativelyFactorLDLTResourceRequirements(dResourceRequirementsID requirements, unsigned maximalAllowedThreadCount, unsigned maximalRowCount); /** * @brief Cooperatively factorizes a matrix `A' into L*D*L' * * The function factorizes a matrix `A' into L*D*L', where `L' is lower triangular with ones on * the diagonal, and `D' is diagonal. * @a A is a rowCount*rowCount matrix stored by rows, with a leading dimension of @a rowCount rounded * up at least to 4 elements. `L; is written into the strict lower triangle of @a A * (the ones are not written) and the reciprocal of the diagonal elements of `D' are written into @a d. * * The @a resources must have had been allocated from a ResourceRequirements object * estimated in @c dEstimateCooperativelyFactorLDLTResourceRequirements. * * The operation is performed cooperatively by up to @a allowedThreadCount threads * from thread pool available in @a resources. The threading must must not be simultaneously * used (via other @c dResourceContainerID instances) in other calls that employ its features. * * @param resources The resources allocated for the function * @param allowedThreadCount Maximum thread count to use (the actual thread count could be less, depending on other parameters) * @param A The `A' matrix * @param d The `d' vector * @param rowCount The row count in @a A and @a d * @param rowskip The actual number of elements to be added to skip to next row in @a A * @ingroup matrix_coop * @see dEstimateCooperativelyFactorLDLTResourceRequirements * @see dResourceContainerAcquire * @see dCooperativelySolveLDLT */ ODE_API void dCooperativelyFactorLDLT(dResourceContainerID resources, unsigned allowedThreadCount, dReal *A, dReal *d, unsigned rowCount, unsigned rowSkip); /** * @brief Estimates resource requirements for a @c dCooperativelySolveLDLT call * * The function updates the contents of @a requirements to also suffice for calling * @c dCooperativelySolveLDLT with the given parameters. * * Note: The requirements that could have already been in the @a requirements parameter * are never decreased. * * @param requirements The ResourceRequirements object to update * @param maximalAllowedThreadCount Maximal value of allowedThreadCount parameter that is going to be used * @param maximalRowCount Maximal value of rowCount parameter that is going to be used * @ingroup matrix_coop * @see dCooperativelySolveLDLT * @see dResourceRequirementsCreate */ ODE_API void dEstimateCooperativelySolveLDLTResourceRequirements(dResourceRequirementsID requirements, unsigned maximalAllowedThreadCount, unsigned maximalRowCount); /** * @brief Cooperatively solves L*D*L'*x=b * * Given `L', a rowCount*rowCount lower triangular matrix with ones on the diagonal, * and `d', a rowCount*1 vector of the reciprocal diagonal elements of a rowCount*rowCount matrix * D, the function solves L*D*L'*x=b where `x' and `b' are rowCount*1. * The leading dimension of @a L is @a rowSkip. The resulting vector `x' overwrites @a b. * * The @a resources must have had been allocated from a ResourceRequirements object * estimated in @c dEstimateCooperativelySolveLDLTResourceRequirements. * * The operation is performed cooperatively by up to @a allowedThreadCount threads * from thread pool available in @a resources. The threading must must not be simultaneously * used (via other @c dResourceContainerID instances) in other calls that employ its features. * * @param resources The resources allocated for the function * @param allowedThreadCount Maximum thread count to use (the actual thread count could be less, depending on other parameters) * @param L The `L' matrix * @param d The `d' vector * @param b The `b' vector; also the result is stored here * @param rowCount The row count in @a L, @a d and @a b * @param rowskip The actual number of elements to be added to skip to next row in @a L * @ingroup matrix_coop * @see dEstimateCooperativelySolveLDLTResourceRequirements * @see dResourceContainerAcquire * @see dCooperativelyFactorLDLT */ ODE_API void dCooperativelySolveLDLT(dResourceContainerID resources, unsigned allowedThreadCount, const dReal *L, const dReal *d, dReal *b, unsigned rowCount, unsigned rowSkip); /** * @brief Estimates resource requirements for a @c dCooperativelySolveL1Straight call * * The function updates the contents of @a requirements to also suffice for calling * @c dCooperativelySolveL1Straight with the given parameters. * * Note: The requirements that could have already been in the @a requirements parameter * are never decreased. * * @param requirements The ResourceRequirements object to update * @param maximalAllowedThreadCount Maximal value of allowedThreadCount parameter that is going to be used * @param maximalRowCount Maximal value of rowCount parameter that is going to be used * @ingroup matrix_coop * @see dCooperativelySolveL1Straight * @see dResourceRequirementsCreate */ ODE_API void dEstimateCooperativelySolveL1StraightResourceRequirements(dResourceRequirementsID requirements, unsigned maximalAllowedThreadCount, unsigned maximalRowCount); /** * @brief Cooperatively solves L*x=b * * The function solves L*x=b, where `L' is rowCount*rowCount lower triangular with ones on the diagonal, * and `x', `b' are rowCount*1. The leading dimension of @a L is @a rowSkip. * @a b is overwritten with `x'. * * The @a resources must have had been allocated from a ResourceRequirements object * estimated in @c dEstimateCooperativelySolveL1StraightResourceRequirements. * * The operation is performed cooperatively by up to @a allowedThreadCount threads * from thread pool available in @a resources. The threading must must not be simultaneously * used (via other @c dResourceContainerID instances) in other calls that employ its features. * * @param resources The resources allocated for the function * @param allowedThreadCount Maximum thread count to use (the actual thread count could be less, depending on other parameters) * @param L The `L' matrix * @param b The `b' vector; also the result is stored here * @param rowCount The row count in @a L and @a b * @param rowskip The actual number of elements to be added to skip to next row in @a L * @ingroup matrix_coop * @see dEstimateCooperativelySolveL1StraightResourceRequirements * @see dResourceContainerAcquire * @see dCooperativelyFactorLDLT */ ODE_API void dCooperativelySolveL1Straight(dResourceContainerID resources, unsigned allowedThreadCount, const dReal *L, dReal *b, unsigned rowCount, unsigned rowSkip); /** * @brief Estimates resource requirements for a @c dCooperativelySolveL1Transposed call * * The function updates the contents of @a requirements to also suffice for calling * @c dCooperativelySolveL1Transposed with the given parameters. * * Note: The requirements that could have already been in the @a requirements parameter * are never decreased. * * @param requirements The ResourceRequirements object to update * @param maximalAllowedThreadCount Maximal value of allowedThreadCount parameter that is going to be used * @param maximalRowCount Maximal value of rowCount parameter that is going to be used * @ingroup matrix_coop * @see dCooperativelySolveL1Transposed * @see dResourceRequirementsCreate */ ODE_API void dEstimateCooperativelySolveL1TransposedResourceRequirements(dResourceRequirementsID requirements, unsigned maximalAllowedThreadCount, unsigned maximalRowCount); /** * @brief Cooperatively solves L'*x=b * * The function solves L'*x=b, where `L' is rowCount*rowCount lower triangular with ones on the diagonal, * and `x', b are rowCount*1. The leading dimension of @a L is @a rowSkip. * @a b is overwritten with `x'. * * The @a resources must have had been allocated from a ResourceRequirements object * estimated in @c dEstimateCooperativelySolveL1TransposedResourceRequirements. * * The operation is performed cooperatively by up to @a allowedThreadCount threads * from thread pool available in @a resources. The threading must must not be simultaneously * used (via other @c dResourceContainerID instances) in other calls that employ its features. * * @param resources The resources allocated for the function * @param allowedThreadCount Maximum thread count to use (the actual thread count could be less, depending on other parameters) * @param L The `L' matrix * @param b The `b' vector; also the result is stored here * @param rowCount The row count in @a L and @a b * @param rowskip The actual number of elements to be added to skip to next row in @a L * @ingroup matrix_coop * @see dEstimateCooperativelySolveL1TransposedResourceRequirements * @see dResourceContainerAcquire * @see dCooperativelyFactorLDLT */ ODE_API void dCooperativelySolveL1Transposed(dResourceContainerID resources, unsigned allowedThreadCount, const dReal *L, dReal *b, unsigned rowCount, unsigned rowSkip); /** * @brief Estimates resource requirements for a @c dCooperativelyScaleVector call * * The function updates the contents of @a requirements to also suffice for calling * @c dCooperativelyScaleVector with the given parameters. * * Note: The requirements that could have already been in the @a requirements parameter * are never decreased. * * @param requirements The ResourceRequirements object to update * @param maximalAllowedThreadCount Maximal value of allowedThreadCount parameter that is going to be used * @param maximalElementCount Maximal value of elementCount parameter that is going to be used * @ingroup matrix_coop * @see dCooperativelyScaleVector * @see dResourceRequirementsCreate */ ODE_API void dEstimateCooperativelyScaleVectorResourceRequirements(dResourceRequirementsID requirements, unsigned maximalAllowedThreadCount, unsigned maximalElementCount); /** * @brief Multiplies elements of one vector by corresponding element of another one * * In matlab syntax, the operation performed is: dataVector(1:elementCount) = dataVector(1:elementCount) .* scaleVector(1:elementCount) * * The @a resources must have had been allocated from a ResourceRequirements object * estimated in @c dEstimateCooperativelyScaleVectorResourceRequirements. * * The operation is performed cooperatively by up to @a allowedThreadCount threads * from thread pool available in @a resources. The threading must must not be simultaneously * used (via other @c dResourceContainerID instances) in other calls that employ its features. * * @param resources The resources allocated for the function * @param allowedThreadCount Maximum thread count to use (the actual thread count could be less, depending on other parameters) * @param dataVector The vector to be scaled in place * @param scaleVector The scale vector * @param elementCount The number of elements in @a dataVector and @a scaleVector * @ingroup matrix_coop * @see dEstimateCooperativelyScaleVectorResourceRequirements * @see dResourceContainerAcquire * @see dCooperativelyFactorLDLT */ ODE_API void dCooperativelyScaleVector(dResourceContainerID resources, unsigned allowedThreadCount, dReal *dataVector, const dReal *scaleVector, unsigned elementCount); #ifdef __cplusplus } // extern "C" #endif #endif // #ifndef _ODE_MATRIX_COOP_H_ ode-0.16/include/ode/version.h.in0000664000175200017520000000013613403272463013577 00000000000000#ifndef _ODE_VERSION_H_ #define _ODE_VERSION_H_ #define dODE_VERSION "@ODE_VERSION@" #endif ode-0.16/include/ode/ode.h0000664000175200017520000000442213403272463012256 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_ODE_H_ #define _ODE_ODE_H_ /* include *everything* here */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __cplusplus # include # include #endif #endif ode-0.16/include/ode/mass.h0000664000175200017520000001247513403272463012461 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_MASS_H_ #define _ODE_MASS_H_ #include #ifdef __cplusplus extern "C" { #endif struct dMass; typedef struct dMass dMass; /** * Check if a mass structure has valid value. * The function check if the mass and innertia matrix are positive definits * * @param m A mass structure to check * * @return 1 if both codition are met */ ODE_API int dMassCheck(const dMass *m); ODE_API void dMassSetZero (dMass *); ODE_API void dMassSetParameters (dMass *, dReal themass, dReal cgx, dReal cgy, dReal cgz, dReal I11, dReal I22, dReal I33, dReal I12, dReal I13, dReal I23); ODE_API void dMassSetSphere (dMass *, dReal density, dReal radius); ODE_API void dMassSetSphereTotal (dMass *, dReal total_mass, dReal radius); ODE_API void dMassSetCapsule (dMass *, dReal density, int direction, dReal radius, dReal length); ODE_API void dMassSetCapsuleTotal (dMass *, dReal total_mass, int direction, dReal radius, dReal length); ODE_API void dMassSetCylinder (dMass *, dReal density, int direction, dReal radius, dReal length); ODE_API void dMassSetCylinderTotal (dMass *, dReal total_mass, int direction, dReal radius, dReal length); ODE_API void dMassSetBox (dMass *, dReal density, dReal lx, dReal ly, dReal lz); ODE_API void dMassSetBoxTotal (dMass *, dReal total_mass, dReal lx, dReal ly, dReal lz); ODE_API void dMassSetTrimesh (dMass *, dReal density, dGeomID g); ODE_API void dMassSetTrimeshTotal (dMass *m, dReal total_mass, dGeomID g); ODE_API void dMassAdjust (dMass *, dReal newmass); ODE_API void dMassTranslate (dMass *, dReal x, dReal y, dReal z); ODE_API void dMassRotate (dMass *, const dMatrix3 R); ODE_API void dMassAdd (dMass *a, const dMass *b); /* Backwards compatible API */ ODE_API_DEPRECATED ODE_API void dMassSetCappedCylinder(dMass *a, dReal b, int c, dReal d, dReal e); ODE_API_DEPRECATED ODE_API void dMassSetCappedCylinderTotal(dMass *a, dReal b, int c, dReal d, dReal e); struct dMass { dReal mass; dVector3 c; dMatrix3 I; #ifdef __cplusplus dMass() { dMassSetZero (this); } void setZero() { dMassSetZero (this); } void setParameters (dReal themass, dReal cgx, dReal cgy, dReal cgz, dReal I11, dReal I22, dReal I33, dReal I12, dReal I13, dReal I23) { dMassSetParameters (this,themass,cgx,cgy,cgz,I11,I22,I33,I12,I13,I23); } void setSphere (dReal density, dReal radius) { dMassSetSphere (this,density,radius); } void setSphereTotal (dReal total, dReal radius) { dMassSetSphereTotal (this,total,radius); } void setCapsule (dReal density, int direction, dReal radius, dReal length) { dMassSetCapsule (this,density,direction,radius,length); } void setCapsuleTotal (dReal total, int direction, dReal radius, dReal length) { dMassSetCapsule (this,total,direction,radius,length); } void setCylinder(dReal density, int direction, dReal radius, dReal length) { dMassSetCylinder (this,density,direction,radius,length); } void setCylinderTotal(dReal total, int direction, dReal radius, dReal length) { dMassSetCylinderTotal (this,total,direction,radius,length); } void setBox (dReal density, dReal lx, dReal ly, dReal lz) { dMassSetBox (this,density,lx,ly,lz); } void setBoxTotal (dReal total, dReal lx, dReal ly, dReal lz) { dMassSetBoxTotal (this,total,lx,ly,lz); } void setTrimesh(dReal density, dGeomID g) { dMassSetTrimesh (this, density, g); } void setTrimeshTotal(dReal total, dGeomID g) { dMassSetTrimeshTotal (this, total, g); } void adjust (dReal newmass) { dMassAdjust (this,newmass); } void translate (dReal x, dReal y, dReal z) { dMassTranslate (this,x,y,z); } void rotate (const dMatrix3 R) { dMassRotate (this,R); } void add (const dMass *b) { dMassAdd (this,b); } #endif }; #ifdef __cplusplus } #endif #endif ode-0.16/include/ode/collision_trimesh.h0000664000175200017520000003007113403272463015234 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* * TriMesh code by Erwin de Vries. * * Trimesh data. * This is where the actual vertexdata (pointers), and BV tree is stored. * Vertices should be single precision! * This should be more sophisticated, so that the user can easyly implement * another collision library, but this is a lot of work, and also costs some * performance because some data has to be copied. */ #ifndef _ODE_COLLISION_TRIMESH_H_ #define _ODE_COLLISION_TRIMESH_H_ #ifdef __cplusplus extern "C" { #endif /* * Data storage for triangle meshes. */ struct dxTriMeshData; typedef struct dxTriMeshData* dTriMeshDataID; typedef enum { dMTV__MIN, dMTV_FIRST = dMTV__MIN, dMTV_SECOND, dMTV_THIRD, dMTV__MAX, } dMeshTriangleVertex; /* * These don't make much sense now, but they will later when we add more * features. */ ODE_API dTriMeshDataID dGeomTriMeshDataCreate(void); ODE_API void dGeomTriMeshDataDestroy(dTriMeshDataID g); /* * The values of data_id that can be used with dGeomTriMeshDataSet/dGeomTriMeshDataGet */ enum { dTRIMESHDATA__MIN, dTRIMESHDATA_FACE_NORMALS = dTRIMESHDATA__MIN, dTRIMESHDATA_USE_FLAGS, dTRIMESHDATA__MAX, #ifndef TRIMESH_FACE_NORMALS // Define this name during the header inclusion if you need it for something else // Included for backward compatibility -- please use the corrected name above. Sorry. TRIMESH_FACE_NORMALS = dTRIMESHDATA_FACE_NORMALS, #endif }; /* * The flags of the dTRIMESHDATA_USE_FLAGS data elements */ enum { dMESHDATAUSE_EDGE1 = 0x01, dMESHDATAUSE_EDGE2 = 0x02, dMESHDATAUSE_EDGE3 = 0x04, dMESHDATAUSE_VERTEX1 = 0x08, dMESHDATAUSE_VERTEX2 = 0x10, dMESHDATAUSE_VERTEX3 = 0x20, }; /* * Set and get the TriMeshData additional data * Note: The data is NOT COPIED on assignment */ ODE_API void dGeomTriMeshDataSet(dTriMeshDataID g, int data_id, void *in_data); ODE_API void *dGeomTriMeshDataGet(dTriMeshDataID g, int data_id); ODE_API void *dGeomTriMeshDataGet2(dTriMeshDataID g, int data_id, dsizeint *pout_size/*=NULL*/); /** * We need to set the last transform after each time step for * accurate collision response. These functions get and set that transform. * It is stored per geom instance, rather than per dTriMeshDataID. */ ODE_API void dGeomTriMeshSetLastTransform( dGeomID g, const dMatrix4 last_trans ); ODE_API const dReal* dGeomTriMeshGetLastTransform( dGeomID g ); /* * Build a TriMesh data object with single precision vertex data. */ ODE_API void dGeomTriMeshDataBuildSingle(dTriMeshDataID g, const void* Vertices, int VertexStride, int VertexCount, const void* Indices, int IndexCount, int TriStride); /* same again with a normals array (used as trimesh-trimesh optimization) */ ODE_API void dGeomTriMeshDataBuildSingle1(dTriMeshDataID g, const void* Vertices, int VertexStride, int VertexCount, const void* Indices, int IndexCount, int TriStride, const void* Normals); /* * Build a TriMesh data object with double precision vertex data. */ ODE_API void dGeomTriMeshDataBuildDouble(dTriMeshDataID g, const void* Vertices, int VertexStride, int VertexCount, const void* Indices, int IndexCount, int TriStride); /* same again with a normals array (used as trimesh-trimesh optimization) */ ODE_API void dGeomTriMeshDataBuildDouble1(dTriMeshDataID g, const void* Vertices, int VertexStride, int VertexCount, const void* Indices, int IndexCount, int TriStride, const void* Normals); /* * Simple build. Single/double precision based on dSINGLE/dDOUBLE! */ ODE_API void dGeomTriMeshDataBuildSimple(dTriMeshDataID g, const dReal* Vertices, int VertexCount, const dTriIndex* Indices, int IndexCount); /* same again with a normals array (used as trimesh-trimesh optimization) */ ODE_API void dGeomTriMeshDataBuildSimple1(dTriMeshDataID g, const dReal* Vertices, int VertexCount, const dTriIndex* Indices, int IndexCount, const int* Normals); /* * Data preprocessing build request flags. */ enum { dTRIDATAPREPROCESS_BUILD__MIN, dTRIDATAPREPROCESS_BUILD_CONCAVE_EDGES = dTRIDATAPREPROCESS_BUILD__MIN, // Used to optimize OPCODE trimesh-capsule collisions; allocates 1 byte per triangle; no extra data associated dTRIDATAPREPROCESS_BUILD_FACE_ANGLES, // Used to aid trimesh-convex collisions; memory requirements depend on extra data dTRIDATAPREPROCESS_BUILD__MAX, }; /* * Data preprocessing extra values for dTRIDATAPREPROCESS_BUILD_FACE_ANGLES. */ enum { dTRIDATAPREPROCESS_FACE_ANGLES_EXTRA__MIN, dTRIDATAPREPROCESS_FACE_ANGLES_EXTRA_BYTE_POSITIVE = dTRIDATAPREPROCESS_FACE_ANGLES_EXTRA__MIN, // Build angles for convex edges only and store as bytes; allocates 3 bytes per triangle; stores angles (0..180] in 1/254 fractions leaving two values for the flat and all the concaves dTRIDATAPREPROCESS_FACE_ANGLES_EXTRA_BYTE_ALL, // Build angles for all the edges and store in bytes; allocates 3 bytes per triangle; stores angles [-180..0) and (0..180] in 1/127 fractions plus a value for the flat angle dTRIDATAPREPROCESS_FACE_ANGLES_EXTRA_WORD_ALL, // Build angles for all the edges and store in words; allocates 6 bytes per triangle; stores angles [-180..0) and (0..180] in 1/32767 fractions plus a value for the flat angle dTRIDATAPREPROCESS_FACE_ANGLES_EXTRA__MAX, dTRIDATAPREPROCESS_FACE_ANGLES_EXTRA__DEFAULT = dTRIDATAPREPROCESS_FACE_ANGLES_EXTRA_BYTE_POSITIVE, // The default value assumed if the extra data is not provided }; /* * Pre-process the trimesh data according to the request flags. * * buildRequestFlags is a bitmask of 1U << dTRIDATAPREPROCESS_BUILD_... * It is allowed to call the function multiple times provided the bitmasks are different each time. * * requestExtraData is an optional pointer to array of extra parameters per bitmask bits * (only the elements indexed by positions of raised bits are examined; * defaults are assumed if the pointer is NULL) * * The function returns a boolean status the only failure reason being insufficient memory. */ ODE_API int dGeomTriMeshDataPreprocess2(dTriMeshDataID g, unsigned int buildRequestFlags, const dintptr *requestExtraData/*=NULL | const dintptr (*)[dTRIDATAPREPROCESS_BUILD__MAX]*/); /* * Obsolete. Equivalent to calling dGeomTriMeshDataPreprocess2(g, (1U << dTRIDATAPREPROCESS_BUILD_CONCAVE_EDGES), NULL) */ ODE_API int dGeomTriMeshDataPreprocess(dTriMeshDataID g); /* * Get and set the internal preprocessed trimesh data buffer (see the enumerated type above), for loading and saving * These functions are deprecated. Use dGeomTriMeshDataSet/dGeomTriMeshDataGet2 with dTRIMESHDATA_USE_FLAGS instead. */ ODE_API_DEPRECATED ODE_API void dGeomTriMeshDataGetBuffer(dTriMeshDataID g, unsigned char** buf, int* bufLen); ODE_API_DEPRECATED ODE_API void dGeomTriMeshDataSetBuffer(dTriMeshDataID g, unsigned char* buf); /* * Per triangle callback. Allows the user to say if he wants a collision with * a particular triangle. */ typedef int dTriCallback(dGeomID TriMesh, dGeomID RefObject, int TriangleIndex); ODE_API void dGeomTriMeshSetCallback(dGeomID g, dTriCallback* Callback); ODE_API dTriCallback* dGeomTriMeshGetCallback(dGeomID g); /* * Per object callback. Allows the user to get the list of triangles in 1 * shot. Maybe we should remove this one. */ typedef void dTriArrayCallback(dGeomID TriMesh, dGeomID RefObject, const int* TriIndices, int TriCount); ODE_API void dGeomTriMeshSetArrayCallback(dGeomID g, dTriArrayCallback* ArrayCallback); ODE_API dTriArrayCallback* dGeomTriMeshGetArrayCallback(dGeomID g); /* * Ray callback. * Allows the user to say if a ray collides with a triangle on barycentric * coords. The user can for example sample a texture with alpha transparency * to determine if a collision should occur. */ typedef int dTriRayCallback(dGeomID TriMesh, dGeomID Ray, int TriangleIndex, dReal u, dReal v); ODE_API void dGeomTriMeshSetRayCallback(dGeomID g, dTriRayCallback* Callback); ODE_API dTriRayCallback* dGeomTriMeshGetRayCallback(dGeomID g); /* * Triangle merging callback. * Allows the user to generate a fake triangle index for a new contact generated * from merging of two other contacts. That index could later be used by the * user to determine attributes of original triangles used as sources for a * merged contact. */ typedef int dTriTriMergeCallback(dGeomID TriMesh, int FirstTriangleIndex, int SecondTriangleIndex); ODE_API void dGeomTriMeshSetTriMergeCallback(dGeomID g, dTriTriMergeCallback* Callback); ODE_API dTriTriMergeCallback* dGeomTriMeshGetTriMergeCallback(dGeomID g); /* * Trimesh class * Construction. Callbacks are optional. */ ODE_API dGeomID dCreateTriMesh(dSpaceID space, dTriMeshDataID Data, dTriCallback* Callback, dTriArrayCallback* ArrayCallback, dTriRayCallback* RayCallback); ODE_API void dGeomTriMeshSetData(dGeomID g, dTriMeshDataID Data); ODE_API dTriMeshDataID dGeomTriMeshGetData(dGeomID g); /* enable/disable/check temporal coherence*/ ODE_API void dGeomTriMeshEnableTC(dGeomID g, int geomClass, int enable); ODE_API int dGeomTriMeshIsTCEnabled(dGeomID g, int geomClass); /* * Clears the internal temporal coherence caches. When a geom has its * collision checked with a trimesh once, data is stored inside the trimesh. * With large worlds with lots of seperate objects this list could get huge. * We should be able to do this automagically. */ ODE_API void dGeomTriMeshClearTCCache(dGeomID g); /* * returns the TriMeshDataID */ ODE_API dTriMeshDataID dGeomTriMeshGetTriMeshDataID(dGeomID g); /* * Gets a triangle. */ ODE_API void dGeomTriMeshGetTriangle(dGeomID g, int Index, dVector3* v0, dVector3* v1, dVector3* v2); /* * Gets the point on the requested triangle and the given barycentric * coordinates. */ ODE_API void dGeomTriMeshGetPoint(dGeomID g, int Index, dReal u, dReal v, dVector3 Out); /* This is how the strided data works: struct StridedVertex{ dVector3 Vertex; // Userdata }; int VertexStride = sizeof(StridedVertex); struct StridedTri{ int Indices[3]; // Userdata }; int TriStride = sizeof(StridedTri); */ ODE_API int dGeomTriMeshGetTriangleCount (dGeomID g); ODE_API void dGeomTriMeshDataUpdate(dTriMeshDataID g); #ifdef __cplusplus } #endif #endif /* _ODE_COLLISION_TRIMESH_H_ */ ode-0.16/include/ode/matrix.h0000664000175200017520000001752613403272463013024 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* optimized and unoptimized vector and matrix functions */ #ifndef _ODE_MATRIX_H_ #define _ODE_MATRIX_H_ #include #ifdef __cplusplus extern "C" { #endif /* set a vector/matrix of size n to all zeros, or to a specific value. */ ODE_API void dSetZero (dReal *a, int n); ODE_API void dSetValue (dReal *a, int n, dReal value); /* get the dot product of two n*1 vectors. if n <= 0 then * zero will be returned (in which case a and b need not be valid). */ ODE_API dReal dDot (const dReal *a, const dReal *b, int n); /* get the dot products of (a0,b), (a1,b), etc and return them in outsum. * all vectors are n*1. if n <= 0 then zeroes will be returned (in which case * the input vectors need not be valid). this function is somewhat faster * than calling dDot() for all of the combinations separately. */ /* NOT INCLUDED in the library for now. void dMultidot2 (const dReal *a0, const dReal *a1, const dReal *b, dReal *outsum, int n); */ /* matrix multiplication. all matrices are stored in standard row format. * the digit refers to the argument that is transposed: * 0: A = B * C (sizes: A:p*r B:p*q C:q*r) * 1: A = B' * C (sizes: A:p*r B:q*p C:q*r) * 2: A = B * C' (sizes: A:p*r B:p*q C:r*q) * case 1,2 are equivalent to saying that the operation is A=B*C but * B or C are stored in standard column format. */ ODE_API void dMultiply0 (dReal *A, const dReal *B, const dReal *C, int p,int q,int r); ODE_API void dMultiply1 (dReal *A, const dReal *B, const dReal *C, int p,int q,int r); ODE_API void dMultiply2 (dReal *A, const dReal *B, const dReal *C, int p,int q,int r); /* do an in-place cholesky decomposition on the lower triangle of the n*n * symmetric matrix A (which is stored by rows). the resulting lower triangle * will be such that L*L'=A. return 1 on success and 0 on failure (on failure * the matrix is not positive definite). */ ODE_API int dFactorCholesky (dReal *A, int n); /* solve for x: L*L'*x = b, and put the result back into x. * L is size n*n, b is size n*1. only the lower triangle of L is considered. */ ODE_API void dSolveCholesky (const dReal *L, dReal *b, int n); /* compute the inverse of the n*n positive definite matrix A and put it in * Ainv. this is not especially fast. this returns 1 on success (A was * positive definite) or 0 on failure (not PD). */ ODE_API int dInvertPDMatrix (const dReal *A, dReal *Ainv, int n); /* check whether an n*n matrix A is positive definite, return 1/0 (yes/no). * positive definite means that x'*A*x > 0 for any x. this performs a * cholesky decomposition of A. if the decomposition fails then the matrix * is not positive definite. A is stored by rows. A is not altered. */ ODE_API int dIsPositiveDefinite (const dReal *A, int n); /* factorize a matrix A into L*D*L', where L is lower triangular with ones on * the diagonal, and D is diagonal. * A is an n*n matrix stored by rows, with a leading dimension of n rounded * up to 4. L is written into the strict lower triangle of A (the ones are not * written) and the reciprocal of the diagonal elements of D are written into * d. */ ODE_API void dFactorLDLT (dReal *A, dReal *d, int n, int nskip); /* solve L*x=b, where L is n*n lower triangular with ones on the diagonal, * and x,b are n*1. b is overwritten with x. * the leading dimension of L is `nskip'. */ ODE_API void dSolveL1 (const dReal *L, dReal *b, int n, int nskip); /* solve L'*x=b, where L is n*n lower triangular with ones on the diagonal, * and x,b are n*1. b is overwritten with x. * the leading dimension of L is `nskip'. */ ODE_API void dSolveL1T (const dReal *L, dReal *b, int n, int nskip); /* in matlab syntax: a(1:n) = a(1:n) .* d(1:n) */ ODE_API void dScaleVector (dReal *a, const dReal *d, int n); /* The function is an alias for @c dScaleVector. * It has been deprecated because of a wrong naming schema used. */ ODE_API_DEPRECATED ODE_API void dVectorScale (dReal *a, const dReal *d, int n); /* given `L', a n*n lower triangular matrix with ones on the diagonal, * and `d', a n*1 vector of the reciprocal diagonal elements of an n*n matrix * D, solve L*D*L'*x=b where x,b are n*1. x overwrites b. * the leading dimension of L is `nskip'. */ ODE_API void dSolveLDLT (const dReal *L, const dReal *d, dReal *b, int n, int nskip); /* given an L*D*L' factorization of an n*n matrix A, return the updated * factorization L2*D2*L2' of A plus the following "top left" matrix: * * [ b a' ] <-- b is a[0] * [ a 0 ] <-- a is a[1..n-1] * * - L has size n*n, its leading dimension is nskip. L is lower triangular * with ones on the diagonal. only the lower triangle of L is referenced. * - d has size n. d contains the reciprocal diagonal elements of D. * - a has size n. * the result is written into L, except that the left column of L and d[0] * are not actually modified. see ldltaddTL.m for further comments. */ ODE_API void dLDLTAddTL (dReal *L, dReal *d, const dReal *a, int n, int nskip); /* given an L*D*L' factorization of a permuted matrix A, produce a new * factorization for row and column `r' removed. * - A has size n1*n1, its leading dimension in nskip. A is symmetric and * positive definite. only the lower triangle of A is referenced. * A itself may actually be an array of row pointers. * - L has size n2*n2, its leading dimension in nskip. L is lower triangular * with ones on the diagonal. only the lower triangle of L is referenced. * - d has size n2. d contains the reciprocal diagonal elements of D. * - p is a permutation vector. it contains n2 indexes into A. each index * must be in the range 0..n1-1. * - r is the row/column of L to remove. * the new L will be written within the old L, i.e. will have the same leading * dimension. the last row and column of L, and the last element of d, are * undefined on exit. * * a fast O(n^2) algorithm is used. see ldltremove.m for further comments. */ ODE_API void dLDLTRemove (dReal **A, const int *p, dReal *L, dReal *d, int n1, int n2, int r, int nskip); /* given an n*n matrix A (with leading dimension nskip), remove the r'th row * and column by moving elements. the new matrix will have the same leading * dimension. the last row and column of A are untouched on exit. */ ODE_API void dRemoveRowCol (dReal *A, int n, int nskip, int r); #ifdef __cplusplus } #endif #endif ode-0.16/include/ode/misc.h0000664000175200017520000000644213403272463012446 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* miscellaneous math functions. these are mostly useful for testing */ #ifndef _ODE_MISC_H_ #define _ODE_MISC_H_ #include #ifdef __cplusplus extern "C" { #endif /* return 1 if the random number generator is working. */ ODE_API int dTestRand(void); /* return next 32 bit random number. this uses a not-very-random linear * congruential method. */ ODE_API unsigned long dRand(void); /* get and set the current random number seed. */ ODE_API unsigned long dRandGetSeed(void); ODE_API void dRandSetSeed (unsigned long s); /* return a random integer between 0..n-1. the distribution will get worse * as n approaches 2^32. */ ODE_API int dRandInt (int n); /* return a random real number between 0..1 */ ODE_API dReal dRandReal(void); /* print out a matrix */ ODE_API void dPrintMatrix (const dReal *A, int n, int m, const char *fmt, FILE *f); /* make a random vector with entries between +/- range. A has n elements. */ ODE_API void dMakeRandomVector (dReal *A, int n, dReal range); /* make a random matrix with entries between +/- range. A has size n*m. */ ODE_API void dMakeRandomMatrix (dReal *A, int n, int m, dReal range); /* clear the upper triangle of a square matrix */ ODE_API void dClearUpperTriangle (dReal *A, int n); /* return the maximum element difference between the two n*m matrices */ ODE_API dReal dMaxDifference (const dReal *A, const dReal *B, int n, int m); /* return the maximum element difference between the lower triangle of two * n*n matrices */ ODE_API dReal dMaxDifferenceLowerTriangle (const dReal *A, const dReal *B, int n); #ifdef __cplusplus } #endif #ifdef __cplusplus static inline void dPrintMatrix (const dReal *A, int n, int m, const char *fmt="%10.4f ") { dPrintMatrix(A, n, m, fmt, stdout); } #endif #endif ode-0.16/include/ode/collision_space.h0000664000175200017520000001472013403272463014657 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_COLLISION_SPACE_H_ #define _ODE_COLLISION_SPACE_H_ #include #ifdef __cplusplus extern "C" { #endif struct dContactGeom; /** * @brief User callback for geom-geom collision testing. * * @param data The user data object, as passed to dSpaceCollide. * @param o1 The first geom being tested. * @param o2 The second geom being test. * * @remarks The callback function can call dCollide on o1 and o2 to generate * contact points between each pair. Then these contact points may be added * to the simulation as contact joints. The user's callback function can of * course chose not to call dCollide for any pair, e.g. if the user decides * that those pairs should not interact. * * @ingroup collide */ typedef void dNearCallback (void *data, dGeomID o1, dGeomID o2); ODE_API dSpaceID dSimpleSpaceCreate (dSpaceID space); ODE_API dSpaceID dHashSpaceCreate (dSpaceID space); ODE_API dSpaceID dQuadTreeSpaceCreate (dSpaceID space, const dVector3 Center, const dVector3 Extents, int Depth); /* SAP */ /* Order XZY or ZXY usually works best, if your Y is up. */ #define dSAP_AXES_XYZ ((0)|(1<<2)|(2<<4)) #define dSAP_AXES_XZY ((0)|(2<<2)|(1<<4)) #define dSAP_AXES_YXZ ((1)|(0<<2)|(2<<4)) #define dSAP_AXES_YZX ((1)|(2<<2)|(0<<4)) #define dSAP_AXES_ZXY ((2)|(0<<2)|(1<<4)) #define dSAP_AXES_ZYX ((2)|(1<<2)|(0<<4)) ODE_API dSpaceID dSweepAndPruneSpaceCreate( dSpaceID space, int axisorder ); ODE_API void dSpaceDestroy (dSpaceID); ODE_API void dHashSpaceSetLevels (dSpaceID space, int minlevel, int maxlevel); ODE_API void dHashSpaceGetLevels (dSpaceID space, int *minlevel, int *maxlevel); ODE_API void dSpaceSetCleanup (dSpaceID space, int mode); ODE_API int dSpaceGetCleanup (dSpaceID space); /** * @brief Sets sublevel value for a space. * * Sublevel affects how the space is handled in dSpaceCollide2 when it is collided * with another space. If sublevels of both spaces match, the function iterates * geometries of both spaces and collides them with each other. If sublevel of one * space is greater than the sublevel of another one, only the geometries of the * space with greater sublevel are iterated, another space is passed into * collision callback as a geometry itself. By default all the spaces are assigned * zero sublevel. * * @note * The space sublevel @e IS @e NOT automatically updated when one space is inserted * into another or removed from one. It is a client's responsibility to update sublevel * value if necessary. * * @param space the space to modify * @param sublevel the sublevel value to be assigned * @ingroup collide * @see dSpaceGetSublevel * @see dSpaceCollide2 */ ODE_API void dSpaceSetSublevel (dSpaceID space, int sublevel); /** * @brief Gets sublevel value of a space. * * Sublevel affects how the space is handled in dSpaceCollide2 when it is collided * with another space. See @c dSpaceSetSublevel for more details. * * @param space the space to query * @returns the sublevel value of the space * @ingroup collide * @see dSpaceSetSublevel * @see dSpaceCollide2 */ ODE_API int dSpaceGetSublevel (dSpaceID space); /** * @brief Sets manual cleanup flag for a space. * * Manual cleanup flag marks a space as eligible for manual thread data cleanup. * This function should be called for every space object right after creation in * case if ODE has been initialized with @c dInitFlagManualThreadCleanup flag. * * Failure to set manual cleanup flag for a space may lead to some resources * remaining leaked until the program exit. * * @param space the space to modify * @param mode 1 for manual cleanup mode and 0 for default cleanup mode * @ingroup collide * @see dSpaceGetManualCleanup * @see dInitODE2 */ ODE_API void dSpaceSetManualCleanup (dSpaceID space, int mode); /** * @brief Get manual cleanup flag of a space. * * Manual cleanup flag marks a space space as eligible for manual thread data cleanup. * See @c dSpaceSetManualCleanup for more details. * * @param space the space to query * @returns 1 for manual cleanup mode and 0 for default cleanup mode of the space * @ingroup collide * @see dSpaceSetManualCleanup * @see dInitODE2 */ ODE_API int dSpaceGetManualCleanup (dSpaceID space); ODE_API void dSpaceAdd (dSpaceID, dGeomID); ODE_API void dSpaceRemove (dSpaceID, dGeomID); ODE_API int dSpaceQuery (dSpaceID, dGeomID); ODE_API void dSpaceClean (dSpaceID); ODE_API int dSpaceGetNumGeoms (dSpaceID); ODE_API dGeomID dSpaceGetGeom (dSpaceID, int i); /** * @brief Given a space, this returns its class. * * The ODE classes are: * @li dSimpleSpaceClass * @li dHashSpaceClass * @li dSweepAndPruneSpaceClass * @li dQuadTreeSpaceClass * @li dFirstUserClass * @li dLastUserClass * * The class id not defined by the user should be between * dFirstSpaceClass and dLastSpaceClass. * * User-defined class will return their own number. * * @param space the space to query * @returns The space class ID. * @ingroup collide */ ODE_API int dSpaceGetClass(dSpaceID space); #ifdef __cplusplus } #endif #endif ode-0.16/include/ode/threading_impl.h0000664000175200017520000003114113403272463014473 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * Builtin ODE threading implementation header. * * Copyright (C) 2011-2012 Oleh Derevenko. All rights reserved. * * e-mail: odar@eleks.com (change all "a" to "e") * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* * A threading implementation built into ODE for those who does not care to * or can't implement an own one. */ #ifndef _ODE_THREADING_IMPL_H_ #define _ODE_THREADING_IMPL_H_ #include #include #ifdef __cplusplus extern "C" { #endif struct dxThreadingThreadPool; typedef struct dxThreadingThreadPool *dThreadingThreadPoolID; /** * @brief Allocates built-in self-threaded threading implementation object. * * A self-threaded implementation is a type of implementation that performs * processing of posted calls by means of caller thread itself. This type of * implementation does not need thread pool to serve it. * * Note that since May 9th, 2017 (rev. #2066) the Self-Threaded implementation * returns 0 rather than 1 as available thread count to distinguish from * thread pools with just one thread in them. * * The processing is arranged in a way to prevent call stack depth growth * as more and more nested calls are posted. * * Note that it is not necessary to create and assign a self-threaded * implementation to a world, as there is a global one used by default * if no implementation is explicitly assigned. You should only assign * each world an individual threading implementation instance if simulations * need to be run in parallel in multiple threads for the worlds. * * @returns ID of object allocated or NULL on failure * * @ingroup threading * @see dThreadingAllocateMultiThreadedImplementation * @see dThreadingFreeImplementation */ ODE_API dThreadingImplementationID dThreadingAllocateSelfThreadedImplementation(); /** * @brief Allocates built-in multi-threaded threading implementation object. * * A multi-threaded implementation is a type of implementation that has to be * served with a thread pool. The thread pool can be either the built-in ODE object * or set of external threads that dedicate themselves to this purpose and stay * in ODE until implementation releases them. * * @returns ID of object allocated or NULL on failure * * @ingroup threading * @see dThreadingThreadPoolServeMultiThreadedImplementation * @see dExternalThreadingServeMultiThreadedImplementation * @see dThreadingFreeImplementation */ ODE_API dThreadingImplementationID dThreadingAllocateMultiThreadedImplementation(); /** * @brief Retrieves the functions record of a built-in threading implementation. * * The implementation can be the one allocated by ODE (from @c dThreadingAllocateMultiThreadedImplementation). * Do not use this function with self-made custom implementations - * they should be bundled with their own set of functions. * * @param impl Threading implementation ID * @returns Pointer to associated functions structure * * @ingroup threading * @see dThreadingAllocateMultiThreadedImplementation */ ODE_API const dThreadingFunctionsInfo *dThreadingImplementationGetFunctions(dThreadingImplementationID impl); /** * @brief Requests a built-in implementation to release threads serving it. * * The function unblocks threads employed in implementation serving and lets them * return to from where they originate. It's the responsibility of external code * to make sure all the calls to ODE that might be dependent on given threading * implementation object had already returned before this call is made. If threading * implementation is still processing some posted calls while this function is * invoked the behavior is implementation dependent. * * This call is to be used to request the threads to be released before waiting * for them in host pool or before waiting for them to exit. Implementation object * must not be destroyed before it is known that all the serving threads have already * returned from it. If implementation needs to be reused after this function is called * and all the threads have exited from it a call to @c dThreadingImplementationCleanupForRestart * must be made to restore internal state of the object. * * If this function is called for self-threaded built-in threading implementation * the call has no effect. * * @param impl Threading implementation ID * * @ingroup threading * @see dThreadingAllocateMultiThreadedImplementation * @see dThreadingImplementationCleanupForRestart */ ODE_API void dThreadingImplementationShutdownProcessing(dThreadingImplementationID impl); /** * @brief Restores built-in implementation's state to let it be reused after shutdown. * * If a multi-threaded built-in implementation needs to be reused after a call * to @c dThreadingImplementationShutdownProcessing this call is to be made to * restore object's internal state. After that the implementation can be served again. * * If this function is called for self-threaded built-in threading implementation * the call has no effect. * * @param impl Threading implementation ID * * @ingroup threading * @see dThreadingAllocateMultiThreadedImplementation * @see dThreadingImplementationShutdownProcessing */ ODE_API void dThreadingImplementationCleanupForRestart(dThreadingImplementationID impl); /** * @brief Deletes an instance of built-in threading implementation. * * @warning A care must be taken to make sure the implementation is unassigned * from all the objects it was assigned to and that there are no more threads * serving it before attempting to call this function. * * @param impl Threading implementation ID * * @ingroup threading * @see dThreadingAllocateMultiThreadedImplementation */ ODE_API void dThreadingFreeImplementation(dThreadingImplementationID impl); typedef void (dThreadReadyToServeCallback)(void *callback_context); /** * @brief An entry point for external threads that would like to serve a built-in * threading implementation object. * * A thread that calls this function remains blocked in ODE and serves implementation * object @p impl until being released with @c dThreadingImplementationShutdownProcessing call. * This function can be used to provide external threads instead of ODE's built-in * thread pools. * * The optional callback @readiness_callback is called after the thread has reached * and has registered within the implementation. The implementation should not * be used until all dedicated threads register within it as otherwise it will not * have accurate view of the execution resources available. * * @param impl Threading implementation ID * @param readiness_callback Optional readiness callback to be called after thread enters the implementation * @param callback_context A value to be passed as parameter to readiness callback * * @ingroup threading * @see dThreadingAllocateMultiThreadedImplementation * @see dThreadingImplementationShutdownProcessing */ ODE_API void dExternalThreadingServeMultiThreadedImplementation(dThreadingImplementationID impl, dThreadReadyToServeCallback *readiness_callback/*=NULL*/, void *callback_context/*=NULL*/); /** * @brief Creates an instance of built-in thread pool object that can be used to serve * multi-threaded threading implementations. * * The threads allocated inherit priority of caller thread. Their affinity is not * explicitly adjusted and gets the value the system assigns by default. Threads * have their stack memory fully committed immediately on start. On POSIX platforms * threads are started with all the possible signals blocked. Threads execute * calls to @c dAllocateODEDataForThread with @p ode_data_allocate_flags * on initialization. * * On POSIX platforms this function must be called with signals masked * or other measures must be taken to prevent reception of signals by calling thread * for the duration of the call. * * @param thread_count Number of threads to start in pool * @param stack_size Size of stack to be used for every thread or 0 for system default value * @param ode_data_allocate_flags Flags to be passed to @c dAllocateODEDataForThread on behalf of each thread * @returns ID of object allocated or NULL on failure * * @ingroup threading * @see dThreadingAllocateMultiThreadedImplementation * @see dThreadingImplementationShutdownProcessing * @see dThreadingFreeThreadPool */ ODE_API dThreadingThreadPoolID dThreadingAllocateThreadPool(unsigned thread_count, dsizeint stack_size, unsigned int ode_data_allocate_flags, void *reserved/*=NULL*/); /** * @brief Commands an instance of built-in thread pool to serve a built-in multi-threaded * threading implementation. * * A pool can only serve one threading implementation at a time. * Call @c dThreadingImplementationShutdownProcessing to release pool threads * from implementation serving and make them idle. Pool threads must be released * from any implementations before pool is attempted to be deleted. * * This function waits for threads to register within implementation before returning. * So, after the function call exits the implementation can be used immediately. * * @param pool Thread pool ID to serve the implementation * @param impl Implementation ID of implementation to be served * * @ingroup threading * @see dThreadingAllocateThreadPool * @see dThreadingAllocateMultiThreadedImplementation * @see dThreadingImplementationShutdownProcessing */ ODE_API void dThreadingThreadPoolServeMultiThreadedImplementation(dThreadingThreadPoolID pool, dThreadingImplementationID impl); /** * @brief Waits until all pool threads are released from threading implementation * they might be serving. * * The function can be used after a call to @c dThreadingImplementationShutdownProcessing * to make sure all the threads have already been released by threading implementation * and it can be deleted or it can be cleaned up for restart and served by another pool * or this pool's threads can be used to serve another threading implementation. * * Note that is it not necessary to call this function before pool destruction * since @c dThreadingFreeThreadPool performs similar wait operation implicitly on its own. * * It is OK to call this function even if pool was not serving any threading implementation * in which case the call exits immediately with minimal delay. * * @param pool Thread pool ID to wait for * * @ingroup threading * @see dThreadingAllocateThreadPool * @see dThreadingImplementationShutdownProcessing * @see dThreadingFreeThreadPool */ ODE_API void dThreadingThreadPoolWaitIdleState(dThreadingThreadPoolID pool); /** * @brief Deletes a built-in thread pool instance. * * The pool threads must be released from any implementations they might be serving * before this function is called. Otherwise the call is going to block * and wait until pool's threads return. * * @param pool Thread pool ID to delete * * @ingroup threading * @see dThreadingAllocateThreadPool * @see dThreadingImplementationShutdownProcessing */ ODE_API void dThreadingFreeThreadPool(dThreadingThreadPoolID pool); #ifdef __cplusplus } #endif #endif /* #ifndef _ODE_THREADING_IMPL_H_ */ ode-0.16/include/ode/rotation.h0000664000175200017520000000603413403272463013347 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_ROTATION_H_ #define _ODE_ROTATION_H_ #include #include #ifdef __cplusplus extern "C" { #endif ODE_API void dRSetIdentity (dMatrix3 R); ODE_API void dRFromAxisAndAngle (dMatrix3 R, dReal ax, dReal ay, dReal az, dReal angle); ODE_API void dRFromEulerAngles (dMatrix3 R, dReal phi, dReal theta, dReal psi); ODE_API void dRFrom2Axes (dMatrix3 R, dReal ax, dReal ay, dReal az, dReal bx, dReal by, dReal bz); ODE_API void dRFromZAxis (dMatrix3 R, dReal ax, dReal ay, dReal az); ODE_API void dQSetIdentity (dQuaternion q); ODE_API void dQFromAxisAndAngle (dQuaternion q, dReal ax, dReal ay, dReal az, dReal angle); /* Quaternion multiplication, analogous to the matrix multiplication routines. */ /* qa = rotate by qc, then qb */ ODE_API void dQMultiply0 (dQuaternion qa, const dQuaternion qb, const dQuaternion qc); /* qa = rotate by qc, then by inverse of qb */ ODE_API void dQMultiply1 (dQuaternion qa, const dQuaternion qb, const dQuaternion qc); /* qa = rotate by inverse of qc, then by qb */ ODE_API void dQMultiply2 (dQuaternion qa, const dQuaternion qb, const dQuaternion qc); /* qa = rotate by inverse of qc, then by inverse of qb */ ODE_API void dQMultiply3 (dQuaternion qa, const dQuaternion qb, const dQuaternion qc); ODE_API void dRfromQ (dMatrix3 R, const dQuaternion q); ODE_API void dQfromR (dQuaternion q, const dMatrix3 R); ODE_API void dDQfromW (dReal dq[4], const dVector3 w, const dQuaternion q); #ifdef __cplusplus } #endif #endif ode-0.16/include/ode/README0000664000175200017520000000062513403272463012217 00000000000000 this is the public C interface to the ODE library. all these files should be includable from C, i.e. they should not use any C++ features. everything should be protected with #ifdef __cplusplus extern "C" { #endif ... #ifdef __cplusplus } #endif the only exceptions are the odecpp.h and odecpp_collisioh.h files, which define a C++ wrapper for the C interface. remember to keep this in sync! ode-0.16/include/ode/Makefile.in0000664000175200017520000004564413403272663013420 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = include/ode ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(dist_libode_la_include_HEADERS) \ $(libode_la_include_HEADERS) $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/ode/src/config.h CONFIG_CLEAN_FILES = version.h precision.h CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libode_la_includedir)" \ "$(DESTDIR)$(libode_la_includedir)" HEADERS = $(dist_libode_la_include_HEADERS) \ $(libode_la_include_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/precision.h.in \ $(srcdir)/version.h.in README DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CCD_CFLAGS = @CCD_CFLAGS@ CCD_LIBS = @CCD_LIBS@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXTRA_LIBTOOL_LDFLAGS = @EXTRA_LIBTOOL_LDFLAGS@ FGREP = @FGREP@ GL_LIBS = @GL_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSTDCXX = @LIBSTDCXX@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ ODE_PRECISION = @ODE_PRECISION@ ODE_VERSION = @ODE_VERSION@ ODE_VERSION_INFO = @ODE_VERSION_INFO@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ WINDRES = @WINDRES@ X11_CFLAGS = @X11_CFLAGS@ X11_LIBS = @X11_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_WINDRES = @ac_ct_WINDRES@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ libode_la_includedir = $(includedir)/ode libode_la_include_HEADERS = \ collision.h \ collision_space.h \ collision_trimesh.h \ common.h \ compatibility.h \ contact.h \ cooperative.h \ error.h \ export-dif.h \ mass.h \ matrix.h matrix_coop.h \ memory.h \ misc.h \ objects.h \ ode.h \ odeconfig.h \ odecpp.h \ odecpp_collision.h \ odeinit.h \ odemath.h \ odemath_legacy.h \ rotation.h \ threading.h \ threading_impl.h \ timer.h EXTRA_DIST = README precision.h.in version.h.in dist_libode_la_include_HEADERS = precision.h version.h all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign include/ode/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign include/ode/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): version.h: $(top_builddir)/config.status $(srcdir)/version.h.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ precision.h: $(top_builddir)/config.status $(srcdir)/precision.h.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-dist_libode_la_includeHEADERS: $(dist_libode_la_include_HEADERS) @$(NORMAL_INSTALL) @list='$(dist_libode_la_include_HEADERS)'; test -n "$(libode_la_includedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libode_la_includedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libode_la_includedir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libode_la_includedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(libode_la_includedir)" || exit $$?; \ done uninstall-dist_libode_la_includeHEADERS: @$(NORMAL_UNINSTALL) @list='$(dist_libode_la_include_HEADERS)'; test -n "$(libode_la_includedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(libode_la_includedir)'; $(am__uninstall_files_from_dir) install-libode_la_includeHEADERS: $(libode_la_include_HEADERS) @$(NORMAL_INSTALL) @list='$(libode_la_include_HEADERS)'; test -n "$(libode_la_includedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libode_la_includedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libode_la_includedir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libode_la_includedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(libode_la_includedir)" || exit $$?; \ done uninstall-libode_la_includeHEADERS: @$(NORMAL_UNINSTALL) @list='$(libode_la_include_HEADERS)'; test -n "$(libode_la_includedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(libode_la_includedir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(HEADERS) installdirs: for dir in "$(DESTDIR)$(libode_la_includedir)" "$(DESTDIR)$(libode_la_includedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dist_libode_la_includeHEADERS \ install-libode_la_includeHEADERS install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-dist_libode_la_includeHEADERS \ uninstall-libode_la_includeHEADERS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool cscopelist-am ctags ctags-am distclean \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am \ install-dist_libode_la_includeHEADERS install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am \ install-libode_la_includeHEADERS install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-dist_libode_la_includeHEADERS \ uninstall-libode_la_includeHEADERS .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ode-0.16/include/ode/compatibility.h0000664000175200017520000000366113403272463014364 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_COMPATIBILITY_H_ #define _ODE_COMPATIBILITY_H_ /* * ODE's backward compatibility system ensures that as ODE's API * evolves, user code will not break. */ /* * These new rotation function names are more consistent with the * rest of the API. */ #define dQtoR(q,R) dRfromQ((R),(q)) #define dRtoQ(R,q) dQfromR((q),(R)) #define dWtoDQ(w,q,dq) dDQfromW((dq),(w),(q)) #endif ode-0.16/include/ode/memory.h0000664000175200017520000000516513403272463013024 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* this comes from the `reuse' library. copy any changes back to the source */ #ifndef _ODE_MEMORY_H_ #define _ODE_MEMORY_H_ #include #ifdef __cplusplus extern "C" { #endif /* function types to allocate and free memory */ typedef void * dAllocFunction (dsizeint size); typedef void * dReallocFunction (void *ptr, dsizeint oldsize, dsizeint newsize); typedef void dFreeFunction (void *ptr, dsizeint size); /* set new memory management functions. if fn is 0, the default handlers are * used. */ ODE_API void dSetAllocHandler (dAllocFunction *fn); ODE_API void dSetReallocHandler (dReallocFunction *fn); ODE_API void dSetFreeHandler (dFreeFunction *fn); /* get current memory management functions */ ODE_API dAllocFunction *dGetAllocHandler (void); ODE_API dReallocFunction *dGetReallocHandler (void); ODE_API dFreeFunction *dGetFreeHandler (void); /* allocate and free memory. */ ODE_API void * dAlloc (dsizeint size); ODE_API void * dRealloc (void *ptr, dsizeint oldsize, dsizeint newsize); ODE_API void dFree (void *ptr, dsizeint size); #ifdef __cplusplus } #endif #endif ode-0.16/include/ode/odecpp_collision.h0000664000175200017520000003332313403272463015036 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* C++ interface for new collision API */ #ifndef _ODE_ODECPP_COLLISION_H_ #define _ODE_ODECPP_COLLISION_H_ #ifdef __cplusplus //#include //namespace ode { class dGeom { // intentionally undefined, don't use these dGeom (dGeom &); void operator= (dGeom &); protected: dGeomID _id; dGeom() { _id = 0; } public: ~dGeom() { if (_id) dGeomDestroy (_id); } dGeomID id() const { return _id; } operator dGeomID() const { return _id; } void destroy() { if (_id) dGeomDestroy (_id); _id = 0; } int getClass() const { return dGeomGetClass (_id); } dSpaceID getSpace() const { return dGeomGetSpace (_id); } void setData (void *data) { dGeomSetData (_id,data); } void *getData() const { return dGeomGetData (_id); } void setBody (dBodyID b) { dGeomSetBody (_id,b); } dBodyID getBody() const { return dGeomGetBody (_id); } void setPosition (dReal x, dReal y, dReal z) { dGeomSetPosition (_id,x,y,z); } const dReal * getPosition() const { return dGeomGetPosition (_id); } void setRotation (const dMatrix3 R) { dGeomSetRotation (_id,R); } const dReal * getRotation() const { return dGeomGetRotation (_id); } void setQuaternion (const dQuaternion quat) { dGeomSetQuaternion (_id,quat); } void getQuaternion (dQuaternion quat) const { dGeomGetQuaternion (_id,quat); } void getAABB (dReal aabb[6]) const { dGeomGetAABB (_id, aabb); } int isSpace() { return dGeomIsSpace (_id); } void setCategoryBits (unsigned long bits) { dGeomSetCategoryBits (_id, bits); } void setCollideBits (unsigned long bits) { dGeomSetCollideBits (_id, bits); } unsigned long getCategoryBits() { return dGeomGetCategoryBits (_id); } unsigned long getCollideBits() { return dGeomGetCollideBits (_id); } void enable() { dGeomEnable (_id); } void disable() { dGeomDisable (_id); } int isEnabled() { return dGeomIsEnabled (_id); } void getRelPointPos (dReal px, dReal py, dReal pz, dVector3 result) const { dGeomGetRelPointPos (_id, px, py, pz, result); } void getRelPointPos (const dVector3 p, dVector3 result) const { getRelPointPos (p[0], p[1], p[2], result); } void getPosRelPoint (dReal px, dReal py, dReal pz, dVector3 result) const { dGeomGetPosRelPoint (_id, px, py, pz, result); } void getPosRelPoint (const dVector3 p, dVector3 result) const { getPosRelPoint (p[0], p[1], p[2], result); } void vectorToWorld (dReal px, dReal py, dReal pz, dVector3 result) const { dGeomVectorToWorld (_id, px, py, pz, result); } void vectorToWorld (const dVector3 p, dVector3 result) const { vectorToWorld (p[0], p[1], p[2], result); } void vectorFromWorld (dReal px, dReal py, dReal pz, dVector3 result) const { dGeomVectorFromWorld (_id, px, py, pz, result); } void vectorFromWorld (const dVector3 p, dVector3 result) const { vectorFromWorld (p[0], p[1], p[2], result); } void collide2 (dGeomID g, void *data, dNearCallback *callback) { dSpaceCollide2 (_id,g,data,callback); } }; class dSpace : public dGeom { // intentionally undefined, don't use these dSpace (dSpace &); void operator= (dSpace &); protected: // the default constructor is protected so that you // can't instance this class. you must instance one // of its subclasses instead. dSpace () { _id = 0; } public: dSpaceID id() const { return (dSpaceID) _id; } operator dSpaceID() const { return (dSpaceID) _id; } void setCleanup (int mode) { dSpaceSetCleanup (id(), mode); } int getCleanup() { return dSpaceGetCleanup (id()); } void add (dGeomID x) { dSpaceAdd (id(), x); } void remove (dGeomID x) { dSpaceRemove (id(), x); } int query (dGeomID x) { return dSpaceQuery (id(),x); } int getNumGeoms() { return dSpaceGetNumGeoms (id()); } dGeomID getGeom (int i) { return dSpaceGetGeom (id(),i); } void collide (void *data, dNearCallback *callback) { dSpaceCollide (id(),data,callback); } }; class dSimpleSpace : public dSpace { // intentionally undefined, don't use these dSimpleSpace (dSimpleSpace &); void operator= (dSimpleSpace &); public: dSimpleSpace () { _id = (dGeomID) dSimpleSpaceCreate (0); } dSimpleSpace (dSpace &space) { _id = (dGeomID) dSimpleSpaceCreate (space.id()); } dSimpleSpace (dSpaceID space) { _id = (dGeomID) dSimpleSpaceCreate (space); } }; class dHashSpace : public dSpace { // intentionally undefined, don't use these dHashSpace (dHashSpace &); void operator= (dHashSpace &); public: dHashSpace () { _id = (dGeomID) dHashSpaceCreate (0); } dHashSpace (dSpace &space) { _id = (dGeomID) dHashSpaceCreate (space.id()); } dHashSpace (dSpaceID space) { _id = (dGeomID) dHashSpaceCreate (space); } void setLevels (int minlevel, int maxlevel) { dHashSpaceSetLevels (id(),minlevel,maxlevel); } }; class dQuadTreeSpace : public dSpace { // intentionally undefined, don't use these dQuadTreeSpace (dQuadTreeSpace &); void operator= (dQuadTreeSpace &); public: dQuadTreeSpace (const dVector3 center, const dVector3 extents, int depth) { _id = (dGeomID) dQuadTreeSpaceCreate (0,center,extents,depth); } dQuadTreeSpace (dSpace &space, const dVector3 center, const dVector3 extents, int depth) { _id = (dGeomID) dQuadTreeSpaceCreate (space.id(),center,extents,depth); } dQuadTreeSpace (dSpaceID space, const dVector3 center, const dVector3 extents, int depth) { _id = (dGeomID) dQuadTreeSpaceCreate (space,center,extents,depth); } }; class dSphere : public dGeom { // intentionally undefined, don't use these dSphere (dSphere &); void operator= (dSphere &); public: dSphere () { } dSphere (dReal radius) { _id = dCreateSphere (0, radius); } dSphere (dSpace &space, dReal radius) { _id = dCreateSphere (space.id(), radius); } dSphere (dSpaceID space, dReal radius) { _id = dCreateSphere (space, radius); } void create (dSpaceID space, dReal radius) { if (_id) dGeomDestroy (_id); _id = dCreateSphere (space, radius); } void setRadius (dReal radius) { dGeomSphereSetRadius (_id, radius); } dReal getRadius() const { return dGeomSphereGetRadius (_id); } }; class dBox : public dGeom { // intentionally undefined, don't use these dBox (dBox &); void operator= (dBox &); public: dBox () { } dBox (dReal lx, dReal ly, dReal lz) { _id = dCreateBox (0,lx,ly,lz); } dBox (dSpace &space, dReal lx, dReal ly, dReal lz) { _id = dCreateBox (space,lx,ly,lz); } dBox (dSpaceID space, dReal lx, dReal ly, dReal lz) { _id = dCreateBox (space,lx,ly,lz); } void create (dSpaceID space, dReal lx, dReal ly, dReal lz) { if (_id) dGeomDestroy (_id); _id = dCreateBox (space,lx,ly,lz); } void setLengths (dReal lx, dReal ly, dReal lz) { dGeomBoxSetLengths (_id, lx, ly, lz); } void getLengths (dVector3 result) const { dGeomBoxGetLengths (_id,result); } }; class dPlane : public dGeom { // intentionally undefined, don't use these dPlane (dPlane &); void operator= (dPlane &); public: dPlane() { } dPlane (dReal a, dReal b, dReal c, dReal d) { _id = dCreatePlane (0,a,b,c,d); } dPlane (dSpace &space, dReal a, dReal b, dReal c, dReal d) { _id = dCreatePlane (space.id(),a,b,c,d); } dPlane (dSpaceID space, dReal a, dReal b, dReal c, dReal d) { _id = dCreatePlane (space,a,b,c,d); } void create (dSpaceID space, dReal a, dReal b, dReal c, dReal d) { if (_id) dGeomDestroy (_id); _id = dCreatePlane (space,a,b,c,d); } void setParams (dReal a, dReal b, dReal c, dReal d) { dGeomPlaneSetParams (_id, a, b, c, d); } void getParams (dVector4 result) const { dGeomPlaneGetParams (_id,result); } }; class dCapsule : public dGeom { // intentionally undefined, don't use these dCapsule (dCapsule &); void operator= (dCapsule &); public: dCapsule() { } dCapsule (dReal radius, dReal length) { _id = dCreateCapsule (0,radius,length); } dCapsule (dSpace &space, dReal radius, dReal length) { _id = dCreateCapsule (space.id(),radius,length); } dCapsule (dSpaceID space, dReal radius, dReal length) { _id = dCreateCapsule (space,radius,length); } void create (dSpaceID space, dReal radius, dReal length) { if (_id) dGeomDestroy (_id); _id = dCreateCapsule (space,radius,length); } void setParams (dReal radius, dReal length) { dGeomCapsuleSetParams (_id, radius, length); } void getParams (dReal *radius, dReal *length) const { dGeomCapsuleGetParams (_id,radius,length); } }; class dCylinder : public dGeom { // intentionally undefined, don't use these dCylinder (dCylinder &); void operator= (dCylinder &); public: dCylinder() { } dCylinder (dReal radius, dReal length) { _id = dCreateCylinder (0,radius,length); } dCylinder (dSpace &space, dReal radius, dReal length) { _id = dCreateCylinder (space.id(),radius,length); } dCylinder (dSpaceID space, dReal radius, dReal length) { _id = dCreateCylinder (space,radius,length); } void create (dSpaceID space, dReal radius, dReal length) { if (_id) dGeomDestroy (_id); _id = dCreateCylinder (space,radius,length); } void setParams (dReal radius, dReal length) { dGeomCylinderSetParams (_id, radius, length); } void getParams (dReal *radius, dReal *length) const { dGeomCylinderGetParams (_id,radius,length); } }; class dRay : public dGeom { // intentionally undefined, don't use these dRay (dRay &); void operator= (dRay &); public: dRay() { } dRay (dReal length) { _id = dCreateRay (0,length); } dRay (dSpace &space, dReal length) { _id = dCreateRay (space.id(),length); } dRay (dSpaceID space, dReal length) { _id = dCreateRay (space,length); } void create (dSpaceID space, dReal length) { if (_id) dGeomDestroy (_id); _id = dCreateRay (space,length); } void setLength (dReal length) { dGeomRaySetLength (_id, length); } dReal getLength() { return dGeomRayGetLength (_id); } void set (dReal px, dReal py, dReal pz, dReal dx, dReal dy, dReal dz) { dGeomRaySet (_id, px, py, pz, dx, dy, dz); } void get (dVector3 start, dVector3 dir) { dGeomRayGet (_id, start, dir); } #ifdef WIN32 #pragma warning( push ) #pragma warning( disable : 4996 ) #else #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif ODE_API_DEPRECATED void setParams (int firstContact, int backfaceCull) { dGeomRaySetParams (_id, firstContact, backfaceCull); } ODE_API_DEPRECATED void getParams (int *firstContact, int *backfaceCull) { dGeomRayGetParams (_id, firstContact, backfaceCull); } #ifdef WIN32 #pragma warning( pop ) #else #pragma GCC diagnostic pop #endif void setBackfaceCull (int backfaceCull) { dGeomRaySetBackfaceCull (_id, backfaceCull); } int getBackfaceCull() { return dGeomRayGetBackfaceCull (_id); } void setFirstContact (int firstContact) { dGeomRaySetFirstContact (_id, firstContact); } int getFirstContact() { return dGeomRayGetFirstContact (_id); } void setClosestHit (int closestHit) { dGeomRaySetClosestHit (_id, closestHit); } int getClosestHit() { return dGeomRayGetClosestHit (_id); } }; #ifdef WIN32 #pragma warning( push ) #pragma warning( disable : 4996 ) #else #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif class ODE_API_DEPRECATED dGeomTransform : public dGeom { // intentionally undefined, don't use these dGeomTransform (dGeomTransform &); void operator= (dGeomTransform &); public: dGeomTransform() { } dGeomTransform (dSpace &space) { _id = dCreateGeomTransform (space.id()); } dGeomTransform (dSpaceID space) { _id = dCreateGeomTransform (space); } void create (dSpaceID space=0) { if (_id) dGeomDestroy (_id); _id = dCreateGeomTransform (space); } void setGeom (dGeomID geom) { dGeomTransformSetGeom (_id, geom); } dGeomID getGeom() const { return dGeomTransformGetGeom (_id); } void setCleanup (int mode) { dGeomTransformSetCleanup (_id,mode); } int getCleanup () { return dGeomTransformGetCleanup (_id); } void setInfo (int mode) { dGeomTransformSetInfo (_id,mode); } int getInfo() { return dGeomTransformGetInfo (_id); } }; #ifdef WIN32 #pragma warning( pop ) #else #pragma GCC diagnostic pop #endif //} #endif #endif ode-0.16/include/Makefile.in0000664000175200017520000004503113403272663012637 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = include ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/ode/src/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CCD_CFLAGS = @CCD_CFLAGS@ CCD_LIBS = @CCD_LIBS@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXTRA_LIBTOOL_LDFLAGS = @EXTRA_LIBTOOL_LDFLAGS@ FGREP = @FGREP@ GL_LIBS = @GL_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSTDCXX = @LIBSTDCXX@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ ODE_PRECISION = @ODE_PRECISION@ ODE_VERSION = @ODE_VERSION@ ODE_VERSION_INFO = @ODE_VERSION_INFO@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ WINDRES = @WINDRES@ X11_CFLAGS = @X11_CFLAGS@ X11_LIBS = @X11_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_WINDRES = @ac_ct_WINDRES@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = ode drawstuff all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign include/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign include/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am tags tags-am uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ode-0.16/INSTALL.txt0000664000175200017520000001307413403272463011016 00000000000000ODE has two new build systems, one for *nix systems and another for just about everything else. 1. Building with Visual Studio 2. Building with Autotools (Linux, OS X, MSYS, etc.) 3. Building with Code::Blocks 4. Building with Something Else 5. Building with CMake 1. BUILDING WITH VISUAL STUDIO (2002 and up) ============================================ If you downloaded this source code from Subversion you must first use the Premake build system to generate project files. Open a command prompt and enter into the build directory. Then run the premake4.exe program with the appropriate options to generate the project files. For example, to generate a project for VS2008: > premake4.exe --with-tests --with-demos vs2008 To see a complete list of options use: > premake4.exe --help Note that Visual Studio 6 is not supported and users are advised to upgrade to at least Visual Studio 2005 Express (it's free!) Using CMake is another option for generating project files for Visual Studio. See section 5 below for more details on this. 2. BUILDING WITH AUTOTOOLS (Linux, OS X, MSYS, etc.) ==================================================== 2.1 FROM SUBVERSION REPOSITORY ------------------------------ If you downloaded the source code from Subversion you must bootstrap the process by running the command: $ ./bootstrap For this command to work you need a set of tools typically available on BSD and Linux distributions with development packages installed. OS X users may need to manually install libtool, autoconf, automake, pkg-config, and maybe some more. If you downloaded a source code package from SourceForge this has already been done for you. You may see some "underquoted definition" warnings depending on your platform, these are (for now) harmless warnings regarding scripts from other m4 installed packages. 2.2 FROM A RELEASED TARBALL --------------------------- First extract the archive (e.g. tar xvfz ) and enter the created directory (ode-x.y). Run the configure script to autodetect your build environment: $ ./configure By default this will build ODE as a static library with single-precision math, trimesh support with OPCODE, and debug symbols enabled. You can modify these defaults by passing additional parameters to configure. For a full list of available options, type: $ ./configure --help Some of the more popular options are --enable-double-precision enable double-precision math --with-trimesh=none disables the trimesh support --with-trimesh=opcode use OPCODE for trimesh code --with-trimesh=gimpact use GIMPACT for trimesh code --enabled-shared builds a shared library To pass specific flags for an optimized build, you must do so in the CFLAGS and CXXFLAGS enviroment variables, or as arguments to ./configure. For example if you are building for an athlon xp processor and you want the compiler to use SSE instructions you can run configure as follows: $ ./configure CFLAGS="-msse -march=atlon-xp" CXXFLAGS="-msse -march=atlon-xp" Note that you must set both CFLAGS and CXXFLAGS as ODE contains a mixture of C and C++ files. Once configure has run successfully, build and install ODE: $ make $ make install The latter command will also create a pkg-config script that provides compilation and linking flags for programs. The old stand-alone "ode-config" script is also installed for compatibility. 3. BUILDING WITH Code::Blocks ============================= Because Code::Blocks supports so many different platforms, we do not provide workspaces. Instead, use Premake to create a workspace tailored for your platform and project. Like so: $ cd build $ premake4 --with-tests --with-demos codeblocks To see a complete list of options: $ cd build $ premake4 --help Using CMake is another option for generating project files for Code::Blocks. See section 5 below for more details on this. 4. BUILDING WITH SOMETHING ELSE =============================== ODE uses the Premake tool to provide support for several different toolsets. Premake adds support for new toolsets on a regular basis, so yours might be supported. Check the Premake website at http://premake.sourceforge.net/, and then follow the directions for Code::Blocks above, substituting your toolset target in place of `codeblocks`. Using CMake is another option for generating project files for other toolsets. See section 5 below for more details on this. 5. BUILDING WITH CMAKE ====================== ODE includes support for CMake to generate project files for various platforms and IDEs including Unix Makefiles, Ninja, Code::Blocks, Visual Studio. A full overview of all supported generators can be found at the latest version of the manual at https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html CMake supports and encourages out-of-source builds. In order to generate build files for your platform, create a build directory at your preferred location and then call CMake with the path to ODE's source directory as argument, e.g., one level above the source directory: $ cd .. $ mkdir ode-build $ cmake ../ode-src The existing build directory in the source directory can also be used as a location for the project files. A different generator than the default one for the system can be specified as well: $ cd build $ cmake -G"Visual Studio 15 2017 Win64" .. QtCreator, CLion, and Visual Studio 2017 also offer the option to open the source directory with the CMakeLists.txt file directly in the IDE. ode-0.16/LICENSE-BSD.TXT0000664000175200017520000000313213403272463011232 00000000000000 This is the BSD-style license for the Open Dynamics Engine ---------------------------------------------------------- Open Dynamics Engine Copyright (c) 2001-2007, Russell L. Smith. All rights reserved. Redistribution and use 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 names of ODE's copyright owner nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 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. ode-0.16/missing0000755000175200017520000001533013403272662010542 00000000000000#! /bin/sh # Common wrapper for a few potentially missing GNU programs. scriptversion=2013-10-28.13; # UTC # Copyright (C) 1996-2014 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try '$0 --help' for more information" exit 1 fi case $1 in --is-lightweight) # Used by our autoconf macros to check whether the available missing # script is modern enough. exit 0 ;; --run) # Back-compat with the calling convention used by older automake. shift ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due to PROGRAM being missing or too old. Options: -h, --help display this help and exit -v, --version output version information and exit Supported PROGRAM values: aclocal autoconf autoheader autom4te automake makeinfo bison yacc flex lex help2man Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 'g' are ignored when checking the name. Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: unknown '$1' option" echo 1>&2 "Try '$0 --help' for more information" exit 1 ;; esac # Run the given program, remember its exit status. "$@"; st=$? # If it succeeded, we are done. test $st -eq 0 && exit 0 # Also exit now if we it failed (or wasn't found), and '--version' was # passed; such an option is passed most likely to detect whether the # program is present and works. case $2 in --version|--help) exit $st;; esac # Exit code 63 means version mismatch. This often happens when the user # tries to use an ancient version of a tool on a file that requires a # minimum version. if test $st -eq 63; then msg="probably too old" elif test $st -eq 127; then # Program was missing. msg="missing on your system" else # Program was found and executed, but failed. Give up. exit $st fi perl_URL=http://www.perl.org/ flex_URL=http://flex.sourceforge.net/ gnu_software_URL=http://www.gnu.org/software program_details () { case $1 in aclocal|automake) echo "The '$1' program is part of the GNU Automake package:" echo "<$gnu_software_URL/automake>" echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/autoconf>" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; autoconf|autom4te|autoheader) echo "The '$1' program is part of the GNU Autoconf package:" echo "<$gnu_software_URL/autoconf/>" echo "It also requires GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; esac } give_advice () { # Normalize program name to check for. normalized_program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` printf '%s\n' "'$1' is $msg." configure_deps="'configure.ac' or m4 files included by 'configure.ac'" case $normalized_program in autoconf*) echo "You should only need it if you modified 'configure.ac'," echo "or m4 files included by it." program_details 'autoconf' ;; autoheader*) echo "You should only need it if you modified 'acconfig.h' or" echo "$configure_deps." program_details 'autoheader' ;; automake*) echo "You should only need it if you modified 'Makefile.am' or" echo "$configure_deps." program_details 'automake' ;; aclocal*) echo "You should only need it if you modified 'acinclude.m4' or" echo "$configure_deps." program_details 'aclocal' ;; autom4te*) echo "You might have modified some maintainer files that require" echo "the 'autom4te' program to be rebuilt." program_details 'autom4te' ;; bison*|yacc*) echo "You should only need it if you modified a '.y' file." echo "You may want to install the GNU Bison package:" echo "<$gnu_software_URL/bison/>" ;; lex*|flex*) echo "You should only need it if you modified a '.l' file." echo "You may want to install the Fast Lexical Analyzer package:" echo "<$flex_URL>" ;; help2man*) echo "You should only need it if you modified a dependency" \ "of a man page." echo "You may want to install the GNU Help2man package:" echo "<$gnu_software_URL/help2man/>" ;; makeinfo*) echo "You should only need it if you modified a '.texi' file, or" echo "any other file indirectly affecting the aspect of the manual." echo "You might want to install the Texinfo package:" echo "<$gnu_software_URL/texinfo/>" echo "The spurious makeinfo call might also be the consequence of" echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" echo "want to install GNU make:" echo "<$gnu_software_URL/make/>" ;; *) echo "You might have modified some files without having the proper" echo "tools for further handling them. Check the 'README' file, it" echo "often tells you about the needed prerequisites for installing" echo "this package. You may also peek at any GNU archive site, in" echo "case some other package contains this missing '$1' program." ;; esac } give_advice "$1" | sed -e '1s/^/WARNING: /' \ -e '2,$s/^/ /' >&2 # Propagate the correct exit status (expected to be 127 for a program # not found, 63 for a program that failed due to version mismatch). exit $st # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: ode-0.16/config.sub0000755000175200017520000010646013403272662011133 00000000000000#! /bin/sh # Configuration validation subroutine script. # Copyright 1992-2015 Free Software Foundation, Inc. timestamp='2015-08-20' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # Please send patches to . # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright 1992-2015 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; android-linux) os=-linux-android basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis | -knuth | -cray | -microblaze*) os= basic_machine=$1 ;; -bluegene*) os=-cnk ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*178) os=-lynxos178 ;; -lynx*5) os=-lynxos5 ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arceb \ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ | avr | avr32 \ | ba \ | be32 | be64 \ | bfin \ | c4x | c8051 | clipper \ | d10v | d30v | dlx | dsp16xx \ | e2k | epiphany \ | fido | fr30 | frv | ft32 \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | k1om \ | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ | mips64r5900 | mips64r5900el \ | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa32r6 | mipsisa32r6el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64r6 | mipsisa64r6el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipsr5900 | mipsr5900el \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nds32 | nds32le | nds32be \ | nios | nios2 | nios2eb | nios2el \ | ns16k | ns32k \ | open8 | or1k | or1knd | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pyramid \ | riscv32 | riscv64 \ | rl78 | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu \ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | visium \ | we32k \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown ;; c54x) basic_machine=tic54x-unknown ;; c55x) basic_machine=tic55x-unknown ;; c6x) basic_machine=tic6x-unknown ;; leon|leon[3-9]) basic_machine=sparc-$basic_machine ;; m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; ms1) basic_machine=mt-unknown ;; strongarm | thumb | xscale) basic_machine=arm-unknown ;; xgate) basic_machine=$basic_machine-unknown os=-none ;; xscaleeb) basic_machine=armeb-unknown ;; xscaleel) basic_machine=armel-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | ba-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | c8051-* | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | e2k-* | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | k1om-* \ | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ | microblaze-* | microblazeel-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ | mips64r5900-* | mips64r5900el-* \ | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa32r6-* | mipsisa32r6el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64r6-* | mipsisa64r6el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipsr5900-* | mipsr5900el-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nds32-* | nds32le-* | nds32be-* \ | nios-* | nios2-* | nios2eb-* | nios2el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ | or1k*-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pyramid-* \ | riscv32-* | riscv64-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ | tron-* \ | ubicom32-* \ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ | visium-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-* | z80-*) ;; # Recognize the basic CPU types without company name, with glob match. xtensa*) basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aros) basic_machine=i386-pc os=-aros ;; asmjs) basic_machine=asmjs-unknown ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; blackfin) basic_machine=bfin-unknown os=-linux ;; blackfin-*) basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) basic_machine=powerpc-ibm os=-cnk ;; c54x-*) basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c55x-*) basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c6x-*) basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray os=-unicos ;; cegcc) basic_machine=arm-unknown os=-cegcc ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16 | cr16-*) basic_machine=cr16-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dicos) basic_machine=i686-pc os=-dicos ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; leon-*|leon[3-9]-*) basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; microblaze*) basic_machine=microblaze-xilinx ;; mingw64) basic_machine=x86_64-pc os=-mingw64 ;; mingw32) basic_machine=i686-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; moxiebox) basic_machine=moxie-unknown os=-moxiebox ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; msys) basic_machine=i686-pc os=-msys ;; mvs) basic_machine=i370-ibm os=-mvs ;; nacl) basic_machine=le32-unknown os=-nacl ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; neo-tandem) basic_machine=neo-tandem ;; nse-tandem) basic_machine=nse-tandem ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; parisc) basic_machine=hppa-unknown os=-linux ;; parisc-*) basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos | rdos64) basic_machine=x86_64-pc os=-rdos ;; rdos32) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh5el) basic_machine=sh5le-unknown ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; strongarm-* | thumb-*) basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tile*) basic_machine=$basic_machine-unknown os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; z80-*-coff) basic_machine=z80-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* | -cloudabi* | -sortix* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -bitrig* | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; -nacl*) ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; c8051-*) os=-elf ;; hexagon-*) os=-elf ;; tic54x-*) os=-coff ;; tic55x-*) os=-coff ;; tic6x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 ;; m68*-cisco) os=-aout ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -cnk*|-aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: ode-0.16/ode/0000775000175200017520000000000013403273061007764 500000000000000ode-0.16/ode/src/0000775000175200017520000000000013403273061010553 500000000000000ode-0.16/ode/src/objects.h0000664000175200017520000002053113403272463012303 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ // object, body, and world structs. #ifndef _ODE__PRIVATE_OBJECTS_H_ #define _ODE__PRIVATE_OBJECTS_H_ #include #include #include #include "error.h" #include "array.h" #include "common.h" #include "threading_base.h" struct dxJointNode; class dxStepWorkingMemory; class dxWorldProcessContext; // some body flags enum { dxBodyFlagFiniteRotation = 1, // use finite rotations dxBodyFlagFiniteRotationAxis = 2, // use finite rotations only along axis dxBodyDisabled = 4, // body is disabled dxBodyNoGravity = 8, // body is not influenced by gravity dxBodyAutoDisable = 16, // enable auto-disable on body dxBodyLinearDamping = 32, // use linear damping dxBodyAngularDamping = 64, // use angular damping dxBodyMaxAngularSpeed = 128,// use maximum angular speed dxBodyGyroscopic = 256 // use gyroscopic term }; // base class that does correct object allocation / deallocation struct dBase { void *operator new (size_t size) { return dAlloc (size); } void *operator new (size_t, void *p) { return p; } void operator delete (void *ptr, size_t size) { dFree (ptr,size); } void *operator new[] (size_t size) { return dAlloc (size); } void operator delete[] (void *ptr, size_t size) { dFree (ptr,size); } }; // base class for bodies and joints struct dObject : public dBase { dxWorld *world; // world this object is in dObject *next; // next object of this type in list dObject **tome; // pointer to previous object's next ptr int tag; // used by dynamics algorithms void *userdata; // user settable data explicit dObject(dxWorld *w): world(w), next(NULL), tome(NULL), tag(0), userdata(NULL) {} virtual ~dObject(); }; // auto disable parameters struct dxAutoDisable { dReal idle_time; // time the body needs to be idle to auto-disable it int idle_steps; // steps the body needs to be idle to auto-disable it unsigned int average_samples; // size of the average_lvel and average_avel buffers dReal linear_average_threshold; // linear (squared) average velocity threshold dReal angular_average_threshold; // angular (squared) average velocity threshold dxAutoDisable() {} explicit dxAutoDisable(void *); }; // damping parameters struct dxDampingParameters { dReal linear_scale; // multiply the linear velocity by (1 - scale) dReal angular_scale; // multiply the angular velocity by (1 - scale) dReal linear_threshold; // linear (squared) average speed threshold dReal angular_threshold; // angular (squared) average speed threshold dxDampingParameters() {} explicit dxDampingParameters(void *); }; // quick-step parameters struct dxQuickStepParameters { int num_iterations; // number of SOR iterations to perform dReal w; // the SOR over-relaxation parameter dxQuickStepParameters() {} explicit dxQuickStepParameters(void *); }; // contact generation parameters struct dxContactParameters { dReal max_vel; // maximum correcting velocity dReal min_depth; // thickness of 'surface layer' dxContactParameters() {} explicit dxContactParameters(void *); }; // position vector and rotation matrix for geometry objects that are not // connected to bodies. struct dxPosR { dVector3 pos; dMatrix3 R; }; struct dxBody : public dObject { dxJointNode *firstjoint; // list of attached joints unsigned flags; // some dxBodyFlagXXX flags dGeomID geom; // first collision geom associated with body dMass mass; // mass parameters about POR dMatrix3 invI; // inverse of mass.I dReal invMass; // 1 / mass.mass dxPosR posr; // position and orientation of point of reference dQuaternion q; // orientation quaternion dVector3 lvel,avel; // linear and angular velocity of POR dVector3 facc,tacc; // force and torque accumulators dVector3 finite_rot_axis; // finite rotation axis, unit length or 0=none // auto-disable information dxAutoDisable adis; // auto-disable parameters dReal adis_timeleft; // time left to be idle int adis_stepsleft; // steps left to be idle dVector3* average_lvel_buffer; // buffer for the linear average velocity calculation dVector3* average_avel_buffer; // buffer for the angular average velocity calculation unsigned int average_counter; // counter/index to fill the average-buffers int average_ready; // indicates ( with = 1 ), if the Body's buffers are ready for average-calculations void (*moved_callback)(dxBody*); // let the user know the body moved dxDampingParameters dampingp; // damping parameters, depends on flags dReal max_angular_speed; // limit the angular velocity to this magnitude dxBody(dxWorld *w); }; struct dxWorld : public dBase, public dxThreadingBase, private dxIThreadingDefaultImplProvider { dxBody *firstbody; // body linked list dxJoint *firstjoint; // joint linked list int nb,nj; // number of bodies and joints in lists dVector3 gravity; // gravity vector (m/s/s) dReal global_erp; // global error reduction parameter dReal global_cfm; // global constraint force mixing parameter dxAutoDisable adis; // auto-disable parameters int body_flags; // flags for new bodies unsigned islands_max_threads; // maximum threads to allocate for island processing dxStepWorkingMemory *wmem; // Working memory object for dWorldStep/dWorldQuickStep dxQuickStepParameters qs; dxContactParameters contactp; dxDampingParameters dampingp; // damping parameters dReal max_angular_speed; // limit the angular velocity to this magnitude void* userdata; dxWorld(); virtual ~dxWorld(); // Compilers issue warnings if a class with virtual methods does not have a virtual destructor :( void assignThreadingImpl(const dxThreadingFunctionsInfo *functions_info, dThreadingImplementationID threading_impl); unsigned calculateIslandProcessingMaxThreadCount(unsigned *ptrOut_activeThreadCount=NULL) const { unsigned activeThreadCount, *ptrActiveThreadCountToUse = ptrOut_activeThreadCount != NULL ? &activeThreadCount : NULL; unsigned limitedCount = calculateThreadingLimitedThreadCount(islands_max_threads, false, ptrActiveThreadCountToUse); if (ptrOut_activeThreadCount != NULL) { *ptrOut_activeThreadCount = dMACRO_MAX(activeThreadCount, 1U); } return dMACRO_MAX(limitedCount, 1U); } dxWorldProcessContext *unsafeGetWorldProcessingContext() const; private: // dxIThreadingDefaultImplProvider virtual const dxThreadingFunctionsInfo *retrieveThreadingDefaultImpl(dThreadingImplementationID &out_defaultImpl); }; #endif // #ifndef _ODE__PRIVATE_OBJECTS_H_ ode-0.16/ode/src/sphere.cpp0000664000175200017520000002061013403272463012471 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* standard ODE geometry primitives: public API and pairwise collision functions. the rule is that only the low level primitive collision functions should set dContactGeom::g1 and dContactGeom::g2. */ #include #include #include #include "config.h" #include "matrix.h" #include "odemath.h" #include "collision_kernel.h" #include "collision_std.h" #include "collision_util.h" #ifdef _MSC_VER #pragma warning(disable:4291) // for VC++, no complaints about "no matching operator delete found" #endif //**************************************************************************** // sphere public API dxSphere::dxSphere (dSpaceID space, dReal _radius) : dxGeom (space,1) { dAASSERT (_radius >= 0); type = dSphereClass; radius = _radius; updateZeroSizedFlag(!_radius); } void dxSphere::computeAABB() { aabb[0] = final_posr->pos[0] - radius; aabb[1] = final_posr->pos[0] + radius; aabb[2] = final_posr->pos[1] - radius; aabb[3] = final_posr->pos[1] + radius; aabb[4] = final_posr->pos[2] - radius; aabb[5] = final_posr->pos[2] + radius; } dGeomID dCreateSphere (dSpaceID space, dReal radius) { return new dxSphere (space,radius); } void dGeomSphereSetRadius (dGeomID g, dReal radius) { dUASSERT (g && g->type == dSphereClass,"argument not a sphere"); dAASSERT (radius >= 0); dxSphere *s = (dxSphere*) g; s->radius = radius; s->updateZeroSizedFlag(!radius); dGeomMoved (g); } dReal dGeomSphereGetRadius (dGeomID g) { dUASSERT (g && g->type == dSphereClass,"argument not a sphere"); dxSphere *s = (dxSphere*) g; return s->radius; } dReal dGeomSpherePointDepth (dGeomID g, dReal x, dReal y, dReal z) { dUASSERT (g && g->type == dSphereClass,"argument not a sphere"); g->recomputePosr(); dxSphere *s = (dxSphere*) g; dReal * pos = s->final_posr->pos; return s->radius - dSqrt ((x-pos[0])*(x-pos[0]) + (y-pos[1])*(y-pos[1]) + (z-pos[2])*(z-pos[2])); } //**************************************************************************** // pairwise collision functions for standard geom types int dCollideSphereSphere (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) { dIASSERT (skip >= (int)sizeof(dContactGeom)); dIASSERT (o1->type == dSphereClass); dIASSERT (o2->type == dSphereClass); dIASSERT ((flags & NUMC_MASK) >= 1); dxSphere *sphere1 = (dxSphere*) o1; dxSphere *sphere2 = (dxSphere*) o2; contact->g1 = o1; contact->g2 = o2; contact->side1 = -1; contact->side2 = -1; return dCollideSpheres (o1->final_posr->pos,sphere1->radius, o2->final_posr->pos,sphere2->radius,contact); } int dCollideSphereBox (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) { dIASSERT (skip >= (int)sizeof(dContactGeom)); dIASSERT (o1->type == dSphereClass); dIASSERT (o2->type == dBoxClass); dIASSERT ((flags & NUMC_MASK) >= 1); // this is easy. get the sphere center `p' relative to the box, and then clip // that to the boundary of the box (call that point `q'). if q is on the // boundary of the box and |p-q| is <= sphere radius, they touch. // if q is inside the box, the sphere is inside the box, so set a contact // normal to push the sphere to the closest box face. dVector3 l,t,p,q,r; dReal depth; int onborder = 0; dxSphere *sphere = (dxSphere*) o1; dxBox *box = (dxBox*) o2; contact->g1 = o1; contact->g2 = o2; contact->side1 = -1; contact->side2 = -1; p[0] = o1->final_posr->pos[0] - o2->final_posr->pos[0]; p[1] = o1->final_posr->pos[1] - o2->final_posr->pos[1]; p[2] = o1->final_posr->pos[2] - o2->final_posr->pos[2]; l[0] = box->side[0]*REAL(0.5); t[0] = dCalcVectorDot3_14(p,o2->final_posr->R); if (t[0] < -l[0]) { t[0] = -l[0]; onborder = 1; } if (t[0] > l[0]) { t[0] = l[0]; onborder = 1; } l[1] = box->side[1]*REAL(0.5); t[1] = dCalcVectorDot3_14(p,o2->final_posr->R+1); if (t[1] < -l[1]) { t[1] = -l[1]; onborder = 1; } if (t[1] > l[1]) { t[1] = l[1]; onborder = 1; } t[2] = dCalcVectorDot3_14(p,o2->final_posr->R+2); l[2] = box->side[2]*REAL(0.5); if (t[2] < -l[2]) { t[2] = -l[2]; onborder = 1; } if (t[2] > l[2]) { t[2] = l[2]; onborder = 1; } if (!onborder) { // sphere center inside box. find closest face to `t' dReal min_distance = l[0] - dFabs(t[0]); int mini = 0; for (int i=1; i<3; i++) { dReal face_distance = l[i] - dFabs(t[i]); if (face_distance < min_distance) { min_distance = face_distance; mini = i; } } // contact position = sphere center contact->pos[0] = o1->final_posr->pos[0]; contact->pos[1] = o1->final_posr->pos[1]; contact->pos[2] = o1->final_posr->pos[2]; // contact normal points to closest face dVector3 tmp; tmp[0] = 0; tmp[1] = 0; tmp[2] = 0; tmp[mini] = (t[mini] > 0) ? REAL(1.0) : REAL(-1.0); dMultiply0_331 (contact->normal,o2->final_posr->R,tmp); // contact depth = distance to wall along normal plus radius contact->depth = min_distance + sphere->radius; return 1; } t[3] = 0; //@@@ hmmm dMultiply0_331 (q,o2->final_posr->R,t); r[0] = p[0] - q[0]; r[1] = p[1] - q[1]; r[2] = p[2] - q[2]; depth = sphere->radius - dSqrt(dCalcVectorDot3(r,r)); if (depth < 0) return 0; contact->pos[0] = q[0] + o2->final_posr->pos[0]; contact->pos[1] = q[1] + o2->final_posr->pos[1]; contact->pos[2] = q[2] + o2->final_posr->pos[2]; contact->normal[0] = r[0]; contact->normal[1] = r[1]; contact->normal[2] = r[2]; dNormalize3 (contact->normal); contact->depth = depth; return 1; } int dCollideSpherePlane (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) { dIASSERT (skip >= (int)sizeof(dContactGeom)); dIASSERT (o1->type == dSphereClass); dIASSERT (o2->type == dPlaneClass); dIASSERT ((flags & NUMC_MASK) >= 1); dxSphere *sphere = (dxSphere*) o1; dxPlane *plane = (dxPlane*) o2; contact->g1 = o1; contact->g2 = o2; contact->side1 = -1; contact->side2 = -1; dReal k = dCalcVectorDot3 (o1->final_posr->pos,plane->p); dReal depth = plane->p[3] - k + sphere->radius; if (depth >= 0) { contact->normal[0] = plane->p[0]; contact->normal[1] = plane->p[1]; contact->normal[2] = plane->p[2]; contact->pos[0] = o1->final_posr->pos[0] - plane->p[0] * sphere->radius; contact->pos[1] = o1->final_posr->pos[1] - plane->p[1] * sphere->radius; contact->pos[2] = o1->final_posr->pos[2] - plane->p[2] * sphere->radius; contact->depth = depth; return 1; } else return 0; } ode-0.16/ode/src/collision_trimesh_sphere.cpp0000664000175200017520000005263213403272463016310 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ // TriMesh code by Erwin de Vries. #include #include #include "config.h" #include "matrix.h" #include "odemath.h" #include "collision_util.h" #ifdef HAVE_CONFIG_H #include "config.h" #endif #if dTRIMESH_ENABLED #include "collision_trimesh_internal.h" #if dTRIMESH_OPCODE // Ripped from Opcode 1.1. static bool GetContactData(const dVector3& Center, dReal Radius, const dVector3 Origin, const dVector3 Edge0, const dVector3 Edge1, dReal& Dist, dReal& u, dReal& v){ // now onto the bulk of the collision... dVector3 Diff; Diff[0] = Origin[0] - Center[0]; Diff[1] = Origin[1] - Center[1]; Diff[2] = Origin[2] - Center[2]; Diff[3] = Origin[3] - Center[3]; dReal A00 = dCalcVectorDot3(Edge0, Edge0); dReal A01 = dCalcVectorDot3(Edge0, Edge1); dReal A11 = dCalcVectorDot3(Edge1, Edge1); dReal B0 = dCalcVectorDot3(Diff, Edge0); dReal B1 = dCalcVectorDot3(Diff, Edge1); dReal C = dCalcVectorDot3(Diff, Diff); dReal Det = dFabs(A00 * A11 - A01 * A01); u = A01 * B1 - A11 * B0; v = A01 * B0 - A00 * B1; dReal DistSq; if (u + v <= Det){ if(u < REAL(0.0)){ if(v < REAL(0.0)){ // region 4 if(B0 < REAL(0.0)){ v = REAL(0.0); if (-B0 >= A00){ u = REAL(1.0); DistSq = A00 + REAL(2.0) * B0 + C; } else{ u = -B0 / A00; DistSq = B0 * u + C; } } else{ u = REAL(0.0); if(B1 >= REAL(0.0)){ v = REAL(0.0); DistSq = C; } else if(-B1 >= A11){ v = REAL(1.0); DistSq = A11 + REAL(2.0) * B1 + C; } else{ v = -B1 / A11; DistSq = B1 * v + C; } } } else{ // region 3 u = REAL(0.0); if(B1 >= REAL(0.0)){ v = REAL(0.0); DistSq = C; } else if(-B1 >= A11){ v = REAL(1.0); DistSq = A11 + REAL(2.0) * B1 + C; } else{ v = -B1 / A11; DistSq = B1 * v + C; } } } else if(v < REAL(0.0)){ // region 5 v = REAL(0.0); if (B0 >= REAL(0.0)){ u = REAL(0.0); DistSq = C; } else if (-B0 >= A00){ u = REAL(1.0); DistSq = A00 + REAL(2.0) * B0 + C; } else{ u = -B0 / A00; DistSq = B0 * u + C; } } else{ // region 0 // minimum at interior point if (Det == REAL(0.0)){ u = REAL(0.0); v = REAL(0.0); DistSq = FLT_MAX; } else{ dReal InvDet = REAL(1.0) / Det; u *= InvDet; v *= InvDet; DistSq = u * (A00 * u + A01 * v + REAL(2.0) * B0) + v * (A01 * u + A11 * v + REAL(2.0) * B1) + C; } } } else{ dReal Tmp0, Tmp1, Numer, Denom; if(u < REAL(0.0)){ // region 2 Tmp0 = A01 + B0; Tmp1 = A11 + B1; if (Tmp1 > Tmp0){ Numer = Tmp1 - Tmp0; Denom = A00 - REAL(2.0) * A01 + A11; if (Numer >= Denom){ u = REAL(1.0); v = REAL(0.0); DistSq = A00 + REAL(2.0) * B0 + C; } else{ u = Numer / Denom; v = REAL(1.0) - u; DistSq = u * (A00 * u + A01 * v + REAL(2.0) * B0) + v * (A01 * u + A11 * v + REAL(2.0) * B1) + C; } } else{ u = REAL(0.0); if(Tmp1 <= REAL(0.0)){ v = REAL(1.0); DistSq = A11 + REAL(2.0) * B1 + C; } else if(B1 >= REAL(0.0)){ v = REAL(0.0); DistSq = C; } else{ v = -B1 / A11; DistSq = B1 * v + C; } } } else if(v < REAL(0.0)){ // region 6 Tmp0 = A01 + B1; Tmp1 = A00 + B0; if (Tmp1 > Tmp0){ Numer = Tmp1 - Tmp0; Denom = A00 - REAL(2.0) * A01 + A11; if (Numer >= Denom){ v = REAL(1.0); u = REAL(0.0); DistSq = A11 + REAL(2.0) * B1 + C; } else{ v = Numer / Denom; u = REAL(1.0) - v; DistSq = u * (A00 * u + A01 * v + REAL(2.0) * B0) + v * (A01 * u + A11 * v + REAL(2.0) * B1) + C; } } else{ v = REAL(0.0); if (Tmp1 <= REAL(0.0)){ u = REAL(1.0); DistSq = A00 + REAL(2.0) * B0 + C; } else if(B0 >= REAL(0.0)){ u = REAL(0.0); DistSq = C; } else{ u = -B0 / A00; DistSq = B0 * u + C; } } } else{ // region 1 Numer = A11 + B1 - A01 - B0; if (Numer <= REAL(0.0)){ u = REAL(0.0); v = REAL(1.0); DistSq = A11 + REAL(2.0) * B1 + C; } else{ Denom = A00 - REAL(2.0) * A01 + A11; if (Numer >= Denom){ u = REAL(1.0); v = REAL(0.0); DistSq = A00 + REAL(2.0) * B0 + C; } else{ u = Numer / Denom; v = REAL(1.0) - u; DistSq = u * (A00 * u + A01 * v + REAL(2.0) * B0) + v * (A01 * u + A11 * v + REAL(2.0) * B1) + C; } } } } Dist = dSqrt(dFabs(DistSq)); if (Dist <= Radius){ Dist = Radius - Dist; return true; } else return false; } int dCollideSTL(dxGeom* g1, dxGeom* SphereGeom, int Flags, dContactGeom* Contacts, int Stride){ dIASSERT (Stride >= (int)sizeof(dContactGeom)); dIASSERT (g1->type == dTriMeshClass); dIASSERT (SphereGeom->type == dSphereClass); dIASSERT ((Flags & NUMC_MASK) >= 1); dxTriMesh* TriMesh = (dxTriMesh*)g1; const unsigned uiTLSKind = TriMesh->getParentSpaceTLSKind(); dIASSERT(uiTLSKind == SphereGeom->getParentSpaceTLSKind()); // The colliding spaces must use matching cleanup method TrimeshCollidersCache *pccColliderCache = GetTrimeshCollidersCache(uiTLSKind); SphereCollider& Collider = pccColliderCache->m_SphereCollider; const dVector3& TLPosition = *(const dVector3*)dGeomGetPosition(TriMesh); const dMatrix3& TLRotation = *(const dMatrix3*)dGeomGetRotation(TriMesh); Matrix4x4 MeshMatrix; const dVector3 ZeroVector3 = { REAL(0.0), }; MakeMatrix(ZeroVector3, TLRotation, MeshMatrix); const dVector3& Position = *(const dVector3*)dGeomGetPosition(SphereGeom); dReal Radius = dGeomSphereGetRadius(SphereGeom); dVector3 OffsetPosition; dSubtractVectors3(OffsetPosition, Position, TLPosition); // Sphere Sphere Sphere; Sphere.mCenter.Set(OffsetPosition[0], OffsetPosition[1], OffsetPosition[2]); Sphere.mRadius = Radius; // TC results if (TriMesh->getDoTC(dxTriMesh::TTC_SPHERE)) { dxTriMesh::SphereTC* sphereTC = 0; const int sphereCacheSize = TriMesh->m_SphereTCCache.size(); for (int i = 0; i != sphereCacheSize; i++){ if (TriMesh->m_SphereTCCache[i].Geom == SphereGeom){ sphereTC = &TriMesh->m_SphereTCCache[i]; break; } } if (!sphereTC) { TriMesh->m_SphereTCCache.push(dxTriMesh::SphereTC()); sphereTC = &TriMesh->m_SphereTCCache[TriMesh->m_SphereTCCache.size() - 1]; sphereTC->Geom = SphereGeom; } // Intersect Collider.SetTemporalCoherence(true); Collider.Collide(*sphereTC, Sphere, TriMesh->retrieveMeshBVTreeRef(), null, &MeshMatrix); } else { Collider.SetTemporalCoherence(false); Collider.Collide(pccColliderCache->m_DefaultSphereCache, Sphere, TriMesh->retrieveMeshBVTreeRef(), null, &MeshMatrix); } if (! Collider.GetContactStatus()) { // no collision occurred return 0; } // get results int TriCount = Collider.GetNbTouchedPrimitives(); const int* Triangles = (const int*)Collider.GetTouchedPrimitives(); if (TriCount != 0){ if (TriMesh->m_ArrayCallback != null){ TriMesh->m_ArrayCallback(TriMesh, SphereGeom, Triangles, TriCount); } int OutTriCount = 0; for (int i = 0; i < TriCount; i++){ if (OutTriCount == (Flags & NUMC_MASK)){ break; } const int TriIndex = Triangles[i]; dVector3 dv[3]; if (!TriMesh->invokeCallback(SphereGeom, TriIndex)) continue; TriMesh->fetchMeshTriangle(dv, TriIndex, TLPosition, TLRotation); dVector3& v0 = dv[0]; dVector3& v1 = dv[1]; dVector3& v2 = dv[2]; dVector3 vu; vu[0] = v1[0] - v0[0]; vu[1] = v1[1] - v0[1]; vu[2] = v1[2] - v0[2]; vu[3] = REAL(0.0); dVector3 vv; vv[0] = v2[0] - v0[0]; vv[1] = v2[1] - v0[1]; vv[2] = v2[2] - v0[2]; vv[3] = REAL(0.0); // Get plane coefficients dVector4 Plane; dCalcVectorCross3(Plane, vu, vv); // Even though all triangles might be initially valid, // a triangle may degenerate into a segment after applying // space transformation. if (!dSafeNormalize3(Plane)) { continue; } /* If the center of the sphere is within the positive halfspace of the * triangle's plane, allow a contact to be generated. * If the center of the sphere made it into the positive halfspace of a * back-facing triangle, then the physics update and/or velocity needs * to be adjusted (penetration has occured anyway). */ dReal side = dCalcVectorDot3(Plane,Position) - dCalcVectorDot3(Plane, v0); if(side < REAL(0.0)) { continue; } dReal Depth; dReal u, v; if (!GetContactData(Position, Radius, v0, vu, vv, Depth, u, v)){ continue; // Sphere doesn't hit triangle } if (Depth < REAL(0.0)){ continue; // Negative depth does not produce a contact } dVector3 ContactPos; dReal w = REAL(1.0) - u - v; ContactPos[0] = (v0[0] * w) + (v1[0] * u) + (v2[0] * v); ContactPos[1] = (v0[1] * w) + (v1[1] * u) + (v2[1] * v); ContactPos[2] = (v0[2] * w) + (v1[2] * u) + (v2[2] * v); // Depth returned from GetContactData is depth along // contact point - sphere center direction // we'll project it to contact normal dVector3 dir; dir[0] = Position[0]-ContactPos[0]; dir[1] = Position[1]-ContactPos[1]; dir[2] = Position[2]-ContactPos[2]; dReal dirProj = dCalcVectorDot3(dir, Plane) / dSqrt(dCalcVectorDot3(dir, dir)); // Since Depth already had a requirement to be non-negative, // negative direction projections should not be allowed as well, // as otherwise the multiplication will result in negative contact depth. if (dirProj < REAL(0.0)){ continue; // Zero contact depth could be ignored } dContactGeom* Contact = SAFECONTACT(Flags, Contacts, OutTriCount, Stride); Contact->pos[0] = ContactPos[0]; Contact->pos[1] = ContactPos[1]; Contact->pos[2] = ContactPos[2]; Contact->pos[3] = REAL(0.0); // Using normal as plane (reversed) Contact->normal[0] = -Plane[0]; Contact->normal[1] = -Plane[1]; Contact->normal[2] = -Plane[2]; Contact->normal[3] = REAL(0.0); Contact->depth = Depth * dirProj; //Contact->depth = Radius - side; // (mg) penetration depth is distance along normal not shortest distance // We need to set these unconditionally, as the merging may fail! - Bram Contact->g1 = TriMesh; Contact->g2 = SphereGeom; Contact->side2 = -1; Contact->side1 = TriIndex; OutTriCount++; } if (OutTriCount > 0){ if (TriMesh->m_SphereContactsMergeOption == MERGE_CONTACTS_FULLY) { dContactGeom* Contact = SAFECONTACT(Flags, Contacts, 0, Stride); Contact->g1 = TriMesh; Contact->g2 = SphereGeom; Contact->side2 = -1; if (OutTriCount > 1 && !(Flags & CONTACTS_UNIMPORTANT)){ dVector3 pos; pos[0] = Contact->pos[0]; pos[1] = Contact->pos[1]; pos[2] = Contact->pos[2]; dVector3 normal; normal[0] = Contact->normal[0] * Contact->depth; normal[1] = Contact->normal[1] * Contact->depth; normal[2] = Contact->normal[2] * Contact->depth; normal[3] = REAL(0.0); int TriIndex = Contact->side1; for (int i = 1; i < OutTriCount; i++){ dContactGeom* TempContact = SAFECONTACT(Flags, Contacts, i, Stride); pos[0] += TempContact->pos[0]; pos[1] += TempContact->pos[1]; pos[2] += TempContact->pos[2]; normal[0] += TempContact->normal[0] * TempContact->depth; normal[1] += TempContact->normal[1] * TempContact->depth; normal[2] += TempContact->normal[2] * TempContact->depth; TriIndex = (TriMesh->m_TriMergeCallback) ? TriMesh->m_TriMergeCallback(TriMesh, TriIndex, TempContact->side1) : -1; } Contact->side1 = TriIndex; Contact->pos[0] = pos[0] / OutTriCount; Contact->pos[1] = pos[1] / OutTriCount; Contact->pos[2] = pos[2] / OutTriCount; if ( !dSafeNormalize3(normal) ) return OutTriCount; // Cannot merge in this pathological case // Using a merged normal, means that for each intersection, this new normal will be less effective in solving the intersection. // That is why we need to correct this by increasing the depth for each intersection. // The maximum of the adjusted depths is our newly merged depth value - Bram. dReal mergedDepth = REAL(0.0); dReal minEffectiveness = REAL(0.5); for ( int i = 0; i < OutTriCount; ++i ) { dContactGeom* TempContact = SAFECONTACT(Flags, Contacts, i, Stride); dReal effectiveness = dCalcVectorDot3(normal, TempContact->normal); if ( effectiveness < dEpsilon ) return OutTriCount; // Cannot merge this pathological case // Cap our adjustment for the new normal to a factor 2, meaning a 60 deg change in normal. effectiveness = ( effectiveness < minEffectiveness ) ? minEffectiveness : effectiveness; dReal adjusted = TempContact->depth / effectiveness; mergedDepth = ( mergedDepth < adjusted ) ? adjusted : mergedDepth; } Contact->depth = mergedDepth; Contact->normal[0] = normal[0]; Contact->normal[1] = normal[1]; Contact->normal[2] = normal[2]; Contact->normal[3] = normal[3]; } return 1; } else if (TriMesh->m_SphereContactsMergeOption == MERGE_CONTACT_NORMALS) { if (OutTriCount != 1 && !(Flags & CONTACTS_UNIMPORTANT)){ dVector3 Normal; dContactGeom* FirstContact = SAFECONTACT(Flags, Contacts, 0, Stride); Normal[0] = FirstContact->normal[0] * FirstContact->depth; Normal[1] = FirstContact->normal[1] * FirstContact->depth; Normal[2] = FirstContact->normal[2] * FirstContact->depth; Normal[3] = FirstContact->normal[3] * FirstContact->depth; for (int i = 1; i < OutTriCount; i++){ dContactGeom* Contact = SAFECONTACT(Flags, Contacts, i, Stride); Normal[0] += Contact->normal[0] * Contact->depth; Normal[1] += Contact->normal[1] * Contact->depth; Normal[2] += Contact->normal[2] * Contact->depth; Normal[3] += Contact->normal[3] * Contact->depth; } dNormalize3(Normal); for (int i = 0; i < OutTriCount; i++){ dContactGeom* Contact = SAFECONTACT(Flags, Contacts, i, Stride); Contact->normal[0] = Normal[0]; Contact->normal[1] = Normal[1]; Contact->normal[2] = Normal[2]; Contact->normal[3] = Normal[3]; } } return OutTriCount; } else { dIASSERT(TriMesh->m_SphereContactsMergeOption == DONT_MERGE_CONTACTS); return OutTriCount; } } else return 0; } else return 0; } #endif // dTRIMESH_OPCODE #if dTRIMESH_GIMPACT #include "gimpact_contact_export_helper.h" #include "gimpact_gim_contact_accessor.h" int dCollideSTL(dxGeom* g1, dxGeom* SphereGeom, int Flags, dContactGeom* Contacts, int Stride) { dIASSERT (Stride >= (int)sizeof(dContactGeom)); dIASSERT (g1->type == dTriMeshClass); dIASSERT (SphereGeom->type == dSphereClass); dIASSERT ((Flags & NUMC_MASK) >= 1); dxTriMesh* TriMesh = (dxTriMesh*)g1; dVector3& Position = *(dVector3*)dGeomGetPosition(SphereGeom); dReal Radius = dGeomSphereGetRadius(SphereGeom); //Create contact list GDYNAMIC_ARRAY trimeshcontacts; GIM_CREATE_CONTACT_LIST(trimeshcontacts); g1 -> recomputeAABB(); SphereGeom -> recomputeAABB(); //Collide trimeshes gim_trimesh_sphere_collisionODE(&TriMesh->m_collision_trimesh,Position,Radius,&trimeshcontacts); if(trimeshcontacts.m_size == 0) { GIM_DYNARRAY_DESTROY(trimeshcontacts); return 0; } GIM_CONTACT * ptrimeshcontacts = GIM_DYNARRAY_POINTER(GIM_CONTACT,trimeshcontacts); unsigned contactcount = trimeshcontacts.m_size; dxGIMCContactAccessor contactaccessor(ptrimeshcontacts, g1, SphereGeom, -1); contactcount = dxGImpactContactsExportHelper::ExportMaxDepthGImpactContacts(contactaccessor, contactcount, Flags, Contacts, Stride); GIM_DYNARRAY_DESTROY(trimeshcontacts); return (int)contactcount; } #endif // dTRIMESH_GIMPACT #endif // dTRIMESH_ENABLED ode-0.16/ode/src/common.h0000664000175200017520000002736313403272463012154 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_PRIVATE_COMMON_H_ #define _ODE_PRIVATE_COMMON_H_ #include "typedefs.h" #include "error.h" #include #include #ifndef SIZE_MAX #define SIZE_MAX ((sizeint)(-1)) #endif #define dMACRO_MAX(a, b) ((a) > (b) ? (a) : (b)) #define dMACRO_MIN(a, b) ((a) < (b) ? (a) : (b)) #ifdef dSINGLE #define dEpsilon FLT_EPSILON #else #define dEpsilon DBL_EPSILON #endif #ifdef dSINGLE #if !defined(FLT_MANT_DIG) #define FLT_MANT_DIG 24 #endif #define dMaxExact ((float)((1UL << FLT_MANT_DIG) - 1)) #define dMinExact ((float)(-dMaxExact)) #else // #ifndef dSINGLE #if !defined(DBL_MANT_DIG) #define DBL_MANT_DIG 53 #endif #define dMaxExact (double)((1ULL << DBL_MANT_DIG) - 1) #define dMinExact ((double)(-dMaxExact)) #endif // #ifndef dSINGLE #define dMaxIntExact dMACRO_MIN(dMaxExact, (dReal)INT_MAX) #define dMinIntExact dMACRO_MAX(dMinExact, (dReal)INT_MIN) #ifndef offsetof #define offsetof(s, m) ((sizeint)&(((s *)8)->m) - (sizeint)8) #endif #ifndef membersize #define membersize(s, m) (sizeof(((s *)8)->m)) #endif #ifndef endoffsetof #define endoffsetof(s, m) ((sizeint)((sizeint)&(((s *)8)->m) - (sizeint)8) + sizeof(((s *)8)->m)) #endif /* the efficient alignment. most platforms align data structures to some * number of bytes, but this is not always the most efficient alignment. * for example, many x86 compilers align to 4 bytes, but on a pentium it * is important to align doubles to 8 byte boundaries (for speed), and * the 4 floats in a SIMD register to 16 byte boundaries. many other * platforms have similar behavior. setting a larger alignment can waste * a (very) small amount of memory. NOTE: this number must be a power of * two. this is set to 16 by default. */ #ifndef EFFICIENT_ALIGNMENT #define EFFICIENT_ALIGNMENT 16 #endif #define dALIGN_SIZE(buf_size, alignment) (((buf_size) + (alignment - 1)) & (int)(~(alignment - 1))) // Casting the mask to int ensures sign-extension to larger integer sizes #define dALIGN_PTR(buf_ptr, alignment) ((void *)(((uintptr)(buf_ptr) + ((alignment) - 1)) & (int)(~(alignment - 1)))) // Casting the mask to int ensures sign-extension to larger integer sizes /* round something up to be a multiple of the EFFICIENT_ALIGNMENT */ #define dEFFICIENT_SIZE(x) dALIGN_SIZE(x, EFFICIENT_ALIGNMENT) #define dEFFICIENT_PTR(p) dALIGN_PTR(p, EFFICIENT_ALIGNMENT) #define dOFFSET_EFFICIENTLY(p, b) ((void *)((uintptr)(p) + dEFFICIENT_SIZE(b))) #define dOVERALIGNED_SIZE(size, alignment) dEFFICIENT_SIZE((size) + ((alignment) - EFFICIENT_ALIGNMENT)) #define dOVERALIGNED_PTR(buf_ptr, alignment) dALIGN_PTR(buf_ptr, alignment) #define dOFFSET_OVERALIGNEDLY(buf_ptr, size, alignment) ((void *)((uintptr)(buf_ptr) + dOVERALIGNED_SIZE(size, alignment))) #define dDERIVE_SIZE_UNION_PADDING_ELEMENTS(DataSize, ElementType) (((DataSize) + sizeof(ElementType) - 1) / sizeof(ElementType)) #define dDERIVE_TYPE_UNION_PADDING_ELEMENTS(DataType, ElementType) dDERIVE_SIZE_UNION_PADDING_ELEMENTS(sizeof(DataType), ElementType) #define dDERIVE_SIZE_EXTRA_PADDING_ELEMENTS(DataSize, AlignmentSize, ElementType) (((dALIGN_SIZE(DataSize, dMACRO_MAX(AlignmentSize, sizeof(ElementType))) - (DataSize)) / sizeof(ElementType)) /* alloca aligned to the EFFICIENT_ALIGNMENT. note that this can waste * up to 15 bytes per allocation, depending on what alloca() returns. */ #define dALLOCA16(n) \ dEFFICIENT_PTR(alloca((n)+(EFFICIENT_ALIGNMENT))) class dxAlignedAllocation { public: dxAlignedAllocation(): m_userAreaPointer(NULL), m_bufferAllocated(NULL), m_sizeUsed(0) {} ~dxAlignedAllocation() { freeAllocation(); } void *allocAligned(sizeint sizeRequired, unsigned alignmentRequired) { dIASSERT((alignmentRequired & (alignmentRequired - 1)) == 0); dIASSERT(alignmentRequired <= SIZE_MAX - sizeRequired); sizeint sizeToUse = sizeRequired + alignmentRequired; void *bufferPointer = dAlloc(sizeToUse); void *userAreaPointer = bufferPointer != NULL && alignmentRequired != 0 ? dALIGN_PTR(bufferPointer, alignmentRequired) : bufferPointer; assignData(userAreaPointer, bufferPointer, sizeToUse); return userAreaPointer; } void *getUserAreaPointer() const { return m_userAreaPointer; } sizeint getUserAreaSize() const { return m_sizeUsed - ((uint8 *)m_userAreaPointer - (uint8 *)m_bufferAllocated); } void freeAllocation() { sizeint sizeUsed; void *bufferPointer = extractData(sizeUsed); if (bufferPointer != NULL) { dFree(bufferPointer, sizeUsed); } } private: void assignData(void *userAreaPointer, void *bufferAllocated, sizeint sizeUsed) { dIASSERT(m_userAreaPointer == NULL); dIASSERT(m_bufferAllocated == NULL); dIASSERT(m_sizeUsed == 0); m_userAreaPointer = userAreaPointer; m_bufferAllocated = bufferAllocated; m_sizeUsed = sizeUsed; } void *extractData(sizeint &out_sizeUsed) { void *bufferPointer = m_bufferAllocated; if (bufferPointer != NULL) { out_sizeUsed = m_sizeUsed; m_userAreaPointer = NULL; m_bufferAllocated = NULL; m_sizeUsed = 0; } return bufferPointer; } private: void *m_userAreaPointer; void *m_bufferAllocated; sizeint m_sizeUsed; }; template inline bool _cast_to_smaller(DstType &dtOutResult, const SrcType &stArgument) { return (SrcType)(dtOutResult = (DstType)stArgument) == stArgument; } #if defined(__GNUC__) #define dCAST_TO_SMALLER(TargetType, SourceValue) ({ TargetType ttCastSmallerValue; dIVERIFY(_cast_to_smaller(ttCastSmallerValue, SourceValue)); ttCastSmallerValue; }) #else // #if !defined(__GNUC__) #define dCAST_TO_SMALLER(TargetType, SourceValue) templateCAST_TO_SMALLER(SourceValue) template inline TTargetType templateCAST_TO_SMALLER(const TSourceType &stSourceValue) { TTargetType ttCastSmallerValue; dIVERIFY(_cast_to_smaller(ttCastSmallerValue, stSourceValue)); return ttCastSmallerValue; } #endif // #if !defined(__GNUC__) template inline void dxSwap(value_type &one, value_type &another) { std::swap(one, another); } template inline value_type dxClamp(const value_type &value, const lo_type &lo, const hi_type &hi) { return value < lo ? (value_type)lo : value > hi ? (value_type)hi : value; } template union _const_type_cast_union { explicit _const_type_cast_union(const void *psvCharBuffer): m_psvCharBuffer(psvCharBuffer) {} operator const Type *() const { return m_pstTypedPointer; } const Type &operator *() const { return *m_pstTypedPointer; } const Type *operator ->() const { return m_pstTypedPointer; } const Type &operator [](diffint diElementIndex) const { return m_pstTypedPointer[diElementIndex]; } const Type &operator [](sizeint siElementIndex) const { return m_pstTypedPointer[siElementIndex]; } const void *m_psvCharBuffer; const Type *m_pstTypedPointer; }; template union _type_cast_union { explicit _type_cast_union(void *psvCharBuffer): m_psvCharBuffer(psvCharBuffer) {} operator Type *() const { return m_pstTypedPointer; } Type &operator *() const { return *m_pstTypedPointer; } Type *operator ->() const { return m_pstTypedPointer; } Type &operator [](diffint diElementIndex) const { return m_pstTypedPointer[diElementIndex]; } Type &operator [](sizeint siElementIndex) const { return m_pstTypedPointer[siElementIndex]; } void *m_psvCharBuffer; Type *m_pstTypedPointer; }; template struct _sized_signed; template<> struct _sized_signed { typedef int8 type; }; template<> struct _sized_signed { typedef int16 type; }; template<> struct _sized_signed { typedef int32 type; }; template<> struct _sized_signed { typedef int64 type; }; template struct _make_signed { typedef typename _sized_signed::type type; }; template struct _sized_unsigned; template<> struct _sized_unsigned { typedef uint8 type; }; template<> struct _sized_unsigned { typedef uint16 type; }; template<> struct _sized_unsigned { typedef uint32 type; }; template<> struct _sized_unsigned { typedef uint64 type; }; template struct _make_unsigned { typedef typename _sized_unsigned::type type; }; // template // inline // bool dxInRange(tvalueint viValue, tminint miMin, tmaxint miMax) // { // return (typename _sized_unsigned::type)(viValue - miMin) < (typename _sized_unsigned::type)(miMax - miMin); // } // #define dIN_RANGE(aval, amin, amax) dxInRange(aval, amin, amax) #define dIN_RANGE(aval, amin, amax) ((_sized_unsigned::type)((_sized_unsigned::type)(aval) - (_sized_unsigned::type)(amin)) < (_sized_unsigned::type)((_sized_unsigned::type)(amax) - (_sized_unsigned::type)(amin))) #define dTMPL_IN_RANGE(aval, amin, amax) ((typename _sized_unsigned::type)((typename _sized_unsigned::type)(aval) - (typename _sized_unsigned::type)(amin)) < (typename _sized_unsigned::type)((typename _sized_unsigned::type)(amax) - (typename _sized_unsigned::type)(amin))) #define dCLAMP(aval, alo, ahi) dxClamp(aval, alo, ahi) #define dARRAY_SIZE(aarr) (sizeof(aarr) / sizeof((aarr)[0])) #define dSTATIC_ARRAY_SIZE(aclass, aarr) dARRAY_SIZE(((aclass *)sizeof(void *))->aarr) #endif ode-0.16/ode/src/odeou.cpp0000664000175200017520000000777613403272463012340 00000000000000/************************************************************************* * * * OU library interface file for Open Dynamics Engine, * * Copyright (C) 2008 Oleh Derevenko. All rights reserved. * * Email: odar@eleks.com (change all "a" to "e") * * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* ODE interface to OU library implementation. */ #include #include #include "config.h" #include "odeou.h" #if dOU_ENABLED using _OU_NAMESPACE::EASSERTIONFAILURESEVERITY; using _OU_NAMESPACE::AFS__MAX; using _OU_NAMESPACE::CMemoryManagerCustomization; using _OU_NAMESPACE::CAssertionCheckCustomization; BEGIN_NAMESPACE_OU(); template<> const char *const CEnumUnsortedElementArray::m_aetElementArray[] = { "assert", // AFS_ASSERT, "check", // AFS_CHECK, }; END_NAMESPACE_OU(); static const CEnumUnsortedElementArray g_aszAssertionFailureSeverityNames; static void _OU_CONVENTION_CALLBACK ForwardOUAssertionFailure(EASSERTIONFAILURESEVERITY fsFailureSeverity, const char *szAssertionExpression, const char *szAssertionFileName, unsigned int uiAssertionSourceLine) { dDebug(d_ERR_IASSERT, "Assertion failure in OU Library. Kind: %s, expression: \"%s\", file: \"%s\", line: %u", g_aszAssertionFailureSeverityNames.Encode(fsFailureSeverity), szAssertionExpression, szAssertionFileName, uiAssertionSourceLine); } static void *_OU_CONVENTION_CALLBACK ForwardOUMemoryAlloc(size_t nBlockSize) { return dAlloc(nBlockSize); } static void *_OU_CONVENTION_CALLBACK ForwardOUMemoryRealloc(void *pv_ExistingBlock, size_t nBlockNewSize) { return dRealloc(pv_ExistingBlock, 0, nBlockNewSize); } static void _OU_CONVENTION_CALLBACK ForwardOUMemoryFree(void *pv_ExistingBlock) { return dFree(pv_ExistingBlock, 0); } bool COdeOu::DoOUCustomizations() { CMemoryManagerCustomization::CustomizeMemoryManager(&ForwardOUMemoryAlloc, &ForwardOUMemoryRealloc, &ForwardOUMemoryFree); CAssertionCheckCustomization::CustomizeAssertionChecks(&ForwardOUAssertionFailure); return true; } void COdeOu::UndoOUCustomizations() { CAssertionCheckCustomization::CustomizeAssertionChecks(NULL); CMemoryManagerCustomization::CustomizeMemoryManager(NULL, NULL, NULL); } #endif // dOU_ENABLED ode-0.16/ode/src/collision_space_internal.h0000664000175200017520000000644013403272463015717 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* stuff common to all spaces */ #ifndef _ODE_COLLISION_SPACE_INTERNAL_H_ #define _ODE_COLLISION_SPACE_INTERNAL_H_ #define ALLOCA(x) dALLOCA16(x) // collide two geoms together. for the hash table space, this is // called if the two AABBs inhabit the same hash table cells. // this only calls the callback function if the AABBs actually // intersect. if a geom has an AABB test function, that is called to // provide a further refinement of the intersection. // // NOTE: this assumes that the geom AABBs are valid on entry // and that both geoms are enabled. static inline void collideAABBs (dxGeom *g1, dxGeom *g2, void *data, dNearCallback *callback) { dIASSERT((g1->gflags & GEOM_AABB_BAD)==0); dIASSERT((g2->gflags & GEOM_AABB_BAD)==0); // no contacts if both geoms on the same body, and the body is not 0 if (g1->body == g2->body && g1->body) return; // test if the category and collide bitfields match if ( ((g1->category_bits & g2->collide_bits) || (g2->category_bits & g1->collide_bits)) == 0) { return; } // if the bounding boxes are disjoint then don't do anything dReal *bounds1 = g1->aabb; dReal *bounds2 = g2->aabb; if (bounds1[0] > bounds2[1] || bounds1[1] < bounds2[0] || bounds1[2] > bounds2[3] || bounds1[3] < bounds2[2] || bounds1[4] > bounds2[5] || bounds1[5] < bounds2[4]) { return; } // check if either object is able to prove that it doesn't intersect the // AABB of the other if (g1->AABBTest (g2,bounds2) == 0) return; if (g2->AABBTest (g1,bounds1) == 0) return; // the objects might actually intersect - call the space callback function callback (data,g1,g2); } #endif ode-0.16/ode/src/lcp.h0000664000175200017520000000572613403272463011441 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* given (A,b,lo,hi), solve the LCP problem: A*x = b+w, where each x(i),w(i) satisfies one of (1) x = lo, w >= 0 (2) x = hi, w <= 0 (3) lo < x < hi, w = 0 A is a matrix of dimension n*n, everything else is a vector of size n*1. lo and hi can be +/- dInfinity as needed. the first `nub' variables are unbounded, i.e. hi and lo are assumed to be +/- dInfinity. we restrict lo(i) <= 0 and hi(i) >= 0. the original data (A,b) may be modified by this function. if the `findex' (friction index) parameter is nonzero, it points to an array of index values. in this case constraints that have findex[i] >= 0 are special. all non-special constraints are solved for, then the lo and hi values for the special constraints are set: hi[i] = abs( hi[i] * x[findex[i]] ) lo[i] = -hi[i] and the solution continues. this mechanism allows a friction approximation to be implemented. the first `nub' variables are assumed to have findex < 0. */ #ifndef _ODE_LCP_H_ #define _ODE_LCP_H_ class dxWorldProcessMemArena; enum dxLCPBXElement { PBX__MIN, PBX_B = PBX__MIN, PBX_X, PBX__MAX, }; enum dxLCPLHElement { PLH__MIN, PLH_LO = PLH__MIN, PLH_HI, PLH__MAX, }; void dxSolveLCP (dxWorldProcessMemArena *memarena, unsigned n, dReal *A, dReal pairsbx[PBX__MAX], dReal *w, unsigned nub, dReal pairslh[PLH__MAX], int *findex); sizeint dxEstimateSolveLCPMemoryReq(unsigned n, bool outer_w_avail); #endif ode-0.16/ode/src/array.cpp0000664000175200017520000000533313403272463012326 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include #include #include "config.h" #include "array.h" static inline int roundUpToPowerOfTwo (int x) { int i = 1; while (i < x) i <<= 1; return i; } void dArrayBase::_freeAll (int sizeofT) { if (_data) { if (_data == this+1) return; // if constructLocalArray() was called dFree (_data,_anum * sizeofT); } } void dArrayBase::_setSize (int newsize, int sizeofT) { if (newsize < 0) return; if (newsize > _anum) { if (_data == this+1) { // this is a no-no, because constructLocalArray() was called dDebug (0,"setSize() out of space in LOCAL array"); } int newanum = roundUpToPowerOfTwo (newsize); if (_data) _data = dRealloc (_data, _anum*sizeofT, newanum*sizeofT); else _data = dAlloc (newanum*sizeofT); _anum = newanum; } _size = newsize; } void * dArrayBase::operator new (size_t size) { return dAlloc (size); } void dArrayBase::operator delete (void *ptr, size_t size) { dFree (ptr,size); } void dArrayBase::constructLocalArray (int __anum) { _size = 0; _anum = __anum; _data = this+1; } ode-0.16/ode/src/collision_trimesh_gimpact.h0000664000175200017520000002331513403272463016107 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ // TriMesh code by Erwin de Vries. // Modified for FreeSOLID Compatibility by Rodrigo Hernandez // Trimesh caches separation by Oleh Derevenko // TriMesh storage classes refactoring and face angle computation code by Oleh Derevenko (C) 2016-2017 #ifndef _ODE_COLLISION_TRIMESH_GIMPACT_H_ #define _ODE_COLLISION_TRIMESH_GIMPACT_H_ #if dTRIMESH_ENABLED && dTRIMESH_GIMPACT //**************************************************************************** // dxTriMesh class #include "collision_kernel.h" #include "collision_trimesh_colliders.h" #include "collision_util.h" #include #include "collision_trimesh_internal.h" #include struct TrimeshCollidersCache // Required for compatibility with OPCODE { }; typedef dxTriDataBase dxTriMeshData_Parent; struct dxTriMeshData: public dxTriMeshData_Parent { public: dxTriMeshData(): dxTriMeshData_Parent() { } ~dxTriMeshData() { /* Do nothing */ } using dxTriMeshData_Parent::buildData; /* Setup the UseFlags array and/or build face angles*/ bool preprocessData(bool buildUseFlags/*=false*/, FaceAngleStorageMethod faceAndgesRequirement/*=ASM__INVALID*/); private: bool meaningfulPreprocessData(FaceAngleStorageMethod faceAndgesRequirement/*=ASM__INVALID*/); public: /* For when app changes the vertices */ void updateData() { /* Do nothing */ } public: const vec3f *retrieveVertexInstances() const { return (const vec3f *)dxTriMeshData_Parent::retrieveVertexInstances(); } const GUINT32 *retrieveTriangleVertexIndices() const { return (const GUINT32 *)dxTriMeshData_Parent::retrieveTriangleVertexIndices(); } public: void assignNormals(const dReal *normals) { dxTriMeshData_Parent::assignNormals(normals); } const dReal *retrieveNormals() const { return (const dReal *)dxTriMeshData_Parent::retrieveNormals(); } sizeint calculateNormalsMemoryRequirement() const { return retrieveTriangleCount() * (sizeof(dReal) * dSA__MAX); } }; #ifdef dDOUBLE // To use GIMPACT with doubles, we need to patch a couple of the GIMPACT functions to // convert arguments to floats before sending them in /// Convert an gimpact vec3f to a ODE dVector3d: dVector3[i] = vec3f[i] #define dVECTOR3_VEC3F_COPY(b,a) { \ (b)[0] = (a)[0]; \ (b)[1] = (a)[1]; \ (b)[2] = (a)[2]; \ (b)[3] = 0; \ } static inline void gim_trimesh_get_triangle_verticesODE(GIM_TRIMESH * trimesh, GUINT32 triangle_index, dVector3 v1, dVector3 v2, dVector3 v3) { vec3f src1, src2, src3; GREAL *psrc1 = v1 != NULL ? src1 : NULL; GREAL *psrc2 = v2 != NULL ? src2 : NULL; GREAL *psrc3 = v3 != NULL ? src3 : NULL; gim_trimesh_get_triangle_vertices(trimesh, triangle_index, psrc1, psrc2, psrc3); if (v1 != NULL) { dVECTOR3_VEC3F_COPY(v1, src1); } if (v2 != NULL) { dVECTOR3_VEC3F_COPY(v2, src2); } if (v3 != NULL) { dVECTOR3_VEC3F_COPY(v3, src3); } } // Anything calling gim_trimesh_get_triangle_vertices from within ODE // should be patched through to the dDOUBLE version above #define gim_trimesh_get_triangle_vertices gim_trimesh_get_triangle_verticesODE static inline int gim_trimesh_ray_closest_collisionODE( GIM_TRIMESH *mesh, dVector3 origin, dVector3 dir, dReal tmax, GIM_TRIANGLE_RAY_CONTACT_DATA *contact ) { vec3f dir_vec3f = { (GREAL)dir[ 0 ], (GREAL)dir[ 1 ], (GREAL)dir[ 2 ] }; vec3f origin_vec3f = { (GREAL)origin[ 0 ], (GREAL)origin[ 1 ], (GREAL)origin[ 2 ] }; return gim_trimesh_ray_closest_collision( mesh, origin_vec3f, dir_vec3f, (GREAL)tmax, contact ); } static inline int gim_trimesh_ray_collisionODE( GIM_TRIMESH *mesh, const dVector3 origin, const dVector3 dir, dReal tmax, GIM_TRIANGLE_RAY_CONTACT_DATA *contact ) { vec3f dir_vec3f = { (GREAL)dir[ 0 ], (GREAL)dir[ 1 ], (GREAL)dir[ 2 ] }; vec3f origin_vec3f = { (GREAL)origin[ 0 ], (GREAL)origin[ 1 ], (GREAL)origin[ 2 ] }; return gim_trimesh_ray_collision( mesh, origin_vec3f, dir_vec3f, (GREAL)tmax, contact ); } static inline void gim_trimesh_sphere_collisionODE( GIM_TRIMESH *mesh, const dVector3 Position, dReal Radius, GDYNAMIC_ARRAY *contact ) { vec3f pos_vec3f = { (GREAL)Position[ 0 ], (GREAL)Position[ 1 ], (GREAL)Position[ 2 ] }; gim_trimesh_sphere_collision( mesh, pos_vec3f, (GREAL)Radius, contact ); } static inline void gim_trimesh_plane_collisionODE( GIM_TRIMESH *mesh, const dVector4 plane, GDYNAMIC_ARRAY *contact ) { vec4f plane_vec4f = { (GREAL)plane[ 0 ], (GREAL)plane[ 1 ], (GREAL)plane[ 2 ], (GREAL)plane[ 3 ] }; \ gim_trimesh_plane_collision( mesh, plane_vec4f, contact ); \ } #define GIM_AABB_COPY( src, dst ) { \ (dst)[ 0 ]= (src) -> minX; \ (dst)[ 1 ]= (src) -> maxX; \ (dst)[ 2 ]= (src) -> minY; \ (dst)[ 3 ]= (src) -> maxY; \ (dst)[ 4 ]= (src) -> minZ; \ (dst)[ 5 ]= (src) -> maxZ; \ } #else // #ifdef !dDOUBLE // With single precision, we can pass native ODE vectors directly to GIMPACT #define gim_trimesh_ray_closest_collisionODE gim_trimesh_ray_closest_collision #define gim_trimesh_ray_collisionODE gim_trimesh_ray_collision #define gim_trimesh_sphere_collisionODE gim_trimesh_sphere_collision #define gim_trimesh_plane_collisionODE gim_trimesh_plane_collision #define GIM_AABB_COPY( src, dst ) memcpy( dst, src, 6 * sizeof( GREAL ) ) #endif // #ifdef !dDOUBLE typedef dxMeshBase dxTriMesh_Parent; struct dxTriMesh: public dxTriMesh_Parent { public: // Functions dxTriMesh(dxSpace *Space, dxTriMeshData *Data, dTriCallback *Callback, dTriArrayCallback *ArrayCallback, dTriRayCallback *RayCallback): dxTriMesh_Parent(Space, NULL, Callback, ArrayCallback, RayCallback, true) // TC has speed/space 'issues' that don't make it a clear win by default on spheres/boxes. { gim_init_buffer_managers(m_buffer_managers); assignMeshData(Data); } ~dxTriMesh(); void clearTCCache() { /* do nothing */ } virtual void computeAABB(); public: dxTriMeshData *retrieveMeshData() const { return getMeshData(); } unsigned getMeshTriangleCount() const { return gim_trimesh_get_triangle_count(const_cast(&m_collision_trimesh)); } void fetchMeshTransformedTriangle(dVector3 *const pout_triangle[3], unsigned index) { gim_trimesh_locks_work_data(&m_collision_trimesh); gim_trimesh_get_triangle_vertices(&m_collision_trimesh, (GUINT32)index, *pout_triangle[0], *pout_triangle[1], *pout_triangle[2]); gim_trimesh_unlocks_work_data(&m_collision_trimesh); } void fetchMeshTransformedTriangle(dVector3 out_triangle[3], unsigned index) { gim_trimesh_locks_work_data(&m_collision_trimesh); gim_trimesh_get_triangle_vertices(&m_collision_trimesh, (GUINT32)index, out_triangle[0], out_triangle[1], out_triangle[2]); gim_trimesh_unlocks_work_data(&m_collision_trimesh); } private: dxTriMeshData *getMeshData() const { return static_cast(dxTriMesh_Parent::getMeshData()); } public: enum { VERTEXINSTANCE_STRIDE = sizeof(vec3f), TRIANGLEINDEX_STRIDE = sizeof(GUINT32) * dMTV__MAX, }; void assignMeshData(dxTriMeshData *Data); public: GIM_TRIMESH m_collision_trimesh; GBUFFER_MANAGER_DATA m_buffer_managers[G_BUFFER_MANAGER__MAX]; }; static inline void MakeMatrix(const dVector3 position, const dMatrix3 rotation, mat4f m) { m[0][0] = (GREAL)rotation[dM3E_XX]; m[0][1] = (GREAL)rotation[dM3E_XY]; m[0][2] = (GREAL)rotation[dM3E_XZ]; m[1][0] = (GREAL)rotation[dM3E_YX]; m[1][1] = (GREAL)rotation[dM3E_YY]; m[1][2] = (GREAL)rotation[dM3E_YZ]; m[2][0] = (GREAL)rotation[dM3E_ZX]; m[2][1] = (GREAL)rotation[dM3E_ZY]; m[2][2] = (GREAL)rotation[dM3E_ZZ]; m[0][3] = (GREAL)position[dV3E_X]; m[1][3] = (GREAL)position[dV3E_Y]; m[2][3] = (GREAL)position[dV3E_Z]; } static inline void MakeMatrix(dxGeom *g, mat4f m) { const dVector3 &position = g->buildUpdatedPosition(); const dMatrix3 &rotation = g->buildUpdatedRotation(); MakeMatrix(position, rotation, m); } #endif // #if dTRIMESH_ENABLED && dTRIMESH_GIMPACT #endif //_ODE_COLLISION_TRIMESH_GIMPACT_H_ ode-0.16/ode/src/convex.cpp0000664000175200017520000016376213403272463012525 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* Code for Convex Collision Detection By Rodrigo Hernandez */ #include #include #include #include "config.h" #include "matrix.h" #include "odemath.h" #include "collision_kernel.h" #include "collision_std.h" #include "collision_util.h" #ifdef _MSC_VER #pragma warning(disable:4291) // for VC++, no complaints about "no matching operator delete found" #endif #if 1 #define dMIN(A,B) ((A)>(B) ? (B) : (A)) #define dMAX(A,B) ((A)>(B) ? (A) : (B)) #else #define dMIN(A,B) std::min(A,B) #define dMAX(A,B) std::max(A,B) #endif //**************************************************************************** // Convex public API dxConvex::dxConvex (dSpaceID space, const dReal *_planes, unsigned int _planecount, const dReal *_points, unsigned int _pointcount, const unsigned int *_polygons) : dxGeom (space,1) { dAASSERT (_planes != NULL); dAASSERT (_points != NULL); dAASSERT (_polygons != NULL); //fprintf(stdout,"dxConvex Constructor planes %X\n",_planes); type = dConvexClass; planes = _planes; planecount = _planecount; // we need points as well points = _points; pointcount = _pointcount; polygons=_polygons; edges = NULL; FillEdges(); #ifndef dNODEBUG // Check for properly build polygons by calculating the determinant // of the 3x3 matrix composed of the first 3 points in the polygon. const unsigned int *points_in_poly=polygons; const unsigned int *index=polygons+1; for(unsigned int i=0;i 2 ); if(( points[(index[0]*3)+0]*points[(index[1]*3)+1]*points[(index[2]*3)+2] + points[(index[0]*3)+1]*points[(index[1]*3)+2]*points[(index[2]*3)+0] + points[(index[0]*3)+2]*points[(index[1]*3)+0]*points[(index[2]*3)+1] - points[(index[0]*3)+2]*points[(index[1]*3)+1]*points[(index[2]*3)+0] - points[(index[0]*3)+1]*points[(index[1]*3)+0]*points[(index[2]*3)+2] - points[(index[0]*3)+0]*points[(index[1]*3)+2]*points[(index[2]*3)+1])<0) { fprintf(stdout,"WARNING: Polygon %d is not defined counterclockwise\n",i); } points_in_poly+=(*points_in_poly+1); index=points_in_poly+1; if(planes[(i*4)+3]<0) fprintf(stdout,"WARNING: Plane %d does not contain the origin\n",i); } #endif //CreateTree(); } void dxConvex::computeAABB() { // this can, and should be optimized dVector3 point; dMultiply0_331 (point,final_posr->R,points); aabb[0] = point[0]+final_posr->pos[0]; aabb[1] = point[0]+final_posr->pos[0]; aabb[2] = point[1]+final_posr->pos[1]; aabb[3] = point[1]+final_posr->pos[1]; aabb[4] = point[2]+final_posr->pos[2]; aabb[5] = point[2]+final_posr->pos[2]; for(unsigned int i=3;i<(pointcount*3);i+=3) { dMultiply0_331 (point,final_posr->R,&points[i]); aabb[0] = dMIN(aabb[0],point[0]+final_posr->pos[0]); aabb[1] = dMAX(aabb[1],point[0]+final_posr->pos[0]); aabb[2] = dMIN(aabb[2],point[1]+final_posr->pos[1]); aabb[3] = dMAX(aabb[3],point[1]+final_posr->pos[1]); aabb[4] = dMIN(aabb[4],point[2]+final_posr->pos[2]); aabb[5] = dMAX(aabb[5],point[2]+final_posr->pos[2]); } } /*! \brief Populates the edges set, should be called only once whenever the polygon array gets updated */ void dxConvex::FillEdges() { const unsigned int *points_in_poly=polygons; const unsigned int *index=polygons+1; if (edges!=NULL) delete[] edges; edgecount = 0; edge e; bool isinset; for(unsigned int i=0;i Arcs,std::vector Polygons) { #if 0 dVector3 ea,eb,e; dVector3Copy(points+((edges.begin()+Arcs[0].edge)first*3),ea); dMultiply0_331(e1b,cvx1.final_posr->R,cvx1.points+(i->second*3)); dVector3Copy(points[edges[Arcs[0].edge] #endif return NULL; } void dxConvex::CreateTree() { std::vector A; A.reserve(edgecount); for(unsigned int i=0;iGetFacesSharedByEdge(i,A[i].normals); A[i].edge = i; } std::vector S; S.reserve(pointcount); for(unsigned int i=0;iGetFacesSharedByVertex(i,S[i].normals); S[i].vertex=i; } this->tree = CreateNode(A,S); } void dxConvex::GetFacesSharedByVertex(int i, std::vector f) { } void dxConvex::GetFacesSharedByEdge(int i, int* f) { } void dxConvex::GetFaceNormal(int i, dVector3 normal) { } #endif dGeomID dCreateConvex (dSpaceID space,const dReal *_planes,unsigned int _planecount, const dReal *_points, unsigned int _pointcount, const unsigned int *_polygons) { //fprintf(stdout,"dxConvex dCreateConvex\n"); return new dxConvex(space,_planes, _planecount, _points, _pointcount, _polygons); } void dGeomSetConvex (dGeomID g,const dReal *_planes,unsigned int _planecount, const dReal *_points, unsigned int _pointcount, const unsigned int *_polygons) { //fprintf(stdout,"dxConvex dGeomSetConvex\n"); dUASSERT (g && g->type == dConvexClass,"argument not a convex shape"); dxConvex *s = (dxConvex*) g; s->planes = _planes; s->planecount = _planecount; s->points = _points; s->pointcount = _pointcount; s->polygons=_polygons; } //**************************************************************************** // Helper Inlines // /*! \brief Returns Whether or not the segment ab intersects plane p \param a origin of the segment \param b segment destination \param p plane to test for intersection \param t returns the time "t" in the segment ray that gives us the intersecting point \param q returns the intersection point \return true if there is an intersection, otherwise false. */ bool IntersectSegmentPlane(dVector3 a, dVector3 b, dVector4 p, dReal &t, dVector3 q) { // Compute the t value for the directed line ab intersecting the plane dVector3 ab; ab[0]= b[0] - a[0]; ab[1]= b[1] - a[1]; ab[2]= b[2] - a[2]; t = (p[3] - dCalcVectorDot3(p,a)) / dCalcVectorDot3(p,ab); // If t in [0..1] compute and return intersection point if (t >= 0.0 && t <= 1.0) { q[0] = a[0] + t * ab[0]; q[1] = a[1] + t * ab[1]; q[2] = a[2] + t * ab[2]; return true; } // Else no intersection return false; } /*! \brief Returns the Closest Point in Ray 1 to Ray 2 \param Origin1 The origin of Ray 1 \param Direction1 The direction of Ray 1 \param Origin1 The origin of Ray 2 \param Direction1 The direction of Ray 3 \param t the time "t" in Ray 1 that gives us the closest point (closest_point=Origin1+(Direction1*t). \return true if there is a closest point, false if the rays are paralell. */ inline bool ClosestPointInRay(const dVector3 Origin1, const dVector3 Direction1, const dVector3 Origin2, const dVector3 Direction2, dReal& t) { dVector3 w = {Origin1[0]-Origin2[0], Origin1[1]-Origin2[1], Origin1[2]-Origin2[2]}; dReal a = dCalcVectorDot3(Direction1 , Direction1); dReal b = dCalcVectorDot3(Direction1 , Direction2); dReal c = dCalcVectorDot3(Direction2 , Direction2); dReal d = dCalcVectorDot3(Direction1 , w); dReal e = dCalcVectorDot3(Direction2 , w); dReal denominator = (a*c)-(b*b); if(denominator==0.0f) { return false; } t = ((a*e)-(b*d))/denominator; return true; } /*! \brief Returns the Closest Points from Segment 1 to Segment 2 \param p1 start of segment 1 \param q1 end of segment 1 \param p2 start of segment 2 \param q2 end of segment 2 \param t the time "t" in Ray 1 that gives us the closest point (closest_point=Origin1+(Direction1*t). \return true if there is a closest point, false if the rays are paralell. \note Adapted from Christer Ericson's Real Time Collision Detection Book. */ inline void ClosestPointBetweenSegments(dVector3& p1, dVector3& q1, dVector3& p2, dVector3& q2, dVector3& c1, dVector3& c2) { // s & t were originaly part of the output args, but since // we don't really need them, we'll just declare them in here dReal s; dReal t; dVector3 d1 = {q1[0] - p1[0], q1[1] - p1[1], q1[2] - p1[2]}; dVector3 d2 = {q2[0] - p2[0], q2[1] - p2[1], q2[2] - p2[2]}; dVector3 r = {p1[0] - p2[0], p1[1] - p2[1], p1[2] - p2[2]}; dReal a = dCalcVectorDot3(d1, d1); dReal e = dCalcVectorDot3(d2, d2); dReal f = dCalcVectorDot3(d2, r); // Check if either or both segments degenerate into points if (a <= dEpsilon && e <= dEpsilon) { // Both segments degenerate into points s = t = 0.0f; dVector3Copy(p1,c1); dVector3Copy(p2,c2); return; } if (a <= dEpsilon) { // First segment degenerates into a point s = 0.0f; t = f / e; // s = 0 => t = (b*s + f) / e = f / e t = dxClamp(t, 0.0f, 1.0f); } else { dReal c = dCalcVectorDot3(d1, r); if (e <= dEpsilon) { // Second segment degenerates into a point t = 0.0f; s = dxClamp(-c / a, 0.0f, 1.0f); // t = 0 => s = (b*t - c) / a = -c / a } else { // The general non degenerate case starts here dReal b = dCalcVectorDot3(d1, d2); dReal denom = a*e-b*b; // Always nonnegative // If segments not parallel, compute closest point on L1 to L2, and // clamp to segment S1. Else pick arbitrary s (here 0) if (denom != 0.0f) { s = dxClamp((b*f - c*e) / denom, 0.0f, 1.0f); } else s = 0.0f; #if 0 // Compute point on L2 closest to S1(s) using // t = Dot((P1+D1*s)-P2,D2) / Dot(D2,D2) = (b*s + f) / e t = (b*s + f) / e; // If t in [0,1] done. Else clamp t, recompute s for the new value // of t using s = Dot((P2+D2*t)-P1,D1) / Dot(D1,D1)= (t*b - c) / a // and clamp s to [0, 1] if (t < 0.0f) { t = 0.0f; s = dxClamp(-c / a, 0.0f, 1.0f); } else if (t > 1.0f) { t = 1.0f; s = dxClamp((b - c) / a, 0.0f, 1.0f); } #else dReal tnom = b*s + f; if (tnom < 0.0f) { t = 0.0f; s = dxClamp(-c / a, 0.0f, 1.0f); } else if (tnom > e) { t = 1.0f; s = dxClamp((b - c) / a, 0.0f, 1.0f); } else { t = tnom / e; } #endif } } c1[0] = p1[0] + d1[0] * s; c1[1] = p1[1] + d1[1] * s; c1[2] = p1[2] + d1[2] * s; c2[0] = p2[0] + d2[0] * t; c2[1] = p2[1] + d2[1] * t; c2[2] = p2[2] + d2[2] * t; } #if 0 dReal tnom = b*s + f; if (tnom < 0.0f) { t = 0.0f; s = dxClamp(-c / a, 0.0f, 1.0f); } else if (tnom > e) { t = 1.0f; s = dxClamp((b - c) / a, 0.0f, 1.0f); } else { t = tnom / e; } #endif /*! \brief Returns the Ray on which 2 planes intersect if they do. \param p1 Plane 1 \param p2 Plane 2 \param p Contains the origin of the ray upon returning if planes intersect \param d Contains the direction of the ray upon returning if planes intersect \return true if the planes intersect, false if paralell. */ inline bool IntersectPlanes(const dVector4 p1, const dVector4 p2, dVector3 p, dVector3 d) { // Compute direction of intersection line dCalcVectorCross3(d,p1,p2); // If d is (near) zero, the planes are parallel (and separated) // or coincident, so they're not considered intersecting dReal denom = dCalcVectorDot3(d, d); if (denom < dEpsilon) return false; dVector3 n; n[0]=p1[3]*p2[0] - p2[3]*p1[0]; n[1]=p1[3]*p2[1] - p2[3]*p1[1]; n[2]=p1[3]*p2[2] - p2[3]*p1[2]; // Compute point on intersection line dCalcVectorCross3(p,n,d); p[0]/=denom; p[1]/=denom; p[2]/=denom; return true; } #if 0 /*! \brief Finds out if a point lies inside a convex \param p Point to test \param convex a pointer to convex to test against \return true if the point lies inside the convex, false if not. */ inline bool IsPointInConvex(dVector3 p, dxConvex *convex) { dVector3 lp,tmp; // move point into convex space to avoid plane local to world calculations tmp[0] = p[0] - convex->final_posr->pos[0]; tmp[1] = p[1] - convex->final_posr->pos[1]; tmp[2] = p[2] - convex->final_posr->pos[2]; dMultiply1_331 (lp,convex->final_posr->R,tmp); for(unsigned int i=0;iplanecount;++i) { if(( ((convex->planes+(i*4))[0]*lp[0])+ ((convex->planes+(i*4))[1]*lp[1])+ ((convex->planes+(i*4))[2]*lp[2])+ -(convex->planes+(i*4))[3] )>0) { return false; } } return true; } #endif /*! \brief Finds out if a point lies inside a 2D polygon \param p Point to test \param polygon a pointer to the start of the convex polygon index buffer \param out the closest point in the polygon if the point is not inside \return true if the point lies inside of the polygon, false if not. */ inline bool IsPointInPolygon(dVector3 p, const unsigned int *polygon, dReal *plane, dxConvex *convex, dVector3 out) { // p is the point we want to check, // polygon is a pointer to the polygon we // are checking against, remember it goes // number of vertices then that many indexes // out returns the closest point on the border of the // polygon if the point is not inside it. dVector3 a; dVector3 b; dVector3 ab; dVector3 ap; dVector3 v; unsigned pointcount=polygon[0]; dIASSERT(pointcount != 0); polygon++; // skip past pointcount dMultiply0_331 (b,convex->final_posr->R, &convex->points[(polygon[pointcount-1]*3)]); b[0]=convex->final_posr->pos[0]+b[0]; b[1]=convex->final_posr->pos[1]+b[1]; b[2]=convex->final_posr->pos[2]+b[2]; for(unsigned i=0; i != pointcount; ++i) { a[0] = b[0]; a[1] = b[1]; a[2] = b[2]; dMultiply0_331 (b,convex->final_posr->R,&convex->points[(polygon[i]*3)]); b[0]=convex->final_posr->pos[0]+b[0]; b[1]=convex->final_posr->pos[1]+b[1]; b[2]=convex->final_posr->pos[2]+b[2]; ab[0] = b[0] - a[0]; ab[1] = b[1] - a[1]; ab[2] = b[2] - a[2]; ap[0] = p[0] - a[0]; ap[1] = p[1] - a[1]; ap[2] = p[2] - a[2]; dCalcVectorCross3(v, ab, plane); if (dCalcVectorDot3(ap, v) > REAL(0.0)) { dReal ab_m2 = dCalcVectorDot3(ab, ab); dReal s = ab_m2 != REAL(0.0) ? dCalcVectorDot3(ab, ap) / ab_m2 : REAL(0.0); if (s <= REAL(0.0)) { out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; } else if (s >= REAL(1.0)) { out[0] = b[0]; out[1] = b[1]; out[2] = b[2]; } else { out[0] = a[0] + ab[0] * s; out[1] = a[1] + ab[1] * s; out[2] = a[2] + ab[2] * s; } return false; } } return true; } int dCollideConvexPlane (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) { dIASSERT (skip >= (int)sizeof(dContactGeom)); dIASSERT (o1->type == dConvexClass); dIASSERT (o2->type == dPlaneClass); dIASSERT ((flags & NUMC_MASK) >= 1); dxConvex *Convex = (dxConvex*) o1; dxPlane *Plane = (dxPlane*) o2; unsigned int contacts=0; unsigned int maxc = flags & NUMC_MASK; dVector3 v2; #define LTEQ_ZERO 0x10000000 #define GTEQ_ZERO 0x20000000 #define BOTH_SIGNS (LTEQ_ZERO | GTEQ_ZERO) dIASSERT((BOTH_SIGNS & NUMC_MASK) == 0); // used in conditional operator later unsigned int totalsign = 0; for(unsigned int i=0;ipointcount;++i) { dMultiply0_331 (v2,Convex->final_posr->R,&Convex->points[(i*3)]); dVector3Add(Convex->final_posr->pos, v2, v2); unsigned int distance2sign = GTEQ_ZERO; dReal distance2 = dVector3Dot(Plane->p, v2) - Plane->p[3]; // Ax + By + Cz - D if((distance2 <= REAL(0.0))) { distance2sign = distance2 != REAL(0.0) ? LTEQ_ZERO : BOTH_SIGNS; if (contacts != maxc) { dContactGeom *target = SAFECONTACT(flags, contact, contacts, skip); dVector3Copy(Plane->p, target->normal); dVector3Copy(v2, target->pos); target->depth = -distance2; target->g1 = Convex; target->g2 = Plane; target->side1 = -1; // TODO: set plane index? target->side2 = -1; contacts++; } } // Take new sign into account totalsign |= distance2sign; // Check if contacts are full and both signs have been already found if (((contacts ^ maxc) | totalsign) == BOTH_SIGNS) // harder to comprehend but requires one register less { break; // Nothing can be changed any more } } if (totalsign == BOTH_SIGNS) return contacts; return 0; #undef BOTH_SIGNS #undef GTEQ_ZERO #undef LTEQ_ZERO } int dCollideSphereConvex (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) { dIASSERT (skip >= (int)sizeof(dContactGeom)); dIASSERT (o1->type == dSphereClass); dIASSERT (o2->type == dConvexClass); dIASSERT ((flags & NUMC_MASK) >= 1); dxSphere *Sphere = (dxSphere*) o1; dxConvex *Convex = (dxConvex*) o2; dReal dist,closestdist=dInfinity; dVector4 plane; // dVector3 contactpoint; dVector3 offsetpos,out,temp; const unsigned int *pPoly=Convex->polygons; int closestplane=-1; bool sphereinside=true; /* Do a good old sphere vs plane check first, if a collision is found then check if the contact point is within the polygon */ // offset the sphere final_posr->position into the convex space offsetpos[0]=Sphere->final_posr->pos[0]-Convex->final_posr->pos[0]; offsetpos[1]=Sphere->final_posr->pos[1]-Convex->final_posr->pos[1]; offsetpos[2]=Sphere->final_posr->pos[2]-Convex->final_posr->pos[2]; for(unsigned int i=0;iplanecount;++i) { // apply rotation to the plane dMultiply0_331(plane,Convex->final_posr->R,&Convex->planes[(i*4)]); plane[3]=(&Convex->planes[(i*4)])[3]; // Get the distance from the sphere origin to the plane dist = dVector3Dot(plane, offsetpos) - plane[3]; // Ax + By + Cz - D if(dist>0) { // if we get here, we know the center of the sphere is // outside of the convex hull. if(distradius) { // if we get here we know the sphere surface penetrates // the plane if(IsPointInPolygon(Sphere->final_posr->pos,pPoly,plane,Convex,out)) { // finally if we get here we know that the // sphere is directly touching the inside of the polyhedron contact->normal[0] = plane[0]; contact->normal[1] = plane[1]; contact->normal[2] = plane[2]; contact->pos[0] = Sphere->final_posr->pos[0]+ (-contact->normal[0]*Sphere->radius); contact->pos[1] = Sphere->final_posr->pos[1]+ (-contact->normal[1]*Sphere->radius); contact->pos[2] = Sphere->final_posr->pos[2]+ (-contact->normal[2]*Sphere->radius); contact->depth = Sphere->radius-dist; contact->g1 = Sphere; contact->g2 = Convex; contact->side1 = -1; contact->side2 = -1; // TODO: set plane index? return 1; } else { // the sphere may not be directly touching // the polyhedron, but it may be touching // a point or an edge, if the distance between // the closest point on the poly (out) and the // center of the sphere is less than the sphere // radius we have a hit. temp[0] = (Sphere->final_posr->pos[0]-out[0]); temp[1] = (Sphere->final_posr->pos[1]-out[1]); temp[2] = (Sphere->final_posr->pos[2]-out[2]); dist=(temp[0]*temp[0])+(temp[1]*temp[1])+(temp[2]*temp[2]); // avoid the sqrt unless really necesary if(dist<(Sphere->radius*Sphere->radius)) { // We got an indirect hit dist=dSqrt(dist); contact->normal[0] = temp[0]/dist; contact->normal[1] = temp[1]/dist; contact->normal[2] = temp[2]/dist; contact->pos[0] = Sphere->final_posr->pos[0]+ (-contact->normal[0]*Sphere->radius); contact->pos[1] = Sphere->final_posr->pos[1]+ (-contact->normal[1]*Sphere->radius); contact->pos[2] = Sphere->final_posr->pos[2]+ (-contact->normal[2]*Sphere->radius); contact->depth = Sphere->radius-dist; contact->g1 = Sphere; contact->g2 = Convex; contact->side1 = -1; contact->side2 = -1; // TODO: set plane index? return 1; } } } sphereinside=false; } if(sphereinside) { if(closestdist>dFabs(dist)) { closestdist=dFabs(dist); closestplane=i; } } pPoly+=pPoly[0]+1; } if(sphereinside) { // if the center of the sphere is inside // the Convex, we need to pop it out dMultiply0_331(contact->normal, Convex->final_posr->R, &Convex->planes[(closestplane*4)]); contact->pos[0] = Sphere->final_posr->pos[0]; contact->pos[1] = Sphere->final_posr->pos[1]; contact->pos[2] = Sphere->final_posr->pos[2]; contact->depth = closestdist+Sphere->radius; contact->g1 = Sphere; contact->g2 = Convex; contact->side1 = -1; contact->side2 = -1; // TODO: set plane index? return 1; } return 0; } int dCollideConvexBox (dxGeom *o1, dxGeom *o2, int flags, dContactGeom * /*contact*/, int skip) { dIASSERT (skip >= (int)sizeof(dContactGeom)); dIASSERT (o1->type == dConvexClass); dIASSERT (o2->type == dBoxClass); dIASSERT ((flags & NUMC_MASK) >= 1); //dxConvex *Convex = (dxConvex*) o1; //dxBox *Box = (dxBox*) o2; return 0; } int dCollideConvexCapsule (dxGeom *o1, dxGeom *o2, int flags, dContactGeom * /*contact*/, int skip) { dIASSERT (skip >= (int)sizeof(dContactGeom)); dIASSERT (o1->type == dConvexClass); dIASSERT (o2->type == dCapsuleClass); dIASSERT ((flags & NUMC_MASK) >= 1); //dxConvex *Convex = (dxConvex*) o1; //dxCapsule *Capsule = (dxCapsule*) o2; return 0; } inline void ComputeInterval(dxConvex& cvx,dVector4 axis,dReal& min,dReal& max) { /* TODO: Use Support points here */ dVector3 point; dReal value; //fprintf(stdout,"Compute Interval Axis %f,%f,%f\n",axis[0],axis[1],axis[2]); dMultiply0_331(point,cvx.final_posr->R,cvx.points); //fprintf(stdout,"initial point %f,%f,%f\n",point[0],point[1],point[2]); point[0]+=cvx.final_posr->pos[0]; point[1]+=cvx.final_posr->pos[1]; point[2]+=cvx.final_posr->pos[2]; max = min = dCalcVectorDot3(point,axis)-axis[3];//(*) for (unsigned int i = 1; i < cvx.pointcount; ++i) { dMultiply0_331(point,cvx.final_posr->R,cvx.points+(i*3)); point[0]+=cvx.final_posr->pos[0]; point[1]+=cvx.final_posr->pos[1]; point[2]+=cvx.final_posr->pos[2]; value=dCalcVectorDot3(point,axis)-axis[3];//(*) if(valuemax) { max=value; } } // *: usually using the distance part of the plane (axis) is // not necesary, however, here we need it here in order to know // which face to pick when there are 2 parallel sides. } bool CheckEdgeIntersection(dxConvex& cvx1,dxConvex& cvx2, int flags,int& curc, dContactGeom *contact, int skip) { int maxc = flags & NUMC_MASK; dIASSERT(maxc != 0); dVector3 e1,e2,q; dVector4 plane,depthplane; dReal t; for(unsigned int i = 0;iR,cvx1.points+(cvx1.edges[i].first*3)); // translate e1[0]+=cvx1.final_posr->pos[0]; e1[1]+=cvx1.final_posr->pos[1]; e1[2]+=cvx1.final_posr->pos[2]; // Rotate dMultiply0_331(e2,cvx1.final_posr->R,cvx1.points+(cvx1.edges[i].second*3)); // translate e2[0]+=cvx1.final_posr->pos[0]; e2[1]+=cvx1.final_posr->pos[1]; e2[2]+=cvx1.final_posr->pos[2]; const unsigned int* pPoly=cvx2.polygons; for(sizeint j=0;jR,cvx2.planes+(j*4)); dNormalize3(plane); // Translate plane[3]= (cvx2.planes[(j*4)+3])+ ((plane[0] * cvx2.final_posr->pos[0]) + (plane[1] * cvx2.final_posr->pos[1]) + (plane[2] * cvx2.final_posr->pos[2])); dContactGeom *target = SAFECONTACT(flags, contact, curc, skip); target->g1=&cvx1; // g1 is the one pushed target->g2=&cvx2; if(IntersectSegmentPlane(e1,e2,plane,t,target->pos)) { if(IsPointInPolygon(target->pos,pPoly,plane,&cvx2,q)) { target->depth = dInfinity; for(sizeint k=0;kR,cvx2.planes+(k*4)); dNormalize3(depthplane); // Translate depthplane[3]= (cvx2.planes[(k*4)+3])+ ((plane[0] * cvx2.final_posr->pos[0]) + (plane[1] * cvx2.final_posr->pos[1]) + (plane[2] * cvx2.final_posr->pos[2])); dReal depth = (dVector3Dot(depthplane, target->pos) - depthplane[3]); // Ax + By + Cz - D if((fabs(depth)depth))&&((depth<-dEpsilon)||(depth>dEpsilon))) { target->depth=depth; dVector3Copy(depthplane,target->normal); } } ++curc; if(curc==maxc) return true; } } pPoly+=pPoly[0]+1; } } return false; } /* Helper struct */ struct ConvexConvexSATOutput { dReal min_depth; int depth_type; dVector3 dist; // distance from center to center, from cvx1 to cvx2 dVector3 e1a,e1b,e2a,e2b; // e1a to e1b = edge in cvx1,e2a to e2b = edge in cvx2. }; /*! \brief Does an axis separation test using cvx1 planes on cvx1 and cvx2, returns true for a collision false for no collision \param cvx1 [IN] First Convex object, its planes are used to do the tests \param cvx2 [IN] Second Convex object \param min_depth [IN/OUT] Used to input as well as output the minimum depth so far, must be set to a huge value such as dInfinity for initialization. \param g1 [OUT] Pointer to the convex which should be used in the returned contact as g1 \param g2 [OUT] Pointer to the convex which should be used in the returned contact as g2 */ inline bool CheckSATConvexFaces(dxConvex& cvx1, dxConvex& cvx2, ConvexConvexSATOutput& ccso) { dReal min,max,min1,max1,min2,max2,depth; dVector4 plane; for(unsigned int i=0;iR,cvx1.planes+(i*4)); dNormalize3(plane); // Translate plane[3]= (cvx1.planes[(i*4)+3])+ ((plane[0] * cvx1.final_posr->pos[0]) + (plane[1] * cvx1.final_posr->pos[1]) + (plane[2] * cvx1.final_posr->pos[2])); ComputeInterval(cvx1,plane,min1,max1); ComputeInterval(cvx2,plane,min2,max2); if(max2R,cvx1.points+(cvx1.edges[i].first*3)); dMultiply0_331(e1b,cvx1.final_posr->R,cvx1.points+(cvx1.edges[i].second*3)); e1[0]=e1b[0]-e1a[0]; e1[1]=e1b[1]-e1a[1]; e1[2]=e1b[2]-e1a[2]; for(unsigned int j = 0;jR,cvx2.points+(cvx2.edges[j].first*3)); dMultiply0_331 (e2b,cvx2.final_posr->R,cvx2.points+(cvx2.edges[j].second*3)); e2[0]=e2b[0]-e2a[0]; e2[1]=e2b[1]-e2a[1]; e2[2]=e2b[2]-e2a[2]; dCalcVectorCross3(plane,e1,e2); if(dCalcVectorDot3(plane,plane)pos[0]; ccso.e1a[1]+=cvx1.final_posr->pos[1]; ccso.e1a[2]+=cvx1.final_posr->pos[2]; ccso.e1b[0]+=cvx1.final_posr->pos[0]; ccso.e1b[1]+=cvx1.final_posr->pos[1]; ccso.e1b[2]+=cvx1.final_posr->pos[2]; dVector3Copy(e2a,ccso.e2a); dVector3Copy(e2b,ccso.e2b); ccso.e2a[0]+=cvx2.final_posr->pos[0]; ccso.e2a[1]+=cvx2.final_posr->pos[1]; ccso.e2a[2]+=cvx2.final_posr->pos[2]; ccso.e2b[0]+=cvx2.final_posr->pos[0]; ccso.e2b[1]+=cvx2.final_posr->pos[1]; ccso.e2b[2]+=cvx2.final_posr->pos[2]; } } } return true; } #if 0 /*! \brief Returns the index of the plane/side of the incident convex (ccso.g2) * which is closer to the reference convex (ccso.g1) side * * This function just looks for the incident face that is facing the reference face * and is the closest to being parallel to it, which sometimes is. */ inline unsigned int GetIncidentSide(ConvexConvexSATOutput& ccso) { dVector3 nis; // (N)ormal in (I)ncident convex (S)pace dReal SavedDot; dReal Dot; unsigned int incident_side=0; // Rotate the plane normal into incident convex space // (things like this should be done all over this file, // will look into that) dMultiply1_331(nis,ccso.g2->final_posr->R,ccso.plane); SavedDot = dCalcVectorDot3(nis,ccso.g2->planes); for(unsigned int i=1;iplanecount;++i) { Dot = dCalcVectorDot3(nis,ccso.g2->planes+(i*4)); if(Dot>SavedDot) { SavedDot=Dot; incident_side=i; } } return incident_side; } #endif inline unsigned int GetSupportSide(dVector3& dir,dxConvex& cvx) { dVector3 dics,tmp; // Direction in convex space dReal SavedDot; dReal Dot; unsigned int side=0; dVector3Copy(dir,tmp); dNormalize3(tmp); dMultiply1_331(dics,cvx.final_posr->R,tmp); SavedDot = dCalcVectorDot3(dics,cvx.planes); for(unsigned int i=1;iSavedDot) { SavedDot=Dot; side=i; } } return side; } /*! \brief Does an axis separation test between the 2 convex shapes using faces and edges */ int TestConvexIntersection(dxConvex& cvx1,dxConvex& cvx2, int flags, dContactGeom *contact, int skip) { ConvexConvexSATOutput ccso; #ifndef dNDEBUG memset(&ccso, 0, sizeof(ccso)); // get rid of 'uninitialized values' warning #endif ccso.min_depth=dInfinity; // Min not min at all ccso.depth_type=0; // no type // precompute distance vector dSubtractVectors3(ccso.dist, cvx2.final_posr->pos, cvx1.final_posr->pos); int maxc = flags & NUMC_MASK; dIASSERT(maxc != 0); dVector3 i1,i2,r1,r2; // edges of incident and reference faces respectively int contacts=0; if(!CheckSATConvexFaces(cvx1,cvx2,ccso)) { return 0; } else if(!CheckSATConvexFaces(cvx2,cvx1,ccso)) { return 0; } else if(!CheckSATConvexEdges(cvx1,cvx2,ccso)) { return 0; } // If we get here, there was a collision if(ccso.depth_type==1) // face-face { // cvx1 MUST always be in contact->g1 and cvx2 in contact->g2 // This was learned the hard way :( unsigned int incident_side; const unsigned int* pIncidentPoly; const unsigned int* pIncidentPoints; unsigned int reference_side; const unsigned int* pReferencePoly; const unsigned int* pReferencePoints; dVector4 plane,rplane,iplane; dVector3 tmp; dVector3 dist,p; dReal t,d,d1,d2; bool outside,out; dVector3Copy(ccso.dist,dist); reference_side = GetSupportSide(dist,cvx1); dNegateVector3(dist); incident_side = GetSupportSide(dist,cvx2); pReferencePoly = cvx1.polygons; pIncidentPoly = cvx2.polygons; // Get Reference plane (We may not have to apply transforms Optimization Oportunity) // Rotate dMultiply0_331(rplane,cvx1.final_posr->R,cvx1.planes+(reference_side*4)); dNormalize3(rplane); // Translate rplane[3]= (cvx1.planes[(reference_side*4)+3])+ ((rplane[0] * cvx1.final_posr->pos[0]) + (rplane[1] * cvx1.final_posr->pos[1]) + (rplane[2] * cvx1.final_posr->pos[2])); // flip rplane[0]=-rplane[0]; rplane[1]=-rplane[1]; rplane[2]=-rplane[2]; rplane[3]=-rplane[3]; for(unsigned int i=0;iR,&cvx2.points[(pIncidentPoints[0]*3)]); dVector3Add(i2,cvx2.final_posr->pos,i2); // Get the same point in the reference convex space dVector3Copy(i2,r2); dVector3Subtract(r2,cvx1.final_posr->pos,r2); dVector3Copy(r2,tmp); dMultiply1_331(r2,cvx1.final_posr->R,tmp); for(unsigned int i=0;iR,&cvx2.points[(pIncidentPoints[(i+1)%pIncidentPoly[0]]*3)]); dVector3Add(i2,cvx2.final_posr->pos,i2); // Get the same point in the reference convex space dVector3Copy(i2,r2); dVector3Subtract(r2,cvx1.final_posr->pos,r2); dVector3Copy(r2,tmp); dMultiply1_331(r2,cvx1.final_posr->R,tmp); outside=false; for(unsigned int j=0;j0) { out = true; break; } } } if(!out) { #if 0 // Use t to move p into global space p[0] = i1[0]+((i2[0]-i1[0])*t); p[1] = i1[1]+((i2[1]-i1[1])*t); p[2] = i1[2]+((i2[2]-i1[2])*t); #else // Apply reference convex transformations to p // The commented out piece of code is likelly to // produce less operations than this one, but // this way we know we are getting the right data dMultiply0_331(tmp,cvx1.final_posr->R,p); dVector3Add(tmp,cvx1.final_posr->pos,p); #endif // get p's distance to reference plane d = p[0]*rplane[0]+ p[1]*rplane[1]+ p[2]*rplane[2]- rplane[3]; if(d>0) { dContactGeom *target = SAFECONTACT(flags, contact, contacts, skip); dVector3Copy(p, target->pos); dVector3Copy(rplane, target->normal); target->g1 = &cvx1; target->g2 = &cvx2; target->depth = d; ++contacts; if (contacts==maxc) return contacts; } } } if(d1>0) { outside=true; } } if(outside) continue; d = i1[0]*rplane[0]+ i1[1]*rplane[1]+ i1[2]*rplane[2]- rplane[3]; if(d>0) { dContactGeom *target = SAFECONTACT(flags, contact, contacts, skip); dVector3Copy(i1, target->pos); dVector3Copy(rplane, target->normal); target->g1 = &cvx1; target->g2 = &cvx2; target->depth = d; ++contacts; if (contacts==maxc) return contacts; } } // IF we get here, we got the easiest contacts to calculate, // but there is still space in the contacts array for more. // So, project the Reference's face points onto the Incident face // plane and test them for inclusion in the reference plane as well. // We already have computed intersections so, skip those. /* Get Incident plane, we need it for projection */ /* Rotate */ dMultiply0_331(iplane,cvx2.final_posr->R,cvx2.planes+(incident_side*4)); dNormalize3(iplane); /* Translate */ iplane[3]= (cvx2.planes[(incident_side*4)+3]) + ((iplane[0] * cvx2.final_posr->pos[0]) + (iplane[1] * cvx2.final_posr->pos[1]) + (iplane[2] * cvx2.final_posr->pos[2])); // get reference face for(unsigned int i=0;iR,&cvx1.points[(pReferencePoints[i]*3)]); dVector3Add(cvx1.final_posr->pos,i1,i1); // Project onto Incident face plane t = -(i1[0]*iplane[0]+ i1[1]*iplane[1]+ i1[2]*iplane[2]- iplane[3]); i1[0]+=iplane[0]*t; i1[1]+=iplane[1]*t; i1[2]+=iplane[2]*t; // Get the same point in the incident convex space dVector3Copy(i1,r1); dVector3Subtract(r1,cvx2.final_posr->pos,r1); dVector3Copy(r1,tmp); dMultiply1_331(r1,cvx2.final_posr->R,tmp); // Check if it is outside the incident convex out = false; for(unsigned int j=0;j=0){out = true;break;}; } if(!out) { // check that the point is not a duplicate outside = false; for(int j=0;jpos[0] == i1[0]) && (cur_contact->pos[1] == i1[1]) && (cur_contact->pos[2] == i1[2])) { outside=true; } } if(!outside) { d = i1[0]*rplane[0]+ i1[1]*rplane[1]+ i1[2]*rplane[2]- rplane[3]; if(d>0) { dContactGeom *target = SAFECONTACT(flags, contact, contacts, skip); dVector3Copy(i1, target->pos); dVector3Copy(rplane, target->normal); target->g1 = &cvx1; target->g2 = &cvx2; target->depth = d; ++contacts; if (contacts==maxc) return contacts; } } } } } else if (ccso.depth_type == 2) // edge-edge { dVector3 c1, c2; ClosestPointBetweenSegments(ccso.e1a, ccso.e1b, ccso.e2a, ccso.e2b, c1, c2); dContactGeom *target = SAFECONTACT(flags, contact, contacts, skip); dSubtractVectors3(target->normal, c2, c1); dReal depth_square = dCalcVectorLengthSquare3(target->normal); if (dxSafeNormalize3(target->normal)) { target->depth = dSqrt(depth_square); } else { // If edges coincide return direction from one center to the other as the contact normal dVector3Copy(ccso.dist, target->normal); if (!dxSafeNormalize3(target->normal)) { // If the both centers coincide as well return an arbitrary vector. The depth is going to be zero anyway. dAssignVector3(target->normal, 1, 0, 0); } target->depth = 0; // Since the edges coincide, return a contact of zero depth } target->g1 = &cvx1; target->g2 = &cvx2; dVector3Copy(c1, target->pos); contacts++; } return contacts; } int dCollideConvexConvex (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) { dIASSERT (skip >= (int)sizeof(dContactGeom)); dIASSERT (o1->type == dConvexClass); dIASSERT (o2->type == dConvexClass); dIASSERT ((flags & NUMC_MASK) >= 1); dxConvex *Convex1 = (dxConvex*) o1; dxConvex *Convex2 = (dxConvex*) o2; return TestConvexIntersection(*Convex1,*Convex2,flags, contact,skip); } #if 0 int dCollideRayConvex (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) { dIASSERT (skip >= (int)sizeof(dContactGeom)); dIASSERT( o1->type == dRayClass ); dIASSERT( o2->type == dConvexClass ); dIASSERT ((flags & NUMC_MASK) >= 1); dxRay* ray = (dxRay*) o1; dxConvex* convex = (dxConvex*) o2; dVector3 origin,destination,contactpoint,out; dReal depth; dVector4 plane; unsigned int *pPoly=convex->polygons; // Calculate ray origin and destination destination[0]=0; destination[1]=0; destination[2]= ray->length; // -- Rotate -- dMultiply0_331(destination,ray->final_posr->R,destination); origin[0]=ray->final_posr->pos[0]; origin[1]=ray->final_posr->pos[1]; origin[2]=ray->final_posr->pos[2]; destination[0]+=origin[0]; destination[1]+=origin[1]; destination[2]+=origin[2]; for(int i=0;iplanecount;++i) { // Rotate dMultiply0_331(plane,convex->final_posr->R,convex->planes+(i*4)); // Translate plane[3]= (convex->planes[(i*4)+3])+ ((plane[0] * convex->final_posr->pos[0]) + (plane[1] * convex->final_posr->pos[1]) + (plane[2] * convex->final_posr->pos[2])); if(IntersectSegmentPlane(origin, destination, plane, depth, contactpoint)) { if(IsPointInPolygon(contactpoint,pPoly,plane,convex,out)) { contact->pos[0]=contactpoint[0]; contact->pos[1]=contactpoint[1]; contact->pos[2]=contactpoint[2]; contact->normal[0]=plane[0]; contact->normal[1]=plane[1]; contact->normal[2]=plane[2]; contact->depth=depth; contact->g1 = ray; contact->g2 = convex; contact->side1 = -1; contact->side2 = -1; // TODO: set plane index? return 1; } } pPoly+=pPoly[0]+1; } return 0; } #else // Ray - Convex collider by David Walters, June 2006 int dCollideRayConvex(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) { dIASSERT(skip >= (int)sizeof(dContactGeom)); dIASSERT(o1->type == dRayClass); dIASSERT(o2->type == dConvexClass); dIASSERT((flags & NUMC_MASK) >= 1); dxRay* ray = (dxRay*)o1; dxConvex* convex = (dxConvex*)o2; contact->g1 = ray; contact->g2 = convex; contact->side1 = -1; contact->side2 = -1; // TODO: set plane index? dReal alpha, beta, nsign; int flag = 0; // // Compute some useful info // dVector3 ray_pos = { ray->final_posr->pos[0] - convex->final_posr->pos[0], ray->final_posr->pos[1] - convex->final_posr->pos[1], ray->final_posr->pos[2] - convex->final_posr->pos[2] }; dVector3 ray_dir = { ray->final_posr->R[0 * 4 + 2], ray->final_posr->R[1 * 4 + 2], ray->final_posr->R[2 * 4 + 2] }; dMultiply1_331(ray_pos, convex->final_posr->R, ray_pos); dMultiply1_331(ray_dir, convex->final_posr->R, ray_dir); for (unsigned int i = 0; i < convex->planecount; ++i) { // Alias this plane. const dReal* plane = convex->planes + (i * 4); // If alpha >= 0 then start point is outside of plane. alpha = dCalcVectorDot3(plane, ray_pos) - plane[3]; // If any alpha is positive, then // the ray start is _outside_ of the hull if (alpha >= 0) { flag = 1; break; } } // If the ray starts inside the convex hull, then everything is flipped. nsign = (flag) ? REAL(1.0) : REAL(-1.0); // // Find closest contact point // // Assume no contacts. contact->depth = dInfinity; for (unsigned int i = 0; i < convex->planecount; ++i) { // Alias this plane. const dReal* plane = convex->planes + (i * 4); // If alpha >= 0 then point is outside of plane. alpha = nsign * (dCalcVectorDot3(plane, ray_pos) - plane[3]); // Compute [ plane-normal DOT ray-normal ], (/flip) beta = dCalcVectorDot3(plane, ray_dir) * nsign; // Ray is pointing at the plane? ( beta < 0 ) // Ray start to plane is within maximum ray length? // Ray start to plane is closer than the current best distance? if (beta < -dEpsilon && alpha >= 0 && alpha <= ray->length && alpha < contact->depth) { // Compute contact point on convex hull surface. contact->pos[0] = ray_pos[0] + alpha * ray_dir[0]; contact->pos[1] = ray_pos[1] + alpha * ray_dir[1]; contact->pos[2] = ray_pos[2] + alpha * ray_dir[2]; flag = 0; // For all _other_ planes. for (unsigned int j = 0; j < convex->planecount; ++j) { if (i == j) continue; // Skip self. // Alias this plane. const dReal* planej = convex->planes + (j * 4); // If beta >= 0 then start is outside of plane. beta = dCalcVectorDot3(planej, contact->pos) - planej[3]; // If any beta is positive, then the contact point // is not on the surface of the convex hull - it's just // intersecting some part of its infinite extent. if (beta > dEpsilon) { flag = 1; break; } } // Contact point isn't outside hull's surface? then it's a good contact! if (flag == 0) { // Store the contact normal, possibly flipped. contact->normal[0] = nsign * plane[0]; contact->normal[1] = nsign * plane[1]; contact->normal[2] = nsign * plane[2]; // Store depth contact->depth = alpha; if ((flags & CONTACTS_UNIMPORTANT) && contact->depth <= ray->length) { // Break on any contact if contacts are not important break; } } } } // Contact? if (contact->depth <= ray->length) { // Adjust contact position and normal back to global space dMultiply0_331(contact->pos, convex->final_posr->R, contact->pos); dMultiply0_331(contact->normal, convex->final_posr->R, contact->normal); contact->pos[0] += convex->final_posr->pos[0]; contact->pos[1] += convex->final_posr->pos[1]; contact->pos[2] += convex->final_posr->pos[2]; return true; } return false; } #endif //<-- Convex Collision ode-0.16/ode/src/gimpact_contact_export_helper.h0000664000175200017520000001460213403272463016753 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_GIMPACT_CONTACT_EXPORT_HELPER_H_ #define _ODE_GIMPACT_CONTACT_EXPORT_HELPER_H_ #include "collision_kernel.h" #include "collision_util.h" #include "util.h" #ifndef ALLOCA #define ALLOCA(x) dALLOCA16(x) #endif struct dxGImpactContactsExportHelper { public: template static unsigned ExportMaxDepthGImpactContacts(dxGImpactContactAccessor &srccontacts, unsigned contactcount, int Flags, dContactGeom* Contacts, int Stride) { unsigned result; unsigned maxcontacts = (unsigned)(Flags & NUMC_MASK); if (contactcount > maxcontacts) { ExportExcesssiveContacts(srccontacts, contactcount, Flags, Contacts, Stride); result = maxcontacts; } else { ExportFitContacts(srccontacts, contactcount, Flags, Contacts, Stride); result = contactcount; } return result; } private: template static void ExportExcesssiveContacts(dxGImpactContactAccessor &srccontacts, unsigned contactcount, int Flags, dContactGeom* Contacts, int Stride); template static void ExportFitContacts(dxGImpactContactAccessor &srccontacts, unsigned contactcount, int Flags, dContactGeom* Contacts, int Stride); template static dReal FindContactsMarginalDepth(dxGImpactContactAccessor &srccontacts, unsigned contactcount, unsigned maxcontacts); static dReal FindContactsMarginalDepth(dReal *pdepths, unsigned contactcount, unsigned maxcontacts, dReal mindepth, dReal maxdepth); }; template /*static */ void dxGImpactContactsExportHelper::ExportExcesssiveContacts(dxGImpactContactAccessor &srccontacts, unsigned contactcount, int Flags, dContactGeom* Contacts, int Stride) { unsigned maxcontacts = (unsigned)(Flags & NUMC_MASK); dReal marginaldepth = FindContactsMarginalDepth(srccontacts, contactcount, maxcontacts); unsigned contactshead = 0, contacttail = maxcontacts; for (unsigned i = 0; i < contactcount; i++) { dReal depth = srccontacts.RetrieveDepthByIndex(i); if (depth > marginaldepth) { dContactGeom *pcontact = SAFECONTACT(Flags, Contacts, contactshead, Stride); srccontacts.ExportContactGeomByIndex(pcontact, i); if (++contactshead == maxcontacts) { break; } } else if (depth == marginaldepth && contactshead < contacttail) { --contacttail; dContactGeom *pcontact = SAFECONTACT(Flags, Contacts, contacttail, Stride); srccontacts.ExportContactGeomByIndex(pcontact, i); } } } template /*static */ void dxGImpactContactsExportHelper::ExportFitContacts(dxGImpactContactAccessor &srccontacts, unsigned contactcount, int Flags, dContactGeom* Contacts, int Stride) { for (unsigned i = 0; i < contactcount; i++) { dContactGeom *pcontact = SAFECONTACT(Flags, Contacts, i, Stride); srccontacts.ExportContactGeomByIndex(pcontact, i); } } template /*static */ dReal dxGImpactContactsExportHelper::FindContactsMarginalDepth(dxGImpactContactAccessor &srccontacts, unsigned contactcount, unsigned maxcontacts) { dReal result; dReal *pdepths = (dReal *)ALLOCA(contactcount * sizeof(dReal)); unsigned marginindex = 0; unsigned highindex = marginindex; dReal firstdepth = srccontacts.RetrieveDepthByIndex(0); dReal mindepth = firstdepth, maxdepth = firstdepth; dIASSERT(contactcount > 1); for (unsigned i = 1; i < contactcount; i++) { dReal depth = srccontacts.RetrieveDepthByIndex(i); if (depth < firstdepth) { dReal temp = pdepths[marginindex]; pdepths[highindex++] = temp; pdepths[marginindex++] = depth; if (depth < mindepth) { mindepth = depth; } } else if (depth > firstdepth) { pdepths[highindex++] = depth; if (maxdepth < depth) { maxdepth = depth; } } } unsigned countabove = highindex - marginindex; if (maxcontacts < countabove) { result = FindContactsMarginalDepth(pdepths + marginindex, countabove, maxcontacts, firstdepth, maxdepth); } else if (maxcontacts == countabove) { result = dNextAfter(firstdepth, dInfinity); } else { unsigned countbelow = marginindex; if (maxcontacts <= contactcount - countbelow) { result = firstdepth; } else { result = FindContactsMarginalDepth(pdepths, countbelow, maxcontacts - (contactcount - countbelow), mindepth, firstdepth); } } return result; } #endif //_ODE_GIMPACT_CONTACT_EXPORT_HELPER_H_ ode-0.16/ode/src/box.cpp0000664000175200017520000007327313403272463012010 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* standard ODE geometry primitives: public API and pairwise collision functions. the rule is that only the low level primitive collision functions should set dContactGeom::g1 and dContactGeom::g2. */ #include #include #include #include "config.h" #include "matrix.h" #include "odemath.h" #include "collision_kernel.h" #include "collision_std.h" #include "collision_util.h" #ifdef _MSC_VER #pragma warning(disable:4291) // for VC++, no complaints about "no matching operator delete found" #endif //**************************************************************************** // box public API dxBox::dxBox (dSpaceID space, dReal lx, dReal ly, dReal lz) : dxGeom (space,1) { dAASSERT (lx >= 0 && ly >= 0 && lz >= 0); type = dBoxClass; side[0] = lx; side[1] = ly; side[2] = lz; updateZeroSizedFlag(!lx || !ly || !lz); } void dxBox::computeAABB() { const dMatrix3& R = final_posr->R; const dVector3& pos = final_posr->pos; dReal xrange = REAL(0.5) * (dFabs (R[0] * side[0]) + dFabs (R[1] * side[1]) + dFabs (R[2] * side[2])); dReal yrange = REAL(0.5) * (dFabs (R[4] * side[0]) + dFabs (R[5] * side[1]) + dFabs (R[6] * side[2])); dReal zrange = REAL(0.5) * (dFabs (R[8] * side[0]) + dFabs (R[9] * side[1]) + dFabs (R[10] * side[2])); aabb[0] = pos[0] - xrange; aabb[1] = pos[0] + xrange; aabb[2] = pos[1] - yrange; aabb[3] = pos[1] + yrange; aabb[4] = pos[2] - zrange; aabb[5] = pos[2] + zrange; } dGeomID dCreateBox (dSpaceID space, dReal lx, dReal ly, dReal lz) { return new dxBox (space,lx,ly,lz); } void dGeomBoxSetLengths (dGeomID g, dReal lx, dReal ly, dReal lz) { dUASSERT (g && g->type == dBoxClass,"argument not a box"); dAASSERT (lx >= 0 && ly >= 0 && lz >= 0); dxBox *b = (dxBox*) g; b->side[0] = lx; b->side[1] = ly; b->side[2] = lz; b->updateZeroSizedFlag(!lx || !ly || !lz); dGeomMoved (g); } void dGeomBoxGetLengths (dGeomID g, dVector3 result) { dUASSERT (g && g->type == dBoxClass,"argument not a box"); dxBox *b = (dxBox*) g; result[0] = b->side[0]; result[1] = b->side[1]; result[2] = b->side[2]; } dReal dGeomBoxPointDepth (dGeomID g, dReal x, dReal y, dReal z) { dUASSERT (g && g->type == dBoxClass,"argument not a box"); g->recomputePosr(); dxBox *b = (dxBox*) g; // Set p = (x,y,z) relative to box center // // This will be (0,0,0) if the point is at (side[0]/2,side[1]/2,side[2]/2) dVector3 p,q; p[0] = x - b->final_posr->pos[0]; p[1] = y - b->final_posr->pos[1]; p[2] = z - b->final_posr->pos[2]; // Rotate p into box's coordinate frame, so we can // treat the OBB as an AABB dMultiply1_331 (q,b->final_posr->R,p); // Record distance from point to each successive box side, and see // if the point is inside all six sides dReal dist[6]; int i; bool inside = true; for (i=0; i < 3; i++) { dReal side = b->side[i] * REAL(0.5); dist[i ] = side - q[i]; dist[i+3] = side + q[i]; if ((dist[i] < 0) || (dist[i+3] < 0)) { inside = false; } } // If point is inside the box, the depth is the smallest positive distance // to any side if (inside) { dReal smallest_dist = (dReal) (unsigned) -1; for (i=0; i < 6; i++) { if (dist[i] < smallest_dist) smallest_dist = dist[i]; } return smallest_dist; } // Otherwise, if point is outside the box, the depth is the largest // distance to any side. This is an approximation to the 'proper' // solution (the proper solution may be larger in some cases). dReal largest_dist = 0; for (i=0; i < 6; i++) { if (dist[i] > largest_dist) largest_dist = dist[i]; } return -largest_dist; } //**************************************************************************** // box-box collision utility // find all the intersection points between the 2D rectangle with vertices // at (+/-h[0],+/-h[1]) and the 2D quadrilateral with vertices (p[0],p[1]), // (p[2],p[3]),(p[4],p[5]),(p[6],p[7]). // // the intersection points are returned as x,y pairs in the 'ret' array. // the number of intersection points is returned by the function (this will // be in the range 0 to 8). static int intersectRectQuad (dReal h[2], dReal p[8], dReal ret[16]) { // q (and r) contain nq (and nr) coordinate points for the current (and // chopped) polygons int nq=4,nr; dReal buffer[16]; dReal *q = p; dReal *r = ret; for (int dir=0; dir <= 1; dir++) { // direction notation: xy[0] = x axis, xy[1] = y axis for (int sign=-1; sign <= 1; sign += 2) { // chop q along the line xy[dir] = sign*h[dir] dReal *pq = q; dReal *pr = r; nr = 0; for (int i=nq; i > 0; i--) { // go through all points in q and all lines between adjacent points if (sign*pq[dir] < h[dir]) { // this point is inside the chopping line pr[0] = pq[0]; pr[1] = pq[1]; pr += 2; nr++; if (nr & 8) { q = r; goto done; } } dReal *nextq = (i > 1) ? pq+2 : q; if ((sign*pq[dir] < h[dir]) ^ (sign*nextq[dir] < h[dir])) { // this line crosses the chopping line pr[1-dir] = pq[1-dir] + (nextq[1-dir]-pq[1-dir]) / (nextq[dir]-pq[dir]) * (sign*h[dir]-pq[dir]); pr[dir] = sign*h[dir]; pr += 2; nr++; if (nr & 8) { q = r; goto done; } } pq += 2; } q = r; r = (q==ret) ? buffer : ret; nq = nr; } } done: if (q != ret) memcpy (ret,q,nr*2*sizeof(dReal)); return nr; } // given n points in the plane (array p, of size 2*n), generate m points that // best represent the whole set. the definition of 'best' here is not // predetermined - the idea is to select points that give good box-box // collision detection behavior. the chosen point indexes are returned in the // array iret (of size m). 'i0' is always the first entry in the array. // n must be in the range [1..8]. m must be in the range [1..n]. i0 must be // in the range [0..n-1]. void cullPoints (int n, dReal p[], int m, int i0, int iret[]) { // compute the centroid of the polygon in cx,cy int i,j; dReal a,cx,cy,q; if (n==1) { cx = p[0]; cy = p[1]; } else if (n==2) { cx = REAL(0.5)*(p[0] + p[2]); cy = REAL(0.5)*(p[1] + p[3]); } else { a = 0; cx = 0; cy = 0; for (i=0; i<(n-1); i++) { q = p[i*2]*p[i*2+3] - p[i*2+2]*p[i*2+1]; a += q; cx += q*(p[i*2]+p[i*2+2]); cy += q*(p[i*2+1]+p[i*2+3]); } q = p[n*2-2]*p[1] - p[0]*p[n*2-1]; a = dRecip(REAL(3.0)*(a+q)); cx = a*(cx + q*(p[n*2-2]+p[0])); cy = a*(cy + q*(p[n*2-1]+p[1])); } // compute the angle of each point w.r.t. the centroid dReal A[8]; for (i=0; i M_PI) a -= (dReal)(2*M_PI); dReal maxdiff=1e9,diff; #ifndef dNODEBUG *iret = i0; // iret is not allowed to keep this value #endif for (i=0; i M_PI) diff = (dReal) (2*M_PI - diff); if (diff < maxdiff) { maxdiff = diff; *iret = i; } } } #ifndef dNODEBUG dIASSERT (*iret != i0); // ensure iret got set #endif avail[*iret] = 0; iret++; } } // given two boxes (p1,R1,side1) and (p2,R2,side2), collide them together and // generate contact points. this returns 0 if there is no contact otherwise // it returns the number of contacts generated. // `normal' returns the contact normal. // `depth' returns the maximum penetration depth along that normal. // `return_code' returns a number indicating the type of contact that was // detected: // 1,2,3 = box 2 intersects with a face of box 1 // 4,5,6 = box 1 intersects with a face of box 2 // 7..15 = edge-edge contact // `maxc' is the maximum number of contacts allowed to be generated, i.e. // the size of the `contact' array. // `contact' and `skip' are the contact array information provided to the // collision functions. this function only fills in the position and depth // fields. int dBoxBox (const dVector3 p1, const dMatrix3 R1, const dVector3 side1, const dVector3 p2, const dMatrix3 R2, const dVector3 side2, dVector3 normal, dReal *depth, int *return_code, int flags, dContactGeom *contact, int skip) { const dReal fudge_factor = REAL(1.05); dVector3 p,pp,normalC={0,0,0}; const dReal *normalR = 0; dReal A[3],B[3],R11,R12,R13,R21,R22,R23,R31,R32,R33, Q11,Q12,Q13,Q21,Q22,Q23,Q31,Q32,Q33,s,s2,l,expr1_val; int i,j,invert_normal,code; // get vector from centers of box 1 to box 2, relative to box 1 p[0] = p2[0] - p1[0]; p[1] = p2[1] - p1[1]; p[2] = p2[2] - p1[2]; dMultiply1_331 (pp,R1,p); // get pp = p relative to body 1 // get side lengths / 2 A[0] = side1[0]*REAL(0.5); A[1] = side1[1]*REAL(0.5); A[2] = side1[2]*REAL(0.5); B[0] = side2[0]*REAL(0.5); B[1] = side2[1]*REAL(0.5); B[2] = side2[2]*REAL(0.5); // Rij is R1'*R2, i.e. the relative rotation between R1 and R2 R11 = dCalcVectorDot3_44(R1+0,R2+0); R12 = dCalcVectorDot3_44(R1+0,R2+1); R13 = dCalcVectorDot3_44(R1+0,R2+2); R21 = dCalcVectorDot3_44(R1+1,R2+0); R22 = dCalcVectorDot3_44(R1+1,R2+1); R23 = dCalcVectorDot3_44(R1+1,R2+2); R31 = dCalcVectorDot3_44(R1+2,R2+0); R32 = dCalcVectorDot3_44(R1+2,R2+1); R33 = dCalcVectorDot3_44(R1+2,R2+2); Q11 = dFabs(R11); Q12 = dFabs(R12); Q13 = dFabs(R13); Q21 = dFabs(R21); Q22 = dFabs(R22); Q23 = dFabs(R23); Q31 = dFabs(R31); Q32 = dFabs(R32); Q33 = dFabs(R33); // for all 15 possible separating axes: // * see if the axis separates the boxes. if so, return 0. // * find the depth of the penetration along the separating axis (s2) // * if this is the largest depth so far, record it. // the normal vector will be set to the separating axis with the smallest // depth. note: normalR is set to point to a column of R1 or R2 if that is // the smallest depth normal so far. otherwise normalR is 0 and normalC is // set to a vector relative to body 1. invert_normal is 1 if the sign of // the normal should be flipped. do { #define TST(expr1,expr2,norm,cc) \ expr1_val = (expr1); /* Avoid duplicate evaluation of expr1 */ \ s2 = dFabs(expr1_val) - (expr2); \ if (s2 > 0) return 0; \ if (s2 > s) { \ s = s2; \ normalR = norm; \ invert_normal = ((expr1_val) < 0); \ code = (cc); \ if (flags & CONTACTS_UNIMPORTANT) break; \ } s = -dInfinity; invert_normal = 0; code = 0; // separating axis = u1,u2,u3 TST (pp[0],(A[0] + B[0]*Q11 + B[1]*Q12 + B[2]*Q13),R1+0,1); TST (pp[1],(A[1] + B[0]*Q21 + B[1]*Q22 + B[2]*Q23),R1+1,2); TST (pp[2],(A[2] + B[0]*Q31 + B[1]*Q32 + B[2]*Q33),R1+2,3); // separating axis = v1,v2,v3 TST (dCalcVectorDot3_41(R2+0,p),(A[0]*Q11 + A[1]*Q21 + A[2]*Q31 + B[0]),R2+0,4); TST (dCalcVectorDot3_41(R2+1,p),(A[0]*Q12 + A[1]*Q22 + A[2]*Q32 + B[1]),R2+1,5); TST (dCalcVectorDot3_41(R2+2,p),(A[0]*Q13 + A[1]*Q23 + A[2]*Q33 + B[2]),R2+2,6); // note: cross product axes need to be scaled when s is computed. // normal (n1,n2,n3) is relative to box 1. #undef TST #define TST(expr1,expr2,n1,n2,n3,cc) \ expr1_val = (expr1); /* Avoid duplicate evaluation of expr1 */ \ s2 = dFabs(expr1_val) - (expr2); \ if (s2 > 0) return 0; \ l = dSqrt ((n1)*(n1) + (n2)*(n2) + (n3)*(n3)); \ if (l > 0) { \ s2 /= l; \ if (s2*fudge_factor > s) { \ s = s2; \ normalR = 0; \ normalC[0] = (n1)/l; normalC[1] = (n2)/l; normalC[2] = (n3)/l; \ invert_normal = ((expr1_val) < 0); \ code = (cc); \ if (flags & CONTACTS_UNIMPORTANT) break; \ } \ } // We only need to check 3 edges per box // since parallel edges are equivalent. // separating axis = u1 x (v1,v2,v3) TST(pp[2]*R21-pp[1]*R31,(A[1]*Q31+A[2]*Q21+B[1]*Q13+B[2]*Q12),0,-R31,R21,7); TST(pp[2]*R22-pp[1]*R32,(A[1]*Q32+A[2]*Q22+B[0]*Q13+B[2]*Q11),0,-R32,R22,8); TST(pp[2]*R23-pp[1]*R33,(A[1]*Q33+A[2]*Q23+B[0]*Q12+B[1]*Q11),0,-R33,R23,9); // separating axis = u2 x (v1,v2,v3) TST(pp[0]*R31-pp[2]*R11,(A[0]*Q31+A[2]*Q11+B[1]*Q23+B[2]*Q22),R31,0,-R11,10); TST(pp[0]*R32-pp[2]*R12,(A[0]*Q32+A[2]*Q12+B[0]*Q23+B[2]*Q21),R32,0,-R12,11); TST(pp[0]*R33-pp[2]*R13,(A[0]*Q33+A[2]*Q13+B[0]*Q22+B[1]*Q21),R33,0,-R13,12); // separating axis = u3 x (v1,v2,v3) TST(pp[1]*R11-pp[0]*R21,(A[0]*Q21+A[1]*Q11+B[1]*Q33+B[2]*Q32),-R21,R11,0,13); TST(pp[1]*R12-pp[0]*R22,(A[0]*Q22+A[1]*Q12+B[0]*Q33+B[2]*Q31),-R22,R12,0,14); TST(pp[1]*R13-pp[0]*R23,(A[0]*Q23+A[1]*Q13+B[0]*Q32+B[1]*Q31),-R23,R13,0,15); #undef TST } while (0); if (!code) return 0; // if we get to this point, the boxes interpenetrate. compute the normal // in global coordinates. if (normalR) { normal[0] = normalR[0]; normal[1] = normalR[4]; normal[2] = normalR[8]; } else { dMultiply0_331 (normal,R1,normalC); } if (invert_normal) { normal[0] = -normal[0]; normal[1] = -normal[1]; normal[2] = -normal[2]; } *depth = -s; // compute contact point(s) if (code > 6) { // An edge from box 1 touches an edge from box 2. // find a point pa on the intersecting edge of box 1 dVector3 pa; dReal sign; // Copy p1 into pa for (i=0; i<3; i++) pa[i] = p1[i]; // why no memcpy? // Get world position of p2 into pa for (j=0; j<3; j++) { sign = (dCalcVectorDot3_14(normal,R1+j) > 0) ? REAL(1.0) : REAL(-1.0); for (i=0; i<3; i++) pa[i] += sign * A[j] * R1[i*4+j]; } // find a point pb on the intersecting edge of box 2 dVector3 pb; // Copy p2 into pb for (i=0; i<3; i++) pb[i] = p2[i]; // why no memcpy? // Get world position of p2 into pb for (j=0; j<3; j++) { sign = (dCalcVectorDot3_14(normal,R2+j) > 0) ? REAL(-1.0) : REAL(1.0); for (i=0; i<3; i++) pb[i] += sign * B[j] * R2[i*4+j]; } dReal alpha,beta; dVector3 ua,ub; // Get direction of first edge for (i=0; i<3; i++) ua[i] = R1[((code)-7)/3 + i*4]; // Get direction of second edge for (i=0; i<3; i++) ub[i] = R2[((code)-7)%3 + i*4]; // Get closest points between edges (one at each) dLineClosestApproach (pa,ua,pb,ub,&alpha,&beta); for (i=0; i<3; i++) pa[i] += ua[i]*alpha; for (i=0; i<3; i++) pb[i] += ub[i]*beta; // Set the contact point as halfway between the 2 closest points for (i=0; i<3; i++) contact[0].pos[i] = REAL(0.5)*(pa[i]+pb[i]); contact[0].depth = *depth; *return_code = code; return 1; } // okay, we have a face-something intersection (because the separating // axis is perpendicular to a face). define face 'a' to be the reference // face (i.e. the normal vector is perpendicular to this) and face 'b' to be // the incident face (the closest face of the other box). // Note: Unmodified parameter values are being used here const dReal *Ra,*Rb,*pa,*pb,*Sa,*Sb; if (code <= 3) { // One of the faces of box 1 is the reference face Ra = R1; // Rotation of 'a' Rb = R2; // Rotation of 'b' pa = p1; // Center (location) of 'a' pb = p2; // Center (location) of 'b' Sa = A; // Side Lenght of 'a' Sb = B; // Side Lenght of 'b' } else { // One of the faces of box 2 is the reference face Ra = R2; // Rotation of 'a' Rb = R1; // Rotation of 'b' pa = p2; // Center (location) of 'a' pb = p1; // Center (location) of 'b' Sa = B; // Side Lenght of 'a' Sb = A; // Side Lenght of 'b' } // nr = normal vector of reference face dotted with axes of incident box. // anr = absolute values of nr. /* The normal is flipped if necessary so it always points outward from box 'a', box 'b' is thus always the incident box */ dVector3 normal2,nr,anr; if (code <= 3) { normal2[0] = normal[0]; normal2[1] = normal[1]; normal2[2] = normal[2]; } else { normal2[0] = -normal[0]; normal2[1] = -normal[1]; normal2[2] = -normal[2]; } // Rotate normal2 in incident box opposite direction dMultiply1_331 (nr,Rb,normal2); anr[0] = dFabs (nr[0]); anr[1] = dFabs (nr[1]); anr[2] = dFabs (nr[2]); // find the largest compontent of anr: this corresponds to the normal // for the incident face. the other axis numbers of the incident face // are stored in a1,a2. int lanr,a1,a2; if (anr[1] > anr[0]) { if (anr[1] > anr[2]) { a1 = 0; lanr = 1; a2 = 2; } else { a1 = 0; a2 = 1; lanr = 2; } } else { if (anr[0] > anr[2]) { lanr = 0; a1 = 1; a2 = 2; } else { a1 = 0; a2 = 1; lanr = 2; } } // compute center point of incident face, in reference-face coordinates dVector3 center; if (nr[lanr] < 0) { for (i=0; i<3; i++) center[i] = pb[i] - pa[i] + Sb[lanr] * Rb[i*4+lanr]; } else { for (i=0; i<3; i++) center[i] = pb[i] - pa[i] - Sb[lanr] * Rb[i*4+lanr]; } // find the normal and non-normal axis numbers of the reference box int codeN,code1,code2; if (code <= 3) codeN = code-1; else codeN = code-4; if (codeN==0) { code1 = 1; code2 = 2; } else if (codeN==1) { code1 = 0; code2 = 2; } else { code1 = 0; code2 = 1; } // find the four corners of the incident face, in reference-face coordinates dReal quad[8]; // 2D coordinate of incident face (x,y pairs) dReal c1,c2,m11,m12,m21,m22; c1 = dCalcVectorDot3_14 (center,Ra+code1); c2 = dCalcVectorDot3_14 (center,Ra+code2); // optimize this? - we have already computed this data above, but it is not // stored in an easy-to-index format. for now it's quicker just to recompute // the four dot products. m11 = dCalcVectorDot3_44 (Ra+code1,Rb+a1); m12 = dCalcVectorDot3_44 (Ra+code1,Rb+a2); m21 = dCalcVectorDot3_44 (Ra+code2,Rb+a1); m22 = dCalcVectorDot3_44 (Ra+code2,Rb+a2); { dReal k1 = m11*Sb[a1]; dReal k2 = m21*Sb[a1]; dReal k3 = m12*Sb[a2]; dReal k4 = m22*Sb[a2]; quad[0] = c1 - k1 - k3; quad[1] = c2 - k2 - k4; quad[2] = c1 - k1 + k3; quad[3] = c2 - k2 + k4; quad[4] = c1 + k1 + k3; quad[5] = c2 + k2 + k4; quad[6] = c1 + k1 - k3; quad[7] = c2 + k2 - k4; } // find the size of the reference face dReal rect[2]; rect[0] = Sa[code1]; rect[1] = Sa[code2]; // intersect the incident and reference faces dReal ret[16]; int n = intersectRectQuad (rect,quad,ret); if (n < 1) return 0; // this should never happen // convert the intersection points into reference-face coordinates, // and compute the contact position and depth for each point. only keep // those points that have a positive (penetrating) depth. delete points in // the 'ret' array as necessary so that 'point' and 'ret' correspond. dReal point[3*8]; // penetrating contact points dReal dep[8]; // depths for those points dReal det1 = dRecip(m11*m22 - m12*m21); m11 *= det1; m12 *= det1; m21 *= det1; m22 *= det1; int cnum = 0; // number of penetrating contact points found for (j=0; j < n; j++) { dReal k1 = m22*(ret[j*2]-c1) - m12*(ret[j*2+1]-c2); dReal k2 = -m21*(ret[j*2]-c1) + m11*(ret[j*2+1]-c2); for (i=0; i<3; i++) point[cnum*3+i] = center[i] + k1*Rb[i*4+a1] + k2*Rb[i*4+a2]; dep[cnum] = Sa[codeN] - dCalcVectorDot3(normal2,point+cnum*3); if (dep[cnum] >= 0) { ret[cnum*2] = ret[j*2]; ret[cnum*2+1] = ret[j*2+1]; cnum++; if ((cnum | CONTACTS_UNIMPORTANT) == (flags & (NUMC_MASK | CONTACTS_UNIMPORTANT))) { break; } } } if (cnum < 1) { return 0; // this should not happen, yet does at times (demo_plane2d single precision). } // we can't generate more contacts than we actually have int maxc = flags & NUMC_MASK; if (maxc > cnum) maxc = cnum; if (maxc < 1) maxc = 1; // Even though max count must not be zero this check is kept for backward compatibility as this is a public function if (cnum <= maxc) { // we have less contacts than we need, so we use them all for (j=0; j < cnum; j++) { dContactGeom *con = CONTACT(contact,skip*j); for (i=0; i<3; i++) con->pos[i] = point[j*3+i] + pa[i]; con->depth = dep[j]; } } else { dIASSERT(!(flags & CONTACTS_UNIMPORTANT)); // cnum should be generated not greater than maxc so that "then" clause is executed // we have more contacts than are wanted, some of them must be culled. // find the deepest point, it is always the first contact. int i1 = 0; dReal maxdepth = dep[0]; for (i=1; i maxdepth) { maxdepth = dep[i]; i1 = i; } } int iret[8]; cullPoints (cnum,ret,maxc,i1,iret); for (j=0; j < maxc; j++) { dContactGeom *con = CONTACT(contact,skip*j); for (i=0; i<3; i++) con->pos[i] = point[iret[j]*3+i] + pa[i]; con->depth = dep[iret[j]]; } cnum = maxc; } *return_code = code; return cnum; } int dCollideBoxBox (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) { dIASSERT (skip >= (int)sizeof(dContactGeom)); dIASSERT (o1->type == dBoxClass); dIASSERT (o2->type == dBoxClass); dIASSERT ((flags & NUMC_MASK) >= 1); dVector3 normal; dReal depth; int code; dxBox *b1 = (dxBox*) o1; dxBox *b2 = (dxBox*) o2; int num = dBoxBox (o1->final_posr->pos,o1->final_posr->R,b1->side, o2->final_posr->pos,o2->final_posr->R,b2->side, normal,&depth,&code,flags,contact,skip); for (int i=0; inormal[0] = -normal[0]; currContact->normal[1] = -normal[1]; currContact->normal[2] = -normal[2]; currContact->g1 = o1; currContact->g2 = o2; currContact->side1 = -1; currContact->side2 = -1; } return num; } int dCollideBoxPlane (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) { dIASSERT (skip >= (int)sizeof(dContactGeom)); dIASSERT (o1->type == dBoxClass); dIASSERT (o2->type == dPlaneClass); dIASSERT ((flags & NUMC_MASK) >= 1); dxBox *box = (dxBox*) o1; dxPlane *plane = (dxPlane*) o2; contact->g1 = o1; contact->g2 = o2; contact->side1 = -1; contact->side2 = -1; int ret = 0; //@@@ problem: using 4-vector (plane->p) as 3-vector (normal). const dReal *R = o1->final_posr->R; // rotation of box const dReal *n = plane->p; // normal vector // project sides lengths along normal vector, get absolute values dReal Q1 = dCalcVectorDot3_14(n,R+0); dReal Q2 = dCalcVectorDot3_14(n,R+1); dReal Q3 = dCalcVectorDot3_14(n,R+2); dReal A1 = box->side[0] * Q1; dReal A2 = box->side[1] * Q2; dReal A3 = box->side[2] * Q3; dReal B1 = dFabs(A1); dReal B2 = dFabs(A2); dReal B3 = dFabs(A3); // early exit test dReal depth = plane->p[3] + REAL(0.5)*(B1+B2+B3) - dCalcVectorDot3(n,o1->final_posr->pos); if (depth < 0) return 0; // find number of contacts requested int maxc = flags & NUMC_MASK; // if (maxc < 1) maxc = 1; // an assertion is made on entry if (maxc > 4) maxc = 4; // not more than 4 contacts per box allowed // find deepest point dVector3 p; p[0] = o1->final_posr->pos[0]; p[1] = o1->final_posr->pos[1]; p[2] = o1->final_posr->pos[2]; #define FOO(i,op) \ p[0] op REAL(0.5)*box->side[i] * R[0+i]; \ p[1] op REAL(0.5)*box->side[i] * R[4+i]; \ p[2] op REAL(0.5)*box->side[i] * R[8+i]; #define BAR(i,iinc) if (A ## iinc > 0) { FOO(i,-=) } else { FOO(i,+=) } BAR(0,1); BAR(1,2); BAR(2,3); #undef FOO #undef BAR // the deepest point is the first contact point contact->pos[0] = p[0]; contact->pos[1] = p[1]; contact->pos[2] = p[2]; contact->depth = depth; ret = 1; // ret is number of contact points found so far if (maxc == 1) goto done; // get the second and third contact points by starting from `p' and going // along the two sides with the smallest projected length. #define FOO(i,j,op) \ CONTACT(contact,i*skip)->pos[0] = p[0] op box->side[j] * R[0+j]; \ CONTACT(contact,i*skip)->pos[1] = p[1] op box->side[j] * R[4+j]; \ CONTACT(contact,i*skip)->pos[2] = p[2] op box->side[j] * R[8+j]; #define BAR(ctact,side,sideinc) \ if (depth - B ## sideinc < 0) goto done; \ if (A ## sideinc > 0) { FOO(ctact,side,+); } else { FOO(ctact,side,-); } \ CONTACT(contact,ctact*skip)->depth = depth - B ## sideinc; \ ret++; if (B1 < B2) { if (B3 < B1) goto use_side_3; else { BAR(1,0,1); // use side 1 if (maxc == 2) goto done; if (B2 < B3) goto contact2_2; else goto contact2_3; } } else { if (B3 < B2) { use_side_3: // use side 3 BAR(1,2,3); if (maxc == 2) goto done; if (B1 < B2) goto contact2_1; else goto contact2_2; } else { BAR(1,1,2); // use side 2 if (maxc == 2) goto done; if (B1 < B3) goto contact2_1; else goto contact2_3; } } contact2_1: BAR(2,0,1); goto done; contact2_2: BAR(2,1,2); goto done; contact2_3: BAR(2,2,3); goto done; #undef FOO #undef BAR done: if (maxc == 4 && ret == 3) { // If user requested 4 contacts, and the first 3 were created... // Combine contacts 2 and 3 (vectorial sum) and get the fourth one // Result: if a box face is completely inside a plane, contacts are created for all the 4 vertices dReal d4 = CONTACT(contact,1*skip)->depth + CONTACT(contact,2*skip)->depth - depth; // depth is the depth for first contact if (d4 > 0) { CONTACT(contact,3*skip)->pos[0] = CONTACT(contact,1*skip)->pos[0] + CONTACT(contact,2*skip)->pos[0] - p[0]; // p is the position of first contact CONTACT(contact,3*skip)->pos[1] = CONTACT(contact,1*skip)->pos[1] + CONTACT(contact,2*skip)->pos[1] - p[1]; CONTACT(contact,3*skip)->pos[2] = CONTACT(contact,1*skip)->pos[2] + CONTACT(contact,2*skip)->pos[2] - p[2]; CONTACT(contact,3*skip)->depth = d4; ret++; } } for (int i=0; ig1 = o1; currContact->g2 = o2; currContact->side1 = -1; currContact->side2 = -1; currContact->normal[0] = n[0]; currContact->normal[1] = n[1]; currContact->normal[2] = n[2]; } return ret; } ode-0.16/ode/src/threading_base.cpp0000664000175200017520000001226113403272463014145 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * Threading base wrapper class implementation file. * * Copyright (C) 2011-2012 Oleh Derevenko. All rights reserved. * * e-mail: odar@eleks.com (change all "a" to "e") * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* * Threading base class to be used for inheritance by dxWorld, dxSpace and others * to take advantage of threaded execution. */ #include #include "config.h" #include "error.h" #include "threading_base.h" dxThreadingBase::~dxThreadingBase() { DoFreeStockCallWait(); } void dxThreadingBase::PostThreadedCallsGroup( int *out_summary_fault/*=NULL*/, ddependencycount_t member_count, dCallReleaseeID dependent_releasee/*=NULL*/, dThreadedCallFunction *call_func, void *call_context, const char *call_name/*=NULL*/) const { dIASSERT(member_count != 0); dThreadingImplementationID impl; const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl); for (unsigned member_index = 0; member_index != member_count; ++member_index) { // Post individual group member jobs functions->post_call(impl, out_summary_fault, NULL, 0, dependent_releasee, NULL, call_func, call_context, member_index, call_name); } } void dxThreadingBase::PostThreadedCallsIndexOverridenGroup(int *out_summary_fault/*=NULL*/, ddependencycount_t member_count, dCallReleaseeID dependent_releasee/*=NULL*/, dThreadedCallFunction *call_func, void *call_context, unsigned index_override, const char *call_name/*=NULL*/) const { dIASSERT(member_count != 0); dThreadingImplementationID impl; const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl); for (unsigned member_index = 0; member_index != member_count; ++member_index) { // Post individual group member jobs functions->post_call(impl, out_summary_fault, NULL, 0, dependent_releasee, NULL, call_func, call_context, index_override, call_name); } } void dxThreadingBase::PostThreadedCallForUnawareReleasee( int *out_summary_fault/*=NULL*/, dCallReleaseeID *out_post_releasee/*=NULL*/, ddependencycount_t dependencies_count, dCallReleaseeID dependent_releasee/*=NULL*/, dCallWaitID call_wait/*=NULL*/, dThreadedCallFunction *call_func, void *call_context, dcallindex_t instance_index, const char *call_name/*=NULL*/) const { dThreadingImplementationID impl; const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl); functions->alter_call_dependencies_count(impl, dependent_releasee, 1); functions->post_call(impl, out_summary_fault, out_post_releasee, dependencies_count, dependent_releasee, call_wait, call_func, call_context, instance_index, call_name); } const dxThreadingFunctionsInfo *dxThreadingBase::FindThreadingImpl(dThreadingImplementationID &out_impl_found) const { const dxThreadingFunctionsInfo *functions_found = GetFunctionsInfo(); if (functions_found != NULL) { out_impl_found = GetThreadingImpl(); } else { functions_found = m_default_impl_provider->retrieveThreadingDefaultImpl(out_impl_found); } return functions_found; } dCallWaitID dxThreadingBase::DoAllocateStockCallWait() { dIASSERT(GetStockCallWait() == NULL); dCallWaitID stock_wait_id = AllocThreadedCallWait(); if (stock_wait_id != NULL) { SetStockCallWait(stock_wait_id); } return stock_wait_id; } void dxThreadingBase::DoFreeStockCallWait() { dCallWaitID stock_wait_id = GetStockCallWait(); if (stock_wait_id != NULL) { FreeThreadedCallWait(stock_wait_id); SetStockCallWait(NULL); } } ode-0.16/ode/src/threading_impl_posix.h0000664000175200017520000004366613403272463015100 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * Threading POSIX implementation file. * * Copyright (C) 2011-2012 Oleh Derevenko. All rights reserved. * * e-mail: odar@eleks.com (change all "a" to "e") * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* * Threading POSIX implementation for built-in threading support provider. */ #ifndef _ODE_THREADING_IMPL_POSIX_H_ #define _ODE_THREADING_IMPL_POSIX_H_ #include #if !defined(_WIN32) #include "threading_impl_templates.h" #include "threading_fake_sync.h" #include "threading_atomics_provs.h" #if dBUILTIN_THREADING_IMPL_ENABLED #include #include #include #if !defined(EOK) #define EOK 0 #endif #if HAVE_PTHREAD_CONDATTR_SETCLOCK static inline int _condvar_clock_gettime(int clock_type, timespec *ts) { return clock_gettime(clock_type, ts); } #else // #if !HAVE_PTHREAD_CONDATTR_SETCLOCK #if defined(__APPLE__) #if HAVE_GETTIMEOFDAY #include #if !defined(CLOCK_MONOTONIC) #define CLOCK_MONOTONIC 2 #endif static inline int _condvar_clock_gettime(int clock_type, timespec *ts) { (void)clock_type; // Unused timeval tv; return gettimeofday(&tv, NULL) == 0 ? (ts->tv_sec = tv.tv_sec, ts->tv_nsec = tv.tv_usec * 1000, 0) : (-1); } #else // #if !HAVE_GETTIMEOFDAY #error It is necessary to check manuals for the correct way of getting condvar wait time for this Apple system #endif // #if !HAVE_GETTIMEOFDAY #else // #if !defined(__APPLE__) #error It is necessary to check manuals for the correct way of getting condvar wait time for this system #endif // #if !defined(__APPLE__) #endif // #if !HAVE_PTHREAD_CONDATTR_SETCLOCK /************************************************************************/ /* dxCondvarWakeup class implementation */ /************************************************************************/ class dxCondvarWakeup { public: dxCondvarWakeup(): m_waiters_list(NULL), m_signaled_state(false), m_state_is_permanent(false), m_object_initialized(false) {} ~dxCondvarWakeup() { DoFinalizeObject(); } bool InitializeObject() { return DoInitializeObject(); } private: bool DoInitializeObject(); void DoFinalizeObject(); public: void ResetWakeup(); void WakeupAThread(); void WakeupAllThreads(); bool WaitWakeup(const dThreadedWaitTime *timeout_time_ptr); private: bool BlockAsAWaiter(const dThreadedWaitTime *timeout_time_ptr); private: struct dxWaiterInfo { dxWaiterInfo(): m_signal_state(false) {} dxWaiterInfo **m_prev_info_ptr; dxWaiterInfo *m_next_info; bool m_signal_state; }; void RegisterWaiterInList(dxWaiterInfo *waiter_info); void UnregisterWaiterFromList(dxWaiterInfo *waiter_info); bool MarkSignaledFirstWaiter(); static bool MarkSignaledFirstWaiterMeaningful(dxWaiterInfo *first_waiter); bool MarkSignaledAllWaiters(); static bool MarkSignaledAllWaitersMeaningful(dxWaiterInfo *first_waiter); private: dxWaiterInfo *m_waiters_list; bool m_signaled_state; bool m_state_is_permanent; bool m_object_initialized; pthread_mutex_t m_wakeup_mutex; pthread_cond_t m_wakeup_cond; }; bool dxCondvarWakeup::DoInitializeObject() { dIASSERT(!m_object_initialized); bool init_result = false; pthread_condattr_t cond_condattr; bool mutex_initialized = false, condattr_initialized = false; do { int mutex_result = pthread_mutex_init(&m_wakeup_mutex, NULL); if (mutex_result != EOK) { errno = mutex_result; break; } mutex_initialized = true; int condattr_init_result = pthread_condattr_init(&cond_condattr); if (condattr_init_result != EOK) { errno = condattr_init_result; break; } condattr_initialized = true; #if HAVE_PTHREAD_CONDATTR_SETCLOCK int condattr_clock_result = pthread_condattr_setclock(&cond_condattr, CLOCK_MONOTONIC); if (condattr_clock_result != EOK) { errno = condattr_clock_result; break; } #endif // #if HAVE_PTHREAD_CONDATTR_SETCLOCK int cond_result = pthread_cond_init(&m_wakeup_cond, &cond_condattr); if (cond_result != EOK) { errno = cond_result; break; } pthread_condattr_destroy(&cond_condattr); // result can be ignored m_object_initialized = true; init_result = true; } while (false); if (!init_result) { if (mutex_initialized) { if (condattr_initialized) { int condattr_destroy_result = pthread_condattr_destroy(&cond_condattr); dICHECK(condattr_destroy_result == EOK || ((errno = condattr_destroy_result), false)); } int mutex_destroy_result = pthread_mutex_destroy(&m_wakeup_mutex); dICHECK(mutex_destroy_result == EOK || ((errno = mutex_destroy_result), false)); } } return init_result; } void dxCondvarWakeup::DoFinalizeObject() { if (m_object_initialized) { int cond_result = pthread_cond_destroy(&m_wakeup_cond); dICHECK(cond_result == EOK || ((errno = cond_result), false)); int mutex_result = pthread_mutex_destroy(&m_wakeup_mutex); dICHECK(mutex_result == EOK || ((errno = mutex_result), false)); m_object_initialized = false; } } void dxCondvarWakeup::ResetWakeup() { int lock_result = pthread_mutex_lock(&m_wakeup_mutex); dICHECK(lock_result == EOK || ((errno = lock_result), false)); m_signaled_state = false; m_state_is_permanent = false; int unlock_result = pthread_mutex_unlock(&m_wakeup_mutex); dICHECK(unlock_result == EOK || ((errno = unlock_result), false)); } void dxCondvarWakeup::WakeupAThread() { int lock_result = pthread_mutex_lock(&m_wakeup_mutex); dICHECK(lock_result == EOK || ((errno = lock_result), false)); dIASSERT(!m_state_is_permanent); // Wakeup should not be used after permanent signal if (!m_signaled_state) { if (MarkSignaledFirstWaiter()) { // All threads must be woken up regardless to the fact that only one waiter is marked. // It is not possible to wake up a chosen thread personally // and if a random thread is woken up it can't know if there was a condition signal for it // or the sleep was interrupted by POSIX signal. // On the other hand, without this it is not possible to guarantee that a thread // will be woken up per each WakeupAThread() call if there is more than one waiter // and wakeup requests will not accumulate if there are no waiters. int broadcast_result = pthread_cond_broadcast(&m_wakeup_cond); dICHECK(broadcast_result == EOK || ((errno = broadcast_result), false)); } else { m_signaled_state = true; } } int unlock_result = pthread_mutex_unlock(&m_wakeup_mutex); dICHECK(unlock_result == EOK || ((errno = unlock_result), false)); } void dxCondvarWakeup::WakeupAllThreads() { int lock_result = pthread_mutex_lock(&m_wakeup_mutex); dICHECK(lock_result == EOK || ((errno = lock_result), false)); m_state_is_permanent = true; if (!m_signaled_state) { m_signaled_state = true; if (MarkSignaledAllWaiters()) { int broadcast_result = pthread_cond_broadcast(&m_wakeup_cond); dICHECK(broadcast_result == EOK || ((errno = broadcast_result), false)); } } int unlock_result = pthread_mutex_unlock(&m_wakeup_mutex); dICHECK(unlock_result == EOK || ((errno = unlock_result), false)); } bool dxCondvarWakeup::WaitWakeup(const dThreadedWaitTime *timeout_time_ptr) { bool wait_result; int lock_result = pthread_mutex_lock(&m_wakeup_mutex); dICHECK(lock_result == EOK || ((errno = lock_result), false)); if (!m_signaled_state) { if (!timeout_time_ptr || timeout_time_ptr->wait_nsec != 0 || timeout_time_ptr->wait_sec != 0) { wait_result = BlockAsAWaiter(timeout_time_ptr); } else { wait_result = false; } } else { m_signaled_state = m_state_is_permanent; wait_result = true; } int unlock_result = pthread_mutex_unlock(&m_wakeup_mutex); dICHECK(unlock_result == EOK || ((errno = unlock_result), false)); return wait_result; } bool dxCondvarWakeup::BlockAsAWaiter(const dThreadedWaitTime *timeout_time_ptr) { bool wait_result = false; dxWaiterInfo waiter_info; RegisterWaiterInList(&waiter_info); timespec wakeup_time; if (timeout_time_ptr != NULL) { timespec current_time; int clock_result = _condvar_clock_gettime(CLOCK_MONOTONIC, ¤t_time); dICHECK(clock_result != -1); time_t wakeup_sec = current_time.tv_sec + timeout_time_ptr->wait_sec; unsigned long wakeup_nsec = current_time.tv_nsec + timeout_time_ptr->wait_nsec; if (wakeup_nsec >= 1000000000) { wakeup_nsec -= 1000000000; wakeup_sec += 1; } wakeup_time.tv_sec = wakeup_sec; wakeup_time.tv_nsec = wakeup_nsec; } while (true) { int cond_result = (timeout_time_ptr != NULL) ? pthread_cond_timedwait(&m_wakeup_cond, &m_wakeup_mutex, &wakeup_time) : pthread_cond_wait(&m_wakeup_cond, &m_wakeup_mutex); dICHECK(cond_result == EOK || cond_result == ETIMEDOUT || ((errno = cond_result), false)); if (waiter_info.m_signal_state) { wait_result = true; break; } if (cond_result == ETIMEDOUT) { dIASSERT(timeout_time_ptr != NULL); break; } } UnregisterWaiterFromList(&waiter_info); return wait_result; } void dxCondvarWakeup::RegisterWaiterInList(dxWaiterInfo *waiter_info) { dxWaiterInfo *const first_waiter = m_waiters_list; if (first_waiter == NULL) { waiter_info->m_next_info = waiter_info; waiter_info->m_prev_info_ptr = &waiter_info->m_next_info; m_waiters_list = waiter_info; } else { waiter_info->m_next_info = first_waiter; waiter_info->m_prev_info_ptr = first_waiter->m_prev_info_ptr; *first_waiter->m_prev_info_ptr = waiter_info; first_waiter->m_prev_info_ptr = &waiter_info->m_next_info; } } void dxCondvarWakeup::UnregisterWaiterFromList(dxWaiterInfo *waiter_info) { dxWaiterInfo *next_info = waiter_info->m_next_info; if (next_info == waiter_info) { m_waiters_list = NULL; } else { next_info->m_prev_info_ptr = waiter_info->m_prev_info_ptr; *waiter_info->m_prev_info_ptr = next_info; if (waiter_info == m_waiters_list) { m_waiters_list = next_info; } } } bool dxCondvarWakeup::MarkSignaledFirstWaiter() { bool waiter_found = false; dxWaiterInfo *const first_waiter = m_waiters_list; if (first_waiter) { waiter_found = MarkSignaledFirstWaiterMeaningful(first_waiter); } return waiter_found; } bool dxCondvarWakeup::MarkSignaledFirstWaiterMeaningful(dxWaiterInfo *first_waiter) { bool waiter_found = false; dxWaiterInfo *current_waiter = first_waiter; while (true) { if (!current_waiter->m_signal_state) { current_waiter->m_signal_state = true; waiter_found = true; break; } current_waiter = current_waiter->m_next_info; if (current_waiter == first_waiter) { break; } } return waiter_found; } bool dxCondvarWakeup::MarkSignaledAllWaiters() { bool waiter_found = false; dxWaiterInfo *const first_waiter = m_waiters_list; if (first_waiter) { waiter_found = MarkSignaledAllWaitersMeaningful(first_waiter); } return waiter_found; } bool dxCondvarWakeup::MarkSignaledAllWaitersMeaningful(dxWaiterInfo *first_waiter) { bool waiter_found = false; dxWaiterInfo *current_waiter = first_waiter; while (true) { if (!current_waiter->m_signal_state) { current_waiter->m_signal_state = true; waiter_found = true; } current_waiter = current_waiter->m_next_info; if (current_waiter == first_waiter) { break; } } return waiter_found; } /************************************************************************/ /* dxMutexMutex class implementation */ /************************************************************************/ class dxMutexMutex { public: dxMutexMutex(): m_mutex_allocated(false) {} ~dxMutexMutex() { DoFinalizeObject(); } bool InitializeObject() { return DoInitializeObject(); } private: bool DoInitializeObject(); void DoFinalizeObject(); public: void LockMutex(); bool TryLockMutex(); void UnlockMutex(); private: pthread_mutex_t m_mutex_instance; bool m_mutex_allocated; }; bool dxMutexMutex::DoInitializeObject() { dIASSERT(!m_mutex_allocated); bool init_result = false; do { int mutex_result = pthread_mutex_init(&m_mutex_instance, NULL); if (mutex_result != EOK) { errno = mutex_result; break; } m_mutex_allocated = true; init_result = true; } while (false); return init_result; } void dxMutexMutex::DoFinalizeObject() { if (m_mutex_allocated) { int mutex_result = pthread_mutex_destroy(&m_mutex_instance); dICHECK(mutex_result == EOK || ((errno = mutex_result), false)); m_mutex_allocated = false; } } void dxMutexMutex::LockMutex() { int lock_result = pthread_mutex_lock(&m_mutex_instance); dICHECK(lock_result == EOK || ((errno = lock_result), false)); } bool dxMutexMutex::TryLockMutex() { int trylock_result = pthread_mutex_trylock(&m_mutex_instance); dICHECK(trylock_result == EOK || trylock_result == EBUSY || ((errno = trylock_result), false)); return trylock_result == EOK; } void dxMutexMutex::UnlockMutex() { int unlock_result = pthread_mutex_unlock(&m_mutex_instance); dICHECK(unlock_result == EOK || ((errno = unlock_result), false)); } #endif // #if dBUILTIN_THREADING_IMPL_ENABLED /************************************************************************/ /* Self-threaded job list definition */ /************************************************************************/ typedef dxtemplateJobListContainer dxSelfThreadedJobListContainer; typedef dxtemplateJobListSelfHandler dxSelfThreadedJobListHandler; typedef dxtemplateThreadingImplementation dxSelfThreadedThreading; #if dBUILTIN_THREADING_IMPL_ENABLED /************************************************************************/ /* Multi-threaded job list definition */ /************************************************************************/ typedef dxtemplateJobListContainer, dxMutexMutex, dxOUAtomicsProvider> dxMultiThreadedJobListContainer; typedef dxtemplateJobListThreadedHandler dxMultiThreadedJobListHandler; typedef dxtemplateThreadingImplementation dxMultiThreadedThreading; #endif // #if dBUILTIN_THREADING_IMPL_ENABLED #endif // #if !defined(_WIN32) #endif // #ifndef _ODE_THREADING_IMPL_POSIX_H_ ode-0.16/ode/src/odemath.h0000664000175200017520000000527013403272463012276 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE__PRIVATE_ODEMATH_H_ #define _ODE__PRIVATE_ODEMATH_H_ #include #include "error.h" bool dxCouldBeNormalized3(const dVector3 a); bool dxSafeNormalize3 (dVector3 a); bool dxCouldBeNormalized4(const dVector4 a); bool dxSafeNormalize4 (dVector4 a); ODE_PURE_INLINE void dxNormalize3(dVector3 a) { bool bSafeNormalize3Fault; if ((bSafeNormalize3Fault = !dxSafeNormalize3(a))) { dIVERIFY(!bSafeNormalize3Fault); a[0] = REAL(1.0); a[2] = a[1] = REAL(0.0); } } ODE_PURE_INLINE void dxNormalize4(dVector4 a) { bool bSafeNormalize4Fault; if ((bSafeNormalize4Fault = !dxSafeNormalize4(a))) { dIVERIFY(!bSafeNormalize4Fault); a[0] = REAL(1.0); a[3] = a[2] = a[1] = REAL(0.0); } } void dxPlaneSpace (const dVector3 n, dVector3 p, dVector3 q); bool dxOrthogonalizeR(dMatrix3 m); // For internal use #define dSafeNormalize3(a) dxSafeNormalize3(a) #define dSafeNormalize4(a) dxSafeNormalize4(a) #define dNormalize3(a) dxNormalize3(a) #define dNormalize4(a) dxNormalize4(a) #define dPlaneSpace(n, p, q) dxPlaneSpace(n, p, q) #define dOrthogonalizeR(m) dxOrthogonalizeR(m) #endif ode-0.16/ode/src/collision_trimesh_ccylinder.cpp0000664000175200017520000011163113403272463016771 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* * Triangle-Capsule(Capsule) collider by Alen Ladavac * Ported to ODE by Nguyen Binh */ // NOTES from Nguyen Binh // 14 Apr : Seem to be robust // There is a problem when you use original Step and set contact friction // surface.mu = dInfinity; // More description : // When I dropped Capsule over the bunny ears, it seems to stuck // there for a while. I think the cause is when you set surface.mu = dInfinity; // the friction force is too high so it just hang the capsule there. // So the good cure for this is to set mu = around 1.5 (in my case) // For StepFast1, this become as solid as rock : StepFast1 just approximate // friction force. // NOTES from Croteam's Alen //As a side note... there are some extra contacts that can be generated //on the edge between two triangles, and if the capsule penetrates deeply into //the triangle (usually happens with large mass or low FPS), some such //contacts can in some cases push the capsule away from the edge instead of //away from the two triangles. This shows up as capsule slowing down a bit //when hitting an edge while sliding along a flat tesselated grid of //triangles. This is only if capsule is standing upwards. //Same thing can appear whenever a smooth object (e.g sphere) hits such an //edge, and it needs to be solved as a special case probably. This is a //problem we are looking forward to address soon. #include #include #include "config.h" #include "matrix.h" #include "odemath.h" #include "collision_util.h" #include "collision_trimesh_internal.h" #include "util.h" #if dTRIMESH_ENABLED // OPCODE version #if dTRIMESH_OPCODE // largest number, double or float #if defined(dSINGLE) #define MAX_REAL FLT_MAX #define MIN_REAL (-FLT_MAX) #else #define MAX_REAL DBL_MAX #define MIN_REAL (-DBL_MAX) #endif // To optimize before send contacts to dynamic part #define OPTIMIZE_CONTACTS 1 // dVector3 // r=a-b #define SUBTRACT(a,b,r) dSubtractVectors3(r, a, b) // dVector3 // a=b #define SET(a,b) dCopyVector3(a, b) // dMatrix3 // a=b #define SETM(a,b) dCopyMatrix4x4(a, b) // dVector3 // r=a+b #define ADD(a,b,r) dAddVectors3(r, a, b) // dMatrix3, int, dVector3 // v=column a from m #define GETCOL(m,a,v) dGetMatrixColumn3(v, m, a) // dVector4, dVector3 // distance between plane p and point v #define POINTDISTANCE(p,v) dPointPlaneDistance(v, p) // dVector4, dVector3, dReal // construct plane from normal and d #define CONSTRUCTPLANE(plane,normal,d) dConstructPlane(normal, d, plane) // dVector3 // length of vector a #define LENGTHOF(a) dCalcVectorLength3(a) static inline dReal _length2OfVector3(dVector3 v) { return dCalcVectorLengthSquare3(v); } // Local contacts data typedef struct _sLocalContactData { dVector3 vPos; dVector3 vNormal; dReal fDepth; int triIndex; int nFlags; // 0 = filtered out, 1 = OK }sLocalContactData; struct sTrimeshCapsuleColliderData { sTrimeshCapsuleColliderData(): m_gLocalContacts(NULL), m_ctContacts(0) { memset(m_vN, 0, sizeof(dVector3)); } void SetupInitialContext(dxTriMesh *TriMesh, dxGeom *Capsule, int flags, int skip); int TestCollisionForSingleTriangle(int ctContacts0, int Triint, dVector3 dv[3], uint8 flags, bool &bOutFinishSearching); #if OPTIMIZE_CONTACTS void _OptimizeLocalContacts(); #endif int _ProcessLocalContacts(dContactGeom *contact, dxTriMesh *TriMesh, dxGeom *Capsule); static BOOL _cldClipEdgeToPlane(dVector3 &vEpnt0, dVector3 &vEpnt1, const dVector4& plPlane); BOOL _cldTestAxis(const dVector3 &v0, const dVector3 &v1, const dVector3 &v2, dVector3 vAxis, int iAxis, BOOL bNoFlip = FALSE); BOOL _cldTestSeparatingAxesOfCapsule(const dVector3 &v0, const dVector3 &v1, const dVector3 &v2, uint8 flags); void _cldTestOneTriangleVSCapsule(const dVector3 &v0, const dVector3 &v1, const dVector3 &v2, uint8 flags); sLocalContactData *m_gLocalContacts; unsigned int m_ctContacts; // capsule data // real time data dMatrix3 m_mCapsuleRotation; dVector3 m_vCapsulePosition; dVector3 m_vCapsuleAxis; // static data dReal m_vCapsuleRadius; dReal m_fCapsuleSize; // mesh data // dMatrix4 mHullDstPl; dMatrix3 m_mTriMeshRot; dVector3 m_vTriMeshPos; dVector3 m_vE0, m_vE1, m_vE2; // global collider data dVector3 m_vNormal; dReal m_fBestDepth; dReal m_fBestCenter; dReal m_fBestrt; int m_iBestAxis; dVector3 m_vN; dVector3 m_vV0; dVector3 m_vV1; dVector3 m_vV2; // ODE contact's specific unsigned int m_iFlags; int m_iStride; }; // Capsule lie on axis number 3 = (Z axis) static const int nCAPSULE_AXIS = 2; #if OPTIMIZE_CONTACTS // Use to classify contacts to be "near" in position static const dReal fSameContactPositionEpsilon = REAL(0.0001); // 1e-4 // Use to classify contacts to be "near" in normal direction static const dReal fSameContactNormalEpsilon = REAL(0.0001); // 1e-4 // If this two contact can be classified as "near" inline int _IsNearContacts(sLocalContactData& c1,sLocalContactData& c2) { int bPosNear = 0; int bSameDir = 0; dVector3 vDiff; // First check if they are "near" in position SUBTRACT(c1.vPos,c2.vPos,vDiff); if ( (dFabs(vDiff[0]) < fSameContactPositionEpsilon) &&(dFabs(vDiff[1]) < fSameContactPositionEpsilon) &&(dFabs(vDiff[2]) < fSameContactPositionEpsilon)) { bPosNear = 1; } // Second check if they are "near" in normal direction SUBTRACT(c1.vNormal,c2.vNormal,vDiff); if ( (dFabs(vDiff[0]) < fSameContactNormalEpsilon) &&(dFabs(vDiff[1]) < fSameContactNormalEpsilon) &&(dFabs(vDiff[2]) < fSameContactNormalEpsilon) ) { bSameDir = 1; } // Will be "near" if position and normal direction are "near" return (bPosNear && bSameDir); } inline int _IsBetter(sLocalContactData& c1,sLocalContactData& c2) { // The not better will be throw away // You can change the selection criteria here return (c1.fDepth > c2.fDepth); } // iterate through gLocalContacts and filtered out "near contact" void sTrimeshCapsuleColliderData::_OptimizeLocalContacts() { int nContacts = m_ctContacts; for (int i = 0; i < nContacts-1; i++) { for (int j = i+1; j < nContacts; j++) { if (_IsNearContacts(m_gLocalContacts[i],m_gLocalContacts[j])) { // If they are seem to be the samed then filtered // out the least penetrate one if (_IsBetter(m_gLocalContacts[j],m_gLocalContacts[i])) { m_gLocalContacts[i].nFlags = 0; // filtered 1st contact } else { m_gLocalContacts[j].nFlags = 0; // filtered 2nd contact } // NOTE // There is other way is to add two depth together but // it not work so well. Why??? } } } } #endif // OPTIMIZE_CONTACTS int sTrimeshCapsuleColliderData::_ProcessLocalContacts(dContactGeom *contact, dxTriMesh *TriMesh, dxGeom *Capsule) { #if OPTIMIZE_CONTACTS if (m_ctContacts > 1 && !(m_iFlags & CONTACTS_UNIMPORTANT)) { // Can be optimized... _OptimizeLocalContacts(); } #endif unsigned int iContact = 0; dContactGeom* Contact = 0; unsigned int nFinalContact = 0; for (iContact = 0; iContact < m_ctContacts; iContact ++) { // Ensure that we haven't created too many contacts if( nFinalContact >= (m_iFlags & NUMC_MASK)) { break; } if (1 == m_gLocalContacts[iContact].nFlags) { Contact = SAFECONTACT(m_iFlags, contact, nFinalContact, m_iStride); Contact->depth = m_gLocalContacts[iContact].fDepth; SET(Contact->normal,m_gLocalContacts[iContact].vNormal); SET(Contact->pos,m_gLocalContacts[iContact].vPos); Contact->g1 = TriMesh; Contact->g2 = Capsule; Contact->side1 = m_gLocalContacts[iContact].triIndex; Contact->side2 = -1; nFinalContact++; } } // debug //if (nFinalContact != m_ctContacts) //{ // printf("[Info] %d contacts generated,%d filtered.\n",m_ctContacts,m_ctContacts-nFinalContact); //} return nFinalContact; } BOOL sTrimeshCapsuleColliderData::_cldClipEdgeToPlane( dVector3 &vEpnt0, dVector3 &vEpnt1, const dVector4& plPlane) { // calculate distance of edge points to plane dReal fDistance0 = POINTDISTANCE( plPlane, vEpnt0 ); dReal fDistance1 = POINTDISTANCE( plPlane, vEpnt1 ); // if both points are behind the plane if ( fDistance0 < 0 && fDistance1 < 0 ) { // do nothing return FALSE; // if both points in front of the plane } else if ( fDistance0 > 0 && fDistance1 > 0 ) { // accept them return TRUE; // if we have edge/plane intersection } else if ((fDistance0 > 0 && fDistance1 < 0) || ( fDistance0 < 0 && fDistance1 > 0)) { // find intersection point of edge and plane dVector3 vIntersectionPoint; vIntersectionPoint[0]= vEpnt0[0]-(vEpnt0[0]-vEpnt1[0])*fDistance0/(fDistance0-fDistance1); vIntersectionPoint[1]= vEpnt0[1]-(vEpnt0[1]-vEpnt1[1])*fDistance0/(fDistance0-fDistance1); vIntersectionPoint[2]= vEpnt0[2]-(vEpnt0[2]-vEpnt1[2])*fDistance0/(fDistance0-fDistance1); // clamp correct edge to intersection point if ( fDistance0 < 0 ) { SET(vEpnt0,vIntersectionPoint); } else { SET(vEpnt1,vIntersectionPoint); } return TRUE; } return TRUE; } BOOL sTrimeshCapsuleColliderData::_cldTestAxis( const dVector3 &/*v0*/, const dVector3 &/*v1*/, const dVector3 &/*v2*/, dVector3 vAxis, int iAxis, BOOL bNoFlip/* = FALSE*/) { // calculate length of separating axis vector dReal fL = LENGTHOF(vAxis); // if not long enough // TODO : dReal epsilon please if ( fL < REAL(1e-5) ) { // do nothing //iLastOutAxis = 0; return TRUE; } // otherwise normalize it dNormalize3(vAxis); // project capsule on vAxis dReal frc = dFabs(dCalcVectorDot3(m_vCapsuleAxis,vAxis))*(m_fCapsuleSize*REAL(0.5)-m_vCapsuleRadius) + m_vCapsuleRadius; // project triangle on vAxis dReal afv[3]; afv[0] = dCalcVectorDot3(m_vV0, vAxis); afv[1] = dCalcVectorDot3(m_vV1, vAxis); afv[2] = dCalcVectorDot3(m_vV2, vAxis); dReal fMin = MAX_REAL; dReal fMax = MIN_REAL; // for each vertex for(int i=0; i<3; i++) { // find minimum if (afv[i]fMax) { fMax = afv[i]; } } // find triangle's center of interval on axis dReal fCenter = (fMin+fMax)*REAL(0.5); // calculate triangles half interval dReal fTriangleRadius = (fMax-fMin)*REAL(0.5); // if they do not overlap, if (dFabs(fCenter) > ( frc + fTriangleRadius )) { // exit, we have no intersection return FALSE; } // calculate depth dReal fDepth = dFabs(fCenter) - (frc+fTriangleRadius); // if greater then best found so far if ( fDepth > m_fBestDepth ) { // remember depth m_fBestDepth = fDepth; m_fBestCenter = fCenter; m_fBestrt = fTriangleRadius; m_vNormal[0] = vAxis[0]; m_vNormal[1] = vAxis[1]; m_vNormal[2] = vAxis[2]; m_iBestAxis = iAxis; // flip normal if interval is wrong faced if (fCenter<0 && !bNoFlip) { m_vNormal[0] = -m_vNormal[0]; m_vNormal[1] = -m_vNormal[1]; m_vNormal[2] = -m_vNormal[2]; m_fBestCenter = -fCenter; } } return TRUE; } // helper for less key strokes inline void _CalculateAxis(const dVector3& v1, const dVector3& v2, const dVector3& v3, const dVector3& v4, dVector3& r) { dVector3 t1; dVector3 t2; SUBTRACT(v1,v2,t1); dCalcVectorCross3(t2,t1,v3); dCalcVectorCross3(r,t2,v4); } BOOL sTrimeshCapsuleColliderData::_cldTestSeparatingAxesOfCapsule( const dVector3 &v0, const dVector3 &v1, const dVector3 &v2, uint8 flags) { // calculate caps centers in absolute space dVector3 vCp0; vCp0[0] = m_vCapsulePosition[0] + m_vCapsuleAxis[0]*(m_fCapsuleSize*REAL(0.5)-m_vCapsuleRadius); vCp0[1] = m_vCapsulePosition[1] + m_vCapsuleAxis[1]*(m_fCapsuleSize*REAL(0.5)-m_vCapsuleRadius); vCp0[2] = m_vCapsulePosition[2] + m_vCapsuleAxis[2]*(m_fCapsuleSize*REAL(0.5)-m_vCapsuleRadius); dVector3 vCp1; vCp1[0] = m_vCapsulePosition[0] - m_vCapsuleAxis[0]*(m_fCapsuleSize*REAL(0.5)-m_vCapsuleRadius); vCp1[1] = m_vCapsulePosition[1] - m_vCapsuleAxis[1]*(m_fCapsuleSize*REAL(0.5)-m_vCapsuleRadius); vCp1[2] = m_vCapsulePosition[2] - m_vCapsuleAxis[2]*(m_fCapsuleSize*REAL(0.5)-m_vCapsuleRadius); // reset best axis m_iBestAxis = 0; // reset best depth m_fBestDepth = -MAX_REAL; // reset separating axis vector dVector3 vAxis = {REAL(0.0),REAL(0.0),REAL(0.0),REAL(0.0)}; // Epsilon value for checking axis vector length const dReal fEpsilon = 1e-6f; // Translate triangle to Cc cord. SUBTRACT(v0, m_vCapsulePosition, m_vV0); SUBTRACT(v1, m_vCapsulePosition, m_vV1); SUBTRACT(v2, m_vCapsulePosition, m_vV2); // We begin to test for 19 separating axis now // I wonder does it help if we employ the method like ISA-GJK??? // Or at least we should do experiment and find what axis will // be most likely to be separating axis to check it first. // Original // axis m_vN //vAxis = -m_vN; vAxis[0] = - m_vN[0]; vAxis[1] = - m_vN[1]; vAxis[2] = - m_vN[2]; if (!_cldTestAxis(v0, v1, v2, vAxis, 1, TRUE)) { return FALSE; } if (flags & dxTriMeshData::CUF_USE_FIRST_EDGE) { // axis CxE0 - Edge 0 dCalcVectorCross3(vAxis,m_vCapsuleAxis,m_vE0); //vAxis = dCalcVectorCross3( m_vCapsuleAxis cross vE0 ); if (_length2OfVector3( vAxis ) > fEpsilon) { if (!_cldTestAxis(v0, v1, v2, vAxis, 2)) { return FALSE; } } } if (flags & dxTriMeshData::CUF_USE_SECOND_EDGE) { // axis CxE1 - Edge 1 dCalcVectorCross3(vAxis,m_vCapsuleAxis,m_vE1); //vAxis = ( m_vCapsuleAxis cross m_vE1 ); if (_length2OfVector3( vAxis ) > fEpsilon) { if (!_cldTestAxis(v0, v1, v2, vAxis, 3)) { return FALSE; } } } if (flags & dxTriMeshData::CUF_USE_THIRD_EDGE) { // axis CxE2 - Edge 2 //vAxis = ( m_vCapsuleAxis cross m_vE2 ); dCalcVectorCross3(vAxis,m_vCapsuleAxis,m_vE2); if (_length2OfVector3( vAxis ) > fEpsilon) { if (!_cldTestAxis(v0, v1, v2, vAxis, 4)) { return FALSE; } } } if (flags & dxTriMeshData::CUF_USE_FIRST_EDGE) { // first capsule point // axis ((Cp0-V0) x E0) x E0 _CalculateAxis(vCp0,v0,m_vE0,m_vE0,vAxis); // vAxis = ( ( vCp0-v0) cross vE0 ) cross vE0; if (_length2OfVector3( vAxis ) > fEpsilon) { if (!_cldTestAxis(v0, v1, v2, vAxis, 5)) { return FALSE; } } } if (flags & dxTriMeshData::CUF_USE_SECOND_EDGE) { // axis ((Cp0-V1) x E1) x E1 _CalculateAxis(vCp0,v1,m_vE1,m_vE1,vAxis); //vAxis = ( ( vCp0-v1) cross vE1 ) cross vE1; if (_length2OfVector3( vAxis ) > fEpsilon) { if (!_cldTestAxis(v0, v1, v2, vAxis, 6)) { return FALSE; } } } if (flags & dxTriMeshData::CUF_USE_THIRD_EDGE) { // axis ((Cp0-V2) x E2) x E2 _CalculateAxis(vCp0,v2,m_vE2,m_vE2,vAxis); //vAxis = ( ( vCp0-v2) cross vE2 ) cross vE2; if (_length2OfVector3( vAxis ) > fEpsilon) { if (!_cldTestAxis(v0, v1, v2, vAxis, 7)) { return FALSE; } } } if (flags & dxTriMeshData::CUF_USE_FIRST_EDGE) { // second capsule point // axis ((Cp1-V0) x E0) x E0 _CalculateAxis(vCp1,v0,m_vE0,m_vE0,vAxis); //vAxis = ( ( vCp1-v0 ) cross vE0 ) cross vE0; if (_length2OfVector3( vAxis ) > fEpsilon) { if (!_cldTestAxis(v0, v1, v2, vAxis, 8)) { return FALSE; } } } if (flags & dxTriMeshData::CUF_USE_SECOND_EDGE) { // axis ((Cp1-V1) x E1) x E1 _CalculateAxis(vCp1,v1,m_vE1,m_vE1,vAxis); //vAxis = ( ( vCp1-v1 ) cross vE1 ) cross vE1; if (_length2OfVector3( vAxis ) > fEpsilon) { if (!_cldTestAxis(v0, v1, v2, vAxis, 9)) { return FALSE; } } } if (flags & dxTriMeshData::CUF_USE_THIRD_EDGE) { // axis ((Cp1-V2) x E2) x E2 _CalculateAxis(vCp1,v2,m_vE2,m_vE2,vAxis); //vAxis = ( ( vCp1-v2 ) cross vE2 ) cross vE2; if (_length2OfVector3( vAxis ) > fEpsilon) { if (!_cldTestAxis(v0, v1, v2, vAxis, 10)) { return FALSE; } } } if (flags & dxTriMeshData::CUF_USE_FIRST_VERTEX) { // first vertex on triangle // axis ((V0-Cp0) x C) x C _CalculateAxis(v0,vCp0,m_vCapsuleAxis,m_vCapsuleAxis,vAxis); //vAxis = ( ( v0-vCp0 ) cross m_vCapsuleAxis ) cross m_vCapsuleAxis; if (_length2OfVector3( vAxis ) > fEpsilon) { if (!_cldTestAxis(v0, v1, v2, vAxis, 11)) { return FALSE; } } } if (flags & dxTriMeshData::CUF_USE_SECOND_VERTEX) { // second vertex on triangle // axis ((V1-Cp0) x C) x C _CalculateAxis(v1,vCp0,m_vCapsuleAxis,m_vCapsuleAxis,vAxis); //vAxis = ( ( v1-vCp0 ) cross vCapsuleAxis ) cross vCapsuleAxis; if (_length2OfVector3( vAxis ) > fEpsilon) { if (!_cldTestAxis(v0, v1, v2, vAxis, 12)) { return FALSE; } } } if (flags & dxTriMeshData::CUF_USE_THIRD_VERTEX) { // third vertex on triangle // axis ((V2-Cp0) x C) x C _CalculateAxis(v2,vCp0,m_vCapsuleAxis,m_vCapsuleAxis,vAxis); //vAxis = ( ( v2-vCp0 ) cross vCapsuleAxis ) cross vCapsuleAxis; if (_length2OfVector3( vAxis ) > fEpsilon) { if (!_cldTestAxis(v0, v1, v2, vAxis, 13)) { return FALSE; } } } // Test as separating axes direction vectors between each triangle // edge and each capsule's cap center if (flags & dxTriMeshData::CUF_USE_FIRST_VERTEX) { // first triangle vertex and first capsule point //vAxis = v0 - vCp0; SUBTRACT(v0,vCp0,vAxis); if (_length2OfVector3( vAxis ) > fEpsilon) { if (!_cldTestAxis(v0, v1, v2, vAxis, 14)) { return FALSE; } } } if (flags & dxTriMeshData::CUF_USE_SECOND_VERTEX) { // second triangle vertex and first capsule point //vAxis = v1 - vCp0; SUBTRACT(v1,vCp0,vAxis); if (_length2OfVector3( vAxis ) > fEpsilon) { if (!_cldTestAxis(v0, v1, v2, vAxis, 15)) { return FALSE; } } } if (flags & dxTriMeshData::CUF_USE_THIRD_VERTEX) { // third triangle vertex and first capsule point //vAxis = v2 - vCp0; SUBTRACT(v2,vCp0,vAxis); if (_length2OfVector3( vAxis ) > fEpsilon) { if (!_cldTestAxis(v0, v1, v2, vAxis, 16)) { return FALSE; } } } if (flags & dxTriMeshData::CUF_USE_FIRST_VERTEX) { // first triangle vertex and second capsule point //vAxis = v0 - vCp1; SUBTRACT(v0,vCp1,vAxis); if (_length2OfVector3( vAxis ) > fEpsilon) { if (!_cldTestAxis(v0, v1, v2, vAxis, 17)) { return FALSE; } } } if (flags & dxTriMeshData::CUF_USE_SECOND_VERTEX) { // second triangle vertex and second capsule point //vAxis = v1 - vCp1; SUBTRACT(v1,vCp1,vAxis); if (_length2OfVector3( vAxis ) > fEpsilon) { if (!_cldTestAxis(v0, v1, v2, vAxis, 18)) { return FALSE; } } } if (flags & dxTriMeshData::CUF_USE_THIRD_VERTEX) { // third triangle vertex and second capsule point //vAxis = v2 - vCp1; SUBTRACT(v2,vCp1,vAxis); if (_length2OfVector3( vAxis ) > fEpsilon) { if (!_cldTestAxis(v0, v1, v2, vAxis, 19)) { return FALSE; } } } return TRUE; } // test one mesh triangle on intersection with capsule void sTrimeshCapsuleColliderData::_cldTestOneTriangleVSCapsule( const dVector3 &v0, const dVector3 &v1, const dVector3 &v2, uint8 flags) { // calculate edges SUBTRACT(v1,v0,m_vE0); SUBTRACT(v2,v1,m_vE1); SUBTRACT(v0,v2,m_vE2); dVector3 _minus_vE0; SUBTRACT(v0,v1,_minus_vE0); // calculate poly normal dCalcVectorCross3(m_vN,m_vE1,_minus_vE0); // Even though all triangles might be initially valid, // a triangle may degenerate into a segment after applying // space transformation. if (!dSafeNormalize3(m_vN)) { return; } // create plane from triangle dReal plDistance = -dCalcVectorDot3(v0,m_vN); dVector4 plTrianglePlane; CONSTRUCTPLANE(plTrianglePlane,m_vN,plDistance); // calculate capsule distance to plane dReal fDistanceCapsuleCenterToPlane = POINTDISTANCE(plTrianglePlane,m_vCapsulePosition); // Capsule must be over positive side of triangle if (fDistanceCapsuleCenterToPlane < 0 /* && !bDoubleSided*/) { // if not don't generate contacts return; } dVector3 vPnt0, vPnt1, vPnt2; SET (vPnt0,v0); if (fDistanceCapsuleCenterToPlane < 0) { SET (vPnt1,v2); SET (vPnt2,v1); } else { SET (vPnt1,v1); SET (vPnt2,v2); } // do intersection test and find best separating axis if (!_cldTestSeparatingAxesOfCapsule(vPnt0, vPnt1, vPnt2, flags)) { // if not found do nothing return; } // if best separation axis is not found if (m_iBestAxis == 0 ) { // this should not happen (we should already exit in that case) dIASSERT(FALSE); // do nothing return; } // calculate caps centers in absolute space dVector3 vCposTrans; vCposTrans[0] = m_vCapsulePosition[0] + m_vNormal[0]*m_vCapsuleRadius; vCposTrans[1] = m_vCapsulePosition[1] + m_vNormal[1]*m_vCapsuleRadius; vCposTrans[2] = m_vCapsulePosition[2] + m_vNormal[2]*m_vCapsuleRadius; dVector3 vCEdgePoint0; vCEdgePoint0[0] = vCposTrans[0] + m_vCapsuleAxis[0]*(m_fCapsuleSize*REAL(0.5)-m_vCapsuleRadius); vCEdgePoint0[1] = vCposTrans[1] + m_vCapsuleAxis[1]*(m_fCapsuleSize*REAL(0.5)-m_vCapsuleRadius); vCEdgePoint0[2] = vCposTrans[2] + m_vCapsuleAxis[2]*(m_fCapsuleSize*REAL(0.5)-m_vCapsuleRadius); dVector3 vCEdgePoint1; vCEdgePoint1[0] = vCposTrans[0] - m_vCapsuleAxis[0]*(m_fCapsuleSize*REAL(0.5)-m_vCapsuleRadius); vCEdgePoint1[1] = vCposTrans[1] - m_vCapsuleAxis[1]*(m_fCapsuleSize*REAL(0.5)-m_vCapsuleRadius); vCEdgePoint1[2] = vCposTrans[2] - m_vCapsuleAxis[2]*(m_fCapsuleSize*REAL(0.5)-m_vCapsuleRadius); // transform capsule edge points into triangle space vCEdgePoint0[0] -= vPnt0[0]; vCEdgePoint0[1] -= vPnt0[1]; vCEdgePoint0[2] -= vPnt0[2]; vCEdgePoint1[0] -= vPnt0[0]; vCEdgePoint1[1] -= vPnt0[1]; vCEdgePoint1[2] -= vPnt0[2]; dVector4 plPlane; dVector3 _minus_vN; _minus_vN[0] = -m_vN[0]; _minus_vN[1] = -m_vN[1]; _minus_vN[2] = -m_vN[2]; // triangle plane CONSTRUCTPLANE(plPlane,_minus_vN,0); //plPlane = Plane4f( -m_vN, 0); if (!_cldClipEdgeToPlane( vCEdgePoint0, vCEdgePoint1, plPlane )) { return; } // plane with edge 0 dVector3 vTemp; dCalcVectorCross3(vTemp,m_vN,m_vE0); CONSTRUCTPLANE(plPlane, vTemp, REAL(1e-5)); if (!_cldClipEdgeToPlane( vCEdgePoint0, vCEdgePoint1, plPlane )) { return; } dCalcVectorCross3(vTemp,m_vN,m_vE1); CONSTRUCTPLANE(plPlane, vTemp, -(dCalcVectorDot3(m_vE0,vTemp)-REAL(1e-5))); if (!_cldClipEdgeToPlane( vCEdgePoint0, vCEdgePoint1, plPlane )) { return; } dCalcVectorCross3(vTemp,m_vN,m_vE2); CONSTRUCTPLANE(plPlane, vTemp, REAL(1e-5)); if (!_cldClipEdgeToPlane( vCEdgePoint0, vCEdgePoint1, plPlane )) { return; } // return capsule edge points into absolute space vCEdgePoint0[0] += vPnt0[0]; vCEdgePoint0[1] += vPnt0[1]; vCEdgePoint0[2] += vPnt0[2]; vCEdgePoint1[0] += vPnt0[0]; vCEdgePoint1[1] += vPnt0[1]; vCEdgePoint1[2] += vPnt0[2]; // calculate depths for both contact points SUBTRACT(vCEdgePoint0,m_vCapsulePosition,vTemp); dReal fDepth0 = dCalcVectorDot3(vTemp,m_vNormal) - (m_fBestCenter-m_fBestrt); SUBTRACT(vCEdgePoint1,m_vCapsulePosition,vTemp); dReal fDepth1 = dCalcVectorDot3(vTemp,m_vNormal) - (m_fBestCenter-m_fBestrt); // clamp depths to zero if (fDepth0 < 0) { fDepth0 = 0.0f; } if (fDepth1 < 0 ) { fDepth1 = 0.0f; } // Cached contacts's data // contact 0 dIASSERT(m_ctContacts < (m_iFlags & NUMC_MASK)); // Do not call function if there is no room to store result m_gLocalContacts[m_ctContacts].fDepth = fDepth0; SET(m_gLocalContacts[m_ctContacts].vNormal,m_vNormal); SET(m_gLocalContacts[m_ctContacts].vPos,vCEdgePoint0); m_gLocalContacts[m_ctContacts].nFlags = 1; m_ctContacts++; if (m_ctContacts < (m_iFlags & NUMC_MASK)) { // contact 1 m_gLocalContacts[m_ctContacts].fDepth = fDepth1; SET(m_gLocalContacts[m_ctContacts].vNormal,m_vNormal); SET(m_gLocalContacts[m_ctContacts].vPos,vCEdgePoint1); m_gLocalContacts[m_ctContacts].nFlags = 1; m_ctContacts++; } } void sTrimeshCapsuleColliderData::SetupInitialContext(dxTriMesh *TriMesh, dxGeom *Capsule, int flags, int skip) { const dMatrix3* pRot = (const dMatrix3*)dGeomGetRotation(Capsule); memcpy(m_mCapsuleRotation, pRot, sizeof(dMatrix3)); const dVector3* pDst = (const dVector3*)dGeomGetPosition(Capsule); memcpy(m_vCapsulePosition, pDst, sizeof(dVector3)); m_vCapsuleAxis[0] = m_mCapsuleRotation[0*4 + nCAPSULE_AXIS]; m_vCapsuleAxis[1] = m_mCapsuleRotation[1*4 + nCAPSULE_AXIS]; m_vCapsuleAxis[2] = m_mCapsuleRotation[2*4 + nCAPSULE_AXIS]; // Get size of Capsule dGeomCapsuleGetParams(Capsule, &m_vCapsuleRadius, &m_fCapsuleSize); m_fCapsuleSize += 2*m_vCapsuleRadius; const dMatrix3* pTriRot = (const dMatrix3*)dGeomGetRotation(TriMesh); memcpy(m_mTriMeshRot, pTriRot, sizeof(dMatrix3)); const dVector3* pTriPos = (const dVector3*)dGeomGetPosition(TriMesh); memcpy(m_vTriMeshPos, pTriPos, sizeof(dVector3)); // global info for contact creation m_iStride =skip; m_iFlags =flags; // reset contact counter m_ctContacts = 0; // reset best depth m_fBestDepth = - MAX_REAL; m_fBestCenter = 0; m_fBestrt = 0; // reset collision normal m_vNormal[0] = REAL(0.0); m_vNormal[1] = REAL(0.0); m_vNormal[2] = REAL(0.0); } int sTrimeshCapsuleColliderData::TestCollisionForSingleTriangle(int ctContacts0, int Triint, dVector3 dv[3], uint8 flags, bool &bOutFinishSearching) { // test this triangle _cldTestOneTriangleVSCapsule(dv[0],dv[1],dv[2], flags); // fill-in tri index for generated contacts for (; ctContacts0 < (int)m_ctContacts; ctContacts0++) m_gLocalContacts[ctContacts0].triIndex = Triint; // Putting "break" at the end of loop prevents unnecessary checks on first pass and "continue" bOutFinishSearching = (m_ctContacts >= (m_iFlags & NUMC_MASK)); return ctContacts0; } static void dQueryCCTLPotentialCollisionTriangles(OBBCollider &Collider, const sTrimeshCapsuleColliderData &cData, dxTriMesh *TriMesh, dxGeom *Capsule, OBBCache &BoxCache) { Matrix4x4 MeshMatrix; const dVector3 vZeroVector3 = { REAL(0.0), }; MakeMatrix(vZeroVector3, cData.m_mTriMeshRot, MeshMatrix); const dVector3 &vCapsulePos = cData.m_vCapsulePosition; const dMatrix3 &mCapsuleRot = cData.m_mCapsuleRotation; dVector3 vCapsuleOffsetPos; dSubtractVectors3(vCapsuleOffsetPos, vCapsulePos, cData.m_vTriMeshPos); const dReal fCapsuleRadius = cData.m_vCapsuleRadius, fCapsuleHalfAxis = cData.m_fCapsuleSize * REAL(0.5); OBB obbCapsule; obbCapsule.mCenter.Set(vCapsuleOffsetPos[0], vCapsuleOffsetPos[1], vCapsuleOffsetPos[2]); obbCapsule.mExtents.Set( 0 == nCAPSULE_AXIS ? fCapsuleHalfAxis : fCapsuleRadius, 1 == nCAPSULE_AXIS ? fCapsuleHalfAxis : fCapsuleRadius, 2 == nCAPSULE_AXIS ? fCapsuleHalfAxis : fCapsuleRadius); obbCapsule.mRot.Set( mCapsuleRot[0], mCapsuleRot[4], mCapsuleRot[8], mCapsuleRot[1], mCapsuleRot[5], mCapsuleRot[9], mCapsuleRot[2], mCapsuleRot[6], mCapsuleRot[10]); // TC results if (TriMesh->getDoTC(dxTriMesh::TTC_BOX)) { dxTriMesh::BoxTC* BoxTC = 0; const int iBoxCacheSize = TriMesh->m_BoxTCCache.size(); for (int i = 0; i != iBoxCacheSize; i++){ if (TriMesh->m_BoxTCCache[i].Geom == Capsule){ BoxTC = &TriMesh->m_BoxTCCache[i]; break; } } if (!BoxTC){ TriMesh->m_BoxTCCache.push(dxTriMesh::BoxTC()); BoxTC = &TriMesh->m_BoxTCCache[TriMesh->m_BoxTCCache.size() - 1]; BoxTC->Geom = Capsule; BoxTC->FatCoeff = 1.0f; } // Intersect Collider.SetTemporalCoherence(true); Collider.Collide(*BoxTC, obbCapsule, TriMesh->retrieveMeshBVTreeRef(), null, &MeshMatrix); } else { Collider.SetTemporalCoherence(false); Collider.Collide(BoxCache, obbCapsule, TriMesh->retrieveMeshBVTreeRef(), null, &MeshMatrix); } } // capsule - trimesh by CroTeam // Ported by Nguyem Binh int dCollideCCTL(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) { dIASSERT (skip >= (int)sizeof(dContactGeom)); dIASSERT (o1->type == dTriMeshClass); dIASSERT (o2->type == dCapsuleClass); dIASSERT ((flags & NUMC_MASK) >= 1); int nContactCount = 0; dxTriMesh *TriMesh = (dxTriMesh*)o1; dxGeom *Capsule = o2; sTrimeshCapsuleColliderData cData; cData.SetupInitialContext(TriMesh, Capsule, flags, skip); const unsigned uiTLSKind = TriMesh->getParentSpaceTLSKind(); dIASSERT(uiTLSKind == Capsule->getParentSpaceTLSKind()); // The colliding spaces must use matching cleanup method TrimeshCollidersCache *pccColliderCache = GetTrimeshCollidersCache(uiTLSKind); OBBCollider& Collider = pccColliderCache->m_OBBCollider; // Will it better to use LSS here? -> confirm Pierre. dQueryCCTLPotentialCollisionTriangles(Collider, cData, TriMesh, Capsule, pccColliderCache->m_DefaultBoxCache); if (Collider.GetContactStatus()) { // Retrieve data int TriCount = Collider.GetNbTouchedPrimitives(); if (TriCount != 0) { const int* Triangles = (const int*)Collider.GetTouchedPrimitives(); if (TriMesh->m_ArrayCallback != null) { TriMesh->m_ArrayCallback(TriMesh, Capsule, Triangles, TriCount); } // allocate buffer for local contacts on stack cData.m_gLocalContacts = (sLocalContactData*)dALLOCA16(sizeof(sLocalContactData)*(cData.m_iFlags & NUMC_MASK)); unsigned int ctContacts0 = cData.m_ctContacts; const uint8 *useFlags = TriMesh->retrieveMeshSmartUseFlags(); // loop through all intersecting triangles for (int i = 0; i < TriCount; i++) { const int Triint = Triangles[i]; if (!TriMesh->invokeCallback(Capsule, Triint)) continue; dVector3 dv[3]; TriMesh->fetchMeshTriangle(dv, Triint, cData.m_vTriMeshPos, cData.m_mTriMeshRot); uint8 flags = useFlags != NULL ? useFlags[Triint] : (uint8)dxTriMeshData::CUF__USE_ALL_COMPONENTS; bool bFinishSearching; ctContacts0 = cData.TestCollisionForSingleTriangle(ctContacts0, Triint, dv, flags, bFinishSearching); if (bFinishSearching) { break; } } if (cData.m_ctContacts != 0) { nContactCount = cData._ProcessLocalContacts(contact, TriMesh, Capsule); } } } return nContactCount; } #endif // GIMPACT version #if dTRIMESH_GIMPACT #include "gimpact_contact_export_helper.h" #include "gimpact_gim_contact_accessor.h" #define nCAPSULE_AXIS 2 // capsule - trimesh By francisco leon int dCollideCCTL(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) { dIASSERT (skip >= (int)sizeof(dContactGeom)); dIASSERT (o1->type == dTriMeshClass); dIASSERT (o2->type == dCapsuleClass); dIASSERT ((flags & NUMC_MASK) >= 1); dxTriMesh* TriMesh = (dxTriMesh*)o1; dxGeom* gCylinder = o2; //Get capsule params dMatrix3 mCapsuleRotation; dVector3 vCapsulePosition; dVector3 vCapsuleAxis; dReal vCapsuleRadius; dReal fCapsuleSize; dMatrix3* pRot = (dMatrix3*) dGeomGetRotation(gCylinder); memcpy(mCapsuleRotation,pRot,sizeof(dMatrix3)); dVector3* pDst = (dVector3*)dGeomGetPosition(gCylinder); memcpy(vCapsulePosition,pDst,sizeof(dVector3)); //Axis vCapsuleAxis[0] = mCapsuleRotation[0*4 + nCAPSULE_AXIS]; vCapsuleAxis[1] = mCapsuleRotation[1*4 + nCAPSULE_AXIS]; vCapsuleAxis[2] = mCapsuleRotation[2*4 + nCAPSULE_AXIS]; // Get size of CCylinder dGeomCCylinderGetParams(gCylinder,&vCapsuleRadius,&fCapsuleSize); fCapsuleSize*=0.5f; //Set Capsule params GIM_CAPSULE_DATA capsule; capsule.m_radius = vCapsuleRadius; VEC_SCALE(capsule.m_point1,fCapsuleSize,vCapsuleAxis); VEC_SUM(capsule.m_point1,vCapsulePosition,capsule.m_point1); VEC_SCALE(capsule.m_point2,-fCapsuleSize,vCapsuleAxis); VEC_SUM(capsule.m_point2,vCapsulePosition,capsule.m_point2); //Create contact list GDYNAMIC_ARRAY trimeshcontacts; GIM_CREATE_CONTACT_LIST(trimeshcontacts); //Collide trimeshe vs capsule gim_trimesh_capsule_collision(&TriMesh->m_collision_trimesh,&capsule,&trimeshcontacts); if(trimeshcontacts.m_size == 0) { GIM_DYNARRAY_DESTROY(trimeshcontacts); return 0; } GIM_CONTACT * ptrimeshcontacts = GIM_DYNARRAY_POINTER(GIM_CONTACT,trimeshcontacts); unsigned contactcount = trimeshcontacts.m_size; dxGIMCContactAccessor contactaccessor(ptrimeshcontacts, TriMesh, gCylinder, -1); contactcount = dxGImpactContactsExportHelper::ExportMaxDepthGImpactContacts(contactaccessor, contactcount, flags, contact, skip); GIM_DYNARRAY_DESTROY(trimeshcontacts); return (int)contactcount; } #endif // dTRIMESH_GIMPACT #endif // dTRIMESH_ENABLED ode-0.16/ode/src/ray.cpp0000664000175200017520000006146613403272463012014 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* standard ODE geometry primitives: public API and pairwise collision functions. the rule is that only the low level primitive collision functions should set dContactGeom::g1 and dContactGeom::g2. */ #include #include #include #include "config.h" #include "matrix.h" #include "odemath.h" #include "collision_kernel.h" #include "collision_std.h" #include "collision_util.h" #ifdef _MSC_VER #pragma warning(disable:4291) // for VC++, no complaints about "no matching operator delete found" #endif //**************************************************************************** // ray public API dxRay::dxRay (dSpaceID space, dReal _length) : dxGeom (space,1) { type = dRayClass; length = _length; } void dxRay::computeAABB() { dVector3 e; e[0] = final_posr->pos[0] + final_posr->R[0*4+2]*length; e[1] = final_posr->pos[1] + final_posr->R[1*4+2]*length; e[2] = final_posr->pos[2] + final_posr->R[2*4+2]*length; if (final_posr->pos[0] < e[0]){ aabb[0] = final_posr->pos[0]; aabb[1] = e[0]; } else{ aabb[0] = e[0]; aabb[1] = final_posr->pos[0]; } if (final_posr->pos[1] < e[1]){ aabb[2] = final_posr->pos[1]; aabb[3] = e[1]; } else{ aabb[2] = e[1]; aabb[3] = final_posr->pos[1]; } if (final_posr->pos[2] < e[2]){ aabb[4] = final_posr->pos[2]; aabb[5] = e[2]; } else{ aabb[4] = e[2]; aabb[5] = final_posr->pos[2]; } } dGeomID dCreateRay (dSpaceID space, dReal length) { return new dxRay (space,length); } void dGeomRaySetLength (dGeomID g, dReal length) { dUASSERT (g && g->type == dRayClass,"argument not a ray"); dxRay *r = (dxRay*) g; r->length = length; dGeomMoved (g); } dReal dGeomRayGetLength (dGeomID g) { dUASSERT (g && g->type == dRayClass,"argument not a ray"); dxRay *r = (dxRay*) g; return r->length; } void dGeomRaySet (dGeomID g, dReal px, dReal py, dReal pz, dReal dx, dReal dy, dReal dz) { dUASSERT (g && g->type == dRayClass,"argument not a ray"); g->recomputePosr(); dReal* rot = g->final_posr->R; dReal* pos = g->final_posr->pos; dVector3 n; pos[0] = px; pos[1] = py; pos[2] = pz; n[0] = dx; n[1] = dy; n[2] = dz; dNormalize3(n); rot[0*4+2] = n[0]; rot[1*4+2] = n[1]; rot[2*4+2] = n[2]; dGeomMoved (g); } void dGeomRayGet (dGeomID g, dVector3 start, dVector3 dir) { dUASSERT (g && g->type == dRayClass,"argument not a ray"); g->recomputePosr(); start[0] = g->final_posr->pos[0]; start[1] = g->final_posr->pos[1]; start[2] = g->final_posr->pos[2]; dir[0] = g->final_posr->R[0*4+2]; dir[1] = g->final_posr->R[1*4+2]; dir[2] = g->final_posr->R[2*4+2]; } void dGeomRaySetParams (dxGeom *g, int FirstContact, int BackfaceCull) { dUASSERT (g && g->type == dRayClass,"argument not a ray"); dGeomRaySetFirstContact(g, FirstContact); dGeomRaySetBackfaceCull(g, BackfaceCull); } void dGeomRayGetParams (dxGeom *g, int *FirstContact, int *BackfaceCull) { dUASSERT (g && g->type == dRayClass,"argument not a ray"); (*FirstContact) = ((g->gflags & RAY_FIRSTCONTACT) != 0); (*BackfaceCull) = ((g->gflags & RAY_BACKFACECULL) != 0); } // set/get backface culling flag void dGeomRaySetBackfaceCull (dxGeom *g, int backfaceCull) { dUASSERT (g && g->type == dRayClass,"argument not a ray"); if (backfaceCull) { g->gflags |= RAY_BACKFACECULL; } else { g->gflags &= ~RAY_BACKFACECULL; } } int dGeomRayGetBackfaceCull (dxGeom *g) { dUASSERT (g && g->type == dRayClass,"argument not a ray"); return ((g->gflags & RAY_BACKFACECULL) != 0); } // set/get first contact flag void dGeomRaySetFirstContact (dxGeom *g, int firstContact) { dUASSERT (g && g->type == dRayClass,"argument not a ray"); if (firstContact) { g->gflags |= RAY_FIRSTCONTACT; } else { g->gflags &= ~RAY_FIRSTCONTACT; } } int dGeomRayGetFirstContact (dxGeom *g) { dUASSERT (g && g->type == dRayClass,"argument not a ray"); return ((g->gflags & RAY_FIRSTCONTACT) != 0); } void dGeomRaySetClosestHit (dxGeom *g, int closestHit) { dUASSERT (g && g->type == dRayClass,"argument not a ray"); if (closestHit){ g->gflags |= RAY_CLOSEST_HIT; } else g->gflags &= ~RAY_CLOSEST_HIT; } int dGeomRayGetClosestHit (dxGeom *g) { dUASSERT (g && g->type == dRayClass,"argument not a ray"); return ((g->gflags & RAY_CLOSEST_HIT) != 0); } // if mode==1 then use the sphere exit contact, not the entry contact static int ray_sphere_helper (dxRay *ray, dVector3 sphere_pos, dReal radius, dContactGeom *contact, int mode) { dVector3 q; q[0] = ray->final_posr->pos[0] - sphere_pos[0]; q[1] = ray->final_posr->pos[1] - sphere_pos[1]; q[2] = ray->final_posr->pos[2] - sphere_pos[2]; dReal B = dCalcVectorDot3_14(q,ray->final_posr->R+2); dReal C = dCalcVectorDot3(q,q) - radius*radius; // note: if C <= 0 then the start of the ray is inside the sphere dReal k = B*B - C; if (k < 0) return 0; k = dSqrt(k); dReal alpha; if (mode && C >= 0) { alpha = -B + k; if (alpha < 0) return 0; } else { alpha = -B - k; if (alpha < 0) { alpha = -B + k; if (alpha < 0) return 0; } } if (alpha > ray->length) return 0; contact->pos[0] = ray->final_posr->pos[0] + alpha*ray->final_posr->R[0*4+2]; contact->pos[1] = ray->final_posr->pos[1] + alpha*ray->final_posr->R[1*4+2]; contact->pos[2] = ray->final_posr->pos[2] + alpha*ray->final_posr->R[2*4+2]; dReal nsign = (C < 0 || mode) ? REAL(-1.0) : REAL(1.0); contact->normal[0] = nsign*(contact->pos[0] - sphere_pos[0]); contact->normal[1] = nsign*(contact->pos[1] - sphere_pos[1]); contact->normal[2] = nsign*(contact->pos[2] - sphere_pos[2]); dNormalize3 (contact->normal); contact->depth = alpha; return 1; } int dCollideRaySphere (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) { dIASSERT (skip >= (int)sizeof(dContactGeom)); dIASSERT (o1->type == dRayClass); dIASSERT (o2->type == dSphereClass); dIASSERT ((flags & NUMC_MASK) >= 1); dxRay *ray = (dxRay*) o1; dxSphere *sphere = (dxSphere*) o2; contact->g1 = ray; contact->g2 = sphere; contact->side1 = -1; contact->side2 = -1; return ray_sphere_helper (ray,sphere->final_posr->pos,sphere->radius,contact,0); } int dCollideRayBox (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) { dIASSERT (skip >= (int)sizeof(dContactGeom)); dIASSERT (o1->type == dRayClass); dIASSERT (o2->type == dBoxClass); dIASSERT ((flags & NUMC_MASK) >= 1); dxRay *ray = (dxRay*) o1; dxBox *box = (dxBox*) o2; contact->g1 = ray; contact->g2 = box; contact->side1 = -1; contact->side2 = -1; int i; // compute the start and delta of the ray relative to the box. // we will do all subsequent computations in this box-relative coordinate // system. we have to do a translation and rotation for each point. dVector3 tmp,s,v; tmp[0] = ray->final_posr->pos[0] - box->final_posr->pos[0]; tmp[1] = ray->final_posr->pos[1] - box->final_posr->pos[1]; tmp[2] = ray->final_posr->pos[2] - box->final_posr->pos[2]; dMultiply1_331 (s,box->final_posr->R,tmp); tmp[0] = ray->final_posr->R[0*4+2]; tmp[1] = ray->final_posr->R[1*4+2]; tmp[2] = ray->final_posr->R[2*4+2]; dMultiply1_331 (v,box->final_posr->R,tmp); // mirror the line so that v has all components >= 0 dVector3 sign; for (i=0; i<3; i++) { if (v[i] < 0) { s[i] = -s[i]; v[i] = -v[i]; sign[i] = 1; } else sign[i] = -1; } // compute the half-sides of the box dReal h[3]; h[0] = REAL(0.5) * box->side[0]; h[1] = REAL(0.5) * box->side[1]; h[2] = REAL(0.5) * box->side[2]; // do a few early exit tests if ((s[0] < -h[0] && v[0] <= 0) || s[0] > h[0] || (s[1] < -h[1] && v[1] <= 0) || s[1] > h[1] || (s[2] < -h[2] && v[2] <= 0) || s[2] > h[2] || (v[0] == 0 && v[1] == 0 && v[2] == 0)) { return 0; } // compute the t=[lo..hi] range for where s+v*t intersects the box dReal lo = -dInfinity; dReal hi = dInfinity; int nlo = 0, nhi = 0; for (i=0; i<3; i++) { if (v[i] != 0) { dReal k = (-h[i] - s[i])/v[i]; if (k > lo) { lo = k; nlo = i; } k = (h[i] - s[i])/v[i]; if (k < hi) { hi = k; nhi = i; } } } // check if the ray intersects if (lo > hi) return 0; dReal alpha; int n; if (lo >= 0) { alpha = lo; n = nlo; } else { alpha = hi; n = nhi; } if (alpha < 0 || alpha > ray->length) return 0; contact->pos[0] = ray->final_posr->pos[0] + alpha*ray->final_posr->R[0*4+2]; contact->pos[1] = ray->final_posr->pos[1] + alpha*ray->final_posr->R[1*4+2]; contact->pos[2] = ray->final_posr->pos[2] + alpha*ray->final_posr->R[2*4+2]; contact->normal[0] = box->final_posr->R[0*4+n] * sign[n]; contact->normal[1] = box->final_posr->R[1*4+n] * sign[n]; contact->normal[2] = box->final_posr->R[2*4+n] * sign[n]; contact->depth = alpha; return 1; } int dCollideRayCapsule (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) { dIASSERT (skip >= (int)sizeof(dContactGeom)); dIASSERT (o1->type == dRayClass); dIASSERT (o2->type == dCapsuleClass); dIASSERT ((flags & NUMC_MASK) >= 1); dxRay *ray = (dxRay*) o1; dxCapsule *ccyl = (dxCapsule*) o2; contact->g1 = ray; contact->g2 = ccyl; contact->side1 = -1; contact->side2 = -1; dReal lz2 = ccyl->lz * REAL(0.5); // compute some useful info dVector3 cs,q,r; dReal C,k; cs[0] = ray->final_posr->pos[0] - ccyl->final_posr->pos[0]; cs[1] = ray->final_posr->pos[1] - ccyl->final_posr->pos[1]; cs[2] = ray->final_posr->pos[2] - ccyl->final_posr->pos[2]; k = dCalcVectorDot3_41(ccyl->final_posr->R+2,cs); // position of ray start along ccyl axis q[0] = k*ccyl->final_posr->R[0*4+2] - cs[0]; q[1] = k*ccyl->final_posr->R[1*4+2] - cs[1]; q[2] = k*ccyl->final_posr->R[2*4+2] - cs[2]; C = dCalcVectorDot3(q,q) - ccyl->radius*ccyl->radius; // if C < 0 then ray start position within infinite extension of cylinder // see if ray start position is inside the capped cylinder int inside_ccyl = 0; if (C < 0) { if (k < -lz2) k = -lz2; else if (k > lz2) k = lz2; r[0] = ccyl->final_posr->pos[0] + k*ccyl->final_posr->R[0*4+2]; r[1] = ccyl->final_posr->pos[1] + k*ccyl->final_posr->R[1*4+2]; r[2] = ccyl->final_posr->pos[2] + k*ccyl->final_posr->R[2*4+2]; if ((ray->final_posr->pos[0]-r[0])*(ray->final_posr->pos[0]-r[0]) + (ray->final_posr->pos[1]-r[1])*(ray->final_posr->pos[1]-r[1]) + (ray->final_posr->pos[2]-r[2])*(ray->final_posr->pos[2]-r[2]) < ccyl->radius*ccyl->radius) { inside_ccyl = 1; } } // compute ray collision with infinite cylinder, except for the case where // the ray is outside the capped cylinder but within the infinite cylinder // (it that case the ray can only hit endcaps) if (!inside_ccyl && C < 0) { // set k to cap position to check if (k < 0) k = -lz2; else k = lz2; } else { dReal uv = dCalcVectorDot3_44(ccyl->final_posr->R+2,ray->final_posr->R+2); r[0] = uv*ccyl->final_posr->R[0*4+2] - ray->final_posr->R[0*4+2]; r[1] = uv*ccyl->final_posr->R[1*4+2] - ray->final_posr->R[1*4+2]; r[2] = uv*ccyl->final_posr->R[2*4+2] - ray->final_posr->R[2*4+2]; dReal A = dCalcVectorDot3(r,r); // A == 0 means that the ray and ccylinder axes are parallel if (A == 0) { // There is a division by A below... // set k to cap position to check if (uv < 0) k = -lz2; else k = lz2; } else { dReal B = 2*dCalcVectorDot3(q,r); k = B*B-4*A*C; if (k < 0) { // the ray does not intersect the infinite cylinder, but if the ray is // inside and parallel to the cylinder axis it may intersect the end // caps. set k to cap position to check. if (!inside_ccyl) return 0; if (uv < 0) k = -lz2; else k = lz2; } else { k = dSqrt(k); A = dRecip (2*A); dReal alpha = (-B-k)*A; if (alpha < 0) { alpha = (-B+k)*A; if (alpha < 0) return 0; } if (alpha > ray->length) return 0; // the ray intersects the infinite cylinder. check to see if the // intersection point is between the caps contact->pos[0] = ray->final_posr->pos[0] + alpha*ray->final_posr->R[0*4+2]; contact->pos[1] = ray->final_posr->pos[1] + alpha*ray->final_posr->R[1*4+2]; contact->pos[2] = ray->final_posr->pos[2] + alpha*ray->final_posr->R[2*4+2]; q[0] = contact->pos[0] - ccyl->final_posr->pos[0]; q[1] = contact->pos[1] - ccyl->final_posr->pos[1]; q[2] = contact->pos[2] - ccyl->final_posr->pos[2]; k = dCalcVectorDot3_14(q,ccyl->final_posr->R+2); dReal nsign = inside_ccyl ? REAL(-1.0) : REAL(1.0); if (k >= -lz2 && k <= lz2) { contact->normal[0] = nsign * (contact->pos[0] - (ccyl->final_posr->pos[0] + k*ccyl->final_posr->R[0*4+2])); contact->normal[1] = nsign * (contact->pos[1] - (ccyl->final_posr->pos[1] + k*ccyl->final_posr->R[1*4+2])); contact->normal[2] = nsign * (contact->pos[2] - (ccyl->final_posr->pos[2] + k*ccyl->final_posr->R[2*4+2])); dNormalize3 (contact->normal); contact->depth = alpha; return 1; } // the infinite cylinder intersection point is not between the caps. // set k to cap position to check. if (k < 0) k = -lz2; else k = lz2; } } } // check for ray intersection with the caps. k must indicate the cap // position to check q[0] = ccyl->final_posr->pos[0] + k*ccyl->final_posr->R[0*4+2]; q[1] = ccyl->final_posr->pos[1] + k*ccyl->final_posr->R[1*4+2]; q[2] = ccyl->final_posr->pos[2] + k*ccyl->final_posr->R[2*4+2]; return ray_sphere_helper (ray,q,ccyl->radius,contact, inside_ccyl); } int dCollideRayPlane (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) { dIASSERT (skip >= (int)sizeof(dContactGeom)); dIASSERT (o1->type == dRayClass); dIASSERT (o2->type == dPlaneClass); dIASSERT ((flags & NUMC_MASK) >= 1); dxRay *ray = (dxRay*) o1; dxPlane *plane = (dxPlane*) o2; dReal alpha = plane->p[3] - dCalcVectorDot3 (plane->p,ray->final_posr->pos); // note: if alpha > 0 the starting point is below the plane dReal nsign = (alpha > 0) ? REAL(-1.0) : REAL(1.0); dReal k = dCalcVectorDot3_14(plane->p,ray->final_posr->R+2); if (k==0) return 0; // ray parallel to plane alpha /= k; if (alpha < 0 || alpha > ray->length) return 0; contact->pos[0] = ray->final_posr->pos[0] + alpha*ray->final_posr->R[0*4+2]; contact->pos[1] = ray->final_posr->pos[1] + alpha*ray->final_posr->R[1*4+2]; contact->pos[2] = ray->final_posr->pos[2] + alpha*ray->final_posr->R[2*4+2]; contact->normal[0] = nsign*plane->p[0]; contact->normal[1] = nsign*plane->p[1]; contact->normal[2] = nsign*plane->p[2]; contact->depth = alpha; contact->g1 = ray; contact->g2 = plane; contact->side1 = -1; contact->side2 = -1; return 1; } // Ray-Cylinder collider by Joseph Cooper (2011) int dCollideRayCylinder( dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip ) { dIASSERT( skip >= (int)sizeof( dContactGeom ) ); dIASSERT( o1->type == dRayClass ); dIASSERT( o2->type == dCylinderClass ); dIASSERT( (flags & NUMC_MASK) >= 1 ); dxRay* ray = (dxRay*)( o1 ); dxCylinder* cyl = (dxCylinder*)( o2 ); // Fill in contact information. contact->g1 = ray; contact->g2 = cyl; contact->side1 = -1; contact->side2 = -1; const dReal half_length = cyl->lz * REAL( 0.5 ); /* Possible collision cases: * Ray origin between/outside caps * Ray origin within/outside radius * Ray direction left/right/perpendicular * Ray direction parallel/perpendicular/other * * Ray origin cases (ignoring origin on surface) * * A B * /-\-----------\ * C ( ) D ) * \_/___________/ * * Cases A and D can collide with caps or cylinder * Case C can only collide with the caps * Case B can only collide with the cylinder * Case D will produce inverted normals * If the ray is perpendicular, only check the cylinder * If the ray is parallel to cylinder axis, * we can only check caps * If the ray points right, * Case A,C Check left cap * Case D Check right cap * If the ray points left * Case A,C Check right cap * Case D Check left cap * Case B, check only first possible cylinder collision * Case D, check only second possible cylinder collision */ // Find the ray in the cylinder coordinate frame: dVector3 tmp; dVector3 pos; // Ray origin in cylinder frame dVector3 dir; // Ray direction in cylinder frame // Translate ray start by inverse cyl dSubtractVectors3(tmp,ray->final_posr->pos,cyl->final_posr->pos); // Rotate ray start by inverse cyl dMultiply1_331(pos,cyl->final_posr->R,tmp); // Get the ray's direction tmp[0] = ray->final_posr->R[2]; tmp[1] = ray->final_posr->R[6]; tmp[2] = ray->final_posr->R[10]; // Rotate the ray direction by inverse cyl dMultiply1_331(dir,cyl->final_posr->R,tmp); // Is the ray origin inside of the (extended) cylinder? dReal r2 = cyl->radius*cyl->radius; dReal C = pos[0]*pos[0] + pos[1]*pos[1] - r2; // Find the different cases // Is ray parallel to the cylinder length? int parallel = (dir[0]==0 && dir[1]==0); // Is ray perpendicular to the cylinder length? int perpendicular = (dir[2]==0); // Is ray origin within the radius of the caps? int inRadius = (C<=0); // Is ray origin between the top and bottom caps? int inCaps = (dFabs(pos[2])<=half_length); int checkCaps = (!perpendicular && (!inCaps || inRadius)); int checkCyl = (!parallel && (!inRadius || inCaps)); int flipNormals = (inCaps&&inRadius); dReal tt=-dInfinity; // Depth to intersection dVector3 tmpNorm = {dNaN, dNaN, dNaN}; // ensure we don't leak garbage if (checkCaps) { // Make it so we only need to check one cap int flipDir = 0; // Wish c had logical xor... if ((dir[2]<0 && flipNormals) || (dir[2]>0 && !flipNormals)) { flipDir = 1; dir[2]=-dir[2]; pos[2]=-pos[2]; } // The cap is half the cylinder's length // from the cylinder's origin // We only checkCaps if dir[2]!=0 tt = (half_length-pos[2])/dir[2]; if (tt>=0 && tt<=ray->length) { tmp[0] = pos[0] + tt*dir[0]; tmp[1] = pos[1] + tt*dir[1]; // Ensure collision point is within cap circle if (tmp[0]*tmp[0] + tmp[1]*tmp[1] <= r2) { // Successful collision tmp[2] = (flipDir)?-half_length:half_length; tmpNorm[0]=0; tmpNorm[1]=0; tmpNorm[2]=(flipDir!=flipNormals)?-REAL(1.0):REAL(1.0); checkCyl = 0; // Short circuit cylinder check } else { // Ray hits cap plane outside of cap circle tt=-dInfinity; // No collision yet } } else { // The cap plane is beyond (or behind) the ray length tt=-dInfinity; // No collision yet } if (flipDir) { // Flip back dir[2]=-dir[2]; pos[2]=-pos[2]; } } if (checkCyl) { // Compute quadratic formula for parametric ray equation dReal A = dir[0]*dir[0] + dir[1]*dir[1]; dReal B = 2*(pos[0]*dir[0] + pos[1]*dir[1]); // Already computed C dReal k = B*B - 4*A*C; // Check collision with infinite cylinder // k<0 means the ray passes outside the cylinder // k==0 means ray is tangent to cylinder (or parallel) // // Our quadratic formula: tt = (-B +- sqrt(k))/(2*A) // // A must be positive (otherwise we wouldn't be checking // cylinder because ray is parallel) // if (k<0) ray doesn't collide with sphere // if (B > sqrt(k)) then both times are negative // -- don't calculate // if (B<-sqrt(k)) then both times are positive (Case A or B) // -- only calculate first, if first isn't valid // -- second can't be without first going through a cap // otherwise (fabs(B)<=sqrt(k)) then C<=0 (ray-origin inside/on cylinder) // -- only calculate second collision if (k>=0 && (B<0 || B*B<=k)) { k = dSqrt(k); A = dRecip(2*A); if (dFabs(B)<=k) { tt = (-B + k)*A; // Second solution // If ray origin is on surface and pointed out, we // can get a tt=0 solution... } else { tt = (-B - k)*A; // First solution } if (tt<=ray->length) { tmp[2] = pos[2] + tt*dir[2]; if (dFabs(tmp[2])<=half_length) { // Valid solution tmp[0] = pos[0] + tt*dir[0]; tmp[1] = pos[1] + tt*dir[1]; tmpNorm[0] = tmp[0]/cyl->radius; tmpNorm[1] = tmp[1]/cyl->radius; tmpNorm[2] = 0; if (flipNormals) { // Ray origin was inside cylinder tmpNorm[0] = -tmpNorm[0]; tmpNorm[1] = -tmpNorm[1]; } } else { // Ray hits cylinder outside of caps tt=-dInfinity; } } else { // Ray doesn't reach the cylinder tt=-dInfinity; } } } if (tt>0) { contact->depth = tt; // Transform the point back to world coordinates tmpNorm[3]=0; tmp[3] = 0; dMultiply0_331(contact->normal,cyl->final_posr->R,tmpNorm); dMultiply0_331(contact->pos,cyl->final_posr->R,tmp); contact->pos[0]+=cyl->final_posr->pos[0]; contact->pos[1]+=cyl->final_posr->pos[1]; contact->pos[2]+=cyl->final_posr->pos[2]; return 1; } // No contact with anything. return 0; } ode-0.16/ode/src/util.h0000664000175200017520000003737513403272463011645 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_UTIL_H_ #define _ODE_UTIL_H_ #include "objects.h" #include "common.h" /* utility */ void dInternalHandleAutoDisabling (dxWorld *world, dReal stepsize); void dxStepBody (dxBody *b, dReal h); struct dxWorldProcessMemoryManager: public dBase { typedef void *(*alloc_block_fn_t)(sizeint block_size); typedef void *(*shrink_block_fn_t)(void *block_pointer, sizeint block_current_size, sizeint block_smaller_size); typedef void (*free_block_fn_t)(void *block_pointer, sizeint block_current_size); dxWorldProcessMemoryManager(alloc_block_fn_t fnAlloc, shrink_block_fn_t fnShrink, free_block_fn_t fnFree) { Assign(fnAlloc, fnShrink, fnFree); } void Assign(alloc_block_fn_t fnAlloc, shrink_block_fn_t fnShrink, free_block_fn_t fnFree) { m_fnAlloc = fnAlloc; m_fnShrink = fnShrink; m_fnFree = fnFree; } alloc_block_fn_t m_fnAlloc; shrink_block_fn_t m_fnShrink; free_block_fn_t m_fnFree; }; extern dxWorldProcessMemoryManager g_WorldProcessMallocMemoryManager; struct dxWorldProcessMemoryReserveInfo: public dBase { dxWorldProcessMemoryReserveInfo(float fReserveFactor, unsigned uiReserveMinimum) { Assign(fReserveFactor, uiReserveMinimum); } void Assign(float fReserveFactor, unsigned uiReserveMinimum) { m_fReserveFactor = fReserveFactor; m_uiReserveMinimum = uiReserveMinimum; } float m_fReserveFactor; // Use float as precision does not matter here unsigned m_uiReserveMinimum; }; extern dxWorldProcessMemoryReserveInfo g_WorldProcessDefaultReserveInfo; class dxWorldProcessMemArena: private dBase // new/delete must not be called for this class { public: #define BUFFER_TO_ARENA_EXTRA (EFFICIENT_ALIGNMENT + dEFFICIENT_SIZE(sizeof(dxWorldProcessMemArena))) static bool IsArenaPossible(sizeint nBufferSize) { return SIZE_MAX - BUFFER_TO_ARENA_EXTRA >= nBufferSize; // This ensures there will be no overflow } static sizeint MakeBufferSize(sizeint nArenaSize) { return nArenaSize - BUFFER_TO_ARENA_EXTRA; } static sizeint MakeArenaSize(sizeint nBufferSize) { return BUFFER_TO_ARENA_EXTRA + nBufferSize; } #undef BUFFER_TO_ARENA_EXTRA bool IsStructureValid() const { return m_pAllocBegin != NULL && m_pAllocEnd != NULL && m_pAllocBegin <= m_pAllocEnd && (m_pAllocCurrentOrNextArena == NULL || m_pAllocCurrentOrNextArena == m_pAllocBegin) && m_pArenaBegin != NULL && m_pArenaBegin <= m_pAllocBegin; } sizeint GetMemorySize() const { return (sizeint)m_pAllocEnd - (sizeint)m_pAllocBegin; } void *SaveState() const { return m_pAllocCurrentOrNextArena; } void RestoreState(void *state) { m_pAllocCurrentOrNextArena = state; } void ResetState() { m_pAllocCurrentOrNextArena = m_pAllocBegin; } void *PeekBufferRemainder() const { return m_pAllocCurrentOrNextArena; } void *AllocateBlock(sizeint size) { void *arena = m_pAllocCurrentOrNextArena; m_pAllocCurrentOrNextArena = dOFFSET_EFFICIENTLY(arena, size); dIASSERT(m_pAllocCurrentOrNextArena <= m_pAllocEnd); dIASSERT(dEFFICIENT_PTR(arena) == arena); return arena; } void *AllocateOveralignedBlock(sizeint size, unsigned alignment) { void *arena = m_pAllocCurrentOrNextArena; m_pAllocCurrentOrNextArena = dOFFSET_OVERALIGNEDLY(arena, size, alignment); dIASSERT(m_pAllocCurrentOrNextArena <= m_pAllocEnd); void *block = dOVERALIGNED_PTR(arena, alignment); return block; } template ElementType *AllocateArray(sizeint count) { return (ElementType *)AllocateBlock(count * sizeof(ElementType)); } template ElementType *AllocateOveralignedArray(sizeint count, unsigned alignment) { return (ElementType *)AllocateOveralignedBlock(count * sizeof(ElementType), alignment); } template void ShrinkArray(ElementType *arr, sizeint oldcount, sizeint newcount) { dIASSERT(newcount <= oldcount); dIASSERT(dOFFSET_EFFICIENTLY(arr, oldcount * sizeof(ElementType)) == m_pAllocCurrentOrNextArena); m_pAllocCurrentOrNextArena = dOFFSET_EFFICIENTLY(arr, newcount * sizeof(ElementType)); } public: static dxWorldProcessMemArena *ReallocateMemArena ( dxWorldProcessMemArena *oldarena, sizeint memreq, const dxWorldProcessMemoryManager *memmgr, float rsrvfactor, unsigned rsrvminimum); static void FreeMemArena (dxWorldProcessMemArena *arena); dxWorldProcessMemArena *GetNextMemArena() const { return (dxWorldProcessMemArena *)m_pAllocCurrentOrNextArena; } void SetNextMemArena(dxWorldProcessMemArena *pArenaInstance) { m_pAllocCurrentOrNextArena = pArenaInstance; } private: static sizeint AdjustArenaSizeForReserveRequirements(sizeint arenareq, float rsrvfactor, unsigned rsrvminimum); private: void *m_pAllocCurrentOrNextArena; void *m_pAllocBegin; void *m_pAllocEnd; void *m_pArenaBegin; const dxWorldProcessMemoryManager *m_pArenaMemMgr; }; class dxWorldProcessContext: public dBase { public: dxWorldProcessContext(); ~dxWorldProcessContext(); void CleanupWorldReferences(dxWorld *pswWorldInstance); public: bool EnsureStepperSyncObjectsAreAllocated(dxWorld *pswWorldInstance); dCallWaitID GetIslandsSteppingWait() const { return m_pcwIslandsSteppingWait; } public: dxWorldProcessMemArena *ObtainStepperMemArena(); void ReturnStepperMemArena(dxWorldProcessMemArena *pmaArenaInstance); dxWorldProcessMemArena *ReallocateIslandsMemArena(sizeint nMemoryRequirement, const dxWorldProcessMemoryManager *pmmMemortManager, float fReserveFactor, unsigned uiReserveMinimum); bool ReallocateStepperMemArenas(dxWorld *world, unsigned nIslandThreadsCount, sizeint nMemoryRequirement, const dxWorldProcessMemoryManager *pmmMemortManager, float fReserveFactor, unsigned uiReserveMinimum); private: static void FreeArenasList(dxWorldProcessMemArena *pmaExistingArenas); private: void SetIslandsMemArena(dxWorldProcessMemArena *pmaInstance) { m_pmaIslandsArena = pmaInstance; } dxWorldProcessMemArena *GetIslandsMemArena() const { return m_pmaIslandsArena; } void SetStepperArenasList(dxWorldProcessMemArena *pmaInstance) { m_pmaStepperArenas = pmaInstance; } dxWorldProcessMemArena *GetStepperArenasList() const { return m_pmaStepperArenas; } inline dxWorldProcessMemArena *GetStepperArenasHead() const; inline bool TryExtractingStepperArenasHead(dxWorldProcessMemArena *pmaHeadInstance); inline bool TryInsertingStepperArenasHead(dxWorldProcessMemArena *pmaArenaInstance, dxWorldProcessMemArena *pmaExistingHead); public: void LockForAddLimotSerialization(); void UnlockForAddLimotSerialization(); void LockForStepbodySerialization(); void UnlockForStepbodySerialization(); private: enum dxProcessContextMutex { dxPCM_STEPPER_ARENA_OBTAIN, dxPCM_STEPPER_ADDLIMOT_SERIALIZE, dxPCM_STEPPER_STEPBODY_SERIALIZE, dxPCM__MAX }; static const char *const m_aszContextMutexNames[dxPCM__MAX]; private: dxWorldProcessMemArena *m_pmaIslandsArena; dxWorldProcessMemArena *volatile m_pmaStepperArenas; dxWorld *m_pswObjectsAllocWorld; dMutexGroupID m_pmgStepperMutexGroup; dCallWaitID m_pcwIslandsSteppingWait; }; struct dxWorldProcessIslandsInfo { void AssignInfo(sizeint islandcount, unsigned int const *islandsizes, dxBody *const *bodies, dxJoint *const *joints) { m_IslandCount = islandcount; m_pIslandSizes = islandsizes; m_pBodies = bodies; m_pJoints = joints; } sizeint GetIslandsCount() const { return m_IslandCount; } unsigned int const *GetIslandSizes() const { return m_pIslandSizes; } dxBody *const *GetBodiesArray() const { return m_pBodies; } dxJoint *const *GetJointsArray() const { return m_pJoints; } private: sizeint m_IslandCount; unsigned int const *m_pIslandSizes; dxBody *const *m_pBodies; dxJoint *const *m_pJoints; }; struct dxStepperProcessingCallContext { dxStepperProcessingCallContext(dxWorld *world, dReal stepSize, unsigned stepperAllowedThreads, dxWorldProcessMemArena *stepperArena, dxBody *const *islandBodiesStart, dxJoint *const *islandJointsStart): m_world(world), m_stepSize(stepSize), m_stepperArena(stepperArena), m_finalReleasee(NULL), m_islandBodiesStart(islandBodiesStart), m_islandJointsStart(islandJointsStart), m_islandBodiesCount(0), m_islandJointsCount(0), m_stepperAllowedThreads(stepperAllowedThreads) { } void AssignIslandSelection(dxBody *const *islandBodiesStart, dxJoint *const *islandJointsStart, unsigned islandBodiesCount, unsigned islandJointsCount) { m_islandBodiesStart = islandBodiesStart; m_islandJointsStart = islandJointsStart; m_islandBodiesCount = islandBodiesCount; m_islandJointsCount = islandJointsCount; } dxBody *const *GetSelectedIslandBodiesEnd() const { return m_islandBodiesStart + m_islandBodiesCount; } dxJoint *const *GetSelectedIslandJointsEnd() const { return m_islandJointsStart + m_islandJointsCount; } void AssignStepperCallFinalReleasee(dCallReleaseeID finalReleasee) { m_finalReleasee = finalReleasee; } dxWorld *const m_world; dReal const m_stepSize; dxWorldProcessMemArena *m_stepperArena; dCallReleaseeID m_finalReleasee; dxBody *const *m_islandBodiesStart; dxJoint *const *m_islandJointsStart; unsigned m_islandBodiesCount; unsigned m_islandJointsCount; unsigned m_stepperAllowedThreads; }; #define BEGIN_STATE_SAVE(memarena, state) void *state = memarena->SaveState(); #define END_STATE_SAVE(memarena, state) memarena->RestoreState(state) typedef void (*dstepper_fn_t) (const dxStepperProcessingCallContext *callContext); typedef unsigned (*dmaxcallcountestimate_fn_t) (unsigned activeThreadCount, unsigned allowedThreadCount); bool dxProcessIslands (dxWorld *world, const dxWorldProcessIslandsInfo &islandsInfo, dReal stepSize, dstepper_fn_t stepper, dmaxcallcountestimate_fn_t maxCallCountEstimator); typedef sizeint (*dmemestimate_fn_t) (dxBody * const *body, unsigned int nb, dxJoint * const *_joint, unsigned int _nj); bool dxReallocateWorldProcessContext (dxWorld *world, dxWorldProcessIslandsInfo &islandsinfo, dReal stepsize, dmemestimate_fn_t stepperestimate); dxWorldProcessMemArena *dxAllocateTemporaryWorldProcessMemArena( sizeint memreq, const dxWorldProcessMemoryManager *memmgr/*=NULL*/, const dxWorldProcessMemoryReserveInfo *reserveinfo/*=NULL*/); void dxFreeTemporaryWorldProcessMemArena(dxWorldProcessMemArena *arena); template inline ClassType *AllocateOnDemand(ClassType *&pctStorage) { ClassType *pctCurrentInstance = pctStorage; if (!pctCurrentInstance) { pctCurrentInstance = new ClassType(); pctStorage = pctCurrentInstance; } return pctCurrentInstance; } // World stepping working memory object class dxStepWorkingMemory: public dBase { public: dxStepWorkingMemory(): m_uiRefCount(1), m_ppcProcessingContext(NULL), m_priReserveInfo(NULL), m_pmmMemoryManager(NULL) {} private: friend struct dBase; // To avoid GCC warning regarding private destructor ~dxStepWorkingMemory() // Use Release() instead { delete m_ppcProcessingContext; delete m_priReserveInfo; delete m_pmmMemoryManager; } public: void Addref() { dIASSERT(~m_uiRefCount != 0); ++m_uiRefCount; } void Release() { dIASSERT(m_uiRefCount != 0); if (--m_uiRefCount == 0) { delete this; } } public: void CleanupMemory() { delete m_ppcProcessingContext; m_ppcProcessingContext = NULL; } void CleanupWorldReferences(dxWorld *world) { if (m_ppcProcessingContext != NULL) { m_ppcProcessingContext->CleanupWorldReferences(world); } } public: dxWorldProcessContext *SureGetWorldProcessingContext() { return AllocateOnDemand(m_ppcProcessingContext); } dxWorldProcessContext *GetWorldProcessingContext() const { return m_ppcProcessingContext; } const dxWorldProcessMemoryReserveInfo *GetMemoryReserveInfo() const { return m_priReserveInfo; } const dxWorldProcessMemoryReserveInfo *SureGetMemoryReserveInfo() const { return m_priReserveInfo ? m_priReserveInfo : &g_WorldProcessDefaultReserveInfo; } void SetMemoryReserveInfo(float fReserveFactor, unsigned uiReserveMinimum) { if (m_priReserveInfo) { m_priReserveInfo->Assign(fReserveFactor, uiReserveMinimum); } else { m_priReserveInfo = new dxWorldProcessMemoryReserveInfo(fReserveFactor, uiReserveMinimum); } } void ResetMemoryReserveInfoToDefault() { if (m_priReserveInfo) { delete m_priReserveInfo; m_priReserveInfo = NULL; } } const dxWorldProcessMemoryManager *GetMemoryManager() const { return m_pmmMemoryManager; } const dxWorldProcessMemoryManager *SureGetMemoryManager() const { return m_pmmMemoryManager ? m_pmmMemoryManager : &g_WorldProcessMallocMemoryManager; } void SetMemoryManager(dxWorldProcessMemoryManager::alloc_block_fn_t fnAlloc, dxWorldProcessMemoryManager::shrink_block_fn_t fnShrink, dxWorldProcessMemoryManager::free_block_fn_t fnFree) { if (m_pmmMemoryManager) { m_pmmMemoryManager->Assign(fnAlloc, fnShrink, fnFree); } else { m_pmmMemoryManager = new dxWorldProcessMemoryManager(fnAlloc, fnShrink, fnFree); } } void ResetMemoryManagerToDefault() { if (m_pmmMemoryManager) { delete m_pmmMemoryManager; m_pmmMemoryManager = NULL; } } private: unsigned m_uiRefCount; dxWorldProcessContext *m_ppcProcessingContext; dxWorldProcessMemoryReserveInfo *m_priReserveInfo; dxWorldProcessMemoryManager *m_pmmMemoryManager; }; #endif ode-0.16/ode/src/util.cpp0000664000175200017520000013723613403272463012175 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include "config.h" #include "util.h" #include "objects.h" #include "joints/joint.h" #include "threadingutils.h" #include #define dMIN(A,B) ((A)>(B) ? (B) : (A)) #define dMAX(A,B) ((B)>(A) ? (B) : (A)) //**************************************************************************** // Malloc based world stepping memory manager /*extern */dxWorldProcessMemoryManager g_WorldProcessMallocMemoryManager(dAlloc, dRealloc, dFree); /*extern */dxWorldProcessMemoryReserveInfo g_WorldProcessDefaultReserveInfo(dWORLDSTEP_RESERVEFACTOR_DEFAULT, dWORLDSTEP_RESERVESIZE_DEFAULT); //**************************************************************************** // dxWorldProcessContext const char *const dxWorldProcessContext::m_aszContextMutexNames[dxPCM__MAX] = { "Stepper Arena Obtain Lock" , // dxPCM_STEPPER_ARENA_OBTAIN, "Joint addLimot Serialize Lock" , // dxPCM_STEPPER_ADDLIMOT_SERIALIZE "Stepper StepBody Serialize Lock" , // dxPCM_STEPPER_STEPBODY_SERIALIZE, }; dxWorldProcessContext::dxWorldProcessContext(): m_pmaIslandsArena(NULL), m_pmaStepperArenas(NULL), m_pswObjectsAllocWorld(NULL), m_pmgStepperMutexGroup(NULL), m_pcwIslandsSteppingWait(NULL) { // Do nothing } dxWorldProcessContext::~dxWorldProcessContext() { dIASSERT((m_pswObjectsAllocWorld != NULL) == (m_pmgStepperMutexGroup != NULL)); dIASSERT((m_pswObjectsAllocWorld != NULL) == (m_pcwIslandsSteppingWait != NULL)); if (m_pswObjectsAllocWorld != NULL) { m_pswObjectsAllocWorld->FreeMutexGroup(m_pmgStepperMutexGroup); // m_pswObjectsAllocWorld->FreeThreadedCallWait(m_pcwIslandsSteppingWait); -- The stock call wait can not be freed } dxWorldProcessMemArena *pmaStepperArenas = m_pmaStepperArenas; if (pmaStepperArenas != NULL) { FreeArenasList(pmaStepperArenas); } if (m_pmaIslandsArena != NULL) { dxWorldProcessMemArena::FreeMemArena(m_pmaIslandsArena); } } void dxWorldProcessContext::CleanupWorldReferences(dxWorld *pswWorldInstance) { dIASSERT((m_pswObjectsAllocWorld != NULL) == (m_pmgStepperMutexGroup != NULL)); dIASSERT((m_pswObjectsAllocWorld != NULL) == (m_pcwIslandsSteppingWait != NULL)); if (m_pswObjectsAllocWorld == pswWorldInstance) { m_pswObjectsAllocWorld->FreeMutexGroup(m_pmgStepperMutexGroup); // m_pswObjectsAllocWorld->FreeThreadedCallWait(m_pcwIslandsSteppingWait); -- The stock call wait can not be freed m_pswObjectsAllocWorld = NULL; m_pmgStepperMutexGroup = NULL; m_pcwIslandsSteppingWait = NULL; } } bool dxWorldProcessContext::EnsureStepperSyncObjectsAreAllocated(dxWorld *pswWorldInstance) { dIASSERT((m_pswObjectsAllocWorld != NULL) == (m_pmgStepperMutexGroup != NULL)); dIASSERT((m_pswObjectsAllocWorld != NULL) == (m_pcwIslandsSteppingWait != NULL)); bool bResult = false; dMutexGroupID pmbStepperMutexGroup = NULL; bool bStepperMutexGroupAllocated = false; do { if (m_pswObjectsAllocWorld == NULL) { pmbStepperMutexGroup = pswWorldInstance->AllocMutexGroup(dxPCM__MAX, m_aszContextMutexNames); if (pmbStepperMutexGroup == NULL) { break; } bStepperMutexGroupAllocated = true; dCallWaitID pcwIslandsSteppingWait = pswWorldInstance->AllocateOrRetrieveStockCallWaitID(); if (pcwIslandsSteppingWait == NULL) { break; } m_pswObjectsAllocWorld = pswWorldInstance; m_pmgStepperMutexGroup = pmbStepperMutexGroup; m_pcwIslandsSteppingWait = pcwIslandsSteppingWait; } bResult = true; } while (false); if (!bResult) { if (bStepperMutexGroupAllocated) { pswWorldInstance->FreeMutexGroup(pmbStepperMutexGroup); } } return bResult; } dxWorldProcessMemArena *dxWorldProcessContext::ObtainStepperMemArena() { dxWorldProcessMemArena *pmaArenaInstance = NULL; while (true) { dxWorldProcessMemArena *pmaRawArenasHead = GetStepperArenasHead(); if (pmaRawArenasHead == NULL) { break; } // Extraction must be locked so that other thread does not "steal" head arena, // use it and then reinsert back with a different "next" dxMutexGroupLockHelper lhLockHelper(m_pswObjectsAllocWorld, m_pmgStepperMutexGroup, dxPCM_STEPPER_ARENA_OBTAIN); dxWorldProcessMemArena *pmaArenasHead = GetStepperArenasHead(); // Arenas head must be re-extracted after mutex has been locked bool bExchangeResult = pmaArenasHead != NULL && TryExtractingStepperArenasHead(pmaArenasHead); lhLockHelper.UnlockMutex(); if (bExchangeResult) { pmaArenasHead->ResetState(); pmaArenaInstance = pmaArenasHead; break; } } return pmaArenaInstance; } void dxWorldProcessContext::ReturnStepperMemArena(dxWorldProcessMemArena *pmaArenaInstance) { while (true) { dxWorldProcessMemArena *pmaArenasHead = GetStepperArenasHead(); pmaArenaInstance->SetNextMemArena(pmaArenasHead); if (TryInsertingStepperArenasHead(pmaArenaInstance, pmaArenasHead)) { break; } } } dxWorldProcessMemArena *dxWorldProcessContext::ReallocateIslandsMemArena(sizeint nMemoryRequirement, const dxWorldProcessMemoryManager *pmmMemortManager, float fReserveFactor, unsigned uiReserveMinimum) { dxWorldProcessMemArena *pmaExistingArena = GetIslandsMemArena(); dxWorldProcessMemArena *pmaNewMemArena = dxWorldProcessMemArena::ReallocateMemArena(pmaExistingArena, nMemoryRequirement, pmmMemortManager, fReserveFactor, uiReserveMinimum); SetIslandsMemArena(pmaNewMemArena); pmaNewMemArena->ResetState(); return pmaNewMemArena; } bool dxWorldProcessContext::ReallocateStepperMemArenas( dxWorld *world, unsigned nIslandThreadsCount, sizeint nMemoryRequirement, const dxWorldProcessMemoryManager *pmmMemortManager, float fReserveFactor, unsigned uiReserveMinimum) { dxWorldProcessMemArena *pmaRebuiltArenasHead = NULL, *pmaRebuiltArenasTail = NULL; dxWorldProcessMemArena *pmaExistingArenas = GetStepperArenasList(); unsigned nArenasToProcess = nIslandThreadsCount; (void)world; // unused // NOTE! // The list is reallocated in a way to assure the largest arenas are at end // and if number of threads decreases they will be freed first of all. while (true) { if (nArenasToProcess == 0) { FreeArenasList(pmaExistingArenas); break; } dxWorldProcessMemArena *pmaOldMemArena = pmaExistingArenas; if (pmaExistingArenas != NULL) { pmaExistingArenas = pmaExistingArenas->GetNextMemArena(); } else { // If existing arenas ended, terminate and erase tail so that new arenas // would be appended to list head. if (pmaRebuiltArenasTail != NULL) { pmaRebuiltArenasTail->SetNextMemArena(NULL); pmaRebuiltArenasTail = NULL; } } dxWorldProcessMemArena *pmaNewMemArena = dxWorldProcessMemArena::ReallocateMemArena(pmaOldMemArena, nMemoryRequirement, pmmMemortManager, fReserveFactor, uiReserveMinimum); if (pmaNewMemArena != NULL) { // Append reallocated arenas to list tail while old arenas still exist... if (pmaRebuiltArenasTail != NULL) { pmaRebuiltArenasTail->SetNextMemArena(pmaNewMemArena); pmaRebuiltArenasTail = pmaNewMemArena; } else if (pmaRebuiltArenasHead == NULL) { pmaRebuiltArenasHead = pmaNewMemArena; pmaRebuiltArenasTail = pmaNewMemArena; } // ...and append them to list head if those are additional arenas created else { pmaNewMemArena->SetNextMemArena(pmaRebuiltArenasHead); pmaRebuiltArenasHead = pmaNewMemArena; } --nArenasToProcess; } else if (pmaOldMemArena == NULL) { break; } } if (pmaRebuiltArenasTail != NULL) { pmaRebuiltArenasTail->SetNextMemArena(NULL); } SetStepperArenasList(pmaRebuiltArenasHead); bool bResult = nArenasToProcess == 0; return bResult; } void dxWorldProcessContext::FreeArenasList(dxWorldProcessMemArena *pmaExistingArenas) { while (pmaExistingArenas != NULL) { dxWorldProcessMemArena *pmaCurrentMemArena = pmaExistingArenas; pmaExistingArenas = pmaExistingArenas->GetNextMemArena(); dxWorldProcessMemArena::FreeMemArena(pmaCurrentMemArena); } } dxWorldProcessMemArena *dxWorldProcessContext::GetStepperArenasHead() const { return m_pmaStepperArenas; } bool dxWorldProcessContext::TryExtractingStepperArenasHead(dxWorldProcessMemArena *pmaHeadInstance) { dxWorldProcessMemArena *pmaNextInstance = pmaHeadInstance->GetNextMemArena(); return ThrsafeCompareExchangePointer((volatile atomicptr *)&m_pmaStepperArenas, (atomicptr)pmaHeadInstance, (atomicptr)pmaNextInstance); } bool dxWorldProcessContext::TryInsertingStepperArenasHead(dxWorldProcessMemArena *pmaArenaInstance, dxWorldProcessMemArena *pmaExistingHead) { return ThrsafeCompareExchangePointer((volatile atomicptr *)&m_pmaStepperArenas, (atomicptr)pmaExistingHead, (atomicptr)pmaArenaInstance); } void dxWorldProcessContext::LockForAddLimotSerialization() { m_pswObjectsAllocWorld->LockMutexGroupMutex(m_pmgStepperMutexGroup, dxPCM_STEPPER_ADDLIMOT_SERIALIZE); } void dxWorldProcessContext::UnlockForAddLimotSerialization() { m_pswObjectsAllocWorld->UnlockMutexGroupMutex(m_pmgStepperMutexGroup, dxPCM_STEPPER_ADDLIMOT_SERIALIZE); } void dxWorldProcessContext::LockForStepbodySerialization() { m_pswObjectsAllocWorld->LockMutexGroupMutex(m_pmgStepperMutexGroup, dxPCM_STEPPER_STEPBODY_SERIALIZE); } void dxWorldProcessContext::UnlockForStepbodySerialization() { m_pswObjectsAllocWorld->UnlockMutexGroupMutex(m_pmgStepperMutexGroup, dxPCM_STEPPER_STEPBODY_SERIALIZE); } //**************************************************************************** // Threading call contexts struct dxSingleIslandCallContext; struct dxIslandsProcessingCallContext { dxIslandsProcessingCallContext(dxWorld *world, const dxWorldProcessIslandsInfo &islandsInfo, dReal stepSize, dstepper_fn_t stepper): m_world(world), m_islandsInfo(islandsInfo), m_stepSize(stepSize), m_stepper(stepper), m_groupReleasee(NULL), m_islandToProcessStorage(0), m_stepperAllowedThreads(0) { } void AssignGroupReleasee(dCallReleaseeID groupReleasee) { m_groupReleasee = groupReleasee; } void SetStepperAllowedThreads(unsigned allowedThreadsLimit) { m_stepperAllowedThreads = allowedThreadsLimit; } static int ThreadedProcessGroup_Callback(void *callContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee); bool ThreadedProcessGroup(); static int ThreadedProcessJobStart_Callback(void *callContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee); void ThreadedProcessJobStart(); static int ThreadedProcessIslandSearch_Callback(void *callContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee); void ThreadedProcessIslandSearch(dxSingleIslandCallContext *stepperCallContext); static int ThreadedProcessIslandStepper_Callback(void *callContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee); void ThreadedProcessIslandStepper(dxSingleIslandCallContext *stepperCallContext); sizeint ObtainNextIslandToBeProcessed(sizeint islandsCount); dxWorld *const m_world; dxWorldProcessIslandsInfo const &m_islandsInfo; dReal const m_stepSize; dstepper_fn_t const m_stepper; dCallReleaseeID m_groupReleasee; sizeint volatile m_islandToProcessStorage; unsigned m_stepperAllowedThreads; }; struct dxSingleIslandCallContext { dxSingleIslandCallContext(dxIslandsProcessingCallContext *islandsProcessingContext, dxWorldProcessMemArena *stepperArena, void *arenaInitialState, dxBody *const *islandBodiesStart, dxJoint *const *islandJointsStart): m_islandsProcessingContext(islandsProcessingContext), m_islandIndex(0), m_stepperArena(stepperArena), m_arenaInitialState(arenaInitialState), m_stepperCallContext(islandsProcessingContext->m_world, islandsProcessingContext->m_stepSize, islandsProcessingContext->m_stepperAllowedThreads, stepperArena, islandBodiesStart, islandJointsStart) { } void AssignIslandSearchProgress(sizeint islandIndex) { m_islandIndex = islandIndex; } void AssignIslandSelection(dxBody *const *islandBodiesStart, dxJoint *const *islandJointsStart, unsigned islandBodiesCount, unsigned islandJointsCount) { m_stepperCallContext.AssignIslandSelection(islandBodiesStart, islandJointsStart, islandBodiesCount, islandJointsCount); } dxBody *const *GetSelectedIslandBodiesEnd() const { return m_stepperCallContext.GetSelectedIslandBodiesEnd(); } dxJoint *const *GetSelectedIslandJointsEnd() const { return m_stepperCallContext.GetSelectedIslandJointsEnd(); } void RestoreSavedMemArenaStateForStepper() { m_stepperArena->RestoreState(m_arenaInitialState); } void AssignStepperCallFinalReleasee(dCallReleaseeID finalReleasee) { m_stepperCallContext.AssignStepperCallFinalReleasee(finalReleasee); } dxIslandsProcessingCallContext *m_islandsProcessingContext; sizeint m_islandIndex; dxWorldProcessMemArena *m_stepperArena; void *m_arenaInitialState; dxStepperProcessingCallContext m_stepperCallContext; }; //**************************************************************************** // Auto disabling void dInternalHandleAutoDisabling (dxWorld *world, dReal stepsize) { dxBody *bb; for ( bb=world->firstbody; bb; bb=(dxBody*)bb->next ) { // don't freeze objects mid-air (patch 1586738) if ( bb->firstjoint == NULL ) continue; // nothing to do unless this body is currently enabled and has // the auto-disable flag set if ( (bb->flags & (dxBodyAutoDisable|dxBodyDisabled)) != dxBodyAutoDisable ) continue; // if sampling / threshold testing is disabled, we can never sleep. if ( bb->adis.average_samples == 0 ) continue; // // see if the body is idle // #ifndef dNODEBUG // sanity check if ( bb->average_counter >= bb->adis.average_samples ) { dUASSERT( bb->average_counter < bb->adis.average_samples, "buffer overflow" ); // something is going wrong, reset the average-calculations bb->average_ready = 0; // not ready for average calculation bb->average_counter = 0; // reset the buffer index } #endif // dNODEBUG // sample the linear and angular velocity bb->average_lvel_buffer[bb->average_counter][0] = bb->lvel[0]; bb->average_lvel_buffer[bb->average_counter][1] = bb->lvel[1]; bb->average_lvel_buffer[bb->average_counter][2] = bb->lvel[2]; bb->average_avel_buffer[bb->average_counter][0] = bb->avel[0]; bb->average_avel_buffer[bb->average_counter][1] = bb->avel[1]; bb->average_avel_buffer[bb->average_counter][2] = bb->avel[2]; bb->average_counter++; // buffer ready test if ( bb->average_counter >= bb->adis.average_samples ) { bb->average_counter = 0; // fill the buffer from the beginning bb->average_ready = 1; // this body is ready now for average calculation } int idle = 0; // Assume it's in motion unless we have samples to disprove it. // enough samples? if ( bb->average_ready ) { idle = 1; // Initial assumption: IDLE // the sample buffers are filled and ready for calculation dVector3 average_lvel, average_avel; // Store first velocity samples average_lvel[0] = bb->average_lvel_buffer[0][0]; average_avel[0] = bb->average_avel_buffer[0][0]; average_lvel[1] = bb->average_lvel_buffer[0][1]; average_avel[1] = bb->average_avel_buffer[0][1]; average_lvel[2] = bb->average_lvel_buffer[0][2]; average_avel[2] = bb->average_avel_buffer[0][2]; // If we're not in "instantaneous mode" if ( bb->adis.average_samples > 1 ) { // add remaining velocities together for ( unsigned int i = 1; i < bb->adis.average_samples; ++i ) { average_lvel[0] += bb->average_lvel_buffer[i][0]; average_avel[0] += bb->average_avel_buffer[i][0]; average_lvel[1] += bb->average_lvel_buffer[i][1]; average_avel[1] += bb->average_avel_buffer[i][1]; average_lvel[2] += bb->average_lvel_buffer[i][2]; average_avel[2] += bb->average_avel_buffer[i][2]; } // make average dReal r1 = dReal( 1.0 ) / dReal( bb->adis.average_samples ); average_lvel[0] *= r1; average_avel[0] *= r1; average_lvel[1] *= r1; average_avel[1] *= r1; average_lvel[2] *= r1; average_avel[2] *= r1; } // threshold test dReal av_lspeed, av_aspeed; av_lspeed = dCalcVectorDot3( average_lvel, average_lvel ); if ( av_lspeed > bb->adis.linear_average_threshold ) { idle = 0; // average linear velocity is too high for idle } else { av_aspeed = dCalcVectorDot3( average_avel, average_avel ); if ( av_aspeed > bb->adis.angular_average_threshold ) { idle = 0; // average angular velocity is too high for idle } } } // if it's idle, accumulate steps and time. // these counters won't overflow because this code doesn't run for disabled bodies. if (idle) { bb->adis_stepsleft--; bb->adis_timeleft -= stepsize; } else { // Reset countdowns bb->adis_stepsleft = bb->adis.idle_steps; bb->adis_timeleft = bb->adis.idle_time; } // disable the body if it's idle for a long enough time if ( bb->adis_stepsleft <= 0 && bb->adis_timeleft <= 0 ) { bb->flags |= dxBodyDisabled; // set the disable flag // disabling bodies should also include resetting the velocity // should prevent jittering in big "islands" bb->lvel[0] = 0; bb->lvel[1] = 0; bb->lvel[2] = 0; bb->avel[0] = 0; bb->avel[1] = 0; bb->avel[2] = 0; } } } //**************************************************************************** // body rotation // return sin(x)/x. this has a singularity at 0 so special handling is needed // for small arguments. static inline dReal sinc (dReal x) { // if |x| < 1e-4 then use a taylor series expansion. this two term expansion // is actually accurate to one LS bit within this range if double precision // is being used - so don't worry! if (dFabs(x) < 1.0e-4) return REAL(1.0) - x*x*REAL(0.166666666666666666667); else return dSin(x)/x; } // given a body b, apply its linear and angular rotation over the time // interval h, thereby adjusting its position and orientation. void dxStepBody (dxBody *b, dReal h) { // cap the angular velocity if (b->flags & dxBodyMaxAngularSpeed) { const dReal max_ang_speed = b->max_angular_speed; const dReal aspeed = dCalcVectorDot3( b->avel, b->avel ); if (aspeed > max_ang_speed*max_ang_speed) { const dReal coef = max_ang_speed/dSqrt(aspeed); dScaleVector3(b->avel, coef); } } // end of angular velocity cap // handle linear velocity for (unsigned int j=0; j<3; j++) b->posr.pos[j] += h * b->lvel[j]; if (b->flags & dxBodyFlagFiniteRotation) { dVector3 irv; // infitesimal rotation vector dQuaternion q; // quaternion for finite rotation if (b->flags & dxBodyFlagFiniteRotationAxis) { // split the angular velocity vector into a component along the finite // rotation axis, and a component orthogonal to it. dVector3 frv; // finite rotation vector dReal k = dCalcVectorDot3 (b->finite_rot_axis,b->avel); frv[0] = b->finite_rot_axis[0] * k; frv[1] = b->finite_rot_axis[1] * k; frv[2] = b->finite_rot_axis[2] * k; irv[0] = b->avel[0] - frv[0]; irv[1] = b->avel[1] - frv[1]; irv[2] = b->avel[2] - frv[2]; // make a rotation quaternion q that corresponds to frv * h. // compare this with the full-finite-rotation case below. h *= REAL(0.5); dReal theta = k * h; q[0] = dCos(theta); dReal s = sinc(theta) * h; q[1] = frv[0] * s; q[2] = frv[1] * s; q[3] = frv[2] * s; } else { // make a rotation quaternion q that corresponds to w * h dReal wlen = dSqrt (b->avel[0]*b->avel[0] + b->avel[1]*b->avel[1] + b->avel[2]*b->avel[2]); h *= REAL(0.5); dReal theta = wlen * h; q[0] = dCos(theta); dReal s = sinc(theta) * h; q[1] = b->avel[0] * s; q[2] = b->avel[1] * s; q[3] = b->avel[2] * s; } // do the finite rotation dQuaternion q2; dQMultiply0 (q2,q,b->q); for (unsigned int j=0; j<4; j++) b->q[j] = q2[j]; // do the infitesimal rotation if required if (b->flags & dxBodyFlagFiniteRotationAxis) { dReal dq[4]; dWtoDQ (irv,b->q,dq); for (unsigned int j=0; j<4; j++) b->q[j] += h * dq[j]; } } else { // the normal way - do an infitesimal rotation dReal dq[4]; dWtoDQ (b->avel,b->q,dq); for (unsigned int j=0; j<4; j++) b->q[j] += h * dq[j]; } // normalize the quaternion and convert it to a rotation matrix dNormalize4 (b->q); dQtoR (b->q,b->posr.R); // notify all attached geoms that this body has moved dxWorldProcessContext *world_process_context = b->world->unsafeGetWorldProcessingContext(); for (dxGeom *geom = b->geom; geom; geom = dGeomGetBodyNext (geom)) { world_process_context->LockForStepbodySerialization(); dGeomMoved (geom); world_process_context->UnlockForStepbodySerialization(); } // notify the user if (b->moved_callback != NULL) { b->moved_callback(b); } // damping if (b->flags & dxBodyLinearDamping) { const dReal lin_threshold = b->dampingp.linear_threshold; const dReal lin_speed = dCalcVectorDot3( b->lvel, b->lvel ); if ( lin_speed > lin_threshold) { const dReal k = 1 - b->dampingp.linear_scale; dScaleVector3(b->lvel, k); } } if (b->flags & dxBodyAngularDamping) { const dReal ang_threshold = b->dampingp.angular_threshold; const dReal ang_speed = dCalcVectorDot3( b->avel, b->avel ); if ( ang_speed > ang_threshold) { const dReal k = 1 - b->dampingp.angular_scale; dScaleVector3(b->avel, k); } } } //**************************************************************************** // island processing enum dxISLANDSIZESELEMENT { dxISE_BODIES_COUNT, dxISE_JOINTS_COUNT, dxISE__MAX }; // This estimates dynamic memory requirements for dxProcessIslands static sizeint EstimateIslandProcessingMemoryRequirements(dxWorld *world) { sizeint res = 0; sizeint islandcounts = dEFFICIENT_SIZE((sizeint)(unsigned)world->nb * 2 * sizeof(int)); res += islandcounts; sizeint bodiessize = dEFFICIENT_SIZE((sizeint)(unsigned)world->nb * sizeof(dxBody*)); sizeint jointssize = dEFFICIENT_SIZE((sizeint)(unsigned)world->nj * sizeof(dxJoint*)); res += bodiessize + jointssize; sizeint sesize = (bodiessize < jointssize) ? bodiessize : jointssize; res += sesize; return res; } static sizeint BuildIslandsAndEstimateStepperMemoryRequirements( dxWorldProcessIslandsInfo &islandsinfo, dxWorldProcessMemArena *memarena, dxWorld *world, dReal stepsize, dmemestimate_fn_t stepperestimate) { sizeint maxreq = 0; // handle auto-disabling of bodies dInternalHandleAutoDisabling (world,stepsize); unsigned int nb = world->nb, nj = world->nj; // Make array for island body/joint counts unsigned int *islandsizes = memarena->AllocateArray(2 * (sizeint)nb); unsigned int *sizescurr; // make arrays for body and joint lists (for a single island) to go into dxBody **body = memarena->AllocateArray(nb); dxJoint **joint = memarena->AllocateArray(nj); BEGIN_STATE_SAVE(memarena, stackstate) { // allocate a stack of unvisited bodies in the island. the maximum size of // the stack can be the lesser of the number of bodies or joints, because // new bodies are only ever added to the stack by going through untagged // joints. all the bodies in the stack must be tagged! unsigned int stackalloc = (nj < nb) ? nj : nb; dxBody **stack = memarena->AllocateArray(stackalloc); { // set all body/joint tags to 0 for (dxBody *b=world->firstbody; b; b=(dxBody*)b->next) b->tag = 0; for (dxJoint *j=world->firstjoint; j; j=(dxJoint*)j->next) j->tag = 0; } sizescurr = islandsizes; dxBody **bodystart = body; dxJoint **jointstart = joint; for (dxBody *bb=world->firstbody; bb; bb=(dxBody*)bb->next) { // get bb = the next enabled, untagged body, and tag it if (!bb->tag) { if (!(bb->flags & dxBodyDisabled)) { bb->tag = 1; dxBody **bodycurr = bodystart; dxJoint **jointcurr = jointstart; // tag all bodies and joints starting from bb. *bodycurr++ = bb; unsigned int stacksize = 0; dxBody *b = bb; while (true) { // traverse and tag all body's joints, add untagged connected bodies // to stack for (dxJointNode *n=b->firstjoint; n; n=n->next) { dxJoint *njoint = n->joint; if (!njoint->tag) { if (njoint->isEnabled()) { njoint->tag = 1; *jointcurr++ = njoint; dxBody *nbody = n->body; // Body disabled flag is not checked here. This is how auto-enable works. if (nbody && nbody->tag <= 0) { nbody->tag = 1; // Make sure all bodies are in the enabled state. nbody->flags &= ~dxBodyDisabled; stack[stacksize++] = nbody; } } else { njoint->tag = -1; // Used in Step to prevent search over disabled joints (not needed for QuickStep so far) } } } dIASSERT(stacksize <= (unsigned int)world->nb); dIASSERT(stacksize <= (unsigned int)world->nj); if (stacksize == 0) { break; } b = stack[--stacksize]; // pop body off stack *bodycurr++ = b; // put body on body list } unsigned int bcount = (unsigned int)(bodycurr - bodystart); unsigned int jcount = (unsigned int)(jointcurr - jointstart); dIASSERT((sizeint)(bodycurr - bodystart) <= (sizeint)UINT_MAX); dIASSERT((sizeint)(jointcurr - jointstart) <= (sizeint)UINT_MAX); sizescurr[dxISE_BODIES_COUNT] = bcount; sizescurr[dxISE_JOINTS_COUNT] = jcount; sizescurr += dxISE__MAX; sizeint islandreq = stepperestimate(bodystart, bcount, jointstart, jcount); maxreq = (maxreq > islandreq) ? maxreq : islandreq; bodystart = bodycurr; jointstart = jointcurr; } else { bb->tag = -1; // Not used so far (assigned to retain consistency with joints) } } } } END_STATE_SAVE(memarena, stackstate); # ifndef dNODEBUG // if debugging, check that all objects (except for disabled bodies, // unconnected joints, and joints that are connected to disabled bodies) // were tagged. { for (dxBody *b=world->firstbody; b; b=(dxBody*)b->next) { if (b->flags & dxBodyDisabled) { if (b->tag > 0) dDebug (0,"disabled body tagged"); } else { if (b->tag <= 0) dDebug (0,"enabled body not tagged"); } } for (dxJoint *j=world->firstjoint; j; j=(dxJoint*)j->next) { if ( (( j->node[0].body && (j->node[0].body->flags & dxBodyDisabled)==0 ) || (j->node[1].body && (j->node[1].body->flags & dxBodyDisabled)==0) ) && j->isEnabled() ) { if (j->tag <= 0) dDebug (0,"attached enabled joint not tagged"); } else { if (j->tag > 0) dDebug (0,"unattached or disabled joint tagged"); } } } # endif sizeint islandcount = ((sizeint)(sizescurr - islandsizes) / dxISE__MAX); islandsinfo.AssignInfo(islandcount, islandsizes, body, joint); return maxreq; } static unsigned EstimateIslandProcessingSimultaneousCallsMaximumCount(unsigned activeThreadCount, unsigned islandsAllowedThreadCount, unsigned stepperAllowedThreadCount, dmaxcallcountestimate_fn_t maxCallCountEstimator) { unsigned stepperCallsMaximum = maxCallCountEstimator(activeThreadCount, stepperAllowedThreadCount); unsigned islandsIntermediateCallsMaximum = (1 + 2); // ThreadedProcessIslandSearch_Callback + (ThreadedProcessIslandStepper_Callback && ThreadedProcessIslandSearch_Callback) unsigned result = 1 // ThreadedProcessGroup_Callback + islandsAllowedThreadCount * dMAX(stepperCallsMaximum, islandsIntermediateCallsMaximum) + dMIN(islandsAllowedThreadCount, (unsigned)(activeThreadCount - islandsAllowedThreadCount)) // ThreadedProcessJobStart_Callback /*...the end*/; return result; } // this groups all joints and bodies in a world into islands. all objects // in an island are reachable by going through connected bodies and joints. // each island can be simulated separately. // note that joints that are not attached to anything will not be included // in any island, an so they do not affect the simulation. // // this function starts new island from unvisited bodies. however, it will // never start a new islands from a disabled body. thus islands of disabled // bodies will not be included in the simulation. disabled bodies are // re-enabled if they are found to be part of an active island. bool dxProcessIslands (dxWorld *world, const dxWorldProcessIslandsInfo &islandsInfo, dReal stepSize, dstepper_fn_t stepper, dmaxcallcountestimate_fn_t maxCallCountEstimator) { bool result = false; dxIslandsProcessingCallContext callContext(world, islandsInfo, stepSize, stepper); do { dxStepWorkingMemory *wmem = world->wmem; dIASSERT(wmem != NULL); dxWorldProcessContext *context = wmem->GetWorldProcessingContext(); dIASSERT(context != NULL); dCallWaitID pcwGroupCallWait = context->GetIslandsSteppingWait(); int summaryFault = 0; unsigned activeThreadCount; const unsigned islandsAllowedThreadCount = world->calculateIslandProcessingMaxThreadCount(&activeThreadCount); dIASSERT(islandsAllowedThreadCount != 0); dIASSERT(activeThreadCount >= islandsAllowedThreadCount); unsigned stepperAllowedThreadCount = islandsAllowedThreadCount; // For now, set stepper allowed threads equal to island stepping threads unsigned simultaneousCallsCount = EstimateIslandProcessingSimultaneousCallsMaximumCount(activeThreadCount, islandsAllowedThreadCount, stepperAllowedThreadCount, maxCallCountEstimator); if (!world->PreallocateResourcesForThreadedCalls(simultaneousCallsCount)) { break; } dCallReleaseeID groupReleasee; // First post a group call with dependency count set to number of expected threads world->PostThreadedCall(&summaryFault, &groupReleasee, islandsAllowedThreadCount, NULL, pcwGroupCallWait, &dxIslandsProcessingCallContext::ThreadedProcessGroup_Callback, (void *)&callContext, 0, "World Islands Stepping Group"); callContext.AssignGroupReleasee(groupReleasee); callContext.SetStepperAllowedThreads(stepperAllowedThreadCount); // Summary fault flag may be omitted as any failures will automatically propagate to dependent releasee (i.e. to groupReleasee) world->PostThreadedCallsGroup(NULL, islandsAllowedThreadCount, groupReleasee, &dxIslandsProcessingCallContext::ThreadedProcessJobStart_Callback, (void *)&callContext, "World Islands Stepping Start"); // Wait until group completes (since jobs were the dependencies of the group the group is going to complete only after all the jobs end) world->WaitThreadedCallExclusively(NULL, pcwGroupCallWait, NULL, "World Islands Stepping Wait"); if (summaryFault != 0) { break; } result = true; } while (false); return result; } int dxIslandsProcessingCallContext::ThreadedProcessGroup_Callback(void *callContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused (void)callThisReleasee; // unused return static_cast(callContext)->ThreadedProcessGroup(); } bool dxIslandsProcessingCallContext::ThreadedProcessGroup() { // Do nothing - it's just a wrapper call return true; } int dxIslandsProcessingCallContext::ThreadedProcessJobStart_Callback(void *callContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused (void)callThisReleasee; // unused static_cast(callContext)->ThreadedProcessJobStart(); return true; } void dxIslandsProcessingCallContext::ThreadedProcessJobStart() { dxWorldProcessContext *context = m_world->unsafeGetWorldProcessingContext(); dxWorldProcessMemArena *stepperArena = context->ObtainStepperMemArena(); dIASSERT(stepperArena != NULL && stepperArena->IsStructureValid()); const dxWorldProcessIslandsInfo &islandsInfo = m_islandsInfo; dxBody *const *islandBodiesStart = islandsInfo.GetBodiesArray(); dxJoint *const *islandJointsStart = islandsInfo.GetJointsArray(); dxSingleIslandCallContext *stepperCallContext = (dxSingleIslandCallContext *)stepperArena->AllocateBlock(sizeof(dxSingleIslandCallContext)); // Save area state after context allocation to be restored for the stepper void *arenaState = stepperArena->SaveState(); new(stepperCallContext) dxSingleIslandCallContext(this, stepperArena, arenaState, islandBodiesStart, islandJointsStart); // Summary fault flag may be omitted as any failures will automatically propagate to dependent releasee (i.e. to m_groupReleasee) m_world->PostThreadedCallForUnawareReleasee(NULL, NULL, 0, m_groupReleasee, NULL, &dxIslandsProcessingCallContext::ThreadedProcessIslandSearch_Callback, (void *)stepperCallContext, 0, "World Islands Stepping Selection"); } int dxIslandsProcessingCallContext::ThreadedProcessIslandSearch_Callback(void *callContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused (void)callThisReleasee; // unused dxSingleIslandCallContext *stepperCallContext = static_cast(callContext); stepperCallContext->m_islandsProcessingContext->ThreadedProcessIslandSearch(stepperCallContext); return true; } void dxIslandsProcessingCallContext::ThreadedProcessIslandSearch(dxSingleIslandCallContext *stepperCallContext) { bool finalizeJob = false; const dxWorldProcessIslandsInfo &islandsInfo = m_islandsInfo; unsigned int const *islandSizes = islandsInfo.GetIslandSizes(); const sizeint islandsCount = islandsInfo.GetIslandsCount(); sizeint islandToProcess = ObtainNextIslandToBeProcessed(islandsCount); if (islandToProcess != islandsCount) { // First time, the counts are zeros and on next passes, adding counts will skip island that has just been processed by stepper dxBody *const *islandBodiesStart = stepperCallContext->GetSelectedIslandBodiesEnd(); dxJoint *const *islandJointsStart = stepperCallContext->GetSelectedIslandJointsEnd(); sizeint islandIndex = stepperCallContext->m_islandIndex; for (; ; ++islandIndex) { unsigned int bcount = islandSizes[islandIndex * dxISE__MAX + dxISE_BODIES_COUNT]; unsigned int jcount = islandSizes[islandIndex * dxISE__MAX + dxISE_JOINTS_COUNT]; if (islandIndex == islandToProcess) { // Store selected island details stepperCallContext->AssignIslandSelection(islandBodiesStart, islandJointsStart, bcount, jcount); // Store next island index to continue search from ++islandIndex; stepperCallContext->AssignIslandSearchProgress(islandIndex); // Restore saved stepper memory arena position stepperCallContext->RestoreSavedMemArenaStateForStepper(); dCallReleaseeID nextSearchReleasee; // Summary fault flag may be omitted as any failures will automatically propagate to dependent releasee (i.e. to m_groupReleasee) m_world->PostThreadedCallForUnawareReleasee(NULL, &nextSearchReleasee, 1, m_groupReleasee, NULL, &dxIslandsProcessingCallContext::ThreadedProcessIslandSearch_Callback, (void *)stepperCallContext, 0, "World Islands Stepping Selection"); stepperCallContext->AssignStepperCallFinalReleasee(nextSearchReleasee); m_world->PostThreadedCall(NULL, NULL, 0, nextSearchReleasee, NULL, &dxIslandsProcessingCallContext::ThreadedProcessIslandStepper_Callback, (void *)stepperCallContext, 0, "Island Stepping Job Start"); break; } islandBodiesStart += bcount; islandJointsStart += jcount; } } else { finalizeJob = true; } if (finalizeJob) { dxWorldProcessMemArena *stepperArena = stepperCallContext->m_stepperArena; stepperCallContext->dxSingleIslandCallContext::~dxSingleIslandCallContext(); dxWorldProcessContext *context = m_world->unsafeGetWorldProcessingContext(); context->ReturnStepperMemArena(stepperArena); } } int dxIslandsProcessingCallContext::ThreadedProcessIslandStepper_Callback(void *callContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused (void)callThisReleasee; // unused dxSingleIslandCallContext *stepperCallContext = static_cast(callContext); stepperCallContext->m_islandsProcessingContext->ThreadedProcessIslandStepper(stepperCallContext); return true; } void dxIslandsProcessingCallContext::ThreadedProcessIslandStepper(dxSingleIslandCallContext *stepperCallContext) { m_stepper(&stepperCallContext->m_stepperCallContext); } sizeint dxIslandsProcessingCallContext::ObtainNextIslandToBeProcessed(sizeint islandsCount) { return ThrsafeIncrementSizeUpToLimit(&m_islandToProcessStorage, islandsCount); } //**************************************************************************** // World processing context management dxWorldProcessMemArena *dxWorldProcessMemArena::ReallocateMemArena ( dxWorldProcessMemArena *oldarena, sizeint memreq, const dxWorldProcessMemoryManager *memmgr, float rsrvfactor, unsigned rsrvminimum) { dxWorldProcessMemArena *arena = oldarena; bool allocsuccess = false; sizeint nOldArenaSize; void *pOldArenaBuffer; do { sizeint oldmemsize = oldarena ? oldarena->GetMemorySize() : 0; if (oldarena == NULL || oldmemsize < memreq) { nOldArenaSize = oldarena ? dxWorldProcessMemArena::MakeArenaSize(oldmemsize) : 0; pOldArenaBuffer = oldarena ? oldarena->m_pArenaBegin : NULL; if (!dxWorldProcessMemArena::IsArenaPossible(memreq)) { break; } sizeint arenareq = dxWorldProcessMemArena::MakeArenaSize(memreq); sizeint arenareq_with_reserve = AdjustArenaSizeForReserveRequirements(arenareq, rsrvfactor, rsrvminimum); sizeint memreq_with_reserve = memreq + (arenareq_with_reserve - arenareq); if (oldarena != NULL) { oldarena->m_pArenaMemMgr->m_fnFree(pOldArenaBuffer, nOldArenaSize); oldarena = NULL; // Zero variables to avoid another freeing on exit pOldArenaBuffer = NULL; nOldArenaSize = 0; } // Allocate new arena void *pNewArenaBuffer = memmgr->m_fnAlloc(arenareq_with_reserve); if (pNewArenaBuffer == NULL) { break; } arena = (dxWorldProcessMemArena *)dEFFICIENT_PTR(pNewArenaBuffer); void *blockbegin = dEFFICIENT_PTR(arena + 1); void *blockend = dOFFSET_EFFICIENTLY(blockbegin, memreq_with_reserve); arena->m_pAllocBegin = blockbegin; arena->m_pAllocEnd = blockend; arena->m_pArenaBegin = pNewArenaBuffer; arena->m_pAllocCurrentOrNextArena = NULL; arena->m_pArenaMemMgr = memmgr; } allocsuccess = true; } while (false); if (!allocsuccess) { if (pOldArenaBuffer != NULL) { dIASSERT(oldarena != NULL); oldarena->m_pArenaMemMgr->m_fnFree(pOldArenaBuffer, nOldArenaSize); } arena = NULL; } return arena; } void dxWorldProcessMemArena::FreeMemArena (dxWorldProcessMemArena *arena) { sizeint memsize = arena->GetMemorySize(); sizeint arenasize = dxWorldProcessMemArena::MakeArenaSize(memsize); void *pArenaBegin = arena->m_pArenaBegin; arena->m_pArenaMemMgr->m_fnFree(pArenaBegin, arenasize); } sizeint dxWorldProcessMemArena::AdjustArenaSizeForReserveRequirements(sizeint arenareq, float rsrvfactor, unsigned rsrvminimum) { float scaledarena = arenareq * rsrvfactor; sizeint adjustedarena = (scaledarena < SIZE_MAX) ? (sizeint)scaledarena : SIZE_MAX; sizeint boundedarena = (adjustedarena > rsrvminimum) ? adjustedarena : (sizeint)rsrvminimum; return dEFFICIENT_SIZE(boundedarena); } bool dxReallocateWorldProcessContext (dxWorld *world, dxWorldProcessIslandsInfo &islandsInfo, dReal stepSize, dmemestimate_fn_t stepperEstimate) { bool result = false; do { dxStepWorkingMemory *wmem = AllocateOnDemand(world->wmem); if (wmem == NULL) { break; } dxWorldProcessContext *context = wmem->SureGetWorldProcessingContext(); if (context == NULL) { break; } if (!context->EnsureStepperSyncObjectsAreAllocated(world)) { break; } const dxWorldProcessMemoryReserveInfo *reserveInfo = wmem->SureGetMemoryReserveInfo(); const dxWorldProcessMemoryManager *memmgr = wmem->SureGetMemoryManager(); sizeint islandsReq = EstimateIslandProcessingMemoryRequirements(world); dIASSERT(islandsReq == dEFFICIENT_SIZE(islandsReq)); dxWorldProcessMemArena *islandsArena = context->ReallocateIslandsMemArena(islandsReq, memmgr, 1.0f, reserveInfo->m_uiReserveMinimum); if (islandsArena == NULL) { break; } dIASSERT(islandsArena->IsStructureValid()); sizeint stepperReq = BuildIslandsAndEstimateStepperMemoryRequirements(islandsInfo, islandsArena, world, stepSize, stepperEstimate); dIASSERT(stepperReq == dEFFICIENT_SIZE(stepperReq)); sizeint stepperReqWithCallContext = stepperReq + dEFFICIENT_SIZE(sizeof(dxSingleIslandCallContext)); unsigned islandThreadsCount = world->calculateIslandProcessingMaxThreadCount(); if (!context->ReallocateStepperMemArenas(world, islandThreadsCount, stepperReqWithCallContext, memmgr, reserveInfo->m_fReserveFactor, reserveInfo->m_uiReserveMinimum)) { break; } result = true; } while (false); return result; } dxWorldProcessMemArena *dxAllocateTemporaryWorldProcessMemArena( sizeint memreq, const dxWorldProcessMemoryManager *memmgr/*=NULL*/, const dxWorldProcessMemoryReserveInfo *reserveinfo/*=NULL*/) { const dxWorldProcessMemoryManager *surememmgr = memmgr ? memmgr : &g_WorldProcessMallocMemoryManager; const dxWorldProcessMemoryReserveInfo *surereserveinfo = reserveinfo ? reserveinfo : &g_WorldProcessDefaultReserveInfo; dxWorldProcessMemArena *arena = dxWorldProcessMemArena::ReallocateMemArena(NULL, memreq, surememmgr, surereserveinfo->m_fReserveFactor, surereserveinfo->m_uiReserveMinimum); return arena; } void dxFreeTemporaryWorldProcessMemArena(dxWorldProcessMemArena *arena) { dxWorldProcessMemArena::FreeMemArena(arena); } ode-0.16/ode/src/collision_libccd.h0000664000175200017520000000506113403272463014146 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _LIBCCD_COLLISION_H_ #define _LIBCCD_COLLISION_H_ int dCollideCylinderCylinder(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); int dCollideBoxCylinderCCD(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); int dCollideCapsuleCylinder(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); int dCollideConvexBoxCCD(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); int dCollideConvexCapsuleCCD(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); int dCollideConvexCylinderCCD(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); int dCollideConvexSphereCCD(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); int dCollideConvexConvexCCD(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); unsigned dCollideConvexTrimeshTrianglesCCD(dxGeom *o1, dxGeom *o2, const int *indices, unsigned numIndices, int flags, dContactGeom *contacts, int skip); #endif /* _LIBCCD_COLLISION_H_ */ ode-0.16/ode/src/Makefile.am0000664000175200017520000001561113403272463012540 00000000000000SUBDIRS = joints AM_CPPFLAGS = -I$(top_srcdir)/include \ -I$(top_builddir)/include \ -D__ODE__ lib_LTLIBRARIES = libode.la libode_la_LDFLAGS = @EXTRA_LIBTOOL_LDFLAGS@ @ODE_VERSION_INFO@ libode_la_LIBADD = joints/libjoints.la # please, let's keep the filenames sorted libode_la_SOURCES = nextafterf.c \ array.cpp array.h \ box.cpp \ capsule.cpp \ collision_cylinder_box.cpp \ collision_cylinder_plane.cpp \ collision_cylinder_sphere.cpp \ collision_kernel.cpp collision_kernel.h \ collision_quadtreespace.cpp \ collision_sapspace.cpp \ collision_space.cpp \ collision_space_internal.h \ collision_std.h \ collision_transform.cpp collision_transform.h \ collision_trimesh_colliders.h \ collision_trimesh_disabled.cpp \ collision_trimesh_internal.h \ collision_trimesh_opcode.h \ collision_trimesh_gimpact.h \ collision_util.cpp collision_util.h \ common.h \ convex.cpp \ coop_matrix_types.h \ cylinder.cpp \ default_threading.cpp default_threading.h \ error.cpp error.h \ export-dif.cpp \ fastdot.cpp fastdot_impl.h \ fastldltfactor.cpp fastldltfactor_impl.h \ fastldltsolve.cpp fastldltsolve_impl.h \ fastlsolve.cpp fastlsolve_impl.h \ fastltsolve.cpp fastltsolve_impl.h \ fastvecscale.cpp fastvecscale_impl.h \ heightfield.cpp heightfield.h \ lcp.cpp lcp.h \ mass.cpp \ mat.cpp mat.h \ matrix.cpp matrix.h \ memory.cpp \ misc.cpp \ objects.cpp objects.h \ obstack.cpp obstack.h \ ode.cpp \ odeinit.cpp \ odemath.cpp odemath.h \ odeou.h \ odetls.h \ plane.cpp \ quickstep.cpp quickstep.h \ ray.cpp \ resource_control.cpp resource_control.h \ rotation.cpp \ simple_cooperative.cpp simple_cooperative.h \ sphere.cpp \ step.cpp step.h \ timer.cpp \ threaded_solver_ldlt.h \ threading_atomics_provs.h \ threading_base.cpp threading_base.h \ threading_fake_sync.h \ threading_impl.cpp threading_impl.h \ threading_impl_posix.h \ threading_impl_templates.h \ threading_impl_win.h \ threading_pool_posix.cpp \ threading_pool_win.cpp \ threadingutils.h \ typedefs.h \ util.cpp util.h ################################### # O U S T U F F ################################### if ENABLE_OU AM_CPPFLAGS += -I$(top_srcdir)/ou/include libode_la_LIBADD += $(top_builddir)/ou/src/ou/libou.la libode_la_SOURCES += odetls.cpp odetls.h \ odeou.cpp odeou.h endif ################################### # G I M P A C T S T U F F ################################### if GIMPACT AM_CPPFLAGS += -DdTRIMESH_ENABLED -DdTRIMESH_GIMPACT -I$(top_srcdir)/GIMPACT/include libode_la_LIBADD += $(top_builddir)/GIMPACT/src/libGIMPACT.la libode_la_SOURCES += collision_trimesh_gimpact.cpp \ collision_trimesh_internal.cpp collision_trimesh_internal_impl.h \ gimpact_contact_export_helper.cpp gimpact_contact_export_helper.h \ gimpact_gim_contact_accessor.h \ gimpact_plane_contact_accessor.h \ collision_trimesh_trimesh.cpp \ collision_trimesh_sphere.cpp \ collision_trimesh_ray.cpp \ collision_trimesh_box.cpp \ collision_trimesh_ccylinder.cpp \ collision_trimesh_internal.h \ collision_cylinder_trimesh.cpp \ collision_trimesh_plane.cpp \ collision_convex_trimesh.cpp endif ################################# # O P C O D E S T U F F ################################# if OPCODE AM_CPPFLAGS += -I$(top_srcdir)/OPCODE -I$(top_srcdir)/OPCODE/Ice -DdTRIMESH_ENABLED -DdTRIMESH_OPCODE libode_la_LIBADD += $(top_builddir)/OPCODE/libOPCODE.la \ $(top_builddir)/OPCODE/Ice/libIce.la libode_la_SOURCES+= collision_trimesh_opcode.cpp \ collision_trimesh_internal.cpp collision_trimesh_internal_impl.h \ collision_trimesh_trimesh.cpp \ collision_trimesh_trimesh_old.cpp \ collision_trimesh_sphere.cpp \ collision_trimesh_ray.cpp \ collision_trimesh_box.cpp \ collision_trimesh_ccylinder.cpp \ collision_trimesh_internal.h \ collision_cylinder_trimesh.cpp \ collision_trimesh_plane.cpp \ collision_convex_trimesh.cpp endif if LIBCCD AM_CPPFLAGS += -DdLIBCCD_ENABLED AM_CPPFLAGS += -I$(top_srcdir)/libccd/src/custom if LIBCCD_INTERNAL AM_CPPFLAGS += -I$(top_srcdir)/libccd/src -I$(top_builddir)/libccd/src libode_la_LIBADD += $(top_builddir)/libccd/src/libccd.la AM_CPPFLAGS += -DdLIBCCD_INTERNAL else AM_CPPFLAGS += $(CCD_CFLAGS) libode_la_LIBADD += $(CCD_LIBS) AM_CPPFLAGS += -DdLIBCCD_SYSTEM endif libode_la_SOURCES += collision_libccd.cpp collision_libccd.h if LIBCCD_BOX_CYL AM_CPPFLAGS += -DdLIBCCD_BOX_CYL endif if LIBCCD_CYL_CYL AM_CPPFLAGS += -DdLIBCCD_CYL_CYL endif if LIBCCD_CAP_CYL AM_CPPFLAGS += -DdLIBCCD_CAP_CYL endif if LIBCCD_CONVEX_BOX AM_CPPFLAGS += -DdLIBCCD_CONVEX_BOX endif if LIBCCD_CONVEX_CAP AM_CPPFLAGS += -DdLIBCCD_CONVEX_CAP endif if LIBCCD_CONVEX_CYL AM_CPPFLAGS += -DdLIBCCD_CONVEX_CYL endif if LIBCCD_CONVEX_SPHERE AM_CPPFLAGS += -DdLIBCCD_CONVEX_SPHERE endif if LIBCCD_CONVEX_CONVEX AM_CPPFLAGS += -DdLIBCCD_CONVEX_CONVEX endif endif ode-0.16/ode/src/rotation.cpp0000664000175200017520000002167513403272463013056 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* quaternions have the format: (s,vx,vy,vz) where (vx,vy,vz) is the "rotation axis" and s is the "rotation angle". */ #include #include "config.h" #include "odemath.h" #define _R(i,j) R[(i)*4+(j)] #define SET_3x3_IDENTITY \ _R(0,0) = REAL(1.0); \ _R(0,1) = REAL(0.0); \ _R(0,2) = REAL(0.0); \ _R(0,3) = REAL(0.0); \ _R(1,0) = REAL(0.0); \ _R(1,1) = REAL(1.0); \ _R(1,2) = REAL(0.0); \ _R(1,3) = REAL(0.0); \ _R(2,0) = REAL(0.0); \ _R(2,1) = REAL(0.0); \ _R(2,2) = REAL(1.0); \ _R(2,3) = REAL(0.0); void dRSetIdentity (dMatrix3 R) { dAASSERT (R); SET_3x3_IDENTITY; } void dRFromAxisAndAngle (dMatrix3 R, dReal ax, dReal ay, dReal az, dReal angle) { dAASSERT (R); dQuaternion q; dQFromAxisAndAngle (q,ax,ay,az,angle); dQtoR (q,R); } void dRFromEulerAngles (dMatrix3 R, dReal phi, dReal theta, dReal psi) { dReal sphi,cphi,stheta,ctheta,spsi,cpsi; dAASSERT (R); sphi = dSin(phi); cphi = dCos(phi); stheta = dSin(theta); ctheta = dCos(theta); spsi = dSin(psi); cpsi = dCos(psi); _R(0,0) = cpsi*ctheta; _R(0,1) = spsi*ctheta; _R(0,2) =-stheta; _R(0,3) = REAL(0.0); _R(1,0) = cpsi*stheta*sphi - spsi*cphi; _R(1,1) = spsi*stheta*sphi + cpsi*cphi; _R(1,2) = ctheta*sphi; _R(1,3) = REAL(0.0); _R(2,0) = cpsi*stheta*cphi + spsi*sphi; _R(2,1) = spsi*stheta*cphi - cpsi*sphi; _R(2,2) = ctheta*cphi; _R(2,3) = REAL(0.0); } void dRFrom2Axes (dMatrix3 R, dReal ax, dReal ay, dReal az, dReal bx, dReal by, dReal bz) { dReal l,k; dAASSERT (R); l = dSqrt (ax*ax + ay*ay + az*az); if (l <= REAL(0.0)) { dDEBUGMSG ("zero length vector"); return; } l = dRecip(l); ax *= l; ay *= l; az *= l; k = ax*bx + ay*by + az*bz; bx -= k*ax; by -= k*ay; bz -= k*az; l = dSqrt (bx*bx + by*by + bz*bz); if (l <= REAL(0.0)) { dDEBUGMSG ("zero length vector"); return; } l = dRecip(l); bx *= l; by *= l; bz *= l; _R(0,0) = ax; _R(1,0) = ay; _R(2,0) = az; _R(0,1) = bx; _R(1,1) = by; _R(2,1) = bz; _R(0,2) = - by*az + ay*bz; _R(1,2) = - bz*ax + az*bx; _R(2,2) = - bx*ay + ax*by; _R(0,3) = REAL(0.0); _R(1,3) = REAL(0.0); _R(2,3) = REAL(0.0); } void dRFromZAxis (dMatrix3 R, dReal ax, dReal ay, dReal az) { dVector3 n,p,q; n[0] = ax; n[1] = ay; n[2] = az; dNormalize3 (n); dPlaneSpace (n,p,q); _R(0,0) = p[0]; _R(1,0) = p[1]; _R(2,0) = p[2]; _R(0,1) = q[0]; _R(1,1) = q[1]; _R(2,1) = q[2]; _R(0,2) = n[0]; _R(1,2) = n[1]; _R(2,2) = n[2]; _R(0,3) = REAL(0.0); _R(1,3) = REAL(0.0); _R(2,3) = REAL(0.0); } void dQSetIdentity (dQuaternion q) { dAASSERT (q); q[0] = 1; q[1] = 0; q[2] = 0; q[3] = 0; } void dQFromAxisAndAngle (dQuaternion q, dReal ax, dReal ay, dReal az, dReal angle) { dAASSERT (q); dReal l = ax*ax + ay*ay + az*az; if (l > REAL(0.0)) { angle *= REAL(0.5); q[0] = dCos (angle); l = dSin(angle) * dRecipSqrt(l); q[1] = ax*l; q[2] = ay*l; q[3] = az*l; } else { q[0] = 1; q[1] = 0; q[2] = 0; q[3] = 0; } } void dQMultiply0 (dQuaternion qa, const dQuaternion qb, const dQuaternion qc) { dAASSERT (qa && qb && qc); qa[0] = qb[0]*qc[0] - qb[1]*qc[1] - qb[2]*qc[2] - qb[3]*qc[3]; qa[1] = qb[0]*qc[1] + qb[1]*qc[0] + qb[2]*qc[3] - qb[3]*qc[2]; qa[2] = qb[0]*qc[2] + qb[2]*qc[0] + qb[3]*qc[1] - qb[1]*qc[3]; qa[3] = qb[0]*qc[3] + qb[3]*qc[0] + qb[1]*qc[2] - qb[2]*qc[1]; } void dQMultiply1 (dQuaternion qa, const dQuaternion qb, const dQuaternion qc) { dAASSERT (qa && qb && qc); qa[0] = qb[0]*qc[0] + qb[1]*qc[1] + qb[2]*qc[2] + qb[3]*qc[3]; qa[1] = qb[0]*qc[1] - qb[1]*qc[0] - qb[2]*qc[3] + qb[3]*qc[2]; qa[2] = qb[0]*qc[2] - qb[2]*qc[0] - qb[3]*qc[1] + qb[1]*qc[3]; qa[3] = qb[0]*qc[3] - qb[3]*qc[0] - qb[1]*qc[2] + qb[2]*qc[1]; } void dQMultiply2 (dQuaternion qa, const dQuaternion qb, const dQuaternion qc) { dAASSERT (qa && qb && qc); qa[0] = qb[0]*qc[0] + qb[1]*qc[1] + qb[2]*qc[2] + qb[3]*qc[3]; qa[1] = -qb[0]*qc[1] + qb[1]*qc[0] - qb[2]*qc[3] + qb[3]*qc[2]; qa[2] = -qb[0]*qc[2] + qb[2]*qc[0] - qb[3]*qc[1] + qb[1]*qc[3]; qa[3] = -qb[0]*qc[3] + qb[3]*qc[0] - qb[1]*qc[2] + qb[2]*qc[1]; } void dQMultiply3 (dQuaternion qa, const dQuaternion qb, const dQuaternion qc) { dAASSERT (qa && qb && qc); qa[0] = qb[0]*qc[0] - qb[1]*qc[1] - qb[2]*qc[2] - qb[3]*qc[3]; qa[1] = -qb[0]*qc[1] - qb[1]*qc[0] + qb[2]*qc[3] - qb[3]*qc[2]; qa[2] = -qb[0]*qc[2] - qb[2]*qc[0] + qb[3]*qc[1] - qb[1]*qc[3]; qa[3] = -qb[0]*qc[3] - qb[3]*qc[0] + qb[1]*qc[2] - qb[2]*qc[1]; } // dRfromQ(), dQfromR() and dDQfromW() are derived from equations in "An Introduction // to Physically Based Modeling: Rigid Body Simulation - 1: Unconstrained // Rigid Body Dynamics" by David Baraff, Robotics Institute, Carnegie Mellon // University, 1997. void dRfromQ (dMatrix3 R, const dQuaternion q) { dAASSERT (q && R); // q = (s,vx,vy,vz) dReal qq1 = 2*q[1]*q[1]; dReal qq2 = 2*q[2]*q[2]; dReal qq3 = 2*q[3]*q[3]; _R(0,0) = 1 - qq2 - qq3; _R(0,1) = 2*(q[1]*q[2] - q[0]*q[3]); _R(0,2) = 2*(q[1]*q[3] + q[0]*q[2]); _R(0,3) = REAL(0.0); _R(1,0) = 2*(q[1]*q[2] + q[0]*q[3]); _R(1,1) = 1 - qq1 - qq3; _R(1,2) = 2*(q[2]*q[3] - q[0]*q[1]); _R(1,3) = REAL(0.0); _R(2,0) = 2*(q[1]*q[3] - q[0]*q[2]); _R(2,1) = 2*(q[2]*q[3] + q[0]*q[1]); _R(2,2) = 1 - qq1 - qq2; _R(2,3) = REAL(0.0); } void dQfromR (dQuaternion q, const dMatrix3 R) { dAASSERT (q && R); dReal tr,s; tr = _R(0,0) + _R(1,1) + _R(2,2); if (tr >= 0) { s = dSqrt (tr + 1); q[0] = REAL(0.5) * s; s = REAL(0.5) * dRecip(s); q[1] = (_R(2,1) - _R(1,2)) * s; q[2] = (_R(0,2) - _R(2,0)) * s; q[3] = (_R(1,0) - _R(0,1)) * s; } else { // find the largest diagonal element and jump to the appropriate case if (_R(1,1) > _R(0,0)) { if (_R(2,2) > _R(1,1)) goto case_2; goto case_1; } if (_R(2,2) > _R(0,0)) goto case_2; goto case_0; case_0: s = dSqrt((_R(0,0) - (_R(1,1) + _R(2,2))) + 1); q[1] = REAL(0.5) * s; s = REAL(0.5) * dRecip(s); q[2] = (_R(0,1) + _R(1,0)) * s; q[3] = (_R(2,0) + _R(0,2)) * s; q[0] = (_R(2,1) - _R(1,2)) * s; return; case_1: s = dSqrt((_R(1,1) - (_R(2,2) + _R(0,0))) + 1); q[2] = REAL(0.5) * s; s = REAL(0.5) * dRecip(s); q[3] = (_R(1,2) + _R(2,1)) * s; q[1] = (_R(0,1) + _R(1,0)) * s; q[0] = (_R(0,2) - _R(2,0)) * s; return; case_2: s = dSqrt((_R(2,2) - (_R(0,0) + _R(1,1))) + 1); q[3] = REAL(0.5) * s; s = REAL(0.5) * dRecip(s); q[1] = (_R(2,0) + _R(0,2)) * s; q[2] = (_R(1,2) + _R(2,1)) * s; q[0] = (_R(1,0) - _R(0,1)) * s; return; } } void dDQfromW (dReal dq[4], const dVector3 w, const dQuaternion q) { dAASSERT (w && q && dq); dq[0] = REAL(0.5)*(- w[0]*q[1] - w[1]*q[2] - w[2]*q[3]); dq[1] = REAL(0.5)*( w[0]*q[0] + w[1]*q[3] - w[2]*q[2]); dq[2] = REAL(0.5)*(- w[0]*q[3] + w[1]*q[0] + w[2]*q[1]); dq[3] = REAL(0.5)*( w[0]*q[2] - w[1]*q[1] + w[2]*q[0]); } ode-0.16/ode/src/collision_trimesh_colliders.h0000664000175200017520000000546213403272463016446 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_COLLISION_TRIMESH_COLLIDERS_H_ #define _ODE_COLLISION_TRIMESH_COLLIDERS_H_ int dCollideCylinderTrimesh(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); int dCollideTrimeshPlane(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); int dCollideSTL(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); int dCollideBTL(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); int dCollideRTL(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); int dCollideTTL(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); int dCollideCCTL(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); int dCollideConvexTrimesh(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); ODE_PURE_INLINE int dCollideRayTrimesh( dxGeom *ray, dxGeom *trimesh, int flags, dContactGeom *contact, int skip ) { // Swapped case, for code that needs it (heightfield initially) // The other ray-geom colliders take geoms in a swapped order to the // dCollideRTL function which is annoying when using function pointers. return dCollideRTL( trimesh, ray, flags, contact, skip ); } #endif // _ODE_COLLISION_TRIMESH_COLLIDERS_H_ ode-0.16/ode/src/step.h0000664000175200017520000000371313403272463011630 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_STEP_H_ #define _ODE_STEP_H_ #include struct dxStepperProcessingCallContext; sizeint dxEstimateStepMemoryRequirements( dxBody * const *body, unsigned int nb, dxJoint * const *_joint, unsigned int _nj); unsigned dxEstimateStepMaxCallCount( unsigned activeThreadCount, unsigned allowedThreadCount); void dxStepIsland(const dxStepperProcessingCallContext *callContext); #endif ode-0.16/ode/src/collision_trimesh_disabled.cpp0000664000175200017520000001534013403272463016564 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include "config.h" #include "matrix.h" #if !dTRIMESH_ENABLED #include "collision_util.h" #include "collision_trimesh_internal.h" static const dMatrix4 identity = { REAL( 0.0 ), REAL( 0.0 ), REAL( 0.0 ), REAL( 0.0 ), REAL( 0.0 ), REAL( 0.0 ), REAL( 0.0 ), REAL( 0.0 ), REAL( 0.0 ), REAL( 0.0 ), REAL( 0.0 ), REAL( 0.0 ), REAL( 0.0 ), REAL( 0.0 ), REAL( 0.0 ), REAL( 0.0 ) }; typedef dxMeshBase dxDisabledTriMesh_Parent; struct dxDisabledTriMesh: public dxDisabledTriMesh_Parent { public: // Functions dxDisabledTriMesh(dxSpace *Space, dTriCallback *Callback, dTriArrayCallback *ArrayCallback, dTriRayCallback *RayCallback): dxDisabledTriMesh_Parent(Space, NULL, Callback, ArrayCallback, RayCallback, false) { } virtual void computeAABB(); // This is an abstract method in the base class }; /*virtual */ void dxDisabledTriMesh::computeAABB() { // Do nothing } ////////////////////////////////////////////////////////////////////////// // Stub functions for trimesh calls /*extern */ dTriMeshDataID dGeomTriMeshDataCreate(void) { return NULL; } /*extern */ void dGeomTriMeshDataDestroy(dTriMeshDataID g) { // Do nothing } /*extern */ void dGeomTriMeshDataSet(dTriMeshDataID g, int data_id, void* in_data) { // Do nothing } /*extern */ void *dGeomTriMeshDataGet(dTriMeshDataID g, int data_id) { return NULL; } /*extern */ void *dGeomTriMeshDataGet2(dTriMeshDataID g, int data_id, sizeint *pout_size/*=NULL*/) { if (pout_size != NULL) { *pout_size = 0; } return NULL; } /*extern */ void dGeomTriMeshSetLastTransform( dGeomID g, const dMatrix4 last_trans ) { // Do nothing } /*extern */ const dReal *dGeomTriMeshGetLastTransform( dGeomID g ) { return identity; } /*extern */ dGeomID dCreateTriMesh(dSpaceID space, dTriMeshDataID Data, dTriCallback* Callback, dTriArrayCallback* ArrayCallback, dTriRayCallback* RayCallback) { return new dxDisabledTriMesh(space, Callback, ArrayCallback, RayCallback); // Oleh_Derevenko: I'm not sure if a NULL can be returned here -- keep on returning an object for backward compatibility } /*extern */ void dGeomTriMeshSetData(dGeomID g, dTriMeshDataID Data) { // Do nothing } /*extern */ dTriMeshDataID dGeomTriMeshGetData(dGeomID g) { return NULL; } /*extern */ void dGeomTriMeshDataBuildSingle(dTriMeshDataID g, const void* Vertices, int VertexStride, int VertexCount, const void* Indices, int IndexCount, int TriStride) { // Do nothing } /*extern */ void dGeomTriMeshDataBuildSingle1(dTriMeshDataID g, const void* Vertices, int VertexStride, int VertexCount, const void* Indices, int IndexCount, int TriStride, const void* Normals) { // Do nothing } /*extern */ void dGeomTriMeshDataBuildDouble(dTriMeshDataID g, const void* Vertices, int VertexStride, int VertexCount, const void* Indices, int IndexCount, int TriStride) { // Do nothing } /*extern */ void dGeomTriMeshDataBuildDouble1(dTriMeshDataID g, const void* Vertices, int VertexStride, int VertexCount, const void* Indices, int IndexCount, int TriStride, const void* Normals) { // Do nothing } /*extern */ void dGeomTriMeshDataBuildSimple(dTriMeshDataID g, const dReal* Vertices, int VertexCount, const dTriIndex* Indices, int IndexCount) { // Do nothing } /*extern */ void dGeomTriMeshDataBuildSimple1(dTriMeshDataID g, const dReal* Vertices, int VertexCount, const dTriIndex* Indices, int IndexCount, const int* Normals) { // Do nothing } /*extern ODE_API */ int dGeomTriMeshDataPreprocess(dTriMeshDataID g) { // Do nothing return 1; } /*extern ODE_API */ int dGeomTriMeshDataPreprocess2(dTriMeshDataID g, unsigned int buildRequestFlags, const intptr *requestExtraData/*=NULL | const intptr (*)[dTRIDATAPREPROCESS_BUILD__MAX]*/) { // Do nothing return 1; } /*extern */ void dGeomTriMeshSetCallback(dGeomID g, dTriCallback* Callback) { // Do nothing } /*extern */ dTriCallback* dGeomTriMeshGetCallback(dGeomID g) { return NULL; } /*extern */ void dGeomTriMeshSetArrayCallback(dGeomID g, dTriArrayCallback* ArrayCallback) { // Do nothing } /*extern */ dTriArrayCallback* dGeomTriMeshGetArrayCallback(dGeomID g) { return NULL; } /*extern */ void dGeomTriMeshSetRayCallback(dGeomID g, dTriRayCallback* Callback) { // Do nothing } /*extern */ dTriRayCallback* dGeomTriMeshGetRayCallback(dGeomID g) { return NULL; } /*extern */ void dGeomTriMeshSetTriMergeCallback(dGeomID g, dTriTriMergeCallback* Callback) { // Do nothing } /*extern */ dTriTriMergeCallback* dGeomTriMeshGetTriMergeCallback(dGeomID g) { return NULL; } /*extern */ void dGeomTriMeshEnableTC(dGeomID g, int geomClass, int enable) { // Do nothing } /*extern */ int dGeomTriMeshIsTCEnabled(dGeomID g, int geomClass) { return 0; } /*extern */ void dGeomTriMeshClearTCCache(dGeomID g) { // Do nothing } /*extern */ dTriMeshDataID dGeomTriMeshGetTriMeshDataID(dGeomID g) { return NULL; } /*extern */ int dGeomTriMeshGetTriangleCount (dGeomID g) { return 0; } /*extern */ void dGeomTriMeshDataUpdate(dTriMeshDataID g) { // Do nothing } #endif // !dTRIMESH_ENABLED ode-0.16/ode/src/odemath.cpp0000664000175200017520000002051013403272463012623 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include "config.h" #include "odemath.h" #undef dSafeNormalize3 #undef dSafeNormalize4 #undef dNormalize3 #undef dNormalize4 #undef dPlaneSpace #undef dOrthogonalizeR int dSafeNormalize3 (dVector3 a) { return dxSafeNormalize3(a); } int dSafeNormalize4 (dVector4 a) { return dxSafeNormalize4(a); } void dNormalize3(dVector3 a) { dxNormalize3(a); } void dNormalize4(dVector4 a) { dxNormalize4(a); } void dPlaneSpace(const dVector3 n, dVector3 p, dVector3 q) { return dxPlaneSpace(n, p, q); } int dOrthogonalizeR(dMatrix3 m) { return dxOrthogonalizeR(m); } /*extern */ bool dxCouldBeNormalized3(const dVector3 a) { dAASSERT (a); bool ret = false; for (unsigned axis = dV3E__AXES_MIN; axis != dV3E__AXES_MAX; ++axis) { if (a[axis] != REAL(0.0)) { ret = true; break; } } return ret; } // this may be called for vectors `a' with extremely small magnitude, for // example the result of a cross product on two nearly perpendicular vectors. // we must be robust to these small vectors. to prevent numerical error, // first find the component a[i] with the largest magnitude and then scale // all the components by 1/a[i]. then we can compute the length of `a' and // scale the components by 1/l. this has been verified to work with vectors // containing the smallest representable numbers. /*extern */ bool dxSafeNormalize3 (dVector3 a) { dAASSERT (a); bool ret = false; do { dReal abs_a0 = dFabs(a[dV3E_X]); dReal abs_a1 = dFabs(a[dV3E_Y]); dReal abs_a2 = dFabs(a[dV3E_Z]); dVec3Element idx; if (abs_a1 > abs_a0) { if (abs_a2 > abs_a1) { // abs_a2 is the largest idx = dV3E_Z; } else { // abs_a1 is the largest idx = dV3E_Y; } } else if (abs_a2 > abs_a0) {// abs_a2 is the largest idx = dV3E_Z; } else { // aa[0] might be the largest if (!(abs_a0 > REAL(0.0))) { // if all a's are zero, this is where we'll end up. // return the vector unchanged. break; } // abs_a0 is the largest idx = dV3E_X; } if (idx == dV3E_X) { dReal aa0_recip = dRecip(abs_a0); dReal a1 = a[dV3E_Y] * aa0_recip; dReal a2 = a[dV3E_Z] * aa0_recip; dReal l = dRecipSqrt(REAL(1.0) + a1 * a1 + a2 * a2); a[dV3E_Y] = a1 * l; a[dV3E_Z] = a2 * l; a[dV3E_X] = dCopySign(l, a[dV3E_X]); } else if (idx == dV3E_Y) { dReal aa1_recip = dRecip(abs_a1); dReal a0 = a[dV3E_X] * aa1_recip; dReal a2 = a[dV3E_Z] * aa1_recip; dReal l = dRecipSqrt(REAL(1.0) + a0 * a0 + a2 * a2); a[dV3E_X] = a0 * l; a[dV3E_Z] = a2 * l; a[dV3E_Y] = dCopySign(l, a[dV3E_Y]); } else { dReal aa2_recip = dRecip(abs_a2); dReal a0 = a[dV3E_X] * aa2_recip; dReal a1 = a[dV3E_Y] * aa2_recip; dReal l = dRecipSqrt(REAL(1.0) + a0 * a0 + a1 * a1); a[dV3E_X] = a0 * l; a[dV3E_Y] = a1 * l; a[dV3E_Z] = dCopySign(l, a[dV3E_Z]); } ret = true; } while (false); return ret; } /* OLD VERSION */ /* void dNormalize3 (dVector3 a) { dIASSERT (a); dReal l = dCalcVectorDot3(a,a); if (l > 0) { l = dRecipSqrt(l); a[0] *= l; a[1] *= l; a[2] *= l; } else { a[0] = 1; a[1] = 0; a[2] = 0; } } */ /*extern */ bool dxCouldBeNormalized4(const dVector4 a) { dAASSERT (a); bool ret = false; for (unsigned axis = dV4E__MIN; axis != dV4E__MAX; ++axis) { if (a[axis] != REAL(0.0)) { ret = true; break; } } return ret; } /*extern */ bool dxSafeNormalize4 (dVector4 a) { dAASSERT (a); bool ret = false; dReal l = a[dV4E_X] * a[dV4E_X] + a[dV4E_Y] * a[dV4E_Y] + a[dV4E_Z] * a[dV4E_Z] + a[dV4E_O] * a[dV4E_O]; if (l > 0) { l = dRecipSqrt(l); a[dV4E_X] *= l; a[dV4E_Y] *= l; a[dV4E_Z] *= l; a[dV4E_O] *= l; ret = true; } return ret; } void dxPlaneSpace (const dVector3 n, dVector3 p, dVector3 q) { dAASSERT (n && p && q); if (dFabs(n[2]) > M_SQRT1_2) { // choose p in y-z plane dReal a = n[1]*n[1] + n[2]*n[2]; dReal k = dRecipSqrt (a); p[0] = 0; p[1] = -n[2]*k; p[2] = n[1]*k; // set q = n x p q[0] = a*k; q[1] = -n[0]*p[2]; q[2] = n[0]*p[1]; } else { // choose p in x-y plane dReal a = n[0]*n[0] + n[1]*n[1]; dReal k = dRecipSqrt (a); p[0] = -n[1]*k; p[1] = n[0]*k; p[2] = 0; // set q = n x p q[0] = -n[2]*p[1]; q[1] = n[2]*p[0]; q[2] = a*k; } } /* * This takes what is supposed to be a rotation matrix, * and make sure it is correct. * Note: this operates on rows, not columns, because for rotations * both ways give equivalent results. */ bool dxOrthogonalizeR(dMatrix3 m) { bool ret = false; do { if (!dxCouldBeNormalized3(m + dM3E__X_MIN)) { break; } dReal n0 = dCalcVectorLengthSquare3(m + dM3E__X_MIN); dVector3 row2_store; dReal *row2 = m + dM3E__Y_MIN; // project row[0] on row[1], should be zero dReal proj = dCalcVectorDot3(m + dM3E__X_MIN, m + dM3E__Y_MIN); if (proj != 0) { // Gram-Schmidt step on row[1] dReal proj_div_n0 = proj / n0; row2_store[dV3E_X] = m[dM3E__Y_MIN + dV3E_X] - proj_div_n0 * m[dM3E__X_MIN + dV3E_X] ; row2_store[dV3E_Y] = m[dM3E__Y_MIN + dV3E_Y] - proj_div_n0 * m[dM3E__X_MIN + dV3E_Y]; row2_store[dV3E_Z] = m[dM3E__Y_MIN + dV3E_Z] - proj_div_n0 * m[dM3E__X_MIN + dV3E_Z]; row2 = row2_store; } if (!dxCouldBeNormalized3(row2)) { break; } if (n0 != REAL(1.0)) { bool row0_norm_fault = !dxSafeNormalize3(m + dM3E__X_MIN); dIVERIFY(!row0_norm_fault); } dReal n1 = dCalcVectorLengthSquare3(row2); if (n1 != REAL(1.0)) { bool row1_norm_fault = !dxSafeNormalize3(row2); dICHECK(!row1_norm_fault); } dIASSERT(dFabs(dCalcVectorDot3(m + dM3E__X_MIN, row2)) < 1e-6); /* just overwrite row[2], this makes sure the matrix is not a reflection */ dCalcVectorCross3(m + dM3E__Z_MIN, m + dM3E__X_MIN, row2); m[dM3E_XPAD] = m[dM3E_YPAD] = m[dM3E_ZPAD] = 0; ret = true; } while (false); return ret; } ode-0.16/ode/src/collision_cylinder_sphere.cpp0000664000175200017520000002571613403272463016451 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /******************************************************************* * * * cylinder-sphere collider by Christoph Beyer (boernerb@web.de) * * * * In Cylinder/Sphere-collisions, there are three possibilies: * * 1. collision with the cylinder's nappe * * 2. collision with one of the cylinder's disc * * 3. collision with one of the disc's border * * * * This collider computes two distances (s, t) and based on them, * * it decides, which collision we have. * * This collider always generates 1 (or 0, if we have no collison) * * contacts. * * It is able to "separate" cylinder and sphere in all * * configurations, but it never pays attention to velocity. * * So, in extrem situations, "tunneling-effect" is possible. * * * *******************************************************************/ #include #include #include #include "config.h" #include "matrix.h" #include "odemath.h" #include "collision_kernel.h" // for dxGeom #include "collision_util.h" int dCollideCylinderSphere(dxGeom* Cylinder, dxGeom* Sphere, int flags, dContactGeom *contact, int skip) { dIASSERT (skip >= (int)sizeof(dContactGeom)); dIASSERT (Cylinder->type == dCylinderClass); dIASSERT (Sphere->type == dSphereClass); dIASSERT ((flags & NUMC_MASK) >= 1); //unsigned char* pContactData = (unsigned char*)contact; int GeomCount = 0; // count of used contacts #ifdef dSINGLE const dReal toleranz = REAL(0.0001); #endif #ifdef dDOUBLE const dReal toleranz = REAL(0.0000001); #endif // get the data from the geoms dReal radius, length; dGeomCylinderGetParams(Cylinder, &radius, &length); dVector3 &cylpos = Cylinder->final_posr->pos; //const dReal* pfRot1 = dGeomGetRotation(Cylinder); dReal radius2; radius2 = dGeomSphereGetRadius(Sphere); const dReal* SpherePos = dGeomGetPosition(Sphere); // G1Pos1 is the middle of the first disc // G1Pos2 is the middle of the second disc // vDir1 is the unit direction of the cylinderaxis dVector3 G1Pos1, G1Pos2, vDir1; vDir1[0] = Cylinder->final_posr->R[2]; vDir1[1] = Cylinder->final_posr->R[6]; vDir1[2] = Cylinder->final_posr->R[10]; dReal s; s = length * REAL(0.5); // just a precomputed factor G1Pos2[0] = vDir1[0] * s + cylpos[0]; G1Pos2[1] = vDir1[1] * s + cylpos[1]; G1Pos2[2] = vDir1[2] * s + cylpos[2]; G1Pos1[0] = vDir1[0] * -s + cylpos[0]; G1Pos1[1] = vDir1[1] * -s + cylpos[1]; G1Pos1[2] = vDir1[2] * -s + cylpos[2]; dVector3 C; dReal t; // Step 1: compute the two distances 's' and 't' // 's' is the distance from the first disc (in vDir1-/Zylinderaxis-direction), the disc with G1Pos1 in the middle s = (SpherePos[0] - G1Pos1[0]) * vDir1[0] - (G1Pos1[1] - SpherePos[1]) * vDir1[1] - (G1Pos1[2] - SpherePos[2]) * vDir1[2]; if(s < (-radius2) || s > (length + radius2) ) { // Sphere is too far away from the discs // no collision return 0; } // C is the direction from Sphere-middle to the cylinder-axis (vDir1); C is orthogonal to the cylinder-axis C[0] = s * vDir1[0] + G1Pos1[0] - SpherePos[0]; C[1] = s * vDir1[1] + G1Pos1[1] - SpherePos[1]; C[2] = s * vDir1[2] + G1Pos1[2] - SpherePos[2]; // t is the distance from the Sphere-middle to the cylinder-axis! t = dVector3Length(C); if(t > (radius + radius2) ) { // Sphere is too far away from the cylinder axis! // no collision return 0; } // decide which kind of collision we have: if(t > radius && (s < 0 || s > length) ) { // 3. collision if(s <= 0) { contact->depth = radius2 - dSqrt( (s) * (s) + (t - radius) * (t - radius) ); if(contact->depth < 0) { // no collision! return 0; } contact->pos[0] = C[0] / t * -radius + G1Pos1[0]; contact->pos[1] = C[1] / t * -radius + G1Pos1[1]; contact->pos[2] = C[2] / t * -radius + G1Pos1[2]; contact->normal[0] = (contact->pos[0] - SpherePos[0]) / (radius2 - contact->depth); contact->normal[1] = (contact->pos[1] - SpherePos[1]) / (radius2 - contact->depth); contact->normal[2] = (contact->pos[2] - SpherePos[2]) / (radius2 - contact->depth); contact->g1 = Cylinder; contact->g2 = Sphere; contact->side1 = -1; contact->side2 = -1; GeomCount++; return GeomCount; } else { // now s is bigger than length here! contact->depth = radius2 - dSqrt( (s - length) * (s - length) + (t - radius) * (t - radius) ); if(contact->depth < 0) { // no collision! return 0; } contact->pos[0] = C[0] / t * -radius + G1Pos2[0]; contact->pos[1] = C[1] / t * -radius + G1Pos2[1]; contact->pos[2] = C[2] / t * -radius + G1Pos2[2]; contact->normal[0] = (contact->pos[0] - SpherePos[0]) / (radius2 - contact->depth); contact->normal[1] = (contact->pos[1] - SpherePos[1]) / (radius2 - contact->depth); contact->normal[2] = (contact->pos[2] - SpherePos[2]) / (radius2 - contact->depth); contact->g1 = Cylinder; contact->g2 = Sphere; contact->side1 = -1; contact->side2 = -1; GeomCount++; return GeomCount; } } else if( (radius - t) <= s && (radius - t) <= (length - s) ) { // 1. collsision if(t > (radius2 + toleranz)) { // cylinder-axis is outside the sphere contact->depth = (radius2 + radius) - t; if(contact->depth < 0) { // should never happen, but just for safeness return 0; } else { C[0] /= t; C[1] /= t; C[2] /= t; contact->pos[0] = C[0] * radius2 + SpherePos[0]; contact->pos[1] = C[1] * radius2 + SpherePos[1]; contact->pos[2] = C[2] * radius2 + SpherePos[2]; contact->normal[0] = C[0]; contact->normal[1] = C[1]; contact->normal[2] = C[2]; contact->g1 = Cylinder; contact->g2 = Sphere; contact->side1 = -1; contact->side2 = -1; GeomCount++; return GeomCount; } } else { // cylinder-axis is outside of the sphere contact->depth = (radius2 + radius) - t; if(contact->depth < 0) { // should never happen, but just for safeness return 0; } else { contact->pos[0] = C[0] + SpherePos[0]; contact->pos[1] = C[1] + SpherePos[1]; contact->pos[2] = C[2] + SpherePos[2]; contact->normal[0] = C[0] / t; contact->normal[1] = C[1] / t; contact->normal[2] = C[2] / t; contact->g1 = Cylinder; contact->g2 = Sphere; contact->side1 = -1; contact->side2 = -1; GeomCount++; return GeomCount; } } } else { // 2. collision if(s <= (length * REAL(0.5)) ) { // collsision with the first disc contact->depth = s + radius2; if(contact->depth < 0) { // should never happen, but just for safeness return 0; } contact->pos[0] = radius2 * vDir1[0] + SpherePos[0]; contact->pos[1] = radius2 * vDir1[1] + SpherePos[1]; contact->pos[2] = radius2 * vDir1[2] + SpherePos[2]; contact->normal[0] = vDir1[0]; contact->normal[1] = vDir1[1]; contact->normal[2] = vDir1[2]; contact->g1 = Cylinder; contact->g2 = Sphere; contact->side1 = -1; contact->side2 = -1; GeomCount++; return GeomCount; } else { // collsision with the second disc contact->depth = (radius2 + length - s); if(contact->depth < 0) { // should never happen, but just for safeness return 0; } contact->pos[0] = radius2 * -vDir1[0] + SpherePos[0]; contact->pos[1] = radius2 * -vDir1[1] + SpherePos[1]; contact->pos[2] = radius2 * -vDir1[2] + SpherePos[2]; contact->normal[0] = -vDir1[0]; contact->normal[1] = -vDir1[1]; contact->normal[2] = -vDir1[2]; contact->g1 = Cylinder; contact->g2 = Sphere; contact->side1 = -1; contact->side2 = -1; GeomCount++; return GeomCount; } } return GeomCount; } ode-0.16/ode/src/simple_cooperative.cpp0000664000175200017520000000646713403272463015112 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * Threading base wrapper class header file. * * Copyright (C) 2011-2012 Oleh Derevenko. All rights reserved. * * e-mail: odar@eleks.com (change all "a" to "e") * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* * The simple cooperative class implementation * Copyright (c) 2017 Oleh Derevenko, odar@eleks.com (change all "a" to "e") */ #include #include #include "config.h" #include "simple_cooperative.h" #include "default_threading.h" /*virtual */ dxSimpleCooperative::~dxSimpleCooperative() { // The virtual destructor } /*virtual */ const dxThreadingFunctionsInfo *dxSimpleCooperative::retrieveThreadingDefaultImpl(dThreadingImplementationID &out_defaultImpl) { out_defaultImpl = DefaultThreadingHolder::getDefaultThreadingImpl(); return DefaultThreadingHolder::getDefaultThreadingFunctions(); } ////////////////////////////////////////////////////////////////////////// // Public interface functions static inline dCooperativeID encodeCooperativeID(dxSimpleCooperative *cooperativeInstance) { return (dCooperativeID)cooperativeInstance; } /*extern ODE_API */ dCooperativeID dCooperativeCreate(const dThreadingFunctionsInfo *functionInfo/*=NULL*/, dThreadingImplementationID threadingImpl/*=NULL*/) { dxSimpleCooperative *cooperativeInstance = new dxSimpleCooperative(functionInfo, threadingImpl); dCooperativeID result = encodeCooperativeID(cooperativeInstance); return result; } /*extern ODE_API */ void dCooperativeDestroy(dCooperativeID cooperative) { dxSimpleCooperative *cooperativeInstance = decodeCooperativeID(cooperative); if (cooperativeInstance != NULL) { delete cooperativeInstance; } } ode-0.16/ode/src/threading_pool_win.cpp0000664000175200017520000004601613403272463015066 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * Threading Windows thread pool implementation file. * * Copyright (C) 2011-2012 Oleh Derevenko. All rights reserved. * * e-mail: odar@eleks.com (change all "a" to "e") * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* * Windows thread pool implementation for built-in threading support provider. */ #if defined(_WIN32) #include #include #include #include #include "config.h" #include "objects.h" #include "threading_impl_templates.h" #if dBUILTIN_THREADING_IMPL_ENABLED #include #include #include #endif // #if dBUILTIN_THREADING_IMPL_ENABLED #if dBUILTIN_THREADING_IMPL_ENABLED #define THREAD_STACK_MAX ((sizeint)(UINT_MAX - 1)) // The absolute maximum would be UINT_MAX but let it be a little bit less to avoid "Comparison is always false" warnings. ;) struct dxEventObject { public: dxEventObject(): m_event_handle(NULL) {} ~dxEventObject() { FinalizeObject(); } bool InitializeObject(bool manual_reset, bool initial_state); void FinalizeObject(); bool WaitInfinitely() { return ::WaitForSingleObject(m_event_handle, INFINITE) == WAIT_OBJECT_0; } void SetEvent(); void ResetEvent(); private: HANDLE m_event_handle; }; bool dxEventObject::InitializeObject(bool manual_reset, bool initial_state) { dIASSERT(m_event_handle == NULL); bool result = false; do { HANDLE event_handle = ::CreateEvent(NULL, manual_reset, initial_state, NULL); if (event_handle == NULL) { break; } m_event_handle = event_handle; result = true; } while (false); return result; } void dxEventObject::FinalizeObject() { HANDLE event_handle = m_event_handle; if (event_handle != NULL) { BOOL close_result = ::CloseHandle(event_handle); dICHECK(close_result); // Object destruction should always succeed m_event_handle = NULL; } } void dxEventObject::SetEvent() { BOOL set_result = ::SetEvent(m_event_handle); dICHECK(set_result); } void dxEventObject::ResetEvent() { BOOL reset_result = ::ResetEvent(m_event_handle); dICHECK(reset_result); } struct dxThreadPoolThreadInfo { public: dxThreadPoolThreadInfo(); ~dxThreadPoolThreadInfo(); bool Initialize(sizeint stack_size, unsigned int ode_data_allocate_flags); private: bool WaitInitStatus(); private: void Finalize(); void WaitAndCloseThreadHandle(HANDLE thread_handle); public: enum dxTHREADCOMMAND { dxTHREAD_COMMAND_EXIT, dxTHREAD_COMMAND_NOOP, dxTHREAD_COMMAND_SERVE_IMPLEMENTATION, }; struct dxServeImplementationParams { dxServeImplementationParams(dThreadingImplementationID impl, dxEventObject *ready_wait_event): m_impl(impl), m_ready_wait_event(ready_wait_event) { } dThreadingImplementationID m_impl; dxEventObject *m_ready_wait_event; }; void ExecuteThreadCommand(dxTHREADCOMMAND command, void *param, bool wait_response); private: static unsigned CALLBACK ThreadProcedure_Callback(void *thread_param); void ThreadProcedure(); void ReportInitStatus(bool init_result); void RunCommandHandlingLoop(); void ThreadedServeImplementation(dThreadingImplementationID impl, dxEventObject *ready_wait_event); static void ProcessThreadServeReadiness_Callback(void *context); private: HANDLE m_thread_handle; unsigned int m_ode_data_allocate_flags; dxTHREADCOMMAND m_command_code; dxEventObject m_command_event; dxEventObject m_acknowledgement_event; void *m_command_param; }; dxThreadPoolThreadInfo::dxThreadPoolThreadInfo(): m_thread_handle(NULL), m_ode_data_allocate_flags(0), m_command_code(dxTHREAD_COMMAND_EXIT), m_command_event(), m_acknowledgement_event(), m_command_param(NULL) { } dxThreadPoolThreadInfo::~dxThreadPoolThreadInfo() { Finalize(); } bool dxThreadPoolThreadInfo::Initialize(sizeint stack_size, unsigned int ode_data_allocate_flags) { bool result = false; bool command_event_allocated = false, acknowledgement_event_allocated = false; HANDLE thread_handle = NULL; do { if (stack_size > THREAD_STACK_MAX) { SetLastError(ERROR_INVALID_PARAMETER); break; } if (!m_command_event.InitializeObject(false, false)) { break; } command_event_allocated = true; if (!m_acknowledgement_event.InitializeObject(true, false)) { break; } acknowledgement_event_allocated = true; m_ode_data_allocate_flags = ode_data_allocate_flags; thread_handle = (HANDLE)_beginthreadex(NULL, (unsigned)stack_size, &ThreadProcedure_Callback, (void *)this, 0, NULL); if (thread_handle == NULL) // Not a bug!!! _beginthreadex() returns NULL on failure { break; } // It is OK to alter priority for thread without creating it in suspended state as // it is anyway going to be waited for (waited for its init result) and // will not be issues commands until after that. int own_priority = GetThreadPriority(GetCurrentThread()); if (own_priority != THREAD_PRIORITY_ERROR_RETURN) { if (!SetThreadPriority(thread_handle, own_priority)) { // own_priority = THREAD_PRIORITY_ERROR_RETURN; -- Well, if priority inheritance fails - just ignore it :-/ } } bool thread_init_result = WaitInitStatus(); if (!thread_init_result) { DWORD error_save = GetLastError(); WaitAndCloseThreadHandle(thread_handle); SetLastError(error_save); break; } m_thread_handle = thread_handle; result = true; } while (false); if (!result) { if (command_event_allocated) { if (acknowledgement_event_allocated) { m_acknowledgement_event.FinalizeObject(); } m_command_event.FinalizeObject(); } } return result; } bool dxThreadPoolThreadInfo::WaitInitStatus() { bool acknowledgement_wait_result = m_acknowledgement_event.WaitInfinitely(); dICHECK(acknowledgement_wait_result); DWORD error_code = (DWORD)(sizeint)m_command_param; bool init_status = error_code == ERROR_SUCCESS ? true : (SetLastError(error_code), false); return init_status; } void dxThreadPoolThreadInfo::Finalize() { HANDLE thread_handle = m_thread_handle; if (thread_handle != NULL) { ExecuteThreadCommand(dxTHREAD_COMMAND_EXIT, NULL, false); WaitAndCloseThreadHandle(thread_handle); m_thread_handle = NULL; m_command_event.FinalizeObject(); m_acknowledgement_event.FinalizeObject(); } } void dxThreadPoolThreadInfo::WaitAndCloseThreadHandle(HANDLE thread_handle) { DWORD thread_wait_result = WaitForSingleObject(thread_handle, INFINITE); dICHECK(thread_wait_result == WAIT_OBJECT_0); BOOL thread_close_result = CloseHandle(thread_handle); dIVERIFY(thread_close_result); } void dxThreadPoolThreadInfo::ExecuteThreadCommand(dxTHREADCOMMAND command, void *param, bool wait_response) { bool acknowledgement_wait_result = m_acknowledgement_event.WaitInfinitely(); dICHECK(acknowledgement_wait_result); m_acknowledgement_event.ResetEvent(); m_command_code = command; m_command_param = param; m_command_event.SetEvent(); if (wait_response) { bool new_acknowledgement_wait_result = m_acknowledgement_event.WaitInfinitely(); dICHECK(new_acknowledgement_wait_result); } } unsigned CALLBACK dxThreadPoolThreadInfo::ThreadProcedure_Callback(void *thread_param) { dxThreadPoolThreadInfo *thread_info = (dxThreadPoolThreadInfo *)thread_param; thread_info->ThreadProcedure(); return 0; } void dxThreadPoolThreadInfo::ThreadProcedure() { bool init_result = dAllocateODEDataForThread(m_ode_data_allocate_flags) != 0; ReportInitStatus(init_result); if (init_result) { RunCommandHandlingLoop(); // dCleanupODEAllDataForThread(); -- this function can only be called if ODE was initialized for manual cleanup. And that is unknown here... } } void dxThreadPoolThreadInfo::ReportInitStatus(bool init_result) { DWORD error_code; m_command_param = (void *)(sizeint)(init_result ? ERROR_SUCCESS : ((error_code = GetLastError()) != ERROR_SUCCESS ? error_code : ERROR_INTERNAL_ERROR)); m_acknowledgement_event.SetEvent(); } void dxThreadPoolThreadInfo::RunCommandHandlingLoop() { bool exit_requested = false; while (!exit_requested) { bool command_wait_result = m_command_event.WaitInfinitely(); dICHECK(command_wait_result); const dxTHREADCOMMAND command_code = m_command_code; switch (command_code) { case dxTHREAD_COMMAND_EXIT: { m_acknowledgement_event.SetEvent(); exit_requested = true; break; } default: { dIASSERT(false); // break; -- proceed to case dxTHREAD_COMMAND_NOOP } case dxTHREAD_COMMAND_NOOP: { m_acknowledgement_event.SetEvent(); // Do nothing break; } case dxTHREAD_COMMAND_SERVE_IMPLEMENTATION: { const dxServeImplementationParams *serve_params = (const dxServeImplementationParams *)m_command_param; dThreadingImplementationID impl = serve_params->m_impl; dxEventObject *ready_wait_event = serve_params->m_ready_wait_event; m_acknowledgement_event.SetEvent(); ThreadedServeImplementation(impl, ready_wait_event); break; } } } } void dxThreadPoolThreadInfo::ThreadedServeImplementation(dThreadingImplementationID impl, dxEventObject *ready_wait_event) { ((dxIThreadingImplementation *)impl)->StickToJobsProcessing(&ProcessThreadServeReadiness_Callback, (void *)ready_wait_event); } void dxThreadPoolThreadInfo::ProcessThreadServeReadiness_Callback(void *context) { dxEventObject *ready_wait_event = (dxEventObject *)context; ready_wait_event->SetEvent(); } struct dxThreadingThreadPool: public dBase { public: dxThreadingThreadPool(); ~dxThreadingThreadPool(); bool InitializeThreads(sizeint thread_count, sizeint stack_size, unsigned int ode_data_allocate_flags); private: void FinalizeThreads(); bool InitializeIndividualThreadInfos(dxThreadPoolThreadInfo *thread_infos, sizeint thread_count, sizeint stack_size, unsigned int ode_data_allocate_flags); void FinalizeIndividualThreadInfos(dxThreadPoolThreadInfo *thread_infos, sizeint thread_count); bool InitializeSingleThreadInfo(dxThreadPoolThreadInfo *thread_info, sizeint stack_size, unsigned int ode_data_allocate_flags); void FinalizeSingleThreadInfo(dxThreadPoolThreadInfo *thread_info); public: void ServeThreadingImplementation(dThreadingImplementationID impl); void WaitIdleState(); private: dxThreadPoolThreadInfo *m_thread_infos; sizeint m_thread_count; dxEventObject m_ready_wait_event; }; dxThreadingThreadPool::dxThreadingThreadPool(): m_thread_infos(NULL), m_thread_count(0), m_ready_wait_event() { } dxThreadingThreadPool::~dxThreadingThreadPool() { FinalizeThreads(); } bool dxThreadingThreadPool::InitializeThreads(sizeint thread_count, sizeint stack_size, unsigned int ode_data_allocate_flags) { dIASSERT(m_thread_infos == NULL); bool result = false; bool wait_event_allocated = false; dxThreadPoolThreadInfo *thread_infos = NULL; bool thread_infos_allocated = false; do { if (!m_ready_wait_event.InitializeObject(false, false)) { break; } wait_event_allocated = true; thread_infos = (dxThreadPoolThreadInfo *)dAlloc(thread_count * sizeof(dxThreadPoolThreadInfo)); if (thread_infos == NULL) { break; } thread_infos_allocated = true; if (!InitializeIndividualThreadInfos(thread_infos, thread_count, stack_size, ode_data_allocate_flags)) { break; } m_thread_infos = thread_infos; m_thread_count = thread_count; result = true; } while (false); if (!result) { if (wait_event_allocated) { if (thread_infos_allocated) { dFree(thread_infos, thread_count * sizeof(dxThreadPoolThreadInfo)); } m_ready_wait_event.FinalizeObject(); } } return result; } void dxThreadingThreadPool::FinalizeThreads() { dxThreadPoolThreadInfo *thread_infos = m_thread_infos; if (thread_infos != NULL) { sizeint thread_count = m_thread_count; FinalizeIndividualThreadInfos(thread_infos, thread_count); dFree(thread_infos, thread_count * sizeof(dxThreadPoolThreadInfo)); m_ready_wait_event.FinalizeObject(); } } bool dxThreadingThreadPool::InitializeIndividualThreadInfos(dxThreadPoolThreadInfo *thread_infos, sizeint thread_count, sizeint stack_size, unsigned int ode_data_allocate_flags) { bool any_fault = false; dxThreadPoolThreadInfo *const infos_end = thread_infos + thread_count; for (dxThreadPoolThreadInfo *current_info = thread_infos; current_info != infos_end; ++current_info) { if (!InitializeSingleThreadInfo(current_info, stack_size, ode_data_allocate_flags)) { FinalizeIndividualThreadInfos(thread_infos, current_info - thread_infos); any_fault = true; break; } } bool result = !any_fault; return result; } void dxThreadingThreadPool::FinalizeIndividualThreadInfos(dxThreadPoolThreadInfo *thread_infos, sizeint thread_count) { dxThreadPoolThreadInfo *const infos_end = thread_infos + thread_count; for (dxThreadPoolThreadInfo *current_info = thread_infos; current_info != infos_end; ++current_info) { FinalizeSingleThreadInfo(current_info); } } bool dxThreadingThreadPool::InitializeSingleThreadInfo(dxThreadPoolThreadInfo *thread_info, sizeint stack_size, unsigned int ode_data_allocate_flags) { bool result = false; new(thread_info) dxThreadPoolThreadInfo(); if (thread_info->Initialize(stack_size, ode_data_allocate_flags)) { result = true; } else { thread_info->dxThreadPoolThreadInfo::~dxThreadPoolThreadInfo(); } return result; } void dxThreadingThreadPool::FinalizeSingleThreadInfo(dxThreadPoolThreadInfo *thread_info) { if (thread_info != NULL) { thread_info->dxThreadPoolThreadInfo::~dxThreadPoolThreadInfo(); } } void dxThreadingThreadPool::ServeThreadingImplementation(dThreadingImplementationID impl) { dxThreadPoolThreadInfo::dxServeImplementationParams params(impl, &m_ready_wait_event); dxThreadPoolThreadInfo *const infos_end = m_thread_infos + m_thread_count; for (dxThreadPoolThreadInfo *current_info = m_thread_infos; current_info != infos_end; ++current_info) { current_info->ExecuteThreadCommand(dxThreadPoolThreadInfo::dxTHREAD_COMMAND_SERVE_IMPLEMENTATION, ¶ms, true); bool ready_wait_result = m_ready_wait_event.WaitInfinitely(); dICHECK(ready_wait_result); } } void dxThreadingThreadPool::WaitIdleState() { dxThreadPoolThreadInfo *const infos_end = m_thread_infos + m_thread_count; for (dxThreadPoolThreadInfo *current_info = m_thread_infos; current_info != infos_end; ++current_info) { current_info->ExecuteThreadCommand(dxThreadPoolThreadInfo::dxTHREAD_COMMAND_NOOP, NULL, true); } } #endif // #if dBUILTIN_THREADING_IMPL_ENABLED /*extern */dThreadingThreadPoolID dThreadingAllocateThreadPool(unsigned thread_count, sizeint stack_size, unsigned int ode_data_allocate_flags, void *reserved/*=NULL*/) { dAASSERT(thread_count != 0); #if dBUILTIN_THREADING_IMPL_ENABLED dxThreadingThreadPool *thread_pool = new dxThreadingThreadPool(); if (thread_pool != NULL) { if (thread_pool->InitializeThreads(thread_count, stack_size, ode_data_allocate_flags)) { // do nothing } else { delete thread_pool; thread_pool = NULL; } } #else dThreadingThreadPoolID thread_pool = NULL; #endif // #if dBUILTIN_THREADING_IMPL_ENABLED return (dThreadingThreadPoolID)thread_pool; } /*extern */void dThreadingThreadPoolServeMultiThreadedImplementation(dThreadingThreadPoolID pool, dThreadingImplementationID impl) { #if dBUILTIN_THREADING_IMPL_ENABLED dxThreadingThreadPool *thread_pool = (dxThreadingThreadPool *)pool; thread_pool->ServeThreadingImplementation(impl); #endif // #if dBUILTIN_THREADING_IMPL_ENABLED } /*extern */void dThreadingThreadPoolWaitIdleState(dThreadingThreadPoolID pool) { #if dBUILTIN_THREADING_IMPL_ENABLED dxThreadingThreadPool *thread_pool = (dxThreadingThreadPool *)pool; thread_pool->WaitIdleState(); #endif // #if dBUILTIN_THREADING_IMPL_ENABLED } /*extern */void dThreadingFreeThreadPool(dThreadingThreadPoolID pool) { #if dBUILTIN_THREADING_IMPL_ENABLED dxThreadingThreadPool *thread_pool = (dxThreadingThreadPool *)pool; delete thread_pool; #endif // #if dBUILTIN_THREADING_IMPL_ENABLED } #endif // #if defined(_WIN32) ode-0.16/ode/src/threading_pool_posix.cpp0000664000175200017520000005452313403272463015435 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * Threading POSIX thread pool implementation file. * * Copyright (C) 2011-2012 Oleh Derevenko. All rights reserved. * * e-mail: odar@eleks.com (change all "a" to "e") * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* * POSIX thread pool implementation for built-in threading support provider. */ #if !defined(_WIN32) #include #include #include #include #include "config.h" #include "objects.h" #include "threading_impl_templates.h" #if dBUILTIN_THREADING_IMPL_ENABLED #include #include #include #include #if !defined(EOK) #define EOK 0 #endif #endif // #if dBUILTIN_THREADING_IMPL_ENABLED #if dBUILTIN_THREADING_IMPL_ENABLED struct dxEventObject { public: dxEventObject(): m_event_allocated(false), m_event_manual(false), m_event_value(false) {} ~dxEventObject() { FinalizeObject(); } bool InitializeObject(bool manual_reset, bool initial_state); void FinalizeObject(); // WARNING! To make implementation simpler, event only releases a single thread even for manual mode. bool WaitInfinitely(); void SetEvent(); void ResetEvent(); private: bool m_event_allocated; bool m_event_manual; bool m_event_value; pthread_mutex_t m_event_mutex; pthread_cond_t m_event_cond; }; bool dxEventObject::InitializeObject(bool manual_reset, bool initial_state) { dIASSERT(!m_event_allocated); bool result = false; bool cond_allocated = false; do { int cond_result = pthread_cond_init(&m_event_cond, NULL); if (cond_result != EOK) { errno = cond_result; break; } cond_allocated = true; int mutex_result = pthread_mutex_init(&m_event_mutex, NULL); if (mutex_result != EOK) { errno = mutex_result; break; } m_event_manual = manual_reset; m_event_value = initial_state; m_event_allocated = true; result = true; } while (false); if (!result) { if (cond_allocated) { int cond_destroy_result = pthread_cond_destroy(&m_event_cond); dIVERIFY(cond_destroy_result == EOK); } } return result; } void dxEventObject::FinalizeObject() { if (m_event_allocated) { int mutex_destroy_result = pthread_mutex_destroy(&m_event_mutex); dICHECK(mutex_destroy_result == EOK); // Why would mutex be unable to be destroyed? int cond_destroy_result = pthread_cond_destroy(&m_event_cond); dICHECK(cond_destroy_result == EOK); // Why would condvar be unable to be destroyed? m_event_allocated = false; } } bool dxEventObject::WaitInfinitely() { bool result = false; int lock_result = pthread_mutex_lock(&m_event_mutex); dICHECK(lock_result == EOK); int wait_result = EOK; if (!m_event_value) { wait_result = pthread_cond_wait(&m_event_cond, &m_event_mutex); dICHECK(wait_result != EINTR); // Would caller be so kind to disable signal handling for thread for duration of the call to ODE at least? } if (wait_result == EOK) { dIASSERT(m_event_value); if (!m_event_manual) { m_event_value = false; } result = true; } int unlock_result = pthread_mutex_unlock(&m_event_mutex); dICHECK(unlock_result == EOK); return result; } void dxEventObject::SetEvent() { int lock_result = pthread_mutex_lock(&m_event_mutex); dICHECK(lock_result == EOK); if (!m_event_value) { m_event_value = true; // NOTE! Event only releases a single thread even for manual mode to simplify implementation. int signal_result = pthread_cond_signal(&m_event_cond); dICHECK(signal_result == EOK); } int unlock_result = pthread_mutex_unlock(&m_event_mutex); dICHECK(unlock_result == EOK); } void dxEventObject::ResetEvent() { int lock_result = pthread_mutex_lock(&m_event_mutex); dICHECK(lock_result == EOK); m_event_value = false; int unlock_result = pthread_mutex_unlock(&m_event_mutex); dICHECK(unlock_result == EOK); } struct dxThreadPoolThreadInfo { public: dxThreadPoolThreadInfo(); ~dxThreadPoolThreadInfo(); bool Initialize(sizeint stack_size, unsigned int ode_data_allocate_flags); private: bool InitializeThreadAttributes(pthread_attr_t *thread_attr, sizeint stack_size); void FinalizeThreadAttributes(pthread_attr_t *thread_attr); bool WaitInitStatus(); private: void Finalize(); void WaitAndCloseThreadHandle(pthread_t thread_handle); public: enum dxTHREADCOMMAND { dxTHREAD_COMMAND_EXIT, dxTHREAD_COMMAND_NOOP, dxTHREAD_COMMAND_SERVE_IMPLEMENTATION, }; struct dxServeImplementationParams { dxServeImplementationParams(dThreadingImplementationID impl, dxEventObject *ready_wait_event): m_impl(impl), m_ready_wait_event(ready_wait_event) { } dThreadingImplementationID m_impl; dxEventObject *m_ready_wait_event; }; void ExecuteThreadCommand(dxTHREADCOMMAND command, void *param, bool wait_response); private: static void *ThreadProcedure_Callback(void *thread_param); void ThreadProcedure(); bool DisableSignalHandlers(); void ReportInitStatus(bool init_result); void RunCommandHandlingLoop(); void ThreadedServeImplementation(dThreadingImplementationID impl, dxEventObject *ready_wait_event); static void ProcessThreadServeReadiness_Callback(void *context); private: pthread_t m_thread_handle; bool m_thread_allocated; unsigned int m_ode_data_allocate_flags; dxTHREADCOMMAND m_command_code; dxEventObject m_command_event; dxEventObject m_acknowledgement_event; void *m_command_param; }; dxThreadPoolThreadInfo::dxThreadPoolThreadInfo(): m_thread_handle(), m_thread_allocated(false), m_ode_data_allocate_flags(0), m_command_code(dxTHREAD_COMMAND_EXIT), m_command_event(), m_acknowledgement_event(), m_command_param(NULL) { } dxThreadPoolThreadInfo::~dxThreadPoolThreadInfo() { Finalize(); } bool dxThreadPoolThreadInfo::Initialize(sizeint stack_size, unsigned int ode_data_allocate_flags) { bool result = false; bool command_event_allocated = false, acknowledgement_event_allocated = false; do { // -- There is no implicit limit on stack size in POSIX implementation // if (stack_size > ...) // { // errno = EINVAL; // break; // } if (!m_command_event.InitializeObject(false, false)) { break; } command_event_allocated = true; if (!m_acknowledgement_event.InitializeObject(true, false)) { break; } acknowledgement_event_allocated = true; m_ode_data_allocate_flags = ode_data_allocate_flags; pthread_attr_t thread_attr; if (!InitializeThreadAttributes(&thread_attr, stack_size)) { break; } int thread_create_result = pthread_create(&m_thread_handle, &thread_attr, &ThreadProcedure_Callback, (void *)this); FinalizeThreadAttributes(&thread_attr); if (thread_create_result != EOK) { errno = thread_create_result; break; } bool thread_init_result = WaitInitStatus(); if (!thread_init_result) { WaitAndCloseThreadHandle(m_thread_handle); break; } m_thread_allocated = true; result = true; } while (false); if (!result) { if (command_event_allocated) { if (acknowledgement_event_allocated) { m_acknowledgement_event.FinalizeObject(); } m_command_event.FinalizeObject(); } } return result; } bool dxThreadPoolThreadInfo::InitializeThreadAttributes(pthread_attr_t *thread_attr, sizeint stack_size) { bool result = false; bool attr_inited = false; do { int init_result = pthread_attr_init(thread_attr); if (init_result != EOK) { errno = init_result; break; } attr_inited = true; int set_result; if ((set_result = pthread_attr_setdetachstate(thread_attr, PTHREAD_CREATE_JOINABLE)) != EOK || (set_result = pthread_attr_setinheritsched(thread_attr, PTHREAD_INHERIT_SCHED)) != EOK #if (HAVE_PTHREAD_ATTR_SETSTACKLAZY) || (set_result = pthread_attr_setstacklazy(thread_attr, PTHREAD_STACK_NOTLAZY)) != EOK #endif || (stack_size != 0 && (set_result = pthread_attr_setstacksize(thread_attr, stack_size)) != EOK)) { errno = set_result; break; } result = true; } while (false); if (!result) { if (attr_inited) { int destroy_result = pthread_attr_destroy(thread_attr); dIVERIFY(destroy_result == EOK); } } return result; } void dxThreadPoolThreadInfo::FinalizeThreadAttributes(pthread_attr_t *thread_attr) { int destroy_result = pthread_attr_destroy(thread_attr); dIVERIFY(destroy_result == EOK); } bool dxThreadPoolThreadInfo::WaitInitStatus() { bool acknowledgement_wait_result = m_acknowledgement_event.WaitInfinitely(); dICHECK(acknowledgement_wait_result); int error_code = (int)(sizeint)m_command_param; bool init_status = error_code == EOK ? true : ((errno = error_code), false); return init_status; } void dxThreadPoolThreadInfo::Finalize() { if (m_thread_allocated) { ExecuteThreadCommand(dxTHREAD_COMMAND_EXIT, NULL, false); WaitAndCloseThreadHandle(m_thread_handle); m_thread_allocated = false; m_command_event.FinalizeObject(); m_acknowledgement_event.FinalizeObject(); } } void dxThreadPoolThreadInfo::WaitAndCloseThreadHandle(pthread_t thread_handle) { int join_result = pthread_join(thread_handle, NULL); dICHECK(join_result == EOK); } void dxThreadPoolThreadInfo::ExecuteThreadCommand(dxTHREADCOMMAND command, void *param, bool wait_response) { bool acknowledgement_wait_result = m_acknowledgement_event.WaitInfinitely(); dICHECK(acknowledgement_wait_result); m_acknowledgement_event.ResetEvent(); m_command_code = command; m_command_param = param; m_command_event.SetEvent(); if (wait_response) { bool new_acknowledgement_wait_result = m_acknowledgement_event.WaitInfinitely(); dICHECK(new_acknowledgement_wait_result); } } void *dxThreadPoolThreadInfo::ThreadProcedure_Callback(void *thread_param) { dxThreadPoolThreadInfo *thread_info = (dxThreadPoolThreadInfo *)thread_param; thread_info->ThreadProcedure(); return 0; } void dxThreadPoolThreadInfo::ThreadProcedure() { bool init_result = dAllocateODEDataForThread(m_ode_data_allocate_flags) != 0 && DisableSignalHandlers(); ReportInitStatus(init_result); if (init_result) { RunCommandHandlingLoop(); // dCleanupODEAllDataForThread(); -- this function can only be called if ODE was initialized for manual cleanup. And that is unknown here... } } bool dxThreadPoolThreadInfo::DisableSignalHandlers() { bool result = false; sigset_t set; sigfillset( &set ); if (sigprocmask( SIG_BLOCK, &set, NULL ) != -1) { result = true; } return result; } void dxThreadPoolThreadInfo::ReportInitStatus(bool init_result) { m_command_param = (void *)(sizeint)(init_result ? EOK : ((errno != EOK) ? errno : EFAULT)); m_acknowledgement_event.SetEvent(); } void dxThreadPoolThreadInfo::RunCommandHandlingLoop() { bool exit_requested = false; while (!exit_requested) { bool command_wait_result = m_command_event.WaitInfinitely(); dICHECK(command_wait_result); const dxTHREADCOMMAND command_code = m_command_code; switch (command_code) { case dxTHREAD_COMMAND_EXIT: { m_acknowledgement_event.SetEvent(); exit_requested = true; break; } default: { dIASSERT(false); // break; -- proceed to case dxTHREAD_COMMAND_NOOP } case dxTHREAD_COMMAND_NOOP: { m_acknowledgement_event.SetEvent(); // Do nothing break; } case dxTHREAD_COMMAND_SERVE_IMPLEMENTATION: { const dxServeImplementationParams *serve_params = (const dxServeImplementationParams *)m_command_param; dThreadingImplementationID impl = serve_params->m_impl; dxEventObject *ready_wait_event = serve_params->m_ready_wait_event; m_acknowledgement_event.SetEvent(); ThreadedServeImplementation(impl, ready_wait_event); break; } } } } void dxThreadPoolThreadInfo::ThreadedServeImplementation(dThreadingImplementationID impl, dxEventObject *ready_wait_event) { ((dxIThreadingImplementation *)impl)->StickToJobsProcessing(&ProcessThreadServeReadiness_Callback, (void *)ready_wait_event); } void dxThreadPoolThreadInfo::ProcessThreadServeReadiness_Callback(void *context) { dxEventObject *ready_wait_event = (dxEventObject *)context; ready_wait_event->SetEvent(); } struct dxThreadingThreadPool: public dBase { public: dxThreadingThreadPool(); ~dxThreadingThreadPool(); bool InitializeThreads(sizeint thread_count, sizeint stack_size, unsigned int ode_data_allocate_flags); private: void FinalizeThreads(); bool InitializeIndividualThreadInfos(dxThreadPoolThreadInfo *thread_infos, sizeint thread_count, sizeint stack_size, unsigned int ode_data_allocate_flags); void FinalizeIndividualThreadInfos(dxThreadPoolThreadInfo *thread_infos, sizeint thread_count); bool InitializeSingleThreadInfo(dxThreadPoolThreadInfo *thread_info, sizeint stack_size, unsigned int ode_data_allocate_flags); void FinalizeSingleThreadInfo(dxThreadPoolThreadInfo *thread_info); public: void ServeThreadingImplementation(dThreadingImplementationID impl); void WaitIdleState(); private: dxThreadPoolThreadInfo *m_thread_infos; sizeint m_thread_count; dxEventObject m_ready_wait_event; }; dxThreadingThreadPool::dxThreadingThreadPool(): m_thread_infos(NULL), m_thread_count(0), m_ready_wait_event() { } dxThreadingThreadPool::~dxThreadingThreadPool() { FinalizeThreads(); } bool dxThreadingThreadPool::InitializeThreads(sizeint thread_count, sizeint stack_size, unsigned int ode_data_allocate_flags) { dIASSERT(m_thread_infos == NULL); bool result = false; bool wait_event_allocated = false; dxThreadPoolThreadInfo *thread_infos = NULL; bool thread_infos_allocated = false; do { if (!m_ready_wait_event.InitializeObject(false, false)) { break; } wait_event_allocated = true; thread_infos = (dxThreadPoolThreadInfo *)dAlloc(thread_count * sizeof(dxThreadPoolThreadInfo)); if (thread_infos == NULL) { break; } thread_infos_allocated = true; if (!InitializeIndividualThreadInfos(thread_infos, thread_count, stack_size, ode_data_allocate_flags)) { break; } m_thread_infos = thread_infos; m_thread_count = thread_count; result = true; } while (false); if (!result) { if (wait_event_allocated) { if (thread_infos_allocated) { dFree(thread_infos, thread_count * sizeof(dxThreadPoolThreadInfo)); } m_ready_wait_event.FinalizeObject(); } } return result; } void dxThreadingThreadPool::FinalizeThreads() { dxThreadPoolThreadInfo *thread_infos = m_thread_infos; if (thread_infos != NULL) { sizeint thread_count = m_thread_count; FinalizeIndividualThreadInfos(thread_infos, thread_count); dFree(thread_infos, thread_count * sizeof(dxThreadPoolThreadInfo)); m_ready_wait_event.FinalizeObject(); } } bool dxThreadingThreadPool::InitializeIndividualThreadInfos(dxThreadPoolThreadInfo *thread_infos, sizeint thread_count, sizeint stack_size, unsigned int ode_data_allocate_flags) { bool any_fault = false; dxThreadPoolThreadInfo *const infos_end = thread_infos + thread_count; for (dxThreadPoolThreadInfo *current_info = thread_infos; current_info != infos_end; ++current_info) { if (!InitializeSingleThreadInfo(current_info, stack_size, ode_data_allocate_flags)) { FinalizeIndividualThreadInfos(thread_infos, current_info - thread_infos); any_fault = true; break; } } bool result = !any_fault; return result; } void dxThreadingThreadPool::FinalizeIndividualThreadInfos(dxThreadPoolThreadInfo *thread_infos, sizeint thread_count) { dxThreadPoolThreadInfo *const infos_end = thread_infos + thread_count; for (dxThreadPoolThreadInfo *current_info = thread_infos; current_info != infos_end; ++current_info) { FinalizeSingleThreadInfo(current_info); } } bool dxThreadingThreadPool::InitializeSingleThreadInfo(dxThreadPoolThreadInfo *thread_info, sizeint stack_size, unsigned int ode_data_allocate_flags) { bool result = false; new(thread_info) dxThreadPoolThreadInfo(); if (thread_info->Initialize(stack_size, ode_data_allocate_flags)) { result = true; } else { thread_info->dxThreadPoolThreadInfo::~dxThreadPoolThreadInfo(); } return result; } void dxThreadingThreadPool::FinalizeSingleThreadInfo(dxThreadPoolThreadInfo *thread_info) { if (thread_info != NULL) { thread_info->dxThreadPoolThreadInfo::~dxThreadPoolThreadInfo(); } } void dxThreadingThreadPool::ServeThreadingImplementation(dThreadingImplementationID impl) { dxThreadPoolThreadInfo::dxServeImplementationParams params(impl, &m_ready_wait_event); dxThreadPoolThreadInfo *const infos_end = m_thread_infos + m_thread_count; for (dxThreadPoolThreadInfo *current_info = m_thread_infos; current_info != infos_end; ++current_info) { current_info->ExecuteThreadCommand(dxThreadPoolThreadInfo::dxTHREAD_COMMAND_SERVE_IMPLEMENTATION, ¶ms, true); bool ready_wait_result = m_ready_wait_event.WaitInfinitely(); dICHECK(ready_wait_result); } } void dxThreadingThreadPool::WaitIdleState() { dxThreadPoolThreadInfo *const infos_end = m_thread_infos + m_thread_count; for (dxThreadPoolThreadInfo *current_info = m_thread_infos; current_info != infos_end; ++current_info) { current_info->ExecuteThreadCommand(dxThreadPoolThreadInfo::dxTHREAD_COMMAND_NOOP, NULL, true); } } #endif // #if dBUILTIN_THREADING_IMPL_ENABLED /*extern */dThreadingThreadPoolID dThreadingAllocateThreadPool(unsigned thread_count, sizeint stack_size, unsigned int ode_data_allocate_flags, void *reserved/*=NULL*/) { dAASSERT(thread_count != 0); #if dBUILTIN_THREADING_IMPL_ENABLED dxThreadingThreadPool *thread_pool = new dxThreadingThreadPool(); if (thread_pool != NULL) { if (thread_pool->InitializeThreads(thread_count, stack_size, ode_data_allocate_flags)) { // do nothing } else { delete thread_pool; thread_pool = NULL; } } #else dThreadingThreadPoolID thread_pool = NULL; (void)stack_size; // unused (void)ode_data_allocate_flags; // unused (void)reserved; // unused #endif // #if dBUILTIN_THREADING_IMPL_ENABLED return (dThreadingThreadPoolID)thread_pool; } /*extern */void dThreadingThreadPoolServeMultiThreadedImplementation(dThreadingThreadPoolID pool, dThreadingImplementationID impl) { #if dBUILTIN_THREADING_IMPL_ENABLED dxThreadingThreadPool *thread_pool = (dxThreadingThreadPool *)pool; thread_pool->ServeThreadingImplementation(impl); #else (void)pool; // unused (void)impl; // unused #endif // #if dBUILTIN_THREADING_IMPL_ENABLED } /*extern */void dThreadingThreadPoolWaitIdleState(dThreadingThreadPoolID pool) { #if dBUILTIN_THREADING_IMPL_ENABLED dxThreadingThreadPool *thread_pool = (dxThreadingThreadPool *)pool; thread_pool->WaitIdleState(); #else (void)pool; // unused #endif // #if dBUILTIN_THREADING_IMPL_ENABLED } /*extern */void dThreadingFreeThreadPool(dThreadingThreadPoolID pool) { #if dBUILTIN_THREADING_IMPL_ENABLED dxThreadingThreadPool *thread_pool = (dxThreadingThreadPool *)pool; delete thread_pool; #else (void)pool; // unused #endif // #if dBUILTIN_THREADING_IMPL_ENABLED } #endif // #if !defined(_WIN32) ode-0.16/ode/src/memory.cpp0000664000175200017520000000526013403272463012517 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include #include #include "config.h" static dAllocFunction *allocfn = 0; static dReallocFunction *reallocfn = 0; static dFreeFunction *freefn = 0; #ifdef __MINGW32__ /* this is a guard against AC_FUNC_MALLOC and AC_FUNC_REALLOC which break cross compilation, no issues in native MSYS. */ #undef malloc #undef realloc #endif void dSetAllocHandler (dAllocFunction *fn) { allocfn = fn; } void dSetReallocHandler (dReallocFunction *fn) { reallocfn = fn; } void dSetFreeHandler (dFreeFunction *fn) { freefn = fn; } dAllocFunction *dGetAllocHandler() { return allocfn; } dReallocFunction *dGetReallocHandler() { return reallocfn; } dFreeFunction *dGetFreeHandler() { return freefn; } void * dAlloc (sizeint size) { if (allocfn) return allocfn (size); else return malloc (size); } void * dRealloc (void *ptr, sizeint oldsize, sizeint newsize) { if (reallocfn) return reallocfn (ptr,oldsize,newsize); else return realloc (ptr,newsize); } void dFree (void *ptr, sizeint size) { if (!ptr) return; if (freefn) freefn (ptr,size); else free (ptr); } ode-0.16/ode/src/collision_kernel.h0000664000175200017520000002514613403272463014214 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* internal data structures and functions for collision detection. */ #ifndef _ODE_COLLISION_KERNEL_H_ #define _ODE_COLLISION_KERNEL_H_ #include #include #include #include "objects.h" #include "odetls.h" #include "common.h" //**************************************************************************** // constants and macros // mask for the number-of-contacts field in the dCollide() flags parameter #define NUMC_MASK (0xffff) #define IS_SPACE(geom) \ dIN_RANGE((geom)->type, dFirstSpaceClass, dLastSpaceClass + 1) #define CHECK_NOT_LOCKED(space) \ dUASSERT ((space) == NULL || (space)->lock_count == 0, \ "Invalid operation for locked space") //**************************************************************************** // geometry object base class // geom flags. // // GEOM_DIRTY means that the space data structures for this geom are // potentially not up to date. NOTE THAT all space parents of a dirty geom // are themselves dirty. this is an invariant that must be enforced. // // GEOM_AABB_BAD means that the cached AABB for this geom is not up to date. // note that GEOM_DIRTY does not imply GEOM_AABB_BAD, as the geom might // recalculate its own AABB but does not know how to update the space data // structures for the space it is in. but GEOM_AABB_BAD implies GEOM_DIRTY. // the valid combinations are: // 0 // GEOM_DIRTY // GEOM_DIRTY|GEOM_AABB_BAD // GEOM_DIRTY|GEOM_AABB_BAD|GEOM_POSR_BAD enum { GEOM_DIRTY = 1, // geom is 'dirty', i.e. position unknown GEOM_POSR_BAD = 2, // geom's final posr is not valid GEOM_AABB_BAD = 4, // geom's AABB is not valid GEOM_PLACEABLE = 8, // geom is placeable GEOM_ENABLED = 16, // geom is enabled GEOM_ZERO_SIZED = 32, // geom is zero sized GEOM_ENABLE_TEST_MASK = GEOM_ENABLED | GEOM_ZERO_SIZED, GEOM_ENABLE_TEST_VALUE = GEOM_ENABLED, // Ray specific RAY_FIRSTCONTACT = 0x10000, RAY_BACKFACECULL = 0x20000, RAY_CLOSEST_HIT = 0x40000 }; enum dxContactMergeOptions { DONT_MERGE_CONTACTS, MERGE_CONTACT_NORMALS, MERGE_CONTACTS_FULLY }; // geometry object base class. pos and R will either point to a separately // allocated buffer (if body is 0 - pos points to the dxPosR object) or to // the pos and R of the body (if body nonzero). // a dGeomID is a pointer to this object. struct dxGeom : public dBase { int type; // geom type number, set by subclass constructor int gflags; // flags used by geom and space void *data; // user-defined data pointer dBodyID body; // dynamics body associated with this object (if any) dxGeom *body_next; // next geom in body's linked list of associated geoms dxPosR *final_posr; // final position of the geom in world coordinates dxPosR *offset_posr; // offset from body in local coordinates // information used by spaces dxGeom *next; // next geom in linked list of geoms dxGeom **tome; // linked list backpointer dxGeom *next_ex; // next geom in extra linked list of geoms (for higher level structures) dxGeom **tome_ex; // extra linked list backpointer (for higher level structures) dxSpace *parent_space;// the space this geom is contained in, 0 if none dReal aabb[6]; // cached AABB for this space unsigned long category_bits,collide_bits; dxGeom (dSpaceID _space, int is_placeable); virtual ~dxGeom(); // Set or clear GEOM_ZERO_SIZED flag void updateZeroSizedFlag(bool is_zero_sized) { gflags = is_zero_sized ? (gflags | GEOM_ZERO_SIZED) : (gflags & ~GEOM_ZERO_SIZED); } // Get parent space TLS kind unsigned getParentSpaceTLSKind() const; const dVector3 &buildUpdatedPosition() { dIASSERT(gflags & GEOM_PLACEABLE); recomputePosr(); return final_posr->pos; } const dMatrix3 &buildUpdatedRotation() { dIASSERT(gflags & GEOM_PLACEABLE); recomputePosr(); return final_posr->R; } // recalculate our new final position if needed void recomputePosr() { if (gflags & GEOM_POSR_BAD) { computePosr(); gflags &= ~GEOM_POSR_BAD; } } // calculate our new final position from our offset and body void computePosr(); bool checkControlValueSizeValidity(void *dataValue, int *dataSize, int iRequiresSize) { return (*dataSize == iRequiresSize && dataValue != 0) ? true : !(*dataSize = iRequiresSize); } // Here it is the intent to return true for 0 required size in any case virtual bool controlGeometry(int controlClass, int controlCode, void *dataValue, int *dataSize); virtual void computeAABB()=0; // compute the AABB for this object and put it in aabb. this function // always performs a fresh computation, it does not inspect the // GEOM_AABB_BAD flag. virtual int AABBTest (dxGeom *o, dReal aabb[6]); // test whether the given AABB object intersects with this object, return // 1=yes, 0=no. this is used as an early-exit test in the space collision // functions. the default implementation returns 1, which is the correct // behavior if no more detailed implementation can be provided. // utility functions // compute the AABB only if it is not current. this function manipulates // the GEOM_AABB_BAD flag. void recomputeAABB() { if (gflags & GEOM_AABB_BAD) { // our aabb functions assume final_posr is up to date recomputePosr(); computeAABB(); gflags &= ~GEOM_AABB_BAD; } } inline void markAABBBad(); // add and remove this geom from a linked list maintained by a space. void spaceAdd (dxGeom **first_ptr) { next = *first_ptr; tome = first_ptr; if (*first_ptr) (*first_ptr)->tome = &next; *first_ptr = this; } void spaceRemove() { if (next) next->tome = tome; *tome = next; } // add and remove this geom from a linked list maintained by a body. void bodyAdd (dxBody *b) { body = b; body_next = b->geom; b->geom = this; } void bodyRemove(); }; //**************************************************************************** // the base space class // // the contained geoms are divided into two kinds: clean and dirty. // the clean geoms have not moved since they were put in the list, // and their AABBs are valid. the dirty geoms have changed position, and // their AABBs are may not be valid. the two types are distinguished by the // GEOM_DIRTY flag. all dirty geoms come *before* all clean geoms in the list. #if dTLS_ENABLED #define dSPACE_TLS_KIND_INIT_VALUE OTK__DEFAULT #define dSPACE_TLS_KIND_MANUAL_VALUE OTK_MANUALCLEANUP #else #define dSPACE_TLS_KIND_INIT_VALUE 0 #define dSPACE_TLS_KIND_MANUAL_VALUE 0 #endif struct dxSpace : public dxGeom { int count; // number of geoms in this space dxGeom *first; // first geom in list int cleanup; // cleanup mode, 1=destroy geoms on exit int sublevel; // space sublevel (used in dSpaceCollide2). NOT TRACKED AUTOMATICALLY!!! unsigned tls_kind; // space TLS kind to be used for global caches retrieval // cached state for getGeom() int current_index; // only valid if current_geom != 0 dxGeom *current_geom; // if 0 then there is no information // locking stuff. the space is locked when it is currently traversing its // internal data structures, e.g. in collide() and collide2(). operations // that modify the contents of the space are not permitted when the space // is locked. int lock_count; dxSpace (dSpaceID _space); ~dxSpace(); void computeAABB(); void setCleanup (int mode) { cleanup = (mode != 0); } int getCleanup() const { return cleanup; } void setSublevel(int value) { sublevel = value; } int getSublevel() const { return sublevel; } void setManulCleanup(int value) { tls_kind = (value ? dSPACE_TLS_KIND_MANUAL_VALUE : dSPACE_TLS_KIND_INIT_VALUE); } int getManualCleanup() const { return (tls_kind == dSPACE_TLS_KIND_MANUAL_VALUE) ? 1 : 0; } int query (dxGeom *geom) const { dAASSERT(geom); return (geom->parent_space == this); } int getNumGeoms() const { return count; } virtual dxGeom *getGeom (int i); virtual void add (dxGeom *); virtual void remove (dxGeom *); virtual void dirty (dxGeom *); virtual void cleanGeoms()=0; // turn all dirty geoms into clean geoms by computing their AABBs and any // other space data structures that are required. this should clear the // GEOM_DIRTY and GEOM_AABB_BAD flags of all geoms. virtual void collide (void *data, dNearCallback *callback)=0; virtual void collide2 (void *data, dxGeom *geom, dNearCallback *callback)=0; }; ////////////////////////////////////////////////////////////////////////// /*inline */ void dxGeom::markAABBBad() { gflags |= (GEOM_DIRTY | GEOM_AABB_BAD); CHECK_NOT_LOCKED(parent_space); } //**************************************************************************** // Initialization and finalization functions void dInitColliders(); void dFinitColliders(); void dClearPosrCache(void); void dFinitUserClasses(); #endif ode-0.16/ode/src/odeou.h0000664000175200017520000000670413403272463011773 00000000000000/************************************************************************* * * * OU library interface file for Open Dynamics Engine, * * Copyright (C) 2008 Oleh Derevenko. All rights reserved. * * Email: odar@eleks.com (change all "a" to "e") * * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* ODE interface to OU library functions. */ #ifndef _ODE_ODEOU_H_ #define _ODE_ODEOU_H_ #if dOU_ENABLED #include #include #include #include #include #include #include #if dATOMICS_ENABLED #include #include #endif #if dTLS_ENABLED #include #endif using _OU_NAMESPACE::CEnumUnsortedElementArray; using _OU_NAMESPACE::CEnumSortedElementArray; #if dATOMICS_ENABLED using _OU_NAMESPACE::atomicord32; using _OU_NAMESPACE::atomicptr; using _OU_NAMESPACE::InitializeAtomicAPI; using _OU_NAMESPACE::FinalizeAtomicAPI; using _OU_NAMESPACE::AtomicIncrement; using _OU_NAMESPACE::AtomicDecrement; using _OU_NAMESPACE::AtomicCompareExchange; using _OU_NAMESPACE::AtomicExchange; using _OU_NAMESPACE::AtomicExchangeAddNoResult; using _OU_NAMESPACE::AtomicExchangeAdd; using _OU_NAMESPACE::AtomicCompareExchangePointer; using _OU_NAMESPACE::AtomicExchangePointer; using _OU_NAMESPACE::AtomicReadReorderBarrier; using _OU_NAMESPACE::AtomicStore; using _OU_NAMESPACE::AtomicStorePointer; #endif class COdeOu { public: static bool DoOUCustomizations(); static void UndoOUCustomizations(); #if dATOMICS_ENABLED static bool InitializeAtomics() { return InitializeAtomicAPI(); } static void FinalizeAtomics() { FinalizeAtomicAPI(); } #endif }; #endif #if !dOU_ENABLED || !dATOMICS_ENABLED typedef unsigned int atomicord32; typedef void *atomicptr; #endif // dOU_ENABLED #endif // _ODE_ODEOU_H_ ode-0.16/ode/src/fastldltfactor_impl.h0000664000175200017520000016207113403272463014715 00000000000000 /************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* * Code style improvements and optimizations by Oleh Derevenko ????-2017 * LDLT cooperative factorization code of ThreadedEquationSolverLDLT copyright (c) 2017 Oleh Derevenko, odar@eleks.com (change all "a" to "e") */ #ifndef _ODE_FASTLDLT_IMPL_H_ #define _ODE_FASTLDLT_IMPL_H_ #include "error.h" #include "common.h" static void solveL1Stripe_2 (const dReal *L, dReal *B, unsigned rowCount, unsigned rowSkip); template void scaleAndFactorizeL1Stripe_2(dReal *ARow, dReal *d, unsigned rowIndex, unsigned rowSkip); template inline void scaleAndFactorizeL1FirstRowStripe_2(dReal *ARow, dReal *d, unsigned rowSkip); static void solveStripeL1_1 (const dReal *L, dReal *B, unsigned rowCount, unsigned rowSkip); template void scaleAndFactorizeL1Stripe_1(dReal *ARow, dReal *d, unsigned rowIndex); template inline void scaleAndFactorizeL1FirstRowStripe_1(dReal *ARow, dReal *d); template void factorMatrixAsLDLT(dReal *A, dReal *d, unsigned rowCount, unsigned rowSkip) { if (rowCount < 1) return; dReal *ARow = A; unsigned blockStartRow = 0; const unsigned blockStep = 2; const unsigned lastRowIndex = rowCount >= blockStep ? rowCount - blockStep + 1 : 0; /* compute blocks of 2 rows */ bool subsequentPass = false; for (; blockStartRow < lastRowIndex; subsequentPass = true, ARow += blockStep * rowSkip, blockStartRow += blockStep) { if (subsequentPass) { /* solve L*(D*l)=a, l is scaled elements in 2 x i block at A(i,0) */ solveL1Stripe_2(A, ARow, blockStartRow, rowSkip); scaleAndFactorizeL1Stripe_2(ARow, d, blockStartRow, rowSkip); } else { scaleAndFactorizeL1FirstRowStripe_2(ARow, d, rowSkip); } dSASSERT(blockStep == 2); /* done factorizing 2 x 2 block */ } /* compute the (less than 2) rows at the bottom */ if (!subsequentPass || blockStartRow == lastRowIndex) { dSASSERT(blockStep == 2); // for the blockStartRow == lastRowIndex comparison above if (subsequentPass) { solveStripeL1_1(A, ARow, blockStartRow, rowSkip); scaleAndFactorizeL1Stripe_1(ARow, d, blockStartRow); } else { scaleAndFactorizeL1FirstRowStripe_1(ARow, d); } dSASSERT(blockStep == 2); /* done factorizing 1 x 1 block */ } } /* solve L*X=B, with B containing 2 right hand sides. * L is an n*n lower triangular matrix with ones on the diagonal. * L is stored by rows and its leading dimension is rowSkip. * B is an n*2 matrix that contains the right hand sides. * B is stored by columns and its leading dimension is also rowSkip. * B is overwritten with X. * this processes blocks of 2*2. * if this is in the factorizer source file, n must be a multiple of 2. */ static void solveL1Stripe_2(const dReal *L, dReal *B, unsigned rowCount, unsigned rowSkip) { dIASSERT(rowCount != 0); dIASSERT(rowCount % 2 == 0); /* compute all 2 x 2 blocks of X */ unsigned blockStartRow = 0; for (bool exitLoop = false, subsequentPass = false; !exitLoop; subsequentPass = true, exitLoop = (blockStartRow += 2) == rowCount) { const dReal *ptrLElement; dReal *ptrBElement; /* declare variables - Z matrix */ dReal Z11, Z12, Z21, Z22; /* compute all 2 x 2 block of X, from rows i..i+2-1 */ if (subsequentPass) { ptrLElement = L + blockStartRow * rowSkip; ptrBElement = B; /* set Z matrix to 0 */ Z11 = 0; Z12 = 0; Z21 = 0; Z22 = 0; /* the inner loop that computes outer products and adds them to Z */ // The iteration starts with even number and decreases it by 2. So, it must end in zero for (unsigned columnCounter = blockStartRow; ;) { /* declare p and q vectors, etc */ dReal p1, q1, p2, q2; /* compute outer product and add it to the Z matrix */ p1 = ptrLElement[0]; q1 = ptrBElement[0]; Z11 += p1 * q1; q2 = ptrBElement[rowSkip]; Z12 += p1 * q2; p2 = ptrLElement[rowSkip]; Z21 += p2 * q1; Z22 += p2 * q2; /* compute outer product and add it to the Z matrix */ p1 = ptrLElement[1]; q1 = ptrBElement[1]; Z11 += p1 * q1; q2 = ptrBElement[1 + rowSkip]; Z12 += p1 * q2; p2 = ptrLElement[1 + rowSkip]; Z21 += p2 * q1; Z22 += p2 * q2; if (columnCounter > 6) { columnCounter -= 6; /* advance pointers */ ptrLElement += 6; ptrBElement += 6; /* compute outer product and add it to the Z matrix */ p1 = ptrLElement[-4]; q1 = ptrBElement[-4]; Z11 += p1 * q1; q2 = ptrBElement[-4 + rowSkip]; Z12 += p1 * q2; p2 = ptrLElement[-4 + rowSkip]; Z21 += p2 * q1; Z22 += p2 * q2; /* compute outer product and add it to the Z matrix */ p1 = ptrLElement[-3]; q1 = ptrBElement[-3]; Z11 += p1 * q1; q2 = ptrBElement[-3 + rowSkip]; Z12 += p1 * q2; p2 = ptrLElement[-3 + rowSkip]; Z21 += p2 * q1; Z22 += p2 * q2; /* compute outer product and add it to the Z matrix */ p1 = ptrLElement[-2]; q1 = ptrBElement[-2]; Z11 += p1 * q1; q2 = ptrBElement[-2 + rowSkip]; Z12 += p1 * q2; p2 = ptrLElement[-2 + rowSkip]; Z21 += p2 * q1; Z22 += p2 * q2; /* compute outer product and add it to the Z matrix */ p1 = ptrLElement[-1]; q1 = ptrBElement[-1]; Z11 += p1 * q1; q2 = ptrBElement[-1 + rowSkip]; Z12 += p1 * q2; p2 = ptrLElement[-1 + rowSkip]; Z21 += p2 * q1; Z22 += p2 * q2; } else { /* advance pointers */ ptrLElement += 2; ptrBElement += 2; if ((columnCounter -= 2) == 0) { break; } } /* end of inner loop */ } } else { ptrLElement = L/* + blockStartRow * rowSkip*/; dIASSERT(blockStartRow == 0); ptrBElement = B; /* set Z matrix to 0 */ Z11 = 0; Z12 = 0; Z21 = 0; Z22 = 0; } /* finish computing the X(i) block */ dReal Y11 = ptrBElement[0] - Z11; dReal Y12 = ptrBElement[rowSkip] - Z12; dReal p2 = ptrLElement[rowSkip]; ptrBElement[0] = Y11; ptrBElement[rowSkip] = Y12; dReal Y21 = ptrBElement[1] - Z21 - p2 * Y11; dReal Y22 = ptrBElement[1 + rowSkip] - Z22 - p2 * Y12; ptrBElement[1] = Y21; ptrBElement[1 + rowSkip] = Y22; /* end of outer loop */ } } template void scaleAndFactorizeL1Stripe_2(dReal *ARow, dReal *d, unsigned factorizationRow, unsigned rowSkip) { dIASSERT(factorizationRow != 0); dIASSERT(factorizationRow % 2 == 0); dReal *ptrAElement = ARow; dReal *ptrDElement = d; /* scale the elements in a 2 x i block at A(i,0), and also */ /* compute Z = the outer product matrix that we'll need. */ dReal Z11 = 0, Z21 = 0, Z22 = 0; for (unsigned columnCounter = factorizationRow; ; ) { dReal p1, q1, p2, q2, dd; p1 = ptrAElement[0]; p2 = ptrAElement[rowSkip]; dd = ptrDElement[0 * d_stride]; q1 = p1 * dd; q2 = p2 * dd; ptrAElement[0] = q1; ptrAElement[rowSkip] = q2; Z11 += p1 * q1; Z21 += p2 * q1; Z22 += p2 * q2; p1 = ptrAElement[1]; p2 = ptrAElement[1 + rowSkip]; dd = ptrDElement[1 * d_stride]; q1 = p1 * dd; q2 = p2 * dd; ptrAElement[1] = q1; ptrAElement[1 + rowSkip] = q2; Z11 += p1 * q1; Z21 += p2 * q1; Z22 += p2 * q2; if (columnCounter > 6) { columnCounter -= 6; ptrAElement += 6; ptrDElement += 6 * d_stride; p1 = ptrAElement[-4]; p2 = ptrAElement[-4 + rowSkip]; dd = ptrDElement[-4 * (int)d_stride]; q1 = p1 * dd; q2 = p2 * dd; ptrAElement[-4] = q1; ptrAElement[-4 + rowSkip] = q2; Z11 += p1 * q1; Z21 += p2 * q1; Z22 += p2 * q2; p1 = ptrAElement[-3]; p2 = ptrAElement[-3 + rowSkip]; dd = ptrDElement[-3 * (int)d_stride]; q1 = p1 * dd; q2 = p2 * dd; ptrAElement[-3] = q1; ptrAElement[-3 + rowSkip] = q2; Z11 += p1 * q1; Z21 += p2 * q1; Z22 += p2 * q2; p1 = ptrAElement[-2]; p2 = ptrAElement[-2 + rowSkip]; dd = ptrDElement[-2 * (int)d_stride]; q1 = p1 * dd; q2 = p2 * dd; ptrAElement[-2] = q1; ptrAElement[-2 + rowSkip] = q2; Z11 += p1 * q1; Z21 += p2 * q1; Z22 += p2 * q2; p1 = ptrAElement[-1]; p2 = ptrAElement[-1 + rowSkip]; dd = ptrDElement[-1 * (int)d_stride]; q1 = p1 * dd; q2 = p2 * dd; ptrAElement[-1] = q1; ptrAElement[-1 + rowSkip] = q2; Z11 += p1 * q1; Z21 += p2 * q1; Z22 += p2 * q2; } else { ptrAElement += 2; ptrDElement += 2 * d_stride; if ((columnCounter -= 2) == 0) { break; } } } /* solve for diagonal 2 x 2 block at A(i,i) */ dReal Y11 = ptrAElement[0] - Z11; dReal Y21 = ptrAElement[rowSkip] - Z21; dReal Y22 = ptrAElement[1 + rowSkip] - Z22; /* factorize 2 x 2 block Y, ptrDElement */ /* factorize row 1 */ dReal dd = dRecip(Y11); ptrDElement[0 * d_stride] = dd; dIASSERT(ptrDElement == d + (sizeint)factorizationRow * d_stride); /* factorize row 2 */ dReal q2 = Y21 * dd; ptrAElement[rowSkip] = q2; dReal sum = Y21 * q2; ptrDElement[1 * d_stride] = dRecip(Y22 - sum); } template void scaleAndFactorizeL1FirstRowStripe_2(dReal *ARow, dReal *d, unsigned rowSkip) { dReal *ptrAElement = ARow; dReal *ptrDElement = d; /* solve for diagonal 2 x 2 block at A(0,0) */ dReal Y11 = ptrAElement[0]/* - Z11*/; dReal Y21 = ptrAElement[rowSkip]/* - Z21*/; dReal Y22 = ptrAElement[1 + rowSkip]/* - Z22*/; /* factorize 2 x 2 block Y, ptrDElement */ /* factorize row 1 */ dReal dd = dRecip(Y11); ptrDElement[0 * d_stride] = dd; dIASSERT(ptrDElement == d/* + (sizeint)factorizationRow * d_stride*/); /* factorize row 2 */ dReal q2 = Y21 * dd; ptrAElement[rowSkip] = q2; dReal sum = Y21 * q2; ptrDElement[1 * d_stride] = dRecip(Y22 - sum); } /* solve L*X=B, with B containing 1 right hand sides. * L is an n*n lower triangular matrix with ones on the diagonal. * L is stored by rows and its leading dimension is lskip. * B is an n*1 matrix that contains the right hand sides. * B is stored by columns and its leading dimension is also lskip. * B is overwritten with X. * this processes blocks of 2*2. * if this is in the factorizer source file, n must be a multiple of 2. */ static void solveStripeL1_1(const dReal *L, dReal *B, unsigned rowCount, unsigned rowSkip) { dIASSERT(rowCount != 0); dIASSERT(rowCount % 2 == 0); /* compute all 2 x 1 blocks of X */ unsigned blockStartRow = 0; for (bool exitLoop = false, subsequentPass = false; !exitLoop; subsequentPass = true, exitLoop = (blockStartRow += 2) == rowCount) { const dReal *ptrLElement; dReal *ptrBElement; /* declare variables - Z matrix */ dReal Z11, Z21; if (subsequentPass) { ptrLElement = L + (sizeint)blockStartRow * rowSkip; ptrBElement = B; /* set the Z matrix to 0 */ Z11 = 0; Z21 = 0; /* compute all 2 x 1 block of X, from rows i..i+2-1 */ /* the inner loop that computes outer products and adds them to Z */ // The iteration starts with even number and decreases it by 2. So, it must end in zero for (unsigned columnCounter = blockStartRow; ; ) { /* declare p and q vectors, etc */ dReal p1, q1, p2; /* compute outer product and add it to the Z matrix */ p1 = ptrLElement[0]; q1 = ptrBElement[0]; Z11 += p1 * q1; p2 = ptrLElement[rowSkip]; Z21 += p2 * q1; /* compute outer product and add it to the Z matrix */ p1 = ptrLElement[1]; q1 = ptrBElement[1]; Z11 += p1 * q1; p2 = ptrLElement[1 + rowSkip]; Z21 += p2 * q1; if (columnCounter > 6) { columnCounter -= 6; /* advance pointers */ ptrLElement += 6; ptrBElement += 6; /* compute outer product and add it to the Z matrix */ p1 = ptrLElement[-4]; q1 = ptrBElement[-4]; Z11 += p1 * q1; p2 = ptrLElement[-4 + rowSkip]; Z21 += p2 * q1; /* compute outer product and add it to the Z matrix */ p1 = ptrLElement[-3]; q1 = ptrBElement[-3]; Z11 += p1 * q1; p2 = ptrLElement[-3 + rowSkip]; Z21 += p2 * q1; /* compute outer product and add it to the Z matrix */ p1 = ptrLElement[-2]; q1 = ptrBElement[-2]; Z11 += p1 * q1; p2 = ptrLElement[-2 + rowSkip]; Z21 += p2 * q1; /* compute outer product and add it to the Z matrix */ p1 = ptrLElement[-1]; q1 = ptrBElement[-1]; Z11 += p1 * q1; p2 = ptrLElement[-1 + rowSkip]; Z21 += p2 * q1; } else { /* advance pointers */ ptrLElement += 2; ptrBElement += 2; if ((columnCounter -= 2) == 0) { break; } } /* end of inner loop */ } } else { ptrLElement = L/* + (sizeint)blockStartRow * rowSkip*/; dIASSERT(blockStartRow == 0); ptrBElement = B; /* set the Z matrix to 0 */ Z11 = 0; Z21 = 0; } /* finish computing the X(i) block */ dReal p2 = ptrLElement[rowSkip]; dReal Y11 = ptrBElement[0] - Z11; dReal Y21 = ptrBElement[1] - Z21 - p2 * Y11; ptrBElement[0] = Y11; ptrBElement[1] = Y21; /* end of outer loop */ } } template void scaleAndFactorizeL1Stripe_1(dReal *ARow, dReal *d, unsigned factorizationRow) { dReal *ptrAElement = ARow; dReal *ptrDElement = d; /* scale the elements in a 1 x i block at A(i,0), and also */ /* compute Z = the outer product matrix that we'll need. */ dReal Z11 = 0, Z22 = 0; for (unsigned columnCounter = factorizationRow; ; ) { dReal p1, p2, q1, q2, dd1, dd2; p1 = ptrAElement[0]; p2 = ptrAElement[1]; dd1 = ptrDElement[0 * d_stride]; dd2 = ptrDElement[1 * d_stride]; q1 = p1 * dd1; q2 = p2 * dd2; ptrAElement[0] = q1; ptrAElement[1] = q2; Z11 += p1 * q1; Z22 += p2 * q2; if (columnCounter > 6) { columnCounter -= 6; ptrAElement += 6; ptrDElement += 6 * d_stride; p1 = ptrAElement[-4]; p2 = ptrAElement[-3]; dd1 = ptrDElement[-4 * (int)d_stride]; dd2 = ptrDElement[-3 * (int)d_stride]; q1 = p1 * dd1; q2 = p2 * dd2; ptrAElement[-4] = q1; ptrAElement[-3] = q2; Z11 += p1 * q1; Z22 += p2 * q2; p1 = ptrAElement[-2]; p2 = ptrAElement[-1]; dd1 = ptrDElement[-2 * (int)d_stride]; dd2 = ptrDElement[-1 * (int)d_stride]; q1 = p1 * dd1; q2 = p2 * dd2; ptrAElement[-2] = q1; ptrAElement[-1] = q2; Z11 += p1 * q1; Z22 += p2 * q2; } else { ptrAElement += 2; ptrDElement += 2 * d_stride; if ((columnCounter -= 2) == 0) { break; } } } dReal Y11 = ptrAElement[0] - (Z11 + Z22); /* solve for diagonal 1 x 1 block at A(i,i) */ dIASSERT(ptrDElement == d + (sizeint)factorizationRow * d_stride); /* factorize 1 x 1 block Y, ptrDElement */ /* factorize row 1 */ ptrDElement[0 * d_stride] = dRecip(Y11); } template void scaleAndFactorizeL1FirstRowStripe_1(dReal *ARow, dReal *d) { dReal *ptrAElement = ARow; dReal *ptrDElement = d; dReal Y11 = ptrAElement[0]; /* solve for diagonal 1 x 1 block at A(0,0) */ /* factorize 1 x 1 block Y, ptrDElement */ /* factorize row 1 */ ptrDElement[0 * d_stride] = dRecip(Y11); } template /*static */ void ThreadedEquationSolverLDLT::participateSolvingL1Stripe_X(const dReal *L, dReal *B, unsigned blockCount, unsigned rowSkip, volatile atomicord32 &refBlockCompletionProgress/*=0*/, volatile cellindexint *blockProgressDescriptors/*=[blockCount]*/, FactorizationSolveL1StripeCellContext *cellContexts/*=[CCI__MAX x blockCount] + [blockCount]*/, unsigned ownThreadIndex) { const unsigned lookaheadRange = 64; BlockProcessingState blockProcessingState = BPS_NO_BLOCKS_PROCESSED; unsigned completedBlocks = refBlockCompletionProgress; unsigned currentBlock = completedBlocks; dIASSERT(completedBlocks <= blockCount); for (bool exitLoop = completedBlocks == blockCount; !exitLoop; exitLoop = false) { bool goForLockedBlockPrimaryCalculation = false, goForLockedBlockDuplicateCalculation = false; bool goAssigningTheResult = false, stayWithinTheBlock = false; dReal Z[block_step][b_rows]; dReal Y[block_step][b_rows]; dReal *ptrBElement; CellContextInstance previousContextInstance; unsigned completedColumnBlock; for (cellindexint testDescriptor = blockProgressDescriptors[currentBlock]; ; ) { if (testDescriptor == INVALID_CELLDESCRIPTOR) { // Invalid descriptor is the indication that the row has been fully calculated // Test if this was the last row and break out if so. if (currentBlock + 1 == blockCount) { exitLoop = true; break; } // Treat detected row advancement as a row processed // blockProcessingState = BPS_SOME_BLOCKS_PROCESSED; <-- performs better without it break; } CooperativeAtomics::AtomicReadReorderBarrier(); // It is necessary to read up to date completedBblocks value after the descriptor retrieval // as otherwise the logic below breaks completedBlocks = refBlockCompletionProgress; if (!GET_CELLDESCRIPTOR_ISLOCKED(testDescriptor)) { completedColumnBlock = GET_CELLDESCRIPTOR_COLUMNINDEX(testDescriptor); dIASSERT(completedColumnBlock < currentBlock || (completedColumnBlock == currentBlock && currentBlock == 0)); // Otherwise, why would the calculation have had stopped if the final column is reachable??? dIASSERT(completedColumnBlock <= completedBlocks); // Since the descriptor is not locked if (completedColumnBlock == completedBlocks && currentBlock != completedBlocks) { dIASSERT(completedBlocks < currentBlock); break; } if (CooperativeAtomics::AtomicCompareExchangeCellindexint(&blockProgressDescriptors[currentBlock], testDescriptor, MARK_CELLDESCRIPTOR_LOCKED(testDescriptor))) { if (completedColumnBlock != 0) { CellContextInstance contextInstance = GET_CELLDESCRIPTOR_CONTEXTINSTANCE(testDescriptor); previousContextInstance = contextInstance; const FactorizationSolveL1StripeCellContext &sourceContext = buildBlockContextRef(cellContexts, currentBlock, contextInstance); sourceContext.loadPrecalculatedZs(Z); } else { previousContextInstance = CCI__MIN; FactorizationSolveL1StripeCellContext::initializePrecalculatedZs(Z); } goForLockedBlockPrimaryCalculation = true; break; } if (blockProcessingState != BPS_COMPETING_FOR_A_BLOCK) { break; } testDescriptor = blockProgressDescriptors[currentBlock]; } else { if (blockProcessingState != BPS_COMPETING_FOR_A_BLOCK) { break; } cellindexint verificativeDescriptor; bool verificationFailure = false; completedColumnBlock = GET_CELLDESCRIPTOR_COLUMNINDEX(testDescriptor); dIASSERT(completedColumnBlock != currentBlock || currentBlock == 0); // There is no reason for computations to stop at the very end other than being the initial value at the very first block if (completedColumnBlock != 0) { CellContextInstance contextInstance = GET_CELLDESCRIPTOR_CONTEXTINSTANCE(testDescriptor); const FactorizationSolveL1StripeCellContext &sourceContext = buildBlockContextRef(cellContexts, currentBlock, contextInstance); sourceContext.loadPrecalculatedZs(Z); } else { FactorizationSolveL1StripeCellContext::initializePrecalculatedZs(Z); } if (completedColumnBlock != 0 && completedColumnBlock <= currentBlock) { // Make sure the descriptor is re-read after the precalculates CooperativeAtomics::AtomicReadReorderBarrier(); } if (completedColumnBlock <= currentBlock) { verificativeDescriptor = blockProgressDescriptors[currentBlock]; verificationFailure = verificativeDescriptor != testDescriptor; } if (!verificationFailure) { dIASSERT(completedColumnBlock <= currentBlock + 1); goForLockedBlockDuplicateCalculation = true; break; } testDescriptor = verificativeDescriptor; } } if (exitLoop) { break; } if (goForLockedBlockPrimaryCalculation) { blockProcessingState = BPS_SOME_BLOCKS_PROCESSED; // Declare and assign the variables at the top to not interfere with any branching -- the compiler is going to eliminate them anyway. bool handleComputationTakenOver = false, rowEndReached = false; const dReal *ptrLElement; unsigned finalColumnBlock; if (currentBlock != 0) { /* compute all 2 x 2 block of X, from rows i..i+2-1 */ ptrLElement = L + (currentBlock * rowSkip + completedColumnBlock) * block_step; ptrBElement = B + completedColumnBlock * block_step; /* the inner loop that computes outer products and adds them to Z */ finalColumnBlock = dMACRO_MIN(currentBlock, completedBlocks); dIASSERT(completedColumnBlock != finalColumnBlock/* || currentBlock == 0*/); // The iteration starts with even number and decreases it by 2. So, it must end in zero for (unsigned columnCounter = finalColumnBlock - completedColumnBlock; ; ) { /* declare p and q vectors, etc */ dReal p[block_step], q[b_rows]; /* compute outer product and add it to the Z matrix */ p[0] = ptrLElement[0]; q[0] = ptrBElement[0]; Z[0][0] += p[0] * q[0]; if (b_rows >= 2) { q[1] = ptrBElement[rowSkip]; Z[0][1] += p[0] * q[1]; } p[1] = ptrLElement[rowSkip]; Z[1][0] += p[1] * q[0]; if (b_rows >= 2) { Z[1][1] += p[1] * q[1]; } /* compute outer product and add it to the Z matrix */ p[0] = ptrLElement[1]; q[0] = ptrBElement[1]; Z[0][0] += p[0] * q[0]; if (b_rows >= 2) { q[1] = ptrBElement[1 + rowSkip]; Z[0][1] += p[0] * q[1]; } p[1] = ptrLElement[1 + rowSkip]; Z[1][0] += p[1] * q[0]; if (b_rows >= 2) { Z[1][1] += p[1] * q[1]; } dSASSERT(block_step == 2); dSASSERT(b_rows >= 1 && b_rows <= 2); if (columnCounter > 2) { /* compute outer product and add it to the Z matrix */ p[0] = ptrLElement[2]; q[0] = ptrBElement[2]; Z[0][0] += p[0] * q[0]; if (b_rows >= 2) { q[1] = ptrBElement[2 + rowSkip]; Z[0][1] += p[0] * q[1]; } p[1] = ptrLElement[2 + rowSkip]; Z[1][0] += p[1] * q[0]; if (b_rows >= 2) { Z[1][1] += p[1] * q[1]; } /* compute outer product and add it to the Z matrix */ p[0] = ptrLElement[3]; q[0] = ptrBElement[3]; Z[0][0] += p[0] * q[0]; if (b_rows >= 2) { q[1] = ptrBElement[3 + rowSkip]; Z[0][1] += p[0] * q[1]; } p[1] = ptrLElement[3 + rowSkip]; Z[1][0] += p[1] * q[0]; if (b_rows >= 2) { Z[1][1] += p[1] * q[1]; } dSASSERT(block_step == 2); dSASSERT(b_rows >= 1 && b_rows <= 2); /* advance pointers */ ptrLElement += 2 * block_step; ptrBElement += 2 * block_step; columnCounter -= 2; } else { /* advance pointers */ ptrLElement += block_step; ptrBElement += block_step; /* end of inner loop */ if (--columnCounter == 0) { if (finalColumnBlock == currentBlock) { rowEndReached = true; break; } // Take a look if any more rows have been completed... completedBlocks = refBlockCompletionProgress; dIASSERT(completedBlocks >= finalColumnBlock); if (completedBlocks == finalColumnBlock) { break; } // ...continue if so. unsigned columnCompletedSoFar = finalColumnBlock; finalColumnBlock = dMACRO_MIN(currentBlock, completedBlocks); columnCounter = finalColumnBlock - columnCompletedSoFar; } } } } else { ptrLElement = L/* + (currentBlock * rowSkip + completedColumnBlock) * block_step*/; ptrBElement = B/* + completedColumnBlock * block_step*/; rowEndReached = true; } if (rowEndReached) { // Check whether there is still a need to proceed or if the computation has been taken over by another thread cellindexint oldDescriptor = MAKE_CELLDESCRIPTOR(completedColumnBlock, previousContextInstance, true); if (blockProgressDescriptors[currentBlock] == oldDescriptor) { /* finish computing the X(i) block */ Y[0][0] = ptrBElement[0] - Z[0][0]; if (b_rows >= 2) { Y[0][1] = ptrBElement[rowSkip] - Z[0][1]; } dReal p2 = ptrLElement[rowSkip]; Y[1][0] = ptrBElement[1] - Z[1][0] - p2 * Y[0][0]; if (b_rows >= 2) { Y[1][1] = ptrBElement[1 + rowSkip] - Z[1][1] - p2 * Y[0][1]; } dSASSERT(block_step == 2); dSASSERT(b_rows >= 1 && b_rows <= 2); // Use atomic memory barrier to make sure memory reads of ptrBElement[] and blockProgressDescriptors[] are not swapped CooperativeAtomics::AtomicReadReorderBarrier(); // The descriptor has not been altered yet - this means the ptrBElement[] values used above were not modified yet // and the computation result is valid. if (blockProgressDescriptors[currentBlock] == oldDescriptor) { // Assign the results to the result context (possibly in parallel with other threads // that could and ought to be assigning exactly the same values) FactorizationSolveL1StripeCellContext &resultContext = buildResultContextRef(cellContexts, currentBlock, blockCount); resultContext.storePrecalculatedZs(Y); // Assign the result assignment progress descriptor cellindexint newDescriptor = MAKE_CELLDESCRIPTOR(currentBlock + 1, CCI__MIN, true); CooperativeAtomics::AtomicCompareExchangeCellindexint(&blockProgressDescriptors[currentBlock], oldDescriptor, newDescriptor); // the result is to be ignored // Whether succeeded or not, the result is valid, so go on trying to assign it to the matrix goAssigningTheResult = true; } else { // Otherwise, go on competing for copying the results handleComputationTakenOver = true; } } else { handleComputationTakenOver = true; } } else { // If the final column has not been reached yet, store current values to the context. // Select the other context instance as the previous one might be read by other threads. CellContextInstance nextContextInstance = buildNextContextInstance(previousContextInstance); FactorizationSolveL1StripeCellContext &destinationContext = buildBlockContextRef(cellContexts, currentBlock, nextContextInstance); destinationContext.storePrecalculatedZs(Z); // Unlock the row until more columns can be used cellindexint oldDescriptor = MAKE_CELLDESCRIPTOR(completedColumnBlock, previousContextInstance, true); cellindexint newDescriptor = MAKE_CELLDESCRIPTOR(finalColumnBlock, nextContextInstance, false); // The descriptor might have been updated by a competing thread if (!CooperativeAtomics::AtomicCompareExchangeCellindexint(&blockProgressDescriptors[currentBlock], oldDescriptor, newDescriptor)) { // Adjust the ptrBElement to point to the result area... ptrBElement = B + currentBlock * block_step; // ...and go on handling the case handleComputationTakenOver = true; } } if (handleComputationTakenOver) { cellindexint existingDescriptor = blockProgressDescriptors[currentBlock]; // This can only happen if the row was (has become) the uppermost not fully completed one // and the competing thread is at final stage of calculation (i.e., it has reached the currentBlock column). if (existingDescriptor != INVALID_CELLDESCRIPTOR) { // If not fully completed this must be the final stage of the result assignment into the matrix dIASSERT(existingDescriptor == MAKE_CELLDESCRIPTOR(currentBlock + 1, CCI__MIN, true)); // Go on competing copying the result as anyway the block is the topmost not completed one // and since there was competition for it, there is no other work that can be done right now. const FactorizationSolveL1StripeCellContext &resultContext = buildResultContextRef(cellContexts, currentBlock, blockCount); resultContext.loadPrecalculatedZs(Y); goAssigningTheResult = true; } else { // everything is over -- just go handling next blocks } } } else if (goForLockedBlockDuplicateCalculation) { blockProcessingState = BPS_SOME_BLOCKS_PROCESSED; bool skipToHandlingSubsequentRows = false, skiptoCopyingResult = false; /* declare variables */ const dReal *ptrLElement; if (completedColumnBlock < currentBlock) { /* compute all 2 x 2 block of X, from rows i..i+2-1 */ ptrLElement = L + (currentBlock * rowSkip + completedColumnBlock) * block_step; ptrBElement = B + completedColumnBlock * block_step; /* the inner loop that computes outer products and adds them to Z */ // The iteration starts with even number and decreases it by 2. So, it must end in zero const unsigned finalColumnBlock = currentBlock; dIASSERT(currentBlock == completedBlocks); // Why would we be competing for a row otherwise? unsigned lastCompletedColumn = completedColumnBlock; unsigned columnCounter = finalColumnBlock - completedColumnBlock; for (bool exitInnerLoop = false; !exitInnerLoop; exitInnerLoop = --columnCounter == 0) { /* declare p and q vectors, etc */ dReal p[block_step], q[b_rows]; /* compute outer product and add it to the Z matrix */ p[0] = ptrLElement[0]; q[0] = ptrBElement[0]; Z[0][0] += p[0] * q[0]; if (b_rows >= 2) { q[1] = ptrBElement[rowSkip]; Z[0][1] += p[0] * q[1]; } p[1] = ptrLElement[rowSkip]; Z[1][0] += p[1] * q[0]; if (b_rows >= 2) { Z[1][1] += p[1] * q[1]; } /* compute outer product and add it to the Z matrix */ p[0] = ptrLElement[1]; q[0] = ptrBElement[1]; Z[0][0] += p[0] * q[0]; if (b_rows >= 2) { q[1] = ptrBElement[1 + rowSkip]; Z[0][1] += p[0] * q[1]; } p[1] = ptrLElement[1 + rowSkip]; Z[1][0] += p[1] * q[0]; if (b_rows >= 2) { Z[1][1] += p[1] * q[1]; } dSASSERT(block_step == 2); dSASSERT(b_rows >= 1 && b_rows <= 2); // Check if the primary solver thread has not made any progress cellindexint descriptorVerification = blockProgressDescriptors[currentBlock]; unsigned newCompletedColumn = GET_CELLDESCRIPTOR_COLUMNINDEX(descriptorVerification); if (newCompletedColumn != lastCompletedColumn) { // Check, this is the first change the current thread detects. // There is absolutely no reason in code for the computation to stop/resume twice // while the current thread is competing. dIASSERT(lastCompletedColumn == completedColumnBlock); if (descriptorVerification == INVALID_CELLDESCRIPTOR) { skipToHandlingSubsequentRows = true; break; } if (newCompletedColumn == currentBlock + 1) { skiptoCopyingResult = true; break; } // Check if the current thread is behind if (newCompletedColumn > finalColumnBlock - columnCounter) { // If so, go starting over one more time blockProcessingState = BPS_COMPETING_FOR_A_BLOCK; stayWithinTheBlock = true; skipToHandlingSubsequentRows = true; break; } // If current thread is ahead, just save new completed column for further comparisons and go on calculating lastCompletedColumn = newCompletedColumn; } /* advance pointers */ ptrLElement += block_step; ptrBElement += block_step; /* end of inner loop */ } } else if (completedColumnBlock > currentBlock) { dIASSERT(completedColumnBlock == currentBlock + 1); skiptoCopyingResult = true; } else { dIASSERT(currentBlock == 0); // Execution can get here within the very first block only /* assign the pointers appropriately and go on computing the results */ ptrLElement = L/* + (currentBlock * rowSkip + completedColumnBlock) * block_step*/; ptrBElement = B/* + completedColumnBlock * block_step*/; } if (!skipToHandlingSubsequentRows) { if (!skiptoCopyingResult) { /* finish computing the X(i) block */ Y[0][0] = ptrBElement[0] - Z[0][0]; if (b_rows >= 2) { Y[0][1] = ptrBElement[rowSkip] - Z[0][1]; } dReal p2 = ptrLElement[rowSkip]; Y[1][0] = ptrBElement[1] - Z[1][0] - p2 * Y[0][0]; if (b_rows >= 2) { Y[1][1] = ptrBElement[1 + rowSkip] - Z[1][1] - p2 * Y[0][1]; } dSASSERT(block_step == 2); dSASSERT(b_rows >= 1 && b_rows <= 2); // Use atomic memory barrier to make sure memory reads of ptrBElement[] and blockProgressDescriptors[] are not swapped CooperativeAtomics::AtomicReadReorderBarrier(); cellindexint existingDescriptor = blockProgressDescriptors[currentBlock]; if (existingDescriptor == INVALID_CELLDESCRIPTOR) { // Everything is over -- proceed to subsequent rows skipToHandlingSubsequentRows = true; } else if (existingDescriptor == MAKE_CELLDESCRIPTOR(currentBlock + 1, CCI__MIN, true)) { // The values computed above may not be valid. Copy the values already in the result context. skiptoCopyingResult = true; } else { // The descriptor has not been altered yet - this means the ptrBElement[] values used above were not modified yet // and the computation result is valid. cellindexint newDescriptor = MAKE_CELLDESCRIPTOR(currentBlock + 1, CCI__MIN, true); // put the computation at the top so that the evaluation result from the expression above is reused // Assign the results to the result context (possibly in parallel with other threads // that could and ought to be assigning exactly the same values) FactorizationSolveL1StripeCellContext &resultContext = buildResultContextRef(cellContexts, currentBlock, blockCount); resultContext.storePrecalculatedZs(Y); // Assign the result assignment progress descriptor CooperativeAtomics::AtomicCompareExchangeCellindexint(&blockProgressDescriptors[currentBlock], existingDescriptor, newDescriptor); // the result is to be ignored // Whether succeeded or not, the result is valid, so go on trying to assign it to the matrix } } if (!skipToHandlingSubsequentRows) { if (skiptoCopyingResult) { // Extract the result values stored in the result context const FactorizationSolveL1StripeCellContext &resultContext = buildResultContextRef(cellContexts, currentBlock, blockCount); resultContext.loadPrecalculatedZs(Y); ptrBElement = B + currentBlock * block_step; } goAssigningTheResult = true; } } } if (goAssigningTheResult) { cellindexint existingDescriptor = blockProgressDescriptors[currentBlock]; // Check if the assignment has not been completed yet if (existingDescriptor != INVALID_CELLDESCRIPTOR) { // Assign the computation results to their places in the matrix ptrBElement[0] = Y[0][0]; ptrBElement[1] = Y[1][0]; if (b_rows >= 2) { ptrBElement[rowSkip] = Y[0][1]; ptrBElement[1 + rowSkip] = Y[1][1]; } dSASSERT(block_step == 2); dSASSERT(b_rows >= 1 && b_rows <= 2); ThrsafeIncrementIntUpToLimit(&refBlockCompletionProgress, currentBlock + 1); dIASSERT(refBlockCompletionProgress >= currentBlock + 1); // And assign the completed status no matter what CooperativeAtomics::AtomicStoreCellindexint(&blockProgressDescriptors[currentBlock], INVALID_CELLDESCRIPTOR); } else { // everything is over -- just go handling next blocks } } if (!stayWithinTheBlock) { completedBlocks = refBlockCompletionProgress; if (completedBlocks == blockCount) { break; } currentBlock += 1; bool lookaheadBoundaryReached = false; if (currentBlock == blockCount || completedBlocks == 0) { lookaheadBoundaryReached = true; } else if (currentBlock >= completedBlocks + lookaheadRange) { lookaheadBoundaryReached = blockProcessingState > BPS_NO_BLOCKS_PROCESSED; } else if (currentBlock < completedBlocks) { // Treat detected row advancement as a row processed // blockProcessingState = BPS_SOME_BLOCKS_PROCESSED; <-- performs better without it currentBlock = completedBlocks; } if (lookaheadBoundaryReached) { dIASSERT(blockProcessingState != BPS_COMPETING_FOR_A_BLOCK); // Why did not we compete??? // If no row has been processed in the previous pass, compete for the next row to avoid cycling uselessly if (blockProcessingState <= BPS_NO_BLOCKS_PROCESSED) { // Abandon job if too few blocks remain if (blockCount - completedBlocks <= ownThreadIndex) { break; } blockProcessingState = BPS_COMPETING_FOR_A_BLOCK; } else { // If there was some progress, just continue to the next pass blockProcessingState = BPS_NO_BLOCKS_PROCESSED; } currentBlock = completedBlocks; } } } } template /*static */ void ThreadedEquationSolverLDLT::participateScalingAndFactorizingL1Stripe_X(dReal *ARow, dReal *d, unsigned factorizationRow, unsigned rowSkip, FactorizationFactorizeL1StripeContext *factorizationContext, unsigned ownThreadIndex) { dIASSERT(factorizationRow != 0); dIASSERT(factorizationRow % 2 == 0); /* scale the elements in a 2 x i block at A(i,0), and also */ /* compute Z = the outer product matrix that we'll need. */ dReal sameZ[a_rows] = { REAL(0.0), }, mixedZ[dMACRO_MAX(a_rows - 1, 1)] = { REAL(0.0), }; bool doneAnything = false; const unsigned blockSize = deriveScalingAndFactorizingL1StripeBlockSize(a_rows); const unsigned blockCount = deriveScalingAndFactorizingL1StripeBlockCountFromFactorizationRow(factorizationRow, blockSize); dIASSERT(blockCount != 0); unsigned blockIndex; while ((blockIndex = ThrsafeIncrementIntUpToLimit(&factorizationContext->m_nextColumnIndex, blockCount)) != blockCount) { doneAnything = true; unsigned blockStartRow = blockIndex * blockSize; dReal *ptrAElement = ARow + blockStartRow; dReal *ptrDElement = d + blockStartRow * d_stride; for (unsigned columnCounter = blockIndex != blockCount - 1 ? blockSize : factorizationRow - blockStartRow; ; ) { dReal p1, q1, p2, q2, dd; p1 = ptrAElement[0]; if (a_rows >= 2) { p2 = ptrAElement[rowSkip]; } dd = ptrDElement[0 * d_stride]; q1 = p1 * dd; if (a_rows >= 2) { q2 = p2 * dd; } ptrAElement[0] = q1; if (a_rows >= 2) { ptrAElement[rowSkip] = q2; } sameZ[0] += p1 * q1; if (a_rows >= 2) { sameZ[1] += p2 * q2; mixedZ[0] += p2 * q1; } p1 = ptrAElement[1]; if (a_rows >= 2) { p2 = ptrAElement[1 + rowSkip]; } dd = ptrDElement[1 * d_stride]; q1 = p1 * dd; if (a_rows >= 2) { q2 = p2 * dd; } ptrAElement[1] = q1; if (a_rows >= 2) { ptrAElement[1 + rowSkip] = q2; } sameZ[0] += p1 * q1; if (a_rows >= 2) { sameZ[1] += p2 * q2; mixedZ[0] += p2 * q1; } if (columnCounter > 6) { columnCounter -= 6; ptrAElement += 6; ptrDElement += 6 * d_stride; p1 = ptrAElement[-4]; if (a_rows >= 2) { p2 = ptrAElement[-4 + rowSkip]; } dd = ptrDElement[-4 * (int)d_stride]; q1 = p1 * dd; if (a_rows >= 2) { q2 = p2 * dd; } ptrAElement[-4] = q1; if (a_rows >= 2) { ptrAElement[-4 + rowSkip] = q2; } sameZ[0] += p1 * q1; if (a_rows >= 2) { sameZ[1] += p2 * q2; mixedZ[0] += p2 * q1; } p1 = ptrAElement[-3]; if (a_rows >= 2) { p2 = ptrAElement[-3 + rowSkip]; } dd = ptrDElement[-3 * (int)d_stride]; q1 = p1 * dd; if (a_rows >= 2) { q2 = p2 * dd; } ptrAElement[-3] = q1; if (a_rows >= 2) { ptrAElement[-3 + rowSkip] = q2; } sameZ[0] += p1 * q1; if (a_rows >= 2) { sameZ[1] += p2 * q2; mixedZ[0] += p2 * q1; } p1 = ptrAElement[-2]; if (a_rows >= 2) { p2 = ptrAElement[-2 + rowSkip]; } dd = ptrDElement[-2 * (int)d_stride]; q1 = p1 * dd; if (a_rows >= 2) { q2 = p2 * dd; } ptrAElement[-2] = q1; if (a_rows >= 2) { ptrAElement[-2 + rowSkip] = q2; } sameZ[0] += p1 * q1; if (a_rows >= 2) { sameZ[1] += p2 * q2; mixedZ[0] += p2 * q1; } p1 = ptrAElement[-1]; if (a_rows >= 2) { p2 = ptrAElement[-1 + rowSkip]; } dd = ptrDElement[-1 * (int)d_stride]; q1 = p1 * dd; if (a_rows >= 2) { q2 = p2 * dd; } ptrAElement[-1] = q1; if (a_rows >= 2) { ptrAElement[-1 + rowSkip] = q2; } sameZ[0] += p1 * q1; if (a_rows >= 2) { sameZ[1] += p2 * q2; mixedZ[0] += p2 * q1; } } else { ptrAElement += 2; ptrDElement += 2 * d_stride; if ((columnCounter -= 2) == 0) { break; } } } } if (doneAnything) { unsigned partialSumThreadIndex; for (bool exitLoop = false; !exitLoop; exitLoop = CooperativeAtomics::AtomicCompareExchangeUint32(&factorizationContext->m_sumThreadIndex, partialSumThreadIndex, ownThreadIndex + 1)) { partialSumThreadIndex = factorizationContext->m_sumThreadIndex; if (partialSumThreadIndex != 0) { const FactorizationFactorizeL1StripeThreadContext &partialSumContext = factorizationContext->m_threadContexts[partialSumThreadIndex - 1]; factorizationContext->m_threadContexts[ownThreadIndex].assignDataSum(sameZ, mixedZ, partialSumContext); } else { factorizationContext->m_threadContexts[ownThreadIndex].assignDataAlone(sameZ, mixedZ); } } } unsigned threadExitIndex = CooperativeAtomics::AtomicDecrementUint32(&factorizationContext->m_threadsRunning); dIASSERT(threadExitIndex + 1U != 0); if (threadExitIndex == 0) { // Let the last thread retrieve the sum and perform final computations unsigned sumThreadIndex = factorizationContext->m_sumThreadIndex; dIASSERT(sumThreadIndex != 0); // The rowIndex was asserted to be not zero, so at least one thread must have done something const FactorizationFactorizeL1StripeThreadContext &sumContext = factorizationContext->m_threadContexts[sumThreadIndex - 1]; sumContext.retrieveData(sameZ, mixedZ); dReal *ptrAElement = ARow + factorizationRow; dReal *ptrDElement = d + factorizationRow * d_stride; /* solve for diagonal 2 x 2 block at A(i,i) */ dReal Y11, Y21, Y22; Y11 = ptrAElement[0] - sameZ[0]; if (a_rows >= 2) { Y21 = ptrAElement[rowSkip] - mixedZ[0]; Y22 = ptrAElement[1 + rowSkip] - sameZ[1]; } /* factorize 2 x 2 block Y, ptrDElement */ /* factorize row 1 */ dReal dd = dRecip(Y11); ptrDElement[0 * d_stride] = dd; dIASSERT(ptrDElement == d + (sizeint)factorizationRow * d_stride); if (a_rows >= 2) { /* factorize row 2 */ dReal q2 = Y21 * dd; ptrAElement[rowSkip] = q2; dReal sum = Y21 * q2; ptrDElement[1 * d_stride] = dRecip(Y22 - sum); } } } #endif // #ifndef _ODE_FASTLDLT_IMPL_H_ ode-0.16/ode/src/collision_kernel.cpp0000664000175200017520000010237313403272463014545 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* core collision functions and data structures, plus part of the public API for geometry objects */ #include #include #include #include "config.h" #include "matrix.h" #include "odemath.h" #include "collision_kernel.h" #include "collision_util.h" #include "collision_std.h" #include "collision_transform.h" #include "collision_trimesh_internal.h" #include "collision_space_internal.h" #include "odeou.h" #ifdef dLIBCCD_ENABLED # include "collision_libccd.h" #endif /* dLIBCCD_ENABLED */ #ifdef _MSC_VER #pragma warning(disable:4291) // for VC++, no complaints about "no matching operator delete found" #endif //**************************************************************************** // helper functions for dCollide()ing a space with another geom // this struct records the parameters passed to dCollideSpaceGeom() #if dATOMICS_ENABLED static volatile atomicptr s_cachedPosR = 0; // dxPosR * #endif // dATOMICS_ENABLED static inline dxPosR* dAllocPosr() { dxPosR *retPosR; #if dATOMICS_ENABLED retPosR = (dxPosR *)AtomicExchangePointer(&s_cachedPosR, NULL); if (!retPosR) #endif { retPosR = (dxPosR*) dAlloc (sizeof(dxPosR)); } return retPosR; } static inline void dFreePosr(dxPosR *oldPosR) { #if dATOMICS_ENABLED if (!AtomicCompareExchangePointer(&s_cachedPosR, NULL, (atomicptr)oldPosR)) #endif { dFree(oldPosR, sizeof(dxPosR)); } } /*extern */void dClearPosrCache(void) { #if dATOMICS_ENABLED // No threads should be accessing ODE at this time already, // hence variable may be read directly. dxPosR *existingPosR = (dxPosR *)s_cachedPosR; if (existingPosR) { dFree(existingPosR, sizeof(dxPosR)); s_cachedPosR = 0; } #endif } struct SpaceGeomColliderData { int flags; // space left in contacts array dContactGeom *contact; int skip; }; static void space_geom_collider (void *data, dxGeom *o1, dxGeom *o2) { SpaceGeomColliderData *d = (SpaceGeomColliderData*) data; if (d->flags & NUMC_MASK) { int n = dCollide (o1,o2,d->flags,d->contact,d->skip); d->contact = CONTACT (d->contact,d->skip*n); d->flags -= n; } } static int dCollideSpaceGeom (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) { SpaceGeomColliderData data; data.flags = flags; data.contact = contact; data.skip = skip; dSpaceCollide2 (o1,o2,&data,&space_geom_collider); return (flags & NUMC_MASK) - (data.flags & NUMC_MASK); } //**************************************************************************** // dispatcher for the N^2 collider functions // function pointers and modes for n^2 class collider functions struct dColliderEntry { dColliderFn *fn; // collider function, 0 = no function available int reverse; // 1 = reverse o1 and o2 }; static dColliderEntry colliders[dGeomNumClasses][dGeomNumClasses]; static int colliders_initialized = 0; // setCollider() will refuse to write over a collider entry once it has // been written. static void setCollider (int i, int j, dColliderFn *fn) { if (colliders[i][j].fn == 0) { colliders[i][j].fn = fn; colliders[i][j].reverse = 0; } if (colliders[j][i].fn == 0) { colliders[j][i].fn = fn; colliders[j][i].reverse = 1; } } static void setAllColliders (int i, dColliderFn *fn) { for (int j=0; j Convex Collision #ifdef dLIBCCD_CONVEX_BOX setCollider (dConvexClass, dBoxClass, &dCollideConvexBoxCCD); #else setCollider (dConvexClass,dBoxClass,&dCollideConvexBox); #endif #ifdef dLIBCCD_CONVEX_CAP setCollider (dConvexClass,dCapsuleClass,&dCollideConvexCapsuleCCD); #else setCollider (dConvexClass,dCapsuleClass,&dCollideConvexCapsule); #endif #ifdef dLIBCCD_CONVEX_CYL setCollider (dConvexClass,dCylinderClass,&dCollideConvexCylinderCCD); #endif #ifdef dLIBCCD_CONVEX_SPHERE setCollider (dConvexClass,dSphereClass,&dCollideConvexSphereCCD); #else setCollider (dSphereClass,dConvexClass,&dCollideSphereConvex); #endif #ifdef dLIBCCD_CONVEX_CONVEX setCollider (dConvexClass,dConvexClass,&dCollideConvexConvexCCD); #else setCollider (dConvexClass,dConvexClass,&dCollideConvexConvex); #endif setCollider (dConvexClass,dPlaneClass,&dCollideConvexPlane); setCollider (dRayClass,dConvexClass,&dCollideRayConvex); //<-- Convex Collision //--> dHeightfield Collision setCollider (dHeightfieldClass,dRayClass,&dCollideHeightfield); setCollider (dHeightfieldClass,dSphereClass,&dCollideHeightfield); setCollider (dHeightfieldClass,dBoxClass,&dCollideHeightfield); setCollider (dHeightfieldClass,dCapsuleClass,&dCollideHeightfield); setCollider (dHeightfieldClass,dCylinderClass,&dCollideHeightfield); setCollider (dHeightfieldClass,dConvexClass,&dCollideHeightfield); #if dTRIMESH_ENABLED setCollider (dHeightfieldClass,dTriMeshClass,&dCollideHeightfield); #endif //<-- dHeightfield Collision setAllColliders (dGeomTransformClass,&dCollideTransform); } /*extern */void dFinitColliders() { colliders_initialized = 0; } void dSetColliderOverride (int i, int j, dColliderFn *fn) { dIASSERT( colliders_initialized ); dAASSERT( i < dGeomNumClasses ); dAASSERT( j < dGeomNumClasses ); colliders[i][j].fn = fn; colliders[i][j].reverse = 0; colliders[j][i].fn = fn; colliders[j][i].reverse = 1; } /* * NOTE! * If it is necessary to add special processing mode without contact generation * use NULL contact parameter value as indicator, not zero in flags. */ int dCollide (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) { dAASSERT(o1 && o2 && contact); dUASSERT(colliders_initialized,"Please call ODE initialization (dInitODE() or similar) before using the library"); dUASSERT(o1->type >= 0 && o1->type < dGeomNumClasses,"bad o1 class number"); dUASSERT(o2->type >= 0 && o2->type < dGeomNumClasses,"bad o2 class number"); // Even though comparison for greater or equal to one is used in all the // other places, here it is more logical to check for greater than zero // because function does not require any specific number of contact slots - // it must be just a positive. dUASSERT((flags & NUMC_MASK) > 0, "no contacts requested"); // Extra precaution for zero contact count in parameters if ((flags & NUMC_MASK) == 0) return 0; // no contacts if both geoms are the same if (o1 == o2) return 0; // no contacts if both geoms on the same body, and the body is not 0 if (o1->body == o2->body && o1->body) return 0; o1->recomputePosr(); o2->recomputePosr(); dColliderEntry *ce = &colliders[o1->type][o2->type]; int count = 0; if (ce->fn) { if (ce->reverse) { count = (*ce->fn) (o2,o1,flags,contact,skip); for (int i=0; inormal[0] = -c->normal[0]; c->normal[1] = -c->normal[1]; c->normal[2] = -c->normal[2]; dxGeom *tmp = c->g1; c->g1 = c->g2; c->g2 = tmp; int tmpint = c->side1; c->side1 = c->side2; c->side2 = tmpint; } } else { count = (*ce->fn) (o1,o2,flags,contact,skip); } } return count; } //**************************************************************************** // dxGeom dxGeom::dxGeom (dSpaceID _space, int is_placeable) { // setup body vars. invalid type of -1 must be changed by the constructor. type = -1; gflags = GEOM_DIRTY | GEOM_AABB_BAD | GEOM_ENABLED; if (is_placeable) gflags |= GEOM_PLACEABLE; data = 0; body = 0; body_next = 0; if (is_placeable) { final_posr = dAllocPosr(); dSetZero (final_posr->pos,4); dRSetIdentity (final_posr->R); } else { final_posr = 0; } offset_posr = 0; // setup space vars next = 0; tome = 0; next_ex = 0; tome_ex = 0; parent_space = 0; dSetZero (aabb,6); category_bits = ~0; collide_bits = ~0; // put this geom in a space if required if (_space) dSpaceAdd (_space,this); } dxGeom::~dxGeom() { if (parent_space) dSpaceRemove (parent_space,this); if ((gflags & GEOM_PLACEABLE) && (!body || (body && offset_posr))) dFreePosr(final_posr); if (offset_posr) dFreePosr(offset_posr); bodyRemove(); } unsigned dxGeom::getParentSpaceTLSKind() const { return parent_space ? parent_space->tls_kind : dSPACE_TLS_KIND_INIT_VALUE; } int dxGeom::AABBTest (dxGeom *, dReal [6]) { return 1; } void dxGeom::bodyRemove() { if (body) { // delete this geom from body list dxGeom **last = &body->geom, *g = body->geom; while (g) { if (g == this) { *last = g->body_next; break; } last = &g->body_next; g = g->body_next; } body = 0; body_next = 0; } } inline void myswap(dReal& a, dReal& b) { dReal t=b; b=a; a=t; } inline void matrixInvert(const dMatrix3& inMat, dMatrix3& outMat) { memcpy(outMat, inMat, sizeof(dMatrix3)); // swap _12 and _21 myswap(outMat[0 + 4*1], outMat[1 + 4*0]); // swap _31 and _13 myswap(outMat[2 + 4*0], outMat[0 + 4*2]); // swap _23 and _32 myswap(outMat[1 + 4*2], outMat[2 + 4*1]); } void getBodyPosr(const dxPosR& offset_posr, const dxPosR& final_posr, dxPosR& body_posr) { dMatrix3 inv_offset; matrixInvert(offset_posr.R, inv_offset); dMultiply0_333(body_posr.R, final_posr.R, inv_offset); dVector3 world_offset; dMultiply0_331(world_offset, body_posr.R, offset_posr.pos); body_posr.pos[0] = final_posr.pos[0] - world_offset[0]; body_posr.pos[1] = final_posr.pos[1] - world_offset[1]; body_posr.pos[2] = final_posr.pos[2] - world_offset[2]; } void getWorldOffsetPosr(const dxPosR& body_posr, const dxPosR& world_posr, dxPosR& offset_posr) { dMatrix3 inv_body; matrixInvert(body_posr.R, inv_body); dMultiply0_333(offset_posr.R, inv_body, world_posr.R); dVector3 world_offset; world_offset[0] = world_posr.pos[0] - body_posr.pos[0]; world_offset[1] = world_posr.pos[1] - body_posr.pos[1]; world_offset[2] = world_posr.pos[2] - body_posr.pos[2]; dMultiply0_331(offset_posr.pos, inv_body, world_offset); } void dxGeom::computePosr() { // should only be recalced if we need to - ie offset from a body dIASSERT(offset_posr); dIASSERT(body); dMultiply0_331 (final_posr->pos,body->posr.R,offset_posr->pos); final_posr->pos[0] += body->posr.pos[0]; final_posr->pos[1] += body->posr.pos[1]; final_posr->pos[2] += body->posr.pos[2]; dMultiply0_333 (final_posr->R,body->posr.R,offset_posr->R); } bool dxGeom::controlGeometry(int /*controlClass*/, int /*controlCode*/, void * /*dataValue*/, int *dataSize) { dAASSERT(false && "Control class/code is not supported for current geom"); *dataSize = 0; return false; } //**************************************************************************** // misc dxGeom *dGeomGetBodyNext (dxGeom *geom) { return geom->body_next; } //**************************************************************************** // public API for geometry objects void dGeomDestroy (dxGeom *g) { dAASSERT (g); delete g; } void dGeomSetData (dxGeom *g, void *data) { dAASSERT (g); g->data = data; } void *dGeomGetData (dxGeom *g) { dAASSERT (g); return g->data; } void dGeomSetBody (dxGeom *g, dxBody *b) { dAASSERT (g); dUASSERT (b == NULL || (g->gflags & GEOM_PLACEABLE),"geom must be placeable"); CHECK_NOT_LOCKED (g->parent_space); if (b) { if (!g->body) dFreePosr(g->final_posr); if (g->body != b) { if (g->offset_posr) { dFreePosr(g->offset_posr); g->offset_posr = 0; } g->final_posr = &b->posr; g->bodyRemove(); g->bodyAdd (b); } dGeomMoved (g); } else { if (g->body) { if (g->offset_posr) { // if we're offset, we already have our own final position, make sure its updated g->recomputePosr(); dFreePosr(g->offset_posr); g->offset_posr = 0; } else { g->final_posr = dAllocPosr(); memcpy (g->final_posr->pos,g->body->posr.pos,sizeof(dVector3)); memcpy (g->final_posr->R,g->body->posr.R,sizeof(dMatrix3)); } g->bodyRemove(); } // dGeomMoved() should not be called if the body is being set to 0, as the // new position of the geom is set to the old position of the body, so the // effective position of the geom remains unchanged. } } dBodyID dGeomGetBody (dxGeom *g) { dAASSERT (g); return g->body; } void dGeomSetPosition (dxGeom *g, dReal x, dReal y, dReal z) { dAASSERT (g); dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable"); CHECK_NOT_LOCKED (g->parent_space); if (g->offset_posr) { // move body such that body+offset = position dVector3 world_offset; dMultiply0_331(world_offset, g->body->posr.R, g->offset_posr->pos); dBodySetPosition(g->body, x - world_offset[0], y - world_offset[1], z - world_offset[2]); } else if (g->body) { // this will call dGeomMoved (g), so we don't have to dBodySetPosition (g->body,x,y,z); } else { g->final_posr->pos[0] = x; g->final_posr->pos[1] = y; g->final_posr->pos[2] = z; dGeomMoved (g); } } void dGeomSetRotation (dxGeom *g, const dMatrix3 R) { dAASSERT (g && R); dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable"); CHECK_NOT_LOCKED (g->parent_space); if (g->offset_posr) { g->recomputePosr(); // move body such that body+offset = rotation dxPosR new_final_posr; dxPosR new_body_posr; memcpy(new_final_posr.pos, g->final_posr->pos, sizeof(dVector3)); memcpy(new_final_posr.R, R, sizeof(dMatrix3)); getBodyPosr(*g->offset_posr, new_final_posr, new_body_posr); dBodySetRotation(g->body, new_body_posr.R); dBodySetPosition(g->body, new_body_posr.pos[0], new_body_posr.pos[1], new_body_posr.pos[2]); } else if (g->body) { // this will call dGeomMoved (g), so we don't have to dBodySetRotation (g->body,R); } else { memcpy (g->final_posr->R,R,sizeof(dMatrix3)); dGeomMoved (g); } } void dGeomSetQuaternion (dxGeom *g, const dQuaternion quat) { dAASSERT (g && quat); dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable"); CHECK_NOT_LOCKED (g->parent_space); if (g->offset_posr) { g->recomputePosr(); // move body such that body+offset = rotation dxPosR new_final_posr; dxPosR new_body_posr; dQtoR (quat, new_final_posr.R); memcpy(new_final_posr.pos, g->final_posr->pos, sizeof(dVector3)); getBodyPosr(*g->offset_posr, new_final_posr, new_body_posr); dBodySetRotation(g->body, new_body_posr.R); dBodySetPosition(g->body, new_body_posr.pos[0], new_body_posr.pos[1], new_body_posr.pos[2]); } if (g->body) { // this will call dGeomMoved (g), so we don't have to dBodySetQuaternion (g->body,quat); } else { dQtoR (quat, g->final_posr->R); dGeomMoved (g); } } const dReal * dGeomGetPosition (dxGeom *g) { dAASSERT (g); dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable"); return g->buildUpdatedPosition(); } void dGeomCopyPosition(dxGeom *g, dVector3 pos) { dAASSERT (g); dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable"); const dVector3 &src = g->buildUpdatedPosition(); pos[0] = src[dV3E_X]; pos[1] = src[dV3E_Y]; pos[2] = src[dV3E_Z]; } const dReal * dGeomGetRotation (dxGeom *g) { dAASSERT (g); dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable"); return g->buildUpdatedRotation(); } void dGeomCopyRotation(dxGeom *g, dMatrix3 R) { dAASSERT (g); dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable"); const dMatrix3 &src = g->buildUpdatedRotation(); R[0] = src[dM3E_XX]; R[1] = src[dM3E_XY]; R[2] = src[dM3E_XZ]; R[4] = src[dM3E_YX]; R[5] = src[dM3E_YY]; R[6] = src[dM3E_YZ]; R[8] = src[dM3E_ZX]; R[9] = src[dM3E_ZY]; R[10] = src[dM3E_ZZ]; } void dGeomGetQuaternion (dxGeom *g, dQuaternion quat) { dAASSERT (g); dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable"); if (g->body && !g->offset_posr) { const dReal * body_quat = dBodyGetQuaternion (g->body); quat[0] = body_quat[0]; quat[1] = body_quat[1]; quat[2] = body_quat[2]; quat[3] = body_quat[3]; } else { g->recomputePosr(); dRtoQ (g->final_posr->R, quat); } } void dGeomGetAABB (dxGeom *g, dReal aabb[6]) { dAASSERT (g); dAASSERT (aabb); g->recomputeAABB(); memcpy (aabb,g->aabb,6 * sizeof(dReal)); } int dGeomIsSpace (dxGeom *g) { dAASSERT (g); return IS_SPACE(g); } dSpaceID dGeomGetSpace (dxGeom *g) { dAASSERT (g); return g->parent_space; } int dGeomGetClass (dxGeom *g) { dAASSERT (g); return g->type; } void dGeomSetCategoryBits (dxGeom *g, unsigned long bits) { dAASSERT (g); CHECK_NOT_LOCKED (g->parent_space); g->category_bits = bits; } void dGeomSetCollideBits (dxGeom *g, unsigned long bits) { dAASSERT (g); CHECK_NOT_LOCKED (g->parent_space); g->collide_bits = bits; } unsigned long dGeomGetCategoryBits (dxGeom *g) { dAASSERT (g); return g->category_bits; } unsigned long dGeomGetCollideBits (dxGeom *g) { dAASSERT (g); return g->collide_bits; } void dGeomEnable (dxGeom *g) { dAASSERT (g); g->gflags |= GEOM_ENABLED; } void dGeomDisable (dxGeom *g) { dAASSERT (g); g->gflags &= ~GEOM_ENABLED; } int dGeomIsEnabled (dxGeom *g) { dAASSERT (g); return (g->gflags & GEOM_ENABLED) != 0; } void dGeomGetRelPointPos (dGeomID g, dReal px, dReal py, dReal pz, dVector3 result) { dAASSERT (g); if ((g->gflags & GEOM_PLACEABLE) == 0) { result[0] = px; result[1] = py; result[2] = pz; return; } g->recomputePosr(); dVector3 prel,p; prel[0] = px; prel[1] = py; prel[2] = pz; prel[3] = 0; dMultiply0_331 (p,g->final_posr->R,prel); result[0] = p[0] + g->final_posr->pos[0]; result[1] = p[1] + g->final_posr->pos[1]; result[2] = p[2] + g->final_posr->pos[2]; } void dGeomGetPosRelPoint (dGeomID g, dReal px, dReal py, dReal pz, dVector3 result) { dAASSERT (g); if ((g->gflags & GEOM_PLACEABLE) == 0) { result[0] = px; result[1] = py; result[2] = pz; return; } g->recomputePosr(); dVector3 prel; prel[0] = px - g->final_posr->pos[0]; prel[1] = py - g->final_posr->pos[1]; prel[2] = pz - g->final_posr->pos[2]; prel[3] = 0; dMultiply1_331 (result,g->final_posr->R,prel); } void dGeomVectorToWorld (dGeomID g, dReal px, dReal py, dReal pz, dVector3 result) { dAASSERT (g); if ((g->gflags & GEOM_PLACEABLE) == 0) { result[0] = px; result[1] = py; result[2] = pz; return; } g->recomputePosr(); dVector3 p; p[0] = px; p[1] = py; p[2] = pz; p[3] = 0; dMultiply0_331 (result,g->final_posr->R,p); } void dGeomVectorFromWorld (dGeomID g, dReal px, dReal py, dReal pz, dVector3 result) { dAASSERT (g); if ((g->gflags & GEOM_PLACEABLE) == 0) { result[0] = px; result[1] = py; result[2] = pz; return; } g->recomputePosr(); dVector3 p; p[0] = px; p[1] = py; p[2] = pz; p[3] = 0; dMultiply1_331 (result,g->final_posr->R,p); } int dGeomLowLevelControl (dxGeom *g, int controlClass, int controlCode, void *dataValue, int *dataSize) { dAASSERT (g); dAASSERT (dataSize); if (!dataSize) { return false; } bool result = g->controlGeometry(controlClass, controlCode, dataValue, dataSize); return result; } //**************************************************************************** // C interface that lets the user make new classes. this interface is a lot // more cumbersome than C++ subclassing, which is what is used internally // in ODE. this API is mainly to support legacy code. static int num_user_classes = 0; static dGeomClass user_classes [dMaxUserClasses]; struct dxUserGeom : public dxGeom { void *user_data; dxUserGeom (int class_num); ~dxUserGeom(); void computeAABB(); int AABBTest (dxGeom *o, dReal aabb[6]); }; dxUserGeom::dxUserGeom (int class_num) : dxGeom (0,1) { type = class_num; int size = user_classes[type-dFirstUserClass].bytes; user_data = dAlloc (size); memset (user_data,0,size); } dxUserGeom::~dxUserGeom() { dGeomClass *c = &user_classes[type-dFirstUserClass]; if (c->dtor) c->dtor (this); dFree (user_data,c->bytes); } void dxUserGeom::computeAABB() { user_classes[type-dFirstUserClass].aabb (this,aabb); } int dxUserGeom::AABBTest (dxGeom *o, dReal aabb[6]) { dGeomClass *c = &user_classes[type-dFirstUserClass]; if (c->aabb_test) return c->aabb_test (this,o,aabb); else return 1; } static int dCollideUserGeomWithGeom (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) { // this generic collider function is called the first time that a user class // tries to collide against something. it will find out the correct collider // function and then set the colliders array so that the correct function is // called directly the next time around. int t1 = o1->type; // note that o1 is a user geom int t2 = o2->type; // o2 *may* be a user geom // find the collider function to use. if o1 does not know how to collide with // o2, then o2 might know how to collide with o1 (provided that it is a user // geom). dColliderFn *fn = user_classes[t1-dFirstUserClass].collider (t2); int reverse = 0; if (!fn && t2 >= dFirstUserClass && t2 <= dLastUserClass) { fn = user_classes[t2-dFirstUserClass].collider (t1); reverse = 1; } // set the colliders array so that the correct function is called directly // the next time around. note that fn can be 0 here if no collider was found, // which means that dCollide() will always return 0 for this case. colliders[t1][t2].fn = fn; colliders[t1][t2].reverse = reverse; colliders[t2][t1].fn = fn; colliders[t2][t1].reverse = !reverse; // now call the collider function indirectly through dCollide(), so that // contact reversing is properly handled. return dCollide (o1,o2,flags,contact,skip); } int dCreateGeomClass (const dGeomClass *c) { dUASSERT(c && c->bytes >= 0 && c->collider && c->aabb,"bad geom class"); if (num_user_classes >= dMaxUserClasses) { dDebug (0,"too many user classes, you must increase the limit and " "recompile ODE"); } user_classes[num_user_classes] = *c; int class_number = num_user_classes + dFirstUserClass; setAllColliders (class_number,&dCollideUserGeomWithGeom); num_user_classes++; return class_number; } /*extern */void dFinitUserClasses() { num_user_classes = 0; } void * dGeomGetClassData (dxGeom *g) { dUASSERT (g && g->type >= dFirstUserClass && g->type <= dLastUserClass,"not a custom class"); dxUserGeom *user = (dxUserGeom*) g; return user->user_data; } dGeomID dCreateGeom (int classnum) { dUASSERT (classnum >= dFirstUserClass && classnum <= dLastUserClass,"not a custom class"); return new dxUserGeom (classnum); } /* ************************************************************************ */ /* geom offset from body */ void dGeomCreateOffset (dxGeom *g) { dAASSERT (g); dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable"); dUASSERT (g->body, "geom must be on a body"); if (g->offset_posr) { return; // already created } dIASSERT (g->final_posr == &g->body->posr); g->final_posr = dAllocPosr(); g->offset_posr = dAllocPosr(); dSetZero (g->offset_posr->pos,4); dRSetIdentity (g->offset_posr->R); g->gflags |= GEOM_POSR_BAD; } void dGeomSetOffsetPosition (dxGeom *g, dReal x, dReal y, dReal z) { dAASSERT (g); dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable"); dUASSERT (g->body, "geom must be on a body"); CHECK_NOT_LOCKED (g->parent_space); if (!g->offset_posr) { dGeomCreateOffset(g); } g->offset_posr->pos[0] = x; g->offset_posr->pos[1] = y; g->offset_posr->pos[2] = z; dGeomMoved (g); } void dGeomSetOffsetRotation (dxGeom *g, const dMatrix3 R) { dAASSERT (g && R); dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable"); dUASSERT (g->body, "geom must be on a body"); CHECK_NOT_LOCKED (g->parent_space); if (!g->offset_posr) { dGeomCreateOffset (g); } memcpy (g->offset_posr->R,R,sizeof(dMatrix3)); dGeomMoved (g); } void dGeomSetOffsetQuaternion (dxGeom *g, const dQuaternion quat) { dAASSERT (g && quat); dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable"); dUASSERT (g->body, "geom must be on a body"); CHECK_NOT_LOCKED (g->parent_space); if (!g->offset_posr) { dGeomCreateOffset (g); } dQtoR (quat, g->offset_posr->R); dGeomMoved (g); } void dGeomSetOffsetWorldPosition (dxGeom *g, dReal x, dReal y, dReal z) { dAASSERT (g); dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable"); dUASSERT (g->body, "geom must be on a body"); CHECK_NOT_LOCKED (g->parent_space); if (!g->offset_posr) { dGeomCreateOffset(g); } dBodyGetPosRelPoint(g->body, x, y, z, g->offset_posr->pos); dGeomMoved (g); } void dGeomSetOffsetWorldRotation (dxGeom *g, const dMatrix3 R) { dAASSERT (g && R); dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable"); dUASSERT (g->body, "geom must be on a body"); CHECK_NOT_LOCKED (g->parent_space); if (!g->offset_posr) { dGeomCreateOffset (g); } g->recomputePosr(); dxPosR new_final_posr; memcpy(new_final_posr.pos, g->final_posr->pos, sizeof(dVector3)); memcpy(new_final_posr.R, R, sizeof(dMatrix3)); getWorldOffsetPosr(g->body->posr, new_final_posr, *g->offset_posr); dGeomMoved (g); } void dGeomSetOffsetWorldQuaternion (dxGeom *g, const dQuaternion quat) { dAASSERT (g && quat); dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable"); dUASSERT (g->body, "geom must be on a body"); CHECK_NOT_LOCKED (g->parent_space); if (!g->offset_posr) { dGeomCreateOffset (g); } g->recomputePosr(); dxPosR new_final_posr; memcpy(new_final_posr.pos, g->final_posr->pos, sizeof(dVector3)); dQtoR (quat, new_final_posr.R); getWorldOffsetPosr(g->body->posr, new_final_posr, *g->offset_posr); dGeomMoved (g); } void dGeomClearOffset(dxGeom *g) { dAASSERT (g); dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable"); if (g->offset_posr) { dIASSERT(g->body); // no longer need an offset posr dFreePosr(g->offset_posr); g->offset_posr = 0; // the geom will now share the position of the body dFreePosr(g->final_posr); g->final_posr = &g->body->posr; // geom has moved g->gflags &= ~GEOM_POSR_BAD; dGeomMoved (g); } } int dGeomIsOffset(dxGeom *g) { dAASSERT (g); return ((0 != g->offset_posr) ? 1 : 0); } static const dVector3 OFFSET_POSITION_ZERO = { 0.0f, 0.0f, 0.0f, 0.0f }; const dReal * dGeomGetOffsetPosition (dxGeom *g) { dAASSERT (g); if (g->offset_posr) { return g->offset_posr->pos; } return OFFSET_POSITION_ZERO; } void dGeomCopyOffsetPosition (dxGeom *g, dVector3 pos) { dAASSERT (g); if (g->offset_posr) { const dReal* src = g->offset_posr->pos; pos[0] = src[0]; pos[1] = src[1]; pos[2] = src[2]; } else { pos[0] = 0; pos[1] = 0; pos[2] = 0; } } static const dMatrix3 OFFSET_ROTATION_ZERO = { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, }; const dReal * dGeomGetOffsetRotation (dxGeom *g) { dAASSERT (g); if (g->offset_posr) { return g->offset_posr->R; } return OFFSET_ROTATION_ZERO; } void dGeomCopyOffsetRotation (dxGeom *g, dMatrix3 R) { dAASSERT (g); if (g->offset_posr) { const dReal* src = g->offset_posr->R; R[0] = src[0]; R[1] = src[1]; R[2] = src[2]; R[4] = src[4]; R[5] = src[5]; R[6] = src[6]; R[8] = src[8]; R[9] = src[9]; R[10] = src[10]; } else { R[0] = OFFSET_ROTATION_ZERO[0]; R[1] = OFFSET_ROTATION_ZERO[1]; R[2] = OFFSET_ROTATION_ZERO[2]; R[4] = OFFSET_ROTATION_ZERO[4]; R[5] = OFFSET_ROTATION_ZERO[5]; R[6] = OFFSET_ROTATION_ZERO[6]; R[8] = OFFSET_ROTATION_ZERO[8]; R[9] = OFFSET_ROTATION_ZERO[9]; R[10] = OFFSET_ROTATION_ZERO[10]; } } void dGeomGetOffsetQuaternion (dxGeom *g, dQuaternion result) { dAASSERT (g); if (g->offset_posr) { dRtoQ (g->offset_posr->R, result); } else { dSetZero (result,4); result[0] = 1; } } ode-0.16/ode/src/mass.cpp0000664000175200017520000004034613403272463012156 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include #include "config.h" #include "matrix.h" #include "odemath.h" // Local dependencies #include "collision_kernel.h" #if dTRIMESH_ENABLED #include "collision_trimesh_internal.h" #endif // dTRIMESH_ENABLED #define SQR(x) ((x)*(x)) //!< Returns x square #define CUBE(x) ((x)*(x)*(x)) //!< Returns x cube #define _I(i,j) I[(i)*4+(j)] // return 1 if ok, 0 if bad int dMassCheck (const dMass *m) { int i; if (m->mass <= 0) { dDEBUGMSG ("mass must be > 0"); return 0; } if (!dIsPositiveDefinite (m->I,3,NULL)) { dDEBUGMSG ("inertia must be positive definite"); return 0; } // verify that the center of mass position is consistent with the mass // and inertia matrix. this is done by checking that the inertia around // the center of mass is also positive definite. from the comment in // dMassTranslate(), if the body is translated so that its center of mass // is at the point of reference, then the new inertia is: // I + mass*crossmat(c)^2 // note that requiring this to be positive definite is exactly equivalent // to requiring that the spatial inertia matrix // [ mass*eye(3,3) M*crossmat(c)^T ] // [ M*crossmat(c) I ] // is positive definite, given that I is PD and mass>0. see the theorem // about partitioned PD matrices for proof. dMatrix3 I2,chat; dSetZero (chat,12); dSetCrossMatrixPlus (chat,m->c,4); dMultiply0_333 (I2,chat,chat); for (i=0; i<3; i++) I2[i] = m->I[i] + m->mass*I2[i]; for (i=4; i<7; i++) I2[i] = m->I[i] + m->mass*I2[i]; for (i=8; i<11; i++) I2[i] = m->I[i] + m->mass*I2[i]; if (!dIsPositiveDefinite (I2,3,NULL)) { dDEBUGMSG ("center of mass inconsistent with mass parameters"); return 0; } return 1; } void dMassSetZero (dMass *m) { dAASSERT (m); m->mass = REAL(0.0); dSetZero (m->c,sizeof(m->c) / sizeof(dReal)); dSetZero (m->I,sizeof(m->I) / sizeof(dReal)); } void dMassSetParameters (dMass *m, dReal themass, dReal cgx, dReal cgy, dReal cgz, dReal I11, dReal I22, dReal I33, dReal I12, dReal I13, dReal I23) { dAASSERT (m); dMassSetZero (m); m->mass = themass; m->c[0] = cgx; m->c[1] = cgy; m->c[2] = cgz; m->_I(0,0) = I11; m->_I(1,1) = I22; m->_I(2,2) = I33; m->_I(0,1) = I12; m->_I(0,2) = I13; m->_I(1,2) = I23; m->_I(1,0) = I12; m->_I(2,0) = I13; m->_I(2,1) = I23; dMassCheck (m); } void dMassSetSphere (dMass *m, dReal density, dReal radius) { dMassSetSphereTotal (m, (dReal) ((REAL(4.0)/REAL(3.0)) * M_PI * radius*radius*radius * density), radius); } void dMassSetSphereTotal (dMass *m, dReal total_mass, dReal radius) { dAASSERT (m); dMassSetZero (m); m->mass = total_mass; dReal II = REAL(0.4) * total_mass * radius*radius; m->_I(0,0) = II; m->_I(1,1) = II; m->_I(2,2) = II; # ifndef dNODEBUG dMassCheck (m); # endif } void dMassSetCapsule (dMass *m, dReal density, int direction, dReal radius, dReal length) { dReal M1,M2,Ia,Ib; dAASSERT (m); dUASSERT (direction >= 1 && direction <= 3,"bad direction number"); dMassSetZero (m); M1 = (dReal) (M_PI*radius*radius*length*density); // cylinder mass M2 = (dReal) ((REAL(4.0)/REAL(3.0))*M_PI*radius*radius*radius*density); // total cap mass m->mass = M1+M2; Ia = M1*(REAL(0.25)*radius*radius + (REAL(1.0)/REAL(12.0))*length*length) + M2*(REAL(0.4)*radius*radius + REAL(0.375)*radius*length + REAL(0.25)*length*length); Ib = (M1*REAL(0.5) + M2*REAL(0.4))*radius*radius; m->_I(0,0) = Ia; m->_I(1,1) = Ia; m->_I(2,2) = Ia; m->_I(direction-1,direction-1) = Ib; # ifndef dNODEBUG dMassCheck (m); # endif } void dMassSetCapsuleTotal (dMass *m, dReal total_mass, int direction, dReal a, dReal b) { dMassSetCapsule (m, 1.0, direction, a, b); dMassAdjust (m, total_mass); } void dMassSetCylinder (dMass *m, dReal density, int direction, dReal radius, dReal length) { dMassSetCylinderTotal (m, (dReal) (M_PI*radius*radius*length*density), direction, radius, length); } void dMassSetCylinderTotal (dMass *m, dReal total_mass, int direction, dReal radius, dReal length) { dReal r2,I; dAASSERT (m); dUASSERT (direction >= 1 && direction <= 3,"bad direction number"); dMassSetZero (m); r2 = radius*radius; m->mass = total_mass; I = total_mass*(REAL(0.25)*r2 + (REAL(1.0)/REAL(12.0))*length*length); m->_I(0,0) = I; m->_I(1,1) = I; m->_I(2,2) = I; m->_I(direction-1,direction-1) = total_mass*REAL(0.5)*r2; # ifndef dNODEBUG dMassCheck (m); # endif } void dMassSetBox (dMass *m, dReal density, dReal lx, dReal ly, dReal lz) { dMassSetBoxTotal (m, lx*ly*lz*density, lx, ly, lz); } void dMassSetBoxTotal (dMass *m, dReal total_mass, dReal lx, dReal ly, dReal lz) { dAASSERT (m); dMassSetZero (m); m->mass = total_mass; m->_I(0,0) = total_mass/REAL(12.0) * (ly*ly + lz*lz); m->_I(1,1) = total_mass/REAL(12.0) * (lx*lx + lz*lz); m->_I(2,2) = total_mass/REAL(12.0) * (lx*lx + ly*ly); # ifndef dNODEBUG dMassCheck (m); # endif } /* * dMassSetTrimesh, implementation by Gero Mueller. * Based on Brian Mirtich, "Fast and Accurate Computation of * Polyhedral Mass Properties," journal of graphics tools, volume 1, * number 2, 1996. */ void dMassSetTrimesh( dMass *m, dReal density, dGeomID g ) { dAASSERT (m); dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh"); dMassSetZero (m); #if dTRIMESH_ENABLED dxTriMesh *TriMesh = static_cast(g); unsigned int triangles = TriMesh->getMeshTriangleCount(); dReal nx, ny, nz; unsigned int i, A, B, C; // face integrals dReal Fa, Fb, Fc, Faa, Fbb, Fcc, Faaa, Fbbb, Fccc, Faab, Fbbc, Fcca; // projection integrals dReal P1, Pa, Pb, Paa, Pab, Pbb, Paaa, Paab, Pabb, Pbbb; dReal T0 = 0; dReal T1[3] = {0., 0., 0.}; dReal T2[3] = {0., 0., 0.}; dReal TP[3] = {0., 0., 0.}; for( i = 0; i < triangles; i++ ) { dVector3 v[3]; TriMesh->fetchMeshTransformedTriangle(v, i); dVector3 n, a, b; dSubtractVectors3( a, v[1], v[0] ); dSubtractVectors3( b, v[2], v[0] ); dCalcVectorCross3( n, b, a ); nx = fabs(n[0]); ny = fabs(n[1]); nz = fabs(n[2]); if( nx > ny && nx > nz ) C = 0; else C = (ny > nz) ? 1 : 2; // Even though all triangles might be initially valid, // a triangle may degenerate into a segment after applying // space transformation. if (n[C] != REAL(0.0)) { A = (C + 1) % 3; B = (A + 1) % 3; // calculate face integrals { dReal w; dReal k1, k2, k3, k4; //compProjectionIntegrals(f); { dReal a0=0, a1=0, da; dReal b0=0, b1=0, db; dReal a0_2, a0_3, a0_4, b0_2, b0_3, b0_4; dReal a1_2, a1_3, b1_2, b1_3; dReal C1, Ca, Caa, Caaa, Cb, Cbb, Cbbb; dReal Cab, Kab, Caab, Kaab, Cabb, Kabb; P1 = Pa = Pb = Paa = Pab = Pbb = Paaa = Paab = Pabb = Pbbb = 0.0; for( int j = 0; j < 3; j++) { switch(j) { case 0: a0 = v[0][A]; b0 = v[0][B]; a1 = v[1][A]; b1 = v[1][B]; break; case 1: a0 = v[1][A]; b0 = v[1][B]; a1 = v[2][A]; b1 = v[2][B]; break; case 2: a0 = v[2][A]; b0 = v[2][B]; a1 = v[0][A]; b1 = v[0][B]; break; } da = a1 - a0; db = b1 - b0; a0_2 = a0 * a0; a0_3 = a0_2 * a0; a0_4 = a0_3 * a0; b0_2 = b0 * b0; b0_3 = b0_2 * b0; b0_4 = b0_3 * b0; a1_2 = a1 * a1; a1_3 = a1_2 * a1; b1_2 = b1 * b1; b1_3 = b1_2 * b1; C1 = a1 + a0; Ca = a1*C1 + a0_2; Caa = a1*Ca + a0_3; Caaa = a1*Caa + a0_4; Cb = b1*(b1 + b0) + b0_2; Cbb = b1*Cb + b0_3; Cbbb = b1*Cbb + b0_4; Cab = 3*a1_2 + 2*a1*a0 + a0_2; Kab = a1_2 + 2*a1*a0 + 3*a0_2; Caab = a0*Cab + 4*a1_3; Kaab = a1*Kab + 4*a0_3; Cabb = 4*b1_3 + 3*b1_2*b0 + 2*b1*b0_2 + b0_3; Kabb = b1_3 + 2*b1_2*b0 + 3*b1*b0_2 + 4*b0_3; P1 += db*C1; Pa += db*Ca; Paa += db*Caa; Paaa += db*Caaa; Pb += da*Cb; Pbb += da*Cbb; Pbbb += da*Cbbb; Pab += db*(b1*Cab + b0*Kab); Paab += db*(b1*Caab + b0*Kaab); Pabb += da*(a1*Cabb + a0*Kabb); } P1 /= 2.0; Pa /= 6.0; Paa /= 12.0; Paaa /= 20.0; Pb /= -6.0; Pbb /= -12.0; Pbbb /= -20.0; Pab /= 24.0; Paab /= 60.0; Pabb /= -60.0; } w = - dCalcVectorDot3(n, v[0]); k1 = 1 / n[C]; k2 = k1 * k1; k3 = k2 * k1; k4 = k3 * k1; Fa = k1 * Pa; Fb = k1 * Pb; Fc = -k2 * (n[A]*Pa + n[B]*Pb + w*P1); Faa = k1 * Paa; Fbb = k1 * Pbb; Fcc = k3 * (SQR(n[A])*Paa + 2*n[A]*n[B]*Pab + SQR(n[B])*Pbb + w*(2*(n[A]*Pa + n[B]*Pb) + w*P1)); Faaa = k1 * Paaa; Fbbb = k1 * Pbbb; Fccc = -k4 * (CUBE(n[A])*Paaa + 3*SQR(n[A])*n[B]*Paab + 3*n[A]*SQR(n[B])*Pabb + CUBE(n[B])*Pbbb + 3*w*(SQR(n[A])*Paa + 2*n[A]*n[B]*Pab + SQR(n[B])*Pbb) + w*w*(3*(n[A]*Pa + n[B]*Pb) + w*P1)); Faab = k1 * Paab; Fbbc = -k2 * (n[A]*Pabb + n[B]*Pbbb + w*Pbb); Fcca = k3 * (SQR(n[A])*Paaa + 2*n[A]*n[B]*Paab + SQR(n[B])*Pabb + w*(2*(n[A]*Paa + n[B]*Pab) + w*Pa)); } T0 += n[0] * ((A == 0) ? Fa : ((B == 0) ? Fb : Fc)); T1[A] += n[A] * Faa; T1[B] += n[B] * Fbb; T1[C] += n[C] * Fcc; T2[A] += n[A] * Faaa; T2[B] += n[B] * Fbbb; T2[C] += n[C] * Fccc; TP[A] += n[A] * Faab; TP[B] += n[B] * Fbbc; TP[C] += n[C] * Fcca; } } T1[0] /= 2; T1[1] /= 2; T1[2] /= 2; T2[0] /= 3; T2[1] /= 3; T2[2] /= 3; TP[0] /= 2; TP[1] /= 2; TP[2] /= 2; m->mass = density * T0; m->_I(0,0) = density * (T2[1] + T2[2]); m->_I(1,1) = density * (T2[2] + T2[0]); m->_I(2,2) = density * (T2[0] + T2[1]); m->_I(0,1) = - density * TP[0]; m->_I(1,0) = - density * TP[0]; m->_I(2,1) = - density * TP[1]; m->_I(1,2) = - density * TP[1]; m->_I(2,0) = - density * TP[2]; m->_I(0,2) = - density * TP[2]; // Added to address SF bug 1729095 dMassTranslate( m, T1[0] / T0, T1[1] / T0, T1[2] / T0 ); # ifndef dNODEBUG dMassCheck (m); # endif #endif // dTRIMESH_ENABLED } void dMassSetTrimeshTotal( dMass *m, dReal total_mass, dGeomID g) { dAASSERT( m ); dUASSERT( g && g->type == dTriMeshClass, "argument not a trimesh" ); dMassSetTrimesh( m, 1.0, g ); dMassAdjust( m, total_mass ); } void dMassAdjust (dMass *m, dReal newmass) { dAASSERT (m); dReal scale = newmass / m->mass; m->mass = newmass; for (int i=0; i<3; i++) for (int j=0; j<3; j++) m->_I(i,j) *= scale; # ifndef dNODEBUG dMassCheck (m); # endif } void dMassTranslate (dMass *m, dReal x, dReal y, dReal z) { // if the body is translated by `a' relative to its point of reference, // the new inertia about the point of reference is: // // I + mass*(crossmat(c)^2 - crossmat(c+a)^2) // // where c is the existing center of mass and I is the old inertia. int i,j; dMatrix3 ahat,chat,t1,t2; dReal a[3]; dAASSERT (m); // adjust inertia matrix dSetZero (chat,12); dSetCrossMatrixPlus (chat,m->c,4); a[0] = x + m->c[0]; a[1] = y + m->c[1]; a[2] = z + m->c[2]; dSetZero (ahat,12); dSetCrossMatrixPlus (ahat,a,4); dMultiply0_333 (t1,ahat,ahat); dMultiply0_333 (t2,chat,chat); for (i=0; i<3; i++) for (j=0; j<3; j++) m->_I(i,j) += m->mass * (t2[i*4+j]-t1[i*4+j]); // ensure perfect symmetry m->_I(1,0) = m->_I(0,1); m->_I(2,0) = m->_I(0,2); m->_I(2,1) = m->_I(1,2); // adjust center of mass m->c[0] += x; m->c[1] += y; m->c[2] += z; # ifndef dNODEBUG dMassCheck (m); # endif } void dMassRotate (dMass *m, const dMatrix3 R) { // if the body is rotated by `R' relative to its point of reference, // the new inertia about the point of reference is: // // R * I * R' // // where I is the old inertia. dMatrix3 t1; dReal t2[3]; dAASSERT (m); // rotate inertia matrix dMultiply2_333 (t1,m->I,R); dMultiply0_333 (m->I,R,t1); // ensure perfect symmetry m->_I(1,0) = m->_I(0,1); m->_I(2,0) = m->_I(0,2); m->_I(2,1) = m->_I(1,2); // rotate center of mass dMultiply0_331 (t2,R,m->c); m->c[0] = t2[0]; m->c[1] = t2[1]; m->c[2] = t2[2]; # ifndef dNODEBUG dMassCheck (m); # endif } void dMassAdd (dMass *a, const dMass *b) { int i; dAASSERT (a && b); dReal denom = dRecip (a->mass + b->mass); for (i=0; i<3; i++) a->c[i] = (a->c[i]*a->mass + b->c[i]*b->mass)*denom; a->mass += b->mass; for (i=0; i<12; i++) a->I[i] += b->I[i]; } // Backwards compatible API void dMassSetCappedCylinder(dMass *a, dReal b, int c, dReal d, dReal e) { return dMassSetCapsule(a,b,c,d,e); } void dMassSetCappedCylinderTotal(dMass *a, dReal b, int c, dReal d, dReal e) { return dMassSetCapsuleTotal(a,b,c,d,e); } ode-0.16/ode/src/default_threading.cpp0000664000175200017520000000612513403272463014661 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * Threading base wrapper class header file. * * Copyright (C) 2011-2012 Oleh Derevenko. All rights reserved. * * e-mail: odar@eleks.com (change all "a" to "e") * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* * The default threading instance holder class implementation * Copyright (c) 2017 Oleh Derevenko, odar@eleks.com (change all "a" to "e") */ #include #include #include "config.h" #include "default_threading.h" #include "error.h" /*static */dThreadingImplementationID DefaultThreadingHolder::m_defaultThreadingImpl = NULL; /*static */const dThreadingFunctionsInfo *DefaultThreadingHolder::m_defaultThreadingFunctions = NULL; /*static */ bool DefaultThreadingHolder::initializeDefaultThreading() { dIASSERT(m_defaultThreadingImpl == NULL); bool initResult = false; dThreadingImplementationID threadingImpl = dThreadingAllocateSelfThreadedImplementation(); if (threadingImpl != NULL) { m_defaultThreadingFunctions = dThreadingImplementationGetFunctions(threadingImpl); m_defaultThreadingImpl = threadingImpl; initResult = true; } return initResult; } /*static */ void DefaultThreadingHolder::finalizeDefaultThreading() { dThreadingImplementationID threadingImpl = m_defaultThreadingImpl; if (threadingImpl != NULL) { dThreadingFreeImplementation(threadingImpl); m_defaultThreadingFunctions = NULL; m_defaultThreadingImpl = NULL; } } ode-0.16/ode/src/typedefs.h0000664000175200017520000000523413403272463012500 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_TYPEDEFS_H_ #define _ODE_TYPEDEFS_H_ #include #include "error.h" /* * Internal typedefs to map public types into more convenient private types */ typedef dint64 int64; dSASSERT(sizeof(int64) == 8); typedef duint64 uint64; dSASSERT(sizeof(uint64) == 8); typedef dint32 int32; dSASSERT(sizeof(int32) == 4); typedef duint32 uint32; dSASSERT(sizeof(uint32) == 4); typedef dint16 int16; dSASSERT(sizeof(int16) == 2); typedef duint16 uint16; dSASSERT(sizeof(uint16) == 2); typedef dint8 int8; dSASSERT(sizeof(int8) == 1); typedef duint8 uint8; dSASSERT(sizeof(uint8) == 1); typedef dintptr intptr; dSASSERT(sizeof(intptr) == sizeof(void *)); typedef duintptr uintptr; dSASSERT(sizeof(uintptr) == sizeof(void *)); typedef ddiffint diffint; dSASSERT(sizeof(diffint) == sizeof(void *)); // So far, we choose to not support systems that have accessible memory segment size smaller than the pointer size typedef dsizeint sizeint; dSASSERT(sizeof(sizeint) == sizeof(void *)); // So far, we choose to not support systems that have accessible memory segment size smaller than the pointer size #endif ode-0.16/ode/src/timer.cpp0000664000175200017520000002402313403272463012325 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* TODO ---- * gettimeofday() and the pentium time stamp counter return the real time, not the process time. fix this somehow! */ #include #include #include "config.h" #include "common.h" // misc defines #define ALLOCA dALLOCA16 //**************************************************************************** // implementation for windows based on the multimedia performance counter. #ifdef WIN32 #include "windows.h" static inline void getClockCount (unsigned long cc[2]) { LARGE_INTEGER a; QueryPerformanceCounter (&a); cc[0] = a.LowPart; cc[1] = a.HighPart; } static inline void serialize() { } static inline double loadClockCount (unsigned long cc[2]) { LARGE_INTEGER a; a.LowPart = cc[0]; a.HighPart = cc[1]; return double(a.QuadPart); } double dTimerResolution() { return 1.0/dTimerTicksPerSecond(); } double dTimerTicksPerSecond() { static int query=0; static double hz=0.0; if (!query) { LARGE_INTEGER a; QueryPerformanceFrequency (&a); hz = double(a.QuadPart); query = 1; } return hz; } #endif //**************************************************************************** // implementation based on the pentium time stamp counter. the timer functions // can be serializing or non-serializing. serializing will ensure that all // instructions have executed and data has been written back before the cpu // time stamp counter is read. the CPUID instruction is used to serialize. #if defined(PENTIUM) && !defined(WIN32) // we need to know the clock rate so that the timing function can report // accurate times. this number only needs to be set accurately if we're // doing performance tests and care about real-world time numbers - otherwise, // just ignore this. i have not worked out how to determine this number // automatically yet. #define PENTIUM_HZ (500e6) static inline void getClockCount (unsigned long cc[2]) { #ifndef X86_64_SYSTEM asm volatile ( "rdtsc\n" "movl %%eax,(%%esi)\n" "movl %%edx,4(%%esi)\n" : : "S" (cc) : "%eax","%edx","cc","memory"); #else asm volatile ( "rdtsc\n" "movl %%eax,(%%rsi)\n" "movl %%edx,4(%%rsi)\n" : : "S" (cc) : "%eax","%edx","cc","memory"); #endif } static inline void serialize() { #ifndef X86_64_SYSTEM asm volatile ( "mov $0,%%eax\n" "push %%ebx\n" "cpuid\n" "pop %%ebx\n" : : : "%eax","%ecx","%edx","cc","memory"); #else asm volatile ( "mov $0,%%rax\n" "push %%rbx\n" "cpuid\n" "pop %%rbx\n" : : : "%rax","%rcx","%rdx","cc","memory"); #endif } static inline double loadClockCount (unsigned long a[2]) { double ret; #ifndef X86_64_SYSTEM asm volatile ("fildll %1; fstpl %0" : "=m" (ret) : "m" (a[0]) : "cc","memory"); #else asm volatile ("fildll %1; fstpl %0" : "=m" (ret) : "m" (a[0]) : "cc","memory"); #endif return ret; } double dTimerResolution() { return 1.0/PENTIUM_HZ; } double dTimerTicksPerSecond() { return PENTIUM_HZ; } #endif //**************************************************************************** // otherwise, do the implementation based on gettimeofday(). #if !defined(PENTIUM) && !defined(WIN32) #ifndef macintosh #include #include static inline void getClockCount (unsigned long cc[2]) { struct timeval tv; gettimeofday (&tv,0); cc[0] = tv.tv_usec; cc[1] = tv.tv_sec; } #else // macintosh #include #include static inline void getClockCount (unsigned long cc[2]) { UnsignedWide ms; Microseconds (&ms); cc[1] = ms.lo / 1000000; cc[0] = ms.lo - ( cc[1] * 1000000 ); } #endif static inline void serialize() { } static inline double loadClockCount (unsigned long a[2]) { return a[1]*1.0e6 + a[0]; } double dTimerResolution() { unsigned long cc1[2],cc2[2]; getClockCount (cc1); do { getClockCount (cc2); } while (cc1[0]==cc2[0] && cc1[1]==cc2[1]); do { getClockCount (cc1); } while (cc1[0]==cc2[0] && cc1[1]==cc2[1]); double t1 = loadClockCount (cc1); double t2 = loadClockCount (cc2); return (t1-t2) / dTimerTicksPerSecond(); } double dTimerTicksPerSecond() { return 1000000; } #endif //**************************************************************************** // stop watches void dStopwatchReset (dStopwatch *s) { s->time = 0; s->cc[0] = 0; s->cc[1] = 0; } void dStopwatchStart (dStopwatch *s) { serialize(); getClockCount (s->cc); } void dStopwatchStop (dStopwatch *s) { unsigned long cc[2]; serialize(); getClockCount (cc); double t1 = loadClockCount (s->cc); double t2 = loadClockCount (cc); s->time += t2-t1; } double dStopwatchTime (dStopwatch *s) { return s->time / dTimerTicksPerSecond(); } //**************************************************************************** // code timers // maximum number of events to record #define MAXNUM 100 static int num = 0; // number of entries used in event array static struct { unsigned long cc[2]; // clock counts double total_t; // total clocks used in this slot. double total_p; // total percentage points used in this slot. int count; // number of times this slot has been updated. const char *description; // pointer to static string } event[MAXNUM]; // make sure all slot totals and counts reset to 0 at start static void initSlots() { static int initialized=0; if (!initialized) { for (int i=0; i (description); num = 1; serialize(); getClockCount (event[0].cc); } void dTimerNow (const char *description) { if (num < MAXNUM) { // do not serialize getClockCount (event[num].cc); event[num].description = const_cast (description); num++; } } void dTimerEnd() { if (num < MAXNUM) { serialize(); getClockCount (event[num].cc); event[num].description = "TOTAL"; num++; } } //**************************************************************************** // print report static void fprintDoubleWithPrefix (FILE *f, double a, const char *fmt) { if (a >= 0.999999) { fprintf (f,fmt,a); return; } a *= 1000.0; if (a >= 0.999999) { fprintf (f,fmt,a); fprintf (f,"m"); return; } a *= 1000.0; if (a >= 0.999999) { fprintf (f,fmt,a); fprintf (f,"u"); return; } a *= 1000.0; fprintf (f,fmt,a); fprintf (f,"n"); } void dTimerReport (FILE *fout, int average) { int i; sizeint maxl; double ccunit = 1.0/dTimerTicksPerSecond(); fprintf (fout,"\nTimer Report ("); fprintDoubleWithPrefix (fout,ccunit,"%.2f "); fprintf (fout,"s resolution)\n------------\n"); if (num < 1) return; // get maximum description length maxl = 0; for (i=0; i maxl) maxl = l; } // calculate total time double t1 = loadClockCount (event[0].cc); double t2 = loadClockCount (event[num-1].cc); double total = t2 - t1; if (total <= 0) total = 1; // compute time difference for all slots except the last one. update totals double *times = (double*) ALLOCA (num * sizeof(double)); for (i=0; i < (num-1); i++) { double t1 = loadClockCount (event[i].cc); double t2 = loadClockCount (event[i+1].cc); times[i] = t2 - t1; event[i].count++; event[i].total_t += times[i]; event[i].total_p += times[i]/total * 100.0; } // print report (with optional averages) for (i=0; i #include #include "config.h" #include "odemath.h" #include "collision_util.h" //**************************************************************************** int dCollideSpheres (dVector3 p1, dReal r1, dVector3 p2, dReal r2, dContactGeom *c) { // printf ("d=%.2f (%.2f %.2f %.2f) (%.2f %.2f %.2f) r1=%.2f r2=%.2f\n", // d,p1[0],p1[1],p1[2],p2[0],p2[1],p2[2],r1,r2); dReal d = dCalcPointsDistance3(p1,p2); if (d > (r1 + r2)) return 0; if (d <= 0) { c->pos[0] = p1[0]; c->pos[1] = p1[1]; c->pos[2] = p1[2]; c->normal[0] = 1; c->normal[1] = 0; c->normal[2] = 0; c->depth = r1 + r2; } else { dReal d1 = dRecip (d); c->normal[0] = (p1[0]-p2[0])*d1; c->normal[1] = (p1[1]-p2[1])*d1; c->normal[2] = (p1[2]-p2[2])*d1; dReal k = REAL(0.5) * (r2 - r1 - d); c->pos[0] = p1[0] + c->normal[0]*k; c->pos[1] = p1[1] + c->normal[1]*k; c->pos[2] = p1[2] + c->normal[2]*k; c->depth = r1 + r2 - d; } return 1; } void dLineClosestApproach (const dVector3 pa, const dVector3 ua, const dVector3 pb, const dVector3 ub, dReal *alpha, dReal *beta) { dVector3 p; p[0] = pb[0] - pa[0]; p[1] = pb[1] - pa[1]; p[2] = pb[2] - pa[2]; dReal uaub = dCalcVectorDot3(ua,ub); dReal q1 = dCalcVectorDot3(ua,p); dReal q2 = -dCalcVectorDot3(ub,p); dReal d = 1-uaub*uaub; if (d <= REAL(0.0001)) { // @@@ this needs to be made more robust *alpha = 0; *beta = 0; } else { d = dRecip(d); *alpha = (q1 + uaub*q2)*d; *beta = (uaub*q1 + q2)*d; } } // given two line segments A and B with endpoints a1-a2 and b1-b2, return the // points on A and B that are closest to each other (in cp1 and cp2). // in the case of parallel lines where there are multiple solutions, a // solution involving the endpoint of at least one line will be returned. // this will work correctly for zero length lines, e.g. if a1==a2 and/or // b1==b2. // // the algorithm works by applying the voronoi clipping rule to the features // of the line segments. the three features of each line segment are the two // endpoints and the line between them. the voronoi clipping rule states that, // for feature X on line A and feature Y on line B, the closest points PA and // PB between X and Y are globally the closest points if PA is in V(Y) and // PB is in V(X), where V(X) is the voronoi region of X. void dClosestLineSegmentPoints (const dVector3 a1, const dVector3 a2, const dVector3 b1, const dVector3 b2, dVector3 cp1, dVector3 cp2) { dVector3 a1a2,b1b2,a1b1,a1b2,a2b1,a2b2,n; dReal la,lb,k,da1,da2,da3,da4,db1,db2,db3,db4,det; #define SET2(a,b) a[0]=b[0]; a[1]=b[1]; a[2]=b[2]; #define SET3(a,b,op,c) a[0]=b[0] op c[0]; a[1]=b[1] op c[1]; a[2]=b[2] op c[2]; // check vertex-vertex features SET3 (a1a2,a2,-,a1); SET3 (b1b2,b2,-,b1); SET3 (a1b1,b1,-,a1); da1 = dCalcVectorDot3(a1a2,a1b1); db1 = dCalcVectorDot3(b1b2,a1b1); if (da1 <= 0 && db1 >= 0) { SET2 (cp1,a1); SET2 (cp2,b1); return; } SET3 (a1b2,b2,-,a1); da2 = dCalcVectorDot3(a1a2,a1b2); db2 = dCalcVectorDot3(b1b2,a1b2); if (da2 <= 0 && db2 <= 0) { SET2 (cp1,a1); SET2 (cp2,b2); return; } SET3 (a2b1,b1,-,a2); da3 = dCalcVectorDot3(a1a2,a2b1); db3 = dCalcVectorDot3(b1b2,a2b1); if (da3 >= 0 && db3 >= 0) { SET2 (cp1,a2); SET2 (cp2,b1); return; } SET3 (a2b2,b2,-,a2); da4 = dCalcVectorDot3(a1a2,a2b2); db4 = dCalcVectorDot3(b1b2,a2b2); if (da4 >= 0 && db4 <= 0) { SET2 (cp1,a2); SET2 (cp2,b2); return; } // check edge-vertex features. // if one or both of the lines has zero length, we will never get to here, // so we do not have to worry about the following divisions by zero. la = dCalcVectorDot3(a1a2,a1a2); if (da1 >= 0 && da3 <= 0) { k = da1 / la; SET3 (n,a1b1,-,k*a1a2); if (dCalcVectorDot3(b1b2,n) >= 0) { SET3 (cp1,a1,+,k*a1a2); SET2 (cp2,b1); return; } } if (da2 >= 0 && da4 <= 0) { k = da2 / la; SET3 (n,a1b2,-,k*a1a2); if (dCalcVectorDot3(b1b2,n) <= 0) { SET3 (cp1,a1,+,k*a1a2); SET2 (cp2,b2); return; } } lb = dCalcVectorDot3(b1b2,b1b2); if (db1 <= 0 && db2 >= 0) { k = -db1 / lb; SET3 (n,-a1b1,-,k*b1b2); if (dCalcVectorDot3(a1a2,n) >= 0) { SET2 (cp1,a1); SET3 (cp2,b1,+,k*b1b2); return; } } if (db3 <= 0 && db4 >= 0) { k = -db3 / lb; SET3 (n,-a2b1,-,k*b1b2); if (dCalcVectorDot3(a1a2,n) <= 0) { SET2 (cp1,a2); SET3 (cp2,b1,+,k*b1b2); return; } } // it must be edge-edge k = dCalcVectorDot3(a1a2,b1b2); det = la*lb - k*k; if (det <= 0) { // this should never happen, but just in case... SET2(cp1,a1); SET2(cp2,b1); return; } det = dRecip (det); dReal alpha = (lb*da1 - k*db1) * det; dReal beta = ( k*da1 - la*db1) * det; SET3 (cp1,a1,+,alpha*a1a2); SET3 (cp2,b1,+,beta*b1b2); # undef SET2 # undef SET3 } // a simple root finding algorithm is used to find the value of 't' that // satisfies: // d|D(t)|^2/dt = 0 // where: // |D(t)| = |p(t)-b(t)| // where p(t) is a point on the line parameterized by t: // p(t) = p1 + t*(p2-p1) // and b(t) is that same point clipped to the boundary of the box. in box- // relative coordinates d|D(t)|^2/dt is the sum of three x,y,z components // each of which looks like this: // // t_lo / // ______/ -->t // / t_hi // / // // t_lo and t_hi are the t values where the line passes through the planes // corresponding to the sides of the box. the algorithm computes d|D(t)|^2/dt // in a piecewise fashion from t=0 to t=1, stopping at the point where // d|D(t)|^2/dt crosses from negative to positive. void dClosestLineBoxPoints (const dVector3 p1, const dVector3 p2, const dVector3 c, const dMatrix3 R, const dVector3 side, dVector3 lret, dVector3 bret) { int i; // compute the start and delta of the line p1-p2 relative to the box. // we will do all subsequent computations in this box-relative coordinate // system. we have to do a translation and rotation for each point. dVector3 tmp,s,v; tmp[0] = p1[0] - c[0]; tmp[1] = p1[1] - c[1]; tmp[2] = p1[2] - c[2]; dMultiply1_331 (s,R,tmp); tmp[0] = p2[0] - p1[0]; tmp[1] = p2[1] - p1[1]; tmp[2] = p2[2] - p1[2]; dMultiply1_331 (v,R,tmp); // mirror the line so that v has all components >= 0 dVector3 sign; for (i=0; i<3; i++) { if (v[i] < 0) { s[i] = -s[i]; v[i] = -v[i]; sign[i] = -1; } else sign[i] = 1; } // compute v^2 dVector3 v2; v2[0] = v[0]*v[0]; v2[1] = v[1]*v[1]; v2[2] = v[2]*v[2]; // compute the half-sides of the box dReal h[3]; h[0] = REAL(0.5) * side[0]; h[1] = REAL(0.5) * side[1]; h[2] = REAL(0.5) * side[2]; // region is -1,0,+1 depending on which side of the box planes each // coordinate is on. tanchor is the next t value at which there is a // transition, or the last one if there are no more. int region[3]; dReal tanchor[3]; // Denormals are a problem, because we divide by v[i], and then // multiply that by 0. Alas, infinity times 0 is infinity (!) // We also use v2[i], which is v[i] squared. Here's how the epsilons // are chosen: // float epsilon = 1.175494e-038 (smallest non-denormal number) // double epsilon = 2.225074e-308 (smallest non-denormal number) // For single precision, choose an epsilon such that v[i] squared is // not a denormal; this is for performance. // For double precision, choose an epsilon such that v[i] is not a // denormal; this is for correctness. (Jon Watte on mailinglist) #if defined( dSINGLE ) const dReal tanchor_eps = REAL(1e-19); #else const dReal tanchor_eps = REAL(1e-307); #endif // find the region and tanchor values for p1 for (i=0; i<3; i++) { if (v[i] > tanchor_eps) { if (s[i] < -h[i]) { region[i] = -1; tanchor[i] = (-h[i]-s[i])/v[i]; } else { region[i] = (s[i] > h[i]); tanchor[i] = (h[i]-s[i])/v[i]; } } else { region[i] = 0; tanchor[i] = 2; // this will never be a valid tanchor } } // compute d|d|^2/dt for t=0. if it's >= 0 then p1 is the closest point dReal t=0; dReal dd2dt = 0; for (i=0; i<3; i++) dd2dt -= (region[i] ? v2[i] : 0) * tanchor[i]; if (dd2dt >= 0) goto got_answer; do { // find the point on the line that is at the next clip plane boundary dReal next_t = 1; for (i=0; i<3; i++) { if (tanchor[i] > t && tanchor[i] < 1 && tanchor[i] < next_t) next_t = tanchor[i]; } // compute d|d|^2/dt for the next t dReal next_dd2dt = 0; for (i=0; i<3; i++) { next_dd2dt += (region[i] ? v2[i] : 0) * (next_t - tanchor[i]); } // if the sign of d|d|^2/dt has changed, solution = the crossover point if (next_dd2dt >= 0) { dReal m = (next_dd2dt-dd2dt)/(next_t - t); t -= dd2dt/m; goto got_answer; } // advance to the next anchor point / region for (i=0; i<3; i++) { if (tanchor[i] == next_t) { tanchor[i] = (h[i]-s[i])/v[i]; region[i]++; } } t = next_t; dd2dt = next_dd2dt; } while (t < 1); t = 1; got_answer: // compute closest point on the line for (i=0; i<3; i++) lret[i] = p1[i] + t*tmp[i]; // note: tmp=p2-p1 // compute closest point on the box for (i=0; i<3; i++) { tmp[i] = sign[i] * (s[i] + t*v[i]); if (tmp[i] < -h[i]) tmp[i] = -h[i]; else if (tmp[i] > h[i]) tmp[i] = h[i]; } dMultiply0_331 (s,R,tmp); for (i=0; i<3; i++) bret[i] = s[i] + c[i]; } // given boxes (p1,R1,side1) and (p1,R1,side1), return 1 if they intersect // or 0 if not. int dBoxTouchesBox (const dVector3 p1, const dMatrix3 R1, const dVector3 side1, const dVector3 p2, const dMatrix3 R2, const dVector3 side2) { // two boxes are disjoint if (and only if) there is a separating axis // perpendicular to a face from one box or perpendicular to an edge from // either box. the following tests are derived from: // "OBB Tree: A Hierarchical Structure for Rapid Interference Detection", // S.Gottschalk, M.C.Lin, D.Manocha., Proc of ACM Siggraph 1996. // Rij is R1'*R2, i.e. the relative rotation between R1 and R2. // Qij is abs(Rij) dVector3 p,pp; dReal A1,A2,A3,B1,B2,B3,R11,R12,R13,R21,R22,R23,R31,R32,R33, Q11,Q12,Q13,Q21,Q22,Q23,Q31,Q32,Q33; // get vector from centers of box 1 to box 2, relative to box 1 p[0] = p2[0] - p1[0]; p[1] = p2[1] - p1[1]; p[2] = p2[2] - p1[2]; dMultiply1_331 (pp,R1,p); // get pp = p relative to body 1 // get side lengths / 2 A1 = side1[0]*REAL(0.5); A2 = side1[1]*REAL(0.5); A3 = side1[2]*REAL(0.5); B1 = side2[0]*REAL(0.5); B2 = side2[1]*REAL(0.5); B3 = side2[2]*REAL(0.5); // for the following tests, excluding computation of Rij, in the worst case, // 15 compares, 60 adds, 81 multiplies, and 24 absolutes. // notation: R1=[u1 u2 u3], R2=[v1 v2 v3] // separating axis = u1,u2,u3 R11 = dCalcVectorDot3_44(R1+0,R2+0); R12 = dCalcVectorDot3_44(R1+0,R2+1); R13 = dCalcVectorDot3_44(R1+0,R2+2); Q11 = dFabs(R11); Q12 = dFabs(R12); Q13 = dFabs(R13); if (dFabs(pp[0]) > (A1 + B1*Q11 + B2*Q12 + B3*Q13)) return 0; R21 = dCalcVectorDot3_44(R1+1,R2+0); R22 = dCalcVectorDot3_44(R1+1,R2+1); R23 = dCalcVectorDot3_44(R1+1,R2+2); Q21 = dFabs(R21); Q22 = dFabs(R22); Q23 = dFabs(R23); if (dFabs(pp[1]) > (A2 + B1*Q21 + B2*Q22 + B3*Q23)) return 0; R31 = dCalcVectorDot3_44(R1+2,R2+0); R32 = dCalcVectorDot3_44(R1+2,R2+1); R33 = dCalcVectorDot3_44(R1+2,R2+2); Q31 = dFabs(R31); Q32 = dFabs(R32); Q33 = dFabs(R33); if (dFabs(pp[2]) > (A3 + B1*Q31 + B2*Q32 + B3*Q33)) return 0; // separating axis = v1,v2,v3 if (dFabs(dCalcVectorDot3_41(R2+0,p)) > (A1*Q11 + A2*Q21 + A3*Q31 + B1)) return 0; if (dFabs(dCalcVectorDot3_41(R2+1,p)) > (A1*Q12 + A2*Q22 + A3*Q32 + B2)) return 0; if (dFabs(dCalcVectorDot3_41(R2+2,p)) > (A1*Q13 + A2*Q23 + A3*Q33 + B3)) return 0; // separating axis = u1 x (v1,v2,v3) if (dFabs(pp[2]*R21-pp[1]*R31) > A2*Q31 + A3*Q21 + B2*Q13 + B3*Q12) return 0; if (dFabs(pp[2]*R22-pp[1]*R32) > A2*Q32 + A3*Q22 + B1*Q13 + B3*Q11) return 0; if (dFabs(pp[2]*R23-pp[1]*R33) > A2*Q33 + A3*Q23 + B1*Q12 + B2*Q11) return 0; // separating axis = u2 x (v1,v2,v3) if (dFabs(pp[0]*R31-pp[2]*R11) > A1*Q31 + A3*Q11 + B2*Q23 + B3*Q22) return 0; if (dFabs(pp[0]*R32-pp[2]*R12) > A1*Q32 + A3*Q12 + B1*Q23 + B3*Q21) return 0; if (dFabs(pp[0]*R33-pp[2]*R13) > A1*Q33 + A3*Q13 + B1*Q22 + B2*Q21) return 0; // separating axis = u3 x (v1,v2,v3) if (dFabs(pp[1]*R11-pp[0]*R21) > A1*Q21 + A2*Q11 + B2*Q33 + B3*Q32) return 0; if (dFabs(pp[1]*R12-pp[0]*R22) > A1*Q22 + A2*Q12 + B1*Q33 + B3*Q31) return 0; if (dFabs(pp[1]*R13-pp[0]*R23) > A1*Q23 + A2*Q13 + B1*Q32 + B2*Q31) return 0; return 1; } //**************************************************************************** // other utility functions /*ODE_API */void dInfiniteAABB (dxGeom *geom, dReal aabb[6]) { aabb[0] = -dInfinity; aabb[1] = dInfinity; aabb[2] = -dInfinity; aabb[3] = dInfinity; aabb[4] = -dInfinity; aabb[5] = dInfinity; } //**************************************************************************** // Helpers for Croteam's collider - by Nguyen Binh int dClipEdgeToPlane( dVector3 &vEpnt0, dVector3 &vEpnt1, const dVector4& plPlane) { // calculate distance of edge points to plane dReal fDistance0 = dPointPlaneDistance( vEpnt0 ,plPlane ); dReal fDistance1 = dPointPlaneDistance( vEpnt1 ,plPlane ); // if both points are behind the plane if ( fDistance0 < 0 && fDistance1 < 0 ) { // do nothing return 0; // if both points in front of the plane } else if ( fDistance0 > 0 && fDistance1 > 0 ) { // accept them return 1; // if we have edge/plane intersection } else if ((fDistance0 > 0 && fDistance1 < 0) || ( fDistance0 < 0 && fDistance1 > 0)) { // find intersection point of edge and plane dVector3 vIntersectionPoint; vIntersectionPoint[0]= vEpnt0[0]-(vEpnt0[0]-vEpnt1[0])*fDistance0/(fDistance0-fDistance1); vIntersectionPoint[1]= vEpnt0[1]-(vEpnt0[1]-vEpnt1[1])*fDistance0/(fDistance0-fDistance1); vIntersectionPoint[2]= vEpnt0[2]-(vEpnt0[2]-vEpnt1[2])*fDistance0/(fDistance0-fDistance1); // clamp correct edge to intersection point if ( fDistance0 < 0 ) { dVector3Copy(vIntersectionPoint,vEpnt0); } else { dVector3Copy(vIntersectionPoint,vEpnt1); } return 1; } return 1; } // clip polygon with plane and generate new polygon points void dClipPolyToPlane( const dVector3 avArrayIn[], const int ctIn, dVector3 avArrayOut[], int &ctOut, const dVector4 &plPlane ) { // start with no output points ctOut = 0; int i0 = ctIn-1; // for each edge in input polygon for (int i1=0; i1= 0 ) { // emit point avArrayOut[ctOut][0] = avArrayIn[i0][0]; avArrayOut[ctOut][1] = avArrayIn[i0][1]; avArrayOut[ctOut][2] = avArrayIn[i0][2]; ctOut++; } // if points are on different sides if( (fDistance0 > 0 && fDistance1 < 0) || ( fDistance0 < 0 && fDistance1 > 0) ) { // find intersection point of edge and plane dVector3 vIntersectionPoint; vIntersectionPoint[0]= avArrayIn[i0][0] - (avArrayIn[i0][0]-avArrayIn[i1][0])*fDistance0/(fDistance0-fDistance1); vIntersectionPoint[1]= avArrayIn[i0][1] - (avArrayIn[i0][1]-avArrayIn[i1][1])*fDistance0/(fDistance0-fDistance1); vIntersectionPoint[2]= avArrayIn[i0][2] - (avArrayIn[i0][2]-avArrayIn[i1][2])*fDistance0/(fDistance0-fDistance1); // emit intersection point avArrayOut[ctOut][0] = vIntersectionPoint[0]; avArrayOut[ctOut][1] = vIntersectionPoint[1]; avArrayOut[ctOut][2] = vIntersectionPoint[2]; ctOut++; } } } void dClipPolyToCircle(const dVector3 avArrayIn[], const int ctIn, dVector3 avArrayOut[], int &ctOut, const dVector4 &plPlane ,dReal fRadius) { // start with no output points ctOut = 0; int i0 = ctIn-1; // for each edge in input polygon for (int i1=0; i1= 0 ) { // emit point if (dVector3LengthSquare(avArrayIn[i0]) <= fRadius*fRadius) { avArrayOut[ctOut][0] = avArrayIn[i0][0]; avArrayOut[ctOut][1] = avArrayIn[i0][1]; avArrayOut[ctOut][2] = avArrayIn[i0][2]; ctOut++; } } // if points are on different sides if( (fDistance0 > 0 && fDistance1 < 0) || ( fDistance0 < 0 && fDistance1 > 0) ) { // find intersection point of edge and plane dVector3 vIntersectionPoint; vIntersectionPoint[0]= avArrayIn[i0][0] - (avArrayIn[i0][0]-avArrayIn[i1][0])*fDistance0/(fDistance0-fDistance1); vIntersectionPoint[1]= avArrayIn[i0][1] - (avArrayIn[i0][1]-avArrayIn[i1][1])*fDistance0/(fDistance0-fDistance1); vIntersectionPoint[2]= avArrayIn[i0][2] - (avArrayIn[i0][2]-avArrayIn[i1][2])*fDistance0/(fDistance0-fDistance1); // emit intersection point if (dVector3LengthSquare(avArrayIn[i0]) <= fRadius*fRadius) { avArrayOut[ctOut][0] = vIntersectionPoint[0]; avArrayOut[ctOut][1] = vIntersectionPoint[1]; avArrayOut[ctOut][2] = vIntersectionPoint[2]; ctOut++; } } } } ode-0.16/ode/src/fastltsolve.cpp0000664000175200017520000002426013403272463013556 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* * L1Transposed Equation Solving Routines * Copyright (c) 2017 Oleh Derevenko, odar@eleks.com (change all "a" to "e") */ #include #include #include #include "config.h" #include "threaded_solver_ldlt.h" #include "threading_base.h" #include "resource_control.h" #include "error.h" #include "fastltsolve_impl.h" /*static */ void ThreadedEquationSolverLDLT::estimateCooperativeSolvingL1TransposedResourceRequirements( dxResourceRequirementDescriptor *summaryRequirementsDescriptor, unsigned allowedThreadCount, unsigned rowCount) { dxThreadingBase *threading = summaryRequirementsDescriptor->getrelatedThreading(); unsigned limitedThreadCount = restrictSolvingL1TransposedAllowedThreadCount(threading, allowedThreadCount, rowCount); if (limitedThreadCount > 1) { doEstimateCooperativeSolvingL1TransposedResourceRequirementsValidated(summaryRequirementsDescriptor, allowedThreadCount, rowCount); } } /*static */ void ThreadedEquationSolverLDLT::cooperativelySolveL1Transposed( dxRequiredResourceContainer *resourceContainer, unsigned allowedThreadCount, const dReal *L, dReal *b, unsigned rowCount, unsigned rowSkip) { dIASSERT(rowCount != 0); dxThreadingBase *threading = resourceContainer->getThreadingInstance(); unsigned limitedThreadCount = restrictSolvingL1TransposedAllowedThreadCount(threading, allowedThreadCount, rowCount); if (limitedThreadCount <= 1) { solveL1Transposed(L, b, rowCount, rowSkip); } else { doCooperativelySolveL1TransposedValidated(resourceContainer, limitedThreadCount, L, b, rowCount, rowSkip); } } /*static */ unsigned ThreadedEquationSolverLDLT::restrictSolvingL1TransposedAllowedThreadCount( dxThreadingBase *threading, unsigned allowedThreadCount, unsigned rowCount) { unsigned limitedThreadCount = 1; #if dCOOPERATIVE_ENABLED const unsigned int blockStep = SL1T_BLOCK_SIZE; // Required by the implementation unsigned solvingBlockCount = deriveSolvingL1TransposedBlockCount(rowCount, blockStep); dIASSERT(deriveSolvingL1TransposedThreadCount(SL1T_COOPERATIVE_BLOCK_COUNT_MINIMUM, 2) > 1); if (solvingBlockCount >= SL1T_COOPERATIVE_BLOCK_COUNT_MINIMUM) { limitedThreadCount = threading->calculateThreadingLimitedThreadCount(allowedThreadCount, true); } #endif // #if dCOOPERATIVE_ENABLED return limitedThreadCount; } /*static */ void ThreadedEquationSolverLDLT::doEstimateCooperativeSolvingL1TransposedResourceRequirementsValidated( dxResourceRequirementDescriptor *summaryRequirementsDescriptor, unsigned allowedThreadCount, unsigned rowCount) { const unsigned int blockStep = SL1T_BLOCK_SIZE; // Required by the implementation unsigned blockCount = deriveSolvingL1TransposedBlockCount(rowCount, blockStep); dIASSERT(blockCount >= 1); unsigned threadCountToUse = deriveSolvingL1TransposedThreadCount(blockCount, allowedThreadCount); dIASSERT(threadCountToUse > 1); unsigned simultaneousCallCount = 1 + (threadCountToUse - 1); SolvingL1TransposedMemoryEstimates solvingMemoryEstimates; sizeint solvingMemoryRequired = estimateCooperativelySolvingL1TransposedMemoryRequirement(rowCount, solvingMemoryEstimates); const unsigned solvingAlignmentRequired = ALLOCATION_DEFAULT_ALIGNMENT; unsigned featureRequirement = dxResourceRequirementDescriptor::STOCK_CALLWAIT_REQUIRED; summaryRequirementsDescriptor->mergeAnotherDescriptorIn(solvingMemoryRequired, solvingAlignmentRequired, simultaneousCallCount, featureRequirement); } /*static */ void ThreadedEquationSolverLDLT::doCooperativelySolveL1TransposedValidated( dxRequiredResourceContainer *resourceContainer, unsigned allowedThreadCount, const dReal *L, dReal *b, unsigned rowCount, unsigned rowSkip) { dIASSERT(allowedThreadCount > 1); const unsigned int blockStep = SL1T_BLOCK_SIZE; // Required by the implementation unsigned blockCount = deriveSolvingL1TransposedBlockCount(rowCount, blockStep); dIASSERT(blockCount >= 1); unsigned threadCountToUse = deriveSolvingL1TransposedThreadCount(blockCount, allowedThreadCount); dIASSERT(threadCountToUse > 1); dCallWaitID completionWait = resourceContainer->getStockCallWait(); dAASSERT(completionWait != NULL); atomicord32 blockCompletionProgress; cellindexint *blockProgressDescriptors; SolveL1TransposedCellContext *cellContexts; SolvingL1TransposedMemoryEstimates solvingMemoryEstimates; sizeint solvingMemoryRequired = estimateCooperativelySolvingL1TransposedMemoryRequirement(rowCount, solvingMemoryEstimates); dIASSERT(solvingMemoryRequired <= resourceContainer->getMemoryBufferSize()); void *bufferAllocated = resourceContainer->getMemoryBufferPointer(); dIASSERT(bufferAllocated != NULL); dIASSERT(dALIGN_PTR(bufferAllocated, ALLOCATION_DEFAULT_ALIGNMENT) == bufferAllocated); void *bufferCurrentLocation = bufferAllocated; bufferCurrentLocation = markCooperativelySolvingL1TransposedMemoryStructuresOut(bufferCurrentLocation, solvingMemoryEstimates, blockProgressDescriptors, cellContexts); dIVERIFY(bufferCurrentLocation <= (uint8 *)bufferAllocated + solvingMemoryRequired); initializeCooperativelySolveL1TransposedMemoryStructures(rowCount, blockCompletionProgress, blockProgressDescriptors, cellContexts); dCallReleaseeID calculationFinishReleasee; SolveL1TransposedWorkerContext workerContext; // The variable must exist in the outer scope workerContext.init(L, b, rowCount, rowSkip, blockCompletionProgress, blockProgressDescriptors, cellContexts); dxThreadingBase *threading = resourceContainer->getThreadingInstance(); threading->PostThreadedCall(NULL, &calculationFinishReleasee, threadCountToUse - 1, NULL, completionWait, &solveL1Transposed_completion_callback, NULL, 0, "SolveL1Transposed Completion"); threading->PostThreadedCallsGroup(NULL, threadCountToUse - 1, calculationFinishReleasee, &solveL1Transposed_worker_callback, &workerContext, "SolveL1Transposed Work"); participateSolvingL1Transposed(L, b, rowCount, rowSkip, blockCompletionProgress, blockProgressDescriptors, cellContexts, threadCountToUse - 1); threading->WaitThreadedCallExclusively(NULL, completionWait, NULL, "SolveL1Transposed End Wait"); } /*static */ int ThreadedEquationSolverLDLT::solveL1Transposed_worker_callback(void *callContext, dcallindex_t callInstanceIndex, dCallReleaseeID dUNUSED(callThisReleasee)) { SolveL1TransposedWorkerContext *ptrContext = (SolveL1TransposedWorkerContext *)callContext; solveL1Transposed_worker(*ptrContext, dCAST_TO_SMALLER(unsigned, callInstanceIndex)); return 1; } /*static */ void ThreadedEquationSolverLDLT::solveL1Transposed_worker(SolveL1TransposedWorkerContext &ref_context, unsigned ownThreadIndex) { const unsigned blockStep = SL1T_BLOCK_SIZE; participateSolvingL1Transposed(ref_context.m_L, ref_context.m_b, ref_context.m_rowCount, ref_context.m_rowSkip, *ref_context.m_ptrBlockCompletionProgress, ref_context.m_blockProgressDescriptors, ref_context.m_cellContexts, ownThreadIndex); } /*static */ int ThreadedEquationSolverLDLT::solveL1Transposed_completion_callback(void *dUNUSED(callContext), dcallindex_t dUNUSED(callInstanceIndex), dCallReleaseeID dUNUSED(callThisReleasee)) { return 1; } ////////////////////////////////////////////////////////////////////////// // Public interface functions /*extern ODE_API */ void dSolveL1T(const dReal *L, dReal *B, int rowCount, int rowSkip) { dAASSERT(rowCount != 0); if (rowCount != 0) { dAASSERT(L != NULL); dAASSERT(B != NULL); solveL1Transposed<1>(L, B, rowCount, rowSkip); } } /*extern ODE_API */ void dEstimateCooperativelySolveL1TransposedResourceRequirements(dResourceRequirementsID requirements, unsigned maximalAllowedThreadCount, unsigned maximalRowCount) { dAASSERT(requirements != NULL); dxResourceRequirementDescriptor *requirementsDescriptor = (dxResourceRequirementDescriptor *)requirements; ThreadedEquationSolverLDLT::estimateCooperativeSolvingL1TransposedResourceRequirements(requirementsDescriptor, maximalAllowedThreadCount, maximalRowCount); } /*extern ODE_API */ void dCooperativelySolveL1Transposed(dResourceContainerID resources, unsigned allowedThreadCount, const dReal *L, dReal *b, unsigned rowCount, unsigned rowSkip) { dAASSERT(resources != NULL); dxRequiredResourceContainer *resourceContainer = (dxRequiredResourceContainer *)resources; ThreadedEquationSolverLDLT::cooperativelySolveL1Transposed(resourceContainer, allowedThreadCount, L, b, rowCount, rowSkip); } ode-0.16/ode/src/threading_impl_templates.h0000664000175200017520000012642613403272463015730 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * Threading implementation templates file. * * Copyright (C) 2011-2012 Oleh Derevenko. All rights reserved. * * e-mail: odar@eleks.com (change all "a" to "e") * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* * Job list and Mutex group implementation templates for built-in threading * support provider. */ #ifndef _ODE_THREADING_IMPL_TEMPLATES_H_ #define _ODE_THREADING_IMPL_TEMPLATES_H_ #include #include #include #include "objects.h" #include #define dMAKE_JOBINSTANCE_RELEASEE(job_instance) ((dCallReleaseeID)(job_instance)) #define dMAKE_RELEASEE_JOBINSTANCE(releasee) ((dxThreadedJobInfo *)(releasee)) template class dxtemplateMutexGroup { private: dxtemplateMutexGroup() {} ~dxtemplateMutexGroup() {} public: static dxtemplateMutexGroup *AllocateInstance(dmutexindex_t Mutex_count); static void FreeInstance(dxtemplateMutexGroup *mutex_group); private: bool InitializeMutexArray(dmutexindex_t Mutex_count); void FinalizeMutexArray(dmutexindex_t Mutex_count); public: void LockMutex(dmutexindex_t mutex_index) { dIASSERT(mutex_index < m_un.m_mutex_count); m_Mutex_array[mutex_index].LockMutex(); } bool TryLockMutex(dmutexindex_t mutex_index) { dIASSERT(mutex_index < m_un.m_mutex_count); return m_Mutex_array[mutex_index].TryLockMutex(); } void UnlockMutex(dmutexindex_t mutex_index) { dIASSERT(mutex_index < m_un.m_mutex_count); m_Mutex_array[mutex_index].UnlockMutex(); } private: union { dmutexindex_t m_mutex_count; unsigned long m_reserved_for_allignment[2]; } m_un; tThreadMutex m_Mutex_array[1]; }; template class dxtemplateCallWait: public dBase { public: dxtemplateCallWait() {} ~dxtemplateCallWait() { DoFinalizeObject(); } bool InitializeObject() { return DoInitializeObject(); } private: bool DoInitializeObject() { return m_wait_wakeup.InitializeObject(); } void DoFinalizeObject() { /* Do nothing */ } public: typedef dxtemplateCallWait dxCallWait; public: void ResetTheWait() { m_wait_wakeup.ResetWakeup(); } void SignalTheWait() { m_wait_wakeup.WakeupAllThreads(); } bool PerformWaiting(const dThreadedWaitTime *timeout_time_ptr/*=NULL*/) { return m_wait_wakeup.WaitWakeup(timeout_time_ptr); } public: static void AbstractSignalTheWait(void *wait_wakeup_ptr) { ((dxCallWait *)wait_wakeup_ptr)->SignalTheWait(); } private: tThreadWakeup m_wait_wakeup; }; #if dBUILTIN_THREADING_IMPL_ENABLED template class dxtemplateThreadedLull { public: dxtemplateThreadedLull(): m_registrant_count(0), m_alarm_wakeup() {} ~dxtemplateThreadedLull() { dIASSERT(m_registrant_count == 0); DoFinalizeObject(); } bool InitializeObject() { return DoInitializeObject(); } private: bool DoInitializeObject() { return m_alarm_wakeup.InitializeObject(); } void DoFinalizeObject() { /* Do nothing */ } private: typedef typename tAtomicsProvider::atomicord_t atomicord_t; public: void RegisterToLull() { tAtomicsProvider::IncrementTargetNoRet(&m_registrant_count); } void WaitForLullAlarm() { dIASSERT(m_registrant_count != 0); m_alarm_wakeup.WaitWakeup(NULL); } void UnregisterFromLull() { tAtomicsProvider::DecrementTargetNoRet(&m_registrant_count); } void SignalLullAlarmIfAnyRegistrants() { if (tatomic_test_required ? (tAtomicsProvider::QueryTargetValue(&m_registrant_count) != 0) : (m_registrant_count != 0)) { m_alarm_wakeup.WakeupAThread(); } } private: atomicord_t m_registrant_count; tThreadWakeup m_alarm_wakeup; }; #endif // #if dBUILTIN_THREADING_IMPL_ENABLED struct dxThreadedJobInfo: public dBase { dxThreadedJobInfo() {} explicit dxThreadedJobInfo(void *): m_next_job(NULL) {} void AssignJobData(ddependencycount_t dependencies_count, dxThreadedJobInfo *dependent_job, void *call_wait, int *fault_accumulator_ptr, dThreadedCallFunction *call_function, void *call_context, dcallindex_t call_index) { m_dependencies_count = dependencies_count; m_dependent_job = dependent_job; m_call_wait = call_wait; m_fault_accumulator_ptr = fault_accumulator_ptr; m_call_fault = 0; m_call_function = call_function; m_call_context = call_context; m_call_index = call_index; } bool InvokeCallFunction() { int call_result = m_call_function(m_call_context, m_call_index, dMAKE_JOBINSTANCE_RELEASEE(this)); return call_result != 0; } dxThreadedJobInfo *m_next_job; dxThreadedJobInfo **m_prev_job_next_ptr; ddependencycount_t m_dependencies_count; dxThreadedJobInfo *m_dependent_job; void *m_call_wait; int *m_fault_accumulator_ptr; int m_call_fault; dThreadedCallFunction *m_call_function; void *m_call_context; dcallindex_t m_call_index; }; template class dxtemplateThreadingLockHelper { public: dxtemplateThreadingLockHelper(tThreadMutex &mutex_instance): m_mutex_instance(mutex_instance), m_lock_indicator_flag(false) { LockMutex(); } ~dxtemplateThreadingLockHelper() { if (m_lock_indicator_flag) { UnlockMutex(); } } void LockMutex() { dIASSERT(!m_lock_indicator_flag); m_mutex_instance.LockMutex(); m_lock_indicator_flag = true; } void UnlockMutex() { dIASSERT(m_lock_indicator_flag); m_mutex_instance.UnlockMutex(); m_lock_indicator_flag = false; } private: tThreadMutex &m_mutex_instance; bool m_lock_indicator_flag; }; template class dxtemplateJobListContainer { public: dxtemplateJobListContainer(): m_job_list(NULL), m_info_pool((atomicptr_t)NULL), m_pool_access_lock(), m_list_access_lock(), m_info_wait_lull(), m_info_count_known_to_be_preallocated(0) { } ~dxtemplateJobListContainer() { dIASSERT(m_job_list == NULL); // Would not it be nice to wait for jobs to complete before deleting the list? FreeJobInfoPoolInfos(); DoFinalizeObject(); } bool InitializeObject() { return DoInitializeObject(); } private: bool DoInitializeObject() { return m_pool_access_lock.InitializeObject() && m_list_access_lock.InitializeObject() && m_info_wait_lull.InitializeObject(); } void DoFinalizeObject() { /* Do nothing */ } public: typedef tAtomicsProvider dxAtomicsProvider; typedef typename tAtomicsProvider::atomicord_t atomicord_t; typedef typename tAtomicsProvider::atomicptr_t atomicptr_t; typedef tThreadMutex dxThreadMutex; typedef dxtemplateThreadingLockHelper dxMutexLockHelper; typedef void dWaitSignallingFunction(void *job_call_wait); public: dxThreadedJobInfo *ReleaseAJobAndPickNextPendingOne( dxThreadedJobInfo *job_to_release, bool job_result, dWaitSignallingFunction *wait_signal_proc_ptr, bool &out_last_job_flag); private: dxThreadedJobInfo *PickNextPendingJob(bool &out_last_job_flag); void ReleaseAJob(dxThreadedJobInfo *job_instance, bool job_result, dWaitSignallingFunction *wait_signal_proc_ptr); public: inline dxThreadedJobInfo *AllocateJobInfoFromPool(); void QueueJobForProcessing(dxThreadedJobInfo *job_instance); void AlterJobProcessingDependencies(dxThreadedJobInfo *job_instance, ddependencychange_t dependencies_count_change, bool &out_job_has_become_ready); private: inline ddependencycount_t SmartAddJobDependenciesCount(dxThreadedJobInfo *job_instance, ddependencychange_t dependencies_count_change); inline void InsertJobInfoIntoListHead(dxThreadedJobInfo *job_instance); inline void RemoveJobInfoFromList(dxThreadedJobInfo *job_instance); dxThreadedJobInfo *ExtractJobInfoFromPoolOrAllocate(); inline void ReleaseJobInfoIntoPool(dxThreadedJobInfo *job_instance); private: void FreeJobInfoPoolInfos(); public: bool EnsureNumberOfJobInfosIsPreallocated(ddependencycount_t required_info_count); private: bool DoPreallocateJobInfos(ddependencycount_t required_info_count); public: bool IsJobListReadyForShutdown() const { return m_job_list == NULL; } private: dxThreadedJobInfo *m_job_list; volatile atomicptr_t m_info_pool; // dxThreadedJobInfo * tThreadMutex m_pool_access_lock; tThreadMutex m_list_access_lock; tThreadLull m_info_wait_lull; ddependencycount_t m_info_count_known_to_be_preallocated; }; typedef void (dxThreadReadyToServeCallback)(void *callback_context); #if dBUILTIN_THREADING_IMPL_ENABLED template class dxtemplateJobListThreadedHandler { public: dxtemplateJobListThreadedHandler(tJobListContainer *list_container_ptr): m_job_list_ptr(list_container_ptr), m_processing_wakeup(), m_active_thread_count(0), m_shutdown_requested(0) { } ~dxtemplateJobListThreadedHandler() { dIASSERT(m_active_thread_count == 0); DoFinalizeObject(); } bool InitializeObject() { return DoInitializeObject(); } private: bool DoInitializeObject() { return m_processing_wakeup.InitializeObject(); } void DoFinalizeObject() { /* Do nothing */ } public: typedef dxtemplateCallWait dxCallWait; public: inline void ProcessActiveJobAddition(); inline void PrepareForWaitingAJobCompletion(); public: inline unsigned RetrieveActiveThreadsCount(); inline void StickToJobsProcessing(dxThreadReadyToServeCallback *readiness_callback/*=NULL*/, void *callback_context/*=NULL*/); private: void PerformJobProcessingUntilShutdown(); void PerformJobProcessingSession(); void BlockAsIdleThread(); void ActivateAnIdleThread(); public: inline void ShutdownProcessing(); inline void CleanupForRestart(); private: bool IsShutdownRequested() const { return m_shutdown_requested != 0; } private: typedef typename tJobListContainer::dxAtomicsProvider dxAtomicsProvider; typedef typename tJobListContainer::atomicord_t atomicord_t; atomicord_t GetActiveThreadsCount() const { return m_active_thread_count; } void RegisterAsActiveThread() { dxAtomicsProvider::template AddValueToTarget((volatile void *)&m_active_thread_count, 1); } void UnregisterAsActiveThread() { dxAtomicsProvider::template AddValueToTarget((volatile void *)&m_active_thread_count, -1); } private: tJobListContainer *m_job_list_ptr; tThreadWakeup m_processing_wakeup; volatile atomicord_t m_active_thread_count; int m_shutdown_requested; }; #endif // #if dBUILTIN_THREADING_IMPL_ENABLED template class dxtemplateJobListSelfHandler { public: dxtemplateJobListSelfHandler(tJobListContainer *list_container_ptr): m_job_list_ptr(list_container_ptr) { } ~dxtemplateJobListSelfHandler() { // Do nothing } bool InitializeObject() { return true; } public: typedef dxtemplateCallWait dxCallWait; public: inline void ProcessActiveJobAddition(); inline void PrepareForWaitingAJobCompletion(); public: inline unsigned RetrieveActiveThreadsCount(); inline void StickToJobsProcessing(dxThreadReadyToServeCallback *readiness_callback/*=NULL*/, void *callback_context/*=NULL*/); private: void PerformJobProcessingUntilExhaustion(); void PerformJobProcessingSession(); public: inline void ShutdownProcessing(); inline void CleanupForRestart(); private: tJobListContainer *m_job_list_ptr; }; struct dIMutexGroup; struct dxICallWait; class dxIThreadingImplementation { public: virtual void FreeInstance() = 0; public: virtual dIMutexGroup *AllocMutexGroup(dmutexindex_t Mutex_count) = 0; virtual void FreeMutexGroup(dIMutexGroup *mutex_group) = 0; virtual void LockMutexGroupMutex(dIMutexGroup *mutex_group, dmutexindex_t mutex_index) = 0; // virtual bool TryLockMutexGroupMutex(dIMutexGroup *mutex_group, dmutexindex_t mutex_index) = 0; virtual void UnlockMutexGroupMutex(dIMutexGroup *mutex_group, dmutexindex_t mutex_index) = 0; public: virtual dxICallWait *AllocACallWait() = 0; virtual void ResetACallWait(dxICallWait *call_wait) = 0; virtual void FreeACallWait(dxICallWait *call_wait) = 0; public: virtual bool PreallocateJobInfos(ddependencycount_t max_simultaneous_calls_estimate) = 0; virtual void ScheduleNewJob(int *fault_accumulator_ptr/*=NULL*/, dCallReleaseeID *out_post_releasee_ptr/*=NULL*/, ddependencycount_t dependencies_count, dCallReleaseeID dependent_releasee/*=NULL*/, dxICallWait *call_wait/*=NULL*/, dThreadedCallFunction *call_func, void *call_context, dcallindex_t instance_index) = 0; virtual void AlterJobDependenciesCount(dCallReleaseeID target_releasee, ddependencychange_t dependencies_count_change) = 0; virtual void WaitJobCompletion(int *out_wait_status_ptr/*=NULL*/, dxICallWait *call_wait, const dThreadedWaitTime *timeout_time_ptr/*=NULL*/) = 0; public: virtual unsigned RetrieveActiveThreadsCount() = 0; virtual void StickToJobsProcessing(dxThreadReadyToServeCallback *readiness_callback/*=NULL*/, void *callback_context/*=NULL*/) = 0; virtual void ShutdownProcessing() = 0; virtual void CleanupForRestart() = 0; }; template class dxtemplateThreadingImplementation: public dBase, public dxIThreadingImplementation { public: dxtemplateThreadingImplementation(): dBase(), m_list_container(), m_list_handler(&m_list_container) { } virtual ~dxtemplateThreadingImplementation() { DoFinalizeObject(); } bool InitializeObject() { return DoInitializeObject(); } private: bool DoInitializeObject() { return m_list_container.InitializeObject() && m_list_handler.InitializeObject(); } void DoFinalizeObject() { /* Do nothing */ } protected: virtual void FreeInstance(); private: typedef dxtemplateMutexGroup dxMutexGroup; typedef typename tJobListHandler::dxCallWait dxCallWait; protected: virtual dIMutexGroup *AllocMutexGroup(dmutexindex_t Mutex_count); virtual void FreeMutexGroup(dIMutexGroup *mutex_group); virtual void LockMutexGroupMutex(dIMutexGroup *mutex_group, dmutexindex_t mutex_index); // virtual bool TryLockMutexGroupMutex(dIMutexGroup *mutex_group, dmutexindex_t mutex_index); virtual void UnlockMutexGroupMutex(dIMutexGroup *mutex_group, dmutexindex_t mutex_index); protected: virtual dxICallWait *AllocACallWait(); virtual void ResetACallWait(dxICallWait *call_wait); virtual void FreeACallWait(dxICallWait *call_wait); protected: virtual bool PreallocateJobInfos(ddependencycount_t max_simultaneous_calls_estimate); virtual void ScheduleNewJob(int *fault_accumulator_ptr/*=NULL*/, dCallReleaseeID *out_post_releasee_ptr/*=NULL*/, ddependencycount_t dependencies_count, dCallReleaseeID dependent_releasee/*=NULL*/, dxICallWait *call_wait/*=NULL*/, dThreadedCallFunction *call_func, void *call_context, dcallindex_t instance_index); virtual void AlterJobDependenciesCount(dCallReleaseeID target_releasee, ddependencychange_t dependencies_count_change); virtual void WaitJobCompletion(int *out_wait_status_ptr/*=NULL*/, dxICallWait *call_wait, const dThreadedWaitTime *timeout_time_ptr/*=NULL*/); protected: virtual unsigned RetrieveActiveThreadsCount(); virtual void StickToJobsProcessing(dxThreadReadyToServeCallback *readiness_callback/*=NULL*/, void *callback_context/*=NULL*/); virtual void ShutdownProcessing(); virtual void CleanupForRestart(); private: tJobListContainer m_list_container; tJobListHandler m_list_handler; }; /************************************************************************/ /* Implementation of dxtemplateMutexGroup */ /************************************************************************/ template /*static */dxtemplateMutexGroup *dxtemplateMutexGroup::AllocateInstance(dmutexindex_t Mutex_count) { dAASSERT(Mutex_count != 0); const dxtemplateMutexGroup *const dummy_group = (dxtemplateMutexGroup *)(sizeint)8; const sizeint size_requited = ((sizeint)(&dummy_group->m_Mutex_array) - (sizeint)dummy_group) + Mutex_count * sizeof(tThreadMutex); dxtemplateMutexGroup *mutex_group = (dxtemplateMutexGroup *)dAlloc(size_requited); if (mutex_group != NULL) { mutex_group->m_un.m_mutex_count = Mutex_count; if (!mutex_group->InitializeMutexArray(Mutex_count)) { dFree((void *)mutex_group, size_requited); mutex_group = NULL; } } return mutex_group; } template /*static */void dxtemplateMutexGroup::FreeInstance(dxtemplateMutexGroup *mutex_group) { if (mutex_group != NULL) { dmutexindex_t Mutex_count = mutex_group->m_un.m_mutex_count; mutex_group->FinalizeMutexArray(Mutex_count); const sizeint anyting_not_zero = 2 * sizeof(sizeint); const dxtemplateMutexGroup *const dummy_group = (dxtemplateMutexGroup *)anyting_not_zero; const sizeint size_requited = ((sizeint)(&dummy_group->m_Mutex_array) - (sizeint)dummy_group) + Mutex_count * sizeof(tThreadMutex); dFree((void *)mutex_group, size_requited); } } template bool dxtemplateMutexGroup::InitializeMutexArray(dmutexindex_t Mutex_count) { bool any_fault = false; dmutexindex_t mutex_index = 0; for (; mutex_index != Mutex_count; ++mutex_index) { tThreadMutex *mutex_storage = m_Mutex_array + mutex_index; new(mutex_storage) tThreadMutex; if (!mutex_storage->InitializeObject()) { mutex_storage->tThreadMutex::~tThreadMutex(); any_fault = true; break; } } if (any_fault) { FinalizeMutexArray(mutex_index); } bool init_result = !any_fault; return init_result; } template void dxtemplateMutexGroup::FinalizeMutexArray(dmutexindex_t Mutex_count) { for (dmutexindex_t mutex_index = 0; mutex_index != Mutex_count; ++mutex_index) { tThreadMutex *mutex_storage = m_Mutex_array + mutex_index; mutex_storage->tThreadMutex::~tThreadMutex(); } } /************************************************************************/ /* Implementation of dxtemplateJobListContainer */ /************************************************************************/ template dxThreadedJobInfo *dxtemplateJobListContainer::ReleaseAJobAndPickNextPendingOne( dxThreadedJobInfo *job_to_release, bool job_result, dWaitSignallingFunction *wait_signal_proc_ptr, bool &out_last_job_flag) { if (job_to_release != NULL) { ReleaseAJob(job_to_release, job_result, wait_signal_proc_ptr); } dxMutexLockHelper list_access(m_list_access_lock); dxThreadedJobInfo *picked_job = PickNextPendingJob(out_last_job_flag); return picked_job; } template dxThreadedJobInfo *dxtemplateJobListContainer::PickNextPendingJob( bool &out_last_job_flag) { dxThreadedJobInfo *current_job = m_job_list; bool last_job_flag = false; while (current_job != NULL) { if (current_job->m_dependencies_count == 0) { // It is OK to assign in unsafe manner - dependencies count should not be changed // after the job has become ready for execution current_job->m_dependencies_count = 1; last_job_flag = current_job->m_next_job == NULL; RemoveJobInfoFromList(current_job); break; } current_job = current_job->m_next_job; } out_last_job_flag = last_job_flag; return current_job; } template void dxtemplateJobListContainer::ReleaseAJob( dxThreadedJobInfo *job_instance, bool job_result, dWaitSignallingFunction *wait_signal_proc_ptr) { dxThreadedJobInfo *current_job = job_instance; if (!job_result) { // Accumulate call fault (be careful to not reset it!!!) current_job->m_call_fault = 1; } bool job_dequeued = true; dIASSERT(current_job->m_prev_job_next_ptr == NULL); while (true) { dIASSERT(current_job->m_dependencies_count != 0); ddependencycount_t new_dependencies_count = SmartAddJobDependenciesCount(current_job, -1); if (new_dependencies_count != 0 || !job_dequeued) { break; } void *job_call_wait = current_job->m_call_wait; if (job_call_wait != NULL) { wait_signal_proc_ptr(job_call_wait); } int call_fault = current_job->m_call_fault; if (current_job->m_fault_accumulator_ptr) { *current_job->m_fault_accumulator_ptr = call_fault; } dxThreadedJobInfo *dependent_job = current_job->m_dependent_job; ReleaseJobInfoIntoPool(current_job); if (dependent_job == NULL) { break; } if (call_fault) { // Accumulate call fault (be careful to not reset it!!!) dependent_job->m_call_fault = 1; } current_job = dependent_job; job_dequeued = dependent_job->m_prev_job_next_ptr == NULL; } } template dxThreadedJobInfo *dxtemplateJobListContainer::AllocateJobInfoFromPool() { // No locking is necessary dxThreadedJobInfo *job_instance = ExtractJobInfoFromPoolOrAllocate(); return job_instance; } template void dxtemplateJobListContainer::QueueJobForProcessing(dxThreadedJobInfo *job_instance) { dxMutexLockHelper list_access(m_list_access_lock); InsertJobInfoIntoListHead(job_instance); } template void dxtemplateJobListContainer::AlterJobProcessingDependencies(dxThreadedJobInfo *job_instance, ddependencychange_t dependencies_count_change, bool &out_job_has_become_ready) { // Dependencies should not be changed when job has already become ready for execution dIASSERT(job_instance->m_dependencies_count != 0); // It's OK that access is not atomic - that is to be handled by external logic dIASSERT(dependencies_count_change < 0 ? (job_instance->m_dependencies_count >= (ddependencycount_t)(-dependencies_count_change)) : ((ddependencycount_t)(-(ddependencychange_t)job_instance->m_dependencies_count) > (ddependencycount_t)dependencies_count_change)); ddependencycount_t new_dependencies_count = SmartAddJobDependenciesCount(job_instance, dependencies_count_change); out_job_has_become_ready = new_dependencies_count == 0; } template ddependencycount_t dxtemplateJobListContainer::SmartAddJobDependenciesCount( dxThreadedJobInfo *job_instance, ddependencychange_t dependencies_count_change) { ddependencycount_t new_dependencies_count = tAtomicsProvider::template AddValueToTarget((volatile void *)&job_instance->m_dependencies_count, dependencies_count_change) + dependencies_count_change; return new_dependencies_count; } template void dxtemplateJobListContainer::InsertJobInfoIntoListHead( dxThreadedJobInfo *job_instance) { dxThreadedJobInfo *job_list_head = m_job_list; job_instance->m_next_job = job_list_head; if (job_list_head != NULL) { job_list_head->m_prev_job_next_ptr = &job_instance->m_next_job; } job_instance->m_prev_job_next_ptr = &m_job_list; m_job_list = job_instance; } template void dxtemplateJobListContainer::RemoveJobInfoFromList( dxThreadedJobInfo *job_instance) { if (job_instance->m_next_job) { job_instance->m_next_job->m_prev_job_next_ptr = job_instance->m_prev_job_next_ptr; } *job_instance->m_prev_job_next_ptr = job_instance->m_next_job; // Assign NULL to m_prev_job_next_ptr as an indicator that instance has been dequeued job_instance->m_prev_job_next_ptr = NULL; } template dxThreadedJobInfo *dxtemplateJobListContainer::ExtractJobInfoFromPoolOrAllocate() { dxThreadedJobInfo *result_info; bool waited_lull = false; m_info_wait_lull.RegisterToLull(); while (true) { dxThreadedJobInfo *raw_head_info = (dxThreadedJobInfo *)m_info_pool; if (raw_head_info == NULL) { result_info = new dxThreadedJobInfo(); if (result_info != NULL) { break; } m_info_wait_lull.WaitForLullAlarm(); waited_lull = true; } // Extraction must be locked so that other thread does not "steal" head info, // use it and then reinsert back with a different "next" dxMutexLockHelper pool_access(m_pool_access_lock); dxThreadedJobInfo *head_info = (dxThreadedJobInfo *)m_info_pool; // Head info must be re-read after mutex had been locked if (head_info != NULL) { dxThreadedJobInfo *next_info = head_info->m_next_job; if (tAtomicsProvider::CompareExchangeTargetPtr(&m_info_pool, (atomicptr_t)head_info, (atomicptr_t)next_info)) { result_info = head_info; break; } } } m_info_wait_lull.UnregisterFromLull(); if (waited_lull) { // It is necessary to re-signal lull alarm if current thread was waiting as // there might be other threads waiting which might have not received alarm signal. m_info_wait_lull.SignalLullAlarmIfAnyRegistrants(); } return result_info; } template void dxtemplateJobListContainer::ReleaseJobInfoIntoPool( dxThreadedJobInfo *job_instance) { while (true) { dxThreadedJobInfo *next_info = (dxThreadedJobInfo *)m_info_pool; job_instance->m_next_job = next_info; if (tAtomicsProvider::CompareExchangeTargetPtr(&m_info_pool, (atomicptr_t)next_info, (atomicptr_t)job_instance)) { break; } } m_info_wait_lull.SignalLullAlarmIfAnyRegistrants(); } template void dxtemplateJobListContainer::FreeJobInfoPoolInfos() { dxThreadedJobInfo *current_info = (dxThreadedJobInfo *)m_info_pool; while (current_info != NULL) { dxThreadedJobInfo *info_save = current_info; current_info = current_info->m_next_job; delete info_save; } m_info_pool = (atomicptr_t)NULL; } template bool dxtemplateJobListContainer::EnsureNumberOfJobInfosIsPreallocated(ddependencycount_t required_info_count) { bool result = required_info_count <= m_info_count_known_to_be_preallocated || DoPreallocateJobInfos(required_info_count); return result; } template bool dxtemplateJobListContainer::DoPreallocateJobInfos(ddependencycount_t required_info_count) { dIASSERT(required_info_count > m_info_count_known_to_be_preallocated); // Also ensures required_info_count > 0 bool allocation_failure = false; dxThreadedJobInfo *info_pool = (dxThreadedJobInfo *)m_info_pool; ddependencycount_t info_index = 0; for (dxThreadedJobInfo **current_info_ptr = &info_pool; ; ) { dxThreadedJobInfo *current_info = *current_info_ptr; if (current_info == NULL) { current_info = new dxThreadedJobInfo(NULL); if (current_info == NULL) { allocation_failure = true; break; } *current_info_ptr = current_info; } if (++info_index == required_info_count) { m_info_count_known_to_be_preallocated = info_index; break; } current_info_ptr = ¤t_info->m_next_job; } // Make sure m_info_pool was not changed dIASSERT(m_info_pool == NULL || m_info_pool == (atomicptr_t)info_pool); m_info_pool = (atomicptr_t)info_pool; bool result = !allocation_failure; return result; } #if dBUILTIN_THREADING_IMPL_ENABLED /************************************************************************/ /* Implementation of dxtemplateJobListThreadedHandler */ /************************************************************************/ template void dxtemplateJobListThreadedHandler::ProcessActiveJobAddition() { ActivateAnIdleThread(); } template void dxtemplateJobListThreadedHandler::PrepareForWaitingAJobCompletion() { // Do nothing } template unsigned dxtemplateJobListThreadedHandler::RetrieveActiveThreadsCount() { return GetActiveThreadsCount(); } template void dxtemplateJobListThreadedHandler::StickToJobsProcessing(dxThreadReadyToServeCallback *readiness_callback/*=NULL*/, void *callback_context/*=NULL*/) { RegisterAsActiveThread(); if (readiness_callback != NULL) { (*readiness_callback)(callback_context); } PerformJobProcessingUntilShutdown(); UnregisterAsActiveThread(); } template void dxtemplateJobListThreadedHandler::PerformJobProcessingUntilShutdown() { while (true) { // It is expected that new jobs will not be queued any longer after shutdown had been requested if (IsShutdownRequested() && m_job_list_ptr->IsJobListReadyForShutdown()) { break; } PerformJobProcessingSession(); // It is expected that new jobs will not be queued any longer after shutdown had been requested if (IsShutdownRequested() && m_job_list_ptr->IsJobListReadyForShutdown()) { break; } BlockAsIdleThread(); } } template void dxtemplateJobListThreadedHandler::PerformJobProcessingSession() { dxThreadedJobInfo *current_job = NULL; bool job_result = false; while (true) { bool last_job_flag; current_job = m_job_list_ptr->ReleaseAJobAndPickNextPendingOne(current_job, job_result, &dxCallWait::AbstractSignalTheWait, last_job_flag); if (!current_job) { break; } if (!last_job_flag) { ActivateAnIdleThread(); } job_result = current_job->InvokeCallFunction(); } } template void dxtemplateJobListThreadedHandler::BlockAsIdleThread() { m_processing_wakeup.WaitWakeup(NULL); } template void dxtemplateJobListThreadedHandler::ActivateAnIdleThread() { m_processing_wakeup.WakeupAThread(); } template void dxtemplateJobListThreadedHandler::ShutdownProcessing() { m_shutdown_requested = true; m_processing_wakeup.WakeupAllThreads(); } template void dxtemplateJobListThreadedHandler::CleanupForRestart() { m_shutdown_requested = false; m_processing_wakeup.ResetWakeup(); } #endif // #if dBUILTIN_THREADING_IMPL_ENABLED /************************************************************************/ /* Implementation of dxtemplateJobListSelfHandler */ /************************************************************************/ template void dxtemplateJobListSelfHandler::ProcessActiveJobAddition() { // Do nothing } template void dxtemplateJobListSelfHandler::PrepareForWaitingAJobCompletion() { PerformJobProcessingUntilExhaustion(); } template unsigned dxtemplateJobListSelfHandler::RetrieveActiveThreadsCount() { return 0U; // Return zero to indicate that there are no actual active threads provided. } template void dxtemplateJobListSelfHandler::StickToJobsProcessing(dxThreadReadyToServeCallback *readiness_callback/*=NULL*/, void *callback_context/*=NULL*/) { (void)readiness_callback; // unused (void)callback_context; // unused dIASSERT(false); // This method is not expected to be called for Self-Handler } template void dxtemplateJobListSelfHandler::PerformJobProcessingUntilExhaustion() { PerformJobProcessingSession(); } template void dxtemplateJobListSelfHandler::PerformJobProcessingSession() { dxThreadedJobInfo *current_job = NULL; bool job_result = false; while (true) { bool dummy_last_job_flag; current_job = m_job_list_ptr->ReleaseAJobAndPickNextPendingOne(current_job, job_result, &dxCallWait::AbstractSignalTheWait, dummy_last_job_flag); if (!current_job) { break; } job_result = current_job->InvokeCallFunction(); } } template void dxtemplateJobListSelfHandler::ShutdownProcessing() { // Do nothing } template void dxtemplateJobListSelfHandler::CleanupForRestart() { // Do nothing } /************************************************************************/ /* Implementation of dxtemplateThreadingImplementation */ /************************************************************************/ template void dxtemplateThreadingImplementation::FreeInstance() { delete this; } template dIMutexGroup *dxtemplateThreadingImplementation::AllocMutexGroup(dmutexindex_t Mutex_count) { dxMutexGroup *mutex_group = dxMutexGroup::AllocateInstance(Mutex_count); return (dIMutexGroup *)mutex_group; } template void dxtemplateThreadingImplementation::FreeMutexGroup(dIMutexGroup *mutex_group) { dxMutexGroup::FreeInstance((dxMutexGroup *)mutex_group); } template void dxtemplateThreadingImplementation::LockMutexGroupMutex(dIMutexGroup *mutex_group, dmutexindex_t mutex_index) { ((dxMutexGroup *)mutex_group)->LockMutex(mutex_index); } // template // bool dxtemplateThreadingImplementation::TryLockMutexGroupMutex(dIMutexGroup *mutex_group, dmutexindex_t mutex_index) // { // return ((dxMutexGroup *)mutex_group)->TryLockMutex(mutex_index); // } template void dxtemplateThreadingImplementation::UnlockMutexGroupMutex(dIMutexGroup *mutex_group, dmutexindex_t mutex_index) { ((dxMutexGroup *)mutex_group)->UnlockMutex(mutex_index); } template dxICallWait *dxtemplateThreadingImplementation::AllocACallWait() { dxCallWait *call_wait = new dxCallWait(); if (call_wait != NULL && !call_wait->InitializeObject()) { delete call_wait; call_wait = NULL; } return (dxICallWait *)call_wait; } template void dxtemplateThreadingImplementation::ResetACallWait(dxICallWait *call_wait) { ((dxCallWait *)call_wait)->ResetTheWait(); } template void dxtemplateThreadingImplementation::FreeACallWait(dxICallWait *call_wait) { delete ((dxCallWait *)call_wait); } template bool dxtemplateThreadingImplementation::PreallocateJobInfos(ddependencycount_t max_simultaneous_calls_estimate) { // No multithreading protection here! // Resources are to be preallocated before jobs start to be scheduled // as otherwise there is no way to implement the preallocation. bool result = m_list_container.EnsureNumberOfJobInfosIsPreallocated(max_simultaneous_calls_estimate); return result; } template void dxtemplateThreadingImplementation::ScheduleNewJob( int *fault_accumulator_ptr/*=NULL*/, dCallReleaseeID *out_post_releasee_ptr/*=NULL*/, ddependencycount_t dependencies_count, dCallReleaseeID dependent_releasee/*=NULL*/, dxICallWait *call_wait/*=NULL*/, dThreadedCallFunction *call_func, void *call_context, dcallindex_t instance_index) { dxThreadedJobInfo *new_job = m_list_container.AllocateJobInfoFromPool(); dIASSERT(new_job != NULL); new_job->AssignJobData(dependencies_count, dMAKE_RELEASEE_JOBINSTANCE(dependent_releasee), (dxCallWait *)call_wait, fault_accumulator_ptr, call_func, call_context, instance_index); if (out_post_releasee_ptr != NULL) { *out_post_releasee_ptr = dMAKE_JOBINSTANCE_RELEASEE(new_job); } m_list_container.QueueJobForProcessing(new_job); if (dependencies_count == 0) { m_list_handler.ProcessActiveJobAddition(); } } template void dxtemplateThreadingImplementation::AlterJobDependenciesCount( dCallReleaseeID target_releasee, ddependencychange_t dependencies_count_change) { dIASSERT(dependencies_count_change != 0); dxThreadedJobInfo *job_instance = dMAKE_RELEASEE_JOBINSTANCE(target_releasee); bool job_has_become_ready; m_list_container.AlterJobProcessingDependencies(job_instance, dependencies_count_change, job_has_become_ready); if (job_has_become_ready) { m_list_handler.ProcessActiveJobAddition(); } } template void dxtemplateThreadingImplementation::WaitJobCompletion( int *out_wait_status_ptr/*=NULL*/, dxICallWait *call_wait, const dThreadedWaitTime *timeout_time_ptr/*=NULL*/) { dIASSERT(call_wait != NULL); m_list_handler.PrepareForWaitingAJobCompletion(); bool wait_status = ((dxCallWait *)call_wait)->PerformWaiting(timeout_time_ptr); dIASSERT(timeout_time_ptr != NULL || wait_status); if (out_wait_status_ptr) { *out_wait_status_ptr = wait_status; } } template unsigned dxtemplateThreadingImplementation::RetrieveActiveThreadsCount() { return m_list_handler.RetrieveActiveThreadsCount(); } template void dxtemplateThreadingImplementation::StickToJobsProcessing(dxThreadReadyToServeCallback *readiness_callback/*=NULL*/, void *callback_context/*=NULL*/) { m_list_handler.StickToJobsProcessing(readiness_callback, callback_context); } template void dxtemplateThreadingImplementation::ShutdownProcessing() { m_list_handler.ShutdownProcessing(); } template void dxtemplateThreadingImplementation::CleanupForRestart() { m_list_handler.CleanupForRestart(); } #endif // #ifndef _ODE_THREADING_IMPL_TEMPLATES_H_ ode-0.16/ode/src/config.h.in0000664000175200017520000002035713403272662012533 00000000000000/* ode/src/config.h.in. Generated from configure.ac by autoheader. */ #ifndef ODE_CONFIG_H #define ODE_CONFIG_H /* Define if building universal (internal helper macro) */ #undef AC_APPLE_UNIVERSAL_BUILD /* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP systems. This function is required for `alloca.c' support on those systems. */ #undef CRAY_STACKSEG_END /* Define to 1 if using `alloca.c'. */ #undef C_ALLOCA /* Define to 1 if you have `alloca', as a function or macro. */ #undef HAVE_ALLOCA /* Define to 1 if you have and it should be used (not on Ultrix). */ #undef HAVE_ALLOCA_H /* Use the Apple OpenGL framework. */ #undef HAVE_APPLE_OPENGL_FRAMEWORK /* Define to 1 if you have the `atan2f' function. */ #undef HAVE_ATAN2F /* Define to 1 if you have the `clock_gettime' function. */ #undef HAVE_CLOCK_GETTIME /* Define to 1 if you have the `copysign' function. */ #undef HAVE_COPYSIGN /* Define to 1 if you have the `copysignf' function. */ #undef HAVE_COPYSIGNF /* Define to 1 if you have the `cosf' function. */ #undef HAVE_COSF /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H /* Define to 1 if you have the `fabsf' function. */ #undef HAVE_FABSF /* Define to 1 if you have the header file. */ #undef HAVE_FLOAT_H /* Define to 1 if you have the `floor' function. */ #undef HAVE_FLOOR /* Define to 1 if you have the `fmodf' function. */ #undef HAVE_FMODF /* Define to 1 if you have the `gettimeofday' function. */ #undef HAVE_GETTIMEOFDAY /* Define to 1 if you have the header file. */ #undef HAVE_GL_GLEXT_H /* Define to 1 if you have the header file. */ #undef HAVE_GL_GLU_H /* Define to 1 if you have the header file. */ #undef HAVE_GL_GL_H /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the `isnan' function. */ #undef HAVE_ISNAN /* Define to 1 if you have the `isnanf' function. */ #undef HAVE_ISNANF /* Define to 1 if you have the `m' library (-lm). */ #undef HAVE_LIBM /* Define to 1 if you have the `rt' library (-lrt). */ #undef HAVE_LIBRT /* Define to 1 if you have the `sunmath' library (-lsunmath). */ #undef HAVE_LIBSUNMATH /* Define to 1 if you have the header file. */ #undef HAVE_LIMITS_H /* Define to 1 if you have the header file. */ #undef HAVE_MALLOC_H /* Define to 1 if you have the header file. */ #undef HAVE_MATH_H /* Define to 1 if you have the `memmove' function. */ #undef HAVE_MEMMOVE /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the `memset' function. */ #undef HAVE_MEMSET /* Define to 1 if libc includes obstacks. */ #undef HAVE_OBSTACK /* Define to 1 if you have the `pthread_attr_setstacklazy' function. */ #undef HAVE_PTHREAD_ATTR_SETSTACKLAZY /* Define to 1 if you have the `pthread_condattr_setclock' function. */ #undef HAVE_PTHREAD_CONDATTR_SETCLOCK /* Define to 1 if you have the `sinf' function. */ #undef HAVE_SINF /* Define to 1 if you have the `snprintf' function. */ #undef HAVE_SNPRINTF /* Define to 1 if you have the `sqrt' function. */ #undef HAVE_SQRT /* Define to 1 if you have the `sqrtf' function. */ #undef HAVE_SQRTF /* Define to 1 if you have the header file. */ #undef HAVE_STDARG_H /* Define to 1 if stdbool.h conforms to C99. */ #undef HAVE_STDBOOL_H /* Define to 1 if you have the header file. */ #undef HAVE_STDDEF_H /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDIO_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the `strchr' function. */ #undef HAVE_STRCHR /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the `strstr' function. */ #undef HAVE_STRSTR /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TIME_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_TIME_H /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to 1 if you have the `vsnprintf' function. */ #undef HAVE_VSNPRINTF /* Define to 1 if the system has the type `_Bool'. */ #undef HAVE__BOOL /* Define to 1 if you have the `_isnan' function. */ #undef HAVE__ISNAN /* Define to 1 if you have the `_isnanf' function. */ #undef HAVE__ISNANF /* Define to 1 if you have the `__isnan' function. */ #undef HAVE___ISNAN /* Define to 1 if you have the `__isnanf' function. */ #undef HAVE___ISNANF /* Define to the sub-directory where libtool stores uninstalled libraries. */ #undef LT_OBJDIR /* Mac OS X version setting for OU Library */ #undef MAC_OS_X_VERSION /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* compiling for a pentium on a gcc-based platform? */ #undef PENTIUM /* If using the C implementation of alloca, define if you know the direction of stack growth for your system; otherwise it will be automatically deduced at runtime. STACK_DIRECTION > 0 => grows toward higher addresses STACK_DIRECTION < 0 => grows toward lower addresses STACK_DIRECTION = 0 => direction of growth unknown */ #undef STACK_DIRECTION /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Version number of package */ #undef VERSION /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ #if defined AC_APPLE_UNIVERSAL_BUILD # if defined __BIG_ENDIAN__ # define WORDS_BIGENDIAN 1 # endif #else # ifndef WORDS_BIGENDIAN # undef WORDS_BIGENDIAN # endif #endif /* compiling for a X86_64 system on a gcc-based platform? */ #undef X86_64_SYSTEM /* OU features enabled */ #undef _OU_FEATURE_SET /* libou namespace for ODE */ #undef _OU_NAMESPACE /* Target OS setting for OU Library */ #undef _OU_TARGET_OS /* Define for Solaris 2.5.1 so the uint32_t typedef from , , or is not used. If the typedef were allowed, the #define below would cause a syntax error. */ #undef _UINT32_T /* Atomic API of OU is enabled */ #undef dATOMICS_ENABLED /* Built-in multithreaded threading implementation is included */ #undef dBUILTIN_THREADING_IMPL_ENABLED /* Generic OU features are enabled */ #undef dOU_ENABLED /* Threading interface is disabled */ #undef dTHREADING_INTF_DISABLED /* Thread Local Storage API of OU is enabled */ #undef dTLS_ENABLED /* Use the old trimesh-trimesh collider */ #undef dTRIMESH_OPCODE_USE_OLD_TRIMESH_TRIMESH_COLLIDER /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus #undef inline #endif /* Define to the type of a signed integer type of width exactly 32 bits if such a type exists and the standard includes do not define it. */ #undef int32_t /* Define to `unsigned int' if does not define. */ #undef size_t /* Define to the type of an unsigned integer type of width exactly 32 bits if such a type exists and the standard includes do not define it. */ #undef uint32_t /* Define to empty if the keyword `volatile' does not work. Warning: valid code using `volatile' can become incorrect without. Disable with care. */ #undef volatile #ifdef HAVE_ALLOCA_H #include #endif #ifdef HAVE_MALLOC_H #include #endif #ifdef HAVE_STDINT_H #include #endif #ifdef HAVE_INTTYPES_H #include #endif #include "typedefs.h" #endif /* #define ODE_CONFIG_H */ ode-0.16/ode/src/resource_control.cpp0000664000175200017520000001752513403272463014605 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* * Resource accounting/preallocation class implementations * Copyright (c) 2017 Oleh Derevenko, odar@eleks.com (change all "a" to "e") */ #include #include #include "config.h" #include "resource_control.h" #include "simple_cooperative.h" ////////////////////////////////////////////////////////////////////////// // dxResourceRequirementDescriptor(); dxResourceRequirementDescriptor::~dxResourceRequirementDescriptor() { // Do nothing } ////////////////////////////////////////////////////////////////////////// // dxRequiredResourceContainer dxRequiredResourceContainer::~dxRequiredResourceContainer() { freeResources(); } bool dxRequiredResourceContainer::allocateResources(const dxResourceRequirementDescriptor &requirementDescriptor) { bool result = false; bool bufferAllocated = false; do { sizeint memorySizeRequirement = requirementDescriptor.getMemorySizeRequirement(); if (memorySizeRequirement != 0) { unsigned memoryAlignmentRequirement = requirementDescriptor.getMemoryAlignmentRequirement(); void *bufferAllocated = m_memoryAllocation.allocAligned(memorySizeRequirement, memoryAlignmentRequirement); if (bufferAllocated == NULL) { break; } } bufferAllocated = true; dxThreadingBase *relatedThreading = requirementDescriptor.getrelatedThreading(); dIASSERT(relatedThreading != NULL); unsigned simultaneousCallRequirement = requirementDescriptor.getSimultaneousCallRequirement(); if (simultaneousCallRequirement != 0) { if (!relatedThreading->PreallocateResourcesForThreadedCalls(simultaneousCallRequirement)) { break; } } dCallWaitID stockCallWait = NULL; if (requirementDescriptor.getIsStockCallWaitRequired()) { stockCallWait = relatedThreading->AllocateOrRetrieveStockCallWaitID(); if (stockCallWait == NULL) { break; } } m_relatedThreading = relatedThreading; m_stockCallWait = stockCallWait; result = true; } while (false); if (!result) { if (bufferAllocated) { m_memoryAllocation.freeAllocation(); } } return result; } void dxRequiredResourceContainer::freeResources() { if (m_relatedThreading != NULL) { m_relatedThreading = NULL; m_stockCallWait = NULL; m_memoryAllocation.freeAllocation(); } else { dIASSERT(m_stockCallWait == NULL); dIASSERT(m_memoryAllocation.getUserAreaPointer() == NULL); } } ////////////////////////////////////////////////////////////////////////// // Public interface functions static inline dResourceRequirementsID encodeResourceRequirementsID(dxResourceRequirementDescriptor *requirementsDescriptor) { return (dResourceRequirementsID)requirementsDescriptor; } /*extern ODE_API */ dResourceRequirementsID dResourceRequirementsCreate(dCooperativeID cooperative) { dAASSERT(cooperative != NULL); dxSimpleCooperative *cooperativeInstance = decodeCooperativeID(cooperative); dxThreadingBase *threading = cooperativeInstance->getRelatedThreading(); dxResourceRequirementDescriptor *requirementsDescriptor = new dxResourceRequirementDescriptor(threading); dResourceRequirementsID result = encodeResourceRequirementsID(requirementsDescriptor); return result; } /*extern ODE_API */ void dResourceRequirementsDestroy(dResourceRequirementsID requirements) { dxResourceRequirementDescriptor *requirementsDescriptor = decodeResourceRequirementsID(requirements); if (requirementsDescriptor != NULL) { delete requirementsDescriptor; } } /*extern ODE_API */ dResourceRequirementsID dResourceRequirementsClone(/*const */dResourceRequirementsID requirements) { dAASSERT(requirements != NULL); dxResourceRequirementDescriptor *requirementsDescriptor = decodeResourceRequirementsID(requirements); dxResourceRequirementDescriptor *descriptorClone = new dxResourceRequirementDescriptor(*requirementsDescriptor); dResourceRequirementsID result = encodeResourceRequirementsID(descriptorClone); return result; } /*extern ODE_API */ void dResourceRequirementsMergeIn(dResourceRequirementsID summaryRequirements, /*const */dResourceRequirementsID extraRequirements) { dAASSERT(summaryRequirements != NULL); dAASSERT(extraRequirements != NULL); dxResourceRequirementDescriptor *summaryDescriptor = decodeResourceRequirementsID(summaryRequirements); dxResourceRequirementDescriptor *extraDescriptor = decodeResourceRequirementsID(extraRequirements); summaryDescriptor->mergeAnotherDescriptorIn(*extraDescriptor); } ////////////////////////////////////////////////////////////////////////// static inline dResourceContainerID encodeResourceContainerID(dxRequiredResourceContainer *containerInstance) { return (dResourceContainerID)containerInstance; } /*extern ODE_API */ dResourceContainerID dResourceContainerAcquire(/*const */dResourceRequirementsID requirements) { dAASSERT(requirements != NULL); dResourceContainerID result = NULL; bool allocationSucceeded = false; dxRequiredResourceContainer *containerInstance; bool containerAllocated = false; dxResourceRequirementDescriptor *requirementsInstance = decodeResourceRequirementsID(requirements); do { containerInstance = new dxRequiredResourceContainer(); if (containerInstance == NULL) { break; } containerAllocated = true; if (!containerInstance->allocateResources(*requirementsInstance)) { break; } result = encodeResourceContainerID(containerInstance); allocationSucceeded = true; } while (false); if (!allocationSucceeded) { if (containerAllocated) { delete containerInstance; } } return result; } /*extern ODE_API */ void dResourceContainerDestroy(dResourceContainerID resources) { dxRequiredResourceContainer *containerInstance = decodeResourceContainerID(resources); if (containerInstance != NULL) { delete containerInstance; } } ode-0.16/ode/src/fastvecscale_impl.h0000664000175200017520000001620313403272463014337 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* * Vector scaling function implementation * Improvements and cooperative implementation copyright (c) 2017 Oleh Derevenko, odar@eleks.com (change all "a" to "e") */ #ifndef _ODE_FASTVECSCALE_IMPL_H_ #define _ODE_FASTVECSCALE_IMPL_H_ template void scaleLargeVector(dReal *aStart, const dReal *dStart, unsigned elementCount) { dAASSERT (aStart && dStart && elementCount >= 0); const unsigned step = 4; dReal *ptrA = aStart; const dReal *ptrD = dStart; const dReal *const dStepsEnd = dStart + (sizeint)(elementCount & ~(step - 1)) * d_stride; for (; ptrD != dStepsEnd; ptrA += step * a_stride, ptrD += step * d_stride) { dReal a0 = ptrA[0], a1 = ptrA[1 * a_stride], a2 = ptrA[2 * a_stride], a3 = ptrA[3 * a_stride]; dReal d0 = ptrD[0], d1 = ptrD[1 * d_stride], d2 = ptrD[2 * d_stride], d3 = ptrD[3 * d_stride]; a0 *= d0; a1 *= d1; a2 *= d2; a3 *= d3; ptrA[0] = a0; ptrA[1 * a_stride] = a1; ptrA[2 * a_stride] = a2; ptrA[3 * a_stride] = a3; dSASSERT(step == 4); } switch (elementCount & (step - 1)) { case 3: { dReal a2 = ptrA[2 * a_stride]; dReal d2 = ptrD[2 * d_stride]; ptrA[2 * a_stride] = a2 * d2; // break; -- proceed to case 2 } case 2: { dReal a1 = ptrA[1 * a_stride]; dReal d1 = ptrD[1 * d_stride]; ptrA[1 * a_stride] = a1 * d1; // break; -- proceed to case 1 } case 1: { dReal a0 = ptrA[0]; dReal d0 = ptrD[0]; ptrA[0] = a0 * d0; break; } } dSASSERT(step == 4); } template /*static */ void ThreadedEquationSolverLDLT::participateScalingVector(dReal *ptrAStart, const dReal *ptrDStart, const unsigned elementCount, volatile atomicord32 &refBlockCompletionProgress/*=0*/) { dAASSERT (ptrAStart != NULL); dAASSERT(ptrDStart != NULL); dAASSERT(elementCount >= 0); const unsigned wrapSize = 4; dSASSERT(block_step % wrapSize == 0); const unsigned completeBlockCount = elementCount / block_step; const unsigned trailingBlockElements = elementCount % block_step; unsigned blockIndex; while ((blockIndex = ThrsafeIncrementIntUpToLimit(&refBlockCompletionProgress, completeBlockCount)) != completeBlockCount) { dReal *ptrAElement = ptrAStart + (sizeint)(blockIndex * block_step) * a_stride; const dReal *ptrDElement = ptrDStart + (sizeint)(blockIndex * block_step) * d_stride; const dReal *const ptrDBlockEnd = ptrDElement + block_step * d_stride; dSASSERT((sizeint)block_step * a_stride < UINT_MAX); dSASSERT((sizeint)block_step * d_stride < UINT_MAX); for (; ptrDElement != ptrDBlockEnd; ptrAElement += wrapSize * a_stride, ptrDElement += wrapSize * d_stride) { dReal a0 = ptrAElement[0], a1 = ptrAElement[1 * a_stride], a2 = ptrAElement[2 * a_stride], a3 = ptrAElement[3 * a_stride]; dReal d0 = ptrDElement[0], d1 = ptrDElement[1 * d_stride], d2 = ptrDElement[2 * d_stride], d3 = ptrDElement[3 * d_stride]; a0 *= d0; a1 *= d1; a2 *= d2; a3 *= d3; ptrAElement[0] = a0; ptrAElement[1 * a_stride] = a1; ptrAElement[2 * a_stride] = a2; ptrAElement[3 * a_stride] = a3; dSASSERT(wrapSize == 4); } } if (trailingBlockElements != 0 && (blockIndex = ThrsafeIncrementIntUpToLimit(&refBlockCompletionProgress, completeBlockCount + 1)) != completeBlockCount + 1) { dReal *ptrAElement = ptrAStart + (sizeint)(completeBlockCount * block_step) * a_stride; const dReal *ptrDElement = ptrDStart + (sizeint)(completeBlockCount * block_step) * d_stride; const dReal *const ptrDBlockEnd = ptrDElement + (trailingBlockElements & ~(wrapSize - 1)) * d_stride; for (; ptrDElement != ptrDBlockEnd; ptrAElement += wrapSize * a_stride, ptrDElement += wrapSize * d_stride) { dReal a0 = ptrAElement[0], a1 = ptrAElement[1 * a_stride], a2 = ptrAElement[2 * a_stride], a3 = ptrAElement[3 * a_stride]; dReal d0 = ptrDElement[0], d1 = ptrDElement[1 * d_stride], d2 = ptrDElement[2 * d_stride], d3 = ptrDElement[3 * d_stride]; a0 *= d0; a1 *= d1; a2 *= d2; a3 *= d3; ptrAElement[0] = a0; ptrAElement[1 * a_stride] = a1; ptrAElement[2 * a_stride] = a2; ptrAElement[3 * a_stride] = a3; dSASSERT(wrapSize == 4); } switch (trailingBlockElements & (wrapSize - 1)) { case 3: { dReal a2 = ptrAElement[2 * a_stride]; dReal d2 = ptrDElement[2 * d_stride]; ptrAElement[2 * a_stride] = a2 * d2; // break; -- proceed to case 2 } case 2: { dReal a1 = ptrAElement[1 * a_stride]; dReal d1 = ptrDElement[1 * d_stride]; ptrAElement[1 * a_stride] = a1 * d1; // break; -- proceed to case 1 } case 1: { dReal a0 = ptrAElement[0]; dReal d0 = ptrDElement[0]; ptrAElement[0] = a0 * d0; break; } } dSASSERT(wrapSize == 4); } } #endif ode-0.16/ode/src/error.h0000664000175200017520000001041713403272463012005 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* Library private error handling functions and macros */ #ifndef _ODE__PRIVATE_ERROR_H_ #define _ODE__PRIVATE_ERROR_H_ #include #include /* debugging: * IASSERT is an internal assertion, i.e. a consistency check. if it fails * we want to know where. * UASSERT is a user assertion, i.e. if it fails a nice error message * should be printed for the user. * AASSERT is an arguments assertion, i.e. if it fails "bad argument(s)" * is printed. * DEBUGMSG just prints out a message */ # if defined(__STDC__) && __STDC_VERSION__ >= 199901L # define __FUNCTION__ __func__ # endif #ifndef dNODEBUG # ifdef __GNUC__ # define dIASSERT(a) { if (!(a)) { dDebug (d_ERR_IASSERT, \ "assertion \"" #a "\" failed in %s() [%s:%u]",__FUNCTION__,__FILE__,__LINE__); } } # define dUASSERT(a,msg) { if (!(a)) { dDebug (d_ERR_UASSERT, \ msg " in %s()", __FUNCTION__); } } # define dDEBUGMSG(msg) { dMessage (d_ERR_UASSERT, \ msg " in %s() [%s:%u]", __FUNCTION__,__FILE__,__LINE__); } # else // not __GNUC__ # define dIASSERT(a) { if (!(a)) { dDebug (d_ERR_IASSERT, \ "assertion \"" #a "\" failed in %s:%u",__FILE__,__LINE__); } } # define dUASSERT(a,msg) { if (!(a)) { dDebug (d_ERR_UASSERT, \ msg " (%s:%u)", __FILE__,__LINE__); } } # define dDEBUGMSG(msg) { dMessage (d_ERR_UASSERT, \ msg " (%s:%u)", __FILE__,__LINE__); } # endif # define dIVERIFY(a) dIASSERT(a) # define dUVERIFY(a, msg) dUASSERT(a, msg) #else # define dIASSERT(a) ((void)0) # define dUASSERT(a,msg) ((void)0) # define dDEBUGMSG(msg) ((void)0) # define dIVERIFY(a) ((void)(a)) # define dUVERIFY(a, msg) ((void)(a)) #endif #ifdef __GNUC__ #define dUNUSED(Name) Name __attribute__((unused)) #else // not __GNUC__ #define dUNUSED(Name) Name #endif #if __cplusplus >= 201103L #define dSASSERT(e) static_assert(e, #e) #define dSMSGASSERT(e, message) static_assert(e, message) #else #define d_SASSERT_INNER_TOKENPASTE(x, y) x ## y #define d_SASSERT_TOKENPASTE(x, y) d_SASSERT_INNER_TOKENPASTE(x, y) #define dSASSERT(e) typedef char dUNUSED(d_SASSERT_TOKENPASTE(d_StaticAssertionFailed_, __LINE__)[(e)?1:-1]) #define dSMSGASSERT(e, message) dSASSERT(e) #endif # ifdef __GNUC__ # define dICHECK(a) { if (!(a)) { dDebug (d_ERR_IASSERT, \ "assertion \"" #a "\" failed in %s() [%s:%u]",__FUNCTION__,__FILE__,__LINE__); *(int *)0 = 0; } } # else // not __GNUC__ # define dICHECK(a) { if (!(a)) { dDebug (d_ERR_IASSERT, \ "assertion \"" #a "\" failed in %s:%u",__FILE__,__LINE__); *(int *)0 = 0; } } # endif // Argument assert is a special case of user assert #define dAASSERT(a) dUASSERT(a, "Bad argument(s)") #define dAVERIFY(a) dUVERIFY(a, "Bad argument(s)") #endif ode-0.16/ode/src/gimpact_plane_contact_accessor.h0000664000175200017520000000562113403272463017055 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_GIMPACT_PLANE_CONTACT_ACCESSOR_H_ #define _ODE_GIMPACT_PLANE_CONTACT_ACCESSOR_H_ struct dxPlaneContactAccessor { dxPlaneContactAccessor(const vec4f *planecontact_results, const dReal *plane, dGeomID g1, dGeomID g2) : m_planecontact_results(planecontact_results), m_plane(plane), m_g1(g1), m_g2(g2) {} dReal RetrieveDepthByIndex(unsigned index) const { return m_planecontact_results[index][3]; } void ExportContactGeomByIndex(dContactGeom *pcontact, unsigned index) const { const vec4f *planecontact = m_planecontact_results + index; pcontact->pos[0] = (*planecontact)[0]; pcontact->pos[1] = (*planecontact)[1]; pcontact->pos[2] = (*planecontact)[2]; pcontact->pos[3] = REAL(1.0); const dReal *plane = m_plane; pcontact->normal[0] = plane[0]; pcontact->normal[1] = plane[1]; pcontact->normal[2] = plane[2]; pcontact->normal[3] = 0; pcontact->depth = (*planecontact)[3]; pcontact->g1 = m_g1; // trimesh geom pcontact->g2 = m_g2; // plane geom pcontact->side1 = -1; // note: don't have the triangle index, but OPCODE *does* do this properly pcontact->side2 = -1; } const vec4f *m_planecontact_results; const dReal *m_plane; dGeomID m_g1, m_g2; }; #endif //_ODE_GIMPACT_PLANE_CONTACT_ACCESSOR_H_ ode-0.16/ode/src/collision_space.cpp0000664000175200017520000006320013403272463014353 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* spaces */ #include #include #include #include #include "config.h" #include "matrix.h" #include "collision_kernel.h" #include "collision_space_internal.h" #include "util.h" #ifdef _MSC_VER #pragma warning(disable:4291) // for VC++, no complaints about "no matching operator delete found" #endif //**************************************************************************** // make the geom dirty by setting the GEOM_DIRTY and GEOM_BAD_AABB flags // and moving it to the front of the space's list. all the parents of a // dirty geom also become dirty. void dGeomMoved (dxGeom *geom) { dAASSERT (geom); // if geom is offset, mark it as needing a calculate if (geom->offset_posr) { geom->gflags |= GEOM_POSR_BAD; } // from the bottom of the space heirarchy up, process all clean geoms // turning them into dirty geoms. dxSpace *parent = geom->parent_space; while (parent && (geom->gflags & GEOM_DIRTY)==0) { geom->markAABBBad(); parent->dirty (geom); geom = parent; parent = parent->parent_space; } // all the remaining dirty geoms must have their AABB_BAD flags set, to // ensure that their AABBs get recomputed while (geom) { geom->markAABBBad(); geom = geom->parent_space; } } #define GEOM_ENABLED(g) (((g)->gflags & GEOM_ENABLE_TEST_MASK) == GEOM_ENABLE_TEST_VALUE) //**************************************************************************** // dxSpace dxSpace::dxSpace (dSpaceID _space) : dxGeom (_space,0) { count = 0; first = 0; cleanup = 1; sublevel = 0; tls_kind = dSPACE_TLS_KIND_INIT_VALUE; current_index = 0; current_geom = 0; lock_count = 0; } dxSpace::~dxSpace() { CHECK_NOT_LOCKED (this); if (cleanup) { // note that destroying each geom will call remove() dxGeom *g,*n; for (g = first; g; g=n) { n = g->next; dGeomDestroy (g); } } else { dxGeom *g,*n; for (g = first; g; g=n) { n = g->next; remove (g); } } } void dxSpace::computeAABB() { if (first) { int i; dReal a[6]; a[0] = dInfinity; a[1] = -dInfinity; a[2] = dInfinity; a[3] = -dInfinity; a[4] = dInfinity; a[5] = -dInfinity; for (dxGeom *g=first; g; g=g->next) { g->recomputeAABB(); for (i=0; i<6; i += 2) if (g->aabb[i] < a[i]) a[i] = g->aabb[i]; for (i=1; i<6; i += 2) if (g->aabb[i] > a[i]) a[i] = g->aabb[i]; } memcpy(aabb,a,6*sizeof(dReal)); } else { dSetZero (aabb,6); } } // the dirty geoms are numbered 0..k, the clean geoms are numbered k+1..count-1 dxGeom *dxSpace::getGeom (int i) { dUASSERT (i >= 0 && i < count,"index out of range"); if (current_geom && current_index == i-1) { current_geom = current_geom->next; current_index = i; return current_geom; } else { dxGeom *g=first; for (int j=0; jnext; else return 0; } current_geom = g; current_index = i; return g; } } void dxSpace::add (dxGeom *geom) { CHECK_NOT_LOCKED (this); dAASSERT (geom); dUASSERT (geom->parent_space == 0 && geom->next == 0, "geom is already in a space"); // add geom->parent_space = this; geom->spaceAdd (&first); count++; // enumerator has been invalidated current_geom = 0; dGeomMoved (this); } void dxSpace::remove (dxGeom *geom) { CHECK_NOT_LOCKED (this); dAASSERT (geom); dUASSERT (geom->parent_space == this,"object is not in this space"); // remove geom->spaceRemove(); count--; // safeguard geom->next = 0; geom->tome = 0; geom->parent_space = 0; // enumerator has been invalidated current_geom = 0; // the bounding box of this space (and that of all the parents) may have // changed as a consequence of the removal. dGeomMoved (this); } void dxSpace::dirty (dxGeom *geom) { geom->spaceRemove(); geom->spaceAdd (&first); } //**************************************************************************** // simple space - reports all n^2 object intersections struct dxSimpleSpace : public dxSpace { dxSimpleSpace (dSpaceID _space); void cleanGeoms(); void collide (void *data, dNearCallback *callback); void collide2 (void *data, dxGeom *geom, dNearCallback *callback); }; dxSimpleSpace::dxSimpleSpace (dSpaceID _space) : dxSpace (_space) { type = dSimpleSpaceClass; } void dxSimpleSpace::cleanGeoms() { // compute the AABBs of all dirty geoms, and clear the dirty flags lock_count++; for (dxGeom *g=first; g && (g->gflags & GEOM_DIRTY); g=g->next) { if (IS_SPACE(g)) { ((dxSpace*)g)->cleanGeoms(); } g->recomputeAABB(); dIASSERT((g->gflags & GEOM_AABB_BAD) == 0); g->gflags &= ~GEOM_DIRTY; } lock_count--; } void dxSimpleSpace::collide (void *data, dNearCallback *callback) { dAASSERT (callback); lock_count++; cleanGeoms(); // intersect all bounding boxes for (dxGeom *g1=first; g1; g1=g1->next) { if (GEOM_ENABLED(g1)){ for (dxGeom *g2=g1->next; g2; g2=g2->next) { if (GEOM_ENABLED(g2)){ collideAABBs (g1,g2,data,callback); } } } } lock_count--; } void dxSimpleSpace::collide2 (void *data, dxGeom *geom, dNearCallback *callback) { dAASSERT (geom && callback); lock_count++; cleanGeoms(); geom->recomputeAABB(); // intersect bounding boxes for (dxGeom *g=first; g; g=g->next) { if (GEOM_ENABLED(g)){ collideAABBs (g,geom,data,callback); } } lock_count--; } //**************************************************************************** // utility stuff for hash table space // kind of silly, but oh well... #ifndef MAXINT #define MAXINT ((int)((((unsigned int)(-1)) << 1) >> 1)) #endif // prime[i] is the largest prime smaller than 2^i #define NUM_PRIMES 31 static const unsigned long int prime[NUM_PRIMES] = {1L,2L,3L,7L,13L,31L,61L,127L,251L,509L, 1021L,2039L,4093L,8191L,16381L,32749L,65521L,131071L,262139L, 524287L,1048573L,2097143L,4194301L,8388593L,16777213L,33554393L, 67108859L,134217689L,268435399L,536870909L,1073741789L}; // an axis aligned bounding box in the hash table struct dxAABB { int level; // the level this is stored in (cell size = 2^level) int dbounds[6]; // AABB bounds, discretized to cell size dxGeom *geom; // corresponding geometry object (AABB stored here) sizeint index; // index of this AABB, starting from 0 }; // a hash table node that represents an AABB that intersects a particular cell // at a particular level struct Node { Node *next; // next node in hash table collision list, 0 if none int x,y,z; // cell position in space, discretized to cell size dxAABB *aabb; // axis aligned bounding box that intersects this cell }; // return the `level' of an AABB. the AABB will be put into cells at this // level - the cell size will be 2^level. the level is chosen to be the // smallest value such that the AABB occupies no more than 8 cells, regardless // of its placement. this means that: // size/2 < q <= size // where q is the maximum AABB dimension. static int findLevel (dReal bounds[6]) { if (bounds[0] <= -dInfinity || bounds[1] >= dInfinity || bounds[2] <= -dInfinity || bounds[3] >= dInfinity || bounds[4] <= -dInfinity || bounds[5] >= dInfinity) { return MAXINT; } // compute q dReal q,q2; q = bounds[1] - bounds[0]; // x bounds q2 = bounds[3] - bounds[2]; // y bounds if (q2 > q) q = q2; q2 = bounds[5] - bounds[4]; // z bounds if (q2 > q) q = q2; // find level such that 0.5 * 2^level < q <= 2^level int level; frexp (q,&level); // q = (0.5 .. 1.0) * 2^level (definition of frexp) return level; } // find a virtual memory address for a cell at the given level and x,y,z // position. // @@@ currently this is not very sophisticated, e.g. the scaling // factors could be better designed to avoid collisions, and they should // probably depend on the hash table physical size. static unsigned long getVirtualAddressBase (unsigned int level, unsigned int x, unsigned int y) { return level * 1000UL + x * 100UL + y * 10UL; } //**************************************************************************** // hash space struct dxHashSpace : public dxSpace { int global_minlevel; // smallest hash table level to put AABBs in int global_maxlevel; // objects that need a level larger than this will be // put in a "big objects" list instead of a hash table dxHashSpace (dSpaceID _space); void setLevels (int minlevel, int maxlevel); void getLevels (int *minlevel, int *maxlevel); void cleanGeoms(); void collide (void *data, dNearCallback *callback); void collide2 (void *data, dxGeom *geom, dNearCallback *callback); }; dxHashSpace::dxHashSpace (dSpaceID _space) : dxSpace (_space) { type = dHashSpaceClass; global_minlevel = -3; global_maxlevel = 10; } void dxHashSpace::setLevels (int minlevel, int maxlevel) { dAASSERT (minlevel <= maxlevel); global_minlevel = minlevel; global_maxlevel = maxlevel; } void dxHashSpace::getLevels (int *minlevel, int *maxlevel) { if (minlevel) *minlevel = global_minlevel; if (maxlevel) *maxlevel = global_maxlevel; } void dxHashSpace::cleanGeoms() { // compute the AABBs of all dirty geoms, and clear the dirty flags lock_count++; for (dxGeom *g=first; g && (g->gflags & GEOM_DIRTY); g=g->next) { if (IS_SPACE(g)) { ((dxSpace*)g)->cleanGeoms(); } g->recomputeAABB(); dIASSERT((g->gflags & GEOM_AABB_BAD) == 0); g->gflags &= ~GEOM_DIRTY; } lock_count--; } void dxHashSpace::collide (void *data, dNearCallback *callback) { dAASSERT(this && callback); dxGeom *geom; int i,maxlevel; // 0 or 1 geoms can't collide with anything if (count < 2) return; lock_count++; cleanGeoms(); // create a list of auxiliary information for all geom axis aligned bounding // boxes. set the level for all AABBs. put AABBs larger than the space's // global_maxlevel in the big_boxes list, check everything else against // that list at the end. for AABBs that are not too big, record the maximum // level that we need. typedef std::vector AABBlist; AABBlist hash_boxes; // list of AABBs in hash table AABBlist big_boxes; // list of AABBs too big for hash table maxlevel = global_minlevel - 1; for (geom = first; geom; geom=geom->next) { if (!GEOM_ENABLED(geom)){ continue; } dxAABB aabb; aabb.geom = geom; // compute level, but prevent cells from getting too small int level = findLevel (geom->aabb); if (level < global_minlevel) level = global_minlevel; if (level <= global_maxlevel) { aabb.level = level; if (level > maxlevel) maxlevel = level; // cellsize = 2^level dReal cellSizeRecip = dRecip(ldexp(REAL(1.0), level)); // No computational errors here! // discretize AABB position to cell size for (i=0; i < 6; i++) { dReal aabbBound = geom->aabb[i] * cellSizeRecip; // No computational errors so far! dICHECK(aabbBound >= dMinIntExact && aabbBound > 3; // number of bytes needed for n bits std::vector tested(n * tested_rowsize); // create a hash table to store all AABBs. each AABB may take up to 8 cells. // we use chaining to resolve collisions, but we use a relatively large table // to reduce the chance of collisions. // compute hash table size sz to be a prime > 8*n for (i=0; i= (8*n)) break; } if (i >= NUM_PRIMES) { i = NUM_PRIMES-1; // probably pointless } const unsigned long sz = prime[i]; // allocate and initialize hash table node pointers typedef std::vector HashTable; HashTable table(sz); // add each AABB to the hash table (may need to add it to up to 8 cells) const AABBlist::iterator hashend = hash_boxes.end(); for (AABBlist::iterator aabb = hash_boxes.begin(); aabb != hashend; ++aabb) { const int *dbounds = aabb->dbounds; const int xend = dbounds[1]; for (int xi = dbounds[0]; xi <= xend; xi++) { const int yend = dbounds[3]; for (int yi = dbounds[2]; yi <= yend; yi++) { int zbegin = dbounds[4]; unsigned long hi = (getVirtualAddressBase(aabb->level,xi,yi) + zbegin) % sz; const int zend = dbounds[5]; for (int zi = zbegin; zi <= zend; (hi = hi + 1U != sz ? hi + 1U : 0UL), zi++) { // get the hash index // add a new node to the hash table Node *node = new Node; node->x = xi; node->y = yi; node->z = zi; node->aabb = &*aabb; node->next = table[hi]; table[hi] = node; } } } } // now that all AABBs are loaded into the hash table, we do the actual // collision detection. for all AABBs, check for other AABBs in the // same cells for collisions, and then check for other AABBs in all // intersecting higher level cells. int db[6]; // discrete bounds at current level for (AABBlist::iterator aabb = hash_boxes.begin(); aabb != hashend; ++aabb) { // we are searching for collisions with aabb for (i=0; i<6; i++) db[i] = aabb->dbounds[i]; for (int level = aabb->level; ; ) { dIASSERT(level <= maxlevel); const int xend = db[1]; for (int xi = db[0]; xi <= xend; xi++) { const int yend = db[3]; for (int yi = db[2]; yi <= yend; yi++) { int zbegin = db[4]; // get the hash index unsigned long hi = (getVirtualAddressBase(level, xi, yi) + zbegin) % sz; const int zend = db[5]; for (int zi = zbegin; zi <= zend; (hi = hi + 1U != sz ? hi + 1U : 0UL), zi++) { // search all nodes at this index for (Node* node = table[hi]; node; node=node->next) { // node points to an AABB that may intersect aabb if (node->aabb == &*aabb) continue; if (node->aabb->level == level && node->x == xi && node->y == yi && node->z == zi) { // see if aabb and node->aabb have already been tested // against each other unsigned char mask; if (aabb->index <= node->aabb->index) { i = (aabb->index * tested_rowsize)+(node->aabb->index >> 3); mask = 1 << (node->aabb->index & 7); } else { i = (node->aabb->index * tested_rowsize)+(aabb->index >> 3); mask = 1 << (aabb->index & 7); } dIASSERT (i >= 0 && (sizeint)i < (tested_rowsize*n)); if ((tested[i] & mask)==0) { tested[i] |= mask; collideAABBs (aabb->geom,node->aabb->geom,data,callback); } } } } } } if (level == maxlevel) { break; } ++level; // get the discrete bounds for the next level up for (i=0; i<6; i++) db[i] >>= 1; } } // every AABB in the normal list must now be intersected against every // AABB in the big_boxes list. so let's hope there are not too many objects // in the big_boxes list. const AABBlist::iterator bigend = big_boxes.end(); for (AABBlist::iterator aabb = hash_boxes.begin(); aabb != hashend; ++aabb) { for (AABBlist::iterator aabb2 = big_boxes.begin(); aabb2 != bigend; ++aabb2) { collideAABBs (aabb->geom, aabb2->geom, data, callback); } } // intersected all AABBs in the big_boxes list together for (AABBlist::iterator aabb = big_boxes.begin(); aabb != bigend; ++aabb) { AABBlist::iterator aabb2 = aabb; while (++aabb2 != bigend) { collideAABBs (aabb->geom, aabb2->geom, data, callback); } } // deallocate table const HashTable::iterator tableend = table.end(); for (HashTable::iterator el = table.begin(); el != tableend; ++el) for (Node* node = *el; node; ) { Node* next = node->next; delete node; node = next; } lock_count--; } void dxHashSpace::collide2 (void *data, dxGeom *geom, dNearCallback *callback) { dAASSERT (geom && callback); // this could take advantage of the hash structure to avoid // O(n2) complexity, but it does not yet. lock_count++; cleanGeoms(); geom->recomputeAABB(); // intersect bounding boxes for (dxGeom *g=first; g; g=g->next) { if (GEOM_ENABLED(g)) collideAABBs (g,geom,data,callback); } lock_count--; } //**************************************************************************** // space functions dxSpace *dSimpleSpaceCreate (dxSpace *space) { return new dxSimpleSpace (space); } dxSpace *dHashSpaceCreate (dxSpace *space) { return new dxHashSpace (space); } void dHashSpaceSetLevels (dxSpace *space, int minlevel, int maxlevel) { dAASSERT (space); dUASSERT (minlevel <= maxlevel,"must have minlevel <= maxlevel"); dUASSERT (space->type == dHashSpaceClass,"argument must be a hash space"); dxHashSpace *hspace = (dxHashSpace*) space; hspace->setLevels (minlevel,maxlevel); } void dHashSpaceGetLevels (dxSpace *space, int *minlevel, int *maxlevel) { dAASSERT (space); dUASSERT (space->type == dHashSpaceClass,"argument must be a hash space"); dxHashSpace *hspace = (dxHashSpace*) space; hspace->getLevels (minlevel,maxlevel); } void dSpaceDestroy (dxSpace *space) { dAASSERT (space); dUASSERT (dGeomIsSpace(space),"argument not a space"); dGeomDestroy (space); } void dSpaceSetCleanup (dxSpace *space, int mode) { dAASSERT (space); dUASSERT (dGeomIsSpace(space),"argument not a space"); space->setCleanup (mode); } int dSpaceGetCleanup (dxSpace *space) { dAASSERT (space); dUASSERT (dGeomIsSpace(space),"argument not a space"); return space->getCleanup(); } void dSpaceSetSublevel (dSpaceID space, int sublevel) { dAASSERT (space); dUASSERT (dGeomIsSpace(space),"argument not a space"); space->setSublevel (sublevel); } int dSpaceGetSublevel (dSpaceID space) { dAASSERT (space); dUASSERT (dGeomIsSpace(space),"argument not a space"); return space->getSublevel(); } void dSpaceSetManualCleanup (dSpaceID space, int mode) { dAASSERT (space); dUASSERT (dGeomIsSpace(space),"argument not a space"); space->setManulCleanup(mode); } int dSpaceGetManualCleanup (dSpaceID space) { dAASSERT (space); dUASSERT (dGeomIsSpace(space),"argument not a space"); return space->getManualCleanup(); } void dSpaceAdd (dxSpace *space, dxGeom *g) { dAASSERT (space); dUASSERT (dGeomIsSpace(space),"argument not a space"); CHECK_NOT_LOCKED (space); space->add (g); } void dSpaceRemove (dxSpace *space, dxGeom *g) { dAASSERT (space); dUASSERT (dGeomIsSpace(space),"argument not a space"); CHECK_NOT_LOCKED (space); space->remove (g); } int dSpaceQuery (dxSpace *space, dxGeom *g) { dAASSERT (space); dUASSERT (dGeomIsSpace(space),"argument not a space"); return space->query (g); } void dSpaceClean (dxSpace *space){ dAASSERT (space); dUASSERT (dGeomIsSpace(space),"argument not a space"); space->cleanGeoms(); } int dSpaceGetNumGeoms (dxSpace *space) { dAASSERT (space); dUASSERT (dGeomIsSpace(space),"argument not a space"); return space->getNumGeoms(); } dGeomID dSpaceGetGeom (dxSpace *space, int i) { dAASSERT (space); dUASSERT (dGeomIsSpace(space),"argument not a space"); return space->getGeom (i); } int dSpaceGetClass (dxSpace *space) { dAASSERT (space); dUASSERT (dGeomIsSpace(space),"argument not a space"); return space->type; } void dSpaceCollide (dxSpace *space, void *data, dNearCallback *callback) { dAASSERT (space && callback); dUASSERT (dGeomIsSpace(space),"argument not a space"); space->collide (data,callback); } struct DataCallback { void *data; dNearCallback *callback; }; // Invokes the callback with arguments swapped static void swap_callback(void *data, dxGeom *g1, dxGeom *g2) { DataCallback *dc = (DataCallback*)data; dc->callback(dc->data, g2, g1); } void dSpaceCollide2 (dxGeom *g1, dxGeom *g2, void *data, dNearCallback *callback) { dAASSERT (g1 && g2 && callback); dxSpace *s1,*s2; // see if either geom is a space if (IS_SPACE(g1)) s1 = (dxSpace*) g1; else s1 = 0; if (IS_SPACE(g2)) s2 = (dxSpace*) g2; else s2 = 0; if (s1 && s2) { int l1 = s1->getSublevel(); int l2 = s2->getSublevel(); if (l1 != l2) { if (l1 > l2) { s2 = 0; } else { s1 = 0; } } } // handle the four space/geom cases if (s1) { if (s2) { // g1 and g2 are spaces. if (s1==s2) { // collide a space with itself --> interior collision s1->collide (data,callback); } else { // iterate through the space that has the fewest geoms, calling // collide2 in the other space for each one. if (s1->count < s2->count) { DataCallback dc = {data, callback}; for (dxGeom *g = s1->first; g; g=g->next) { s2->collide2 (&dc,g,swap_callback); } } else { for (dxGeom *g = s2->first; g; g=g->next) { s1->collide2 (data,g,callback); } } } } else { // g1 is a space, g2 is a geom s1->collide2 (data,g2,callback); } } else { if (s2) { // g1 is a geom, g2 is a space DataCallback dc = {data, callback}; s2->collide2 (&dc,g1,swap_callback); } else { // g1 and g2 are geoms // make sure they have valid AABBs g1->recomputeAABB(); g2->recomputeAABB(); collideAABBs(g1,g2, data, callback); } } } ode-0.16/ode/src/mat.h0000664000175200017520000000626213403272463011440 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ // matrix class. this is mostly for convenience in the testing code, it is // not optimized at all. correctness is much more importance here. #ifndef _ODE_MAT_H_ #define _ODE_MAT_H_ #include class dMatrix { int n,m; // matrix dimension, n,m >= 0 dReal *data; // if nonzero, n*m elements allocated on the heap public: // constructors, destructors dMatrix(); // make default 0x0 matrix dMatrix (int rows, int cols); // construct zero matrix of given size dMatrix (const dMatrix &); // construct copy of given matrix // create copy of given data - element (i,j) is data[i*rowskip+j*colskip] dMatrix (int rows, int cols, dReal *_data, int rowskip, int colskip); ~dMatrix(); // destructor // data movement dReal & operator () (int i, int j); // reference an element void operator= (const dMatrix &); // matrix = matrix void operator= (dReal); // matrix = scalar dMatrix transpose(); // return transposed matrix // return a permuted submatrix of this matrix, made up of the rows in p // and the columns in q. p has np elements, q has nq elements. dMatrix select (int np, int *p, int nq, int *q); // operators dMatrix operator + (const dMatrix &); dMatrix operator - (const dMatrix &); dMatrix operator - (); dMatrix operator * (const dMatrix &); void operator += (const dMatrix &); void operator -= (const dMatrix &); // utility void clearUpperTriangle(); void clearLowerTriangle(); void makeRandom (dReal range); void print (const char *fmt = "%10.4f ", FILE *f=stdout); dReal maxDifference (const dMatrix &); }; #endif ode-0.16/ode/src/fastdot_impl.h0000664000175200017520000000437513403272463013347 00000000000000 /************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_FASTDOT_IMPL_H_ #define _ODE_FASTDOT_IMPL_H_ template dReal calculateLargeVectorDot (const dReal *a, const dReal *b, unsigned n) { dReal sum = 0; const dReal *a_end = a + (n & (int)(~3)); for (; a != a_end; b += 4 * b_stride, a += 4) { dReal p0 = a[0], p1 = a[1], p2 = a[2], p3 = a[3]; dReal q0 = b[0 * b_stride], q1 = b[1 * b_stride], q2 = b[2 * b_stride], q3 = b[3 * b_stride]; dReal m0 = p0 * q0; dReal m1 = p1 * q1; dReal m2 = p2 * q2; dReal m3 = p3 * q3; sum += m0 + m1 + m2 + m3; } a_end += (n & 3); for (; a != a_end; b += b_stride, ++a) { sum += (*a) * (*b); } return sum; } #endif ode-0.16/ode/src/fastlsolve_impl.h0000664000175200017520000021234213403272463014060 00000000000000 /************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* * Code style improvements and optimizations by Oleh Derevenko ????-2017 * L1Straight cooperative solving code of ThreadedEquationSolverLDLT copyright (c) 2017 Oleh Derevenko, odar@eleks.com (change all "a" to "e") */ #ifndef _ODE_FASTLSOLVE_IMPL_H_ #define _ODE_FASTLSOLVE_IMPL_H_ /* solve L*X=B, with B containing 1 right hand sides. * L is an n*n lower triangular matrix with ones on the diagonal. * L is stored by rows and its leading dimension is lskip. * B is an n*1 matrix that contains the right hand sides. * B is stored by columns and its leading dimension is also lskip. * B is overwritten with X. * this processes blocks of 4*4. * if this is in the factorizer source file, n must be a multiple of 4. */ template void solveL1Straight (const dReal *L, dReal *B, unsigned rowCount, unsigned rowSkip) { dIASSERT(rowCount != 0); /* compute all 4 x 1 blocks of X */ unsigned blockStartRow = 0; bool subsequentPass = false; bool goForLoopX4 = rowCount >= 4; const unsigned loopX4LastRow = goForLoopX4 ? rowCount - 4 : 0; for (; goForLoopX4; subsequentPass = true, goForLoopX4 = (blockStartRow += 4) <= loopX4LastRow) { /* declare variables - Z matrix, p and q vectors, etc */ const dReal *ptrLElement; dReal *ptrBElement; dReal Z11, Z21, Z31, Z41; /* compute all 4 x 1 block of X, from rows i..i+4-1 */ if (subsequentPass) { ptrLElement = L + (1 + blockStartRow) * rowSkip; ptrBElement = B; /* set the Z matrix to 0 */ Z11 = 0; Z21 = 0; Z31 = 0; Z41 = 0; /* the inner loop that computes outer products and adds them to Z */ for (unsigned columnCounter = blockStartRow; ; ) { dReal q1, p1, p2, p3, p4; /* load p and q values */ q1 = ptrBElement[0 * b_stride]; p1 = (ptrLElement - rowSkip)[0]; p2 = ptrLElement[0]; ptrLElement += rowSkip; p3 = ptrLElement[0]; p4 = ptrLElement[0 + rowSkip]; /* compute outer product and add it to the Z matrix */ Z11 += p1 * q1; Z21 += p2 * q1; Z31 += p3 * q1; Z41 += p4 * q1; /* load p and q values */ q1 = ptrBElement[1 * b_stride]; p3 = ptrLElement[1]; p4 = ptrLElement[1 + rowSkip]; ptrLElement -= rowSkip; p1 = (ptrLElement - rowSkip)[1]; p2 = ptrLElement[1]; /* compute outer product and add it to the Z matrix */ Z11 += p1 * q1; Z21 += p2 * q1; Z31 += p3 * q1; Z41 += p4 * q1; /* load p and q values */ q1 = ptrBElement[2 * b_stride]; p1 = (ptrLElement - rowSkip)[2]; p2 = ptrLElement[2]; ptrLElement += rowSkip; p3 = ptrLElement[2]; p4 = ptrLElement[2 + rowSkip]; /* compute outer product and add it to the Z matrix */ Z11 += p1 * q1; Z21 += p2 * q1; Z31 += p3 * q1; Z41 += p4 * q1; /* load p and q values */ q1 = ptrBElement[3 * b_stride]; p3 = ptrLElement[3]; p4 = ptrLElement[3 + rowSkip]; ptrLElement -= rowSkip; p1 = (ptrLElement - rowSkip)[3]; p2 = ptrLElement[3]; /* compute outer product and add it to the Z matrix */ Z11 += p1 * q1; Z21 += p2 * q1; Z31 += p3 * q1; Z41 += p4 * q1; if (columnCounter > 12) { columnCounter -= 12; /* advance pointers */ ptrLElement += 12; ptrBElement += 12 * b_stride; /* load p and q values */ q1 = ptrBElement[-8 * (int)b_stride]; p1 = (ptrLElement - rowSkip)[-8]; p2 = ptrLElement[-8]; ptrLElement += rowSkip; p3 = ptrLElement[-8]; p4 = ptrLElement[-8 + rowSkip]; /* compute outer product and add it to the Z matrix */ Z11 += p1 * q1; Z21 += p2 * q1; Z31 += p3 * q1; Z41 += p4 * q1; /* load p and q values */ q1 = ptrBElement[-7 * (int)b_stride]; p3 = ptrLElement[-7]; p4 = ptrLElement[-7 + rowSkip]; ptrLElement -= rowSkip; p1 = (ptrLElement - rowSkip)[-7]; p2 = ptrLElement[-7]; /* compute outer product and add it to the Z matrix */ Z11 += p1 * q1; Z21 += p2 * q1; Z31 += p3 * q1; Z41 += p4 * q1; /* load p and q values */ q1 = ptrBElement[-6 * (int)b_stride]; p1 = (ptrLElement - rowSkip)[-6]; p2 = ptrLElement[-6]; ptrLElement += rowSkip; p3 = ptrLElement[-6]; p4 = ptrLElement[-6 + rowSkip]; /* compute outer product and add it to the Z matrix */ Z11 += p1 * q1; Z21 += p2 * q1; Z31 += p3 * q1; Z41 += p4 * q1; /* load p and q values */ q1 = ptrBElement[-5 * (int)b_stride]; p3 = ptrLElement[-5]; p4 = ptrLElement[-5 + rowSkip]; ptrLElement -= rowSkip; p1 = (ptrLElement - rowSkip)[-5]; p2 = ptrLElement[-5]; /* compute outer product and add it to the Z matrix */ Z11 += p1 * q1; Z21 += p2 * q1; Z31 += p3 * q1; Z41 += p4 * q1; /* load p and q values */ q1 = ptrBElement[-4 * (int)b_stride]; p1 = (ptrLElement - rowSkip)[-4]; p2 = ptrLElement[-4]; ptrLElement += rowSkip; p3 = ptrLElement[-4]; p4 = ptrLElement[-4 + rowSkip]; /* compute outer product and add it to the Z matrix */ Z11 += p1 * q1; Z21 += p2 * q1; Z31 += p3 * q1; Z41 += p4 * q1; /* load p and q values */ q1 = ptrBElement[-3 * (int)b_stride]; p3 = ptrLElement[-3]; p4 = ptrLElement[-3 + rowSkip]; ptrLElement -= rowSkip; p1 = (ptrLElement - rowSkip)[-3]; p2 = ptrLElement[-3]; /* compute outer product and add it to the Z matrix */ Z11 += p1 * q1; Z21 += p2 * q1; Z31 += p3 * q1; Z41 += p4 * q1; /* load p and q values */ q1 = ptrBElement[-2 * (int)b_stride]; p1 = (ptrLElement - rowSkip)[-2]; p2 = ptrLElement[-2]; ptrLElement += rowSkip; p3 = ptrLElement[-2]; p4 = ptrLElement[-2 + rowSkip]; /* compute outer product and add it to the Z matrix */ Z11 += p1 * q1; Z21 += p2 * q1; Z31 += p3 * q1; Z41 += p4 * q1; /* load p and q values */ q1 = ptrBElement[-1 * (int)b_stride]; p3 = ptrLElement[-1]; p4 = ptrLElement[-1 + rowSkip]; ptrLElement -= rowSkip; p1 = (ptrLElement - rowSkip)[-1]; p2 = ptrLElement[-1]; /* compute outer product and add it to the Z matrix */ Z11 += p1 * q1; Z21 += p2 * q1; Z31 += p3 * q1; Z41 += p4 * q1; } else { /* advance pointers */ ptrLElement += 4; ptrBElement += 4 * b_stride; if ((columnCounter -= 4) == 0) { break; } } /* end of inner loop */ } } else { ptrLElement = L + rowSkip/* + blockStartRow * rowSkip*/; dIASSERT(blockStartRow == 0); ptrBElement = B; /* set the Z matrix to 0 */ Z11 = 0; Z21 = 0; Z31 = 0; Z41 = 0; } /* finish computing the X(i) block */ dReal Y11, Y21, Y31, Y41; { Y11 = ptrBElement[0 * b_stride] - Z11; ptrBElement[0 * b_stride] = Y11; } { dReal p2 = ptrLElement[0]; Y21 = ptrBElement[1 * b_stride] - Z21 - p2 * Y11; ptrBElement[1 * b_stride] = Y21; } ptrLElement += rowSkip; { dReal p3 = ptrLElement[0]; dReal p3_1 = ptrLElement[1]; Y31 = ptrBElement[2 * b_stride] - Z31 - p3 * Y11 - p3_1 * Y21; ptrBElement[2 * b_stride] = Y31; } { dReal p4 = ptrLElement[rowSkip]; dReal p4_1 = ptrLElement[1 + rowSkip]; dReal p4_2 = ptrLElement[2 + rowSkip]; Y41 = ptrBElement[3 * b_stride] - Z41 - p4 * Y11 - p4_1 * Y21 - p4_2 * Y31; ptrBElement[3 * b_stride] = Y41; } /* end of outer loop */ } /* compute rows at end that are not a multiple of block size */ for (; !subsequentPass || blockStartRow < rowCount; subsequentPass = true, ++blockStartRow) { /* compute all 1 x 1 block of X, from rows i..i+1-1 */ dReal *ptrBElement; dReal Z11, Z12; if (subsequentPass) { ptrBElement = B; /* set the Z matrix to 0 */ Z11 = 0; Z12 = 0; const dReal *ptrLElement = L + blockStartRow * rowSkip; /* the inner loop that computes outer products and adds them to Z */ unsigned columnCounter = blockStartRow; for (bool exitLoop = columnCounter < 4; !exitLoop; exitLoop = false) { dReal p1, p2, q1, q2; /* load p and q values */ p1 = ptrLElement[0]; p2 = ptrLElement[1]; q1 = ptrBElement[0 * b_stride]; q2 = ptrBElement[1 * b_stride]; /* compute outer product and add it to the Z matrix */ Z11 += p1 * q1; Z12 += p2 * q2; /* load p and q values */ p1 = ptrLElement[2]; p2 = ptrLElement[3]; q1 = ptrBElement[2 * b_stride]; q2 = ptrBElement[3 * b_stride]; /* compute outer product and add it to the Z matrix */ Z11 += p1 * q1; Z12 += p2 * q2; if (columnCounter >= (12 + 4)) { columnCounter -= 12; /* advance pointers */ ptrLElement += 12; ptrBElement += 12 * b_stride; /* load p and q values */ p1 = ptrLElement[-8]; p2 = ptrLElement[-7]; q1 = ptrBElement[-8 * (int)b_stride]; q2 = ptrBElement[-7 * (int)b_stride]; /* compute outer product and add it to the Z matrix */ Z11 += p1 * q1; Z12 += p2 * q2; /* load p and q values */ p1 = ptrLElement[-6]; p2 = ptrLElement[-5]; q1 = ptrBElement[-6 * (int)b_stride]; q2 = ptrBElement[-5 * (int)b_stride]; /* compute outer product and add it to the Z matrix */ Z11 += p1 * q1; Z12 += p2 * q2; /* load p and q values */ p1 = ptrLElement[-4]; p2 = ptrLElement[-3]; q1 = ptrBElement[-4 * (int)b_stride]; q2 = ptrBElement[-3 * (int)b_stride]; /* compute outer product and add it to the Z matrix */ Z11 += p1 * q1; Z12 += p2 * q2; /* load p and q values */ p1 = ptrLElement[-2]; p2 = ptrLElement[-1]; q1 = ptrBElement[-2 * (int)b_stride]; q2 = ptrBElement[-1 * (int)b_stride]; /* compute outer product and add it to the Z matrix */ Z11 += p1 * q1; Z12 += p2 * q2; } else { /* advance pointers */ ptrLElement += 4; ptrBElement += 4 * b_stride; if ((columnCounter -= 4) < 4) { break; } } /* end of inner loop */ } /* compute left-over iterations */ if ((columnCounter & 2) != 0) { dReal p1, p2, q1, q2; /* load p and q values */ p1 = ptrLElement[0]; p2 = ptrLElement[1]; q1 = ptrBElement[0 * b_stride]; q2 = ptrBElement[1 * b_stride]; /* compute outer product and add it to the Z matrix */ Z11 += p1 * q1; Z12 += p2 * q2; /* advance pointers */ ptrLElement += 2; ptrBElement += 2 * b_stride; } if ((columnCounter & 1) != 0) { dReal p1, q1; /* load p and q values */ p1 = ptrLElement[0]; q1 = ptrBElement[0 * b_stride]; /* compute outer product and add it to the Z matrix */ Z11 += p1 * q1; /* advance pointers */ // ptrLElement += 1; -- not needed any more ptrBElement += 1 * b_stride; } /* finish computing the X(i) block */ dReal Y11 = ptrBElement[0 * b_stride] - (Z11 + Z12); ptrBElement[0 * b_stride] = Y11; } } } template /*static */ sizeint ThreadedEquationSolverLDLT::estimateCooperativelySolvingL1StraightMemoryRequirement(unsigned rowCount, SolvingL1StraightMemoryEstimates &ref_solvingMemoryEstimates) { unsigned blockCount = deriveSolvingL1StraightBlockCount(rowCount, block_step); sizeint descriptorSizeRequired = dEFFICIENT_SIZE(sizeof(cellindexint) * blockCount); sizeint contextSizeRequired = dEFFICIENT_SIZE(sizeof(SolveL1StraightCellContext) * (CCI__MAX + 1) * blockCount); ref_solvingMemoryEstimates.assignData(descriptorSizeRequired, contextSizeRequired); sizeint totalSizeRequired = descriptorSizeRequired + contextSizeRequired; return totalSizeRequired; } template /*static */ void ThreadedEquationSolverLDLT::initializeCooperativelySolveL1StraightMemoryStructures(unsigned rowCount, atomicord32 &out_blockCompletionProgress, cellindexint *blockProgressDescriptors, SolveL1StraightCellContext *dUNUSED(cellContexts)) { unsigned blockCount = deriveSolvingL1StraightBlockCount(rowCount, block_step); out_blockCompletionProgress = 0; memset(blockProgressDescriptors, 0, blockCount * sizeof(*blockProgressDescriptors)); } template void ThreadedEquationSolverLDLT::participateSolvingL1Straight(const dReal *L, dReal *B, unsigned rowCount, unsigned rowSkip, volatile atomicord32 &refBlockCompletionProgress/*=0*/, volatile cellindexint *blockProgressDescriptors/*=[blockCount]*/, SolveL1StraightCellContext *cellContexts/*=[CCI__MAX x blockCount] + [blockCount]*/, unsigned ownThreadIndex) { const unsigned lookaheadRange = 32; const unsigned blockCount = deriveSolvingL1StraightBlockCount(rowCount, block_step), lastBlock = blockCount - 1; /* compute rows at end that are not a multiple of block size */ const unsigned loopX1RowCount = rowCount % block_step; BlockProcessingState blockProcessingState = BPS_NO_BLOCKS_PROCESSED; unsigned completedBlocks = refBlockCompletionProgress; unsigned currentBlock = completedBlocks; dIASSERT(completedBlocks <= blockCount); for (bool exitLoop = completedBlocks == blockCount; !exitLoop; exitLoop = false) { bool goForLockedBlockPrimaryCalculation = false, goForLockedBlockDuplicateCalculation = false; bool goAssigningTheResult = false, stayWithinTheBlock = false; dReal Z[block_step]; dReal Y[block_step]; dReal *ptrBElement; CellContextInstance previousContextInstance; unsigned completedColumnBlock; bool partialBlock; for (cellindexint testDescriptor = blockProgressDescriptors[currentBlock]; ; ) { if (testDescriptor == INVALID_CELLDESCRIPTOR) { // Invalid descriptor is the indication that the row has been fully calculated // Test if this was the last row and break out if so. if (currentBlock + 1 == blockCount) { exitLoop = true; break; } // Treat detected row advancement as a row processed // blockProcessingState = BPS_SOME_BLOCKS_PROCESSED; <-- performs better without it break; } CooperativeAtomics::AtomicReadReorderBarrier(); // It is necessary to read up to date completedBblocks value after the descriptor retrieval // as otherwise the logic below breaks completedBlocks = refBlockCompletionProgress; if (!GET_CELLDESCRIPTOR_ISLOCKED(testDescriptor)) { completedColumnBlock = GET_CELLDESCRIPTOR_COLUMNINDEX(testDescriptor); dIASSERT(completedColumnBlock < currentBlock || (completedColumnBlock == currentBlock && currentBlock == 0)); // Otherwise, why would the calculation have had stopped if the final column is reachable??? dIASSERT(completedColumnBlock <= completedBlocks); // Since the descriptor is not locked if (completedColumnBlock == completedBlocks && currentBlock != completedBlocks) { dIASSERT(completedBlocks < currentBlock); break; } if (CooperativeAtomics::AtomicCompareExchangeCellindexint(&blockProgressDescriptors[currentBlock], testDescriptor, MARK_CELLDESCRIPTOR_LOCKED(testDescriptor))) { if (completedColumnBlock != 0) { CellContextInstance contextInstance = GET_CELLDESCRIPTOR_CONTEXTINSTANCE(testDescriptor); previousContextInstance = contextInstance; const SolveL1StraightCellContext &sourceContext = buildBlockContextRef(cellContexts, currentBlock, contextInstance); sourceContext.loadPrecalculatedZs(Z); } else { previousContextInstance = CCI__MIN; SolveL1StraightCellContext::initializePrecalculatedZs(Z); } goForLockedBlockPrimaryCalculation = true; break; } if (blockProcessingState != BPS_COMPETING_FOR_A_BLOCK) { break; } testDescriptor = blockProgressDescriptors[currentBlock]; } else { if (blockProcessingState != BPS_COMPETING_FOR_A_BLOCK) { break; } cellindexint verificativeDescriptor; bool verificationFailure = false; completedColumnBlock = GET_CELLDESCRIPTOR_COLUMNINDEX(testDescriptor); dIASSERT(completedColumnBlock != currentBlock || currentBlock == 0); // There is no reason for computations to stop at the very end other than being the initial value at the very first block if (completedColumnBlock != 0) { CellContextInstance contextInstance = GET_CELLDESCRIPTOR_CONTEXTINSTANCE(testDescriptor); const SolveL1StraightCellContext &sourceContext = buildBlockContextRef(cellContexts, currentBlock, contextInstance); sourceContext.loadPrecalculatedZs(Z); } else { SolveL1StraightCellContext::initializePrecalculatedZs(Z); } if (completedColumnBlock != 0 && completedColumnBlock <= currentBlock) { // Make sure the descriptor is re-read after the precalculates CooperativeAtomics::AtomicReadReorderBarrier(); } if (completedColumnBlock <= currentBlock) { verificativeDescriptor = blockProgressDescriptors[currentBlock]; verificationFailure = verificativeDescriptor != testDescriptor; } if (!verificationFailure) { dIASSERT(completedColumnBlock <= currentBlock + 1); goForLockedBlockDuplicateCalculation = true; break; } testDescriptor = verificativeDescriptor; } } if (exitLoop) { break; } if (goForLockedBlockPrimaryCalculation) { blockProcessingState = BPS_SOME_BLOCKS_PROCESSED; // Declare and assign the variables at the top to not interfere with any branching -- the compiler is going to eliminate them anyway. bool handleComputationTakenOver = false, rowEndReached = false; const dReal *ptrLElement; unsigned finalColumnBlock; /* check if this is not the partial block of fewer rows */ if (currentBlock != lastBlock || loopX1RowCount == 0) { partialBlock = false; if (currentBlock != 0) { ptrLElement = L + (sizeint)(1 + currentBlock * block_step) * rowSkip + completedColumnBlock * block_step; ptrBElement = B + (sizeint)(completedColumnBlock * block_step) * b_stride; /* the inner loop that computes outer products and adds them to Z */ finalColumnBlock = dMACRO_MIN(currentBlock, completedBlocks); dIASSERT(completedColumnBlock != finalColumnBlock/* || currentBlock == 0*/); for (unsigned columnCounter = finalColumnBlock - completedColumnBlock; ; ) { dReal q1, p1, p2, p3, p4; /* load p and q values */ q1 = ptrBElement[0 * b_stride]; p1 = (ptrLElement - rowSkip)[0]; p2 = ptrLElement[0]; ptrLElement += rowSkip; p3 = ptrLElement[0]; p4 = ptrLElement[0 + rowSkip]; /* compute outer product and add it to the Z matrix */ Z[0] += p1 * q1; Z[1] += p2 * q1; Z[2] += p3 * q1; Z[3] += p4 * q1; /* load p and q values */ q1 = ptrBElement[1 * b_stride]; p3 = ptrLElement[1]; p4 = ptrLElement[1 + rowSkip]; ptrLElement -= rowSkip; p1 = (ptrLElement - rowSkip)[1]; p2 = ptrLElement[1]; /* compute outer product and add it to the Z matrix */ Z[0] += p1 * q1; Z[1] += p2 * q1; Z[2] += p3 * q1; Z[3] += p4 * q1; /* load p and q values */ q1 = ptrBElement[2 * b_stride]; p1 = (ptrLElement - rowSkip)[2]; p2 = ptrLElement[2]; ptrLElement += rowSkip; p3 = ptrLElement[2]; p4 = ptrLElement[2 + rowSkip]; /* compute outer product and add it to the Z matrix */ Z[0] += p1 * q1; Z[1] += p2 * q1; Z[2] += p3 * q1; Z[3] += p4 * q1; /* load p and q values */ q1 = ptrBElement[3 * b_stride]; p3 = ptrLElement[3]; p4 = ptrLElement[3 + rowSkip]; ptrLElement -= rowSkip; p1 = (ptrLElement - rowSkip)[3]; p2 = ptrLElement[3]; /* compute outer product and add it to the Z matrix */ Z[0] += p1 * q1; Z[1] += p2 * q1; Z[2] += p3 * q1; Z[3] += p4 * q1; dSASSERT(block_step == 4); if (columnCounter > 3) { columnCounter -= 3; ptrLElement += 3 * block_step; ptrBElement += 3 * block_step * b_stride; /* load p and q values */ q1 = ptrBElement[-8 * (int)b_stride]; p1 = (ptrLElement - rowSkip)[-8]; p2 = ptrLElement[-8]; ptrLElement += rowSkip; p3 = ptrLElement[-8]; p4 = ptrLElement[-8 + rowSkip]; /* compute outer product and add it to the Z matrix */ Z[0] += p1 * q1; Z[1] += p2 * q1; Z[2] += p3 * q1; Z[3] += p4 * q1; /* load p and q values */ q1 = ptrBElement[-7 * (int)b_stride]; p3 = ptrLElement[-7]; p4 = ptrLElement[-7 + rowSkip]; ptrLElement -= rowSkip; p1 = (ptrLElement - rowSkip)[-7]; p2 = ptrLElement[-7]; /* compute outer product and add it to the Z matrix */ Z[0] += p1 * q1; Z[1] += p2 * q1; Z[2] += p3 * q1; Z[3] += p4 * q1; /* load p and q values */ q1 = ptrBElement[-6 * (int)b_stride]; p1 = (ptrLElement - rowSkip)[-6]; p2 = ptrLElement[-6]; ptrLElement += rowSkip; p3 = ptrLElement[-6]; p4 = ptrLElement[-6 + rowSkip]; /* compute outer product and add it to the Z matrix */ Z[0] += p1 * q1; Z[1] += p2 * q1; Z[2] += p3 * q1; Z[3] += p4 * q1; /* load p and q values */ q1 = ptrBElement[-5 * (int)b_stride]; p3 = ptrLElement[-5]; p4 = ptrLElement[-5 + rowSkip]; ptrLElement -= rowSkip; p1 = (ptrLElement - rowSkip)[-5]; p2 = ptrLElement[-5]; /* compute outer product and add it to the Z matrix */ Z[0] += p1 * q1; Z[1] += p2 * q1; Z[2] += p3 * q1; Z[3] += p4 * q1; /* load p and q values */ q1 = ptrBElement[-4 * (int)b_stride]; p1 = (ptrLElement - rowSkip)[-4]; p2 = ptrLElement[-4]; ptrLElement += rowSkip; p3 = ptrLElement[-4]; p4 = ptrLElement[-4 + rowSkip]; /* compute outer product and add it to the Z matrix */ Z[0] += p1 * q1; Z[1] += p2 * q1; Z[2] += p3 * q1; Z[3] += p4 * q1; /* load p and q values */ q1 = ptrBElement[-3 * (int)b_stride]; p3 = ptrLElement[-3]; p4 = ptrLElement[-3 + rowSkip]; ptrLElement -= rowSkip; p1 = (ptrLElement - rowSkip)[-3]; p2 = ptrLElement[-3]; /* compute outer product and add it to the Z matrix */ Z[0] += p1 * q1; Z[1] += p2 * q1; Z[2] += p3 * q1; Z[3] += p4 * q1; /* load p and q values */ q1 = ptrBElement[-2 * (int)b_stride]; p1 = (ptrLElement - rowSkip)[-2]; p2 = ptrLElement[-2]; ptrLElement += rowSkip; p3 = ptrLElement[-2]; p4 = ptrLElement[-2 + rowSkip]; /* compute outer product and add it to the Z matrix */ Z[0] += p1 * q1; Z[1] += p2 * q1; Z[2] += p3 * q1; Z[3] += p4 * q1; /* load p and q values */ q1 = ptrBElement[-1 * (int)b_stride]; p3 = ptrLElement[-1]; p4 = ptrLElement[-1 + rowSkip]; ptrLElement -= rowSkip; p1 = (ptrLElement - rowSkip)[-1]; p2 = ptrLElement[-1]; /* compute outer product and add it to the Z matrix */ Z[0] += p1 * q1; Z[1] += p2 * q1; Z[2] += p3 * q1; Z[3] += p4 * q1; dSASSERT(block_step == 4); } else { ptrLElement += block_step; ptrBElement += block_step * b_stride; if (--columnCounter == 0) { if (finalColumnBlock == currentBlock) { rowEndReached = true; break; } // Take a look if any more columns have been completed... completedBlocks = refBlockCompletionProgress; dIASSERT(completedBlocks >= finalColumnBlock); if (completedBlocks == finalColumnBlock) { break; } // ...continue if so. unsigned columnCompletedSoFar = finalColumnBlock; finalColumnBlock = dMACRO_MIN(currentBlock, completedBlocks); columnCounter = finalColumnBlock - columnCompletedSoFar; } } /* end of inner loop */ } } else { ptrLElement = L + (sizeint)(1/* + currentBlock * block_step*/) * rowSkip/* + completedColumnBlock * block_step*/; ptrBElement = B/* + (sizeint)(completedColumnBlock * block_step) * b_stride*/; dIASSERT(completedColumnBlock == 0); rowEndReached = true; } } else { partialBlock = true; if (currentBlock != 0) { dReal tempZ[dMACRO_MAX(block_step - 1U, 1U)] = { REAL(0.0), }; ptrLElement = L + (sizeint)(/*1 + */currentBlock * block_step) * rowSkip + completedColumnBlock * block_step; ptrBElement = B + (sizeint)(completedColumnBlock * block_step) * b_stride; /* the inner loop that computes outer products and adds them to Z */ finalColumnBlock = dMACRO_MIN(currentBlock, completedBlocks); dIASSERT(completedColumnBlock != finalColumnBlock/* || currentBlock == 0*/); for (unsigned partialRow = 0, columnCompletedSoFar = completedColumnBlock; ; ) { dReal Z1 = 0, Z2 = 0, Z3 = 0, Z4 = 0; for (unsigned columnCounter = finalColumnBlock - columnCompletedSoFar; ; ) { dReal q1, q2, q3, q4, p1, p2, p3, p4; /* load p and q values */ q1 = ptrBElement[0 * b_stride]; q2 = ptrBElement[1 * b_stride]; q3 = ptrBElement[2 * b_stride]; q4 = ptrBElement[3 * b_stride]; p1 = ptrLElement[0]; p2 = ptrLElement[1]; p3 = ptrLElement[2]; p4 = ptrLElement[3]; /* compute outer product and add it to the Z matrix */ Z1 += p1 * q1; Z2 += p2 * q2; Z3 += p3 * q3; Z4 += p4 * q4; dSASSERT(block_step == 4); if (columnCounter > 3) { columnCounter -= 3; ptrLElement += 3 * block_step; ptrBElement += 3 * block_step * b_stride; /* load p and q values */ q1 = ptrBElement[-8 * (int)b_stride]; q2 = ptrBElement[-7 * (int)b_stride]; q3 = ptrBElement[-6 * (int)b_stride]; q4 = ptrBElement[-5 * (int)b_stride]; p1 = ptrLElement[-8]; p2 = ptrLElement[-7]; p3 = ptrLElement[-6]; p4 = ptrLElement[-5]; /* compute outer product and add it to the Z matrix */ Z1 += p1 * q1; Z2 += p2 * q2; Z3 += p3 * q3; Z4 += p4 * q4; /* load p and q values */ q1 = ptrBElement[-4 * (int)b_stride]; q2 = ptrBElement[-3 * (int)b_stride]; q3 = ptrBElement[-2 * (int)b_stride]; q4 = ptrBElement[-1 * (int)b_stride]; p1 = ptrLElement[-4]; p2 = ptrLElement[-3]; p3 = ptrLElement[-2]; p4 = ptrLElement[-1]; /* compute outer product and add it to the Z matrix */ Z1 += p1 * q1; Z2 += p2 * q2; Z3 += p3 * q3; Z4 += p4 * q4; dSASSERT(block_step == 4); } else { ptrLElement += block_step; ptrBElement += block_step * b_stride; if (--columnCounter == 0) { break; } } /* end of inner loop */ } tempZ[partialRow] += Z1 + Z2 + Z3 + Z4; if (++partialRow == loopX1RowCount) { // Here switch is used to avoid accessing Z by parametrized index. // So far all the accesses were performed by explicit constants // what lets the compiler treat Z elements as individual variables // rather than array elements. Z[0] += tempZ[0]; if (loopX1RowCount >= 2) { Z[1] += tempZ[1]; if (loopX1RowCount > 2) { Z[2] += tempZ[2]; } } dSASSERT(block_step == 4); if (finalColumnBlock == currentBlock) { if (loopX1RowCount > 2) { // Correct the LElement so that it points to the second row // // Note, that ff there is just one partial row, it does not matter that // the LElement will remain pointing at the first row, // since the former is not going to be used in that case. ptrLElement -= /*(sizeint)*/rowSkip/* * (loopX1RowCount - 2)*/; dIASSERT(loopX1RowCount == 3); } dSASSERT(block_step == 4); rowEndReached = true; break; } // Take a look if any more columns have been completed... completedBlocks = refBlockCompletionProgress; dIASSERT(completedBlocks >= finalColumnBlock); if (completedBlocks == finalColumnBlock) { break; } std::fill(tempZ, tempZ + loopX1RowCount, REAL(0.0)); partialRow = 0; // Correct the LElement pointer to continue at the first partial row ptrLElement -= (sizeint)rowSkip * (loopX1RowCount - 1); // ...continue if so. columnCompletedSoFar = finalColumnBlock; finalColumnBlock = dMACRO_MIN(currentBlock, completedBlocks); } else { ptrLElement += rowSkip - (finalColumnBlock - columnCompletedSoFar) * block_step; ptrBElement -= (sizeint)((finalColumnBlock - columnCompletedSoFar) * block_step) * b_stride; } /* end of loop by individual rows */ } } else { ptrLElement = L + (sizeint)(1/* + currentBlock * block_step*/) * rowSkip/* + completedColumnBlock * block_step*/; ptrBElement = B/* + (sizeint)(completedColumnBlock * block_step) * b_stride*/; dIASSERT(completedColumnBlock == 0); rowEndReached = true; } } if (rowEndReached) { // Check whether there is still a need to proceed or if the computation has been taken over by another thread cellindexint oldDescriptor = MAKE_CELLDESCRIPTOR(completedColumnBlock, previousContextInstance, true); if (blockProgressDescriptors[currentBlock] == oldDescriptor) { /* finish computing the X(i) block */ if (!partialBlock) { Y[0] = ptrBElement[0 * b_stride] - Z[0]; dReal p2 = ptrLElement[0]; Y[1] = ptrBElement[1 * b_stride] - Z[1] - p2 * Y[0]; ptrLElement += rowSkip; dReal p3 = ptrLElement[0]; dReal p3_1 = ptrLElement[1]; Y[2] = ptrBElement[2 * b_stride] - Z[2] - p3 * Y[0] - p3_1 * Y[1]; dReal p4 = ptrLElement[rowSkip]; dReal p4_1 = ptrLElement[1 + rowSkip]; dReal p4_2 = ptrLElement[2 + rowSkip]; Y[3] = ptrBElement[3 * b_stride] - Z[3] - p4 * Y[0] - p4_1 * Y[1] - p4_2 * Y[2]; dSASSERT(block_step == 4); } else { Y[0] = ptrBElement[0 * b_stride] - Z[0]; if (loopX1RowCount >= 2) { dReal p2 = ptrLElement[0]; Y[1] = ptrBElement[1 * b_stride] - Z[1] - p2 * Y[0]; if (loopX1RowCount > 2) { dReal p3 = ptrLElement[0 + rowSkip]; dReal p3_1 = ptrLElement[1 + rowSkip]; Y[2] = ptrBElement[2 * b_stride] - Z[2] - p3 * Y[0] - p3_1 * Y[1]; } } dSASSERT(block_step == 4); } // Use atomic memory barrier to make sure memory reads of ptrBElement[] and blockProgressDescriptors[] are not swapped CooperativeAtomics::AtomicReadReorderBarrier(); // The descriptor has not been altered yet - this means the ptrBElement[] values used above were not modified yet // and the computation result is valid. if (blockProgressDescriptors[currentBlock] == oldDescriptor) { // Assign the results to the result context (possibly in parallel with other threads // that could and ought to be assigning exactly the same values) SolveL1StraightCellContext &resultContext = buildResultContextRef(cellContexts, currentBlock, blockCount); resultContext.storePrecalculatedZs(Y); // Assign the result assignment progress descriptor cellindexint newDescriptor = MAKE_CELLDESCRIPTOR(currentBlock + 1, CCI__MIN, true); CooperativeAtomics::AtomicCompareExchangeCellindexint(&blockProgressDescriptors[currentBlock], oldDescriptor, newDescriptor); // the result is to be ignored // Whether succeeded or not, the result is valid, so go on trying to assign it to the matrix goAssigningTheResult = true; } else { // Otherwise, go on competing for copying the results handleComputationTakenOver = true; } } else { handleComputationTakenOver = true; } } else { // If the final column has not been reached yet, store current values to the context. // Select the other context instance as the previous one might be read by other threads. CellContextInstance nextContextInstance = buildNextContextInstance(previousContextInstance); SolveL1StraightCellContext &destinationContext = buildBlockContextRef(cellContexts, currentBlock, nextContextInstance); destinationContext.storePrecalculatedZs(Z); // Unlock the row until more columns can be used cellindexint oldDescriptor = MAKE_CELLDESCRIPTOR(completedColumnBlock, previousContextInstance, true); cellindexint newDescriptor = MAKE_CELLDESCRIPTOR(finalColumnBlock, nextContextInstance, false); // The descriptor might have been updated by a competing thread if (!CooperativeAtomics::AtomicCompareExchangeCellindexint(&blockProgressDescriptors[currentBlock], oldDescriptor, newDescriptor)) { // Adjust the ptrBElement to point to the result area... ptrBElement = B + (sizeint)(currentBlock * block_step) * b_stride; // ...and go on handling the case handleComputationTakenOver = true; } } if (handleComputationTakenOver) { cellindexint existingDescriptor = blockProgressDescriptors[currentBlock]; // This can only happen if the row was (has become) the uppermost not fully completed one // and the competing thread is at final stage of calculation (i.e., it has reached the currentBlock column). if (existingDescriptor != INVALID_CELLDESCRIPTOR) { // If not fully completed this must be the final stage of the result assignment into the matrix dIASSERT(existingDescriptor == MAKE_CELLDESCRIPTOR(currentBlock + 1, CCI__MIN, true)); // Go on competing copying the result as anyway the block is the topmost not completed one // and since there was competition for it, there is no other work that can be done right now. const SolveL1StraightCellContext &resultContext = buildResultContextRef(cellContexts, currentBlock, blockCount); resultContext.loadPrecalculatedZs(Y); goAssigningTheResult = true; } else { // everything is over -- just go handling next blocks } } } else if (goForLockedBlockDuplicateCalculation) { blockProcessingState = BPS_SOME_BLOCKS_PROCESSED; bool skipToHandlingSubsequentRows = false, skiptoCopyingResult = false; /* declare variables */ const dReal *ptrLElement; if (completedColumnBlock < currentBlock) { /* check if this is not the partial block of fewer rows */ if (currentBlock != lastBlock || loopX1RowCount == 0) { partialBlock = false; ptrLElement = L + (sizeint)(1 + currentBlock * block_step) * rowSkip + completedColumnBlock * block_step; ptrBElement = B + (sizeint)(completedColumnBlock * block_step) * b_stride; /* the inner loop that computes outer products and adds them to Z */ unsigned finalColumnBlock = currentBlock; dIASSERT(currentBlock == completedBlocks); // Why would we be competing for a row otherwise? unsigned lastCompletedColumn = completedColumnBlock; unsigned columnCounter = finalColumnBlock - completedColumnBlock; for (bool exitInnerLoop = false; !exitInnerLoop; exitInnerLoop = --columnCounter == 0) { dReal q1, p1, p2, p3, p4; /* load p and q values */ q1 = ptrBElement[0 * b_stride]; p1 = (ptrLElement - rowSkip)[0]; p2 = ptrLElement[0]; ptrLElement += rowSkip; p3 = ptrLElement[0]; p4 = ptrLElement[0 + rowSkip]; /* compute outer product and add it to the Z matrix */ Z[0] += p1 * q1; Z[1] += p2 * q1; Z[2] += p3 * q1; Z[3] += p4 * q1; /* load p and q values */ q1 = ptrBElement[1 * b_stride]; p3 = ptrLElement[1]; p4 = ptrLElement[1 + rowSkip]; ptrLElement -= rowSkip; p1 = (ptrLElement - rowSkip)[1]; p2 = ptrLElement[1]; /* compute outer product and add it to the Z matrix */ Z[0] += p1 * q1; Z[1] += p2 * q1; Z[2] += p3 * q1; Z[3] += p4 * q1; /* load p and q values */ q1 = ptrBElement[2 * b_stride]; p1 = (ptrLElement - rowSkip)[2]; p2 = ptrLElement[2]; ptrLElement += rowSkip; p3 = ptrLElement[2]; p4 = ptrLElement[2 + rowSkip]; /* compute outer product and add it to the Z matrix */ Z[0] += p1 * q1; Z[1] += p2 * q1; Z[2] += p3 * q1; Z[3] += p4 * q1; /* load p and q values */ q1 = ptrBElement[3 * b_stride]; p3 = ptrLElement[3]; p4 = ptrLElement[3 + rowSkip]; ptrLElement -= rowSkip; p1 = (ptrLElement - rowSkip)[3]; p2 = ptrLElement[3]; /* compute outer product and add it to the Z matrix */ Z[0] += p1 * q1; Z[1] += p2 * q1; Z[2] += p3 * q1; Z[3] += p4 * q1; dSASSERT(block_step == 4); // Check if the primary solver thread has not made any progress cellindexint descriptorVerification = blockProgressDescriptors[currentBlock]; unsigned newCompletedColumn = GET_CELLDESCRIPTOR_COLUMNINDEX(descriptorVerification); if (newCompletedColumn != lastCompletedColumn) { // Check, this is the first change the current thread detects. // There is absolutely no reason in code for the computation to stop/resume twice // while the current thread is competing. dIASSERT(lastCompletedColumn == completedColumnBlock); if (descriptorVerification == INVALID_CELLDESCRIPTOR) { skipToHandlingSubsequentRows = true; break; } if (newCompletedColumn == currentBlock + 1) { skiptoCopyingResult = true; break; } // Check if the current thread is behind if (newCompletedColumn > finalColumnBlock - columnCounter) { // If so, go starting over one more time blockProcessingState = BPS_COMPETING_FOR_A_BLOCK; stayWithinTheBlock = true; skipToHandlingSubsequentRows = true; break; } // If current thread is ahead, just save new completed column for further comparisons and go on calculating lastCompletedColumn = newCompletedColumn; } /* advance pointers */ ptrLElement += block_step; ptrBElement += block_step * b_stride; /* end of inner loop */ } } else { partialBlock = true; dReal tempZ[dMACRO_MAX(block_step - 1U, 1U)] = { REAL(0.0), }; ptrLElement = L + (sizeint)(/*1 + */currentBlock * block_step) * rowSkip + completedColumnBlock * block_step; ptrBElement = B + (sizeint)(completedColumnBlock * block_step) * b_stride; /* the inner loop that computes outer products and adds them to Z */ unsigned finalColumnBlock = currentBlock; dIASSERT(currentBlock == completedBlocks); // Why would we be competing for a row otherwise? unsigned lastCompletedColumn = completedColumnBlock; for (unsigned columnCounter = finalColumnBlock - completedColumnBlock; ; ) { dReal q1, q2, q3, q4; /* load q values */ q1 = ptrBElement[0 * b_stride]; q2 = ptrBElement[1 * b_stride]; q3 = ptrBElement[2 * b_stride]; q4 = ptrBElement[3 * b_stride]; for (unsigned partialRow = 0; ; ) { dReal p1, p2, p3, p4; /* load p values */ p1 = ptrLElement[0]; p2 = ptrLElement[1]; p3 = ptrLElement[2]; p4 = ptrLElement[3]; /* compute outer product and add it to the Z matrix */ tempZ[partialRow] += p1 * q1 + p2 * q2 + p3 * q3 + p4 * q4; dSASSERT(block_step == 4); if (++partialRow == loopX1RowCount) { break; } ptrLElement += rowSkip; } // Check if the primary solver thread has not made any progress cellindexint descriptorVerification = blockProgressDescriptors[currentBlock]; unsigned newCompletedColumn = GET_CELLDESCRIPTOR_COLUMNINDEX(descriptorVerification); if (newCompletedColumn != lastCompletedColumn) { // Check, this is the first change the current thread detects. // There is absolutely no reason in code for the computation to stop/resume twice // while the current thread is competing. dIASSERT(lastCompletedColumn == completedColumnBlock); if (descriptorVerification == INVALID_CELLDESCRIPTOR) { skipToHandlingSubsequentRows = true; break; } if (newCompletedColumn == currentBlock + 1) { skiptoCopyingResult = true; break; } // Check if the current thread is behind if (newCompletedColumn > finalColumnBlock - columnCounter) { // If so, go starting over one more time blockProcessingState = BPS_COMPETING_FOR_A_BLOCK; stayWithinTheBlock = true; skipToHandlingSubsequentRows = true; break; } // If current thread is ahead, just save new completed column for further comparisons and go on calculating lastCompletedColumn = newCompletedColumn; } ptrLElement += block_step; ptrBElement += block_step * b_stride; if (--columnCounter == 0) { // Here switch is used to avoid accessing Z by parametrized index. // So far all the accesses were performed by explicit constants // what lets the compiler treat Z elements as individual variables // rather than array elements. Z[0] += tempZ[0]; if (loopX1RowCount >= 2) { Z[1] += tempZ[1]; if (loopX1RowCount > 2) { Z[2] += tempZ[2]; // Correct the LElement so that it points to the second row // // Note, that if there is just one partial row, it does not matter that // the LElement will remain pointing at the first row, // since the former is not going to be used in that case. ptrLElement -= /*(sizeint)*/rowSkip/* * (loopX1RowCount - 2)*/; dIASSERT(loopX1RowCount == 3); } } dSASSERT(block_step == 4); break; } /* advance pointers */ ptrLElement -= (sizeint)rowSkip * (loopX1RowCount - 1); /* end of inner loop */ } } } else if (completedColumnBlock > currentBlock) { dIASSERT(completedColumnBlock == currentBlock + 1); partialBlock = currentBlock == lastBlock && loopX1RowCount != 0; skiptoCopyingResult = true; } else { dIASSERT(currentBlock == 0); // Execution can get here within the very first block only partialBlock = rowCount < block_step; /* assign the pointers appropriately and go on computing the results */ ptrLElement = L + (sizeint)(1/* + currentBlock * block_step*/) * rowSkip/* + completedColumnBlock * block_step*/; ptrBElement = B/* + (sizeint)(completedColumnBlock * block_step) * b_stride*/; } if (!skipToHandlingSubsequentRows) { if (!skiptoCopyingResult) { if (!partialBlock) { Y[0] = ptrBElement[0 * b_stride] - Z[0]; dReal p2 = ptrLElement[0]; Y[1] = ptrBElement[1 * b_stride] - Z[1] - p2 * Y[0]; ptrLElement += rowSkip; dReal p3 = ptrLElement[0]; dReal p3_1 = ptrLElement[1]; Y[2] = ptrBElement[2 * b_stride] - Z[2] - p3 * Y[0] - p3_1 * Y[1]; dReal p4 = ptrLElement[rowSkip]; dReal p4_1 = ptrLElement[1 + rowSkip]; dReal p4_2 = ptrLElement[2 + rowSkip]; Y[3] = ptrBElement[3 * b_stride] - Z[3] - p4 * Y[0] - p4_1 * Y[1] - p4_2 * Y[2]; dSASSERT(block_step == 4); } else { Y[0] = ptrBElement[0 * b_stride] - Z[0]; if (loopX1RowCount >= 2) { dReal p2 = ptrLElement[0]; Y[1] = ptrBElement[1 * b_stride] - Z[1] - p2 * Y[0]; if (loopX1RowCount > 2) { dReal p3 = ptrLElement[0 + rowSkip]; dReal p3_1 = ptrLElement[1 + rowSkip]; Y[2] = ptrBElement[2 * b_stride] - Z[2] - p3 * Y[0] - p3_1 * Y[1]; } } dSASSERT(block_step == 4); } CooperativeAtomics::AtomicReadReorderBarrier(); // Use atomic load to make sure memory reads of ptrBElement[] and blockProgressDescriptors[] are not swapped cellindexint existingDescriptor = blockProgressDescriptors[currentBlock]; if (existingDescriptor == INVALID_CELLDESCRIPTOR) { // Everything is over -- proceed to subsequent rows skipToHandlingSubsequentRows = true; } else if (existingDescriptor == MAKE_CELLDESCRIPTOR(currentBlock + 1, CCI__MIN, true)) { // The values computed above may not be valid. Copy the values already in the result context. skiptoCopyingResult = true; } else { // The descriptor has not been altered yet - this means the ptrBElement[] values used above were not modified yet // and the computation result is valid. cellindexint newDescriptor = MAKE_CELLDESCRIPTOR(currentBlock + 1, CCI__MIN, true); // put the computation at the top so that the evaluation result from the expression above is reused // Assign the results to the result context (possibly in parallel with other threads // that could and ought to be assigning exactly the same values) SolveL1StraightCellContext &resultContext = buildResultContextRef(cellContexts, currentBlock, blockCount); resultContext.storePrecalculatedZs(Y); // Assign the result assignment progress descriptor CooperativeAtomics::AtomicCompareExchangeCellindexint(&blockProgressDescriptors[currentBlock], existingDescriptor, newDescriptor); // the result is to be ignored // Whether succeeded or not, the result is valid, so go on trying to assign it to the matrix } } if (!skipToHandlingSubsequentRows) { if (skiptoCopyingResult) { // Extract the result values stored in the result context const SolveL1StraightCellContext &resultContext = buildResultContextRef(cellContexts, currentBlock, blockCount); resultContext.loadPrecalculatedZs(Y); ptrBElement = B + (sizeint)(currentBlock * block_step) * b_stride; } goAssigningTheResult = true; } } } if (goAssigningTheResult) { cellindexint existingDescriptor = blockProgressDescriptors[currentBlock]; // Check if the assignment has not been completed yet if (existingDescriptor != INVALID_CELLDESCRIPTOR) { // Assign the computation results to the B vector if (!partialBlock) { ptrBElement[0 * b_stride] = Y[0]; ptrBElement[1 * b_stride] = Y[1]; ptrBElement[2 * b_stride] = Y[2]; ptrBElement[3 * b_stride] = Y[3]; dSASSERT(block_step == 4); } else { ptrBElement[0 * b_stride] = Y[0]; if (loopX1RowCount >= 2) { ptrBElement[1 * b_stride] = Y[1]; if (loopX1RowCount > 2) { ptrBElement[2 * b_stride] = Y[2]; } } dSASSERT(block_step == 4); } ThrsafeIncrementIntUpToLimit(&refBlockCompletionProgress, currentBlock + 1); dIASSERT(refBlockCompletionProgress >= currentBlock + 1); // And assign the completed status no matter what CooperativeAtomics::AtomicStoreCellindexint(&blockProgressDescriptors[currentBlock], INVALID_CELLDESCRIPTOR); } else { // everything is over -- just go handling next blocks } } if (!stayWithinTheBlock) { completedBlocks = refBlockCompletionProgress; if (completedBlocks == blockCount) { break; } currentBlock += 1; bool lookaheadBoundaryReached = false; if (currentBlock == blockCount || completedBlocks == 0) { lookaheadBoundaryReached = true; } else if (currentBlock >= completedBlocks + lookaheadRange) { lookaheadBoundaryReached = blockProcessingState > BPS_NO_BLOCKS_PROCESSED; } else if (currentBlock < completedBlocks) { // Treat detected row advancement as a row processed // blockProcessingState = BPS_SOME_BLOCKS_PROCESSED; <-- performs better without it currentBlock = completedBlocks; } if (lookaheadBoundaryReached) { dIASSERT(blockProcessingState != BPS_COMPETING_FOR_A_BLOCK); // Why did not we compete??? // If no row has been processed in the previous pass, compete for the next row to avoid cycling uselessly if (blockProcessingState <= BPS_NO_BLOCKS_PROCESSED) { // Abandon job if too few blocks remain if (blockCount - completedBlocks <= ownThreadIndex) { break; } blockProcessingState = BPS_COMPETING_FOR_A_BLOCK; } else { // If there was some progress, just continue to the next pass blockProcessingState = BPS_NO_BLOCKS_PROCESSED; } currentBlock = completedBlocks; } } } } #endif ode-0.16/ode/src/heightfield.cpp0000664000175200017520000017371213403272463013473 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ // dHeightfield Collider // Paul Cheyrou-Lagreze aka Tuan Kuranes 2006 Speed enhancements http://www.pop-3d.com // Martijn Buijs 2006 http://home.planet.nl/~buijs512/ // Based on Terrain & Cone contrib by: // Benoit CHAPEROT 2003-2004 http://www.jstarlab.com // Some code inspired by Magic Software #include #include #include #include "config.h" #include "matrix.h" #include "odemath.h" #include "collision_kernel.h" #include "collision_std.h" #include "collision_util.h" #include "heightfield.h" #if dTRIMESH_ENABLED #include "collision_trimesh_colliders.h" #endif // dTRIMESH_ENABLED #define dMIN(A,B) ((A)>(B) ? (B) : (A)) #define dMAX(A,B) ((A)>(B) ? (A) : (B)) // Three-way MIN and MAX #define dMIN3(A,B,C) ( (A)<(B) ? dMIN((A),(C)) : dMIN((B),(C)) ) #define dMAX3(A,B,C) ( (A)>(B) ? dMAX((A),(C)) : dMAX((B),(C)) ) #define dOPESIGN(a, op1, op2,b) \ (a)[0] op1 op2 ((b)[0]); \ (a)[1] op1 op2 ((b)[1]); \ (a)[2] op1 op2 ((b)[2]); #define dGeomRaySetNoNormalize(myRay, MyPoint, MyVector) { \ \ dVector3Copy (MyPoint, (myRay).final_posr->pos); \ (myRay).final_posr->R[2] = (MyVector)[0]; \ (myRay).final_posr->R[6] = (MyVector)[1]; \ (myRay).final_posr->R[10] = (MyVector)[2]; \ dGeomMoved (&myRay); \ } #define dGeomPlaneSetNoNormalize(MyPlane, MyPlaneDef) { \ \ (MyPlane)->p[0] = (MyPlaneDef)[0]; \ (MyPlane)->p[1] = (MyPlaneDef)[1]; \ (MyPlane)->p[2] = (MyPlaneDef)[2]; \ (MyPlane)->p[3] = (MyPlaneDef)[3]; \ dGeomMoved (MyPlane); \ } //////// Local Build Option //////////////////////////////////////////////////// // Uncomment this #define to use the (0,0) corner of the geom as the origin, // rather than the center. This was the way the original heightfield worked, // but as it does not match the way all other geometries work, so for constancy it // was changed to work like this. // #define DHEIGHTFIELD_CORNER_ORIGIN // Uncomment this #define to add heightfield triangles edge colliding // Code is not guaranteed and I didn't find the need to add that as // colliding planes triangles and edge triangles seems enough. // #define _HEIGHTFIELDEDGECOLLIDING //////// dxHeightfieldData ///////////////////////////////////////////////////////////// // dxHeightfieldData constructor dxHeightfieldData::dxHeightfieldData(): m_fWidth( 0 ), m_fDepth( 0 ), m_fSampleWidth( 0 ), m_fSampleDepth( 0 ), m_fSampleZXAspect( 0 ), m_fInvSampleWidth( 0 ), m_fInvSampleDepth( 0 ), m_fHalfWidth( 0 ), m_fHalfDepth( 0 ), m_fMinHeight( 0 ), m_fMaxHeight( 0 ), m_fThickness( 0 ), m_fScale( 0 ), m_fOffset( 0 ), m_nWidthSamples( 0 ), m_nDepthSamples( 0 ), m_bCopyHeightData( 0 ), m_bWrapMode( 0 ), m_nGetHeightMode( 0 ), m_pHeightData( NULL ), m_pUserData( NULL ), m_pGetHeightCallback( NULL ) { memset( m_contacts, 0, sizeof( m_contacts ) ); } // build Heightfield data void dxHeightfieldData::SetData( int nWidthSamples, int nDepthSamples, dReal fWidth, dReal fDepth, dReal fScale, dReal fOffset, dReal fThickness, int bWrapMode ) { dIASSERT( fWidth > REAL( 0.0 ) ); dIASSERT( fDepth > REAL( 0.0 ) ); dIASSERT( nWidthSamples > 0 ); dIASSERT( nDepthSamples > 0 ); // x,z bounds m_fWidth = fWidth; m_fDepth = fDepth; // cache half x,z bounds m_fHalfWidth = fWidth / REAL( 2.0 ); m_fHalfDepth = fDepth / REAL( 2.0 ); // scale and offset m_fScale = fScale; m_fOffset = fOffset; // infinite min height bounds m_fThickness = fThickness; // number of vertices per side m_nWidthSamples = nWidthSamples; m_nDepthSamples = nDepthSamples; m_fSampleWidth = m_fWidth / ( m_nWidthSamples - REAL( 1.0 ) ); m_fSampleDepth = m_fDepth / ( m_nDepthSamples - REAL( 1.0 ) ); m_fSampleZXAspect = m_fSampleDepth / m_fSampleWidth; m_fInvSampleWidth = REAL( 1.0 ) / m_fSampleWidth; m_fInvSampleDepth = REAL( 1.0 ) / m_fSampleDepth; // finite or repeated terrain? m_bWrapMode = bWrapMode; } // recomputes heights bounds void dxHeightfieldData::ComputeHeightBounds() { int i; dReal h; unsigned char *data_byte; short *data_short; float *data_float; double *data_double; switch ( m_nGetHeightMode ) { // callback case 0: // change nothing, keep using default or user specified bounds return; // byte case 1: data_byte = (unsigned char*)m_pHeightData; m_fMinHeight = dInfinity; m_fMaxHeight = -dInfinity; for (i=0; i m_fMaxHeight) m_fMaxHeight = h; } break; // short case 2: data_short = (short*)m_pHeightData; m_fMinHeight = dInfinity; m_fMaxHeight = -dInfinity; for (i=0; i m_fMaxHeight) m_fMaxHeight = h; } break; // float case 3: data_float = (float*)m_pHeightData; m_fMinHeight = dInfinity; m_fMaxHeight = -dInfinity; for (i=0; i m_fMaxHeight) m_fMaxHeight = h; } break; // double case 4: data_double = (double*)m_pHeightData; m_fMinHeight = dInfinity; m_fMaxHeight = -dInfinity; for (i=0; i( data_double[i] ); if (h < m_fMinHeight) m_fMinHeight = h; if (h > m_fMaxHeight) m_fMaxHeight = h; } break; } // scale and offset m_fMinHeight *= m_fScale; m_fMaxHeight *= m_fScale; m_fMinHeight += m_fOffset; m_fMaxHeight += m_fOffset; // add thickness m_fMinHeight -= m_fThickness; } // returns whether point is over terrain Cell triangle? bool dxHeightfieldData::IsOnHeightfield2 ( const HeightFieldVertex * const CellCorner, const dReal * const pos, const bool isABC) const { // WARNING!!! // This function must be written in the way to make sure that every point on // XZ plane falls in one and only one triangle. Keep that in mind if you // intend to change the code. // Also remember about computational errors and possible mismatches in // values if they are calculated differently in different places in the code. // Currently both the implementation has been optimized and effects of // computational errors have been eliminated. dReal MaxX, MinX; dReal MaxZ, MinZ; if (isABC) { // point A MinX = CellCorner->vertex[0]; if (pos[0] < MinX) return false; MaxX = (CellCorner->coords[0] + 1) * m_fSampleWidth; if (pos[0] >= MaxX) return false; MinZ = CellCorner->vertex[2]; if (pos[2] < MinZ) return false; MaxZ = (CellCorner->coords[1] + 1) * m_fSampleDepth; if (pos[2] >= MaxZ) return false; return (MaxZ - pos[2]) > (pos[0] - MinX) * m_fSampleZXAspect; } else { // point D MaxX = CellCorner->vertex[0]; if (pos[0] >= MaxX) return false; MinX = (CellCorner->coords[0] - 1) * m_fSampleWidth; if (pos[0] < MinX) return false; MaxZ = CellCorner->vertex[2]; if (pos[2] >= MaxZ) return false; MinZ = (CellCorner->coords[1] - 1) * m_fSampleDepth; if (pos[2] < MinZ) return false; return (MaxZ - pos[2]) <= (pos[0] - MinX) * m_fSampleZXAspect; } } // returns height at given sample coordinates dReal dxHeightfieldData::GetHeight( int x, int z ) { dReal h=0; unsigned char *data_byte; short *data_short; float *data_float; double *data_double; if ( m_bWrapMode == 0 ) { // Finite if ( x < 0 ) x = 0; if ( z < 0 ) z = 0; if ( x > m_nWidthSamples - 1 ) x = m_nWidthSamples - 1; if ( z > m_nDepthSamples - 1 ) z = m_nDepthSamples - 1; } else { // Infinite x %= m_nWidthSamples - 1; z %= m_nDepthSamples - 1; if ( x < 0 ) x += m_nWidthSamples - 1; if ( z < 0 ) z += m_nDepthSamples - 1; } switch ( m_nGetHeightMode ) { // callback (dReal) case 0: h = (*m_pGetHeightCallback)(m_pUserData, x, z); break; // byte case 1: data_byte = (unsigned char*)m_pHeightData; h = data_byte[x+(z * m_nWidthSamples)]; break; // short case 2: data_short = (short*)m_pHeightData; h = data_short[x+(z * m_nWidthSamples)]; break; // float case 3: data_float = (float*)m_pHeightData; h = data_float[x+(z * m_nWidthSamples)]; break; // double case 4: data_double = (double*)m_pHeightData; h = (dReal)( data_double[x+(z * m_nWidthSamples)] ); break; } return (h * m_fScale) + m_fOffset; } // returns height at given coordinates dReal dxHeightfieldData::GetHeight( dReal x, dReal z ) { dReal dnX = dFloor( x * m_fInvSampleWidth ); dReal dnZ = dFloor( z * m_fInvSampleDepth ); dReal dx = ( x - ( dnX * m_fSampleWidth ) ) * m_fInvSampleWidth; dReal dz = ( z - ( dnZ * m_fSampleDepth ) ) * m_fInvSampleDepth; int nX = int( dnX ); int nZ = int( dnZ ); //dIASSERT( ( dx + dEpsilon >= 0.0f ) && ( dx - dEpsilon <= 1.0f ) ); //dIASSERT( ( dz + dEpsilon >= 0.0f ) && ( dz - dEpsilon <= 1.0f ) ); dReal y, y0; if ( dx + dz <= REAL( 1.0 ) ) // Use <= comparison to prefer simpler branch { y0 = GetHeight( nX, nZ ); y = y0 + ( GetHeight( nX + 1, nZ ) - y0 ) * dx + ( GetHeight( nX, nZ + 1 ) - y0 ) * dz; } else { y0 = GetHeight( nX + 1, nZ + 1 ); y = y0 + ( GetHeight( nX + 1, nZ ) - y0 ) * ( REAL(1.0) - dz ) + ( GetHeight( nX, nZ + 1 ) - y0 ) * ( REAL(1.0) - dx ); } return y; } // dxHeightfieldData destructor dxHeightfieldData::~dxHeightfieldData() { unsigned char *data_byte; short *data_short; float *data_float; double *data_double; if ( m_bCopyHeightData ) { switch ( m_nGetHeightMode ) { // callback case 0: // do nothing break; // byte case 1: dIASSERT( m_pHeightData ); data_byte = (unsigned char*)m_pHeightData; delete [] data_byte; break; // short case 2: dIASSERT( m_pHeightData ); data_short = (short*)m_pHeightData; delete [] data_short; break; // float case 3: dIASSERT( m_pHeightData ); data_float = (float*)m_pHeightData; delete [] data_float; break; // double case 4: dIASSERT( m_pHeightData ); data_double = (double*)m_pHeightData; delete [] data_double; break; } } } //////// dxHeightfield ///////////////////////////////////////////////////////////////// // dxHeightfield constructor dxHeightfield::dxHeightfield( dSpaceID space, dHeightfieldDataID data, int bPlaceable ) : dxGeom( space, bPlaceable ), tempPlaneBuffer(0), tempPlaneInstances(0), tempPlaneBufferSize(0), tempTriangleBuffer(0), tempTriangleBufferSize(0), tempHeightBuffer(0), tempHeightInstances(0), tempHeightBufferSizeX(0), tempHeightBufferSizeZ(0) { type = dHeightfieldClass; this->m_p_data = data; } // compute axis aligned bounding box void dxHeightfield::computeAABB() { const dxHeightfieldData *d = m_p_data; if ( d->m_bWrapMode == 0 ) { // Finite if ( gflags & GEOM_PLACEABLE ) { dReal dx[6], dy[6], dz[6]; // Y-axis if (d->m_fMinHeight != -dInfinity) { dy[0] = ( final_posr->R[ 1] * d->m_fMinHeight ); dy[1] = ( final_posr->R[ 5] * d->m_fMinHeight ); dy[2] = ( final_posr->R[ 9] * d->m_fMinHeight ); } else { // Multiplication is performed to obtain infinity of correct sign dy[0] = ( final_posr->R[ 1] ? final_posr->R[ 1] * -dInfinity : REAL(0.0) ); dy[1] = ( final_posr->R[ 5] ? final_posr->R[ 5] * -dInfinity : REAL(0.0) ); dy[2] = ( final_posr->R[ 9] ? final_posr->R[ 9] * -dInfinity : REAL(0.0) ); } if (d->m_fMaxHeight != dInfinity) { dy[3] = ( final_posr->R[ 1] * d->m_fMaxHeight ); dy[4] = ( final_posr->R[ 5] * d->m_fMaxHeight ); dy[5] = ( final_posr->R[ 9] * d->m_fMaxHeight ); } else { dy[3] = ( final_posr->R[ 1] ? final_posr->R[ 1] * dInfinity : REAL(0.0) ); dy[4] = ( final_posr->R[ 5] ? final_posr->R[ 5] * dInfinity : REAL(0.0) ); dy[5] = ( final_posr->R[ 9] ? final_posr->R[ 9] * dInfinity : REAL(0.0) ); } #ifdef DHEIGHTFIELD_CORNER_ORIGIN // X-axis dx[0] = 0; dx[3] = ( final_posr->R[ 0] * d->m_fWidth ); dx[1] = 0; dx[4] = ( final_posr->R[ 4] * d->m_fWidth ); dx[2] = 0; dx[5] = ( final_posr->R[ 8] * d->m_fWidth ); // Z-axis dz[0] = 0; dz[3] = ( final_posr->R[ 2] * d->m_fDepth ); dz[1] = 0; dz[4] = ( final_posr->R[ 6] * d->m_fDepth ); dz[2] = 0; dz[5] = ( final_posr->R[10] * d->m_fDepth ); #else // DHEIGHTFIELD_CORNER_ORIGIN // X-axis dx[0] = ( final_posr->R[ 0] * -d->m_fHalfWidth ); dx[1] = ( final_posr->R[ 4] * -d->m_fHalfWidth ); dx[2] = ( final_posr->R[ 8] * -d->m_fHalfWidth ); dx[3] = ( final_posr->R[ 0] * d->m_fHalfWidth ); dx[4] = ( final_posr->R[ 4] * d->m_fHalfWidth ); dx[5] = ( final_posr->R[ 8] * d->m_fHalfWidth ); // Z-axis dz[0] = ( final_posr->R[ 2] * -d->m_fHalfDepth ); dz[1] = ( final_posr->R[ 6] * -d->m_fHalfDepth ); dz[2] = ( final_posr->R[10] * -d->m_fHalfDepth ); dz[3] = ( final_posr->R[ 2] * d->m_fHalfDepth ); dz[4] = ( final_posr->R[ 6] * d->m_fHalfDepth ); dz[5] = ( final_posr->R[10] * d->m_fHalfDepth ); #endif // DHEIGHTFIELD_CORNER_ORIGIN // X extents aabb[0] = final_posr->pos[0] + dMIN3( dMIN( dx[0], dx[3] ), dMIN( dy[0], dy[3] ), dMIN( dz[0], dz[3] ) ); aabb[1] = final_posr->pos[0] + dMAX3( dMAX( dx[0], dx[3] ), dMAX( dy[0], dy[3] ), dMAX( dz[0], dz[3] ) ); // Y extents aabb[2] = final_posr->pos[1] + dMIN3( dMIN( dx[1], dx[4] ), dMIN( dy[1], dy[4] ), dMIN( dz[1], dz[4] ) ); aabb[3] = final_posr->pos[1] + dMAX3( dMAX( dx[1], dx[4] ), dMAX( dy[1], dy[4] ), dMAX( dz[1], dz[4] ) ); // Z extents aabb[4] = final_posr->pos[2] + dMIN3( dMIN( dx[2], dx[5] ), dMIN( dy[2], dy[5] ), dMIN( dz[2], dz[5] ) ); aabb[5] = final_posr->pos[2] + dMAX3( dMAX( dx[2], dx[5] ), dMAX( dy[2], dy[5] ), dMAX( dz[2], dz[5] ) ); } else { #ifdef DHEIGHTFIELD_CORNER_ORIGIN aabb[0] = 0; aabb[1] = d->m_fWidth; aabb[2] = d->m_fMinHeight; aabb[3] = d->m_fMaxHeight; aabb[4] = 0; aabb[5] = d->m_fDepth; #else // DHEIGHTFIELD_CORNER_ORIGIN aabb[0] = -d->m_fHalfWidth; aabb[1] = +d->m_fHalfWidth; aabb[2] = d->m_fMinHeight; aabb[3] = d->m_fMaxHeight; aabb[4] = -d->m_fHalfDepth; aabb[5] = +d->m_fHalfDepth; #endif // DHEIGHTFIELD_CORNER_ORIGIN } } else { // Infinite if ( gflags & GEOM_PLACEABLE ) { aabb[0] = -dInfinity; aabb[1] = +dInfinity; aabb[2] = -dInfinity; aabb[3] = +dInfinity; aabb[4] = -dInfinity; aabb[5] = +dInfinity; } else { aabb[0] = -dInfinity; aabb[1] = +dInfinity; aabb[2] = d->m_fMinHeight; aabb[3] = d->m_fMaxHeight; aabb[4] = -dInfinity; aabb[5] = +dInfinity; } } } // dxHeightfield destructor dxHeightfield::~dxHeightfield() { resetTriangleBuffer(); resetPlaneBuffer(); resetHeightBuffer(); } void dxHeightfield::allocateTriangleBuffer(sizeint numTri) { sizeint alignedNumTri = AlignBufferSize(numTri, TEMP_TRIANGLE_BUFFER_ELEMENT_COUNT_ALIGNMENT); tempTriangleBufferSize = alignedNumTri; tempTriangleBuffer = new HeightFieldTriangle[alignedNumTri]; } void dxHeightfield::resetTriangleBuffer() { delete[] tempTriangleBuffer; } void dxHeightfield::allocatePlaneBuffer(sizeint numTri) { sizeint alignedNumTri = AlignBufferSize(numTri, TEMP_PLANE_BUFFER_ELEMENT_COUNT_ALIGNMENT); tempPlaneBufferSize = alignedNumTri; tempPlaneBuffer = new HeightFieldPlane *[alignedNumTri]; tempPlaneInstances = new HeightFieldPlane[alignedNumTri]; HeightFieldPlane *ptrPlaneMatrix = tempPlaneInstances; for (sizeint indexTri = 0; indexTri != alignedNumTri; indexTri++) { tempPlaneBuffer[indexTri] = ptrPlaneMatrix; ptrPlaneMatrix += 1; } } void dxHeightfield::resetPlaneBuffer() { delete[] tempPlaneInstances; delete[] tempPlaneBuffer; } void dxHeightfield::allocateHeightBuffer(sizeint numX, sizeint numZ) { sizeint alignedNumX = AlignBufferSize(numX, TEMP_HEIGHT_BUFFER_ELEMENT_COUNT_ALIGNMENT_X); sizeint alignedNumZ = AlignBufferSize(numZ, TEMP_HEIGHT_BUFFER_ELEMENT_COUNT_ALIGNMENT_Z); tempHeightBufferSizeX = alignedNumX; tempHeightBufferSizeZ = alignedNumZ; tempHeightBuffer = new HeightFieldVertex *[alignedNumX]; sizeint numCells = alignedNumX * alignedNumZ; tempHeightInstances = new HeightFieldVertex [numCells]; HeightFieldVertex *ptrHeightMatrix = tempHeightInstances; for (sizeint indexX = 0; indexX != alignedNumX; indexX++) { tempHeightBuffer[indexX] = ptrHeightMatrix; ptrHeightMatrix += alignedNumZ; } } void dxHeightfield::resetHeightBuffer() { delete[] tempHeightInstances; delete[] tempHeightBuffer; } //////// Heightfield data interface //////////////////////////////////////////////////// dHeightfieldDataID dGeomHeightfieldDataCreate() { return new dxHeightfieldData(); } void dGeomHeightfieldDataBuildCallback( dHeightfieldDataID d, void* pUserData, dHeightfieldGetHeight* pCallback, dReal width, dReal depth, int widthSamples, int depthSamples, dReal scale, dReal offset, dReal thickness, int bWrap ) { dUASSERT( d, "argument not Heightfield data" ); dIASSERT( pCallback ); dIASSERT( widthSamples >= 2 ); // Ensure we're making something with at least one cell. dIASSERT( depthSamples >= 2 ); // callback d->m_nGetHeightMode = 0; d->m_pUserData = pUserData; d->m_pGetHeightCallback = pCallback; // set info d->SetData( widthSamples, depthSamples, width, depth, scale, offset, thickness, bWrap ); // default bounds d->m_fMinHeight = -dInfinity; d->m_fMaxHeight = dInfinity; } void dGeomHeightfieldDataBuildByte( dHeightfieldDataID d, const unsigned char *pHeightData, int bCopyHeightData, dReal width, dReal depth, int widthSamples, int depthSamples, dReal scale, dReal offset, dReal thickness, int bWrap ) { dUASSERT( d, "Argument not Heightfield data" ); dIASSERT( pHeightData ); dIASSERT( widthSamples >= 2 ); // Ensure we're making something with at least one cell. dIASSERT( depthSamples >= 2 ); // set info d->SetData( widthSamples, depthSamples, width, depth, scale, offset, thickness, bWrap ); d->m_nGetHeightMode = 1; d->m_bCopyHeightData = bCopyHeightData; if ( d->m_bCopyHeightData == 0 ) { // Data is referenced only. d->m_pHeightData = pHeightData; } else { // We own the height data, allocate storage d->m_pHeightData = new unsigned char[ d->m_nWidthSamples * d->m_nDepthSamples ]; dIASSERT( d->m_pHeightData ); // Copy data. memcpy( (void*)d->m_pHeightData, pHeightData, sizeof( unsigned char ) * d->m_nWidthSamples * d->m_nDepthSamples ); } // Find height bounds d->ComputeHeightBounds(); } void dGeomHeightfieldDataBuildShort( dHeightfieldDataID d, const short* pHeightData, int bCopyHeightData, dReal width, dReal depth, int widthSamples, int depthSamples, dReal scale, dReal offset, dReal thickness, int bWrap ) { dUASSERT( d, "Argument not Heightfield data" ); dIASSERT( pHeightData ); dIASSERT( widthSamples >= 2 ); // Ensure we're making something with at least one cell. dIASSERT( depthSamples >= 2 ); // set info d->SetData( widthSamples, depthSamples, width, depth, scale, offset, thickness, bWrap ); d->m_nGetHeightMode = 2; d->m_bCopyHeightData = bCopyHeightData; if ( d->m_bCopyHeightData == 0 ) { // Data is referenced only. d->m_pHeightData = pHeightData; } else { // We own the height data, allocate storage d->m_pHeightData = new short[ d->m_nWidthSamples * d->m_nDepthSamples ]; dIASSERT( d->m_pHeightData ); // Copy data. memcpy( (void*)d->m_pHeightData, pHeightData, sizeof( short ) * d->m_nWidthSamples * d->m_nDepthSamples ); } // Find height bounds d->ComputeHeightBounds(); } void dGeomHeightfieldDataBuildSingle( dHeightfieldDataID d, const float *pHeightData, int bCopyHeightData, dReal width, dReal depth, int widthSamples, int depthSamples, dReal scale, dReal offset, dReal thickness, int bWrap ) { dUASSERT( d, "Argument not Heightfield data" ); dIASSERT( pHeightData ); dIASSERT( widthSamples >= 2 ); // Ensure we're making something with at least one cell. dIASSERT( depthSamples >= 2 ); // set info d->SetData( widthSamples, depthSamples, width, depth, scale, offset, thickness, bWrap ); d->m_nGetHeightMode = 3; d->m_bCopyHeightData = bCopyHeightData; if ( d->m_bCopyHeightData == 0 ) { // Data is referenced only. d->m_pHeightData = pHeightData; } else { // We own the height data, allocate storage d->m_pHeightData = new float[ d->m_nWidthSamples * d->m_nDepthSamples ]; dIASSERT( d->m_pHeightData ); // Copy data. memcpy( (void*)d->m_pHeightData, pHeightData, sizeof( float ) * d->m_nWidthSamples * d->m_nDepthSamples ); } // Find height bounds d->ComputeHeightBounds(); } void dGeomHeightfieldDataBuildDouble( dHeightfieldDataID d, const double *pHeightData, int bCopyHeightData, dReal width, dReal depth, int widthSamples, int depthSamples, dReal scale, dReal offset, dReal thickness, int bWrap ) { dUASSERT( d, "Argument not Heightfield data" ); dIASSERT( pHeightData ); dIASSERT( widthSamples >= 2 ); // Ensure we're making something with at least one cell. dIASSERT( depthSamples >= 2 ); // set info d->SetData( widthSamples, depthSamples, width, depth, scale, offset, thickness, bWrap ); d->m_nGetHeightMode = 4; d->m_bCopyHeightData = bCopyHeightData; if ( d->m_bCopyHeightData == 0 ) { // Data is referenced only. d->m_pHeightData = pHeightData; } else { // We own the height data, allocate storage d->m_pHeightData = new double[ d->m_nWidthSamples * d->m_nDepthSamples ]; dIASSERT( d->m_pHeightData ); // Copy data. memcpy( (void*)d->m_pHeightData, pHeightData, sizeof( double ) * d->m_nWidthSamples * d->m_nDepthSamples ); } // Find height bounds d->ComputeHeightBounds(); } void dGeomHeightfieldDataSetBounds( dHeightfieldDataID d, dReal minHeight, dReal maxHeight ) { dUASSERT(d, "Argument not Heightfield data"); d->m_fMinHeight = ( minHeight * d->m_fScale ) + d->m_fOffset - d->m_fThickness; d->m_fMaxHeight = ( maxHeight * d->m_fScale ) + d->m_fOffset; } void dGeomHeightfieldDataDestroy( dHeightfieldDataID d ) { dUASSERT(d, "argument not Heightfield data"); delete d; } //////// Heightfield geom interface //////////////////////////////////////////////////// dGeomID dCreateHeightfield( dSpaceID space, dHeightfieldDataID data, int bPlaceable ) { return new dxHeightfield( space, data, bPlaceable ); } void dGeomHeightfieldSetHeightfieldData( dGeomID g, dHeightfieldDataID d ) { dxHeightfield* geom = (dxHeightfield*) g; geom->m_p_data = d; } dHeightfieldDataID dGeomHeightfieldGetHeightfieldData( dGeomID g ) { dxHeightfield* geom = (dxHeightfield*) g; return geom->m_p_data; } //////// dxHeightfield ///////////////////////////////////////////////////////////////// // Typedef for generic 'get point depth' function typedef dReal dGetDepthFn( dGeomID g, dReal x, dReal y, dReal z ); #define DMESS(A) \ dMessage(0,"Contact Plane (%d %d %d) %.5e %.5e (%.5e %.5e %.5e)(%.5e %.5e %.5e)).", \ x,z,(A), \ pContact->depth, \ dGeomSphereGetRadius(o2), \ pContact->pos[0], \ pContact->pos[1], \ pContact->pos[2], \ pContact->normal[0], \ pContact->normal[1], \ pContact->normal[2]); static inline bool DescendingTriangleSort(const HeightFieldTriangle * const A, const HeightFieldTriangle * const B) { return ((A->maxAAAB - B->maxAAAB) > dEpsilon); } static inline bool DescendingPlaneSort(const HeightFieldPlane * const A, const HeightFieldPlane * const B) { return ((A->maxAAAB - B->maxAAAB) > dEpsilon); } void dxHeightfield::sortPlanes(const sizeint numPlanes) { bool has_swapped = true; do { has_swapped = false;//reset flag for (sizeint i = 0; i < numPlanes - 1; i++) { //if they are in the wrong order if (DescendingPlaneSort(tempPlaneBuffer[i], tempPlaneBuffer[i + 1])) { //exchange them HeightFieldPlane * tempPlane = tempPlaneBuffer[i]; tempPlaneBuffer[i] = tempPlaneBuffer[i + 1]; tempPlaneBuffer[i + 1] = tempPlane; //we have swapped at least once, list may not be sorted yet has_swapped = true; } } } //if no swaps were made during this pass, the list has been sorted while (has_swapped); } static inline dReal DistancePointToLine(const dVector3 &_point, const dVector3 &_pt0, const dVector3 &_Edge, const dReal _Edgelength) { dVector3 v; dVector3Subtract(_point, _pt0, v); dVector3 s; dVector3Copy (_Edge, s); const dReal dot = dVector3Dot(v, _Edge) / _Edgelength; dVector3Scale(s, dot); dVector3Subtract(v, s, v); return dVector3Length(v); } int dxHeightfield::dCollideHeightfieldZone( const int minX, const int maxX, const int minZ, const int maxZ, dxGeom* o2, const int numMaxContactsPossible, int flags, dContactGeom* contact, int skip ) { dContactGeom *pContact = 0; int x, z; // check if not above or inside terrain first // while filling a heightmap partial temporary buffer const unsigned int numX = (maxX - minX) + 1; const unsigned int numZ = (maxZ - minZ) + 1; const dReal minO2Height = o2->aabb[2]; const dReal maxO2Height = o2->aabb[3]; unsigned int x_local, z_local; dReal maxY = - dInfinity; dReal minY = dInfinity; // localize and const for faster access const dReal cfSampleWidth = m_p_data->m_fSampleWidth; const dReal cfSampleDepth = m_p_data->m_fSampleDepth; { if (tempHeightBufferSizeX < numX || tempHeightBufferSizeZ < numZ) { resetHeightBuffer(); allocateHeightBuffer(numX, numZ); } dReal Xpos, Ypos; for ( x = minX, x_local = 0; x_local < numX; x++, x_local++) { Xpos = x * cfSampleWidth; // Always calculate pos via multiplication to avoid computational error accumulation during multiple additions const dReal c_Xpos = Xpos; HeightFieldVertex *HeightFieldRow = tempHeightBuffer[x_local]; for ( z = minZ, z_local = 0; z_local < numZ; z++, z_local++) { Ypos = z * cfSampleDepth; // Always calculate pos via multiplication to avoid computational error accumulation during multiple additions const dReal h = m_p_data->GetHeight(x, z); HeightFieldRow[z_local].vertex[0] = c_Xpos; HeightFieldRow[z_local].vertex[1] = h; HeightFieldRow[z_local].vertex[2] = Ypos; HeightFieldRow[z_local].coords[0] = x; HeightFieldRow[z_local].coords[1] = z; maxY = dMAX(maxY, h); minY = dMIN(minY, h); } } if (minO2Height - maxY > -dEpsilon ) { //totally above heightfield return 0; } if (minY - maxO2Height > -dEpsilon ) { // totally under heightfield pContact = CONTACT(contact, 0); pContact->pos[0] = o2->final_posr->pos[0]; pContact->pos[1] = minY; pContact->pos[2] = o2->final_posr->pos[2]; pContact->normal[0] = 0; pContact->normal[1] = - 1; pContact->normal[2] = 0; pContact->depth = minY - maxO2Height; pContact->side1 = -1; pContact->side2 = -1; return 1; } } // get All Planes that could collide against. dColliderFn *geomRayNCollider=0; dColliderFn *geomNPlaneCollider=0; dGetDepthFn *geomNDepthGetter=0; // int max_collisionContact = numMaxContactsPossible; -- not used switch (o2->type) { case dRayClass: geomRayNCollider = NULL; geomNPlaneCollider = dCollideRayPlane; geomNDepthGetter = NULL; //max_collisionContact = 1; break; case dSphereClass: geomRayNCollider = dCollideRaySphere; geomNPlaneCollider = dCollideSpherePlane; geomNDepthGetter = dGeomSpherePointDepth; //max_collisionContact = 3; break; case dBoxClass: geomRayNCollider = dCollideRayBox; geomNPlaneCollider = dCollideBoxPlane; geomNDepthGetter = dGeomBoxPointDepth; //max_collisionContact = 8; break; case dCapsuleClass: geomRayNCollider = dCollideRayCapsule; geomNPlaneCollider = dCollideCapsulePlane; geomNDepthGetter = dGeomCapsulePointDepth; // max_collisionContact = 3; break; case dCylinderClass: geomRayNCollider = dCollideRayCylinder; geomNPlaneCollider = dCollideCylinderPlane; geomNDepthGetter = NULL;// TODO: dGeomCCylinderPointDepth //max_collisionContact = 3; break; case dConvexClass: geomRayNCollider = dCollideRayConvex; geomNPlaneCollider = dCollideConvexPlane; geomNDepthGetter = NULL;// TODO: dGeomConvexPointDepth; //max_collisionContact = 3; break; #if dTRIMESH_ENABLED case dTriMeshClass: geomRayNCollider = dCollideRayTrimesh; geomNPlaneCollider = dCollideTrimeshPlane; geomNDepthGetter = NULL;// TODO: dGeomTrimeshPointDepth; //max_collisionContact = 3; break; #endif // dTRIMESH_ENABLED default: dIASSERT(0); // Shouldn't ever get here. break; } dxPlane myplane(0,0,0,0,0); dxPlane* sliding_plane = &myplane; dReal triplane[4]; int i; // check some trivial case. // Vector Up plane if (maxY - minY < dEpsilon) { // it's a single plane. triplane[0] = 0; triplane[1] = 1; triplane[2] = 0; triplane[3] = minY; dGeomPlaneSetNoNormalize (sliding_plane, triplane); // find collision and compute contact points const int numTerrainContacts = geomNPlaneCollider (o2, sliding_plane, flags, contact, skip); dIASSERT(numTerrainContacts <= numMaxContactsPossible); for (i = 0; i < numTerrainContacts; i++) { pContact = CONTACT(contact, i*skip); dOPESIGN(pContact->normal, =, -, triplane); } return numTerrainContacts; } /* -- This block is invalid as per Martijn Buijs The problem seems to be based on the erroneously assumption that if two of the four vertices of a 'grid' are at the same height, the entire grid can be represented as a single plane. It works for an axis aligned slope, but fails on all 4 grids of a 3x3 spike feature. Since the plane normal is constructed from only 3 vertices (only one of the two triangles) this often results in discontinuities at the grid edges (causing small jumps when the contact point moves from one grid to another). // unique plane { // check for very simple plane heightfield dReal minXHeightDelta = dInfinity, maxXHeightDelta = - dInfinity; dReal minZHeightDelta = dInfinity, maxZHeightDelta = - dInfinity; dReal lastXHeight = tempHeightBuffer[0][0].vertex[1]; for ( x_local = 1; x_local < numX; x_local++) { HeightFieldVertex *HeightFieldRow = tempHeightBuffer[x_local]; const dReal deltaX = HeightFieldRow[0].vertex[1] - lastXHeight; maxXHeightDelta = dMAX (maxXHeightDelta, deltaX); minXHeightDelta = dMIN (minXHeightDelta, deltaX); dReal lastZHeight = HeightFieldRow[0].vertex[1]; for ( z_local = 1; z_local < numZ; z_local++) { const dReal deltaZ = (HeightFieldRow[z_local].vertex[1] - lastZHeight); maxZHeightDelta = dMAX (maxZHeightDelta, deltaZ); minZHeightDelta = dMIN (minZHeightDelta, deltaZ); } } if (maxZHeightDelta - minZHeightDelta < dEpsilon && maxXHeightDelta - minXHeightDelta < dEpsilon ) { // it's a single plane. const dVector3 &A = tempHeightBuffer[0][0].vertex; const dVector3 &B = tempHeightBuffer[1][0].vertex; const dVector3 &C = tempHeightBuffer[0][1].vertex; // define 2 edges and a point that will define collision plane { dVector3 Edge1, Edge2; dVector3Subtract(C, A, Edge1); dVector3Subtract(B, A, Edge2); dVector3Cross(Edge1, Edge2, triplane); } // Define Plane // Normalize plane normal const dReal dinvlength = REAL(1.0) / dVector3Length(triplane); triplane[0] *= dinvlength; triplane[1] *= dinvlength; triplane[2] *= dinvlength; // get distance to origin from plane triplane[3] = dVector3Dot(triplane, A); dGeomPlaneSetNoNormalize (sliding_plane, triplane); // find collision and compute contact points const int numTerrainContacts = geomNPlaneCollider (o2, sliding_plane, flags, contact, skip); dIASSERT(numTerrainContacts <= numMaxContactsPossible); for (i = 0; i < numTerrainContacts; i++) { pContact = CONTACT(contact, i*skip); dOPESIGN(pContact->normal, =, -, triplane); } return numTerrainContacts; } } */ int numTerrainContacts = 0; dContactGeom *PlaneContact = m_p_data->m_contacts; const unsigned int numTriMax = (maxX - minX) * (maxZ - minZ) * 2; if (tempTriangleBufferSize < numTriMax) { resetTriangleBuffer(); allocateTriangleBuffer(numTriMax); } // Sorting triangle/plane resulting from heightfield zone // Perhaps that would be necessary in case of too much limited // maximum contact point... // or in complex mesh case (trimesh and convex) // need some test or insights on this before enabling this. const bool isContactNumPointsLimited = true; // (numMaxContacts < 8) // || o2->type == dConvexClass // || o2->type == dTriMeshClass // || (numMaxContacts < (int)numTriMax) // if small heightfield triangle related to O2 colliding // or no Triangle colliding at all. bool needFurtherPasses = (o2->type == dTriMeshClass); //compute Ratio between Triangle size and O2 aabb size // no FurtherPasses are needed in ray class if (o2->type != dRayClass && needFurtherPasses == false) { const dReal xratio = (o2->aabb[1] - o2->aabb[0]) * m_p_data->m_fInvSampleWidth; if (xratio > REAL(1.5)) needFurtherPasses = true; else { const dReal zratio = (o2->aabb[5] - o2->aabb[4]) * m_p_data->m_fInvSampleDepth; if (zratio > REAL(1.5)) needFurtherPasses = true; } } unsigned int numTri = 0; HeightFieldVertex *A, *B, *C, *D; /* (y is up) A--------B-...x | /| | / | | / | | / | | / | | / | | / | |/ | C--------D . . . z */ // keep only triangle that does intersect geom const unsigned int maxX_local = maxX - minX; const unsigned int maxZ_local = maxZ - minZ; for ( x_local = 0; x_local < maxX_local; x_local++) { HeightFieldVertex *HeightFieldRow = tempHeightBuffer[x_local]; HeightFieldVertex *HeightFieldNextRow = tempHeightBuffer[x_local + 1]; // First A C = &HeightFieldRow [0]; // First B D = &HeightFieldNextRow[0]; for ( z_local = 0; z_local < maxZ_local; z_local++) { A = C; B = D; C = &HeightFieldRow [z_local + 1]; D = &HeightFieldNextRow[z_local + 1]; const dReal AHeight = A->vertex[1]; const dReal BHeight = B->vertex[1]; const dReal CHeight = C->vertex[1]; const dReal DHeight = D->vertex[1]; const bool isACollide = AHeight > minO2Height; const bool isBCollide = BHeight > minO2Height; const bool isCCollide = CHeight > minO2Height; const bool isDCollide = DHeight > minO2Height; A->state = !(isACollide); B->state = !(isBCollide); C->state = !(isCCollide); D->state = !(isDCollide); if (isACollide || isBCollide || isCCollide) { HeightFieldTriangle * const CurrTriUp = &tempTriangleBuffer[numTri++]; CurrTriUp->state = false; // changing point order here implies to change it in isOnHeightField CurrTriUp->vertices[0] = A; CurrTriUp->vertices[1] = B; CurrTriUp->vertices[2] = C; if (isContactNumPointsLimited) CurrTriUp->setMinMax(); CurrTriUp->isUp = true; } if (isBCollide || isCCollide || isDCollide) { HeightFieldTriangle * const CurrTriDown = &tempTriangleBuffer[numTri++]; CurrTriDown->state = false; // changing point order here implies to change it in isOnHeightField CurrTriDown->vertices[0] = D; CurrTriDown->vertices[1] = B; CurrTriDown->vertices[2] = C; if (isContactNumPointsLimited) CurrTriDown->setMinMax(); CurrTriDown->isUp = false; } if (needFurtherPasses && (isBCollide || isCCollide) && (AHeight > CHeight && AHeight > BHeight && DHeight > CHeight && DHeight > BHeight)) { // That means Edge BC is concave, therefore // BC Edge and B and C vertices cannot collide B->state = true; C->state = true; } // should find a way to check other edges (AB, BD, CD) too for concavity } } // at least on triangle should intersect geom dIASSERT (numTri != 0); // pass1: VS triangle as Planes // Group Triangle by same plane definition // as Terrain often has many triangles using same plane definition // then collide against that list of triangles. { dVector3 Edge1, Edge2; //compute all triangles normals. for (unsigned int k = 0; k < numTri; k++) { HeightFieldTriangle * const itTriangle = &tempTriangleBuffer[k]; // define 2 edges and a point that will define collision plane dVector3Subtract(itTriangle->vertices[2]->vertex, itTriangle->vertices[0]->vertex, Edge1); dVector3Subtract(itTriangle->vertices[1]->vertex, itTriangle->vertices[0]->vertex, Edge2); // find a perpendicular vector to the triangle if (itTriangle->isUp) dVector3Cross(Edge1, Edge2, triplane); else dVector3Cross(Edge2, Edge1, triplane); // Define Plane // Normalize plane normal const dReal dinvlength = REAL(1.0) / dVector3Length(triplane); triplane[0] *= dinvlength; triplane[1] *= dinvlength; triplane[2] *= dinvlength; // get distance to origin from plane triplane[3] = dVector3Dot(triplane, itTriangle->vertices[0]->vertex); // saves normal for collision check (planes, triangles, vertices and edges.) dVector3Copy(triplane, itTriangle->planeDef); // saves distance for collision check (planes, triangles, vertices and edges.) itTriangle->planeDef[3] = triplane[3]; } // group by Triangles by Planes sharing shame plane definition if (tempPlaneBufferSize < numTri) { resetPlaneBuffer(); allocatePlaneBuffer(numTri); } unsigned int numPlanes = 0; for (unsigned int k = 0; k < numTri; k++) { HeightFieldTriangle * const tri_base = &tempTriangleBuffer[k]; if (tri_base->state == true) continue;// already tested or added to plane list. HeightFieldPlane * const currPlane = tempPlaneBuffer[numPlanes]; currPlane->resetTriangleListSize(numTri - k); currPlane->addTriangle(tri_base); // saves normal for collision check (planes, triangles, vertices and edges.) dVector3Copy(tri_base->planeDef, currPlane->planeDef); // saves distance for collision check (planes, triangles, vertices and edges.) currPlane->planeDef[3]= tri_base->planeDef[3]; const dReal normx = tri_base->planeDef[0]; const dReal normy = tri_base->planeDef[1]; const dReal normz = tri_base->planeDef[2]; const dReal dist = tri_base->planeDef[3]; for (unsigned int m = k + 1; m < numTri; m++) { HeightFieldTriangle * const tri_test = &tempTriangleBuffer[m]; if (tri_test->state == true) continue;// already tested or added to plane list. // normals and distance are the same. if ( dFabs(normy - tri_test->planeDef[1]) < dEpsilon && dFabs(dist - tri_test->planeDef[3]) < dEpsilon && dFabs(normx - tri_test->planeDef[0]) < dEpsilon && dFabs(normz - tri_test->planeDef[2]) < dEpsilon ) { currPlane->addTriangle (tri_test); tri_test->state = true; } } tri_base->state = true; if (isContactNumPointsLimited) currPlane->setMinMax(); numPlanes++; } // sort planes if (isContactNumPointsLimited) sortPlanes(numPlanes); #if !defined(NO_CONTACT_CULLING_BY_ISONHEIGHTFIELD2) /* Note by Oleh_Derevenko: It seems to be incorrect to limit contact count by some particular value since some of them (and even all of them) may be culled in following condition. However I do not see an easy way to fix this. If not that culling the flags modification should be changed here and additionally repeated after some contacts have been generated (in "if (didCollide)"). The maximum of contacts in flags would then be set to minimum of contacts remaining and HEIGHTFIELDMAXCONTACTPERCELL. */ int planeTestFlags = (flags & ~NUMC_MASK) | HEIGHTFIELDMAXCONTACTPERCELL; dIASSERT((HEIGHTFIELDMAXCONTACTPERCELL & ~NUMC_MASK) == 0); #else // if defined(NO_CONTACT_CULLING_BY_ISONHEIGHTFIELD2) int numMaxContactsPerPlane = dMIN(numMaxContactsPossible - numTerrainContacts, HEIGHTFIELDMAXCONTACTPERCELL); int planeTestFlags = (flags & ~NUMC_MASK) | numMaxContactsPerPlane; dIASSERT((HEIGHTFIELDMAXCONTACTPERCELL & ~NUMC_MASK) == 0); #endif for (unsigned int k = 0; k < numPlanes; k++) { HeightFieldPlane * const itPlane = tempPlaneBuffer[k]; //set Geom dGeomPlaneSetNoNormalize (sliding_plane, itPlane->planeDef); //dGeomPlaneSetParams (sliding_plane, triangle_Plane[0], triangle_Plane[1], triangle_Plane[2], triangle_Plane[3]); // find collision and compute contact points bool didCollide = false; const int numPlaneContacts = geomNPlaneCollider (o2, sliding_plane, planeTestFlags, PlaneContact, sizeof(dContactGeom)); const sizeint planeTriListSize = itPlane->trianglelistCurrentSize; for (i = 0; i < numPlaneContacts; i++) { dContactGeom *planeCurrContact = PlaneContact + i; // Check if contact point found in plane is inside Triangle. const dVector3 &pCPos = planeCurrContact->pos; for (sizeint b = 0; planeTriListSize > b; b++) { if (m_p_data->IsOnHeightfield2 (itPlane->trianglelist[b]->vertices[0], pCPos, itPlane->trianglelist[b]->isUp)) { pContact = CONTACT(contact, numTerrainContacts*skip); dVector3Copy(pCPos, pContact->pos); dOPESIGN(pContact->normal, =, -, itPlane->planeDef); pContact->depth = planeCurrContact->depth; pContact->side1 = planeCurrContact->side1; pContact->side2 = planeCurrContact->side2; numTerrainContacts++; if ( numTerrainContacts == numMaxContactsPossible ) return numTerrainContacts; didCollide = true; break; } } } if (didCollide) { #if defined(NO_CONTACT_CULLING_BY_ISONHEIGHTFIELD2) /* Note by Oleh_Derevenko: This code is not used - see another note above */ numMaxContactsPerPlane = dMIN(numMaxContactsPossible - numTerrainContacts, HEIGHTFIELDMAXCONTACTPERCELL); planeTestFlags = (flags & ~NUMC_MASK) | numMaxContactsPerPlane; dIASSERT((HEIGHTFIELDMAXCONTACTPERCELL & ~NUMC_MASK) == 0); #endif for (sizeint b = 0; planeTriListSize > b; b++) { // flag Triangles Vertices as collided // to prevent any collision test of those for (i = 0; i < 3; i++) itPlane->trianglelist[b]->vertices[i]->state = true; } } else { // flag triangle as not collided so that Vertices or Edge // of that triangles will be checked. for (sizeint b = 0; planeTriListSize > b; b++) { itPlane->trianglelist[b]->state = false; } } } } // pass2: VS triangle vertices if (needFurtherPasses) { dxRay tempRay(0, 1); dReal depth; bool vertexCollided; // Only one contact is necessary for ray test int rayTestFlags = (flags & ~NUMC_MASK) | 1; dIASSERT((1 & ~NUMC_MASK) == 0); // // Find Contact Penetration Depth of each vertices // for (unsigned int k = 0; k < numTri; k++) { const HeightFieldTriangle * const itTriangle = &tempTriangleBuffer[k]; if (itTriangle->state == true) continue;// plane triangle did already collide. for (sizeint i = 0; i < 3; i++) { HeightFieldVertex *vertex = itTriangle->vertices[i]; if (vertex->state == true) continue;// vertice did already collide. vertexCollided = false; const dVector3 &triVertex = vertex->vertex; if ( geomNDepthGetter ) { depth = geomNDepthGetter( o2, triVertex[0], triVertex[1], triVertex[2] ); if (depth > dEpsilon) vertexCollided = true; } else { // We don't have a GetDepth function, so do a ray cast instead. // NOTE: This isn't ideal, and a GetDepth function should be // written for all geom classes. tempRay.length = (minO2Height - triVertex[1]) * REAL(1000.0); //dGeomRaySet( &tempRay, pContact->pos[0], pContact->pos[1], pContact->pos[2], // - itTriangle->Normal[0], - itTriangle->Normal[1], - itTriangle->Normal[2] ); dGeomRaySetNoNormalize(tempRay, triVertex, itTriangle->planeDef); if ( geomRayNCollider( &tempRay, o2, rayTestFlags, PlaneContact, sizeof( dContactGeom ) ) ) { depth = PlaneContact[0].depth; vertexCollided = true; } } if (vertexCollided) { pContact = CONTACT(contact, numTerrainContacts*skip); //create contact using vertices dVector3Copy (triVertex, pContact->pos); //create contact using Plane Normal dOPESIGN(pContact->normal, =, -, itTriangle->planeDef); pContact->depth = depth; pContact->side1 = -1; pContact->side2 = -1; numTerrainContacts++; if ( numTerrainContacts == numMaxContactsPossible ) return numTerrainContacts; vertex->state = true; } } } } #ifdef _HEIGHTFIELDEDGECOLLIDING // pass3: VS triangle Edges if (needFurtherPasses) { dVector3 Edge; dxRay edgeRay(0, 1); int numMaxContactsPerTri = dMIN(numMaxContactsPossible - numTerrainContacts, HEIGHTFIELDMAXCONTACTPERCELL); int triTestFlags = (flags & ~NUMC_MASK) | numMaxContactsPerTri; dIASSERT((HEIGHTFIELDMAXCONTACTPERCELL & ~NUMC_MASK) == 0); for (unsigned int k = 0; k < numTri; k++) { const HeightFieldTriangle * const itTriangle = &tempTriangleBuffer[k]; if (itTriangle->state == true) continue;// plane did already collide. for (sizeint m = 0; m < 3; m++) { const sizeint next = (m + 1) % 3; HeightFieldVertex *vertex0 = itTriangle->vertices[m]; HeightFieldVertex *vertex1 = itTriangle->vertices[next]; // not concave or under the AABB // nor triangle already collided against vertices if (vertex0->state == true && vertex1->state == true) continue;// plane did already collide. dVector3Subtract(vertex1->vertex, vertex0->vertex, Edge); edgeRay.length = dVector3Length (Edge); dGeomRaySetNoNormalize(edgeRay, vertex1->vertex, Edge); int prevTerrainContacts = numTerrainContacts; pContact = CONTACT(contact, prevTerrainContacts*skip); const int numCollision = geomRayNCollider(&edgeRay,o2,triTestFlags,pContact,skip); dIASSERT(numCollision <= numMaxContactsPerTri); if (numCollision) { numTerrainContacts += numCollision; do { pContact = CONTACT(contact, prevTerrainContacts*skip); //create contact using Plane Normal dOPESIGN(pContact->normal, =, -, itTriangle->planeDef); pContact->depth = DistancePointToLine(pContact->pos, vertex1->vertex, Edge, edgeRay.length); } while (++prevTerrainContacts != numTerrainContacts); if ( numTerrainContacts == numMaxContactsPossible ) return numTerrainContacts; numMaxContactsPerTri = dMIN(numMaxContactsPossible - numTerrainContacts, HEIGHTFIELDMAXCONTACTPERCELL); triTestFlags = (flags & ~NUMC_MASK) | numMaxContactsPerTri; dIASSERT((HEIGHTFIELDMAXCONTACTPERCELL & ~NUMC_MASK) == 0); } } itTriangle->vertices[0]->state = true; itTriangle->vertices[1]->state = true; itTriangle->vertices[2]->state = true; } } #endif // _HEIGHTFIELDEDGECOLLIDING return numTerrainContacts; } int dCollideHeightfield( dxGeom *o1, dxGeom *o2, int flags, dContactGeom* contact, int skip ) { dIASSERT( skip >= (int)sizeof(dContactGeom) ); dIASSERT( o1->type == dHeightfieldClass ); dIASSERT((flags & NUMC_MASK) >= 1); int i; // if ((flags & NUMC_MASK) == 0) -- An assertion check is made on entry // { flags = (flags & ~NUMC_MASK) | 1; dIASSERT((1 & ~NUMC_MASK) == 0); } int numMaxTerrainContacts = (flags & NUMC_MASK); dxHeightfield *terrain = (dxHeightfield*) o1; dVector3 posbak; dMatrix3 Rbak; dReal aabbbak[6]; int gflagsbak; dVector3 pos0,pos1; dMatrix3 R1; int numTerrainContacts = 0; int numTerrainOrigContacts = 0; //@@ Should find a way to set reComputeAABB to false in default case // aka DHEIGHTFIELD_CORNER_ORIGIN not defined and terrain not PLACEABLE // so that we can free some memory and speed up things a bit // while saving some precision loss #ifndef DHEIGHTFIELD_CORNER_ORIGIN const bool reComputeAABB = true; #else const bool reComputeAABB = ( terrain->gflags & GEOM_PLACEABLE ) ? true : false; #endif //DHEIGHTFIELD_CORNER_ORIGIN // // Transform O2 into Heightfield Space // if (reComputeAABB) { // Backup original o2 position, rotation and AABB. dVector3Copy( o2->final_posr->pos, posbak ); dMatrix3Copy( o2->final_posr->R, Rbak ); memcpy( aabbbak, o2->aabb, sizeof( dReal ) * 6 ); gflagsbak = o2->gflags; } if ( terrain->gflags & GEOM_PLACEABLE ) { // Transform o2 into heightfield space. dSubtractVectors3( pos0, o2->final_posr->pos, terrain->final_posr->pos ); dMultiply1_331( pos1, terrain->final_posr->R, pos0 ); dMultiply1_333( R1, terrain->final_posr->R, o2->final_posr->R ); // Update o2 with transformed position and rotation. dVector3Copy( pos1, o2->final_posr->pos ); dMatrix3Copy( R1, o2->final_posr->R ); } #ifndef DHEIGHTFIELD_CORNER_ORIGIN o2->final_posr->pos[ 0 ] += terrain->m_p_data->m_fHalfWidth; o2->final_posr->pos[ 2 ] += terrain->m_p_data->m_fHalfDepth; #endif // DHEIGHTFIELD_CORNER_ORIGIN // Rebuild AABB for O2 if (reComputeAABB) o2->computeAABB(); // // Collide // //check if inside boundaries // using O2 aabb // aabb[6] is (minx, maxx, miny, maxy, minz, maxz) const bool wrapped = terrain->m_p_data->m_bWrapMode != 0; if ( !wrapped ) { if ( o2->aabb[0] > terrain->m_p_data->m_fWidth //MinX || o2->aabb[4] > terrain->m_p_data->m_fDepth)//MinZ goto dCollideHeightfieldExit; if ( o2->aabb[1] < 0 //MaxX || o2->aabb[5] < 0)//MaxZ goto dCollideHeightfieldExit; } { // To narrow scope of following variables const dReal fInvSampleWidth = terrain->m_p_data->m_fInvSampleWidth; int nMinX = (int)dFloor(dNextAfter(o2->aabb[0] * fInvSampleWidth, -dInfinity)); int nMaxX = (int)dCeil(dNextAfter(o2->aabb[1] * fInvSampleWidth, dInfinity)); const dReal fInvSampleDepth = terrain->m_p_data->m_fInvSampleDepth; int nMinZ = (int)dFloor(dNextAfter(o2->aabb[4] * fInvSampleDepth, -dInfinity)); int nMaxZ = (int)dCeil(dNextAfter(o2->aabb[5] * fInvSampleDepth, dInfinity)); if ( !wrapped ) { nMinX = dMAX( nMinX, 0 ); nMaxX = dMIN( nMaxX, terrain->m_p_data->m_nWidthSamples - 1 ); nMinZ = dMAX( nMinZ, 0 ); nMaxZ = dMIN( nMaxZ, terrain->m_p_data->m_nDepthSamples - 1 ); dIASSERT ((nMinX < nMaxX) && (nMinZ < nMaxZ)); } numTerrainOrigContacts = numTerrainContacts; numTerrainContacts += terrain->dCollideHeightfieldZone( nMinX,nMaxX,nMinZ,nMaxZ,o2,numMaxTerrainContacts - numTerrainContacts, flags,CONTACT(contact,numTerrainContacts*skip),skip ); dIASSERT( numTerrainContacts <= numMaxTerrainContacts ); } dContactGeom *pContact; for ( i = numTerrainOrigContacts; i != numTerrainContacts; ++i ) { pContact = CONTACT(contact,i*skip); pContact->g1 = o1; pContact->g2 = o2; // pContact->side1 = -1; -- Oleh_Derevenko: sides must not be erased here as they are set by respective colliders during ray/plane tests // pContact->side2 = -1; } //------------------------------------------------------------------------------ dCollideHeightfieldExit: if (reComputeAABB) { // Restore o2 position, rotation and AABB dVector3Copy( posbak, o2->final_posr->pos ); dMatrix3Copy( Rbak, o2->final_posr->R ); memcpy( o2->aabb, aabbbak, sizeof(dReal)*6 ); o2->gflags = gflagsbak; // // Transform Contacts to World Space // if ( terrain->gflags & GEOM_PLACEABLE ) { for ( i = 0; i < numTerrainContacts; ++i ) { pContact = CONTACT(contact,i*skip); dCopyVector3( pos0, pContact->pos ); #ifndef DHEIGHTFIELD_CORNER_ORIGIN pos0[ 0 ] -= terrain->m_p_data->m_fHalfWidth; pos0[ 2 ] -= terrain->m_p_data->m_fHalfDepth; #endif // !DHEIGHTFIELD_CORNER_ORIGIN dMultiply0_331( pContact->pos, terrain->final_posr->R, pos0 ); dAddVectors3( pContact->pos, pContact->pos, terrain->final_posr->pos ); dCopyVector3( pos0, pContact->normal ); dMultiply0_331( pContact->normal, terrain->final_posr->R, pos0 ); } } #ifndef DHEIGHTFIELD_CORNER_ORIGIN else { for ( i = 0; i < numTerrainContacts; ++i ) { pContact = CONTACT(contact,i*skip); pContact->pos[ 0 ] -= terrain->m_p_data->m_fHalfWidth; pContact->pos[ 2 ] -= terrain->m_p_data->m_fHalfDepth; } } #endif // !DHEIGHTFIELD_CORNER_ORIGIN } // Return contact count. return numTerrainContacts; } ode-0.16/ode/src/collision_trimesh_gimpact.cpp0000664000175200017520000003207013403272463016440 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ // TriMesh storage classes refactoring and face angle computation code by Oleh Derevenko (C) 2016-2017 #include #include #include "config.h" #include "matrix.h" #include "odemath.h" #include "util.h" #if dTRIMESH_ENABLED && dTRIMESH_GIMPACT #include "collision_util.h" #include "collision_trimesh_gimpact.h" #include "collision_trimesh_internal_impl.h" ////////////////////////////////////////////////////////////////////////// // dxTriMeshData bool dxTriMeshData::preprocessData(bool /*buildUseFlags*//*=false*/, FaceAngleStorageMethod faceAndgesRequirement/*=ASM__INVALID*/) { FaceAngleStorageMethod faceAndgesRequirementToUse = faceAndgesRequirement; if (faceAndgesRequirement != ASM__INVALID && haveFaceAnglesBeenBuilt()) { dUASSERT(false, "Another request to build face angles after they had already been built"); faceAndgesRequirementToUse = ASM__INVALID; } // If this mesh has already been preprocessed, exit bool result = faceAndgesRequirementToUse == ASM__INVALID || retrieveTriangleCount() == 0 || meaningfulPreprocessData(faceAndgesRequirementToUse); return result; } struct TrimeshDataVertexIndexAccessor_GIMPACT { enum { TRIANGLEINDEX_STRIDE = dxTriMesh::TRIANGLEINDEX_STRIDE, }; explicit TrimeshDataVertexIndexAccessor_GIMPACT(dxTriMeshData *meshData): m_TriangleVertexIndices(meshData->retrieveTriangleVertexIndices()) { dIASSERT(meshData->retrieveTriangleStride() == TRIANGLEINDEX_STRIDE); } void getTriangleVertexIndices(unsigned out_VertexIndices[dMTV__MAX], unsigned triangleIdx) const { const GUINT32 *triIndicesBegin = m_TriangleVertexIndices; const unsigned triStride = TRIANGLEINDEX_STRIDE; const GUINT32 *triIndicesOfInterest = (const GUINT32 *)((const uint8 *)triIndicesBegin + (sizeint)triangleIdx * triStride); std::copy(triIndicesOfInterest, triIndicesOfInterest + dMTV__MAX, out_VertexIndices); } const GUINT32 *m_TriangleVertexIndices; }; struct TrimeshDataTrianglePointAccessor_GIMPACT { enum { VERTEXINSTANCE_STRIDE = dxTriMesh::VERTEXINSTANCE_STRIDE, TRIANGLEINDEX_STRIDE = dxTriMesh::TRIANGLEINDEX_STRIDE, }; TrimeshDataTrianglePointAccessor_GIMPACT(dxTriMeshData *meshData): m_VertexInstances(meshData->retrieveVertexInstances()), m_TriangleVertexIndices(meshData->retrieveTriangleVertexIndices()) { dIASSERT((unsigned)meshData->retrieveVertexStride() == (unsigned)VERTEXINSTANCE_STRIDE); dIASSERT((unsigned)meshData->retrieveTriangleStride() == (unsigned)TRIANGLEINDEX_STRIDE); } void getTriangleVertexPoints(dVector3 out_Points[dMTV__MAX], unsigned triangleIndex) const { dxTriMeshData::retrieveTriangleVertexPoints(out_Points, triangleIndex, &m_VertexInstances[0][0], VERTEXINSTANCE_STRIDE, m_TriangleVertexIndices, TRIANGLEINDEX_STRIDE); } const vec3f *m_VertexInstances; const GUINT32 *m_TriangleVertexIndices; }; bool dxTriMeshData::meaningfulPreprocessData(FaceAngleStorageMethod faceAndgesRequirement/*=ASM__INVALID*/) { const bool buildFaceAngles = true; dIASSERT(faceAndgesRequirement != ASM__INVALID); // dIASSERT(buildFaceAngles); dIASSERT(/*!buildFaceAngles || */!haveFaceAnglesBeenBuilt()); bool result = false; bool anglesAllocated = false; do { if (buildFaceAngles) { if (!allocateFaceAngles(faceAndgesRequirement)) { break; } } anglesAllocated = true; const unsigned int numTris = retrieveTriangleCount(); const unsigned int numVertices = retrieveVertexCount(); sizeint numEdges = (sizeint)numTris * dMTV__MAX; dIASSERT(numVertices <= numEdges); // Edge records are going to be used for vertex data as well const sizeint recordsMemoryRequired = dEFFICIENT_SIZE(numEdges * sizeof(EdgeRecord)); const sizeint verticesMemoryRequired = /*dEFFICIENT_SIZE*/(numVertices * sizeof(VertexRecord)); // Skip alignment for the last chunk const sizeint totalTempMemoryRequired = recordsMemoryRequired + verticesMemoryRequired; void *tempBuffer = dAlloc(totalTempMemoryRequired); if (tempBuffer == NULL) { break; } EdgeRecord *edges = (EdgeRecord *)tempBuffer; VertexRecord *vertices = (VertexRecord *)((uint8 *)tempBuffer + recordsMemoryRequired); TrimeshDataVertexIndexAccessor_GIMPACT indexAccessor(this); meaningfulPreprocess_SetupEdgeRecords(edges, numEdges, indexAccessor); // Sort the edges, so the ones sharing the same verts are beside each other std::sort(edges, edges + numEdges); TrimeshDataTrianglePointAccessor_GIMPACT pointAccessor(this); const dReal *const externalNormals = retrieveNormals(); IFaceAngleStorageControl *faceAngles = retrieveFaceAngles(); meaningfulPreprocess_buildEdgeFlags(NULL, faceAngles, edges, numEdges, vertices, externalNormals, pointAccessor); dFree(tempBuffer, totalTempMemoryRequired); result = true; } while (false); if (!result) { if (anglesAllocated) { if (buildFaceAngles) { freeFaceAngles(); } } } return result; } ////////////////////////////////////////////////////////////////////////// // Trimesh dxTriMesh::~dxTriMesh() { //Terminate Trimesh gim_trimesh_destroy(&m_collision_trimesh); gim_terminate_buffer_managers(m_buffer_managers); } /*virtual */ void dxTriMesh::computeAABB() { //update trimesh transform mat4f transform; IDENTIFY_MATRIX_4X4(transform); MakeMatrix(this, transform); gim_trimesh_set_tranform(&m_collision_trimesh, transform); //Update trimesh boxes gim_trimesh_update(&m_collision_trimesh); GIM_AABB_COPY( &m_collision_trimesh.m_aabbset.m_global_bound, aabb ); } void dxTriMesh::assignMeshData(dxTriMeshData *Data) { // GIMPACT only supports stride 12, so we need to catch the error early. dUASSERT( (unsigned int)Data->retrieveVertexStride() == (unsigned)VERTEXINSTANCE_STRIDE && (unsigned int)Data->retrieveTriangleStride() == (unsigned)TRIANGLEINDEX_STRIDE, "Gimpact trimesh only supports a stride of 3 float/int\n" "This means that you cannot use dGeomTriMeshDataBuildSimple() with Gimpact.\n" "Change the stride, or use Opcode trimeshes instead.\n" ); dxTriMesh_Parent::assignMeshData(Data); //Create trimesh const vec3f *vertexInstances = Data->retrieveVertexInstances(); if ( vertexInstances != NULL ) { const GUINT32 *triangleVertexIndices = Data->retrieveTriangleVertexIndices(); sizeint vertexInstanceCount = Data->retrieveVertexCount(); sizeint triangleVertexCount = (sizeint)Data->retrieveTriangleCount() * dMTV__MAX; gim_trimesh_create_from_data( m_buffer_managers, &m_collision_trimesh, // gimpact mesh const_cast(vertexInstances), // vertices dCAST_TO_SMALLER(GUINT32, vertexInstanceCount), // nr of verts 0, // copy verts? const_cast(triangleVertexIndices), // indices dCAST_TO_SMALLER(GUINT32, triangleVertexCount), // nr of indices 0, // copy indices? 1 // transformed reply ); } } ////////////////////////////////////////////////////////////////////////// /*extern */ dTriMeshDataID dGeomTriMeshDataCreate() { return new dxTriMeshData(); } /*extern */ void dGeomTriMeshDataDestroy(dTriMeshDataID g) { dxTriMeshData *data = g; delete data; } /*extern */ void dGeomTriMeshDataSet(dTriMeshDataID g, int dataId, void *pDataLocation) { dUASSERT(g, "The argument is not a trimesh data"); dxTriMeshData *data = g; switch (dataId) { case dTRIMESHDATA_FACE_NORMALS: { data->assignNormals((const dReal *)pDataLocation); break; } case dTRIMESHDATA_USE_FLAGS: // Not used for GIMPACT { break; } // case dTRIMESHDATA__MAX: -- To be located by Find in Files default: { dUASSERT(dataId, "invalid data type"); break; } } } static void *geomTriMeshDataGet(dTriMeshDataID g, int dataId, sizeint *pOutDataSize) ; /*extern */ void *dGeomTriMeshDataGet(dTriMeshDataID g, int dataId) { return geomTriMeshDataGet(g, dataId, NULL); } /*extern */ void *dGeomTriMeshDataGet2(dTriMeshDataID g, int dataId, sizeint *pOutDataSize) { return geomTriMeshDataGet(g, dataId, pOutDataSize); } static void *geomTriMeshDataGet(dTriMeshDataID g, int dataId, sizeint *pOutDataSize) { dUASSERT(g, "The argument is not a trimesh data"); const dxTriMeshData *data = g; void *result = NULL; switch (dataId) { case dTRIMESHDATA_FACE_NORMALS: { if (pOutDataSize != NULL) { *pOutDataSize = data->calculateNormalsMemoryRequirement(); } result = (void *)data->retrieveNormals(); break; } case dTRIMESHDATA_USE_FLAGS: // Not not used for GIMPACT { if (pOutDataSize != NULL) { *pOutDataSize = 0; } break; } // case dTRIMESHDATA__MAX: -- To be located by Find in Files default: { if (pOutDataSize != NULL) { *pOutDataSize = 0; } dUASSERT(dataId, "invalid data type"); break; } } return result; } /*extern */ void dGeomTriMeshDataBuildSingle1(dTriMeshDataID g, const void* Vertices, int VertexStride, int VertexCount, const void* Indices, int IndexCount, int TriStride, const void* Normals) { dUASSERT(g, "The argument is not a trimesh data"); dAASSERT(Vertices); dAASSERT(Indices); dxTriMeshData *data = g; data->buildData(Vertices, VertexStride, VertexCount, Indices, IndexCount, TriStride, Normals, true); } /*extern */ void dGeomTriMeshDataBuildDouble1(dTriMeshDataID g, const void* Vertices, int VertexStride, int VertexCount, const void* Indices, int IndexCount, int TriStride, const void* Normals) { dUASSERT(g, "The argument is not a trimesh data"); dAASSERT(Vertices); dAASSERT(Indices); dxTriMeshData *data = g; data->buildData(Vertices, VertexStride, VertexCount, Indices, IndexCount, TriStride, Normals, false); } ////////////////////////////////////////////////////////////////////////// /*extern */ dGeomID dCreateTriMesh(dSpaceID space, dTriMeshDataID Data, dTriCallback* Callback, dTriArrayCallback* ArrayCallback, dTriRayCallback* RayCallback) { dxTriMesh *mesh = new dxTriMesh(space, Data, Callback, ArrayCallback, RayCallback); return mesh; } /*extern */ void dGeomTriMeshSetLastTransform(dGeomID g, const dMatrix4 last_trans ) { dAASSERT(g); dUASSERT(g->type == dTriMeshClass, "The geom is not a trimesh"); //stub } /*extern */ const dReal *dGeomTriMeshGetLastTransform(dGeomID g) { dAASSERT(g); dUASSERT(g->type == dTriMeshClass, "The geom is not a trimesh"); return NULL; // stub } #endif // #if dTRIMESH_ENABLED && dTRIMESH_GIMPACT ode-0.16/ode/src/nextafterf.c0000664000175200017520000000755113403272463013022 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* _nextafterf() implementation for MSVC */ #include #include "config.h" #if defined(_ODE__NEXTAFTERF_REQUIRED) /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* A union which permits us to convert between a float and a 32 bit int. */ typedef union { float value; uint32 word; } ieee_float_shape_type; /* Get a 32 bit int from a float. */ #define GET_FLOAT_WORD(i,d) \ do { \ volatile ieee_float_shape_type gf_u; \ gf_u.value = (d); \ (i) = gf_u.word; \ } while (0) /* Set a float from a 32 bit int. */ #define SET_FLOAT_WORD(d,i) \ do { \ volatile ieee_float_shape_type sf_u; \ sf_u.word = (i); \ (d) = sf_u.value; \ } while (0) #undef nextafterf float _nextafterf(float x, float y) { int32 hx,hy,ix,iy; GET_FLOAT_WORD(hx,x); GET_FLOAT_WORD(hy,y); ix = hx&0x7fffffff; /* |x| */ iy = hy&0x7fffffff; /* |y| */ if((ix>0x7f800000) || /* x is nan */ (iy>0x7f800000)) /* y is nan */ return x+y; if(x==y) return x; /* x=y, return x */ if(ix==0) { /* x == 0 */ SET_FLOAT_WORD(x,(hy&0x80000000)|1);/* return +-minsubnormal */ y = x*x; if(y==x) return y; else return x; /* raise underflow flag */ } if(hx>=0) { /* x > 0 */ if(hx>hy) { /* x > y, x -= ulp */ hx -= 1; } else { /* x < y, x += ulp */ hx += 1; } } else { /* x < 0 */ if(hy>=0||hx>hy){ /* x < y, x -= ulp */ hx -= 1; } else { /* x > y, x += ulp */ hx += 1; } } hy = hx&0x7f800000; if(hy>=0x7f800000) return x+x; /* overflow */ if(hy<0x00800000) { /* underflow */ y = x*x; if(y!=x) { /* raise underflow flag */ SET_FLOAT_WORD(y,hx); return y; } } SET_FLOAT_WORD(x,hx); return x; } #endif /* #if defined(_ODE__NEXTAFTERF_REQUIRED) */ ode-0.16/ode/src/threading_base.h0000664000175200017520000002716013403272463013616 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * Threading base wrapper class header file. * * Copyright (C) 2011-2012 Oleh Derevenko. All rights reserved. * * e-mail: odar@eleks.com (change all "a" to "e") * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* * Threading base class to be used for inheritance by dxWorld, dxSpace and others * to take advantage of threaded execution. */ #ifndef _ODE_THREADING_BASE_H_ #define _ODE_THREADING_BASE_H_ #include "common.h" #include struct dxIThreadingDefaultImplProvider { public: virtual const dxThreadingFunctionsInfo *retrieveThreadingDefaultImpl(dThreadingImplementationID &out_defaultImpl) = 0; }; class dxThreadingBase { protected: dxThreadingBase(): m_default_impl_provider(NULL), m_functions_info(NULL), m_threading_impl(NULL), m_stock_call_wait(NULL) { } // This ought to be done via constructor, but passing 'this' in base class initializer emits a warning in MSVC :( void setThreadingDefaultImplProvider(dxIThreadingDefaultImplProvider *default_impl_provider) { m_default_impl_provider = default_impl_provider; dIASSERT(GetStockCallWait() == NULL); } ~dxThreadingBase(); public: void assignThreadingImpl(const dxThreadingFunctionsInfo *functions_info, dThreadingImplementationID threading_impl) { dAASSERT((functions_info == NULL) == (threading_impl == NULL)); // Free the stock call wait first to have it executed before new pointer values are assigned DoFreeStockCallWait(); m_functions_info = functions_info; m_threading_impl = threading_impl; } public: unsigned calculateThreadingLimitedThreadCount(unsigned limitValue, bool countCallerAsExtraThread, unsigned *ptrOut_activeThreadCount=NULL) const { unsigned activeThreadCount = RetrieveThreadingThreadCount(); if (ptrOut_activeThreadCount != NULL) { *ptrOut_activeThreadCount = activeThreadCount; } unsigned adjustedActiveThreads = countCallerAsExtraThread && activeThreadCount != UINT_MAX ? activeThreadCount + 1 : activeThreadCount; return limitValue == dTHREADING_THREAD_COUNT_UNLIMITED ? adjustedActiveThreads : dMACRO_MIN(limitValue, adjustedActiveThreads); } public: dCallWaitID AllocateOrRetrieveStockCallWaitID() { dCallWaitID stock_wait_id = GetStockCallWait(); return stock_wait_id != NULL ? (ResetThreadedCallWait(stock_wait_id), stock_wait_id) : DoAllocateStockCallWait(); } public: dMutexGroupID AllocMutexGroup(dmutexindex_t Mutex_count, const char *const *Mutex_names_ptr/*=NULL*/) const { dThreadingImplementationID impl; const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl); return functions->alloc_mutex_group(impl, Mutex_count, Mutex_names_ptr); } void FreeMutexGroup(dMutexGroupID mutex_group) const { dThreadingImplementationID impl; const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl); functions->free_mutex_group(impl, mutex_group); } void LockMutexGroupMutex(dMutexGroupID mutex_group, dmutexindex_t mutex_index) const { dThreadingImplementationID impl; const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl); functions->lock_group_mutex(impl, mutex_group, mutex_index); } // bool TryLockMutexGroupMutex(dMutexGroupID mutex_group, dmutexindex_t mutex_index) const // { // dThreadingImplementationID impl; // const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl); // return functions->trylock_group_mutex(impl, mutex_group, mutex_index) != 0; // } void UnlockMutexGroupMutex(dMutexGroupID mutex_group, dmutexindex_t mutex_index) const { dThreadingImplementationID impl; const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl); functions->unlock_group_mutex(impl, mutex_group, mutex_index); } dCallWaitID AllocThreadedCallWait() const { dThreadingImplementationID impl; const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl); return functions->alloc_call_wait(impl); } void ResetThreadedCallWait(dCallWaitID call_wait) const { dThreadingImplementationID impl; const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl); functions->reset_call_wait(impl, call_wait); } void FreeThreadedCallWait(dCallWaitID call_wait) const { dThreadingImplementationID impl; const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl); functions->free_call_wait(impl, call_wait); } void PostThreadedCall(int *out_summary_fault/*=NULL*/, dCallReleaseeID *out_post_releasee/*=NULL*/, ddependencycount_t dependencies_count, dCallReleaseeID dependent_releasee/*=NULL*/, dCallWaitID call_wait/*=NULL*/, dThreadedCallFunction *call_func, void *call_context, dcallindex_t instance_index, const char *call_name/*=NULL*/) const { dThreadingImplementationID impl; const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl); functions->post_call(impl, out_summary_fault, out_post_releasee, dependencies_count, dependent_releasee, call_wait, call_func, call_context, instance_index, call_name); } void AlterThreadedCallDependenciesCount(dCallReleaseeID target_releasee, ddependencychange_t dependencies_count_change) const { dThreadingImplementationID impl; const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl); functions->alter_call_dependencies_count(impl, target_releasee, dependencies_count_change); } void WaitThreadedCallExclusively(int *out_wait_status/*=NULL*/, dCallWaitID call_wait, const dThreadedWaitTime *timeout_time_ptr/*=NULL*/, const char *wait_name/*=NULL*/) const { dThreadingImplementationID impl; const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl); functions->wait_call(impl, out_wait_status, call_wait, timeout_time_ptr, wait_name); functions->reset_call_wait(impl, call_wait); } void WaitThreadedCallCollectively(int *out_wait_status/*=NULL*/, dCallWaitID call_wait, const dThreadedWaitTime *timeout_time_ptr/*=NULL*/, const char *wait_name/*=NULL*/) const { dThreadingImplementationID impl; const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl); functions->wait_call(impl, out_wait_status, call_wait, timeout_time_ptr, wait_name); } unsigned RetrieveThreadingThreadCount() const { dThreadingImplementationID impl; const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl); return functions->retrieve_thread_count(impl); } bool PreallocateResourcesForThreadedCalls(unsigned max_simultaneous_calls_estimate) const { dThreadingImplementationID impl; const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl); return functions->preallocate_resources_for_calls(impl, max_simultaneous_calls_estimate) != 0; } public: void PostThreadedCallsGroup(int *out_summary_fault/*=NULL*/, ddependencycount_t member_count, dCallReleaseeID dependent_releasee/*=NULL*/, dThreadedCallFunction *call_func, void *call_context, const char *call_name/*=NULL*/) const; void PostThreadedCallsIndexOverridenGroup(int *out_summary_fault/*=NULL*/, ddependencycount_t member_count, dCallReleaseeID dependent_releasee/*=NULL*/, dThreadedCallFunction *call_func, void *call_context, unsigned index_override, const char *call_name/*=NULL*/) const; void PostThreadedCallForUnawareReleasee(int *out_summary_fault/*=NULL*/, dCallReleaseeID *out_post_releasee/*=NULL*/, ddependencycount_t dependencies_count, dCallReleaseeID dependent_releasee/*=NULL*/, dCallWaitID call_wait/*=NULL*/, dThreadedCallFunction *call_func, void *call_context, dcallindex_t instance_index, const char *call_name/*=NULL*/) const; protected: const dxThreadingFunctionsInfo *FindThreadingImpl(dThreadingImplementationID &out_impl_found) const; private: dCallWaitID DoAllocateStockCallWait(); void DoFreeStockCallWait(); private: const dxThreadingFunctionsInfo *GetFunctionsInfo() const { return m_functions_info; } dThreadingImplementationID GetThreadingImpl() const { return m_threading_impl; } void SetStockCallWait(dCallWaitID value) { m_stock_call_wait = value; } dCallWaitID GetStockCallWait() const { return m_stock_call_wait; } private: dxIThreadingDefaultImplProvider *m_default_impl_provider; const dxThreadingFunctionsInfo *m_functions_info; dThreadingImplementationID m_threading_impl; dCallWaitID m_stock_call_wait; }; class dxMutexGroupLockHelper { public: dxMutexGroupLockHelper(dxThreadingBase *threading_base, dMutexGroupID mutex_group, dmutexindex_t mutex_index): m_threading_base(threading_base), m_mutex_group(mutex_group), m_mutex_index(mutex_index), m_mutex_locked(true) { threading_base->LockMutexGroupMutex(mutex_group, mutex_index); } ~dxMutexGroupLockHelper() { if (m_mutex_locked) { m_threading_base->UnlockMutexGroupMutex(m_mutex_group, m_mutex_index); } } void UnlockMutex() { dIASSERT(m_mutex_locked); m_threading_base->UnlockMutexGroupMutex(m_mutex_group, m_mutex_index); m_mutex_locked = false; } void RelockMutex() { dIASSERT(!m_mutex_locked); m_threading_base->LockMutexGroupMutex(m_mutex_group, m_mutex_index); m_mutex_locked = true; } private: dxThreadingBase *m_threading_base; dMutexGroupID m_mutex_group; dmutexindex_t m_mutex_index; bool m_mutex_locked; }; #endif // #ifndef _ODE_THREADING_BASE_H_ ode-0.16/ode/src/obstack.h0000664000175200017520000000612513403272463012303 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_OBSTACK_H_ #define _ODE_OBSTACK_H_ #include "objects.h" // each obstack Arena pointer points to a block of this many bytes #define dOBSTACK_ARENA_SIZE 16384 struct dObStack : public dBase { dObStack(); ~dObStack(); void *alloc (sizeint num_bytes); // allocate a block in the last arena, allocating a new arena if necessary. // it is a runtime error if num_bytes is larger than the arena size. void freeAll(); // free all blocks in all arenas. this does not deallocate the arenas // themselves, so future alloc()s will reuse them. void *rewind(); // rewind the obstack iterator, and return the address of the first // allocated block. return 0 if there are no allocated blocks. void *next (sizeint num_bytes); // return the address of the next allocated block. 'num_bytes' is the size // of the previous block. this returns null if there are no more arenas. // the sequence of 'num_bytes' parameters passed to next() during a // traversal of the list must exactly match the parameters passed to alloc(). private: struct Arena { Arena *m_next; // next arena in linked list sizeint m_used; // total number of bytes used in this arena, counting }; // this header private: void *switch_to_arena(Arena *next_arena); private: Arena *m_first; // head of the arena linked list. 0 if no arenas yet Arena *m_last; // arena where blocks are currently being allocated // used for iterator Arena *m_current_arena; sizeint m_current_ofs; }; #endif ode-0.16/ode/src/default_threading.h0000664000175200017520000000520013403272463014317 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * Threading base wrapper class header file. * * Copyright (C) 2011-2012 Oleh Derevenko. All rights reserved. * * e-mail: odar@eleks.com (change all "a" to "e") * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* * A default threading instance holder class definition * Copyright (c) 2017 Oleh Derevenko, odar@eleks.com (change all "a" to "e") */ #ifndef _ODE__PRIVATE_DEFAULT_THREADING_H_ #define _ODE__PRIVATE_DEFAULT_THREADING_H_ #include class DefaultThreadingHolder { public: static bool initializeDefaultThreading(); static void finalizeDefaultThreading(); static dThreadingImplementationID getDefaultThreadingImpl() { return m_defaultThreadingImpl; } static const dThreadingFunctionsInfo *getDefaultThreadingFunctions() { return m_defaultThreadingFunctions; } private: static dThreadingImplementationID m_defaultThreadingImpl; static const dThreadingFunctionsInfo *m_defaultThreadingFunctions; }; #endif // #ifndef _ODE__PRIVATE_DEFAULT_THREADING_H_ ode-0.16/ode/src/plane.cpp0000664000175200017520000001114613403272463012306 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* standard ODE geometry primitives: public API and pairwise collision functions. the rule is that only the low level primitive collision functions should set dContactGeom::g1 and dContactGeom::g2. */ #include #include #include #include "config.h" #include "matrix.h" #include "odemath.h" #include "collision_kernel.h" #include "collision_std.h" #include "collision_util.h" #ifdef _MSC_VER #pragma warning(disable:4291) // for VC++, no complaints about "no matching operator delete found" #endif //**************************************************************************** // plane public API static void make_sure_plane_normal_has_unit_length (dxPlane *g) { dReal l = g->p[0]*g->p[0] + g->p[1]*g->p[1] + g->p[2]*g->p[2]; if (l > 0) { l = dRecipSqrt(l); g->p[0] *= l; g->p[1] *= l; g->p[2] *= l; g->p[3] *= l; } else { g->p[0] = 1; g->p[1] = 0; g->p[2] = 0; g->p[3] = 0; } } dxPlane::dxPlane (dSpaceID space, dReal a, dReal b, dReal c, dReal d) : dxGeom (space,0) { type = dPlaneClass; p[0] = a; p[1] = b; p[2] = c; p[3] = d; make_sure_plane_normal_has_unit_length (this); } void dxPlane::computeAABB() { aabb[0] = -dInfinity; aabb[1] = dInfinity; aabb[2] = -dInfinity; aabb[3] = dInfinity; aabb[4] = -dInfinity; aabb[5] = dInfinity; // Planes that have normal vectors aligned along an axis can use a // less comprehensive (half space) bounding box. if ( p[1] == 0.0f && p[2] == 0.0f ) { // normal aligned with x-axis aabb[0] = (p[0] > 0) ? -dInfinity : -p[3]; aabb[1] = (p[0] > 0) ? p[3] : dInfinity; } else if ( p[0] == 0.0f && p[2] == 0.0f ) { // normal aligned with y-axis aabb[2] = (p[1] > 0) ? -dInfinity : -p[3]; aabb[3] = (p[1] > 0) ? p[3] : dInfinity; } else if ( p[0] == 0.0f && p[1] == 0.0f ) { // normal aligned with z-axis aabb[4] = (p[2] > 0) ? -dInfinity : -p[3]; aabb[5] = (p[2] > 0) ? p[3] : dInfinity; } } dGeomID dCreatePlane (dSpaceID space, dReal a, dReal b, dReal c, dReal d) { return new dxPlane (space,a,b,c,d); } void dGeomPlaneSetParams (dGeomID g, dReal a, dReal b, dReal c, dReal d) { dUASSERT (g && g->type == dPlaneClass,"argument not a plane"); dxPlane *p = (dxPlane*) g; p->p[0] = a; p->p[1] = b; p->p[2] = c; p->p[3] = d; make_sure_plane_normal_has_unit_length (p); dGeomMoved (g); } void dGeomPlaneGetParams (dGeomID g, dVector4 result) { dUASSERT (g && g->type == dPlaneClass,"argument not a plane"); dxPlane *p = (dxPlane*) g; result[0] = p->p[0]; result[1] = p->p[1]; result[2] = p->p[2]; result[3] = p->p[3]; } dReal dGeomPlanePointDepth (dGeomID g, dReal x, dReal y, dReal z) { dUASSERT (g && g->type == dPlaneClass,"argument not a plane"); dxPlane *p = (dxPlane*) g; return p->p[3] - p->p[0]*x - p->p[1]*y - p->p[2]*z; } ode-0.16/ode/src/fastvecscale.cpp0000664000175200017520000002066213403272463013655 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* * Vector scaling related code of ThreadedEquationSolverLDLT * Copyright (c) 2017 Oleh Derevenko, odar@eleks.com (change all "a" to "e") */ #include #include #include #include "config.h" #include "threaded_solver_ldlt.h" #include "threading_base.h" #include "resource_control.h" #include "error.h" #include "fastvecscale_impl.h" /*static */ void ThreadedEquationSolverLDLT::estimateCooperativeScalingVectorResourceRequirements( dxResourceRequirementDescriptor *summaryRequirementsDescriptor, unsigned allowedThreadCount, unsigned elementCount) { dxThreadingBase *threading = summaryRequirementsDescriptor->getrelatedThreading(); unsigned limitedThreadCount = restrictScalingVectorAllowedThreadCount(threading, allowedThreadCount, elementCount); if (limitedThreadCount > 1) { doEstimateCooperativeScalingVectorResourceRequirementsValidated(summaryRequirementsDescriptor, allowedThreadCount, elementCount); } } /*static */ void ThreadedEquationSolverLDLT::cooperativelyScaleVector(dxRequiredResourceContainer *resourceContainer, unsigned allowedThreadCount, dReal *vectorData, const dReal *scaleData, unsigned elementCount) { dAASSERT(elementCount != 0); dxThreadingBase *threading = resourceContainer->getThreadingInstance(); unsigned limitedThreadCount = restrictScalingVectorAllowedThreadCount(threading, allowedThreadCount, elementCount); if (limitedThreadCount <= 1) { scaleLargeVector(vectorData, scaleData, elementCount); } else { doCooperativelyScaleVectorValidated(resourceContainer, limitedThreadCount, vectorData, scaleData, elementCount); } } /*static */ unsigned ThreadedEquationSolverLDLT::restrictScalingVectorAllowedThreadCount( dxThreadingBase *threading, unsigned allowedThreadCount, unsigned elementCount) { unsigned limitedThreadCount = 1; #if dCOOPERATIVE_ENABLED const unsigned int blockStep = SV_BLOCK_SIZE; // Required by the implementation unsigned scalingBlockCount = deriveScalingVectorBlockCount(elementCount, blockStep); dIASSERT(deriveScalingVectorThreadCount(SV_COOPERATIVE_BLOCK_COUNT_MINIMUM - 1, 2) > 1); if (scalingBlockCount >= SV_COOPERATIVE_BLOCK_COUNT_MINIMUM) { limitedThreadCount = threading->calculateThreadingLimitedThreadCount(allowedThreadCount, true); } #endif // #if dCOOPERATIVE_ENABLED return limitedThreadCount; } /*static */ void ThreadedEquationSolverLDLT::doEstimateCooperativeScalingVectorResourceRequirementsValidated( dxResourceRequirementDescriptor *summaryRequirementsDescriptor, unsigned allowedThreadCount, unsigned elementCount) { unsigned simultaneousCallCount = 1 + (allowedThreadCount - 1); sizeint scalingMemoryRequired = 0; const unsigned scalingAlignmentRequired = 0; unsigned featureRequirement = dxResourceRequirementDescriptor::STOCK_CALLWAIT_REQUIRED; summaryRequirementsDescriptor->mergeAnotherDescriptorIn(scalingMemoryRequired, scalingAlignmentRequired, simultaneousCallCount, featureRequirement); } /*static */ void ThreadedEquationSolverLDLT::doCooperativelyScaleVectorValidated( dxRequiredResourceContainer *resourceContainer, unsigned allowedThreadCount, dReal *vectorData, const dReal *scaleData, unsigned elementCount) { dIASSERT(allowedThreadCount > 1); const unsigned int blockStep = SV_BLOCK_SIZE; // Required by the implementation unsigned scalingBlockCount = deriveScalingVectorBlockCount(elementCount, blockStep); dIASSERT(scalingBlockCount > 0U); unsigned threadCountToUse = deriveScalingVectorThreadCount(scalingBlockCount - 1, allowedThreadCount); dIASSERT(threadCountToUse > 1); dCallWaitID completionWait = resourceContainer->getStockCallWait(); dAASSERT(completionWait != NULL); atomicord32 blockCompletionProgress; initializeCooperativelyScaleVectorMemoryStructures(blockCompletionProgress); dCallReleaseeID calculationFinishReleasee; ScaleVectorWorkerContext workerContext; // The variable must exist in the outer scope workerContext.init(vectorData, scaleData, elementCount, blockCompletionProgress); dxThreadingBase *threading = resourceContainer->getThreadingInstance(); threading->PostThreadedCall(NULL, &calculationFinishReleasee, threadCountToUse - 1, NULL, completionWait, &scaleVector_completion_callback, NULL, 0, "ScaleVector Completion"); threading->PostThreadedCallsGroup(NULL, threadCountToUse - 1, calculationFinishReleasee, &scaleVector_worker_callback, &workerContext, "ScaleVector Work"); participateScalingVector(vectorData, scaleData, elementCount, blockCompletionProgress); threading->WaitThreadedCallExclusively(NULL, completionWait, NULL, "ScaleVector End Wait"); } /*static */ int ThreadedEquationSolverLDLT::scaleVector_worker_callback(void *callContext, dcallindex_t dUNUSED(callInstanceIndex), dCallReleaseeID dUNUSED(callThisReleasee)) { ScaleVectorWorkerContext *ptrContext = (ScaleVectorWorkerContext *)callContext; scaleVector_worker(*ptrContext); return 1; } /*static */ void ThreadedEquationSolverLDLT::scaleVector_worker(ScaleVectorWorkerContext &ref_context) { const unsigned blockStep = SV_BLOCK_SIZE; participateScalingVector(ref_context.m_vectorData, ref_context.m_scaleData, ref_context.m_elementCount, *ref_context.m_ptrBlockCompletionProgress); } /*static */ int ThreadedEquationSolverLDLT::scaleVector_completion_callback(void *dUNUSED(callContext), dcallindex_t dUNUSED(callInstanceIndex), dCallReleaseeID dUNUSED(callThisReleasee)) { return 1; } ////////////////////////////////////////////////////////////////////////// // Public interface functions /*extern ODE_API */ void dScaleVector(dReal *a, const dReal *d, int n) { scaleLargeVector<1, 1>(a, d, n); } /*extern ODE_API_DEPRECATED ODE_API */ void dVectorScale(dReal *a, const dReal *d, int n) { scaleLargeVector<1, 1>(a, d, n); } /*extern ODE_API */ void dEstimateCooperativelyScaleVectorResourceRequirements(dResourceRequirementsID requirements, unsigned maximalAllowedThreadCount, unsigned maximalElementCount) { dAASSERT(requirements != NULL); dxResourceRequirementDescriptor *requirementsDescriptor = (dxResourceRequirementDescriptor *)requirements; ThreadedEquationSolverLDLT::estimateCooperativeScalingVectorResourceRequirements(requirementsDescriptor, maximalAllowedThreadCount, maximalElementCount); } /*extern ODE_API */ void dCooperativelyScaleVector(dResourceContainerID resources, unsigned allowedThreadCount, dReal *dataVector, const dReal *scaleVector, unsigned elementCount) { dAASSERT(resources != NULL); dxRequiredResourceContainer *resourceContainer = (dxRequiredResourceContainer *)resources; ThreadedEquationSolverLDLT::cooperativelyScaleVector(resourceContainer, allowedThreadCount, dataVector, scaleVector, elementCount); } ode-0.16/ode/src/mat.cpp0000664000175200017520000001371113403272463011770 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include #include #include #include "config.h" #include "matrix.h" #include "mat.h" dMatrix::dMatrix() { n = 0; m = 0; data = 0; } dMatrix::dMatrix (int rows, int cols) { if (rows < 1 || cols < 1) dDebug (0,"bad matrix size"); n = rows; m = cols; data = (dReal*) dAlloc (n*m*sizeof(dReal)); dSetZero (data,n*m); } dMatrix::dMatrix (const dMatrix &a) { n = a.n; m = a.m; data = (dReal*) dAlloc (n*m*sizeof(dReal)); memcpy (data,a.data,n*m*sizeof(dReal)); } dMatrix::dMatrix (int rows, int cols, dReal *_data, int rowskip, int colskip) { if (rows < 1 || cols < 1) dDebug (0,"bad matrix size"); n = rows; m = cols; data = (dReal*) dAlloc (n*m*sizeof(dReal)); for (int i=0; i= n || j < 0 || j >= m) dDebug (0,"bad matrix (i,j)"); return data [i*m+j]; } void dMatrix::operator= (const dMatrix &a) { if (data) dFree (data,n*m*sizeof(dReal)); n = a.n; m = a.m; if (n > 0 && m > 0) { data = (dReal*) dAlloc (n*m*sizeof(dReal)); memcpy (data,a.data,n*m*sizeof(dReal)); } else data = 0; } void dMatrix::operator= (dReal a) { for (int i=0; i= n || q[i] < 0 || q[i] >= m) dDebug (0,"Matrix select, bad index arrays"); r.data[i*nq+j] = data[p[i]*m+q[j]]; } } return r; } dMatrix dMatrix::operator + (const dMatrix &a) { if (n != a.n || m != a.m) dDebug (0,"matrix +, mismatched sizes"); dMatrix r (n,m); for (int i=0; i max) max = diff; } } return max; } ode-0.16/ode/src/collision_trimesh_trimesh.cpp0000664000175200017520000011232313403272463016467 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ // OPCODE TriMesh/TriMesh collision code // Written at 2006-10-28 by Francisco León (http://gimpact.sourceforge.net) #ifdef _MSC_VER #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints #endif #include #include #include "config.h" #include "matrix.h" #include "odemath.h" #if dTRIMESH_ENABLED #include "collision_util.h" #include "collision_trimesh_internal.h" #if !dTLS_ENABLED // Have collider cache instance unconditionally of OPCODE or GIMPACT selection /*extern */TrimeshCollidersCache g_ccTrimeshCollidersCache; #endif #if dTRIMESH_OPCODE // New Implementation #if !dTRIMESH_OPCODE_USE_OLD_TRIMESH_TRIMESH_COLLIDER #define SMALL_ELT REAL(2.5e-4) #define EXPANDED_ELT_THRESH REAL(1.0e-3) #define DISTANCE_EPSILON REAL(1.0e-8) #define VELOCITY_EPSILON REAL(1.0e-5) #define TINY_PENETRATION REAL(5.0e-6) struct LineContactSet { enum { MAX_POINTS = 8 }; dVector3 Points[MAX_POINTS]; int Count; }; // static void GetTriangleGeometryCallback(udword, VertexPointers&, udword); -- not used static inline void dMakeMatrix4(const dVector3 Position, const dMatrix3 Rotation, dMatrix4 &B); //static void dInvertMatrix4( dMatrix4& B, dMatrix4& Binv ); //static int IntersectLineSegmentRay(dVector3, dVector3, dVector3, dVector3, dVector3); static void ClipConvexPolygonAgainstPlane( const dVector3, dReal, LineContactSet& ); ///returns the penetration depth static dReal MostDeepPoints( LineContactSet & points, const dVector3 plane_normal, dReal plane_dist, LineContactSet & deep_points); static bool TriTriContacts(const dVector3 tr1[3], const dVector3 tr2[3], int TriIndex1, int TriIndex2, dxGeom* g1, dxGeom* g2, int Flags, CONTACT_KEY_HASH_TABLE &hashcontactset, dContactGeom* Contacts, int Stride, int &contactcount); /* some math macros */ #define IS_ZERO(v) (!(v)[0] && !(v)[1] && !(v)[2]) #define CROSS(dest,v1,v2) dCalcVectorCross3(dest, v1, v2) #define DOT(v1,v2) dCalcVectorDot3(v1, v2) #define SUB(dest,v1,v2) dSubtractVectors3(dest, v1, v2) #define ADD(dest,v1,v2) dAddVectors3(dest, v1, v2) #define MULT(dest,v,factor) dCopyScaledVector3(dest, v, factor) #define SET(dest,src) dCopyVector3(dest, src) #define SMULT(p,q,s) dCopyScaledVector3(p, q, s) #define COMBO(combo,p,t,q) dAddVectorScaledVector3(combo, p, q, t) #define LENGTH(x) dCalcVectorLength3(x) #define DEPTH(d, p, q, n) d = dCalcPointDepth3(q, p, n) static inline void SwapNormals(dVector3 *&pen_v, dVector3 *&col_v, dVector3* v1, dVector3* v2, dVector3 *&pen_elt, dVector3 *elt_f1, dVector3 *elt_f2, dVector3 n, dVector3 n1, dVector3 n2) { if (pen_v == v1) { pen_v = v2; pen_elt = elt_f2; col_v = v1; SET(n, n1); } else { pen_v = v1; pen_elt = elt_f1; col_v = v2; SET(n, n2); } } ///////////////////////MECHANISM FOR AVOID CONTACT REDUNDANCE/////////////////////////////// ////* Written by Francisco León (http://gimpact.sourceforge.net) */// #define CONTACT_DIFF_EPSILON REAL(0.00001) #if defined(dDOUBLE) #define CONTACT_NORMAL_ZERO REAL(0.0000001) #else // if defined(dSINGLE) #define CONTACT_NORMAL_ZERO REAL(0.00001) #endif #define CONTACT_POS_HASH_QUOTIENT REAL(10000.0) #define dSQRT3 REAL(1.7320508075688773) static void UpdateContactKey(CONTACT_KEY & key, dContactGeom * contact) { key.m_contact = contact; unsigned int hash=0; int i = 0; while (true) { dReal coord = contact->pos[i]; coord = dFloor(coord * CONTACT_POS_HASH_QUOTIENT); const int sz = sizeof(coord) / sizeof(unsigned); dIASSERT(sizeof(coord) % sizeof(unsigned) == 0); unsigned hash_v[ sz ]; memcpy(hash_v, &coord, sizeof(coord)); unsigned int hash_input = hash_v[0]; for (int i=1; i> 24)) ^ ( hash >> 28 ); hash = (( hash << 4 ) + ((hash_input >> 16) & 0xFF)) ^ ( hash >> 28 ); hash = (( hash << 4 ) + ((hash_input >> 8) & 0xFF)) ^ ( hash >> 28 ); hash = (( hash << 4 ) + (hash_input & 0xFF)) ^ ( hash >> 28 ); if (++i == 3) { break; } hash = (hash << 11) | (hash >> 21); } key.m_key = hash; } static inline unsigned int MakeContactIndex(unsigned int key) { dIASSERT(CONTACTS_HASHSIZE == 256); unsigned int index = key ^ (key >> 16); index = (index ^ (index >> 8)) & 0xFF; return index; } static dContactGeom *AddContactToNode(const CONTACT_KEY * contactkey,CONTACT_KEY_HASH_NODE * node) { for(int i=0;im_keycount;i++) { if(node->m_keyarray[i].m_key == contactkey->m_key) { dContactGeom *contactfound = node->m_keyarray[i].m_contact; if (dCalcPointsDistance3(contactfound->pos, contactkey->m_contact->pos) < REAL(1.00001) /*for comp. errors*/ * dSQRT3 / CONTACT_POS_HASH_QUOTIENT /*cube diagonal*/) { return contactfound; } } } if (node->m_keycount < MAXCONTACT_X_NODE) { node->m_keyarray[node->m_keycount].m_contact = contactkey->m_contact; node->m_keyarray[node->m_keycount].m_key = contactkey->m_key; node->m_keycount++; } else { dDEBUGMSG("Trimesh-trimesh contach hash table bucket overflow - close contacts might not be culled"); } return contactkey->m_contact; } static void RemoveNewContactFromNode(const CONTACT_KEY * contactkey, CONTACT_KEY_HASH_NODE * node) { dIASSERT(node->m_keycount > 0); if (node->m_keyarray[node->m_keycount - 1].m_contact == contactkey->m_contact) { node->m_keycount -= 1; } else { dIASSERT(node->m_keycount == MAXCONTACT_X_NODE); } } static void RemoveArbitraryContactFromNode(const CONTACT_KEY *contactkey, CONTACT_KEY_HASH_NODE *node) { dIASSERT(node->m_keycount > 0); int keyindex, lastkeyindex = node->m_keycount - 1; // Do not check the last contact for (keyindex = 0; keyindex < lastkeyindex; keyindex++) { if (node->m_keyarray[keyindex].m_contact == contactkey->m_contact) { node->m_keyarray[keyindex] = node->m_keyarray[lastkeyindex]; break; } } dIASSERT(keyindex < lastkeyindex || node->m_keyarray[keyindex].m_contact == contactkey->m_contact); // It has been either the break from loop or last element should match node->m_keycount = lastkeyindex; } static void UpdateArbitraryContactInNode(const CONTACT_KEY *contactkey, CONTACT_KEY_HASH_NODE *node, dContactGeom *pwithcontact) { dIASSERT(node->m_keycount > 0); int keyindex, lastkeyindex = node->m_keycount - 1; // Do not check the last contact for (keyindex = 0; keyindex < lastkeyindex; keyindex++) { if (node->m_keyarray[keyindex].m_contact == contactkey->m_contact) { break; } } dIASSERT(keyindex < lastkeyindex || node->m_keyarray[keyindex].m_contact == contactkey->m_contact); // It has been either the break from loop or last element should match node->m_keyarray[keyindex].m_contact = pwithcontact; } static void ClearContactSet(CONTACT_KEY_HASH_TABLE &hashcontactset) { memset(&hashcontactset, 0, sizeof(CONTACT_KEY_HASH_TABLE)); } //return true if found static dContactGeom *InsertContactInSet(CONTACT_KEY_HASH_TABLE &hashcontactset, const CONTACT_KEY &newkey) { unsigned int index = MakeContactIndex(newkey.m_key); return AddContactToNode(&newkey, &hashcontactset[index]); } static void RemoveNewContactFromSet(CONTACT_KEY_HASH_TABLE &hashcontactset, const CONTACT_KEY &contactkey) { unsigned int index = MakeContactIndex(contactkey.m_key); RemoveNewContactFromNode(&contactkey, &hashcontactset[index]); } static void RemoveArbitraryContactFromSet(CONTACT_KEY_HASH_TABLE &hashcontactset, const CONTACT_KEY &contactkey) { unsigned int index = MakeContactIndex(contactkey.m_key); RemoveArbitraryContactFromNode(&contactkey, &hashcontactset[index]); } static void UpdateArbitraryContactInSet(CONTACT_KEY_HASH_TABLE &hashcontactset, const CONTACT_KEY &contactkey, dContactGeom *pwithcontact) { unsigned int index = MakeContactIndex(contactkey.m_key); UpdateArbitraryContactInNode(&contactkey, &hashcontactset[index], pwithcontact); } static bool AllocNewContact( const dVector3 newpoint, dContactGeom *& out_pcontact, int Flags, CONTACT_KEY_HASH_TABLE &hashcontactset, dContactGeom* Contacts, int Stride, int &contactcount) { bool allocated_new = false; dContactGeom dLocalContact; dContactGeom * pcontact = contactcount != (Flags & NUMC_MASK) ? SAFECONTACT(Flags, Contacts, contactcount, Stride) : &dLocalContact; pcontact->pos[0] = newpoint[0]; pcontact->pos[1] = newpoint[1]; pcontact->pos[2] = newpoint[2]; pcontact->pos[3] = 1.0f; CONTACT_KEY newkey; UpdateContactKey(newkey, pcontact); dContactGeom *pcontactfound = InsertContactInSet(hashcontactset, newkey); if (pcontactfound == pcontact) { if (pcontactfound != &dLocalContact) { contactcount++; } else { RemoveNewContactFromSet(hashcontactset, newkey); pcontactfound = NULL; } allocated_new = true; } out_pcontact = pcontactfound; return allocated_new; } static void FreeExistingContact(dContactGeom *pcontact, int Flags, CONTACT_KEY_HASH_TABLE &hashcontactset, dContactGeom *Contacts, int Stride, int &contactcount) { CONTACT_KEY contactKey; UpdateContactKey(contactKey, pcontact); RemoveArbitraryContactFromSet(hashcontactset, contactKey); int lastContactIndex = contactcount - 1; dContactGeom *plastContact = SAFECONTACT(Flags, Contacts, lastContactIndex, Stride); if (pcontact != plastContact) { *pcontact = *plastContact; CONTACT_KEY lastContactKey; UpdateContactKey(lastContactKey, plastContact); UpdateArbitraryContactInSet(hashcontactset, lastContactKey, pcontact); } contactcount = lastContactIndex; } static dContactGeom * PushNewContact( dxGeom* g1, dxGeom* g2, int TriIndex1, int TriIndex2, const dVector3 point, dVector3 normal, dReal depth, int Flags, CONTACT_KEY_HASH_TABLE &hashcontactset, dContactGeom* Contacts, int Stride, int &contactcount) { dIASSERT(dFabs(dVector3Length((const dVector3 &)(*normal)) - REAL(1.0)) < REAL(1e-6)); // This assumption is used in the code dContactGeom * pcontact; if (!AllocNewContact(point, pcontact, Flags, hashcontactset, Contacts, Stride, contactcount)) { const dReal depthDifference = depth - pcontact->depth; if (depthDifference > CONTACT_DIFF_EPSILON) { pcontact->normal[0] = normal[0]; pcontact->normal[1] = normal[1]; pcontact->normal[2] = normal[2]; pcontact->normal[3] = REAL(1.0); // used to store length of vector sum for averaging pcontact->depth = depth; pcontact->g1 = g1; pcontact->g2 = g2; pcontact->side1 = TriIndex1; pcontact->side2 = TriIndex2; } else if (depthDifference >= -CONTACT_DIFF_EPSILON) ///average { if(pcontact->g1 == g2) { MULT(normal,normal, REAL(-1.0)); int tempInt = TriIndex1; TriIndex1 = TriIndex2; TriIndex2 = tempInt; // This should be discarded by optimizer as g1 and g2 are // not used any more but it's preferable to keep this line for // the sake of consistency in variable values. dxGeom *tempGeom = g1; g1 = g2; g2 = tempGeom; } const dReal oldLen = pcontact->normal[3]; COMBO(pcontact->normal, normal, oldLen, pcontact->normal); const dReal len = LENGTH(pcontact->normal); if (len > CONTACT_NORMAL_ZERO) { MULT(pcontact->normal, pcontact->normal, REAL(1.0) / len); pcontact->normal[3] = len; pcontact->side1 = ((dxTriMesh *)pcontact->g1)->m_TriMergeCallback ? ((dxTriMesh *)pcontact->g1)->m_TriMergeCallback((dxTriMesh *)pcontact->g1, pcontact->side1, TriIndex1) : -1; pcontact->side2 = ((dxTriMesh *)pcontact->g2)->m_TriMergeCallback ? ((dxTriMesh *)pcontact->g2)->m_TriMergeCallback((dxTriMesh *)pcontact->g2, pcontact->side2, TriIndex2) : -1; } else { FreeExistingContact(pcontact, Flags, hashcontactset, Contacts, Stride, contactcount); } } } // Contact can be not available if buffer is full else if (pcontact) { pcontact->normal[0] = normal[0]; pcontact->normal[1] = normal[1]; pcontact->normal[2] = normal[2]; pcontact->normal[3] = REAL(1.0); // used to store length of vector sum for averaging pcontact->depth = depth; pcontact->g1 = g1; pcontact->g2 = g2; pcontact->side1 = TriIndex1; pcontact->side2 = TriIndex2; } return pcontact; } //////////////////////////////////////////////////////////////////////////////////////////// /*extern */ int dCollideTTL(dxGeom* g1, dxGeom* g2, int Flags, dContactGeom* Contacts, int Stride) { dIASSERT (Stride >= (int)sizeof(dContactGeom)); dIASSERT (g1->type == dTriMeshClass); dIASSERT (g2->type == dTriMeshClass); dIASSERT ((Flags & NUMC_MASK) >= 1); dxTriMesh* TriMesh1 = (dxTriMesh*) g1; dxTriMesh* TriMesh2 = (dxTriMesh*) g2; //dReal * TriNormals1 = (dReal *) TriMesh1->Data->Normals; //dReal * TriNormals2 = (dReal *) TriMesh2->Data->Normals; const dVector3& TLPosition1 = *(const dVector3*) dGeomGetPosition(TriMesh1); // TLRotation1 = column-major order const dMatrix3& TLRotation1 = *(const dMatrix3*) dGeomGetRotation(TriMesh1); const dVector3& TLPosition2 = *(const dVector3*) dGeomGetPosition(TriMesh2); // TLRotation2 = column-major order const dMatrix3& TLRotation2 = *(const dMatrix3*) dGeomGetRotation(TriMesh2); const unsigned uiTLSKind = TriMesh1->getParentSpaceTLSKind(); dIASSERT(uiTLSKind == TriMesh2->getParentSpaceTLSKind()); // The colliding spaces must use matching cleanup method TrimeshCollidersCache *pccColliderCache = GetTrimeshCollidersCache(uiTLSKind); AABBTreeCollider& Collider = pccColliderCache->m_AABBTreeCollider; BVTCache &ColCache = pccColliderCache->ColCache; CONTACT_KEY_HASH_TABLE &hashcontactset = pccColliderCache->m_hashcontactset; ColCache.Model0 = &TriMesh1->retrieveMeshBVTreeRef(); ColCache.Model1 = &TriMesh2->retrieveMeshBVTreeRef(); ////Prepare contact list ClearContactSet(hashcontactset); // Collision query Matrix4x4 amatrix, bmatrix; dVector3 TLOffsetPosition1 = { REAL(0.0), }; dVector3 TLOffsetPosition2; dSubtractVectors3(TLOffsetPosition2, TLPosition2, TLPosition1); MakeMatrix(TLOffsetPosition1, TLRotation1, amatrix); MakeMatrix(TLOffsetPosition2, TLRotation2, bmatrix); bool IsOk = Collider.Collide(ColCache, &amatrix, &bmatrix); if (IsOk) { // Get collision status => if true, objects overlap if ( Collider.GetContactStatus() ) { // Number of colliding pairs and list of pairs int TriCount = Collider.GetNbPairs(); const Pair* CollidingPairs = Collider.GetPairs(); if (TriCount > 0) { // step through the pairs, adding contacts int id1, id2; int OutTriCount = 0; dVector3 v1[3], v2[3]; for (int i = 0; i < TriCount; i++) { id1 = CollidingPairs[i].id0; id2 = CollidingPairs[i].id1; // grab the colliding triangles static_cast(g1)->fetchMeshTriangle(v1, id1, TLPosition1, TLRotation1); static_cast(g2)->fetchMeshTriangle(v2, id2, TLPosition2, TLRotation2); // Since we'll be doing matrix transformations, we need to // make sure that all vertices have four elements for (int j=0; j<3; j++) { v1[j][3] = 1.0; v2[j][3] = 1.0; } TriTriContacts(v1,v2, id1,id2, g1, g2, Flags, hashcontactset, Contacts,Stride,OutTriCount); // Continue loop even after contacts are full // as existing contacts' normals/depths might be updated // Break only if contacts are not important if ((OutTriCount | CONTACTS_UNIMPORTANT) == (Flags & (NUMC_MASK | CONTACTS_UNIMPORTANT))) { break; } } // Return the number of contacts return OutTriCount; } } } // There was some kind of failure during the Collide call or // there are no faces overlapping return 0; } /* -- not used static void GetTriangleGeometryCallback(udword triangleindex, VertexPointers& triangle, udword user_data) { dVector3 Out[3]; FetchTriangle((dxTriMesh*) user_data, (int) triangleindex, Out); for (int i = 0; i < 3; i++) triangle.Vertex[i] = (const Point*) ((dReal*) Out[i]); } */ // // // #define B11 B[0] #define B12 B[1] #define B13 B[2] #define B14 B[3] #define B21 B[4] #define B22 B[5] #define B23 B[6] #define B24 B[7] #define B31 B[8] #define B32 B[9] #define B33 B[10] #define B34 B[11] #define B41 B[12] #define B42 B[13] #define B43 B[14] #define B44 B[15] #define Binv11 Binv[0] #define Binv12 Binv[1] #define Binv13 Binv[2] #define Binv14 Binv[3] #define Binv21 Binv[4] #define Binv22 Binv[5] #define Binv23 Binv[6] #define Binv24 Binv[7] #define Binv31 Binv[8] #define Binv32 Binv[9] #define Binv33 Binv[10] #define Binv34 Binv[11] #define Binv41 Binv[12] #define Binv42 Binv[13] #define Binv43 Binv[14] #define Binv44 Binv[15] static inline void dMakeMatrix4(const dVector3 Position, const dMatrix3 Rotation, dMatrix4 &B) { B11 = Rotation[0]; B21 = Rotation[1]; B31 = Rotation[2]; B41 = Position[0]; B12 = Rotation[4]; B22 = Rotation[5]; B32 = Rotation[6]; B42 = Position[1]; B13 = Rotation[8]; B23 = Rotation[9]; B33 = Rotation[10]; B43 = Position[2]; B14 = 0.0; B24 = 0.0; B34 = 0.0; B44 = 1.0; } #if 0 static void dInvertMatrix4( dMatrix4& B, dMatrix4& Binv ) { dReal det = (B11 * B22 - B12 * B21) * (B33 * B44 - B34 * B43) -(B11 * B23 - B13 * B21) * (B32 * B44 - B34 * B42) +(B11 * B24 - B14 * B21) * (B32 * B43 - B33 * B42) +(B12 * B23 - B13 * B22) * (B31 * B44 - B34 * B41) -(B12 * B24 - B14 * B22) * (B31 * B43 - B33 * B41) +(B13 * B24 - B14 * B23) * (B31 * B42 - B32 * B41); dAASSERT (det != 0.0); det = 1.0 / det; Binv11 = (dReal) (det * ((B22 * B33) - (B23 * B32))); Binv12 = (dReal) (det * ((B32 * B13) - (B33 * B12))); Binv13 = (dReal) (det * ((B12 * B23) - (B13 * B22))); Binv14 = 0.0f; Binv21 = (dReal) (det * ((B23 * B31) - (B21 * B33))); Binv22 = (dReal) (det * ((B33 * B11) - (B31 * B13))); Binv23 = (dReal) (det * ((B13 * B21) - (B11 * B23))); Binv24 = 0.0f; Binv31 = (dReal) (det * ((B21 * B32) - (B22 * B31))); Binv32 = (dReal) (det * ((B31 * B12) - (B32 * B11))); Binv33 = (dReal) (det * ((B11 * B22) - (B12 * B21))); Binv34 = 0.0f; Binv41 = (dReal) (det * (B21*(B33*B42 - B32*B43) + B22*(B31*B43 - B33*B41) + B23*(B32*B41 - B31*B42))); Binv42 = (dReal) (det * (B31*(B13*B42 - B12*B43) + B32*(B11*B43 - B13*B41) + B33*(B12*B41 - B11*B42))); Binv43 = (dReal) (det * (B41*(B13*B22 - B12*B23) + B42*(B11*B23 - B13*B21) + B43*(B12*B21 - B11*B22))); Binv44 = 1.0f; } #endif // Find the intersectiojn point between a coplanar line segement, // defined by X1 and X2, and a ray defined by X3 and direction N. // // This forumla for this calculation is: // (c x b) . (a x b) // Q = x1 + a ------------------- // | a x b | ^2 // // where a = x2 - x1 // b = x4 - x3 // c = x3 - x1 // x1 and x2 are the edges of the triangle, and x3 is CoplanarPt // and x4 is (CoplanarPt - n) #if 0 static int IntersectLineSegmentRay(dVector3 x1, dVector3 x2, dVector3 x3, dVector3 n, dVector3 out_pt) { dVector3 a, b, c, x4; ADD(x4, x3, n); // x4 = x3 + n SUB(a, x2, x1); // a = x2 - x1 SUB(b, x4, x3); SUB(c, x3, x1); dVector3 tmp1, tmp2; CROSS(tmp1, c, b); CROSS(tmp2, a, b); dReal num, denom; num = dCalcVectorDot3(tmp1, tmp2); denom = LENGTH( tmp2 ); dReal s; s = num /(denom*denom); for (int i=0; i<3; i++) out_pt[i] = x1[i] + a[i]*s; // Test if this intersection is "behind" x3, w.r.t. n SUB(a, x3, out_pt); if (dCalcVectorDot3(a, n) > 0.0) return 0; // Test if this intersection point is outside the edge limits, // if (dot( (out_pt-x1), (out_pt-x2) ) < 0) it's inside // else outside SUB(a, out_pt, x1); SUB(b, out_pt, x2); if (dCalcVectorDot3(a,b) < 0.0) return 1; else return 0; } #endif void PlaneClipSegment( const dVector3 s1, const dVector3 s2, const dVector3 N, dReal C, dVector3 clipped) { dReal dis1,dis2; dis1 = DOT(s1,N)-C; SUB(clipped,s2,s1); dis2 = DOT(clipped,N); MULT(clipped,clipped,-dis1/dis2); ADD(clipped,clipped,s1); clipped[3] = 1.0f; } /* ClipConvexPolygonAgainstPlane - Clip a a convex polygon, described by CONTACTS, with a plane (described by N and C distance from origin). Note: the input vertices are assumed to be in invcounterclockwise order. changed by Francisco Leon (http://gimpact.sourceforge.net) */ static void ClipConvexPolygonAgainstPlane( const dVector3 N, dReal C, LineContactSet& Contacts ) { int i, vi, prevclassif=32000, classif; /* classif 0 : back, 1 : front */ dReal d; dVector3 clipped[8]; int clippedcount =0; if(Contacts.Count==0) { return; } for(i=0;i<=Contacts.Count;i++) { vi = i%Contacts.Count; d = DOT(N,Contacts.Points[vi]) - C; ////classify point if(d>REAL(1.0e-8)) classif = 1; else classif = 0; if(classif == 0)//back { if(i>0) { if(prevclassif==1)///in front { ///add clipped point if(clippedcount<8) { PlaneClipSegment(Contacts.Points[i-1],Contacts.Points[vi], N,C,clipped[clippedcount]); clippedcount++; } } } ///add point if(clippedcount<8&&i0) { if(prevclassif==0) { ///add point if(clippedcount<8) { PlaneClipSegment(Contacts.Points[i-1],Contacts.Points[vi], N,C,clipped[clippedcount]); clippedcount++; } } } } prevclassif = classif; } if(clippedcount==0) { Contacts.Count = 0; return; } Contacts.Count = clippedcount; memcpy( Contacts.Points, clipped, clippedcount * sizeof(dVector3) ); return; } bool BuildPlane(const dVector3 s0, const dVector3 s1,const dVector3 s2, dVector3 Normal, dReal & Dist) { dVector3 e0,e1; SUB(e0,s1,s0); SUB(e1,s2,s0); CROSS(Normal,e0,e1); if (!dSafeNormalize3(Normal)) { return false; } Dist = DOT(Normal,s0); return true; } // bool BuildEdgesDir(const dVector3 s0, const dVector3 s1, // const dVector3 t0, const dVector3 t1, // dVector3 crossdir) // { // dVector3 e0,e1; // // SUB(e0,s1,s0); // SUB(e1,t1,t0); // CROSS(crossdir,e0,e1); // // if (!dSafeNormalize3(crossdir)) // { // return false; // } // return true; // } bool BuildEdgePlane( const dVector3 s0, const dVector3 s1, const dVector3 normal, dVector3 plane_normal, dReal & plane_dist) { dVector3 e0; SUB(e0,s1,s0); CROSS(plane_normal,e0,normal); if (!dSafeNormalize3(plane_normal)) { return false; } plane_dist = DOT(plane_normal,s0); return true; } /* Positive penetration Negative number: they are separated */ dReal IntervalPenetration(dReal &vmin1,dReal &vmax1, dReal &vmin2,dReal &vmax2) { if(vmax1<=vmin2) { return -(vmin2-vmax1); } else { if(vmax2<=vmin1) { return -(vmin1-vmax2); } else { if(vmax1<=vmax2) { return vmax1-vmin2; } return vmax2-vmin1; } } return 0; } void FindInterval( const dVector3 * vertices, int verticecount, dVector3 dir,dReal &vmin,dReal &vmax) { dReal dist; int i; vmin = DOT(vertices[0],dir); vmax = vmin; for(i=1;idist) vmin=dist; else if(vmaxmaxdeep) { maxdeep = dist; deep_points.Count=1; max_candidates[deep_points.Count-1] = i; } else if(dist+REAL(0.000001)>=maxdeep) { deep_points.Count++; max_candidates[deep_points.Count-1] = i; } } for(i=0;i0.0) { MULT(separating_normal,separating_normal,-1.0f); deep_points.Count = 1; SET(deep_points.Points[0],pt2); } else { deep_points.Count = 1; SET(deep_points.Points[0],pt2); } } else { vmin1 = DOT(separating_normal,tri2plane); if(vmin1<0.0) { MULT(separating_normal,separating_normal,-1.0f); deep_points.Count = 1; SET(deep_points.Points[0],pt2); } else { deep_points.Count = 1; SET(deep_points.Points[0],pt2); } } } else { MULT(separating_normal,crossdir,1.0f/vmin1); vmin1 = DOT(separating_normal,tri1plane); if(vmin1>0.0) { MULT(separating_normal,separating_normal,-1.0f); deep_points.Count = 1; SET(deep_points.Points[0],pt2); } else { deep_points.Count = 1; SET(deep_points.Points[0],pt2); } } }*/ return maxdeep; } ///SUPPORT UP TO 8 CONTACTS bool TriTriContacts(const dVector3 tr1[3], const dVector3 tr2[3], int TriIndex1, int TriIndex2, dxGeom* g1, dxGeom* g2, int Flags, CONTACT_KEY_HASH_TABLE &hashcontactset, dContactGeom* Contacts, int Stride, int &contactcount) { dVector4 normal; dReal depth; ///Test Tri Vs Tri // dContactGeom* pcontact; int ccount = 0; LineContactSet contactpoints; contactpoints.Count = 0; ///find best direction depth = FindTriangleTriangleCollision( tr1, tr2, normal, contactpoints); if(depth<0.0f) return false; ccount = 0; while (ccount= (int)sizeof(dContactGeom)); dIASSERT (g1->type == dTriMeshClass); dIASSERT (g2->type == dTriMeshClass); dIASSERT ((Flags & NUMC_MASK) >= 1); int result = 0; dxTriMesh *triMesh1 = static_cast(g1); dxTriMesh *triMesh2 = static_cast(g2); //Create contact list GDYNAMIC_ARRAY trimeshContacts; GIM_CREATE_CONTACT_LIST(trimeshContacts); triMesh1->recomputeAABB(); triMesh2->recomputeAABB(); //Collide trimeshes gim_trimesh_trimesh_collision(&triMesh1->m_collision_trimesh, &triMesh2->m_collision_trimesh, &trimeshContacts); unsigned contactCount = trimeshContacts.m_size; if (contactCount != 0) { GIM_CONTACT *pTriMeshContacts = GIM_DYNARRAY_POINTER(GIM_CONTACT, trimeshContacts); dxGIMCContactAccessor contactAccessor(pTriMeshContacts, g1, g2); unsigned culledContactCount = dxGImpactContactsExportHelper::ExportMaxDepthGImpactContacts(contactAccessor, contactCount, Flags, Contacts, Stride); result = culledContactCount; } GIM_DYNARRAY_DESTROY(trimeshContacts); return result; } #endif // dTRIMESH_GIMPACT #endif // dTRIMESH_ENABLED ode-0.16/ode/src/lcp.cpp0000664000175200017520000014231013403272463011763 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* THE ALGORITHM ------------- solve A*x = b+w, with x and w subject to certain LCP conditions. each x(i),w(i) must lie on one of the three line segments in the following diagram. each line segment corresponds to one index set : w(i) /|\ | : | | : | |i in N : w>0 | |state[i]=0 : | | : | | : i in C w=0 + +-----------------------+ | : | | : | w<0 | : |i in N | : |state[i]=1 | : | | : | +-------|-----------|-----------|----------> x(i) lo 0 hi the Dantzig algorithm proceeds as follows: for i=1:n * if (x(i),w(i)) is not on the line, push x(i) and w(i) positive or negative towards the line. as this is done, the other (x(j),w(j)) for j= 0. this makes the algorithm a bit simpler, because the starting point for x(i),w(i) is always on the dotted line x=0 and x will only ever increase in one direction, so it can only hit two out of the three line segments. NOTES ----- this is an implementation of "lcp_dantzig2_ldlt.m" and "lcp_dantzig_lohi.m". the implementation is split into an LCP problem object (dLCP) and an LCP driver function. most optimization occurs in the dLCP object. a naive implementation of the algorithm requires either a lot of data motion or a lot of permutation-array lookup, because we are constantly re-ordering rows and columns. to avoid this and make a more optimized algorithm, a non-trivial data structure is used to represent the matrix A (this is implemented in the fast version of the dLCP object). during execution of this algorithm, some indexes in A are clamped (set C), some are non-clamped (set N), and some are "don't care" (where x=0). A,x,b,w (and other problem vectors) are permuted such that the clamped indexes are first, the unclamped indexes are next, and the don't-care indexes are last. this permutation is recorded in the array `p'. initially p = 0..n-1, and as the rows and columns of A,x,b,w are swapped, the corresponding elements of p are swapped. because the C and N elements are grouped together in the rows of A, we can do lots of work with a fast dot product function. if A,x,etc were not permuted and we only had a permutation array, then those dot products would be much slower as we would have a permutation array lookup in some inner loops. A is accessed through an array of row pointers, so that element (i,j) of the permuted matrix is A[i][j]. this makes row swapping fast. for column swapping we still have to actually move the data. during execution of this algorithm we maintain an L*D*L' factorization of the clamped submatrix of A (call it `AC') which is the top left nC*nC submatrix of A. there are two ways we could arrange the rows/columns in AC. (1) AC is always permuted such that L*D*L' = AC. this causes a problem when a row/column is removed from C, because then all the rows/columns of A between the deleted index and the end of C need to be rotated downward. this results in a lot of data motion and slows things down. (2) L*D*L' is actually a factorization of a *permutation* of AC (which is itself a permutation of the underlying A). this is what we do - the permutation is recorded in the vector C. call this permutation A[C,C]. when a row/column is removed from C, all we have to do is swap two rows/columns and manipulate C. */ #include #include #include // for testing #include "config.h" #include "lcp.h" #include "util.h" #include "matrix.h" #include "mat.h" // for testing #include "threaded_solver_ldlt.h" #include "fastdot_impl.h" #include "fastldltfactor_impl.h" #include "fastldltsolve_impl.h" //*************************************************************************** // code generation parameters // LCP debugging (mostly for fast dLCP) - this slows things down a lot //#define DEBUG_LCP #define dLCP_FAST // use fast dLCP object #define NUB_OPTIMIZATIONS // use NUB optimizations // option 1 : matrix row pointers (less data copying) #define ROWPTRS #define ATYPE dReal ** #define AROW(i) (m_A[i]) // option 2 : no matrix row pointers (slightly faster inner loops) //#define NOROWPTRS //#define ATYPE dReal * //#define AROW(i) (m_A+(i)*m_nskip) //*************************************************************************** #define dMIN(A,B) ((A)>(B) ? (B) : (A)) #define dMAX(A,B) ((B)>(A) ? (B) : (A)) #define LMATRIX_ALIGNMENT dMAX(64, EFFICIENT_ALIGNMENT) //*************************************************************************** // transfer b-values to x-values template inline void transfer_b_to_x(dReal pairsbx[PBX__MAX], unsigned n) { dReal *const endbx = pairsbx + (sizeint)n * PBX__MAX; for (dReal *currbx = pairsbx; currbx != endbx; currbx += PBX__MAX) { currbx[PBX_X] = currbx[PBX_B]; if (zero_b) { currbx[PBX_B] = REAL(0.0); } } } // swap row/column i1 with i2 in the n*n matrix A. the leading dimension of // A is nskip. this only references and swaps the lower triangle. // if `do_fast_row_swaps' is nonzero and row pointers are being used, then // rows will be swapped by exchanging row pointers. otherwise the data will // be copied. static void swapRowsAndCols (ATYPE A, unsigned n, unsigned i1, unsigned i2, unsigned nskip, int do_fast_row_swaps) { dAASSERT (A && n > 0 && i1 >= 0 && i2 >= 0 && i1 < n && i2 < n && nskip >= n && i1 < i2); # ifdef ROWPTRS dReal *A_i1 = A[i1]; dReal *A_i2 = A[i2]; for (unsigned i=i1+1; i0 && i1 < n && i2 < n && nskip >= n && i1 <= i2); if (i1 != i2) { swapRowsAndCols (A, n, i1, i2, nskip, do_fast_row_swaps); dxSwap((pairsbx + (sizeint)i1 * PBX__MAX)[PBX_B], (pairsbx + (sizeint)i2 * PBX__MAX)[PBX_B]); dxSwap((pairsbx + (sizeint)i1 * PBX__MAX)[PBX_X], (pairsbx + (sizeint)i2 * PBX__MAX)[PBX_X]); dSASSERT(PBX__MAX == 2); dxSwap(w[i1], w[i2]); dxSwap((pairslh + (sizeint)i1 * PLH__MAX)[PLH_LO], (pairslh + (sizeint)i2 * PLH__MAX)[PLH_LO]); dxSwap((pairslh + (sizeint)i1 * PLH__MAX)[PLH_HI], (pairslh + (sizeint)i2 * PLH__MAX)[PLH_HI]); dSASSERT(PLH__MAX == 2); dxSwap(p[i1], p[i2]); dxSwap(state[i1], state[i2]); if (findex != NULL) { dxSwap(findex[i1], findex[i2]); } } } // for debugging - check that L,d is the factorization of A[C,C]. // A[C,C] has size nC*nC and leading dimension nskip. // L has size nC*nC and leading dimension nskip. // d has size nC. #ifdef DEBUG_LCP static void checkFactorization (ATYPE A, dReal *_L, dReal *_d, unsigned nC, unsigned *C, unsigned nskip) { unsigned i, j; if (nC == 0) return; // get A1=A, copy the lower triangle to the upper triangle, get A2=A[C,C] dMatrix A1 (nC, nC); for (i=0; i < nC; i++) { for (j = 0; j <= i; j++) A1(i, j) = A1(j, i) = AROW(i)[j]; } dMatrix A2 = A1.select (nC, C, nC, C); // printf ("A1=\n"); A1.print(); printf ("\n"); // printf ("A2=\n"); A2.print(); printf ("\n"); // compute A3 = L*D*L' dMatrix L (nC, nC, _L, nskip, 1); dMatrix D (nC, nC); for (i = 0; i < nC; i++) D(i, i) = 1.0 / _d[i]; L.clearUpperTriangle(); for (i = 0; i < nC; i++) L(i, i) = 1; dMatrix A3 = L * D * L.transpose(); // printf ("L=\n"); L.print(); printf ("\n"); // printf ("D=\n"); D.print(); printf ("\n"); // printf ("A3=\n"); A2.print(); printf ("\n"); // compare A2 and A3 dReal diff = A2.maxDifference (A3); if (diff > 1e-8) dDebug (0, "L*D*L' check, maximum difference = %.6e\n", diff); } #endif // for debugging #ifdef DEBUG_LCP static void checkPermutations (unsigned i, unsigned n, unsigned nC, unsigned nN, unsigned *p, unsigned *C) { unsigned j,k; dIASSERT (/*nC >= 0 && nN >= 0 && */(nC + nN) == i && i < n); for (k=0; k= 0 && p[k] < i); for (k=i; k dReal AiC_times_qC (unsigned i, dReal *q) const { return calculateLargeVectorDot (AROW(i), q, m_nC); } template dReal AiN_times_qN (unsigned i, dReal *q) const { return calculateLargeVectorDot (AROW(i) + m_nC, q + (sizeint)m_nC * q_stride, m_nN); } void pN_equals_ANC_times_qC (dReal *p, dReal *q); void pN_plusequals_ANi (dReal *p, unsigned i, bool dir_positive); template void pC_plusequals_s_times_qC (dReal *p, dReal s, dReal *q); void pN_plusequals_s_times_qN (dReal *p, dReal s, dReal *q); void solve1 (dReal *a, unsigned i, bool dir_positive, int only_transfer=0); void unpermute_X(); void unpermute_W(); }; dLCP::dLCP (unsigned _n, unsigned _nskip, unsigned _nub, dReal *_Adata, dReal *_pairsbx, dReal *_w, dReal *_pairslh, dReal *_L, dReal *_d, dReal *_Dell, dReal *_ell, dReal *_tmp, bool *_state, int *_findex, unsigned *_p, unsigned *_C, dReal **Arows): m_n(_n), m_nskip(_nskip), m_nub(_nub), m_nC(0), m_nN(0), # ifdef ROWPTRS m_A(Arows), #else m_A(_Adata), #endif m_pairsbx(_pairsbx), m_w(_w), m_pairslh(_pairslh), m_L(_L), m_d(_d), m_Dell(_Dell), m_ell(_ell), m_tmp(_tmp), m_state(_state), m_findex(_findex), m_p(_p), m_C(_C) { dxtSetZero(m_pairsbx + PBX_X, m_n); { # ifdef ROWPTRS // make matrix row pointers dReal *aptr = _Adata; ATYPE A = m_A; const unsigned n = m_n, nskip = m_nskip; for (unsigned k=0; k nub { const unsigned n = m_n; const unsigned nub = m_nub; if (nub < n) { for (unsigned k=0; k<100; k++) { unsigned i1,i2; do { i1 = dRandInt(n-nub)+nub; i2 = dRandInt(n-nub)+nub; } while (i1 > i2); //printf ("--> %d %d\n",i1,i2); swapProblem (m_A, m_pairsbx, m_w, m_pairslh, m_p, m_state, m_findex, n, i1, i2, m_nskip, 0); } } */ // permute the problem so that *all* the unbounded variables are at the // start, i.e. look for unbounded variables not included in `nub'. we can // potentially push up `nub' this way and get a bigger initial factorization. // note that when we swap rows/cols here we must not just swap row pointers, // as the initial factorization relies on the data being all in one chunk. // variables that have findex >= 0 are *not* considered to be unbounded even // if lo=-inf and hi=inf - this is because these limits may change during the // solution process. { int *findex = m_findex; dReal *pairslh = m_pairslh; const unsigned n = m_n; for (unsigned k = m_nub; k < n; ++k) { if (findex && findex[k] >= 0) continue; if ((pairslh + (sizeint)k * PLH__MAX)[PLH_LO] == -dInfinity && (pairslh + (sizeint)k * PLH__MAX)[PLH_HI] == dInfinity) { swapProblem (m_A, m_pairsbx, m_w, pairslh, m_p, m_state, findex, n, m_nub, k, m_nskip, 0); m_nub++; } } } // if there are unbounded variables at the start, factorize A up to that // point and solve for x. this puts all indexes 0..nub-1 into C. if (m_nub > 0) { const unsigned nub = m_nub; { dReal *Lrow = m_L; const unsigned nskip = m_nskip; for (unsigned j = 0; j < nub; Lrow += nskip, ++j) memcpy(Lrow, AROW(j), (j + 1) * sizeof(dReal)); } transfer_b_to_x (m_pairsbx, nub); factorMatrixAsLDLT<1> (m_L, m_d, nub, m_nskip); solveEquationSystemWithLDLT<1, PBX__MAX> (m_L, m_d, m_pairsbx + PBX_X, nub, m_nskip); dSetZero (m_w, nub); { unsigned *C = m_C; for (unsigned k = 0; k < nub; ++k) C[k] = k; } m_nC = nub; } // permute the indexes > nub such that all findex variables are at the end if (m_findex) { const unsigned nub = m_nub; int *findex = m_findex; unsigned num_at_end = 0; for (unsigned k = m_n; k > nub; ) { --k; if (findex[k] >= 0) { swapProblem (m_A, m_pairsbx, m_w, m_pairslh, m_p, m_state, findex, m_n, k, m_n - 1 - num_at_end, m_nskip, 1); num_at_end++; } } } // print info about indexes /* { const unsigned n = m_n; const unsigned nub = m_nub; for (unsigned k=0; k 0) { // ell,Dell were computed by solve1(). note, ell = D \ L1solve (L,A(i,C)) dReal *const Ltgt = m_L + (sizeint)m_nskip * nC, *ell = m_ell; memcpy(Ltgt, ell, nC * sizeof(dReal)); dReal ell_Dell_dot = dxDot(m_ell, m_Dell, nC); dReal AROW_i_i = AROW(i)[i] != ell_Dell_dot ? AROW(i)[i] : dNextAfter(AROW(i)[i], dInfinity); // A hack to avoid getting a zero in the denominator m_d[nC] = dRecip (AROW_i_i - ell_Dell_dot); } else { m_d[0] = dRecip (AROW(i)[i]); } swapProblem (m_A, m_pairsbx, m_w, m_pairslh, m_p, m_state, m_findex, m_n, nC, i, m_nskip, 1); m_C[nC] = nC; m_nC = nC + 1; // nC value is outdated after this line } # ifdef DEBUG_LCP checkFactorization (m_A, m_L, m_d, m_nC, m_C, m_nskip); if (i < (m_n-1)) checkPermutations (i+1, m_n, m_nC, m_nN, m_p, m_C); # endif } void dLCP::transfer_i_from_N_to_C (unsigned i) { { const unsigned nC = m_nC; if (nC > 0) { { dReal *const aptr = AROW(i); dReal *Dell = m_Dell; const unsigned *C = m_C; # ifdef NUB_OPTIMIZATIONS // if nub>0, initial part of aptr unpermuted const unsigned nub = m_nub; unsigned j=0; for ( ; j(m_L, m_Dell, nC, m_nskip); dReal ell_Dell_dot = REAL(0.0); dReal *const Ltgt = m_L + (sizeint)m_nskip * nC; dReal *ell = m_ell, *Dell = m_Dell, *d = m_d; for (unsigned j = 0; j < nC; ++j) { dReal ell_j, Dell_j = Dell[j]; Ltgt[j] = ell[j] = ell_j = Dell_j * d[j]; ell_Dell_dot += ell_j * Dell_j; } dReal AROW_i_i = AROW(i)[i] != ell_Dell_dot ? AROW(i)[i] : dNextAfter(AROW(i)[i], dInfinity); // A hack to avoid getting a zero in the denominator m_d[nC] = dRecip (AROW_i_i - ell_Dell_dot); } else { m_d[0] = dRecip (AROW(i)[i]); } swapProblem (m_A, m_pairsbx, m_w, m_pairslh, m_p, m_state, m_findex, m_n, nC, i, m_nskip, 1); m_C[nC] = nC; m_nN--; m_nC = nC + 1; // nC value is outdated after this line } // @@@ TO DO LATER // if we just finish here then we'll go back and re-solve for // delta_x. but actually we can be more efficient and incrementally // update delta_x here. but if we do this, we wont have ell and Dell // to use in updating the factorization later. # ifdef DEBUG_LCP checkFactorization (m_A,m_L,m_d,m_nC,m_C,m_nskip); # endif } void dLCP::transfer_i_from_C_to_N (unsigned i, void *tmpbuf) { { unsigned *C = m_C; // remove a row/column from the factorization, and adjust the // indexes (black magic!) int last_idx = -1; const unsigned nC = m_nC; unsigned j = 0; for ( ; j < nC; ++j) { if (C[j] == nC - 1) { last_idx = j; } if (C[j] == i) { dxLDLTRemove (m_A, C, m_L, m_d, m_n, nC, j, m_nskip, tmpbuf); unsigned k; if (last_idx == -1) { for (k = j + 1 ; k < nC; ++k) { if (C[k] == nC - 1) { break; } } dIASSERT (k < nC); } else { k = last_idx; } C[k] = C[j]; if (j != (nC - 1)) memmove (C + j, C + j + 1, (nC - j - 1) * sizeof(C[0])); break; } } dIASSERT (j < nC); swapProblem (m_A, m_pairsbx, m_w, m_pairslh, m_p, m_state, m_findex, m_n, i, nC - 1, m_nskip, 1); m_nN++; m_nC = nC - 1; // nC value is outdated after this line } # ifdef DEBUG_LCP checkFactorization (m_A, m_L, m_d, m_nC, m_C, m_nskip); # endif } void dLCP::pN_equals_ANC_times_qC (dReal *p, dReal *q) { // we could try to make this matrix-vector multiplication faster using // outer product matrix tricks, e.g. with the dMultidotX() functions. // but i tried it and it actually made things slower on random 100x100 // problems because of the overhead involved. so we'll stick with the // simple method for now. const unsigned nC = m_nC; dReal *ptgt = p + nC; const unsigned nN = m_nN; for (unsigned i = 0; i < nN; ++i) { ptgt[i] = dxDot (AROW(i + nC), q, nC); } } void dLCP::pN_plusequals_ANi (dReal *p, unsigned i, bool dir_positive) { const unsigned nC = m_nC; dReal *aptr = AROW(i) + nC; dReal *ptgt = p + nC; if (dir_positive) { const unsigned nN = m_nN; for (unsigned j=0; j < nN; ++j) ptgt[j] += aptr[j]; } else { const unsigned nN = m_nN; for (unsigned j=0; j < nN; ++j) ptgt[j] -= aptr[j]; } } template void dLCP::pC_plusequals_s_times_qC (dReal *p, dReal s, dReal *q) { const unsigned nC = m_nC; dReal *q_end = q + nC; for (; q != q_end; p += p_stride, ++q) { *p += s * (*q); } } void dLCP::pN_plusequals_s_times_qN (dReal *p, dReal s, dReal *q) { const unsigned nC = m_nC; dReal *ptgt = p + nC, *qsrc = q + nC; const unsigned nN = m_nN; for (unsigned i = 0; i < nN; ++i) { ptgt[i] += s * qsrc[i]; } } void dLCP::solve1 (dReal *a, unsigned i, bool dir_positive, int only_transfer) { // the `Dell' and `ell' that are computed here are saved. if index i is // later added to the factorization then they can be reused. // // @@@ question: do we need to solve for entire delta_x??? yes, but // only if an x goes below 0 during the step. const unsigned nC = m_nC; if (nC > 0) { { dReal *Dell = m_Dell; unsigned *C = m_C; dReal *aptr = AROW(i); # ifdef NUB_OPTIMIZATIONS // if nub>0, initial part of aptr[] is guaranteed unpermuted const unsigned nub = m_nub; unsigned j = 0; for ( ; j < nub; ++j) Dell[j] = aptr[j]; for ( ; j < nC; ++j) Dell[j] = aptr[C[j]]; # else for (unsigned j = 0; j < nC; ++j) Dell[j] = aptr[C[j]]; # endif } solveL1Straight<1>(m_L, m_Dell, nC, m_nskip); { dReal *ell = m_ell, *Dell = m_Dell, *d = m_d; for (unsigned j = 0; j < nC; ++j) ell[j] = Dell[j] * d[j]; } if (!only_transfer) { dReal *tmp = m_tmp, *ell = m_ell; { for (unsigned j = 0; j < nC; ++j) tmp[j] = ell[j]; } solveL1Transposed<1>(m_L, tmp, nC, m_nskip); if (dir_positive) { unsigned *C = m_C; dReal *tmp = m_tmp; for (unsigned j = 0; j < nC; ++j) a[C[j]] = -tmp[j]; } else { unsigned *C = m_C; dReal *tmp = m_tmp; for (unsigned j = 0; j < nC; ++j) a[C[j]] = tmp[j]; } } } } void dLCP::unpermute_X() { unsigned *p = m_p; dReal *pairsbx = m_pairsbx; const unsigned n = m_n; for (unsigned j = 0; j < n; ++j) { unsigned k = p[j]; if (k != j) { // p[j] = j; -- not going to be checked anymore anyway dReal x_j = (pairsbx + (sizeint)j * PBX__MAX)[PBX_X]; for (;;) { dxSwap(x_j, (pairsbx + (sizeint)k * PBX__MAX)[PBX_X]); unsigned orig_k = p[k]; p[k] = k; if (orig_k == j) { break; } k = orig_k; } (pairsbx + (sizeint)j * PBX__MAX)[PBX_X] = x_j; } } } void dLCP::unpermute_W() { memcpy (m_tmp, m_w, m_n * sizeof(dReal)); const unsigned *p = m_p; dReal *w = m_w, *tmp = m_tmp; const unsigned n = m_n; for (unsigned j = 0; j < n; ++j) { unsigned k = p[j]; w[k] = tmp[j]; } } #endif // dLCP_FAST static void dxSolveLCP_AllUnbounded (dxWorldProcessMemArena *memarena, unsigned n, dReal *A, dReal pairsbx[PBX__MAX]); static void dxSolveLCP_Generic (dxWorldProcessMemArena *memarena, unsigned n, dReal *A, dReal pairsbx[PBX__MAX], dReal *outer_w/*=NULL*/, unsigned nub, dReal pairslh[PLH__MAX], int *findex); /*extern */ void dxSolveLCP (dxWorldProcessMemArena *memarena, unsigned n, dReal *A, dReal pairsbx[PBX__MAX], dReal *outer_w/*=NULL*/, unsigned nub, dReal pairslh[PLH__MAX], int *findex) { if (nub >= n) { dxSolveLCP_AllUnbounded (memarena, n, A, pairsbx); } else { dxSolveLCP_Generic (memarena, n, A, pairsbx, outer_w, nub, pairslh, findex); } } //*************************************************************************** // if all the variables are unbounded then we can just factor, solve, and return static void dxSolveLCP_AllUnbounded (dxWorldProcessMemArena *memarena, unsigned n, dReal *A, dReal pairsbx[PBX__MAX]) { dAASSERT(A != NULL); dAASSERT(pairsbx != NULL); dAASSERT(n != 0); transfer_b_to_x(pairsbx, n); unsigned nskip = dPAD(n); factorMatrixAsLDLT (A, pairsbx + PBX_B, n, nskip); solveEquationSystemWithLDLT (A, pairsbx + PBX_B, pairsbx + PBX_X, n, nskip); } //*************************************************************************** // an optimized Dantzig LCP driver routine for the lo-hi LCP problem. static void dxSolveLCP_Generic (dxWorldProcessMemArena *memarena, unsigned n, dReal *A, dReal pairsbx[PBX__MAX], dReal *outer_w/*=NULL*/, unsigned nub, dReal pairslh[PLH__MAX], int *findex) { dAASSERT (n > 0 && A && pairsbx && pairslh && nub >= 0 && nub < n); # ifndef dNODEBUG { // check restrictions on lo and hi dReal *endlh = pairslh + (sizeint)n * PLH__MAX; for (dReal *currlh = pairslh; currlh != endlh; currlh += PLH__MAX) dIASSERT (currlh[PLH_LO] <= 0 && currlh[PLH_HI] >= 0); } # endif const unsigned nskip = dPAD(n); dReal *L = memarena->AllocateOveralignedArray ((sizeint)nskip * n, LMATRIX_ALIGNMENT); dReal *d = memarena->AllocateArray (n); dReal *w = outer_w != NULL ? outer_w : memarena->AllocateArray (n); dReal *delta_w = memarena->AllocateArray (n); dReal *delta_x = memarena->AllocateArray (n); dReal *Dell = memarena->AllocateArray (n); dReal *ell = memarena->AllocateArray (n); #ifdef ROWPTRS dReal **Arows = memarena->AllocateArray (n); #else dReal **Arows = NULL; #endif unsigned *p = memarena->AllocateArray (n); unsigned *C = memarena->AllocateArray (n); // for i in N, state[i] is 0 if x(i)==lo(i) or 1 if x(i)==hi(i) bool *state = memarena->AllocateArray (n); // create LCP object. note that tmp is set to delta_w to save space, this // optimization relies on knowledge of how tmp is used, so be careful! dLCP lcp(n, nskip, nub, A, pairsbx, w, pairslh, L, d, Dell, ell, delta_w, state, findex, p, C, Arows); unsigned adj_nub = lcp.getNub(); // loop over all indexes adj_nub..n-1. for index i, if x(i),w(i) satisfy the // LCP conditions then i is added to the appropriate index set. otherwise // x(i),w(i) is driven either +ve or -ve to force it to the valid region. // as we drive x(i), x(C) is also adjusted to keep w(C) at zero. // while driving x(i) we maintain the LCP conditions on the other variables // 0..i-1. we do this by watching out for other x(i),w(i) values going // outside the valid region, and then switching them between index sets // when that happens. bool hit_first_friction_index = false; for (unsigned i = adj_nub; i < n; ++i) { bool s_error = false; // the index i is the driving index and indexes i+1..n-1 are "dont care", // i.e. when we make changes to the system those x's will be zero and we // don't care what happens to those w's. in other words, we only consider // an (i+1)*(i+1) sub-problem of A*x=b+w. // if we've hit the first friction index, we have to compute the lo and // hi values based on the values of x already computed. we have been // permuting the indexes, so the values stored in the findex vector are // no longer valid. thus we have to temporarily unpermute the x vector. // for the purposes of this computation, 0*infinity = 0 ... so if the // contact constraint's normal force is 0, there should be no tangential // force applied. if (!hit_first_friction_index && findex && findex[i] >= 0) { // un-permute x into delta_w, which is not being used at the moment for (unsigned j = 0; j < n; ++j) delta_w[p[j]] = (pairsbx + (sizeint)j * PBX__MAX)[PBX_X]; // set lo and hi values for (unsigned k = i; k < n; ++k) { dReal *currlh = pairslh + (sizeint)k * PLH__MAX; dReal wfk = delta_w[findex[k]]; if (wfk == 0) { currlh[PLH_HI] = 0; currlh[PLH_LO] = 0; } else { currlh[PLH_HI] = dFabs (currlh[PLH_HI] * wfk); currlh[PLH_LO] = -currlh[PLH_HI]; } } hit_first_friction_index = true; } // thus far we have not even been computing the w values for indexes // greater than i, so compute w[i] now. dReal wPrep = lcp.AiC_times_qC (i, pairsbx + PBX_X) + lcp.AiN_times_qN (i, pairsbx + PBX_X); dReal *currbx = pairsbx + (sizeint)i * PBX__MAX; w[i] = wPrep - currbx[PBX_B]; // if lo=hi=0 (which can happen for tangential friction when normals are // 0) then the index will be assigned to set N with some state. however, // set C's line has zero size, so the index will always remain in set N. // with the "normal" switching logic, if w changed sign then the index // would have to switch to set C and then back to set N with an inverted // state. this is pointless, and also computationally expensive. to // prevent this from happening, we use the rule that indexes with lo=hi=0 // will never be checked for set changes. this means that the state for // these indexes may be incorrect, but that doesn't matter. dReal *currlh = pairslh + (sizeint)i * PLH__MAX; // see if x(i),w(i) is in a valid region if (currlh[PLH_LO] == 0 && w[i] >= 0) { lcp.transfer_i_to_N (i); state[i] = false; } else if (currlh[PLH_HI] == 0 && w[i] <= 0) { lcp.transfer_i_to_N (i); state[i] = true; } else if (w[i] == 0) { // this is a degenerate case. by the time we get to this test we know // that lo != 0, which means that lo < 0 as lo is not allowed to be +ve, // and similarly that hi > 0. this means that the line segment // corresponding to set C is at least finite in extent, and we are on it. // NOTE: we must call lcp.solve1() before lcp.transfer_i_to_C() lcp.solve1 (delta_x, i, false, 1); lcp.transfer_i_to_C (i); } else { // we must push x(i) and w(i) for (;;) { // find direction to push on x(i) bool dir_positive = (w[i] <= 0); // compute: delta_x(C) = -dir*A(C,C)\A(C,i) lcp.solve1 (delta_x, i, dir_positive); // note that delta_x[i] = (dir_positive ? 1 : -1), but we wont bother to set it // compute: delta_w = A*delta_x ... note we only care about // delta_w(N) and delta_w(i), the rest is ignored lcp.pN_equals_ANC_times_qC (delta_w, delta_x); lcp.pN_plusequals_ANi (delta_w, i, dir_positive); delta_w[i] = dir_positive ? lcp.AiC_times_qC<1> (i, delta_x) + lcp.Aii(i) : lcp.AiC_times_qC<1> (i, delta_x) - lcp.Aii(i); // find largest step we can take (size=s), either to drive x(i),w(i) // to the valid LCP region or to drive an already-valid variable // outside the valid region. int cmd = 1; // index switching command unsigned si = 0; // si = index to switch if cmd>3 dReal s = delta_w[i] != REAL(0.0) ? -w[i] / delta_w[i] : (w[i] != REAL(0.0) ? dCopySign(dInfinity, -w[i]) : REAL(0.0)); if (dir_positive) { if (currlh[PLH_HI] < dInfinity) { dReal s2 = (currlh[PLH_HI] - currbx[PBX_X]); // was (hi[i]-x[i])/dirf // step to x(i)=hi(i) if (s2 < s) { s = s2; cmd = 3; } } } else { if (currlh[PLH_LO] > -dInfinity) { dReal s2 = (currbx[PBX_X] - currlh[PLH_LO]); // was (lo[i]-x[i])/dirf // step to x(i)=lo(i) if (s2 < s) { s = s2; cmd = 2; } } } { const unsigned numN = lcp.numN(); for (unsigned k = 0; k < numN; ++k) { const unsigned indexN_k = lcp.indexN(k); if (!state[indexN_k] ? delta_w[indexN_k] < 0 : delta_w[indexN_k] > 0) { // don't bother checking if lo=hi=0 dReal *indexlh = pairslh + (sizeint)indexN_k * PLH__MAX; if (indexlh[PLH_LO] == 0 && indexlh[PLH_HI] == 0) continue; dReal s2 = -w[indexN_k] / delta_w[indexN_k]; if (s2 < s) { s = s2; cmd = 4; si = indexN_k; } } } } { const unsigned numC = lcp.numC(); for (unsigned k = adj_nub; k < numC; ++k) { const unsigned indexC_k = lcp.indexC(k); dReal *indexlh = pairslh + (sizeint)indexC_k * PLH__MAX; if (delta_x[indexC_k] < 0 && indexlh[PLH_LO] > -dInfinity) { dReal s2 = (indexlh[PLH_LO] - (pairsbx + (sizeint)indexC_k * PBX__MAX)[PBX_X]) / delta_x[indexC_k]; if (s2 < s) { s = s2; cmd = 5; si = indexC_k; } } if (delta_x[indexC_k] > 0 && indexlh[PLH_HI] < dInfinity) { dReal s2 = (indexlh[PLH_HI] - (pairsbx + (sizeint)indexC_k * PBX__MAX)[PBX_X]) / delta_x[indexC_k]; if (s2 < s) { s = s2; cmd = 6; si = indexC_k; } } } } //static char* cmdstring[8] = {0,"->C","->NL","->NH","N->C", // "C->NL","C->NH"}; //printf ("cmd=%d (%s), si=%d\n",cmd,cmdstring[cmd],(cmd>3) ? si : i); // if s <= 0 then we've got a problem. if we just keep going then // we're going to get stuck in an infinite loop. instead, just cross // our fingers and exit with the current solution. if (s <= REAL(0.0)) { dMessage (d_ERR_LCP, "LCP internal error, s <= 0 (s=%.4e)",(double)s); if (i < n) { dxtSetZero(currbx + PBX_X, n - i); dxSetZero (w + i, n - i); } s_error = true; break; } // apply x = x + s * delta_x lcp.pC_plusequals_s_times_qC (pairsbx + PBX_X, s, delta_x); currbx[PBX_X] = dir_positive ? currbx[PBX_X] + s : currbx[PBX_X] - s; // apply w = w + s * delta_w lcp.pN_plusequals_s_times_qN (w, s, delta_w); w[i] += s * delta_w[i]; void *tmpbuf; // switch indexes between sets if necessary switch (cmd) { case 1: // done w[i] = 0; lcp.transfer_i_to_C (i); break; case 2: // done currbx[PBX_X] = currlh[PLH_LO]; state[i] = false; lcp.transfer_i_to_N (i); break; case 3: // done currbx[PBX_X] = currlh[PLH_HI]; state[i] = true; lcp.transfer_i_to_N (i); break; case 4: // keep going w[si] = 0; lcp.transfer_i_from_N_to_C (si); break; case 5: // keep going (pairsbx + (sizeint)si * PBX__MAX)[PBX_X] = (pairslh + (sizeint)si * PLH__MAX)[PLH_LO]; state[si] = false; tmpbuf = memarena->PeekBufferRemainder(); lcp.transfer_i_from_C_to_N (si, tmpbuf); break; case 6: // keep going (pairsbx + (sizeint)si * PBX__MAX)[PBX_X] = (pairslh + (sizeint)si * PLH__MAX)[PLH_HI]; state[si] = true; tmpbuf = memarena->PeekBufferRemainder(); lcp.transfer_i_from_C_to_N (si, tmpbuf); break; } if (cmd <= 3) break; } // for (;;) } // else if (s_error) { break; } } // for (unsigned i = adj_nub; i < n; ++i) // now we have to un-permute x and w if (outer_w != NULL) { lcp.unpermute_W(); } lcp.unpermute_X(); // This destroys p[] and must be done last } sizeint dxEstimateSolveLCPMemoryReq(unsigned n, bool outer_w_avail) { const unsigned nskip = dPAD(n); sizeint res = 0; res += dOVERALIGNED_SIZE(sizeof(dReal) * ((sizeint)n * nskip), LMATRIX_ALIGNMENT); // for L res += 5 * dEFFICIENT_SIZE(sizeof(dReal) * n); // for d, delta_w, delta_x, Dell, ell if (!outer_w_avail) { res += dEFFICIENT_SIZE(sizeof(dReal) * n); // for w } #ifdef ROWPTRS res += dEFFICIENT_SIZE(sizeof(dReal *) * n); // for Arows #endif res += 2 * dEFFICIENT_SIZE(sizeof(unsigned) * n); // for p, C res += dEFFICIENT_SIZE(sizeof(bool) * n); // for state // Use n instead of nC as nC varies at runtime while n is greater or equal to nC sizeint lcp_transfer_req = dLCP::estimate_transfer_i_from_C_to_N_mem_req(n, nskip); res += dEFFICIENT_SIZE(lcp_transfer_req); // for dLCP::transfer_i_from_C_to_N return res; } //*************************************************************************** // accuracy and timing test static sizeint EstimateTestSolveLCPMemoryReq(unsigned n) { const unsigned nskip = dPAD(n); sizeint res = 0; res += 2 * dEFFICIENT_SIZE(sizeof(dReal) * ((sizeint)n * nskip)); // for A, A2 res += 7 * dEFFICIENT_SIZE(sizeof(dReal) * n); // for x, b, w, lo, hi, tmp1, tmp2 res += dEFFICIENT_SIZE(sizeof(dReal) * PBX__MAX * n); // for pairsbx, res += dEFFICIENT_SIZE(sizeof(dReal) * PLH__MAX * n); // for pairslh res += dxEstimateSolveLCPMemoryReq(n, true); return res; } extern "C" ODE_API int dTestSolveLCP() { const unsigned n = 100; sizeint memreq = EstimateTestSolveLCPMemoryReq(n); dxWorldProcessMemArena *arena = dxAllocateTemporaryWorldProcessMemArena(memreq, NULL, NULL); if (arena == NULL) { return 0; } arena->ResetState(); unsigned i,nskip = dPAD(n); #ifdef dDOUBLE const dReal tol = REAL(1e-9); #endif #ifdef dSINGLE const dReal tol = REAL(1e-4); #endif printf ("dTestSolveLCP()\n"); dReal *A = arena->AllocateArray (n*nskip); dReal *x = arena->AllocateArray (n); dReal *b = arena->AllocateArray (n); dReal *w = arena->AllocateArray (n); dReal *lo = arena->AllocateArray (n); dReal *hi = arena->AllocateArray (n); dReal *A2 = arena->AllocateArray (n*nskip); dReal *pairsbx = arena->AllocateArray (n * PBX__MAX); dReal *pairslh = arena->AllocateArray (n * PLH__MAX); dReal *tmp1 = arena->AllocateArray (n); dReal *tmp2 = arena->AllocateArray (n); double total_time = 0; for (unsigned count=0; count < 1000; count++) { BEGIN_STATE_SAVE(arena, saveInner) { // form (A,b) = a random positive definite LCP problem dMakeRandomMatrix (A2,n,n,1.0); dMultiply2 (A,A2,A2,n,n,n); dMakeRandomMatrix (x,n,1,1.0); dMultiply0 (b,A,x,n,n,1); for (i=0; i tol ? "FAILED" : "passed"); if (diff > tol) dDebug (0,"A*x = b+w, maximum difference = %.6e",diff); unsigned n1=0,n2=0,n3=0; for (i=0; i= 0) { n1++; // ok } else if (x[i]==hi[i] && w[i] <= 0) { n2++; // ok } else if (x[i] >= lo[i] && x[i] <= hi[i] && w[i] == 0) { n3++; // ok } else { dDebug (0,"FAILED: i=%d x=%.4e w=%.4e lo=%.4e hi=%.4e",i, x[i],w[i],lo[i],hi[i]); } } // pacifier printf ("passed: NL=%3d NH=%3d C=%3d ",n1,n2,n3); printf ("time=%10.3f ms avg=%10.4f\n",time * 1000.0,average); } END_STATE_SAVE(arena, saveInner); } dxFreeTemporaryWorldProcessMemArena(arena); return 1; } ode-0.16/ode/src/collision_trimesh_internal.h0000664000175200017520000003442313403272463016301 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ // TriMesh code by Erwin de Vries. // Modified for FreeSOLID Compatibility by Rodrigo Hernandez // TriMesh caches separation by Oleh Derevenko // TriMesh storage classes refactoring and face angle computation code by Oleh Derevenko (C) 2016-2017 #ifndef _ODE_COLLISION_TRIMESH_INTERNAL_H_ #define _ODE_COLLISION_TRIMESH_INTERNAL_H_ //**************************************************************************** // dxTriMesh class #include "collision_kernel.h" #include "collision_trimesh_colliders.h" #include "collision_util.h" #include #if dTLS_ENABLED #include "odetls.h" #endif struct TrimeshCollidersCache; struct dxTriMeshData; static inline TrimeshCollidersCache *GetTrimeshCollidersCache(unsigned uiTLSKind) { #if dTLS_ENABLED EODETLSKIND tkTLSKind = (EODETLSKIND)uiTLSKind; return COdeTls::GetTrimeshCollidersCache(tkTLSKind); #else // dTLS_ENABLED (void)uiTLSKind; // unused extern TrimeshCollidersCache g_ccTrimeshCollidersCache; return &g_ccTrimeshCollidersCache; #endif // dTLS_ENABLED } enum FaceAngleStorageMethod { ASM__MIN, ASM_BYTE_SIGNED = ASM__MIN, ASM_BYTE_POSITIVE, ASM_WORD_SIGNED, ASM__MAX, ASM__INVALID = ASM__MAX, }; enum FaceAngleDomain { FAD__MIN, FAD_CONCAVE = FAD__MIN, FAD__SIGNSTORED_IMPLICITVALUE_MIN, FAD_FLAT = FAD__SIGNSTORED_IMPLICITVALUE_MIN, FAD__SIGNSTORED_IMPLICITVALUE_MAX, FAD__BYTEPOS_STORED_MIN = FAD__SIGNSTORED_IMPLICITVALUE_MAX, FAD_CONVEX = FAD__BYTEPOS_STORED_MIN, FAD__BYTEPOS_STORED_MAX, EAD__MAX = FAD__BYTEPOS_STORED_MAX, }; class IFaceAngleStorageControl { public: virtual void disposeStorage() = 0; virtual bool areNegativeAnglesStored() const = 0; // This is to store angles between neighbor triangle normals as positive value for convex and negative for concave edges virtual void assignFacesAngleIntoStorage(unsigned triangleIndex, dMeshTriangleVertex vertexIndex, dReal dAngleValue) = 0; }; class IFaceAngleStorageView { public: virtual FaceAngleDomain retrieveFacesAngleFromStorage(dReal &out_AngleValue, unsigned triangleIndex, dMeshTriangleVertex vertexIndex) = 0; }; typedef dBase dxTriDataBase_Parent; struct dxTriDataBase: public dxTriDataBase_Parent { public: dxTriDataBase(): dxTriDataBase_Parent(), m_vertices(NULL), m_vertexStride(0), m_vertexCount(0), m_indices(NULL), m_triangleCount(0), m_triStride(0), m_single(false), m_normals(NULL), m_faceAngles(NULL), m_faceAngleView(NULL) { #if !dTRIMESH_ENABLED dUASSERT(false, "dTRIMESH_ENABLED is not defined. Trimesh geoms will not work"); #endif } ~dxTriDataBase(); void buildData(const void *Vertices, int VertexStide, unsigned VertexCount, const void *Indices, unsigned IndexCount, int TriStride, const void *Normals, bool Single); public: unsigned retrieveVertexCount() const { return m_vertexCount; } int retrieveVertexStride() const { return m_vertexStride; } unsigned retrieveTriangleCount() const { return m_triangleCount; } int retrieveTriangleStride() const { return m_triStride; } protected: const void *retrieveVertexInstances() const { return m_vertices; } const void *retrieveTriangleVertexIndices() const { return m_indices; } bool isSingle() const { return m_single; } public: template static void retrieveTriangleVertexPoints(dVector3 out_Points[dMTV__MAX], unsigned triangleIndex, const tcoordfloat *vertexInstances, int vertexStride, const tindexint *triangleVertexIndices, int triangleStride); public: void assignNormals(const void *normals) { m_normals = normals; } const void *retrieveNormals() const { return m_normals; } IFaceAngleStorageControl *retrieveFaceAngles() const { return m_faceAngles; } IFaceAngleStorageView *retrieveFaceAngleView() const { return m_faceAngleView; } protected: bool allocateFaceAngles(FaceAngleStorageMethod storageMethod); void freeFaceAngles(); bool haveFaceAnglesBeenBuilt() const { return m_faceAngles != NULL; } public: enum MeshComponentUseFlags { CUF__USE_EDGES_MIN = 0x01, CUF_USE_FIRST_EDGE = CUF__USE_EDGES_MIN << dMTV_FIRST, CUF_USE_SECOND_EDGE = CUF__USE_EDGES_MIN << dMTV_SECOND, CUF_USE_THIRD_EDGE = CUF__USE_EDGES_MIN << dMTV_THIRD, CUF__USE_EDGES_MAX = CUF__USE_EDGES_MIN << dMTV__MAX, CUF__USE_ALL_EDGES = CUF_USE_FIRST_EDGE | CUF_USE_SECOND_EDGE | CUF_USE_THIRD_EDGE, CUF__USE_VERTICES_MIN = CUF__USE_EDGES_MAX, CUF_USE_FIRST_VERTEX = CUF__USE_VERTICES_MIN << dMTV_FIRST, CUF_USE_SECOND_VERTEX = CUF__USE_VERTICES_MIN << dMTV_SECOND, CUF_USE_THIRD_VERTEX = CUF__USE_VERTICES_MIN << dMTV_THIRD, CUF__USE_VERTICES_LAST = CUF__USE_VERTICES_MIN << (dMTV__MAX - 1), CUF__USE_VERTICES_MAX = CUF__USE_VERTICES_MIN << dMTV__MAX, CUF__USE_ALL_VERTICES = CUF_USE_FIRST_VERTEX | CUF_USE_SECOND_VERTEX | CUF_USE_THIRD_VERTEX, CUF__USE_ALL_COMPONENTS = CUF__USE_ALL_VERTICES | CUF__USE_ALL_EDGES, }; // Make sure that the flags match the values declared in public interface dSASSERT((unsigned)CUF_USE_FIRST_EDGE == dMESHDATAUSE_EDGE1); dSASSERT((unsigned)CUF_USE_SECOND_EDGE == dMESHDATAUSE_EDGE2); dSASSERT((unsigned)CUF_USE_THIRD_EDGE == dMESHDATAUSE_EDGE3); dSASSERT((unsigned)CUF_USE_FIRST_VERTEX == dMESHDATAUSE_VERTEX1); dSASSERT((unsigned)CUF_USE_SECOND_VERTEX == dMESHDATAUSE_VERTEX2); dSASSERT((unsigned)CUF_USE_THIRD_VERTEX == dMESHDATAUSE_VERTEX3); protected: struct EdgeRecord { public: void setupEdge(dMeshTriangleVertex edgeIdx, int triIdx, const unsigned vertexIndices[dMTV__MAX]); // Get the vertex opposite this edge in the triangle dMeshTriangleVertex getOppositeVertexIndex() const { extern const CEnumUnsortedElementArray g_VertFlagOppositeIndices; dMeshTriangleVertex oppositeIndex = g_VertFlagOppositeIndices.Encode(((m_vert1Flags | m_vert2Flags) ^ CUF__USE_ALL_VERTICES) / CUF__USE_VERTICES_MIN - 1); dIASSERT(dIN_RANGE(oppositeIndex, dMTV__MIN, dMTV__MAX)); return oppositeIndex; } dMeshTriangleVertex getEdgeStartVertexIndex() const { extern const CEnumUnsortedElementArray g_VertFlagEdgeStartIndices; dMeshTriangleVertex startIndex = g_VertFlagEdgeStartIndices.Encode(((m_vert1Flags | m_vert2Flags) ^ CUF__USE_ALL_VERTICES) / CUF__USE_VERTICES_MIN - 1); dIASSERT(dIN_RANGE(startIndex, dMTV__MIN, dMTV__MAX)); return startIndex; } public: bool operator <(const EdgeRecord &anotherEdge) const { return m_vertIdx1 < anotherEdge.m_vertIdx1 || (m_vertIdx1 == anotherEdge.m_vertIdx1 && m_vertIdx2 < anotherEdge.m_vertIdx2); } public: enum { AVF_VERTEX_USED = 0x01, AVF_VERTEX_HAS_CONCAVE_EDGE = 0x02, }; public: unsigned m_vertIdx1; // Index into vertex array for this edges vertices unsigned m_vertIdx2; unsigned m_triIdx; // Index into triangle array for triangle this edge belongs to uint8 m_edgeFlags; uint8 m_vert1Flags; uint8 m_vert2Flags; uint8 m_absVertexFlags; }; struct VertexRecord { unsigned m_UsedFromEdgeIndex; }; template static void meaningfulPreprocess_SetupEdgeRecords(EdgeRecord *edges, sizeint numEdges, const TMeshDataAccessor &dataAccessor); template static void meaningfulPreprocess_buildEdgeFlags(uint8 *useFlags/*=NULL*/, IFaceAngleStorageControl *faceAngles/*=NULL*/, EdgeRecord *edges, sizeint numEdges, VertexRecord *vertices, const dReal *externalNormals, const TMeshDataAccessor &dataAccessor); static void buildBoundaryEdgeAngle(IFaceAngleStorageControl *faceAngles, EdgeRecord *currEdge); template static void buildConcaveEdgeAngle(IFaceAngleStorageControl *faceAngles, bool negativeAnglesStored, EdgeRecord *currEdge, const dReal &normalSegmentDot, const dReal &lengthSquareProduct, const dVector3 &triangleNormal, const dVector3 &secondOppositeVertexSegment, const dVector3 *pSecondTriangleMatchingEdge/*=NULL*/, const dVector3 *pFirstTriangle/*=NULL*/, const TMeshDataAccessor &dataAccessor); template static void buildConvexEdgeAngle(IFaceAngleStorageControl *faceAngles, EdgeRecord *currEdge, const dReal &normalSegmentDot, const dReal &lengthSquareProduct, const dVector3 &triangleNormal, const dVector3 &secondOppositeVertexSegment, const dVector3 *pSecondTriangleMatchingEdge/*=NULL*/, const dVector3 *pFirstTriangle/*=NULL*/, const TMeshDataAccessor &dataAccessor); template static dReal calculateEdgeAngleValidated(unsigned firstVertexStartIndex, EdgeRecord *currEdge, const dReal &normalSegmentDot, const dReal &lengthSquareProduct, const dVector3 &triangleNormal, const dVector3 &secondOppositeVertexSegment, const dVector3 *pSecondTriangleMatchingEdge/*=NULL*/, const dVector3 *pFirstTriangle/*=NULL*/, const TMeshDataAccessor &dataAccessor); private: const void *m_vertices; int m_vertexStride; unsigned m_vertexCount; const void *m_indices; unsigned m_triangleCount; int m_triStride; bool m_single; private: const void *m_normals; IFaceAngleStorageControl *m_faceAngles; IFaceAngleStorageView *m_faceAngleView; }; typedef dxGeom dxMeshBase_Parent; struct dxMeshBase: public dxMeshBase_Parent { public: dxMeshBase(dxSpace *Space, dxTriDataBase *Data, dTriCallback *Callback, dTriArrayCallback *ArrayCallback, dTriRayCallback *RayCallback, bool doTCs=false): dxMeshBase_Parent(Space, 1), m_Callback(Callback), m_ArrayCallback(ArrayCallback), m_RayCallback(RayCallback), m_TriMergeCallback(NULL), m_Data(Data) { std::fill(m_DoTCs, m_DoTCs + dARRAY_SIZE(m_DoTCs), doTCs); type = dTriMeshClass; } bool invokeCallback(dxGeom *Object, int TriIndex) { return m_Callback == NULL || m_Callback(this, Object, TriIndex) != 0; } public: enum TRIMESHTC { TTC__MIN, TTC_SPHERE = TTC__MIN, TTC_BOX, TTC_CAPSULE, TTC__MAX, }; public: void assignCallback(dTriCallback *value) { m_Callback = value; } dTriCallback *retrieveCallback() const { return m_Callback; } void assignArrayCallback(dTriArrayCallback *value) { m_ArrayCallback = value; } dTriArrayCallback *retrieveArrayCallback() const { return m_ArrayCallback; } void assignRayCallback(dTriRayCallback *value) { m_RayCallback = value; } dTriRayCallback *retrieveRayCallback() const { return m_RayCallback; } void assignTriMergeCallback(dTriTriMergeCallback *value) { m_TriMergeCallback = value; } dTriTriMergeCallback *retrieveTriMergeCallback() const { return m_TriMergeCallback; } void assignMeshData(dxTriDataBase *instance) { setMeshData(instance); // I changed my data -- I know nothing about my own AABB anymore. markAABBBad(); } dxTriDataBase *retrieveMeshData() const { return getMeshData(); } IFaceAngleStorageControl *retrieveFaceAngleStorage() const { return m_Data->retrieveFaceAngles(); } IFaceAngleStorageView *retrieveFaceAngleView() const { return m_Data->retrieveFaceAngleView(); } void assignDoTC(TRIMESHTC tc, bool value) { setDoTC(tc, value); } bool retrieveDoTC(TRIMESHTC tc) const { return getDoTC(tc); } public: void setDoTC(TRIMESHTC tc, bool value) { dIASSERT(dIN_RANGE(tc, TTC__MIN, TTC__MAX)); m_DoTCs[tc] = value; } bool getDoTC(TRIMESHTC tc) const { dIASSERT(dIN_RANGE(tc, TTC__MIN, TTC__MAX)); return m_DoTCs[tc]; } private: void setMeshData(dxTriDataBase *Data) { m_Data = Data; } protected: dxTriDataBase *getMeshData() const { return m_Data; } public: // Callbacks dTriCallback *m_Callback; dTriArrayCallback *m_ArrayCallback; dTriRayCallback *m_RayCallback; dTriTriMergeCallback *m_TriMergeCallback; private: // Data types dxTriDataBase *m_Data; public: bool m_DoTCs[TTC__MAX]; }; IFaceAngleStorageView *dxGeomTriMeshGetFaceAngleView(dxGeom *triMeshGeom); #include "collision_trimesh_gimpact.h" #include "collision_trimesh_opcode.h" #endif //_ODE_COLLISION_TRIMESH_INTERNAL_H_ ode-0.16/ode/src/threading_atomics_provs.h0000664000175200017520000001570213403272463015573 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * Threading atomics providers file. * * Copyright (C) 2011-2012 Oleh Derevenko. All rights reserved. * * e-mail: odar@eleks.com (change all "a" to "e") * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* * Fake atomics provider for built-in threading support provider. * OU-based atomics provider for built-in threading support provider. * * The classes have been moved into a separate header as they are to be used * in both WIN and POSIX implementations. */ #ifndef _ODE_THREADING_ATOMICS_PROVS_H_ #define _ODE_THREADING_ATOMICS_PROVS_H_ #include #include /************************************************************************/ /* Fake atomics provider class implementation */ /************************************************************************/ class dxFakeAtomicsProvider { public: typedef unsigned long atomicord_t; typedef void *atomicptr_t; public: static void IncrementTargetNoRet(volatile atomicord_t *value_accumulator_ptr) { ++(*value_accumulator_ptr); } static void DecrementTargetNoRet(volatile atomicord_t *value_accumulator_ptr) { --(*value_accumulator_ptr); } static atomicord_t QueryTargetValue(volatile atomicord_t *value_storage_ptr) { return *value_storage_ptr; } template static sizeint AddValueToTarget(volatile void *value_accumulator_ptr, diffint value_addend); static bool CompareExchangeTargetPtr(volatile atomicptr_t *pointer_storage_ptr, atomicptr_t comparand_value, atomicptr_t new_value) { bool exchange_result = false; atomicptr_t original_value = *pointer_storage_ptr; if (original_value == comparand_value) { *pointer_storage_ptr = new_value; exchange_result = true; } return exchange_result; } }; template<> inline sizeint dxFakeAtomicsProvider::AddValueToTarget(volatile void *value_accumulator_ptr, diffint value_addend) { atomicord_t original_value = *(volatile atomicord_t *)value_accumulator_ptr; *(volatile atomicord_t *)value_accumulator_ptr = original_value + (atomicord_t)value_addend; return original_value; } template<> inline sizeint dxFakeAtomicsProvider::AddValueToTarget<2 * sizeof(dxFakeAtomicsProvider::atomicord_t)>(volatile void *value_accumulator_ptr, diffint value_addend) { atomicptr_t original_value = *(volatile atomicptr_t *)value_accumulator_ptr; *(volatile atomicptr_t *)value_accumulator_ptr = (atomicptr_t)((sizeint)original_value + (sizeint)value_addend); return (sizeint)original_value; } #if dBUILTIN_THREADING_IMPL_ENABLED /************************************************************************/ /* dxOUAtomicsProvider class implementation */ /************************************************************************/ #if !dOU_ENABLED #error OU library must be enabled for this to compile #elif !dATOMICS_ENABLED #error OU Atomics must be enabled for this to compile #endif #include "odeou.h" class dxOUAtomicsProvider { public: typedef _OU_NAMESPACE::atomicord32 atomicord_t; typedef _OU_NAMESPACE::atomicptr atomicptr_t; public: static void IncrementTargetNoRet(volatile atomicord_t *value_accumulator_ptr) { _OU_NAMESPACE::AtomicIncrementNoResult(value_accumulator_ptr); } static void DecrementTargetNoRet(volatile atomicord_t *value_accumulator_ptr) { _OU_NAMESPACE::AtomicDecrementNoResult(value_accumulator_ptr); } static atomicord_t QueryTargetValue(volatile atomicord_t *value_storage_ptr) { // Query value with memory barrier before atomicord_t result_value = *value_storage_ptr; if (!_OU_NAMESPACE::AtomicCompareExchange(value_storage_ptr, result_value, result_value)) { result_value = *value_storage_ptr; } return result_value; } template static sizeint AddValueToTarget(volatile void *value_accumulator_ptr, diffint value_addend); static bool CompareExchangeTargetPtr(volatile atomicptr_t *pointer_storage_ptr, atomicptr_t comparand_value, atomicptr_t new_value) { return _OU_NAMESPACE::AtomicCompareExchangePointer(pointer_storage_ptr, comparand_value, new_value); } }; template<> inline sizeint dxOUAtomicsProvider::AddValueToTarget(volatile void *value_accumulator_ptr, diffint value_addend) { return _OU_NAMESPACE::AtomicExchangeAdd((volatile atomicord_t *)value_accumulator_ptr, (atomicord_t)value_addend); } template<> inline sizeint dxOUAtomicsProvider::AddValueToTarget<2 * sizeof(dxOUAtomicsProvider::atomicord_t)>(volatile void *value_accumulator_ptr, diffint value_addend) { atomicptr_t original_value; while (true) { original_value = *(volatile atomicptr_t *)value_accumulator_ptr; atomicptr_t new_value = (atomicptr_t)((sizeint)original_value + (sizeint)value_addend); if (_OU_NAMESPACE::AtomicCompareExchangePointer((volatile atomicptr_t *)value_accumulator_ptr, original_value, new_value)) { break; } } return (sizeint)original_value; } #endif // #if dBUILTIN_THREADING_IMPL_ENABLED #endif // #ifndef _ODE_THREADING_ATOMICS_PROVS_H_ ode-0.16/ode/src/collision_trimesh_ray.cpp0000664000175200017520000001754013403272463015614 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ // TriMesh code by Erwin de Vries. #include #include #include "config.h" #include "matrix.h" #include "odemath.h" #if dTRIMESH_ENABLED #include "collision_util.h" #include "collision_trimesh_internal.h" #if dTRIMESH_OPCODE int dCollideRTL(dxGeom* g1, dxGeom* RayGeom, int Flags, dContactGeom* Contacts, int Stride){ dIASSERT (Stride >= (int)sizeof(dContactGeom)); dIASSERT (g1->type == dTriMeshClass); dIASSERT (RayGeom->type == dRayClass); dIASSERT ((Flags & NUMC_MASK) >= 1); dxTriMesh* TriMesh = (dxTriMesh*)g1; const unsigned uiTLSKind = TriMesh->getParentSpaceTLSKind(); dIASSERT(uiTLSKind == RayGeom->getParentSpaceTLSKind()); // The colliding spaces must use matching cleanup method TrimeshCollidersCache *pccColliderCache = GetTrimeshCollidersCache(uiTLSKind); RayCollider& Collider = pccColliderCache->m_RayCollider; dReal Length = dGeomRayGetLength(RayGeom); int FirstContact = dGeomRayGetFirstContact(RayGeom); int BackfaceCull = dGeomRayGetBackfaceCull(RayGeom); int ClosestHit = dGeomRayGetClosestHit(RayGeom); Collider.SetFirstContact(FirstContact != 0); Collider.SetClosestHit(ClosestHit != 0); Collider.SetCulling(BackfaceCull != 0); Collider.SetMaxDist(Length); const dVector3& TLPosition = *(const dVector3*)dGeomGetPosition(TriMesh); const dMatrix3& TLRotation = *(const dMatrix3*)dGeomGetRotation(TriMesh); Matrix4x4 MeshMatrix; const dVector3 ZeroVector3 = { REAL(0.0), }; MakeMatrix(ZeroVector3, TLRotation, MeshMatrix); dVector3 Origin, Direction; dGeomRayGet(RayGeom, Origin, Direction); dVector3 OffsetOrigin; dSubtractVectors3(OffsetOrigin, Origin, TLPosition); /* Make Ray */ Ray WorldRay; WorldRay.mOrig.Set(OffsetOrigin[0], OffsetOrigin[1], OffsetOrigin[2]); WorldRay.mDir.Set(Direction[0], Direction[1], Direction[2]); /* Intersect */ int TriCount = 0; if (Collider.Collide(WorldRay, TriMesh->retrieveMeshBVTreeRef(), &MeshMatrix)) { TriCount = pccColliderCache->m_Faces.GetNbFaces(); } if (TriCount == 0) { return 0; } const CollisionFace* Faces = pccColliderCache->m_Faces.GetFaces(); int OutTriCount = 0; for (int i = 0; i < TriCount; i++) { if (TriMesh->m_RayCallback == null || TriMesh->m_RayCallback(TriMesh, RayGeom, Faces[i].mFaceID, Faces[i].mU, Faces[i].mV)) { const int& TriIndex = Faces[i].mFaceID; if (!TriMesh->invokeCallback(RayGeom, TriIndex)) { continue; } dContactGeom* Contact = SAFECONTACT(Flags, Contacts, OutTriCount, Stride); dVector3 dv[3]; TriMesh->fetchMeshTriangle(dv, TriIndex, TLPosition, TLRotation); dVector3 vu; vu[0] = dv[1][0] - dv[0][0]; vu[1] = dv[1][1] - dv[0][1]; vu[2] = dv[1][2] - dv[0][2]; vu[3] = REAL(0.0); dVector3 vv; vv[0] = dv[2][0] - dv[0][0]; vv[1] = dv[2][1] - dv[0][1]; vv[2] = dv[2][2] - dv[0][2]; vv[3] = REAL(0.0); dCalcVectorCross3(Contact->normal, vv, vu); // Reversed // Even though all triangles might be initially valid, // a triangle may degenerate into a segment after applying // space transformation. if (dSafeNormalize3(Contact->normal)) { // No sense to save on single type conversion in algorithm of this size. // If there would be a custom typedef for distance type it could be used // instead of dReal. However using float directly is the loss of abstraction // and possible loss of precision in future. /*float*/ dReal T = Faces[i].mDistance; Contact->pos[0] = Origin[0] + (Direction[0] * T); Contact->pos[1] = Origin[1] + (Direction[1] * T); Contact->pos[2] = Origin[2] + (Direction[2] * T); Contact->pos[3] = REAL(0.0); Contact->depth = T; Contact->g1 = TriMesh; Contact->g2 = RayGeom; Contact->side1 = TriIndex; Contact->side2 = -1; OutTriCount++; // Putting "break" at the end of loop prevents unnecessary checks on first pass and "continue" if (OutTriCount >= (Flags & NUMC_MASK)) { break; } } } } return OutTriCount; } #endif // dTRIMESH_OPCODE #if dTRIMESH_GIMPACT int dCollideRTL(dxGeom* g1, dxGeom* RayGeom, int Flags, dContactGeom* Contacts, int Stride) { dIASSERT (Stride >= (int)sizeof(dContactGeom)); dIASSERT (g1->type == dTriMeshClass); dIASSERT (RayGeom->type == dRayClass); dIASSERT ((Flags & NUMC_MASK) >= 1); dxTriMesh* TriMesh = (dxTriMesh*)g1; dReal Length = dGeomRayGetLength(RayGeom); int FirstContact = dGeomRayGetFirstContact(RayGeom); int BackfaceCull = dGeomRayGetBackfaceCull(RayGeom); int ClosestHit = dGeomRayGetClosestHit(RayGeom); dVector3 Origin, Direction; dGeomRayGet(RayGeom, Origin, Direction); char intersect=0; GIM_TRIANGLE_RAY_CONTACT_DATA contact_data; if(ClosestHit) { intersect = gim_trimesh_ray_closest_collisionODE(&TriMesh->m_collision_trimesh,Origin,Direction,Length,&contact_data); } else { intersect = gim_trimesh_ray_collisionODE(&TriMesh->m_collision_trimesh,Origin,Direction,Length,&contact_data); } if(intersect == 0) { return 0; } if(!TriMesh->m_RayCallback || TriMesh->m_RayCallback(TriMesh, RayGeom, contact_data.m_face_id, contact_data.u , contact_data.v)) { dContactGeom* Contact = &( Contacts[ 0 ] ); VEC_COPY(Contact->pos,contact_data.m_point); VEC_COPY(Contact->normal,contact_data.m_normal); Contact->depth = contact_data.tparam; Contact->g1 = TriMesh; Contact->g2 = RayGeom; Contact->side1 = contact_data.m_face_id; Contact->side2 = -1; return 1; } return 0; } #endif // dTRIMESH_GIMPACT #endif // dTRIMESH_ENABLED ode-0.16/ode/src/fastlsolve.cpp0000664000175200017520000002406513403272463013375 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* * L1Straight Equation Solving Routines * Copyright (c) 2017 Oleh Derevenko, odar@eleks.com (change all "a" to "e") */ #include #include #include #include "config.h" #include "threaded_solver_ldlt.h" #include "threading_base.h" #include "resource_control.h" #include "error.h" #include "fastlsolve_impl.h" /*static */ void ThreadedEquationSolverLDLT::estimateCooperativeSolvingL1StraightResourceRequirements( dxResourceRequirementDescriptor *summaryRequirementsDescriptor, unsigned allowedThreadCount, unsigned rowCount) { dxThreadingBase *threading = summaryRequirementsDescriptor->getrelatedThreading(); unsigned limitedThreadCount = restrictSolvingL1StraightAllowedThreadCount(threading, allowedThreadCount, rowCount); if (limitedThreadCount > 1) { doEstimateCooperativeSolvingL1StraightResourceRequirementsValidated(summaryRequirementsDescriptor, allowedThreadCount, rowCount); } } /*static */ void ThreadedEquationSolverLDLT::cooperativelySolveL1Straight( dxRequiredResourceContainer *resourceContainer, unsigned allowedThreadCount, const dReal *L, dReal *b, unsigned rowCount, unsigned rowSkip) { dAASSERT(rowCount != 0); dxThreadingBase *threading = resourceContainer->getThreadingInstance(); unsigned limitedThreadCount = restrictSolvingL1StraightAllowedThreadCount(threading, allowedThreadCount, rowCount); if (limitedThreadCount <= 1) { solveL1Straight(L, b, rowCount, rowSkip); } else { doCooperativelySolveL1StraightValidated(resourceContainer, limitedThreadCount, L, b, rowCount, rowSkip); } } /*static */ unsigned ThreadedEquationSolverLDLT::restrictSolvingL1StraightAllowedThreadCount( dxThreadingBase *threading, unsigned allowedThreadCount, unsigned rowCount) { unsigned limitedThreadCount = 1; #if dCOOPERATIVE_ENABLED const unsigned int blockStep = SL1S_BLOCK_SIZE; // Required by the implementation unsigned solvingBlockCount = deriveSolvingL1StraightBlockCount(rowCount, blockStep); dIASSERT(deriveSolvingL1StraightThreadCount(SL1S_COOPERATIVE_BLOCK_COUNT_MINIMUM, 2) > 1); if (solvingBlockCount >= SL1S_COOPERATIVE_BLOCK_COUNT_MINIMUM) { limitedThreadCount = threading->calculateThreadingLimitedThreadCount(allowedThreadCount, true); } #endif // #if dCOOPERATIVE_ENABLED return limitedThreadCount; } /*static */ void ThreadedEquationSolverLDLT::doEstimateCooperativeSolvingL1StraightResourceRequirementsValidated( dxResourceRequirementDescriptor *summaryRequirementsDescriptor, unsigned allowedThreadCount, unsigned rowCount) { const unsigned int blockStep = SL1S_BLOCK_SIZE; // Required by the implementation unsigned blockCount = deriveSolvingL1StraightBlockCount(rowCount, blockStep); dIASSERT(blockCount >= 1); unsigned threadCountToUse = deriveSolvingL1StraightThreadCount(blockCount, allowedThreadCount); dIASSERT(threadCountToUse > 1); unsigned simultaneousCallCount = 1 + (threadCountToUse - 1); SolvingL1StraightMemoryEstimates solvingMemoryEstimates; sizeint solvingMemoryRequired = estimateCooperativelySolvingL1StraightMemoryRequirement(rowCount, solvingMemoryEstimates); const unsigned solvingAlignmentRequired = ALLOCATION_DEFAULT_ALIGNMENT; unsigned featureRequirement = dxResourceRequirementDescriptor::STOCK_CALLWAIT_REQUIRED; summaryRequirementsDescriptor->mergeAnotherDescriptorIn(solvingMemoryRequired, solvingAlignmentRequired, simultaneousCallCount, featureRequirement); } /*static */ void ThreadedEquationSolverLDLT::doCooperativelySolveL1StraightValidated( dxRequiredResourceContainer *resourceContainer, unsigned allowedThreadCount, const dReal *L, dReal *b, unsigned rowCount, unsigned rowSkip) { dIASSERT(allowedThreadCount > 1); const unsigned int blockStep = SL1S_BLOCK_SIZE; // Required by the implementation unsigned blockCount = deriveSolvingL1StraightBlockCount(rowCount, blockStep); dIASSERT(blockCount >= 1); unsigned threadCountToUse = deriveSolvingL1StraightThreadCount(blockCount, allowedThreadCount); dIASSERT(threadCountToUse > 1); dCallWaitID completionWait = resourceContainer->getStockCallWait(); dAASSERT(completionWait != NULL); atomicord32 blockCompletionProgress; cellindexint *blockProgressDescriptors; SolveL1StraightCellContext *cellContexts; SolvingL1StraightMemoryEstimates solvingMemoryEstimates; sizeint solvingMemoryRequired = estimateCooperativelySolvingL1StraightMemoryRequirement(rowCount, solvingMemoryEstimates); dIASSERT(solvingMemoryRequired <= resourceContainer->getMemoryBufferSize()); void *bufferAllocated = resourceContainer->getMemoryBufferPointer(); dIASSERT(bufferAllocated != NULL); dIASSERT(dALIGN_PTR(bufferAllocated, ALLOCATION_DEFAULT_ALIGNMENT) == bufferAllocated); void *bufferCurrentLocation = bufferAllocated; bufferCurrentLocation = markCooperativelySolvingL1StraightMemoryStructuresOut(bufferCurrentLocation, solvingMemoryEstimates, blockProgressDescriptors, cellContexts); dIVERIFY(bufferCurrentLocation <= (uint8 *)bufferAllocated + solvingMemoryRequired); initializeCooperativelySolveL1StraightMemoryStructures(rowCount, blockCompletionProgress, blockProgressDescriptors, cellContexts); dCallReleaseeID calculationFinishReleasee; SolveL1StraightWorkerContext workerContext; // The variable must exist in the outer scope workerContext.init(L, b, rowCount, rowSkip, blockCompletionProgress, blockProgressDescriptors, cellContexts); dxThreadingBase *threading = resourceContainer->getThreadingInstance(); threading->PostThreadedCall(NULL, &calculationFinishReleasee, threadCountToUse - 1, NULL, completionWait, &solveL1Straight_completion_callback, NULL, 0, "SolveL1Straight Completion"); threading->PostThreadedCallsGroup(NULL, threadCountToUse - 1, calculationFinishReleasee, &solveL1Straight_worker_callback, &workerContext, "SolveL1Straight Work"); participateSolvingL1Straight(L, b, rowCount, rowSkip, blockCompletionProgress, blockProgressDescriptors, cellContexts, threadCountToUse - 1); threading->WaitThreadedCallExclusively(NULL, completionWait, NULL, "SolveL1Straight End Wait"); } /*static */ int ThreadedEquationSolverLDLT::solveL1Straight_worker_callback(void *callContext, dcallindex_t callInstanceIndex, dCallReleaseeID dUNUSED(callThisReleasee)) { SolveL1StraightWorkerContext *ptrContext = (SolveL1StraightWorkerContext *)callContext; solveL1Straight_worker(*ptrContext, dCAST_TO_SMALLER(unsigned, callInstanceIndex)); return 1; } /*static */ void ThreadedEquationSolverLDLT::solveL1Straight_worker(SolveL1StraightWorkerContext &ref_context, unsigned ownThreadIndex) { const unsigned blockStep = SL1S_BLOCK_SIZE; participateSolvingL1Straight(ref_context.m_L, ref_context.m_b, ref_context.m_rowCount, ref_context.m_rowSkip, *ref_context.m_ptrBlockCompletionProgress, ref_context.m_blockProgressDescriptors, ref_context.m_cellContexts, ownThreadIndex); } /*static */ int ThreadedEquationSolverLDLT::solveL1Straight_completion_callback(void *dUNUSED(callContext), dcallindex_t dUNUSED(callInstanceIndex), dCallReleaseeID dUNUSED(callThisReleasee)) { return 1; } ////////////////////////////////////////////////////////////////////////// // Public interface functions /*extern ODE_API */ void dSolveL1(const dReal *L, dReal *B, int n, int lskip1) { dAASSERT(n != 0); if (n != 0) { dAASSERT(L != NULL); dAASSERT(B != NULL); solveL1Straight<1>(L, B, n, lskip1); } } /*extern ODE_API */ void dEstimateCooperativelySolveL1StraightResourceRequirements(dResourceRequirementsID requirements, unsigned maximalAllowedThreadCount, unsigned maximalRowCount) { dAASSERT(requirements != NULL); dxResourceRequirementDescriptor *requirementsDescriptor = (dxResourceRequirementDescriptor *)requirements; ThreadedEquationSolverLDLT::estimateCooperativeSolvingL1StraightResourceRequirements(requirementsDescriptor, maximalAllowedThreadCount, maximalRowCount); } /*extern ODE_API */ void dCooperativelySolveL1Straight(dResourceContainerID resources, unsigned allowedThreadCount, const dReal *L, dReal *b, unsigned rowCount, unsigned rowSkip) { dAASSERT(resources != NULL); dxRequiredResourceContainer *resourceContainer = (dxRequiredResourceContainer *)resources; ThreadedEquationSolverLDLT::cooperativelySolveL1Straight(resourceContainer, allowedThreadCount, L, b, rowCount, rowSkip); } ode-0.16/ode/src/array.h0000664000175200017520000001314613403272463011774 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* this comes from the `reuse' library. copy any changes back to the source. * * Variable sized array template. The array is always stored in a contiguous * chunk. The array can be resized. A size increase will cause more memory * to be allocated, and may result in relocation of the array memory. * A size decrease has no effect on the memory allocation. * * Array elements with constructors or destructors are not supported! * But if you must have such elements, here's what to know/do: * - Bitwise copy is used when copying whole arrays. * - When copying individual items (via push(), insert() etc) the `=' * (equals) operator is used. Thus you should define this operator to do * a bitwise copy. You should probably also define the copy constructor. */ #ifndef _ODE_ARRAY_H_ #define _ODE_ARRAY_H_ #include // this base class has no constructors or destructor, for your convenience. class dArrayBase { protected: int _size; // number of elements in `data' int _anum; // allocated number of elements in `data' void *_data; // array data void _freeAll (int sizeofT); void _setSize (int newsize, int sizeofT); // set the array size to `newsize', allocating more memory if necessary. // if newsize>_anum and is a power of two then this is guaranteed to // set _size and _anum to newsize. public: // not: dArrayBase () { _size=0; _anum=0; _data=0; } int size() const { return _size; } int allocatedSize() const { return _anum; } void * operator new (size_t size); void operator delete (void *ptr, size_t size); void constructor() { _size=0; _anum=0; _data=0; } // if this structure is allocated with malloc() instead of new, you can // call this to set it up. void constructLocalArray (int __anum); // this helper function allows non-reallocating arrays to be constructed // on the stack (or in the heap if necessary). this is something of a // kludge and should be used with extreme care. this function acts like // a constructor - it is called on uninitialized memory that will hold the // Array structure and the data. __anum is the number of elements that // are allocated. the memory MUST be allocated with size: // sizeof(ArrayBase) + __anum*sizeof(T) // arrays allocated this way will never try to reallocate or free the // memory - that's your job. }; template class dArray : public dArrayBase { public: void equals (const dArray &x) { setSize (x.size()); memcpy (_data,x._data,x._size * sizeof(T)); } dArray () { constructor(); } dArray (const dArray &x) { constructor(); equals (x); } ~dArray () { _freeAll(sizeof(T)); } void setSize (int newsize) { _setSize (newsize,sizeof(T)); } T *data() const { return (T*) _data; } T & operator[] (int i) const { return ((T*)_data)[i]; } void operator = (const dArray &x) { equals (x); } void push (const T item) { if (_size < _anum) _size++; else _setSize (_size+1,sizeof(T)); memcpy (&(((T*)_data)[_size-1]), &item, sizeof(T)); } void swap (dArray &x) { int tmp1; void *tmp2; tmp1=_size; _size=x._size; x._size=tmp1; tmp1=_anum; _anum=x._anum; x._anum=tmp1; tmp2=_data; _data=x._data; x._data=tmp2; } // insert the item at the position `i'. if i<0 then add the item to the // start, if i >= size then add the item to the end of the array. void insert (int i, const T item) { if (_size < _anum) _size++; else _setSize (_size+1,sizeof(T)); if (i >= (_size-1)) i = _size-1; // add to end else { if (i < 0) i=0; // add to start int n = _size-1-i; if (n>0) memmove (((T*)_data) + i+1, ((T*)_data) + i, n*sizeof(T)); } ((T*)_data)[i] = item; } void remove (int i) { if (i >= 0 && i < _size) { // passing this test guarantees size>0 int n = _size-1-i; if (n>0) memmove (((T*)_data) + i, ((T*)_data) + i+1, n*sizeof(T)); _size--; } } }; #endif ode-0.16/ode/src/gimpact_contact_export_helper.cpp0000664000175200017520000000665313403272463017315 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include "config.h" #if dTRIMESH_ENABLED && dTRIMESH_GIMPACT #include "gimpact_contact_export_helper.h" #include "error.h" /*static */ dReal dxGImpactContactsExportHelper::FindContactsMarginalDepth(dReal *pdepths, unsigned contactcount, unsigned maxcontacts, dReal mindepth, dReal maxdepth) { dReal result; while (true) { dReal firstdepth = REAL(0.5) * (mindepth + maxdepth); dReal lowdepth = maxdepth, highdepth = mindepth; unsigned marginindex = 0; unsigned highindex = marginindex; dIASSERT(contactcount != 0); for (unsigned i = 0; i < contactcount; i++) { dReal depth = pdepths[i]; if (depth < firstdepth) { dReal temp = pdepths[marginindex]; pdepths[highindex++] = temp; pdepths[marginindex++] = depth; if (highdepth < depth) { highdepth = depth; } } else if (depth > firstdepth) { pdepths[highindex++] = depth; if (depth < lowdepth) { lowdepth = depth; } } } unsigned countabove = highindex - marginindex; if (maxcontacts < countabove) { contactcount = countabove; pdepths += marginindex; mindepth = lowdepth; } else if (maxcontacts == countabove) { result = dNextAfter(firstdepth, dInfinity); break; } else { unsigned countbelow = marginindex; if (maxcontacts <= contactcount - countbelow) { result = firstdepth; break; } maxcontacts -= contactcount - countbelow; contactcount = countbelow; maxdepth = highdepth; } } return result; } #endif // #if dTRIMESH_ENABLED && dTRIMESH_GIMPACT ode-0.16/ode/src/collision_trimesh_plane.cpp0000664000175200017520000001677213403272463016126 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ // TriMesh - Plane collider by David Walters, July 2006 #include #include #include "config.h" #include "matrix.h" #include "odemath.h" #if dTRIMESH_ENABLED #include "collision_util.h" #include "collision_std.h" #include "collision_trimesh_internal.h" #if dTRIMESH_OPCODE int dCollideTrimeshPlane( dxGeom *o1, dxGeom *o2, int flags, dContactGeom* contacts, int skip ) { dIASSERT( skip >= (int)sizeof( dContactGeom ) ); dIASSERT( o1->type == dTriMeshClass ); dIASSERT( o2->type == dPlaneClass ); dIASSERT ((flags & NUMC_MASK) >= 1); // Alias pointers to the plane and trimesh dxTriMesh* trimesh = (dxTriMesh*)( o1 ); dxPlane* plane = (dxPlane*)( o2 ); int contact_count = 0; // Cache the maximum contact count. const int contact_max = ( flags & NUMC_MASK ); // Cache trimesh position and rotation. const dVector3& trimesh_pos = *(const dVector3*)dGeomGetPosition( trimesh ); const dMatrix3& trimesh_R = *(const dMatrix3*)dGeomGetRotation( trimesh ); // // For all triangles. // VertexPointersEx VPE; VertexPointers &VP = VPE.vp; ConversionArea VC; dReal alpha; dVector3 vertex; #if !defined(dSINGLE) || 1 dVector3 int_vertex; // Intermediate vertex for double precision mode. #endif // dSINGLE const unsigned uiTLSKind = trimesh->getParentSpaceTLSKind(); dIASSERT(uiTLSKind == plane->getParentSpaceTLSKind()); // The colliding spaces must use matching cleanup method TrimeshCollidersCache *pccColliderCache = GetTrimeshCollidersCache(uiTLSKind); VertexUseCache &vertex_use_cache = pccColliderCache->m_VertexUses; // Reallocate vertex use cache if necessary const dxTriMeshData *meshData = trimesh->retrieveMeshData(); const int vertex_count = meshData->m_Mesh.GetNbVertices(); const bool cache_status = vertex_use_cache.resizeAndResetVertexUSEDFlags(vertex_count); // Cache the triangle count. const int tri_count = meshData->m_Mesh.GetNbTriangles(); // For each triangle for ( int t = 0; t < tri_count; ++t ) { // Get triangle, which should also use callback. bool ex_avail = meshData->m_Mesh.GetExTriangle( VPE, t, VC); // For each vertex. for ( int v = 0; v < 3; ++v ) { // point already used ? if (cache_status && ex_avail) { unsigned VIndex = VPE.Index[v]; if (vertex_use_cache.getVertexUSEDFlag(VIndex)) continue; // mark this point as used vertex_use_cache.setVertexUSEDFlag(VIndex); } // // Get Vertex // #if defined(dSINGLE) && 0 // Always assign via intermediate array as otherwise it is an incapsulation violation dMultiply0_331( vertex, trimesh_R, (float*)( VP.Vertex[ v ] ) ); #else // dDOUBLE || 1 // OPCODE data is in single precision format. int_vertex[ 0 ] = VP.Vertex[ v ]->x; int_vertex[ 1 ] = VP.Vertex[ v ]->y; int_vertex[ 2 ] = VP.Vertex[ v ]->z; dMultiply0_331( vertex, trimesh_R, int_vertex ); #endif // dSINGLE/dDOUBLE vertex[ 0 ] += trimesh_pos[ 0 ]; vertex[ 1 ] += trimesh_pos[ 1 ]; vertex[ 2 ] += trimesh_pos[ 2 ]; // // Collision? // // If alpha < 0 then point is if front of plane. i.e. no contact // If alpha = 0 then the point is on the plane alpha = plane->p[ 3 ] - dCalcVectorDot3( plane->p, vertex ); // If alpha > 0 the point is behind the plane. CONTACT! if ( alpha > 0 ) { // Alias the contact dContactGeom* contact = SAFECONTACT( flags, contacts, contact_count, skip ); contact->pos[ 0 ] = vertex[ 0 ]; contact->pos[ 1 ] = vertex[ 1 ]; contact->pos[ 2 ] = vertex[ 2 ]; contact->normal[ 0 ] = plane->p[ 0 ]; contact->normal[ 1 ] = plane->p[ 1 ]; contact->normal[ 2 ] = plane->p[ 2 ]; contact->depth = alpha; contact->g1 = trimesh; contact->g2 = plane; contact->side1 = t; contact->side2 = -1; ++contact_count; // All contact slots are full? if ( contact_count >= contact_max ) return contact_count; // <=== STOP HERE } } } // Return contact count. return contact_count; } #endif // dTRIMESH_OPCODE #if dTRIMESH_GIMPACT #include "gimpact_contact_export_helper.h" #include "gimpact_plane_contact_accessor.h" int dCollideTrimeshPlane( dxGeom *o1, dxGeom *o2, int flags, dContactGeom* contacts, int skip ) { dIASSERT( skip >= (int)sizeof( dContactGeom ) ); dIASSERT( o1->type == dTriMeshClass ); dIASSERT( o2->type == dPlaneClass ); dIASSERT ((flags & NUMC_MASK) >= 1); // Alias pointers to the plane and trimesh dxTriMesh* trimesh = (dxTriMesh*)( o1 ); dVector4 plane; dGeomPlaneGetParams(o2, plane); o1 -> recomputeAABB(); o2 -> recomputeAABB(); //Find collision GDYNAMIC_ARRAY collision_result; GIM_CREATE_TRIMESHPLANE_CONTACTS(collision_result); gim_trimesh_plane_collisionODE(&trimesh->m_collision_trimesh,plane,&collision_result); if(collision_result.m_size == 0 ) { GIM_DYNARRAY_DESTROY(collision_result); return 0; } vec4f * planecontact_results = GIM_DYNARRAY_POINTER(vec4f, collision_result); unsigned int contactcount = collision_result.m_size; dxPlaneContactAccessor contactaccessor(planecontact_results, plane, o1, o2); contactcount = dxGImpactContactsExportHelper::ExportMaxDepthGImpactContacts(contactaccessor, contactcount, flags, contacts, skip); GIM_DYNARRAY_DESTROY(collision_result); return (int)contactcount; } #endif // dTRIMESH_GIMPACT #endif // dTRIMESH_ENABLED ode-0.16/ode/src/obstack.cpp0000664000175200017520000001167313403272463012642 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include #include #include "config.h" #include "obstack.h" //**************************************************************************** // macros and constants #define ROUND_UP_OFFSET_TO_EFFICIENT_SIZE(arena,ofs) \ ofs = (sizeint) (dEFFICIENT_SIZE( ((sizeint)(arena)) + ofs ) - ((sizeint)(arena)) ) #define MAX_ALLOC_SIZE \ ((sizeint)(dOBSTACK_ARENA_SIZE - sizeof (Arena) - EFFICIENT_ALIGNMENT + 1)) //**************************************************************************** // dObStack dObStack::dObStack(): m_first(NULL), m_last(NULL), m_current_arena(NULL), m_current_ofs(0) { } dObStack::~dObStack() { // free all arenas Arena *a,*nexta; a = m_first; while (a) { nexta = a->m_next; dFree (a,dOBSTACK_ARENA_SIZE); a = nexta; } } void *dObStack::alloc (sizeint num_bytes) { if (num_bytes > MAX_ALLOC_SIZE) dDebug (0,"num_bytes too large"); bool last_alloc_needed = false, last_init_needed = false; Arena **last_ptr = NULL; if (m_last != NULL) { if ((m_last->m_used + num_bytes) > dOBSTACK_ARENA_SIZE) { if (m_last->m_next != NULL) { m_last = m_last->m_next; last_init_needed = true; } else { last_ptr = &m_last->m_next; last_alloc_needed = true; } } } else { last_ptr = &m_last; last_alloc_needed = true; } if (last_alloc_needed) { Arena *new_last = (Arena *) dAlloc (dOBSTACK_ARENA_SIZE); new_last->m_next = 0; *last_ptr = new_last; if (m_first == NULL) { m_first = new_last; } m_last = new_last; last_init_needed = true; } if (last_init_needed) { m_last->m_used = sizeof (Arena); ROUND_UP_OFFSET_TO_EFFICIENT_SIZE (m_last,m_last->m_used); } // allocate an area in the arena char *c = ((char*) m_last) + m_last->m_used; m_last->m_used += num_bytes; ROUND_UP_OFFSET_TO_EFFICIENT_SIZE (m_last,m_last->m_used); return c; } void dObStack::freeAll() { Arena *current = m_first; m_last = current; // It is necessary to reset used sizes in whole arena chain // otherwise enumeration may proceed to remains of old deleted joints in unused arenas while (current) { current->m_used = sizeof(Arena); ROUND_UP_OFFSET_TO_EFFICIENT_SIZE (current,current->m_used); current = current->m_next; } } void *dObStack::rewind() { return switch_to_arena(m_first); } void *dObStack::next (sizeint num_bytes) { // this functions like alloc, except that no new storage is ever allocated if (!m_current_arena) { return 0; } m_current_ofs += num_bytes; ROUND_UP_OFFSET_TO_EFFICIENT_SIZE (m_current_arena,m_current_ofs); if (m_current_ofs < m_current_arena->m_used) { return ((char*) m_current_arena) + m_current_ofs; } return switch_to_arena(m_current_arena->m_next); } void *dObStack::switch_to_arena(Arena *next_arena) { m_current_arena = next_arena; if (!next_arena) { return 0; } m_current_ofs = sizeof (Arena); ROUND_UP_OFFSET_TO_EFFICIENT_SIZE (next_arena, m_current_ofs); // Check if end of allocation has been reached if (m_current_ofs >= next_arena->m_used) { return 0; } return ((char*) next_arena) + m_current_ofs; } ode-0.16/ode/src/collision_trimesh_trimesh_old.cpp0000664000175200017520000026102713403272463017333 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ // OPCODE TriMesh/TriMesh collision code by Jeff Smith (c) 2004 #ifdef _MSC_VER #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints #endif #include #include #include "config.h" #include "matrix.h" #include "odemath.h" #if dTRIMESH_ENABLED #include "collision_util.h" #include "collision_trimesh_internal.h" #if dTRIMESH_OPCODE // Classic Implementation #if dTRIMESH_OPCODE_USE_OLD_TRIMESH_TRIMESH_COLLIDER #define SMALL_ELT REAL(2.5e-4) #define EXPANDED_ELT_THRESH REAL(1.0e-3) #define DISTANCE_EPSILON REAL(1.0e-8) #define VELOCITY_EPSILON REAL(1.0e-5) #define TINY_PENETRATION REAL(5.0e-6) struct LineContactSet { enum { MAX_POINTS = 8 }; dVector3 Points[MAX_POINTS]; int Count; }; // static void GetTriangleGeometryCallback(udword, VertexPointers&, udword); -- not used static void GenerateContact(int, dContactGeom*, int, dxTriMesh*, dxTriMesh*, int TriIndex1, int TriIndex2, const dVector3, const dVector3, dReal, int&); static int TriTriIntersectWithIsectLine(dReal V0[3],dReal V1[3],dReal V2[3], dReal U0[3],dReal U1[3],dReal U2[3],int *coplanar, dReal isectpt1[3],dReal isectpt2[3]); inline void dMakeMatrix4(const dVector3 Position, const dMatrix3 Rotation, dMatrix4 &B); static void dInvertMatrix4( dMatrix4& B, dMatrix4& Binv ); //static int IntersectLineSegmentRay(dVector3, dVector3, dVector3, dVector3, dVector3); static bool FindTriSolidIntrsection(const dVector3 Tri[3], const dVector4 Planes[6], int numSides, LineContactSet& ClippedPolygon ); static void ClipConvexPolygonAgainstPlane( const dVector3, dReal, LineContactSet& ); static bool SimpleUnclippedTest(dVector3 in_CoplanarPt, dVector3 in_v, dVector3 in_elt, dVector3 in_n, dVector3* in_col_v, dReal &out_depth); static int ExamineContactPoint(dVector3* v_col, dVector3 in_n, dVector3 in_point); static int RayTriangleIntersect(const dVector3 orig, const dVector3 dir, const dVector3 vert0, const dVector3 vert1,const dVector3 vert2, dReal *t,dReal *u,dReal *v); /* some math macros */ #define IS_ZERO(v) (!(v)[0] && !(v)[1] && !(v)[2]) #define CROSS(dest,v1,v2) dCalcVectorCross3(dest, v1, v2) #define DOT(v1,v2) dCalcVectorDot3(v1, v2) #define SUB(dest,v1,v2) dSubtractVectors3(dest, v1, v2) #define ADD(dest,v1,v2) dAddVectors3(dest, v1, v2) #define MULT(dest,v,factor) dCopyScaledVector3(dest, v, factor) #define SET(dest,src) dCopyVector3(dest, src) #define SMULT(p,q,s) dCopyScaledVector3(p, q, s) #define LENGTH(x) dCalcVectorLength3(x) #define DEPTH(d, p, q, n) d = dCalcPointDepth3(q, p, n) inline void SwapNormals(dVector3 *&pen_v, dVector3 *&col_v, dVector3* v1, dVector3* v2, dVector3 *&pen_elt, dVector3 *elt_f1, dVector3 *elt_f2, dVector3 n, dVector3 n1, dVector3 n2) { if (pen_v == v1) { pen_v = v2; pen_elt = elt_f2; col_v = v1; SET(n, n1); } else { pen_v = v1; pen_elt = elt_f1; col_v = v2; SET(n, n2); } } int dCollideTTL(dxGeom* g1, dxGeom* g2, int Flags, dContactGeom* Contacts, int Stride) { dIASSERT (Stride >= (int)sizeof(dContactGeom)); dIASSERT (g1->type == dTriMeshClass); dIASSERT (g2->type == dTriMeshClass); dIASSERT ((Flags & NUMC_MASK) >= 1); dxTriMesh* TriMesh1 = (dxTriMesh*) g1; dxTriMesh* TriMesh2 = (dxTriMesh*) g2; const dReal* TriNormals1 = TriMesh1->retrieveMeshNormals(); const dReal* TriNormals2 = TriMesh2->retrieveMeshNormals(); const dVector3& TLPosition1 = *(const dVector3*) dGeomGetPosition(TriMesh1); // TLRotation1 = column-major order const dMatrix3& TLRotation1 = *(const dMatrix3*) dGeomGetRotation(TriMesh1); const dVector3& TLPosition2 = *(const dVector3*) dGeomGetPosition(TriMesh2); // TLRotation2 = column-major order const dMatrix3& TLRotation2 = *(const dMatrix3*) dGeomGetRotation(TriMesh2); const unsigned uiTLSKind = TriMesh1->getParentSpaceTLSKind(); dIASSERT(uiTLSKind == TriMesh2->getParentSpaceTLSKind()); // The colliding spaces must use matching cleanup method TrimeshCollidersCache *pccColliderCache = GetTrimeshCollidersCache(uiTLSKind); AABBTreeCollider& Collider = pccColliderCache->m_AABBTreeCollider; BVTCache &ColCache = pccColliderCache->ColCache; ColCache.Model0 = &TriMesh1->retrieveMeshBVTreeRef(); ColCache.Model1 = &TriMesh2->retrieveMeshBVTreeRef(); // Collision query Matrix4x4 amatrix, bmatrix; dVector3 TLOffsetPosition1 = { REAL(0.0), }; dVector3 TLOffsetPosition2; dSubtractVectors3(TLOffsetPosition2, TLPosition2, TLPosition1); MakeMatrix(TLOffsetPosition1, TLRotation1, amatrix); MakeMatrix(TLOffsetPosition2, TLRotation2, bmatrix); BOOL IsOk = Collider.Collide(ColCache, &amatrix, &bmatrix); // Make "double" versions of these matrices, if appropriate dMatrix4 A, B; dMakeMatrix4(TLPosition1, TLRotation1, A); dMakeMatrix4(TLPosition2, TLRotation2, B); if (IsOk) { // Get collision status => if true, objects overlap if ( Collider.GetContactStatus() ) { // Number of colliding pairs and list of pairs int TriCount = Collider.GetNbPairs(); const Pair* CollidingPairs = Collider.GetPairs(); if (TriCount > 0) { // step through the pairs, adding contacts int id1, id2; int OutTriCount = 0; dVector3 v1[3], v2[3], CoplanarPt; dVector3 e1, e2, e3, n1, n2, n, ContactNormal; dReal depth; dVector3 orig_pos, old_pos1, old_pos2, elt1, elt2, elt_sum; dVector3 elt_f1[3], elt_f2[3]; dReal contact_elt_length = SMALL_ELT; LineContactSet firstClippedTri, secondClippedTri; dVector3 *firstClippedElt = new dVector3[LineContactSet::MAX_POINTS]; dVector3 *secondClippedElt = new dVector3[LineContactSet::MAX_POINTS]; // only do these expensive inversions once dMatrix4 InvMatrix1, InvMatrix2; dInvertMatrix4(A, InvMatrix1); dInvertMatrix4(B, InvMatrix2); for (int i = 0; i < TriCount; i++) { id1 = CollidingPairs[i].id0; id2 = CollidingPairs[i].id1; // grab the colliding triangles static_cast(g1)->fetchMeshTriangle(v1, id1, TLPosition1, TLRotation1); static_cast(g2)->fetchMeshTriangle(v2, id2, TLPosition2, TLRotation2); // Since we'll be doing matrix transformations, we need to // make sure that all vertices have four elements for (int j=0; j<3; j++) { v1[j][3] = 1.0; v2[j][3] = 1.0; } int IsCoplanar = 0; dReal IsectPt1[3], IsectPt2[3]; // Sometimes OPCODE makes mistakes, so we look at the return // value for TriTriIntersectWithIsectLine. A retcode of "0" // means no intersection took place if ( TriTriIntersectWithIsectLine( v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], &IsCoplanar, IsectPt1, IsectPt2) ) { // Compute the normals of the colliding faces // if (TriNormals1 == NULL) { SUB( e1, v1[1], v1[0] ); SUB( e2, v1[2], v1[0] ); CROSS( n1, e1, e2 ); dNormalize3(n1); } else { // If we were passed normals, we need to adjust them to take into // account the objects' current rotations e1[0] = TriNormals1[id1*3]; e1[1] = TriNormals1[id1*3 + 1]; e1[2] = TriNormals1[id1*3 + 2]; e1[3] = 0.0; //dMultiply1(n1, TLRotation1, e1, 3, 3, 1); dMultiply0(n1, TLRotation1, e1, 3, 3, 1); n1[3] = 1.0; } if (TriNormals2 == NULL) { SUB( e1, v2[1], v2[0] ); SUB( e2, v2[2], v2[0] ); CROSS( n2, e1, e2); dNormalize3(n2); } else { // If we were passed normals, we need to adjust them to take into // account the objects' current rotations e2[0] = TriNormals2[id2*3]; e2[1] = TriNormals2[id2*3 + 1]; e2[2] = TriNormals2[id2*3 + 2]; e2[3] = 0.0; //dMultiply1(n2, TLRotation2, e2, 3, 3, 1); dMultiply0(n2, TLRotation2, e2, 3, 3, 1); n2[3] = 1.0; } if (IsCoplanar) { // We can reach this case if the faces are coplanar, OR // if they don't actually intersect. (OPCODE can make // mistakes) if (dFabs(dCalcVectorDot3(n1, n2)) > REAL(0.999)) { // If the faces are coplanar, we declare that the point of // contact is at the average location of the vertices of // both faces dVector3 ContactPt; for (int j=0; j<3; j++) { ContactPt[j] = 0.0; for (int k=0; k<3; k++) ContactPt[j] += v1[k][j] + v2[k][j]; ContactPt[j] /= 6.0; } ContactPt[3] = 1.0; // and the contact normal is the normal of face 2 // (could be face 1, because they are the same) SET(n, n2); // and the penetration depth is the co-normal // distance between any two vertices A and B, // i.e. d = DOT(n, (A-B)) DEPTH(depth, v1[1], v2[1], n); if (depth < 0) depth *= -1.0; GenerateContact(Flags, Contacts, Stride, TriMesh1, TriMesh2, id1, id2, ContactPt, n, depth, OutTriCount); } } else { // Otherwise (in non-co-planar cases), we create a coplanar // point -- the middle of the line of intersection -- that // will be used for various computations down the road for (int j=0; j<3; j++) CoplanarPt[j] = ( (IsectPt1[j] + IsectPt2[j]) / REAL(2.0) ); CoplanarPt[3] = 1.0; // Find the ELT of the coplanar point // dMultiply1(orig_pos, InvMatrix1, CoplanarPt, 4, 4, 1); dMultiply1(old_pos1, ((dxTriMesh*)g1)->m_last_trans, orig_pos, 4, 4, 1); SUB(elt1, CoplanarPt, old_pos1); dMultiply1(orig_pos, InvMatrix2, CoplanarPt, 4, 4, 1); dMultiply1(old_pos2, ((dxTriMesh*)g2)->m_last_trans, orig_pos, 4, 4, 1); SUB(elt2, CoplanarPt, old_pos2); SUB(elt_sum, elt1, elt2); // net motion of the coplanar point dReal elt_sum_len = LENGTH(elt_sum); // Could be calculated on demand but there is no good place... // Calculate how much the vertices of each face moved in the // direction of the opposite face's normal // dReal total_dp1, total_dp2; total_dp1 = 0.0; total_dp2 = 0.0; for (int ii=0; ii<3; ii++) { // find the estimated linear translation (ELT) of the vertices // on face 1, wrt to the center of face 2. // un-transform this vertex by the current transform dMultiply1(orig_pos, InvMatrix1, v1[ii], 4, 4, 1 ); // re-transform this vertex by last_trans (to get its old // position) dMultiply1(old_pos1, ((dxTriMesh*)g1)->m_last_trans, orig_pos, 4, 4, 1); // Then subtract this position from our current one to find // the elapsed linear translation (ELT) for (int k=0; k<3; k++) { elt_f1[ii][k] = (v1[ii][k] - old_pos1[k]) - elt2[k]; } // Take the dot product of the ELT for each vertex (wrt the // center of face2) total_dp1 += dFabs( dCalcVectorDot3(elt_f1[ii], n2) ); } for (int ii=0; ii<3; ii++) { // find the estimated linear translation (ELT) of the vertices // on face 2, wrt to the center of face 1. dMultiply1(orig_pos, InvMatrix2, v2[ii], 4, 4, 1); dMultiply1(old_pos2, ((dxTriMesh*)g2)->m_last_trans, orig_pos, 4, 4, 1); for (int k=0; k<3; k++) { elt_f2[ii][k] = (v2[ii][k] - old_pos2[k]) - elt1[k]; } // Take the dot product of the ELT for each vertex (wrt the // center of face2) and add them total_dp2 += dFabs( dCalcVectorDot3(elt_f2[ii], n1) ); } //////// // Estimate the penetration depth. // dReal dp; BOOL badPen = true; dVector3 *pen_v; // the "penetrating vertices" dVector3 *pen_elt; // the elt_f of the penetrating face dVector3 *col_v; // the "collision vertices" (the penetrated face) SMULT(n2, n2, -1.0); // SF PATCH #1335183 depth = 0.0; if ((total_dp1 > DISTANCE_EPSILON) || (total_dp2 > DISTANCE_EPSILON)) { //////// // Find the collision normal, by finding the face // that is pointed "most" in the direction of travel // of the two triangles // if (total_dp2 > total_dp1) { pen_v = v2; pen_elt = elt_f2; col_v = v1; SET(n, n1); } else { pen_v = v1; pen_elt = elt_f1; col_v = v2; SET(n, n2); } } else { // the total_dp is very small, so let's fall back // to a different test if (LENGTH(elt2) > LENGTH(elt1)) { pen_v = v2; pen_elt = elt_f2; col_v = v1; SET(n, n1); } else { pen_v = v1; pen_elt = elt_f1; col_v = v2; SET(n, n2); } } for (int j=0; j<3; j++) { if (SimpleUnclippedTest(CoplanarPt, pen_v[j], pen_elt[j], n, col_v, depth)) { GenerateContact(Flags, Contacts, Stride, TriMesh1, TriMesh2, id1, id2, pen_v[j], n, depth, OutTriCount); badPen = false; if ((OutTriCount | CONTACTS_UNIMPORTANT) == (Flags & (NUMC_MASK | CONTACTS_UNIMPORTANT))) { break; } } } if (badPen) { // try the other normal SwapNormals(pen_v, col_v, v1, v2, pen_elt, elt_f1, elt_f2, n, n1, n2); for (int j=0; j<3; j++) if (SimpleUnclippedTest(CoplanarPt, pen_v[j], pen_elt[j], n, col_v, depth)) { GenerateContact(Flags, Contacts, Stride, TriMesh1, TriMesh2, id1, id2, pen_v[j], n, depth, OutTriCount); badPen = false; if ((OutTriCount | CONTACTS_UNIMPORTANT) == (Flags & (NUMC_MASK | CONTACTS_UNIMPORTANT))) { break; } } } //////////////////////////////////////// // // If we haven't found a good penetration, then we're probably straddling // the edge of one of the objects, or the penetraing face is big // enough that all of its vertices are outside the bounds of the // penetrated face. // In these cases, we do a more expensive test. We clip the penetrating // triangle with a solid defined by the penetrated triangle, and repeat // the tests above on this new polygon if (badPen) { // Switch pen_v and n back again SwapNormals(pen_v, col_v, v1, v2, pen_elt, elt_f1, elt_f2, n, n1, n2); // Find the three sides (no top or bottom) of the solid defined by // the edges of the penetrated triangle. // The dVector4 "plane" structures contain the following information: // [0]-[2]: The normal of the face, pointing INWARDS (i.e. // the inverse normal // [3]: The distance between the face and the center of the // solid, along the normal dVector4 SolidPlanes[3]; dVector3 tmp1; dVector3 sn; for (int j=0; j<3; j++) { e1[j] = col_v[1][j] - col_v[0][j]; e2[j] = col_v[0][j] - col_v[2][j]; e3[j] = col_v[2][j] - col_v[1][j]; } // side 1 CROSS(sn, e1, n); dNormalize3(sn); SMULT( SolidPlanes[0], sn, -1.0 ); ADD(tmp1, col_v[0], col_v[1]); SMULT(tmp1, tmp1, 0.5); // center of edge // distance from center to edge along normal SolidPlanes[0][3] = dCalcVectorDot3(tmp1, SolidPlanes[0]); // side 2 CROSS(sn, e2, n); dNormalize3(sn); SMULT( SolidPlanes[1], sn, -1.0 ); ADD(tmp1, col_v[0], col_v[2]); SMULT(tmp1, tmp1, 0.5); // center of edge // distance from center to edge along normal SolidPlanes[1][3] = dCalcVectorDot3(tmp1, SolidPlanes[1]); // side 3 CROSS(sn, e3, n); dNormalize3(sn); SMULT( SolidPlanes[2], sn, -1.0 ); ADD(tmp1, col_v[2], col_v[1]); SMULT(tmp1, tmp1, 0.5); // center of edge // distance from center to edge along normal SolidPlanes[2][3] = dCalcVectorDot3(tmp1, SolidPlanes[2]); FindTriSolidIntrsection(pen_v, SolidPlanes, 3, firstClippedTri); for (int j=0; jm_last_trans, orig_pos, 4, 4, 1); for (int k=0; k<3; k++) { firstClippedElt[j][k] = (firstClippedTri.Points[j][k] - old_pos1[k]) - elt2[k]; } } else { dMultiply1(orig_pos, InvMatrix2, firstClippedTri.Points[j], 4, 4, 1); dMultiply1(old_pos2, ((dxTriMesh*)g2)->m_last_trans, orig_pos, 4, 4, 1); for (int k=0; k<3; k++) { firstClippedElt[j][k] = (firstClippedTri.Points[j][k] - old_pos2[k]) - elt1[k]; } } if (dp >= 0.0) { contact_elt_length = dFabs(dCalcVectorDot3(firstClippedElt[j], n)); depth = dp; if (depth == 0.0) depth = dMin(DISTANCE_EPSILON, contact_elt_length); if ((contact_elt_length < SMALL_ELT) && (depth < EXPANDED_ELT_THRESH)) depth = contact_elt_length; if (depth <= contact_elt_length) { // Add a contact GenerateContact(Flags, Contacts, Stride, TriMesh1, TriMesh2, id1, id2, firstClippedTri.Points[j], n, depth, OutTriCount); badPen = false; if ((OutTriCount | CONTACTS_UNIMPORTANT) == (Flags & (NUMC_MASK | CONTACTS_UNIMPORTANT))) { break; } } } } } if (badPen) { // Switch pen_v and n (again!) SwapNormals(pen_v, col_v, v1, v2, pen_elt, elt_f1, elt_f2, n, n1, n2); // Find the three sides (no top or bottom) of the solid created by // the penetrated triangle. // The dVector4 "plane" structures contain the following information: // [0]-[2]: The normal of the face, pointing INWARDS (i.e. // the inverse normal // [3]: The distance between the face and the center of the // solid, along the normal dVector4 SolidPlanes[3]; dVector3 tmp1; dVector3 sn; for (int j=0; j<3; j++) { e1[j] = col_v[1][j] - col_v[0][j]; e2[j] = col_v[0][j] - col_v[2][j]; e3[j] = col_v[2][j] - col_v[1][j]; } // side 1 CROSS(sn, e1, n); dNormalize3(sn); SMULT( SolidPlanes[0], sn, -1.0 ); ADD(tmp1, col_v[0], col_v[1]); SMULT(tmp1, tmp1, 0.5); // center of edge // distance from center to edge along normal SolidPlanes[0][3] = dCalcVectorDot3(tmp1, SolidPlanes[0]); // side 2 CROSS(sn, e2, n); dNormalize3(sn); SMULT( SolidPlanes[1], sn, -1.0 ); ADD(tmp1, col_v[0], col_v[2]); SMULT(tmp1, tmp1, 0.5); // center of edge // distance from center to edge along normal SolidPlanes[1][3] = dCalcVectorDot3(tmp1, SolidPlanes[1]); // side 3 CROSS(sn, e3, n); dNormalize3(sn); SMULT( SolidPlanes[2], sn, -1.0 ); ADD(tmp1, col_v[2], col_v[1]); SMULT(tmp1, tmp1, 0.5); // center of edge // distance from center to edge along normal SolidPlanes[2][3] = dCalcVectorDot3(tmp1, SolidPlanes[2]); FindTriSolidIntrsection(pen_v, SolidPlanes, 3, secondClippedTri); for (int j=0; jm_last_trans, orig_pos, 4, 4, 1); for (int k=0; k<3; k++) { secondClippedElt[j][k] = (secondClippedTri.Points[j][k] - old_pos1[k]) - elt2[k]; } } else { dMultiply1(orig_pos, InvMatrix2, secondClippedTri.Points[j], 4, 4, 1); dMultiply1(old_pos2, ((dxTriMesh*)g2)->m_last_trans, orig_pos, 4, 4, 1); for (int k=0; k<3; k++) { secondClippedElt[j][k] = (secondClippedTri.Points[j][k] - old_pos2[k]) - elt1[k]; } } if (dp >= 0.0) { contact_elt_length = dFabs(dCalcVectorDot3(secondClippedElt[j],n)); depth = dp; if (depth == 0.0) depth = dMin(DISTANCE_EPSILON, contact_elt_length); if ((contact_elt_length < SMALL_ELT) && (depth < EXPANDED_ELT_THRESH)) depth = contact_elt_length; if (depth <= contact_elt_length) { // Add a contact GenerateContact(Flags, Contacts, Stride, TriMesh1, TriMesh2, id1, id2, secondClippedTri.Points[j], n, depth, OutTriCount); badPen = false; if ((OutTriCount | CONTACTS_UNIMPORTANT) == (Flags & (NUMC_MASK | CONTACTS_UNIMPORTANT))) { break; } } } } } ///////////////// // All conventional tests have failed at this point, so now we deal with // cases on a more "heuristic" basis // if (badPen) { // Switch pen_v and n (for the fourth time, so they're // what my original guess said they were) SwapNormals(pen_v, col_v, v1, v2, pen_elt, elt_f1, elt_f2, n, n1, n2); if (dFabs(dCalcVectorDot3(n1, n2)) < REAL(0.01)) { // If we reach this point, we have (close to) perpindicular // faces, either resting on each other or sliding in a // direction orthogonal to both surface normals. if (elt_sum_len < DISTANCE_EPSILON) { depth = dFabs(dCalcVectorDot3(n, elt_sum)); if (depth > REAL(1e-12)) { dNormalize3(n); GenerateContact(Flags, Contacts, Stride, TriMesh1, TriMesh2, id1, id2, CoplanarPt, n, depth, OutTriCount); badPen = false; } else { // If the two faces are (nearly) perfectly at rest with // respect to each other, then we ignore the contact, // allowing the objects to slip a little in the hopes // that next frame, they'll give us something to work // with. badPen = false; } } else { // The faces are perpindicular, but moving significantly // This can be sliding, or an unusual edge-straddling // penetration. dVector3 cn; CROSS(cn, n1, n2); dNormalize3(cn); SET(n, cn); // The shallowest ineterpenetration of the faces // is the depth dVector3 ContactPt; dVector3 dvTmp; dReal rTmp; depth = dInfinity; for (int j=0; j<3; j++) { for (int k=0; k<3; k++) { SUB(dvTmp, col_v[k], pen_v[j]); rTmp = dCalcVectorDot3(dvTmp, n); if ( dFabs(rTmp) < dFabs(depth) ) { depth = rTmp; SET( ContactPt, pen_v[j] ); contact_elt_length = dFabs(dCalcVectorDot3(pen_elt[j], n)); } } } if (depth < 0.0) { SMULT(n, n, -1.0); depth *= -1.0; } if ((depth > 0.0) && (depth <= contact_elt_length)) { GenerateContact(Flags, Contacts, Stride, TriMesh1, TriMesh2, id1, id2, ContactPt, n, depth, OutTriCount); badPen = false; } } } } if (badPen && elt_sum_len != 0.0) { // Use as the normal the direction of travel, rather than any particular // face normal // dVector3 esn; if (pen_v == v1) { SMULT(esn, elt_sum, -1.0); } else { SET(esn, elt_sum); } dNormalize3(esn); // The shallowest ineterpenetration of the faces // is the depth dVector3 ContactPt; depth = dInfinity; for (int j=0; j<3; j++) { for (int k=0; k<3; k++) { DEPTH(dp, col_v[k], pen_v[j], esn); if ( (ExamineContactPoint(col_v, esn, pen_v[j])) && ( dFabs(dp) < dFabs(depth)) ) { depth = dp; SET( ContactPt, pen_v[j] ); contact_elt_length = dFabs(dCalcVectorDot3(pen_elt[j], esn)); } } } if ((depth > 0.0) && (depth <= contact_elt_length)) { GenerateContact(Flags, Contacts, Stride, TriMesh1, TriMesh2, id1, id2, ContactPt, esn, depth, OutTriCount); badPen = false; } } if (badPen && elt_sum_len != 0.0) { // If the direction of motion is perpindicular to both normals if ( (dFabs(dCalcVectorDot3(n1, elt_sum)) < REAL(0.01)) && (dFabs(dCalcVectorDot3(n2, elt_sum)) < REAL(0.01)) ) { dVector3 esn; if (pen_v == v1) { SMULT(esn, elt_sum, -1.0); } else { SET(esn, elt_sum); } dNormalize3(esn); // Look at the clipped points again, checking them against this // new normal for (int j=0; j= 0.0) { contact_elt_length = dFabs(dCalcVectorDot3(firstClippedElt[j], esn)); depth = dp; //if (depth == 0.0) //depth = dMin(DISTANCE_EPSILON, contact_elt_length); if ((contact_elt_length < SMALL_ELT) && (depth < EXPANDED_ELT_THRESH)) depth = contact_elt_length; if (depth <= contact_elt_length) { // Add a contact GenerateContact(Flags, Contacts, Stride, TriMesh1, TriMesh2, id1, id2, firstClippedTri.Points[j], esn, depth, OutTriCount); badPen = false; if ((OutTriCount | CONTACTS_UNIMPORTANT) == (Flags & (NUMC_MASK | CONTACTS_UNIMPORTANT))) { break; } } } } if (badPen) { // If this test failed, try it with the second set of clipped faces for (int j=0; j= 0.0) { contact_elt_length = dFabs(dCalcVectorDot3(secondClippedElt[j], esn)); depth = dp; //if (depth == 0.0) //depth = dMin(DISTANCE_EPSILON, contact_elt_length); if ((contact_elt_length < SMALL_ELT) && (depth < EXPANDED_ELT_THRESH)) depth = contact_elt_length; if (depth <= contact_elt_length) { // Add a contact GenerateContact(Flags, Contacts, Stride, TriMesh1, TriMesh2, id1, id2, secondClippedTri.Points[j], esn, depth, OutTriCount); badPen = false; if ((OutTriCount | CONTACTS_UNIMPORTANT) == (Flags & (NUMC_MASK | CONTACTS_UNIMPORTANT))) { break; } } } } } } } if (badPen) { // if we have very little motion, we're dealing with resting contact // and shouldn't reference the ELTs at all // if (elt_sum_len < VELOCITY_EPSILON) { // instead of a "contact_elt_length" threshhold, we'll use an // arbitrary, small one for (int j=0; j<3; j++) { DEPTH(dp, CoplanarPt, pen_v[j], n); if (dp == 0.0) dp = TINY_PENETRATION; if ( (dp > 0.0) && (dp <= SMALL_ELT)) { // Add a contact GenerateContact(Flags, Contacts, Stride, TriMesh1, TriMesh2, id1, id2, pen_v[j], n, dp, OutTriCount); badPen = false; if ((OutTriCount | CONTACTS_UNIMPORTANT) == (Flags & (NUMC_MASK | CONTACTS_UNIMPORTANT))) { break; } } } if (badPen) { // try the other normal SwapNormals(pen_v, col_v, v1, v2, pen_elt, elt_f1, elt_f2, n, n1, n2); for (int j=0; j<3; j++) { DEPTH(dp, CoplanarPt, pen_v[j], n); if (dp == 0.0) dp = TINY_PENETRATION; if ( (dp > 0.0) && (dp <= SMALL_ELT)) { GenerateContact(Flags, Contacts, Stride, TriMesh1, TriMesh2, id1, id2, pen_v[j], n, dp, OutTriCount); badPen = false; if ((OutTriCount | CONTACTS_UNIMPORTANT) == (Flags & (NUMC_MASK | CONTACTS_UNIMPORTANT))) { break; } } } } } } if (badPen) { // find the nearest existing contact, and replicate it's // normal and depth // dContactGeom* Contact; dVector3 pos_diff; dReal min_dist, dist; min_dist = dInfinity; depth = 0.0; for (int j=0; jpos, CoplanarPt); dist = dCalcVectorDot3(pos_diff, pos_diff); if (dist < min_dist) { min_dist = dist; depth = Contact->depth; SMULT(ContactNormal, Contact->normal, -1.0); } } if (depth > 0.0) { // Add a tiny contact at the coplanar point GenerateContact(Flags, Contacts, Stride, TriMesh1, TriMesh2, id1, id2, CoplanarPt, ContactNormal, depth, OutTriCount); badPen = false; } } if (badPen) { // Add a tiny contact at the coplanar point if (-dCalcVectorDot3(elt_sum, n1) > -dCalcVectorDot3(elt_sum, n2)) { SET(ContactNormal, n1); } else { SET(ContactNormal, n2); } GenerateContact(Flags, Contacts, Stride, TriMesh1, TriMesh2, id1, id2, CoplanarPt, ContactNormal, TINY_PENETRATION, OutTriCount); badPen = false; } } // not coplanar (main loop) } // TriTriIntersectWithIsectLine if ((OutTriCount | CONTACTS_UNIMPORTANT) == (Flags & (NUMC_MASK | CONTACTS_UNIMPORTANT))) { break; } } // Free memory delete[] firstClippedElt; delete[] secondClippedElt; // Return the number of contacts return OutTriCount; } } } // There was some kind of failure during the Collide call or // there are no faces overlapping return 0; } /* -- not used static void GetTriangleGeometryCallback(udword triangleindex, VertexPointers& triangle, udword user_data) { dVector3 Out[3]; FetchTriangle((dxTriMesh*) user_data, (int) triangleindex, Out); for (int i = 0; i < 3; i++) triangle.Vertex[i] = (const Point*) ((dReal*) Out[i]); } */ // // // #define B11 B[0] #define B12 B[1] #define B13 B[2] #define B14 B[3] #define B21 B[4] #define B22 B[5] #define B23 B[6] #define B24 B[7] #define B31 B[8] #define B32 B[9] #define B33 B[10] #define B34 B[11] #define B41 B[12] #define B42 B[13] #define B43 B[14] #define B44 B[15] #define Binv11 Binv[0] #define Binv12 Binv[1] #define Binv13 Binv[2] #define Binv14 Binv[3] #define Binv21 Binv[4] #define Binv22 Binv[5] #define Binv23 Binv[6] #define Binv24 Binv[7] #define Binv31 Binv[8] #define Binv32 Binv[9] #define Binv33 Binv[10] #define Binv34 Binv[11] #define Binv41 Binv[12] #define Binv42 Binv[13] #define Binv43 Binv[14] #define Binv44 Binv[15] inline void dMakeMatrix4(const dVector3 Position, const dMatrix3 Rotation, dMatrix4 &B) { B11 = Rotation[0]; B21 = Rotation[1]; B31 = Rotation[2]; B41 = Position[0]; B12 = Rotation[4]; B22 = Rotation[5]; B32 = Rotation[6]; B42 = Position[1]; B13 = Rotation[8]; B23 = Rotation[9]; B33 = Rotation[10]; B43 = Position[2]; B14 = 0.0; B24 = 0.0; B34 = 0.0; B44 = 1.0; } static void dInvertMatrix4( dMatrix4& B, dMatrix4& Binv ) { dReal det = (B11 * B22 - B12 * B21) * (B33 * B44 - B34 * B43) -(B11 * B23 - B13 * B21) * (B32 * B44 - B34 * B42) +(B11 * B24 - B14 * B21) * (B32 * B43 - B33 * B42) +(B12 * B23 - B13 * B22) * (B31 * B44 - B34 * B41) -(B12 * B24 - B14 * B22) * (B31 * B43 - B33 * B41) +(B13 * B24 - B14 * B23) * (B31 * B42 - B32 * B41); dAASSERT (det != 0.0); det = 1.0 / det; Binv11 = (dReal) (det * ((B22 * B33) - (B23 * B32))); Binv12 = (dReal) (det * ((B32 * B13) - (B33 * B12))); Binv13 = (dReal) (det * ((B12 * B23) - (B13 * B22))); Binv14 = 0.0f; Binv21 = (dReal) (det * ((B23 * B31) - (B21 * B33))); Binv22 = (dReal) (det * ((B33 * B11) - (B31 * B13))); Binv23 = (dReal) (det * ((B13 * B21) - (B11 * B23))); Binv24 = 0.0f; Binv31 = (dReal) (det * ((B21 * B32) - (B22 * B31))); Binv32 = (dReal) (det * ((B31 * B12) - (B32 * B11))); Binv33 = (dReal) (det * ((B11 * B22) - (B12 * B21))); Binv34 = 0.0f; Binv41 = (dReal) (det * (B21*(B33*B42 - B32*B43) + B22*(B31*B43 - B33*B41) + B23*(B32*B41 - B31*B42))); Binv42 = (dReal) (det * (B31*(B13*B42 - B12*B43) + B32*(B11*B43 - B13*B41) + B33*(B12*B41 - B11*B42))); Binv43 = (dReal) (det * (B41*(B13*B22 - B12*B23) + B42*(B11*B23 - B13*B21) + B43*(B12*B21 - B11*B22))); Binv44 = 1.0f; } ///////////////////////////////////////////////// // // Triangle/Triangle intersection utilities // // From the article "A Fast Triangle-Triangle Intersection Test", // Journal of Graphics Tools, 2(2), 1997 // // Some of this functionality is duplicated in OPCODE (see // OPC_TriTriOverlap.h) but we have replicated it here so we don't // have to mess with the internals of OPCODE, as well as so we can // further optimize some of the functions. // // This version computes the line of intersection as well (if they // are not coplanar): // int TriTriIntersectWithIsectLine(dReal V0[3],dReal V1[3],dReal V2[3], // dReal U0[3],dReal U1[3],dReal U2[3], // int *coplanar, // dReal isectpt1[3],dReal isectpt2[3]); // // parameters: vertices of triangle 1: V0,V1,V2 // vertices of triangle 2: U0,U1,U2 // // result : returns 1 if the triangles intersect, otherwise 0 // "coplanar" returns whether the tris are coplanar // isectpt1, isectpt2 are the endpoints of the line of // intersection // /* if USE_EPSILON_TEST is true then we do a check: if |dv|b) \ { \ dReal c; \ c=a; \ a=b; \ b=c; \ } #define ISECT(VV0,VV1,VV2,D0,D1,D2,isect0,isect1) \ isect0=VV0+(VV1-VV0)*D0/(D0-D1); \ isect1=VV0+(VV2-VV0)*D0/(D0-D2); #define COMPUTE_INTERVALS(VV0,VV1,VV2,D0,D1,D2,D0D1,D0D2,isect0,isect1) \ if(D0D1>0.0f) \ { \ /* here we know that D0D2<=0.0 */ \ /* that is D0, D1 are on the same side, D2 on the other or on the plane */ \ ISECT(VV2,VV0,VV1,D2,D0,D1,isect0,isect1); \ } \ else if(D0D2>0.0f) \ { \ /* here we know that d0d1<=0.0 */ \ ISECT(VV1,VV0,VV2,D1,D0,D2,isect0,isect1); \ } \ else if(D1*D2>0.0f || D0!=0.0f) \ { \ /* here we know that d0d1<=0.0 or that D0!=0.0 */ \ ISECT(VV0,VV1,VV2,D0,D1,D2,isect0,isect1); \ } \ else if(D1!=0.0f) \ { \ ISECT(VV1,VV0,VV2,D1,D0,D2,isect0,isect1); \ } \ else if(D2!=0.0f) \ { \ ISECT(VV2,VV0,VV1,D2,D0,D1,isect0,isect1); \ } \ else \ { \ /* triangles are coplanar */ \ return coplanar_tri_tri(N1,V0,V1,V2,U0,U1,U2); \ } /* this edge to edge test is based on Franlin Antonio's gem: "Faster Line Segment Intersection", in Graphics Gems III, pp. 199-202 */ #define EDGE_EDGE_TEST(V0,U0,U1) \ Bx=U0[i0]-U1[i0]; \ By=U0[i1]-U1[i1]; \ Cx=V0[i0]-U0[i0]; \ Cy=V0[i1]-U0[i1]; \ f=Ay*Bx-Ax*By; \ d=By*Cx-Bx*Cy; \ if((f>0 && d>=0 && d<=f) || (f<0 && d<=0 && d>=f)) \ { \ e=Ax*Cy-Ay*Cx; \ if(f>0) \ { \ if(e>=0 && e<=f) return 1; \ } \ else \ { \ if(e<=0 && e>=f) return 1; \ } \ } #define EDGE_AGAINST_TRI_EDGES(V0,V1,U0,U1,U2) \ { \ dReal Ax,Ay,Bx,By,Cx,Cy,e,d,f; \ Ax=V1[i0]-V0[i0]; \ Ay=V1[i1]-V0[i1]; \ /* test edge U0,U1 against V0,V1 */ \ EDGE_EDGE_TEST(V0,U0,U1); \ /* test edge U1,U2 against V0,V1 */ \ EDGE_EDGE_TEST(V0,U1,U2); \ /* test edge U2,U1 against V0,V1 */ \ EDGE_EDGE_TEST(V0,U2,U0); \ } #define POINT_IN_TRI(V0,U0,U1,U2) \ { \ dReal a,b,c,d0,d1,d2; \ /* is T1 completly inside T2? */ \ /* check if V0 is inside tri(U0,U1,U2) */ \ a=U1[i1]-U0[i1]; \ b=-(U1[i0]-U0[i0]); \ c=-a*U0[i0]-b*U0[i1]; \ d0=a*V0[i0]+b*V0[i1]+c; \ \ a=U2[i1]-U1[i1]; \ b=-(U2[i0]-U1[i0]); \ c=-a*U1[i0]-b*U1[i1]; \ d1=a*V0[i0]+b*V0[i1]+c; \ \ a=U0[i1]-U2[i1]; \ b=-(U0[i0]-U2[i0]); \ c=-a*U2[i0]-b*U2[i1]; \ d2=a*V0[i0]+b*V0[i1]+c; \ if(d0*d1>0.0) \ { \ if(d0*d2>0.0) return 1; \ } \ } int coplanar_tri_tri(dReal N[3],dReal V0[3],dReal V1[3],dReal V2[3], dReal U0[3],dReal U1[3],dReal U2[3]) { dReal A[3]; short i0,i1; /* first project onto an axis-aligned plane, that maximizes the area */ /* of the triangles, compute indices: i0,i1. */ A[0]= dFabs(N[0]); A[1]= dFabs(N[1]); A[2]= dFabs(N[2]); if(A[0]>A[1]) { if(A[0]>A[2]) { i0=1; /* A[0] is greatest */ i1=2; } else { i0=0; /* A[2] is greatest */ i1=1; } } else /* A[0]<=A[1] */ { if(A[2]>A[1]) { i0=0; /* A[2] is greatest */ i1=1; } else { i0=0; /* A[1] is greatest */ i1=2; } } /* test all edges of triangle 1 against the edges of triangle 2 */ EDGE_AGAINST_TRI_EDGES(V0,V1,U0,U1,U2); EDGE_AGAINST_TRI_EDGES(V1,V2,U0,U1,U2); EDGE_AGAINST_TRI_EDGES(V2,V0,U0,U1,U2); /* finally, test if tri1 is totally contained in tri2 or vice versa */ POINT_IN_TRI(V0,U0,U1,U2); POINT_IN_TRI(U0,V0,V1,V2); return 0; } #define NEWCOMPUTE_INTERVALS(VV0,VV1,VV2,D0,D1,D2,D0D1,D0D2,A,B,C,X0,X1) \ { \ if(D0D1>0.0f) \ { \ /* here we know that D0D2<=0.0 */ \ /* that is D0, D1 are on the same side, D2 on the other or on the plane */ \ A=VV2; B=(VV0-VV2)*D2; C=(VV1-VV2)*D2; X0=D2-D0; X1=D2-D1; \ } \ else if(D0D2>0.0f)\ { \ /* here we know that d0d1<=0.0 */ \ A=VV1; B=(VV0-VV1)*D1; C=(VV2-VV1)*D1; X0=D1-D0; X1=D1-D2; \ } \ else if(D1*D2>0.0f || D0!=0.0f) \ { \ /* here we know that d0d1<=0.0 or that D0!=0.0 */ \ A=VV0; B=(VV1-VV0)*D0; C=(VV2-VV0)*D0; X0=D0-D1; X1=D0-D2; \ } \ else if(D1!=0.0f) \ { \ A=VV1; B=(VV0-VV1)*D1; C=(VV2-VV1)*D1; X0=D1-D0; X1=D1-D2; \ } \ else if(D2!=0.0f) \ { \ A=VV2; B=(VV0-VV2)*D2; C=(VV1-VV2)*D2; X0=D2-D0; X1=D2-D1; \ } \ else \ { \ /* triangles are coplanar */ \ return coplanar_tri_tri(N1,V0,V1,V2,U0,U1,U2); \ } \ } /* sort so that a<=b */ #define SORT2(a,b,smallest) \ if(a>b) \ { \ dReal c; \ c=a; \ a=b; \ b=c; \ smallest=1; \ } \ else smallest=0; inline void isect2(dReal VTX0[3],dReal VTX1[3],dReal VTX2[3],dReal VV0,dReal VV1,dReal VV2, dReal D0,dReal D1,dReal D2,dReal *isect0,dReal *isect1,dReal isectpoint0[3],dReal isectpoint1[3]) { dReal tmp=D0/(D0-D1); dReal diff[3]; *isect0=VV0+(VV1-VV0)*tmp; SUB(diff,VTX1,VTX0); MULT(diff,diff,tmp); ADD(isectpoint0,diff,VTX0); tmp=D0/(D0-D2); *isect1=VV0+(VV2-VV0)*tmp; SUB(diff,VTX2,VTX0); MULT(diff,diff,tmp); ADD(isectpoint1,VTX0,diff); } #if 0 #define ISECT2(VTX0,VTX1,VTX2,VV0,VV1,VV2,D0,D1,D2,isect0,isect1,isectpoint0,isectpoint1) \ tmp=D0/(D0-D1); \ isect0=VV0+(VV1-VV0)*tmp; \ SUB(diff,VTX1,VTX0); \ MULT(diff,diff,tmp); \ ADD(isectpoint0,diff,VTX0); \ tmp=D0/(D0-D2); /*isect1=VV0+(VV2-VV0)*tmp; \ */ /*SUB(diff,VTX2,VTX0); \ */ /*MULT(diff,diff,tmp); \ */ /*ADD(isectpoint1,VTX0,diff); */ #endif inline int compute_intervals_isectline(dReal VERT0[3],dReal VERT1[3],dReal VERT2[3], dReal VV0,dReal VV1,dReal VV2,dReal D0,dReal D1,dReal D2, dReal D0D1,dReal D0D2,dReal *isect0,dReal *isect1, dReal isectpoint0[3],dReal isectpoint1[3]) { if(D0D1>0.0f) { /* here we know that D0D2<=0.0 */ /* that is D0, D1 are on the same side, D2 on the other or on the plane */ isect2(VERT2,VERT0,VERT1,VV2,VV0,VV1,D2,D0,D1,isect0,isect1,isectpoint0,isectpoint1); } else if(D0D2>0.0f) { /* here we know that d0d1<=0.0 */ isect2(VERT1,VERT0,VERT2,VV1,VV0,VV2,D1,D0,D2,isect0,isect1,isectpoint0,isectpoint1); } else if(D1*D2>0.0f || D0!=0.0f) { /* here we know that d0d1<=0.0 or that D0!=0.0 */ isect2(VERT0,VERT1,VERT2,VV0,VV1,VV2,D0,D1,D2,isect0,isect1,isectpoint0,isectpoint1); } else if(D1!=0.0f) { isect2(VERT1,VERT0,VERT2,VV1,VV0,VV2,D1,D0,D2,isect0,isect1,isectpoint0,isectpoint1); } else if(D2!=0.0f) { isect2(VERT2,VERT0,VERT1,VV2,VV0,VV1,D2,D0,D1,isect0,isect1,isectpoint0,isectpoint1); } else { /* triangles are coplanar */ return 1; } return 0; } #define COMPUTE_INTERVALS_ISECTLINE(VERT0,VERT1,VERT2,VV0,VV1,VV2,D0,D1,D2,D0D1,D0D2,isect0,isect1,isectpoint0,isectpoint1) \ if(D0D1>0.0f) \ { \ /* here we know that D0D2<=0.0 */ \ /* that is D0, D1 are on the same side, D2 on the other or on the plane */ \ isect2(VERT2,VERT0,VERT1,VV2,VV0,VV1,D2,D0,D1,&isect0,&isect1,isectpoint0,isectpoint1); \ } #if 0 else if(D0D2>0.0f) \ { \ /* here we know that d0d1<=0.0 */ \ isect2(VERT1,VERT0,VERT2,VV1,VV0,VV2,D1,D0,D2,&isect0,&isect1,isectpoint0,isectpoint1); \ } \ else if(D1*D2>0.0f || D0!=0.0f) \ { \ /* here we know that d0d1<=0.0 or that D0!=0.0 */ \ isect2(VERT0,VERT1,VERT2,VV0,VV1,VV2,D0,D1,D2,&isect0,&isect1,isectpoint0,isectpoint1); \ } \ else if(D1!=0.0f) \ { \ isect2(VERT1,VERT0,VERT2,VV1,VV0,VV2,D1,D0,D2,&isect0,&isect1,isectpoint0,isectpoint1); \ } \ else if(D2!=0.0f) \ { \ isect2(VERT2,VERT0,VERT1,VV2,VV0,VV1,D2,D0,D1,&isect0,&isect1,isectpoint0,isectpoint1); \ } \ else \ { \ /* triangles are coplanar */ \ coplanar=1; \ return coplanar_tri_tri(N1,V0,V1,V2,U0,U1,U2); \ } #endif static int TriTriIntersectWithIsectLine(dReal V0[3],dReal V1[3],dReal V2[3], dReal U0[3],dReal U1[3],dReal U2[3],int *coplanar, dReal isectpt1[3],dReal isectpt2[3]) { dReal E1[3],E2[3]; dReal N1[3],N2[3],d1,d2; dReal du0,du1,du2,dv0,dv1,dv2; dReal D[3]; dReal isect1[2]={0,0}, isect2[2]={0,0}; dReal isectpointA1[3],isectpointA2[3]; dReal isectpointB1[3]={0,0,0},isectpointB2[3]={0,0,0}; dReal du0du1,du0du2,dv0dv1,dv0dv2; short index; dReal vp0,vp1,vp2; dReal up0,up1,up2; dReal b,c,max; int smallest1,smallest2; /* compute plane equation of triangle(V0,V1,V2) */ SUB(E1,V1,V0); SUB(E2,V2,V0); CROSS(N1,E1,E2); // Even though all triangles might be initially valid, // a triangle may degenerate into a segment after applying // space transformation. // // Oleh_Derevenko: // I'm not quite sure if this routine will fail/assert for zero normal // (it's too large and complex to be fully analyzed). // However in such a large code block three extra float comparisons // will not have any noticeable influence on performance. if (IS_ZERO(N1)) return 0; d1=-DOT(N1,V0); /* plane equation 1: N1.X+d1=0 */ /* put U0,U1,U2 into plane equation 1 to compute signed distances to the plane*/ du0=DOT(N1,U0)+d1; du1=DOT(N1,U1)+d1; du2=DOT(N1,U2)+d1; /* coplanarity robustness check */ #if USE_EPSILON_TEST==TRUE if(dFabs(du0)0.0f && du0du2>0.0f) /* same sign on all of them + not equal 0 ? */ return 0; /* no intersection occurs */ /* compute plane of triangle (U0,U1,U2) */ SUB(E1,U1,U0); SUB(E2,U2,U0); CROSS(N2,E1,E2); // Even though all triangles might be initially valid, // a triangle may degenerate into a segment after applying // space transformation. // // Oleh_Derevenko: // I'm not quite sure if this routine will fail/assert for zero normal // (it's too large and complex to be fully analyzed). // However in such a large code block three extra float comparisons // will not have any noticeable influence on performance. if (IS_ZERO(N2)) return 0; d2=-DOT(N2,U0); /* plane equation 2: N2.X+d2=0 */ /* put V0,V1,V2 into plane equation 2 */ dv0=DOT(N2,V0)+d2; dv1=DOT(N2,V1)+d2; dv2=DOT(N2,V2)+d2; #if USE_EPSILON_TEST==TRUE if(dFabs(dv0)0.0f && dv0dv2>0.0f) /* same sign on all of them + not equal 0 ? */ return 0; /* no intersection occurs */ /* compute direction of intersection line */ CROSS(D,N1,N2); /* compute and index to the largest component of D */ max= dFabs(D[0]); index=0; b= dFabs(D[1]); c= dFabs(D[2]); if(b>max) max=b,index=1; if(c>max) max=c,index=2; /* this is the simplified projection onto L*/ vp0=V0[index]; vp1=V1[index]; vp2=V2[index]; up0=U0[index]; up1=U1[index]; up2=U2[index]; /* compute interval for triangle 1 */ *coplanar=compute_intervals_isectline(V0,V1,V2,vp0,vp1,vp2,dv0,dv1,dv2, dv0dv1,dv0dv2,&isect1[0],&isect1[1],isectpointA1,isectpointA2); if(*coplanar) return coplanar_tri_tri(N1,V0,V1,V2,U0,U1,U2); /* compute interval for triangle 2 */ compute_intervals_isectline(U0,U1,U2,up0,up1,up2,du0,du1,du2, du0du1,du0du2,&isect2[0],&isect2[1],isectpointB1,isectpointB2); SORT2(isect1[0],isect1[1],smallest1); SORT2(isect2[0],isect2[1],smallest2); if(isect1[1]isect1[1]) { if(smallest1==0) { SET(isectpt2,isectpointA2); } else { SET(isectpt2,isectpointA1); } } else { if(smallest2==0) { SET(isectpt2,isectpointB2); } else { SET(isectpt2,isectpointB1); } } } return 1; } // Find the intersectiojn point between a coplanar line segement, // defined by X1 and X2, and a ray defined by X3 and direction N. // // This forumla for this calculation is: // (c x b) . (a x b) // Q = x1 + a ------------------- // | a x b | ^2 // // where a = x2 - x1 // b = x4 - x3 // c = x3 - x1 // x1 and x2 are the edges of the triangle, and x3 is CoplanarPt // and x4 is (CoplanarPt - n) #if 0 // not used anywhere static int IntersectLineSegmentRay(dVector3 x1, dVector3 x2, dVector3 x3, dVector3 n, dVector3 out_pt) { dVector3 a, b, c, x4; ADD(x4, x3, n); // x4 = x3 + n SUB(a, x2, x1); // a = x2 - x1 SUB(b, x4, x3); SUB(c, x3, x1); dVector3 tmp1, tmp2; CROSS(tmp1, c, b); CROSS(tmp2, a, b); dReal num, denom; num = dCalcVectorDot3(tmp1, tmp2); denom = LENGTH( tmp2 ); dReal s; s = num /(denom*denom); for (int i=0; i<3; i++) out_pt[i] = x1[i] + a[i]*s; // Test if this intersection is "behind" x3, w.r.t. n SUB(a, x3, out_pt); if (dCalcVectorDot3(a, n) > 0.0) return 0; // Test if this intersection point is outside the edge limits, // if (dot( (out_pt-x1), (out_pt-x2) ) < 0) it's inside // else outside SUB(a, out_pt, x1); SUB(b, out_pt, x2); if (dCalcVectorDot3(a,b) < 0.0) return 1; else return 0; } #endif // FindTriSolidIntersection - Clips the input trinagle TRI with the // sides of a convex bounding solid, described by PLANES, returning // the (convex) clipped polygon in CLIPPEDPOLYGON // static bool FindTriSolidIntrsection(const dVector3 Tri[3], const dVector4 Planes[6], int numSides, LineContactSet& ClippedPolygon ) { // Set up the LineContactSet structure for (int k=0; k<3; k++) { SET(ClippedPolygon.Points[k], Tri[k]); } ClippedPolygon.Count = 3; // Clip wrt the sides for ( int i = 0; i < numSides; i++ ) ClipConvexPolygonAgainstPlane( Planes[i], Planes[i][3], ClippedPolygon ); return (ClippedPolygon.Count > 0); } // ClipConvexPolygonAgainstPlane - Clip a a convex polygon, described by // CONTACTS, with a plane (described by N and C). Note: the input // vertices are assumed to be in counterclockwise order. // // This code is taken from The Nebula Device: // http://nebuladevice.sourceforge.net/cgi-bin/twiki/view/Nebula/WebHome // and is licensed under the following license: // http://nebuladevice.sourceforge.net/doc/source/license.txt // static void ClipConvexPolygonAgainstPlane( const dVector3 N, dReal C, LineContactSet& Contacts ) { // test on which side of line are the vertices int Positive = 0, Negative = 0, PIndex = -1; int Quantity = Contacts.Count; dReal Test[8]; for ( int i = 0; i < Contacts.Count; i++ ) { // An epsilon is used here because it is possible for the dot product // and C to be exactly equal to each other (in theory), but differ // slightly because of floating point problems. Thus, add a little // to the test number to push actually equal numbers over the edge // towards the positive. This should probably be somehow a relative // tolerance, and I don't think multiplying by the constant is the best // way to do this. Test[i] = dCalcVectorDot3(N, Contacts.Points[i]) - C + dFabs(C)*REAL(1e-08); if (Test[i] >= REAL(0.0)) { Positive++; if (PIndex < 0) { PIndex = i; } } else Negative++; } if (Positive > 0) { if (Negative > 0) { // plane transversely intersects polygon dVector3 CV[8]; int CQuantity = 0, Cur, Prv; dReal T; if (PIndex > 0) { // first clip vertex on line Cur = PIndex; Prv = Cur - 1; T = Test[Cur] / (Test[Cur] - Test[Prv]); CV[CQuantity][0] = Contacts.Points[Cur][0] + T * (Contacts.Points[Prv][0] - Contacts.Points[Cur][0]); CV[CQuantity][1] = Contacts.Points[Cur][1] + T * (Contacts.Points[Prv][1] - Contacts.Points[Cur][1]); CV[CQuantity][2] = Contacts.Points[Cur][2] + T * (Contacts.Points[Prv][2] - Contacts.Points[Cur][2]); CV[CQuantity][3] = Contacts.Points[Cur][3] + T * (Contacts.Points[Prv][3] - Contacts.Points[Cur][3]); CQuantity++; // vertices on positive side of line while (Cur < Quantity && Test[Cur] >= REAL(0.0)) { CV[CQuantity][0] = Contacts.Points[Cur][0]; CV[CQuantity][1] = Contacts.Points[Cur][1]; CV[CQuantity][2] = Contacts.Points[Cur][2]; CV[CQuantity][3] = Contacts.Points[Cur][3]; CQuantity++; Cur++; } // last clip vertex on line if (Cur < Quantity) { Prv = Cur - 1; } else { Cur = 0; Prv = Quantity - 1; } T = Test[Cur] / (Test[Cur] - Test[Prv]); CV[CQuantity][0] = Contacts.Points[Cur][0] + T * (Contacts.Points[Prv][0] - Contacts.Points[Cur][0]); CV[CQuantity][1] = Contacts.Points[Cur][1] + T * (Contacts.Points[Prv][1] - Contacts.Points[Cur][1]); CV[CQuantity][2] = Contacts.Points[Cur][2] + T * (Contacts.Points[Prv][2] - Contacts.Points[Cur][2]); CV[CQuantity][3] = Contacts.Points[Cur][3] + T * (Contacts.Points[Prv][3] - Contacts.Points[Cur][3]); CQuantity++; } else { // iPIndex is 0 // vertices on positive side of line Cur = 0; while (Cur < Quantity && Test[Cur] >= REAL(0.0)) { CV[CQuantity][0] = Contacts.Points[Cur][0]; CV[CQuantity][1] = Contacts.Points[Cur][1]; CV[CQuantity][2] = Contacts.Points[Cur][2]; CV[CQuantity][3] = Contacts.Points[Cur][3]; CQuantity++; Cur++; } // last clip vertex on line Prv = Cur - 1; T = Test[Cur] / (Test[Cur] - Test[Prv]); CV[CQuantity][0] = Contacts.Points[Cur][0] + T * (Contacts.Points[Prv][0] - Contacts.Points[Cur][0]); CV[CQuantity][1] = Contacts.Points[Cur][1] + T * (Contacts.Points[Prv][1] - Contacts.Points[Cur][1]); CV[CQuantity][2] = Contacts.Points[Cur][2] + T * (Contacts.Points[Prv][2] - Contacts.Points[Cur][2]); CV[CQuantity][3] = Contacts.Points[Cur][3] + T * (Contacts.Points[Prv][3] - Contacts.Points[Cur][3]); CQuantity++; // skip vertices on negative side while (Cur < Quantity && Test[Cur] < REAL(0.0)) { Cur++; } // first clip vertex on line if (Cur < Quantity) { Prv = Cur - 1; T = Test[Cur] / (Test[Cur] - Test[Prv]); CV[CQuantity][0] = Contacts.Points[Cur][0] + T * (Contacts.Points[Prv][0] - Contacts.Points[Cur][0]); CV[CQuantity][1] = Contacts.Points[Cur][1] + T * (Contacts.Points[Prv][1] - Contacts.Points[Cur][1]); CV[CQuantity][2] = Contacts.Points[Cur][2] + T * (Contacts.Points[Prv][2] - Contacts.Points[Cur][2]); CV[CQuantity][3] = Contacts.Points[Cur][3] + T * (Contacts.Points[Prv][3] - Contacts.Points[Cur][3]); CQuantity++; // vertices on positive side of line while (Cur < Quantity && Test[Cur] >= REAL(0.0)) { CV[CQuantity][0] = Contacts.Points[Cur][0]; CV[CQuantity][1] = Contacts.Points[Cur][1]; CV[CQuantity][2] = Contacts.Points[Cur][2]; CV[CQuantity][3] = Contacts.Points[Cur][3]; CQuantity++; Cur++; } } else { // iCur = 0 Prv = Quantity - 1; T = Test[0] / (Test[0] - Test[Prv]); CV[CQuantity][0] = Contacts.Points[0][0] + T * (Contacts.Points[Prv][0] - Contacts.Points[0][0]); CV[CQuantity][1] = Contacts.Points[0][1] + T * (Contacts.Points[Prv][1] - Contacts.Points[0][1]); CV[CQuantity][2] = Contacts.Points[0][2] + T * (Contacts.Points[Prv][2] - Contacts.Points[0][2]); CV[CQuantity][3] = Contacts.Points[0][3] + T * (Contacts.Points[Prv][3] - Contacts.Points[0][3]); CQuantity++; } } Quantity = CQuantity; memcpy( Contacts.Points, CV, CQuantity * sizeof(dVector3) ); } // else polygon fully on positive side of plane, nothing to do Contacts.Count = Quantity; } else { Contacts.Count = 0; // This should not happen, but for safety } } // Determine if a potential collision point is // // static int ExamineContactPoint(dVector3* v_col, dVector3 in_n, dVector3 in_point) { // Cast a ray from in_point, along the collison normal. Does it intersect the // collision face. dReal t, u, v; if (!RayTriangleIntersect(in_point, in_n, v_col[0], v_col[1], v_col[2], &t, &u, &v)) return 0; else return 1; } // RayTriangleIntersect - If an intersection is found, t contains the // distance along the ray (dir) and u/v contain u/v coordinates into // the triangle. Returns 0 if no hit is found // From "Real-Time Rendering," page 305 // static int RayTriangleIntersect(const dVector3 orig, const dVector3 dir, const dVector3 vert0, const dVector3 vert1,const dVector3 vert2, dReal *t,dReal *u,dReal *v) { dReal edge1[3], edge2[3], tvec[3], pvec[3], qvec[3]; dReal det,inv_det; // find vectors for two edges sharing vert0 SUB(edge1, vert1, vert0); SUB(edge2, vert2, vert0); // begin calculating determinant - also used to calculate U parameter CROSS(pvec, dir, edge2); // if determinant is near zero, ray lies in plane of triangle det = DOT(edge1, pvec); if ((det > REAL(-0.001)) && (det < REAL(0.001))) return 0; inv_det = 1.0 / det; // calculate distance from vert0 to ray origin SUB(tvec, orig, vert0); // calculate U parameter and test bounds *u = DOT(tvec, pvec) * inv_det; if ((*u < 0.0) || (*u > 1.0)) return 0; // prepare to test V parameter CROSS(qvec, tvec, edge1); // calculate V parameter and test bounds *v = DOT(dir, qvec) * inv_det; if ((*v < 0.0) || ((*u + *v) > 1.0)) return 0; // calculate t, ray intersects triangle *t = DOT(edge2, qvec) * inv_det; return 1; } static bool SimpleUnclippedTest(dVector3 in_CoplanarPt, dVector3 in_v, dVector3 in_elt, dVector3 in_n, dVector3* in_col_v, dReal &out_depth) { dReal dp = 0.0; dReal contact_elt_length; DEPTH(dp, in_CoplanarPt, in_v, in_n); if (dp >= 0.0) { // if the penetration depth (calculated above) is more than // the contact point's ELT, then we've chosen the wrong face // and should switch faces contact_elt_length = dFabs(dCalcVectorDot3(in_elt, in_n)); if (dp == 0.0) dp = dMin(DISTANCE_EPSILON, contact_elt_length); if ((contact_elt_length < SMALL_ELT) && (dp < EXPANDED_ELT_THRESH)) dp = contact_elt_length; if ( (dp > 0.0) && (dp <= contact_elt_length)) { // Add a contact if ( ExamineContactPoint(in_col_v, in_n, in_v) ) { out_depth = dp; return true; } } } return false; } // Generate a "unique" contact. A unique contact has a unique // position or normal. If the potential contact has the same // position and normal as an existing contact, but a larger // penetration depth, this new depth is used instead // static void GenerateContact(int in_Flags, dContactGeom* in_Contacts, int in_Stride, dxTriMesh* in_TriMesh1, dxTriMesh* in_TriMesh2, int TriIndex1, int TriIndex2, const dVector3 in_ContactPos, const dVector3 in_Normal, dReal in_Depth, int& OutTriCount) { /* NOTE by Oleh_Derevenko: This function is called after maximal number of contacts has already been collected because it has a side effect of replacing penetration depth of existing contact with larger penetration depth of another matching normal contact. If this logic is not necessary any more, you can bail out on reach of contact number maximum immediately in dCollideTTL(). You will also need to correct conditional statements after invocations of GenerateContact() in dCollideTTL(). */ dIASSERT(in_Depth >= 0.0); //if (in_Depth < 0.0) -- the function is always called with depth >= 0 // return; do { dContactGeom* Contact; dVector3 diff; if (!(in_Flags & CONTACTS_UNIMPORTANT)) { bool duplicate = false; for (int i=0; ipos); if (dCalcVectorDot3(diff, diff) < dEpsilon) { // same normal? if (REAL(1.0) - dFabs(dCalcVectorDot3(in_Normal, Contact->normal)) < dEpsilon) { if (in_Depth > Contact->depth) { Contact->depth = in_Depth; SMULT( Contact->normal, in_Normal, -1.0); Contact->normal[3] = 0.0; } duplicate = true; /* NOTE by Oleh_Derevenko: There may be a case when two normals are close to each other but no duplicate while third normal is detected to be duplicate for both of them. This is the only reason I can think of, there is no "break" statement. Perhaps author considered it to be logical that the third normal would replace the depth in both of initial contacts. However, I consider it a questionable practice which should not be applied without deep understanding of underlaying physics. Even more, is this situation with close normal triplet acceptable at all? Should not be two initial contacts reduced to one (replaced with the latter)? If you know the answers for these questions, you may want to change this code. See the same statement in GenerateContact() of collision_trimesh_box.cpp */ } } } if (duplicate || OutTriCount == (in_Flags & NUMC_MASK)) { break; } } else { dIASSERT(OutTriCount < (in_Flags & NUMC_MASK)); } // Add a new contact Contact = SAFECONTACT(in_Flags, in_Contacts, OutTriCount, in_Stride); SET( Contact->pos, in_ContactPos ); Contact->pos[3] = 0.0; SMULT( Contact->normal, in_Normal, -1.0); Contact->normal[3] = 0.0; Contact->depth = in_Depth; Contact->g1 = in_TriMesh1; Contact->g2 = in_TriMesh2; Contact->side1 = TriIndex1; Contact->side2 = TriIndex2; OutTriCount++; } while (false); } #endif // dTRIMESH_OPCODE_USE_OLD_TRIMESH_TRIMESH_COLLIDER #endif // dTRIMESH_OPCODE #endif // dTRIMESH_ENABLED ode-0.16/ode/src/collision_cylinder_plane.cpp0000664000175200017520000002234213403272463016252 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* * Cylinder-Plane collider by Christoph Beyer ( boernerb@web.de ) * * This testing basically comes down to testing the intersection * of the cylinder caps (discs) with the plane. * */ #include #include #include #include "config.h" #include "matrix.h" #include "odemath.h" #include "collision_kernel.h" // for dxGeom #include "collision_util.h" int dCollideCylinderPlane(dxGeom *Cylinder, dxGeom *Plane, int flags, dContactGeom *contact, int skip) { dIASSERT (skip >= (int)sizeof(dContactGeom)); dIASSERT (Cylinder->type == dCylinderClass); dIASSERT (Plane->type == dPlaneClass); dIASSERT ((flags & NUMC_MASK) >= 1); int GeomCount = 0; // count of used contactgeoms #ifdef dSINGLE const dReal toleranz = REAL(0.0001); #endif #ifdef dDOUBLE const dReal toleranz = REAL(0.0000001); #endif // Get the properties of the cylinder (length+radius) dReal radius, length; dGeomCylinderGetParams(Cylinder, &radius, &length); dVector3 &cylpos = Cylinder->final_posr->pos; // and the plane dVector4 planevec; dGeomPlaneGetParams(Plane, planevec); dVector3 PlaneNormal = {planevec[0],planevec[1],planevec[2]}; //dVector3 PlanePos = {planevec[0] * planevec[3],planevec[1] * planevec[3],planevec[2] * planevec[3]}; dVector3 G1Pos1, G1Pos2, vDir1; vDir1[0] = Cylinder->final_posr->R[2]; vDir1[1] = Cylinder->final_posr->R[6]; vDir1[2] = Cylinder->final_posr->R[10]; dReal s; s = length * REAL(0.5); G1Pos2[0] = vDir1[0] * s + cylpos[0]; G1Pos2[1] = vDir1[1] * s + cylpos[1]; G1Pos2[2] = vDir1[2] * s + cylpos[2]; G1Pos1[0] = vDir1[0] * -s + cylpos[0]; G1Pos1[1] = vDir1[1] * -s + cylpos[1]; G1Pos1[2] = vDir1[2] * -s + cylpos[2]; dVector3 C; // parallel-check s = vDir1[0] * PlaneNormal[0] + vDir1[1] * PlaneNormal[1] + vDir1[2] * PlaneNormal[2]; if(s < 0) s += REAL(1.0); // is ca. 0, if vDir1 and PlaneNormal are parallel else s -= REAL(1.0); // is ca. 0, if vDir1 and PlaneNormal are parallel if(s < toleranz && s > (-toleranz)) { // discs are parallel to the plane // 1.compute if, and where contacts are dVector3 P; s = planevec[3] - dVector3Dot(planevec, G1Pos1); dReal t; t = planevec[3] - dVector3Dot(planevec, G1Pos2); if(s >= t) // s == t does never happen, { if(s >= 0) { // 1. Disc dVector3Copy(G1Pos1, P); } else return GeomCount; // no contacts } else { if(t >= 0) { // 2. Disc dVector3Copy(G1Pos2, P); } else return GeomCount; // no contacts } // 2. generate a coordinate-system on the disc dVector3 V1, V2; if(vDir1[0] < toleranz && vDir1[0] > (-toleranz)) { // not x-axis V1[0] = vDir1[0] + REAL(1.0); // random value V1[1] = vDir1[1]; V1[2] = vDir1[2]; } else { // maybe x-axis V1[0] = vDir1[0]; V1[1] = vDir1[1] + REAL(1.0); // random value V1[2] = vDir1[2]; } // V1 is now another direction than vDir1 // Cross-product dVector3Cross(V1, vDir1, V2); // make unit V2 t = dVector3Length(V2); t = radius / t; dVector3Scale(V2, t); // cross again dVector3Cross(V2, vDir1, V1); // |V2| is 'radius' and vDir1 unit, so |V1| is 'radius' // V1 = first axis // V2 = second axis // 3. generate contactpoints // Potential contact 1 dVector3Add(P, V1, contact->pos); contact->depth = planevec[3] - dVector3Dot(planevec, contact->pos); if(contact->depth > 0) { dVector3Copy(PlaneNormal, contact->normal); contact->g1 = Cylinder; contact->g2 = Plane; contact->side1 = -1; contact->side2 = -1; GeomCount++; if( GeomCount >= (flags & NUMC_MASK)) return GeomCount; // enough contactgeoms contact = (dContactGeom *)((char *)contact + skip); } // Potential contact 2 dVector3Subtract(P, V1, contact->pos); contact->depth = planevec[3] - dVector3Dot(planevec, contact->pos); if(contact->depth > 0) { dVector3Copy(PlaneNormal, contact->normal); contact->g1 = Cylinder; contact->g2 = Plane; contact->side1 = -1; contact->side2 = -1; GeomCount++; if( GeomCount >= (flags & NUMC_MASK)) return GeomCount; // enough contactgeoms contact = (dContactGeom *)((char *)contact + skip); } // Potential contact 3 dVector3Add(P, V2, contact->pos); contact->depth = planevec[3] - dVector3Dot(planevec, contact->pos); if(contact->depth > 0) { dVector3Copy(PlaneNormal, contact->normal); contact->g1 = Cylinder; contact->g2 = Plane; contact->side1 = -1; contact->side2 = -1; GeomCount++; if( GeomCount >= (flags & NUMC_MASK)) return GeomCount; // enough contactgeoms contact = (dContactGeom *)((char *)contact + skip); } // Potential contact 4 dVector3Subtract(P, V2, contact->pos); contact->depth = planevec[3] - dVector3Dot(planevec, contact->pos); if(contact->depth > 0) { dVector3Copy(PlaneNormal, contact->normal); contact->g1 = Cylinder; contact->g2 = Plane; contact->side1 = -1; contact->side2 = -1; GeomCount++; if( GeomCount >= (flags & NUMC_MASK)) return GeomCount; // enough contactgeoms contact = (dContactGeom *)((char *)contact + skip); } } else { dReal t = dVector3Dot(PlaneNormal, vDir1); C[0] = vDir1[0] * t - PlaneNormal[0]; C[1] = vDir1[1] * t - PlaneNormal[1]; C[2] = vDir1[2] * t - PlaneNormal[2]; s = dVector3Length(C); // move C onto the circle s = radius / s; dVector3Scale(C, s); // deepest point of disc 1 dVector3Add(C, G1Pos1, contact->pos); // depth of the deepest point contact->depth = planevec[3] - dVector3Dot(planevec, contact->pos); if(contact->depth >= 0) { dVector3Copy(PlaneNormal, contact->normal); contact->g1 = Cylinder; contact->g2 = Plane; contact->side1 = -1; contact->side2 = -1; GeomCount++; if( GeomCount >= (flags & NUMC_MASK)) return GeomCount; // enough contactgeoms contact = (dContactGeom *)((char *)contact + skip); } // C is still computed // deepest point of disc 2 dVector3Add(C, G1Pos2, contact->pos); // depth of the deepest point contact->depth = planevec[3] - planevec[0] * contact->pos[0] - planevec[1] * contact->pos[1] - planevec[2] * contact->pos[2]; if(contact->depth >= 0) { dVector3Copy(PlaneNormal, contact->normal); contact->g1 = Cylinder; contact->g2 = Plane; contact->side1 = -1; contact->side2 = -1; GeomCount++; if( GeomCount >= (flags & NUMC_MASK)) return GeomCount; // enough contactgeoms contact = (dContactGeom *)((char *)contact + skip); } } return GeomCount; } ode-0.16/ode/src/collision_trimesh_box.cpp0000664000175200017520000012334613403272463015613 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /************************************************************************* * * * Triangle-box collider by Alen Ladavac and Vedran Klanac. * * Ported to ODE by Oskari Nyman. * * * *************************************************************************/ #include #include #include "config.h" #include "matrix.h" #include "odemath.h" #include "collision_util.h" #include "collision_trimesh_internal.h" #if dTRIMESH_ENABLED // largest number, double or float #if defined(dSINGLE) #define MAXVALUE FLT_MAX #else #define MAXVALUE DBL_MAX #endif // dVector3 // r=a-b #define SUBTRACT(a,b,r) dSubtractVectors3(r, a, b) // dVector3 // a=b #define SET(a,b) dCopyVector3(a, b) // dMatrix3 // a=b #define SETM(a,b) dCopyMatrix4x4(a, b) // dVector3 // r=a+b #define ADD(a,b,r) dAddVectors3(r, a, b) // dMatrix3, int, dVector3 // v=column a from m #define GETCOL(m,a,v) dGetMatrixColumn3(v, m, a) // dVector4, dVector3 // distance between plane p and point v #define POINTDISTANCE(p,v) dPointPlaneDistance(v, p) // dVector4, dVector3, dReal // construct plane from normal and d #define CONSTRUCTPLANE(plane,normal,d) dConstructPlane(normal, d, plane) // dVector3 // length of vector a #define LENGTHOF(a) dCalcVectorLength3(a) struct sTrimeshBoxColliderData { sTrimeshBoxColliderData(): m_iBestAxis(0), m_iExitAxis(0), m_ctContacts(0) {} void SetupInitialContext(dxTriMesh *TriMesh, dxGeom *BoxGeom, int Flags, dContactGeom* Contacts, int Stride); void TestCollisionForSingleTriangle(int Triint, dVector3 dv[3], bool &bOutFinishSearching); bool _cldTestNormal(dReal fp0, dReal fR, dVector3 vNormal, int iAxis); bool _cldTestFace(dReal fp0, dReal fp1, dReal fp2, dReal fR, dReal fD, dVector3 vNormal, int iAxis); bool _cldTestEdge(dReal fp0, dReal fp1, dReal fR, dReal fD, dVector3 vNormal, int iAxis); bool _cldTestSeparatingAxes(const dVector3 &v0, const dVector3 &v1, const dVector3 &v2); void _cldClipping(const dVector3 &v0, const dVector3 &v1, const dVector3 &v2, int TriIndex); bool _cldTestOneTriangle(const dVector3 &v0, const dVector3 &v1, const dVector3 &v2, int TriIndex); void GenerateContact(int TriIndex, const dVector3 in_ContactPos, const dVector3 in_Normal, dReal in_Depth); // box data dMatrix3 m_mHullBoxRot; dVector3 m_vHullBoxPos; dVector3 m_vBoxHalfSize; // mesh data dVector3 m_vHullDstPos; // global collider data dVector3 m_vBestNormal; dReal m_fBestDepth; int m_iBestAxis; int m_iExitAxis; dVector3 m_vE0, m_vE1, m_vE2, m_vN; // global info for contact creation int m_iFlags; dContactGeom *m_ContactGeoms; int m_iStride; dxGeom *m_Geom1; dxGeom *m_Geom2; int m_ctContacts; }; // Test normal of mesh face as separating axis for intersection bool sTrimeshBoxColliderData::_cldTestNormal(dReal fp0, dReal fR, dVector3 vNormal, int iAxis) { // calculate overlapping interval of box and triangle dReal fDepth = fR+fp0; // if we do not overlap if ( fDepth<0 ) { // do nothing return false; } // calculate normal's length dReal fLength = LENGTHOF(vNormal); // if long enough if ( fLength > 0.0f ) { dReal fOneOverLength = 1.0f/fLength; // normalize depth fDepth = fDepth*fOneOverLength; // get minimum depth if (fDepth < m_fBestDepth) { m_vBestNormal[0] = -vNormal[0]*fOneOverLength; m_vBestNormal[1] = -vNormal[1]*fOneOverLength; m_vBestNormal[2] = -vNormal[2]*fOneOverLength; m_iBestAxis = iAxis; //dAASSERT(fDepth>=0); m_fBestDepth = fDepth; } } return true; } // Test box axis as separating axis bool sTrimeshBoxColliderData::_cldTestFace(dReal fp0, dReal fp1, dReal fp2, dReal fR, dReal fD, dVector3 vNormal, int iAxis) { dReal fMin, fMax; // find min of triangle interval if ( fp0 < fp1 ) { if ( fp0 < fp2 ) { fMin = fp0; } else { fMin = fp2; } } else { if( fp1 < fp2 ) { fMin = fp1; } else { fMin = fp2; } } // find max of triangle interval if ( fp0 > fp1 ) { if ( fp0 > fp2 ) { fMax = fp0; } else { fMax = fp2; } } else { if( fp1 > fp2 ) { fMax = fp1; } else { fMax = fp2; } } // calculate minimum and maximum depth dReal fDepthMin = fR - fMin; dReal fDepthMax = fMax + fR; // if we dont't have overlapping interval if ( fDepthMin < 0 || fDepthMax < 0 ) { // do nothing return false; } dReal fDepth = 0; // if greater depth is on negative side if ( fDepthMin > fDepthMax ) { // use smaller depth (one from positive side) fDepth = fDepthMax; // flip normal direction vNormal[0] = -vNormal[0]; vNormal[1] = -vNormal[1]; vNormal[2] = -vNormal[2]; fD = -fD; // if greater depth is on positive side } else { // use smaller depth (one from negative side) fDepth = fDepthMin; } // if lower depth than best found so far if (fDepth < m_fBestDepth) { // remember current axis as best axis m_vBestNormal[0] = vNormal[0]; m_vBestNormal[1] = vNormal[1]; m_vBestNormal[2] = vNormal[2]; m_iBestAxis = iAxis; //dAASSERT(fDepth>=0); m_fBestDepth = fDepth; } return true; } // Test cross products of box axis and triangle edges as separating axis bool sTrimeshBoxColliderData::_cldTestEdge(dReal fp0, dReal fp1, dReal fR, dReal fD, dVector3 vNormal, int iAxis) { dReal fMin, fMax; // ===== Begin Patch by Francisco Leon, 2006/10/28 ===== // Fixed Null Normal. This prevents boxes passing // through trimeshes at certain contact angles fMin = vNormal[0] * vNormal[0] + vNormal[1] * vNormal[1] + vNormal[2] * vNormal[2]; if ( fMin <= dEpsilon ) /// THIS NORMAL WOULD BE DANGEROUS return true; // ===== Ending Patch by Francisco Leon ===== // calculate min and max interval values if ( fp0 < fp1 ) { fMin = fp0; fMax = fp1; } else { fMin = fp1; fMax = fp0; } // check if we overlapp dReal fDepthMin = fR - fMin; dReal fDepthMax = fMax + fR; // if we don't overlapp if ( fDepthMin < 0 || fDepthMax < 0 ) { // do nothing return false; } dReal fDepth; // if greater depth is on negative side if ( fDepthMin > fDepthMax ) { // use smaller depth (one from positive side) fDepth = fDepthMax; // flip normal direction vNormal[0] = -vNormal[0]; vNormal[1] = -vNormal[1]; vNormal[2] = -vNormal[2]; fD = -fD; // if greater depth is on positive side } else { // use smaller depth (one from negative side) fDepth = fDepthMin; } // calculate normal's length dReal fLength = LENGTHOF(vNormal); // if long enough if ( fLength > 0.0f ) { // normalize depth dReal fOneOverLength = 1.0f/fLength; fDepth = fDepth*fOneOverLength; fD*=fOneOverLength; // if lower depth than best found so far (favor face over edges) if (fDepth*1.5f < m_fBestDepth) { // remember current axis as best axis m_vBestNormal[0] = vNormal[0]*fOneOverLength; m_vBestNormal[1] = vNormal[1]*fOneOverLength; m_vBestNormal[2] = vNormal[2]*fOneOverLength; m_iBestAxis = iAxis; //dAASSERT(fDepth>=0); m_fBestDepth = fDepth; } } return true; } // clip polygon with plane and generate new polygon points static void _cldClipPolyToPlane( dVector3 avArrayIn[], int ctIn, dVector3 avArrayOut[], int &ctOut, const dVector4 &plPlane ) { // start with no output points ctOut = 0; int i0 = ctIn-1; // for each edge in input polygon for (int i1=0; i1= 0 ) { // emit point avArrayOut[ctOut][0] = avArrayIn[i0][0]; avArrayOut[ctOut][1] = avArrayIn[i0][1]; avArrayOut[ctOut][2] = avArrayIn[i0][2]; ctOut++; } // if points are on different sides if( (fDistance0 > 0 && fDistance1 < 0) || ( fDistance0 < 0 && fDistance1 > 0) ) { // find intersection point of edge and plane dVector3 vIntersectionPoint; vIntersectionPoint[0]= avArrayIn[i0][0] - (avArrayIn[i0][0]-avArrayIn[i1][0])*fDistance0/(fDistance0-fDistance1); vIntersectionPoint[1]= avArrayIn[i0][1] - (avArrayIn[i0][1]-avArrayIn[i1][1])*fDistance0/(fDistance0-fDistance1); vIntersectionPoint[2]= avArrayIn[i0][2] - (avArrayIn[i0][2]-avArrayIn[i1][2])*fDistance0/(fDistance0-fDistance1); // emit intersection point avArrayOut[ctOut][0] = vIntersectionPoint[0]; avArrayOut[ctOut][1] = vIntersectionPoint[1]; avArrayOut[ctOut][2] = vIntersectionPoint[2]; ctOut++; } } } bool sTrimeshBoxColliderData::_cldTestSeparatingAxes(const dVector3 &v0, const dVector3 &v1, const dVector3 &v2) { // reset best axis m_iBestAxis = 0; m_iExitAxis = -1; m_fBestDepth = MAXVALUE; // calculate edges SUBTRACT(v1,v0,m_vE0); SUBTRACT(v2,v0,m_vE1); SUBTRACT(m_vE1,m_vE0,m_vE2); // calculate poly normal dCalcVectorCross3(m_vN,m_vE0,m_vE1); // calculate length of face normal dReal fNLen = LENGTHOF(m_vN); // Even though all triangles might be initially valid, // a triangle may degenerate into a segment after applying // space transformation. if (!fNLen) { return false; } // extract box axes as vectors dVector3 vA0,vA1,vA2; GETCOL(m_mHullBoxRot,0,vA0); GETCOL(m_mHullBoxRot,1,vA1); GETCOL(m_mHullBoxRot,2,vA2); // box halfsizes dReal fa0 = m_vBoxHalfSize[0]; dReal fa1 = m_vBoxHalfSize[1]; dReal fa2 = m_vBoxHalfSize[2]; // calculate relative position between box and triangle dVector3 vD; SUBTRACT(v0,m_vHullBoxPos,vD); dVector3 vL; dReal fp0, fp1, fp2, fR, fD; // Test separating axes for intersection // ************************************************ // Axis 1 - Triangle Normal SET(vL,m_vN); fp0 = dCalcVectorDot3(vL,vD); fp1 = fp0; fp2 = fp0; fR=fa0*dFabs( dCalcVectorDot3(m_vN,vA0) ) + fa1 * dFabs( dCalcVectorDot3(m_vN,vA1) ) + fa2 * dFabs( dCalcVectorDot3(m_vN,vA2) ); if (!_cldTestNormal(fp0, fR, vL, 1)) { m_iExitAxis=1; return false; } // ************************************************ // Test Faces // ************************************************ // Axis 2 - Box X-Axis SET(vL,vA0); fD = dCalcVectorDot3(vL,m_vN)/fNLen; fp0 = dCalcVectorDot3(vL,vD); fp1 = fp0 + dCalcVectorDot3(vA0,m_vE0); fp2 = fp0 + dCalcVectorDot3(vA0,m_vE1); fR = fa0; if (!_cldTestFace(fp0, fp1, fp2, fR, fD, vL, 2)) { m_iExitAxis=2; return false; } // ************************************************ // ************************************************ // Axis 3 - Box Y-Axis SET(vL,vA1); fD = dCalcVectorDot3(vL,m_vN)/fNLen; fp0 = dCalcVectorDot3(vL,vD); fp1 = fp0 + dCalcVectorDot3(vA1,m_vE0); fp2 = fp0 + dCalcVectorDot3(vA1,m_vE1); fR = fa1; if (!_cldTestFace(fp0, fp1, fp2, fR, fD, vL, 3)) { m_iExitAxis=3; return false; } // ************************************************ // ************************************************ // Axis 4 - Box Z-Axis SET(vL,vA2); fD = dCalcVectorDot3(vL,m_vN)/fNLen; fp0 = dCalcVectorDot3(vL,vD); fp1 = fp0 + dCalcVectorDot3(vA2,m_vE0); fp2 = fp0 + dCalcVectorDot3(vA2,m_vE1); fR = fa2; if (!_cldTestFace(fp0, fp1, fp2, fR, fD, vL, 4)) { m_iExitAxis=4; return false; } // ************************************************ // Test Edges // ************************************************ // Axis 5 - Box X-Axis cross Edge0 dCalcVectorCross3(vL,vA0,m_vE0); fD = dCalcVectorDot3(vL,m_vN)/fNLen; fp0 = dCalcVectorDot3(vL,vD); fp1 = fp0; fp2 = fp0 + dCalcVectorDot3(vA0,m_vN); fR = fa1 * dFabs(dCalcVectorDot3(vA2,m_vE0)) + fa2 * dFabs(dCalcVectorDot3(vA1,m_vE0)); if (!_cldTestEdge(fp1, fp2, fR, fD, vL, 5)) { m_iExitAxis=5; return false; } // ************************************************ // ************************************************ // Axis 6 - Box X-Axis cross Edge1 dCalcVectorCross3(vL,vA0,m_vE1); fD = dCalcVectorDot3(vL,m_vN)/fNLen; fp0 = dCalcVectorDot3(vL,vD); fp1 = fp0 - dCalcVectorDot3(vA0,m_vN); fp2 = fp0; fR = fa1 * dFabs(dCalcVectorDot3(vA2,m_vE1)) + fa2 * dFabs(dCalcVectorDot3(vA1,m_vE1)); if (!_cldTestEdge(fp0, fp1, fR, fD, vL, 6)) { m_iExitAxis=6; return false; } // ************************************************ // ************************************************ // Axis 7 - Box X-Axis cross Edge2 dCalcVectorCross3(vL,vA0,m_vE2); fD = dCalcVectorDot3(vL,m_vN)/fNLen; fp0 = dCalcVectorDot3(vL,vD); fp1 = fp0 - dCalcVectorDot3(vA0,m_vN); fp2 = fp0 - dCalcVectorDot3(vA0,m_vN); fR = fa1 * dFabs(dCalcVectorDot3(vA2,m_vE2)) + fa2 * dFabs(dCalcVectorDot3(vA1,m_vE2)); if (!_cldTestEdge(fp0, fp1, fR, fD, vL, 7)) { m_iExitAxis=7; return false; } // ************************************************ // ************************************************ // Axis 8 - Box Y-Axis cross Edge0 dCalcVectorCross3(vL,vA1,m_vE0); fD = dCalcVectorDot3(vL,m_vN)/fNLen; fp0 = dCalcVectorDot3(vL,vD); fp1 = fp0; fp2 = fp0 + dCalcVectorDot3(vA1,m_vN); fR = fa0 * dFabs(dCalcVectorDot3(vA2,m_vE0)) + fa2 * dFabs(dCalcVectorDot3(vA0,m_vE0)); if (!_cldTestEdge(fp0, fp2, fR, fD, vL, 8)) { m_iExitAxis=8; return false; } // ************************************************ // ************************************************ // Axis 9 - Box Y-Axis cross Edge1 dCalcVectorCross3(vL,vA1,m_vE1); fD = dCalcVectorDot3(vL,m_vN)/fNLen; fp0 = dCalcVectorDot3(vL,vD); fp1 = fp0 - dCalcVectorDot3(vA1,m_vN); fp2 = fp0; fR = fa0 * dFabs(dCalcVectorDot3(vA2,m_vE1)) + fa2 * dFabs(dCalcVectorDot3(vA0,m_vE1)); if (!_cldTestEdge(fp0, fp1, fR, fD, vL, 9)) { m_iExitAxis=9; return false; } // ************************************************ // ************************************************ // Axis 10 - Box Y-Axis cross Edge2 dCalcVectorCross3(vL,vA1,m_vE2); fD = dCalcVectorDot3(vL,m_vN)/fNLen; fp0 = dCalcVectorDot3(vL,vD); fp1 = fp0 - dCalcVectorDot3(vA1,m_vN); fp2 = fp0 - dCalcVectorDot3(vA1,m_vN); fR = fa0 * dFabs(dCalcVectorDot3(vA2,m_vE2)) + fa2 * dFabs(dCalcVectorDot3(vA0,m_vE2)); if (!_cldTestEdge(fp0, fp1, fR, fD, vL, 10)) { m_iExitAxis=10; return false; } // ************************************************ // ************************************************ // Axis 11 - Box Z-Axis cross Edge0 dCalcVectorCross3(vL,vA2,m_vE0); fD = dCalcVectorDot3(vL,m_vN)/fNLen; fp0 = dCalcVectorDot3(vL,vD); fp1 = fp0; fp2 = fp0 + dCalcVectorDot3(vA2,m_vN); fR = fa0 * dFabs(dCalcVectorDot3(vA1,m_vE0)) + fa1 * dFabs(dCalcVectorDot3(vA0,m_vE0)); if (!_cldTestEdge(fp0, fp2, fR, fD, vL, 11)) { m_iExitAxis=11; return false; } // ************************************************ // ************************************************ // Axis 12 - Box Z-Axis cross Edge1 dCalcVectorCross3(vL,vA2,m_vE1); fD = dCalcVectorDot3(vL,m_vN)/fNLen; fp0 = dCalcVectorDot3(vL,vD); fp1 = fp0 - dCalcVectorDot3(vA2,m_vN); fp2 = fp0; fR = fa0 * dFabs(dCalcVectorDot3(vA1,m_vE1)) + fa1 * dFabs(dCalcVectorDot3(vA0,m_vE1)); if (!_cldTestEdge(fp0, fp1, fR, fD, vL, 12)) { m_iExitAxis=12; return false; } // ************************************************ // ************************************************ // Axis 13 - Box Z-Axis cross Edge2 dCalcVectorCross3(vL,vA2,m_vE2); fD = dCalcVectorDot3(vL,m_vN)/fNLen; fp0 = dCalcVectorDot3(vL,vD); fp1 = fp0 - dCalcVectorDot3(vA2,m_vN); fp2 = fp0 - dCalcVectorDot3(vA2,m_vN); fR = fa0 * dFabs(dCalcVectorDot3(vA1,m_vE2)) + fa1 * dFabs(dCalcVectorDot3(vA0,m_vE2)); if (!_cldTestEdge(fp0, fp1, fR, fD, vL, 13)) { m_iExitAxis=13; return false; } // ************************************************ return true; } // find two closest points on two lines static bool _cldClosestPointOnTwoLines( dVector3 vPoint1, dVector3 vLenVec1, dVector3 vPoint2, dVector3 vLenVec2, dReal &fvalue1, dReal &fvalue2) { // calculate denominator dVector3 vp; SUBTRACT(vPoint2,vPoint1,vp); dReal fuaub = dCalcVectorDot3(vLenVec1,vLenVec2); dReal fq1 = dCalcVectorDot3(vLenVec1,vp); dReal fq2 = -dCalcVectorDot3(vLenVec2,vp); dReal fd = 1.0f - fuaub * fuaub; // if denominator is positive if (fd > 0.0f) { // calculate points of closest approach fd = 1.0f/fd; fvalue1 = (fq1 + fuaub*fq2)*fd; fvalue2 = (fuaub*fq1 + fq2)*fd; return true; // otherwise } else { // lines are parallel fvalue1 = 0.0f; fvalue2 = 0.0f; return false; } } // clip and generate contacts void sTrimeshBoxColliderData::_cldClipping(const dVector3 &v0, const dVector3 &v1, const dVector3 &v2, int TriIndex) { dIASSERT( !(m_iFlags & CONTACTS_UNIMPORTANT) || m_ctContacts < (m_iFlags & NUMC_MASK) ); // Do not call the function if there is no room to store results // if we have edge/edge intersection if (m_iBestAxis > 4 ) { dVector3 vub,vPb,vPa; SET(vPa,m_vHullBoxPos); // calculate point on box edge for( int i=0; i<3; i++) { dVector3 vRotCol; GETCOL(m_mHullBoxRot,i,vRotCol); dReal fSign = dCalcVectorDot3(m_vBestNormal,vRotCol) > 0 ? 1.0f : -1.0f; vPa[0] += fSign * m_vBoxHalfSize[i] * vRotCol[0]; vPa[1] += fSign * m_vBoxHalfSize[i] * vRotCol[1]; vPa[2] += fSign * m_vBoxHalfSize[i] * vRotCol[2]; } int iEdge = (m_iBestAxis-5)%3; // decide which edge is on triangle if ( iEdge == 0 ) { SET(vPb,v0); SET(vub,m_vE0); } else if ( iEdge == 1) { SET(vPb,v2); SET(vub,m_vE1); } else { SET(vPb,v1); SET(vub,m_vE2); } // setup direction parameter for face edge dNormalize3(vub); dReal fParam1, fParam2; // setup direction parameter for box edge dVector3 vua; int col=(m_iBestAxis-5)/3; GETCOL(m_mHullBoxRot,col,vua); // find two closest points on both edges _cldClosestPointOnTwoLines( vPa, vua, vPb, vub, fParam1, fParam2 ); vPa[0] += vua[0]*fParam1; vPa[1] += vua[1]*fParam1; vPa[2] += vua[2]*fParam1; vPb[0] += vub[0]*fParam2; vPb[1] += vub[1]*fParam2; vPb[2] += vub[2]*fParam2; // calculate collision point dVector3 vPntTmp; ADD(vPa,vPb,vPntTmp); vPntTmp[0]*=0.5f; vPntTmp[1]*=0.5f; vPntTmp[2]*=0.5f; // generate contact point between two closest points GenerateContact(TriIndex, vPntTmp, m_vBestNormal, m_fBestDepth); // if triangle is the referent face then clip box to triangle face } else if (m_iBestAxis == 1) { dVector3 vNormal2; vNormal2[0]=-m_vBestNormal[0]; vNormal2[1]=-m_vBestNormal[1]; vNormal2[2]=-m_vBestNormal[2]; // vNr is normal in box frame, pointing from triangle to box dMatrix3 mTransposed; mTransposed[0*4+0]=m_mHullBoxRot[0*4+0]; mTransposed[0*4+1]=m_mHullBoxRot[1*4+0]; mTransposed[0*4+2]=m_mHullBoxRot[2*4+0]; mTransposed[1*4+0]=m_mHullBoxRot[0*4+1]; mTransposed[1*4+1]=m_mHullBoxRot[1*4+1]; mTransposed[1*4+2]=m_mHullBoxRot[2*4+1]; mTransposed[2*4+0]=m_mHullBoxRot[0*4+2]; mTransposed[2*4+1]=m_mHullBoxRot[1*4+2]; mTransposed[2*4+2]=m_mHullBoxRot[2*4+2]; dVector3 vNr; vNr[0]=mTransposed[0*4+0]*vNormal2[0]+ mTransposed[0*4+1]*vNormal2[1]+ mTransposed[0*4+2]*vNormal2[2]; vNr[1]=mTransposed[1*4+0]*vNormal2[0]+ mTransposed[1*4+1]*vNormal2[1]+ mTransposed[1*4+2]*vNormal2[2]; vNr[2]=mTransposed[2*4+0]*vNormal2[0]+ mTransposed[2*4+1]*vNormal2[1]+ mTransposed[2*4+2]*vNormal2[2]; dVector3 vAbsNormal; vAbsNormal[0] = dFabs( vNr[0] ); vAbsNormal[1] = dFabs( vNr[1] ); vAbsNormal[2] = dFabs( vNr[2] ); // get closest face from box int iB0, iB1, iB2; if (vAbsNormal[1] > vAbsNormal[0]) { if (vAbsNormal[1] > vAbsNormal[2]) { iB1 = 0; iB0 = 1; iB2 = 2; } else { iB1 = 0; iB2 = 1; iB0 = 2; } } else { if (vAbsNormal[0] > vAbsNormal[2]) { iB0 = 0; iB1 = 1; iB2 = 2; } else { iB1 = 0; iB2 = 1; iB0 = 2; } } // Here find center of box face we are going to project dVector3 vCenter; dVector3 vRotCol; GETCOL(m_mHullBoxRot,iB0,vRotCol); if (vNr[iB0] > 0) { vCenter[0] = m_vHullBoxPos[0] - v0[0] - m_vBoxHalfSize[iB0] * vRotCol[0]; vCenter[1] = m_vHullBoxPos[1] - v0[1] - m_vBoxHalfSize[iB0] * vRotCol[1]; vCenter[2] = m_vHullBoxPos[2] - v0[2] - m_vBoxHalfSize[iB0] * vRotCol[2]; } else { vCenter[0] = m_vHullBoxPos[0] - v0[0] + m_vBoxHalfSize[iB0] * vRotCol[0]; vCenter[1] = m_vHullBoxPos[1] - v0[1] + m_vBoxHalfSize[iB0] * vRotCol[1]; vCenter[2] = m_vHullBoxPos[2] - v0[2] + m_vBoxHalfSize[iB0] * vRotCol[2]; } // Here find 4 corner points of box dVector3 avPoints[4]; dVector3 vRotCol2; GETCOL(m_mHullBoxRot,iB1,vRotCol); GETCOL(m_mHullBoxRot,iB2,vRotCol2); for(int x=0;x<3;x++) { avPoints[0][x] = vCenter[x] + (m_vBoxHalfSize[iB1] * vRotCol[x]) - (m_vBoxHalfSize[iB2] * vRotCol2[x]); avPoints[1][x] = vCenter[x] - (m_vBoxHalfSize[iB1] * vRotCol[x]) - (m_vBoxHalfSize[iB2] * vRotCol2[x]); avPoints[2][x] = vCenter[x] - (m_vBoxHalfSize[iB1] * vRotCol[x]) + (m_vBoxHalfSize[iB2] * vRotCol2[x]); avPoints[3][x] = vCenter[x] + (m_vBoxHalfSize[iB1] * vRotCol[x]) + (m_vBoxHalfSize[iB2] * vRotCol2[x]); } // clip Box face with 4 planes of triangle (1 face plane, 3 egde planes) dVector3 avTempArray1[9]; dVector3 avTempArray2[9]; dVector4 plPlane; int iTempCnt1=0; int iTempCnt2=0; // zeroify vectors - necessary? for(int i=0; i<9; i++) { avTempArray1[i][0]=0; avTempArray1[i][1]=0; avTempArray1[i][2]=0; avTempArray2[i][0]=0; avTempArray2[i][1]=0; avTempArray2[i][2]=0; } // Normal plane dVector3 vTemp; vTemp[0]=-m_vN[0]; vTemp[1]=-m_vN[1]; vTemp[2]=-m_vN[2]; dNormalize3(vTemp); CONSTRUCTPLANE(plPlane,vTemp,0); _cldClipPolyToPlane( avPoints, 4, avTempArray1, iTempCnt1, plPlane ); // Plane p0 dVector3 vTemp2; SUBTRACT(v1,v0,vTemp2); dCalcVectorCross3(vTemp,m_vN,vTemp2); dNormalize3(vTemp); CONSTRUCTPLANE(plPlane,vTemp,0); _cldClipPolyToPlane( avTempArray1, iTempCnt1, avTempArray2, iTempCnt2, plPlane ); // Plane p1 SUBTRACT(v2,v1,vTemp2); dCalcVectorCross3(vTemp,m_vN,vTemp2); dNormalize3(vTemp); SUBTRACT(v0,v2,vTemp2); CONSTRUCTPLANE(plPlane,vTemp,dCalcVectorDot3(vTemp2,vTemp)); _cldClipPolyToPlane( avTempArray2, iTempCnt2, avTempArray1, iTempCnt1, plPlane ); // Plane p2 SUBTRACT(v0,v2,vTemp2); dCalcVectorCross3(vTemp,m_vN,vTemp2); dNormalize3(vTemp); CONSTRUCTPLANE(plPlane,vTemp,0); _cldClipPolyToPlane( avTempArray1, iTempCnt1, avTempArray2, iTempCnt2, plPlane ); // END of clipping polygons // for each generated contact point for ( int i=0; i 0) { fTempDepth = 0; } dVector3 vPntTmp; ADD(avTempArray2[i],v0,vPntTmp); GenerateContact(TriIndex, vPntTmp, m_vBestNormal, -fTempDepth); if ((m_ctContacts | CONTACTS_UNIMPORTANT) == (m_iFlags & (NUMC_MASK | CONTACTS_UNIMPORTANT))) { break; } } //dAASSERT(m_ctContacts>0); // if box face is the referent face, then clip triangle on box face } else { // 2 <= if iBestAxis <= 4 // get normal of box face dVector3 vNormal2; SET(vNormal2,m_vBestNormal); // get indices of box axes in correct order int iA0,iA1,iA2; iA0 = m_iBestAxis-2; if ( iA0 == 0 ) { iA1 = 1; iA2 = 2; } else if ( iA0 == 1 ) { iA1 = 0; iA2 = 2; } else { iA1 = 0; iA2 = 1; } dVector3 avPoints[3]; // calculate triangle vertices in box frame SUBTRACT(v0,m_vHullBoxPos,avPoints[0]); SUBTRACT(v1,m_vHullBoxPos,avPoints[1]); SUBTRACT(v2,m_vHullBoxPos,avPoints[2]); // CLIP Polygons // define temp data for clipping dVector3 avTempArray1[9]; dVector3 avTempArray2[9]; int iTempCnt1, iTempCnt2; // zeroify vectors - necessary? for(int i=0; i<9; i++) { avTempArray1[i][0]=0; avTempArray1[i][1]=0; avTempArray1[i][2]=0; avTempArray2[i][0]=0; avTempArray2[i][1]=0; avTempArray2[i][2]=0; } // clip triangle with 5 box planes (1 face plane, 4 edge planes) dVector4 plPlane; // Normal plane dVector3 vTemp; vTemp[0]=-vNormal2[0]; vTemp[1]=-vNormal2[1]; vTemp[2]=-vNormal2[2]; CONSTRUCTPLANE(plPlane,vTemp,m_vBoxHalfSize[iA0]); _cldClipPolyToPlane( avPoints, 3, avTempArray1, iTempCnt1, plPlane ); // Plane p0 GETCOL(m_mHullBoxRot,iA1,vTemp); CONSTRUCTPLANE(plPlane,vTemp,m_vBoxHalfSize[iA1]); _cldClipPolyToPlane( avTempArray1, iTempCnt1, avTempArray2, iTempCnt2, plPlane ); // Plane p1 GETCOL(m_mHullBoxRot,iA1,vTemp); vTemp[0]=-vTemp[0]; vTemp[1]=-vTemp[1]; vTemp[2]=-vTemp[2]; CONSTRUCTPLANE(plPlane,vTemp,m_vBoxHalfSize[iA1]); _cldClipPolyToPlane( avTempArray2, iTempCnt2, avTempArray1, iTempCnt1, plPlane ); // Plane p2 GETCOL(m_mHullBoxRot,iA2,vTemp); CONSTRUCTPLANE(plPlane,vTemp,m_vBoxHalfSize[iA2]); _cldClipPolyToPlane( avTempArray1, iTempCnt1, avTempArray2, iTempCnt2, plPlane ); // Plane p3 GETCOL(m_mHullBoxRot,iA2,vTemp); vTemp[0]=-vTemp[0]; vTemp[1]=-vTemp[1]; vTemp[2]=-vTemp[2]; CONSTRUCTPLANE(plPlane,vTemp,m_vBoxHalfSize[iA2]); _cldClipPolyToPlane( avTempArray2, iTempCnt2, avTempArray1, iTempCnt1, plPlane ); // for each generated contact point for ( int i=0; i 0) { fTempDepth = 0; } // generate contact data dVector3 vPntTmp; ADD(avTempArray1[i],m_vHullBoxPos,vPntTmp); GenerateContact(TriIndex, vPntTmp, m_vBestNormal, -fTempDepth); if ((m_ctContacts | CONTACTS_UNIMPORTANT) == (m_iFlags & (NUMC_MASK | CONTACTS_UNIMPORTANT))) { break; } } //dAASSERT(m_ctContacts>0); } } // GenerateContact - Written by Jeff Smith (jeff@burri.to) // Generate a "unique" contact. A unique contact has a unique // position or normal. If the potential contact has the same // position and normal as an existing contact, but a larger // penetration depth, this new depth is used instead // void sTrimeshBoxColliderData::GenerateContact(int TriIndex, const dVector3 in_ContactPos, const dVector3 in_Normal, dReal in_Depth) { int TriCount = m_ctContacts; do { dContactGeom* TgtContact = NULL; bool deeper = false; if (!(m_iFlags & CONTACTS_UNIMPORTANT)) { dReal MinDepth = dInfinity; dContactGeom* MinContact = NULL; bool duplicate = false; for (int i = 0; i < TriCount; i++) { dContactGeom* Contact = SAFECONTACT(m_iFlags, m_ContactGeoms, i, m_iStride); // same position? dVector3 diff; dSubtractVectors3(diff, in_ContactPos, Contact->pos); if (dCalcVectorDot3(diff, diff) < dEpsilon) { // same normal? if (REAL(1.0) - dCalcVectorDot3(in_Normal, Contact->normal) < dEpsilon) { if (in_Depth > Contact->depth) { Contact->depth = in_Depth; Contact->side1 = TriIndex; } duplicate = true; break; } } if (Contact->depth < MinDepth) { MinDepth = Contact->depth; MinContact = Contact; } } if (duplicate) { break; } if (TriCount == (m_iFlags & NUMC_MASK)) { if (!(MinDepth < in_Depth)) { break; } TgtContact = MinContact; deeper = true; } } else { dIASSERT(TriCount < (m_iFlags & NUMC_MASK)); } if (!deeper) { // Add a new contact TgtContact = SAFECONTACT(m_iFlags, m_ContactGeoms, TriCount, m_iStride); TriCount++; TgtContact->pos[3] = 0.0; TgtContact->normal[3] = 0.0; TgtContact->g1 = m_Geom1; TgtContact->g2 = m_Geom2; TgtContact->side2 = -1; } TgtContact->pos[0] = in_ContactPos[0]; TgtContact->pos[1] = in_ContactPos[1]; TgtContact->pos[2] = in_ContactPos[2]; TgtContact->normal[0] = in_Normal[0]; TgtContact->normal[1] = in_Normal[1]; TgtContact->normal[2] = in_Normal[2]; TgtContact->depth = in_Depth; TgtContact->side1 = TriIndex; m_ctContacts = TriCount; } while (false); } void sTrimeshBoxColliderData::SetupInitialContext(dxTriMesh *TriMesh, dxGeom *BoxGeom, int Flags, dContactGeom* Contacts, int Stride) { // get source hull position, orientation and half size const dMatrix3& mRotBox=*(const dMatrix3*)dGeomGetRotation(BoxGeom); const dVector3& vPosBox=*(const dVector3*)dGeomGetPosition(BoxGeom); // to global SETM(m_mHullBoxRot,mRotBox); SET(m_vHullBoxPos,vPosBox); dGeomBoxGetLengths(BoxGeom, m_vBoxHalfSize); m_vBoxHalfSize[0] *= 0.5f; m_vBoxHalfSize[1] *= 0.5f; m_vBoxHalfSize[2] *= 0.5f; // get destination hull position and orientation const dVector3& vPosMesh=*(const dVector3*)dGeomGetPosition(TriMesh); // to global SET(m_vHullDstPos,vPosMesh); // global info for contact creation m_ctContacts = 0; m_iStride=Stride; m_iFlags=Flags; m_ContactGeoms=Contacts; m_Geom1=TriMesh; m_Geom2=BoxGeom; // reset stuff m_fBestDepth = MAXVALUE; m_vBestNormal[0]=0; m_vBestNormal[1]=0; m_vBestNormal[2]=0; } void sTrimeshBoxColliderData::TestCollisionForSingleTriangle(int Triint, dVector3 dv[3], bool &bOutFinishSearching) { bool finish = false; // test this triangle if (_cldTestOneTriangle(dv[0], dv[1], dv[2], Triint)) { /* NOTE by Oleh_Derevenko: The function continues checking triangles after maximal number of contacts is reached because it selects maximal penetration depths. See also comments in GenerateContact() */ finish = ((m_ctContacts | CONTACTS_UNIMPORTANT) == (m_iFlags & (NUMC_MASK | CONTACTS_UNIMPORTANT))); } bOutFinishSearching = finish; } // test one mesh triangle on intersection with given box bool sTrimeshBoxColliderData::_cldTestOneTriangle(const dVector3 &v0, const dVector3 &v1, const dVector3 &v2, int TriIndex)//, void *pvUser) { // do intersection test and find best separating axis if (!_cldTestSeparatingAxes(v0, v1, v2)) { // if not found do nothing return false; } // if best separation axis is not found if (m_iBestAxis == 0) { // this should not happen (we should already exit in that case) //dMessage (0, "best separation axis not found"); // do nothing return false; } _cldClipping(v0, v1, v2, TriIndex); return true; } // OPCODE version of box to mesh collider #if dTRIMESH_OPCODE static void dQueryBTLPotentialCollisionTriangles(OBBCollider &Collider, const sTrimeshBoxColliderData &cData, dxTriMesh *TriMesh, dxGeom *BoxGeom, OBBCache &BoxCache) { // get destination hull position and orientation const dMatrix3& mRotMesh=*(const dMatrix3*)dGeomGetRotation(TriMesh); const dVector3& vPosMesh=*(const dVector3*)dGeomGetPosition(TriMesh); Matrix4x4 MeshMatrix; const dVector3 vZeroVector3 = { REAL(0.0), }; MakeMatrix(vZeroVector3, mRotMesh, MeshMatrix); // get source hull position, orientation and half size const dMatrix3& mRotBox=*(const dMatrix3*)dGeomGetRotation(BoxGeom); const dVector3& vPosBox=*(const dVector3*)dGeomGetPosition(BoxGeom); dVector3 vOffsetPosBox; dSubtractVectors3(vOffsetPosBox, vPosBox, vPosMesh); // Make OBB OBB Box; Box.mCenter.Set(vOffsetPosBox[0], vOffsetPosBox[1], vOffsetPosBox[2]); Box.mExtents.Set(cData.m_vBoxHalfSize[0], cData.m_vBoxHalfSize[1], cData.m_vBoxHalfSize[2]); Box.mRot.Set( mRotBox[0], mRotBox[4], mRotBox[8], mRotBox[1], mRotBox[5], mRotBox[9], mRotBox[2], mRotBox[6], mRotBox[10]); // TC results if (TriMesh->getDoTC(dxTriMesh::TTC_BOX)) { dxTriMesh::BoxTC* BoxTC = 0; const int iBoxCacheSize = TriMesh->m_BoxTCCache.size(); for (int i = 0; i != iBoxCacheSize; i++){ if (TriMesh->m_BoxTCCache[i].Geom == BoxGeom){ BoxTC = &TriMesh->m_BoxTCCache[i]; break; } } if (!BoxTC){ TriMesh->m_BoxTCCache.push(dxTriMesh::BoxTC()); BoxTC = &TriMesh->m_BoxTCCache[TriMesh->m_BoxTCCache.size() - 1]; BoxTC->Geom = BoxGeom; BoxTC->FatCoeff = 1.1f; // Pierre recommends this, instead of 1.0 } // Intersect Collider.SetTemporalCoherence(true); Collider.Collide(*BoxTC, Box, TriMesh->retrieveMeshBVTreeRef(), null, &MeshMatrix); } else { Collider.SetTemporalCoherence(false); Collider.Collide(BoxCache, Box, TriMesh->retrieveMeshBVTreeRef(), null, &MeshMatrix); } } int dCollideBTL(dxGeom* g1, dxGeom* BoxGeom, int Flags, dContactGeom* Contacts, int Stride){ dIASSERT (Stride >= (int)sizeof(dContactGeom)); dIASSERT (g1->type == dTriMeshClass); dIASSERT (BoxGeom->type == dBoxClass); dIASSERT ((Flags & NUMC_MASK) >= 1); dxTriMesh* TriMesh = (dxTriMesh*)g1; sTrimeshBoxColliderData cData; cData.SetupInitialContext(TriMesh, BoxGeom, Flags, Contacts, Stride); const unsigned uiTLSKind = TriMesh->getParentSpaceTLSKind(); dIASSERT(uiTLSKind == BoxGeom->getParentSpaceTLSKind()); // The colliding spaces must use matching cleanup method TrimeshCollidersCache *pccColliderCache = GetTrimeshCollidersCache(uiTLSKind); OBBCollider& Collider = pccColliderCache->m_OBBCollider; dQueryBTLPotentialCollisionTriangles(Collider, cData, TriMesh, BoxGeom, pccColliderCache->m_DefaultBoxCache); if (!Collider.GetContactStatus()) { // no collision occurred return 0; } // Retrieve data int TriCount = Collider.GetNbTouchedPrimitives(); const int* Triangles = (const int*)Collider.GetTouchedPrimitives(); if (TriCount != 0){ if (TriMesh->m_ArrayCallback != null){ TriMesh->m_ArrayCallback(TriMesh, BoxGeom, Triangles, TriCount); } // get destination hull position and orientation const dMatrix3& mRotMesh=*(const dMatrix3*)dGeomGetRotation(TriMesh); const dVector3& vPosMesh=*(const dVector3*)dGeomGetPosition(TriMesh); // loop through all intersecting triangles for (int i = 0; i < TriCount; i++){ const int Triint = Triangles[i]; if (!TriMesh->invokeCallback(BoxGeom, Triint)) continue; dVector3 dv[3]; TriMesh->fetchMeshTriangle(dv, Triint, vPosMesh, mRotMesh); bool bFinishSearching; cData.TestCollisionForSingleTriangle(Triint, dv, bFinishSearching); if (bFinishSearching) { break; } } } return cData.m_ctContacts; } #endif // GIMPACT version of box to mesh collider #if dTRIMESH_GIMPACT int dCollideBTL(dxGeom* g1, dxGeom* BoxGeom, int Flags, dContactGeom* Contacts, int Stride) { dIASSERT (Stride >= (int)sizeof(dContactGeom)); dIASSERT (g1->type == dTriMeshClass); dIASSERT (BoxGeom->type == dBoxClass); dIASSERT ((Flags & NUMC_MASK) >= 1); dxTriMesh* TriMesh = (dxTriMesh*)g1; g1 -> recomputeAABB(); BoxGeom -> recomputeAABB(); sTrimeshBoxColliderData cData; cData.SetupInitialContext(TriMesh, BoxGeom, Flags, Contacts, Stride); //*****at first , collide box aabb******// GIM_TRIMESH * ptrimesh = &TriMesh->m_collision_trimesh; aabb3f test_aabb(BoxGeom->aabb[0], BoxGeom->aabb[1], BoxGeom->aabb[2], BoxGeom->aabb[3], BoxGeom->aabb[4], BoxGeom->aabb[5]); GDYNAMIC_ARRAY collision_result; GIM_CREATE_BOXQUERY_LIST(collision_result); gim_aabbset_box_collision(&test_aabb, &ptrimesh->m_aabbset , &collision_result); if(collision_result.m_size==0) { GIM_DYNARRAY_DESTROY(collision_result); return 0; } //*****Set globals for box collision******// //collide triangles GUINT32 * boxesresult = GIM_DYNARRAY_POINTER(GUINT32,collision_result); gim_trimesh_locks_work_data(ptrimesh); for(unsigned int i=0;i #ifdef __cplusplus template ODE_INLINE void dxtSetZero (element_type *a, sizeint n) { element_type *const aend = a + n * a_stride; for (element_type *acurr = a; acurr != aend; acurr += a_stride) { *acurr = (element_type)0; } } template ODE_INLINE void dxSetZero (element_type *a, sizeint n) { dxtSetZero<1>(a, n); } template ODE_INLINE void dxSetValue (element_type *a, sizeint n, element_type value) { element_type *const aend = a + n; for (element_type *acurr = a; acurr != aend; ++acurr) { *acurr = value; } } #else // #ifndef __cplusplus ODE_PURE_INLINE void dxSetZero (dReal *a, sizeint n) { dReal *const aend = a + n; dReal *acurr; for (acurr = a; acurr != aend; ++acurr) { *acurr = 0; } } ODE_PURE_INLINE void dxSetValue (dReal *a, sizeint n, dReal value) { dReal *const aend = a + n; dReal *acurr; for (acurr = a; acurr != aend; ++acurr) { *acurr = value; } } #endif // #ifdef __cplusplus dReal dxDot (const dReal *a, const dReal *b, unsigned n); void dxMultiply0 (dReal *A, const dReal *B, const dReal *C, unsigned p, unsigned q, unsigned r); void dxMultiply1 (dReal *A, const dReal *B, const dReal *C, unsigned p, unsigned q, unsigned r); void dxMultiply2 (dReal *A, const dReal *B, const dReal *C, unsigned p, unsigned q, unsigned r); int dxFactorCholesky (dReal *A, unsigned n, void *tmpbuf); void dxSolveCholesky (const dReal *L, dReal *b, unsigned n, void *tmpbuf); int dxInvertPDMatrix (const dReal *A, dReal *Ainv, unsigned n, void *tmpbuf); int dxIsPositiveDefinite (const dReal *A, unsigned n, void *tmpbuf); void dxLDLTAddTL (dReal *L, dReal *d, const dReal *a, unsigned n, unsigned nskip, void *tmpbuf); void dxLDLTRemove (dReal **A, const unsigned *p, dReal *L, dReal *d, unsigned n1, unsigned n2, unsigned r, unsigned nskip, void *tmpbuf); void dxRemoveRowCol (dReal *A, unsigned n, unsigned nskip, unsigned r); ODE_PURE_INLINE sizeint dxEstimateFactorCholeskyTmpbufSize(unsigned n) { return dPAD(n) * sizeof(dReal); } ODE_PURE_INLINE sizeint dxEstimateSolveCholeskyTmpbufSize(unsigned n) { return dPAD(n) * sizeof(dReal); } ODE_PURE_INLINE sizeint dxEstimateInvertPDMatrixTmpbufSize(unsigned n) { sizeint FactorCholesky_size = dxEstimateFactorCholeskyTmpbufSize(n); sizeint SolveCholesky_size = dxEstimateSolveCholeskyTmpbufSize(n); sizeint MaxCholesky_size = FactorCholesky_size > SolveCholesky_size ? FactorCholesky_size : SolveCholesky_size; return (sizeint)dPAD(n) * (n + 1) * sizeof(dReal) + MaxCholesky_size; } ODE_PURE_INLINE sizeint dxEstimateIsPositiveDefiniteTmpbufSize(unsigned n) { return (sizeint)dPAD(n) * n * sizeof(dReal) + dxEstimateFactorCholeskyTmpbufSize(n); } ODE_PURE_INLINE sizeint dxEstimateLDLTAddTLTmpbufSize(unsigned nskip) { return nskip * (2 * sizeof(dReal)); } ODE_PURE_INLINE sizeint dxEstimateLDLTRemoveTmpbufSize(unsigned n2, unsigned nskip) { return n2 * sizeof(dReal) + dxEstimateLDLTAddTLTmpbufSize(nskip); } /* For internal use */ #define dSetZero(a, n) dxSetZero(a, n) #define dSetValue(a, n, value) dxSetValue(a, n, value) #define dDot(a, b, n) dxDot(a, b, n) #define dMultiply0(A, B, C, p, q, r) dxMultiply0(A, B, C, p, q, r) #define dMultiply1(A, B, C, p, q, r) dxMultiply1(A, B, C, p, q, r) #define dMultiply2(A, B, C, p, q, r) dxMultiply2(A, B, C, p, q, r) #define dFactorCholesky(A, n, tmpbuf) dxFactorCholesky(A, n, tmpbuf) #define dSolveCholesky(L, b, n, tmpbuf) dxSolveCholesky(L, b, n, tmpbuf) #define dInvertPDMatrix(A, Ainv, n, tmpbuf) dxInvertPDMatrix(A, Ainv, n, tmpbuf) #define dIsPositiveDefinite(A, n, tmpbuf) dxIsPositiveDefinite(A, n, tmpbuf) #define dLDLTAddTL(L, d, a, n, nskip, tmpbuf) dxLDLTAddTL(L, d, a, n, nskip, tmpbuf) #define dLDLTRemove(A, p, L, d, n1, n2, r, nskip, tmpbuf) dxLDLTRemove(A, p, L, d, n1, n2, r, nskip, tmpbuf) #define dRemoveRowCol(A, n, nskip, r) dxRemoveRowCol(A, n, nskip, r) #define dEstimateFactorCholeskyTmpbufSize(n) dxEstimateFactorCholeskyTmpbufSize(n) #define dEstimateSolveCholeskyTmpbufSize(n) dxEstimateSolveCholeskyTmpbufSize(n) #define dEstimateInvertPDMatrixTmpbufSize(n) dxEstimateInvertPDMatrixTmpbufSize(n) #define dEstimateIsPositiveDefiniteTmpbufSize(n) dxEstimateIsPositiveDefiniteTmpbufSize(n) #define dEstimateLDLTAddTLTmpbufSize(nskip) dxEstimateLDLTAddTLTmpbufSize(nskip) #define dEstimateLDLTRemoveTmpbufSize(n2, nskip) dxEstimateLDLTRemoveTmpbufSize(n2, nskip) #endif // #ifndef _ODE__PRIVATE_MATRIX_H_ ode-0.16/ode/src/joints/0000775000175200017520000000000013403273061012061 500000000000000ode-0.16/ode/src/joints/slider.h0000664000175200017520000000510213403272463013437 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_JOINT_SLIDER_H_ #define _ODE_JOINT_SLIDER_H_ #include "joint.h" // slider. if body2 is 0 then qrel is the absolute rotation of body1 and // offset is the position of body1 center along axis1. struct dxJointSlider : public dxJoint { dVector3 axis1; // axis w.r.t first body dQuaternion qrel; // initial relative rotation body1 -> body2 dVector3 offset; // point relative to body2 that should be // aligned with body1 center along axis1 dxJointLimitMotor limot; // limit and motor information dxJointSlider ( dxWorld *w ); virtual void getSureMaxInfo( SureMaxInfo* info ); virtual void getInfo1 ( Info1* info ); virtual void getInfo2 ( dReal worldFPS, dReal worldERP, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dReal *pairLoHi, int *findex ); virtual dJointType type() const; virtual sizeint size() const; virtual void setRelativeValues(); void computeInitialRelativeRotation(); void computeOffset(); }; #endif ode-0.16/ode/src/joints/joint_internal.h0000664000175200017520000000600013403272463015172 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_JOINT_INTERNAL_H_ #define _ODE_JOINT_INTERNAL_H_ #include #include #include "matrix.h" #include "odemath.h" #define checktype(j,t) dUASSERT(j->type() == dJointType##t, \ "joint type is not " #t) void setBall( dxJoint *joint, dReal fps, dReal erp, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dVector3 anchor1, dVector3 anchor2 ); void setBall2( dxJoint *joint, dReal fps, dReal erp, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dVector3 anchor1, dVector3 anchor2, dVector3 axis, dReal erp1 ); void setFixedOrientation( dxJoint *joint, dReal fps, dReal erp, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dQuaternion qrel ); void setAnchors( dxJoint *j, dReal x, dReal y, dReal z, dVector3 anchor1, dVector3 anchor2 ); void getAnchor( dxJoint *j, dVector3 result, dVector3 anchor1 ); void getAnchor2( dxJoint *j, dVector3 result, dVector3 anchor2 ); void setAxes( dxJoint *j, dReal x, dReal y, dReal z, dVector3 axis1, dVector3 axis2 ); void getAxis( dxJoint *j, dVector3 result, dVector3 axis1 ); void getAxis2( dxJoint *j, dVector3 result, dVector3 axis2 ); dReal getHingeAngle( dxBody *body1, dxBody *body2, dVector3 axis, dQuaternion q_initial ); dReal getHingeAngleFromRelativeQuat( dQuaternion qrel, dVector3 axis ); #endif ode-0.16/ode/src/joints/dball.h0000664000175200017520000000465013403272463013242 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_JOINT_DBALL_H_ #define _ODE_JOINT_DBALL_H_ #include "joint.h" // ball and socket struct dxJointDBall : public dxJoint { dVector3 anchor1; // anchor w.r.t first body dVector3 anchor2; // anchor w.r.t second body dReal erp; // error reduction dReal cfm; // constraint force mix in dReal targetDistance; void set( int num, dReal value ); dReal get( int num ); void updateTargetDistance(); dxJointDBall( dxWorld *w ); virtual void getSureMaxInfo( SureMaxInfo* info ); virtual void getInfo1( Info1* info ); virtual void getInfo2( dReal worldFPS, dReal worldERP, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dReal *pairLoHi, int *findex ); virtual dJointType type() const; virtual sizeint size() const; virtual void setRelativeValues(); }; #endif ode-0.16/ode/src/joints/dhinge.cpp0000664000175200017520000001511713403272463013755 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include "config.h" #include "dhinge.h" #include "joint_internal.h" /* * Double Hinge joint */ dxJointDHinge::dxJointDHinge(dxWorld* w) : dxJointDBall(w) { dSetZero(axis1, 3); dSetZero(axis2, 3); } void dxJointDHinge::getSureMaxInfo( SureMaxInfo* info ) { info->max_m = 4; } void dxJointDHinge::getInfo1( dxJoint::Info1* info ) { info->m = 4; info->nub = 4; } void dxJointDHinge::getInfo2( dReal worldFPS, dReal worldERP, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dReal *pairLoHi, int *findex ) { dxJointDBall::getInfo2( worldFPS, worldERP, rowskip, J1, J2, pairskip, pairRhsCfm, pairLoHi, findex ); // sets row0 dVector3 globalAxis1; dBodyVectorToWorld(node[0].body, axis1[0], axis1[1], axis1[2], globalAxis1); dxBody *body1 = node[1].body; // angular constraints, perpendicular to axis dVector3 p, q; dPlaneSpace(globalAxis1, p, q); dCopyVector3(J1 + rowskip + GI2__JA_MIN, p); if ( body1 ) { dCopyNegatedVector3(J2 + rowskip + GI2__JA_MIN, p); } dCopyVector3(J1 + 2 * rowskip + GI2__JA_MIN, q); if ( body1 ) { dCopyNegatedVector3(J2 + 2 * rowskip + GI2__JA_MIN, q); } dVector3 globalAxis2; if ( body1 ) { dBodyVectorToWorld(body1, axis2[0], axis2[1], axis2[2], globalAxis2); } else { dCopyVector3(globalAxis2, axis2); } // similar to the hinge joint dVector3 u; dCalcVectorCross3(u, globalAxis1, globalAxis2); const dReal k = worldFPS * this->erp; pairRhsCfm[pairskip + GI2_RHS] = k * dCalcVectorDot3( u, p ); pairRhsCfm[2 * pairskip + GI2_RHS] = k * dCalcVectorDot3( u, q ); /* * Constraint along the axis: translation along it should couple angular movement. * This is just the ball-and-socket derivation, projected onto the hinge axis, * producing a single constraint at the end. * * The choice of "ball" position can be arbitrary; we could place it at the center * of one of the bodies, canceling out its rotational jacobian; or we could make * everything symmetrical by just placing at the midpoint between the centers. * * I like symmetry, so I'll use the second approach here. I'll call the midpoint h. * * Of course, if the second body is NULL, the first body is pretty much locked * along this axis, and the linear constraint is enough. */ int rowskip_mul_3 = 3 * rowskip; dCopyVector3(J1 + rowskip_mul_3 + GI2__JL_MIN, globalAxis1); if ( body1 ) { dVector3 h; dAddScaledVectors3(h, node[0].body->posr.pos, body1->posr.pos, -0.5, 0.5); dCalcVectorCross3(J1 + rowskip_mul_3 + GI2__JA_MIN, h, globalAxis1); dCopyNegatedVector3(J2 + rowskip_mul_3 + GI2__JL_MIN, globalAxis1); dCopyVector3(J2 + rowskip_mul_3 + GI2__JA_MIN, J1 + rowskip_mul_3 + GI2__JA_MIN); } // error correction: both anchors should lie on the same plane perpendicular to the axis dVector3 globalA1, globalA2; dBodyGetRelPointPos(node[0].body, anchor1[0], anchor1[1], anchor1[2], globalA1); if ( body1 ) { dBodyGetRelPointPos(body1, anchor2[0], anchor2[1], anchor2[2], globalA2); } else { dCopyVector3(globalA2, anchor2); } dVector3 d; dSubtractVectors3(d, globalA1, globalA2); // displacement error pairRhsCfm[3 * pairskip + GI2_RHS] = -k * dCalcVectorDot3(globalAxis1, d); } void dJointSetDHingeAxis( dJointID j, dReal x, dReal y, dReal z ) { dxJointDHinge* joint = static_cast(j); dUASSERT( joint, "bad joint argument" ); dBodyVectorFromWorld(joint->node[0].body, x, y, z, joint->axis1); if (joint->node[1].body) dBodyVectorFromWorld(joint->node[1].body, x, y, z, joint->axis2); else { joint->axis2[0] = x; joint->axis2[1] = y; joint->axis2[2] = z; } dNormalize3(joint->axis1); dNormalize3(joint->axis2); } void dJointGetDHingeAxis( dJointID j, dVector3 result ) { dxJointDHinge* joint = static_cast(j); dUASSERT( joint, "bad joint argument" ); dBodyVectorToWorld(joint->node[0].body, joint->axis1[0], joint->axis1[1], joint->axis1[2], result); } void dJointSetDHingeAnchor1( dJointID j, dReal x, dReal y, dReal z ) { dJointSetDBallAnchor1(j, x, y, z); } void dJointSetDHingeAnchor2( dJointID j, dReal x, dReal y, dReal z ) { dJointSetDBallAnchor2(j, x, y, z); } dReal dJointGetDHingeDistance(dJointID j) { return dJointGetDBallDistance(j); } void dJointGetDHingeAnchor1( dJointID j, dVector3 result ) { dJointGetDBallAnchor1(j, result); } void dJointGetDHingeAnchor2( dJointID j, dVector3 result ) { dJointGetDBallAnchor2(j, result); } void dJointSetDHingeParam( dJointID j, int parameter, dReal value ) { dJointSetDBallParam(j, parameter, value); } dReal dJointGetDHingeParam( dJointID j, int parameter ) { return dJointGetDBallParam(j, parameter); } dJointType dxJointDHinge::type() const { return dJointTypeDHinge; } sizeint dxJointDHinge::size() const { return sizeof( *this ); } ode-0.16/ode/src/joints/piston.cpp0000664000175200017520000006011613403272463014032 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include "config.h" #include "piston.h" #include "joint_internal.h" //**************************************************************************** // Piston // dxJointPiston::dxJointPiston ( dxWorld *w ) : dxJoint ( w ) { dSetZero ( axis1, 4 ); dSetZero ( axis2, 4 ); axis1[0] = 1; axis2[0] = 1; dSetZero ( qrel, 4 ); dSetZero ( anchor1, 4 ); dSetZero ( anchor2, 4 ); limotP.init ( world ); limotR.init ( world ); } dReal dJointGetPistonPosition ( dJointID j ) { dxJointPiston* joint = ( dxJointPiston* ) j; dUASSERT ( joint, "bad joint argument" ); checktype ( joint, Piston ); if ( joint->node[0].body ) { dVector3 q; // get the anchor (or offset) in global coordinates dMultiply0_331 ( q, joint->node[0].body->posr.R, joint->anchor1 ); if ( joint->node[1].body ) { dVector3 anchor2; // get the anchor2 in global coordinates dMultiply0_331 ( anchor2, joint->node[1].body->posr.R, joint->anchor2 ); q[0] = ( ( joint->node[0].body->posr.pos[0] + q[0] ) - ( joint->node[1].body->posr.pos[0] + anchor2[0] ) ); q[1] = ( ( joint->node[0].body->posr.pos[1] + q[1] ) - ( joint->node[1].body->posr.pos[1] + anchor2[1] ) ); q[2] = ( ( joint->node[0].body->posr.pos[2] + q[2] ) - ( joint->node[1].body->posr.pos[2] + anchor2[2] ) ); } else { // N.B. When there is no body 2 the joint->anchor2 is already in // global coordinates q[0] = ( ( joint->node[0].body->posr.pos[0] + q[0] ) - ( joint->anchor2[0] ) ); q[1] = ( ( joint->node[0].body->posr.pos[1] + q[1] ) - ( joint->anchor2[1] ) ); q[2] = ( ( joint->node[0].body->posr.pos[2] + q[2] ) - ( joint->anchor2[2] ) ); if ( joint->flags & dJOINT_REVERSE ) { q[0] = -q[0]; q[1] = -q[1]; q[2] = -q[2]; } } // get axis in global coordinates dVector3 ax; dMultiply0_331 ( ax, joint->node[0].body->posr.R, joint->axis1 ); return dCalcVectorDot3 ( ax, q ); } dDEBUGMSG ( "The function always return 0 since no body are attached" ); return 0; } dReal dJointGetPistonPositionRate ( dJointID j ) { dxJointPiston* joint = ( dxJointPiston* ) j; dUASSERT ( joint, "bad joint argument" ); checktype ( joint, Piston ); // get axis in global coordinates dVector3 ax; dMultiply0_331 ( ax, joint->node[0].body->posr.R, joint->axis1 ); // The linear velocity created by the rotation can be discarded since // the rotation is along the prismatic axis and this rotation don't create // linear velocity in the direction of the prismatic axis. if ( joint->node[1].body ) { return ( dCalcVectorDot3 ( ax, joint->node[0].body->lvel ) - dCalcVectorDot3 ( ax, joint->node[1].body->lvel ) ); } else { dReal rate = dCalcVectorDot3 ( ax, joint->node[0].body->lvel ); return ( (joint->flags & dJOINT_REVERSE) ? -rate : rate); } } dReal dJointGetPistonAngle ( dJointID j ) { dxJointPiston* joint = ( dxJointPiston * ) j; dAASSERT ( joint ); checktype ( joint, Piston ); if ( joint->node[0].body ) { dReal ang = getHingeAngle ( joint->node[0].body, joint->node[1].body, joint->axis1, joint->qrel ); if ( joint->flags & dJOINT_REVERSE ) return -ang; else return ang; } else return 0; } dReal dJointGetPistonAngleRate ( dJointID j ) { dxJointPiston* joint = ( dxJointPiston* ) j; dAASSERT ( joint ); checktype ( joint, Piston ); if ( joint->node[0].body ) { dVector3 axis; dMultiply0_331 ( axis, joint->node[0].body->posr.R, joint->axis1 ); dReal rate = dCalcVectorDot3 ( axis, joint->node[0].body->avel ); if ( joint->node[1].body ) rate -= dCalcVectorDot3 ( axis, joint->node[1].body->avel ); if ( joint->flags & dJOINT_REVERSE ) rate = - rate; return rate; } else return 0; } void dxJointPiston::getSureMaxInfo( SureMaxInfo* info ) { info->max_m = 6; } void dxJointPiston::getInfo1 ( dxJoint::Info1 *info ) { info->nub = 4; // Number of unbound variables // The only bound variable is one linear displacement info->m = 4; // Default number of constraint row // see if we're at a joint limit. limotP.limit = 0; if ( ( limotP.lostop > -dInfinity || limotP.histop < dInfinity ) && limotP.lostop <= limotP.histop ) { // measure joint position dReal pos = dJointGetPistonPosition ( this ); limotP.testRotationalLimit ( pos ); // N.B. The fucntion is ill named } // powered Piston or at limits needs an extra constraint row if ( limotP.limit || limotP.fmax > 0 ) info->m++; // see if we're at a joint limit. limotR.limit = 0; if ( ( limotR.lostop > -dInfinity || limotR.histop < dInfinity ) && limotR.lostop <= limotR.histop ) { // measure joint position dReal angle = getHingeAngle ( node[0].body, node[1].body, axis1, qrel ); limotR.testRotationalLimit ( angle ); } // powered Piston or at limits needs an extra constraint row if ( limotR.limit || limotR.fmax > 0 ) info->m++; } void dxJointPiston::getInfo2 ( dReal worldFPS, dReal worldERP, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dReal *pairLoHi, int *findex ) { const dReal k = worldFPS * worldERP; // Pull out pos and R for both bodies. also get the `connection' // vector pos2-pos1. dVector3 dist; // Current position of body_1 w.r.t "anchor" // 2 bodies anchor is center of body 2 // 1 bodies anchor is origin dVector3 lanchor2 = { 0,0,0 }; dReal *pos1 = node[0].body->posr.pos; dReal *R1 = node[0].body->posr.R; dReal *R2 = NULL; dxBody *body1 = node[1].body; if ( body1 ) { dReal *pos2 = body1->posr.pos; R2 = body1->posr.R; dMultiply0_331 ( lanchor2, R2, anchor2 ); dist[0] = lanchor2[0] + pos2[0] - pos1[0]; dist[1] = lanchor2[1] + pos2[1] - pos1[1]; dist[2] = lanchor2[2] + pos2[2] - pos1[2]; } else { // pos2 = 0; // N.B. We can do that to be safe but it is no necessary // R2 = 0; // N.B. We can do that to be safe but it is no necessary if ( (flags & dJOINT_REVERSE) != 0 ) { dSubtractVectors3(dist, pos1, anchor2); // Invert the value } else { dSubtractVectors3(dist, anchor2, pos1); } } // ====================================================================== // Work on the angular part (i.e. row 0, 1) // Set the two orientation rows. The rotoide axis should be the only // unconstrained rotational axis, the angular velocity of the two bodies // perpendicular to the rotoide axis should be equal. // Thus the constraint equations are: // p*w1 - p*w2 = 0 // q*w1 - q*w2 = 0 // where p and q are unit vectors normal to the rotoide axis, and w1 and w2 // are the angular velocity vectors of the two bodies. // Since the rotoide axis is the same as the prismatic axis. // // // Also, compute the right hand side (RHS) of the rotation constraint equation set. // The first 2 element will result in the relative angular velocity of the two // bodies along axis p and q. This is set to bring the rotoide back into alignment. // if `theta' is the angle between ax1 and ax2, we need an angular velocity // along u to cover angle erp*theta in one step : // |angular_velocity| = angle/time = erp*theta / stepsize // = (erp*fps) * theta // angular_velocity = |angular_velocity| * u // = (erp*fps) * theta * u // where rotation along unit length axis u by theta brings body 2's frame // // if theta is smallish, sin(theta) ~= theta and cos(theta) ~= 1 // where the quaternion of the relative rotation between the two bodies is // quat = [cos(theta/2) sin(theta/2)*u] // quat = [1 theta/2*u] // => q[0] ~= 1 // 2 * q[1+i] = theta * u[i] // // Since there is no constraint along the rotoide axis // only along p and q that we want the same angular velocity and need to reduce // the error dVector3 b, ax1, p, q; dMultiply0_331 ( ax1, node[0].body->posr.R, axis1 ); // Find the 2 axis perpendicular to the rotoide axis. dPlaneSpace ( ax1, p, q ); // LHS dCopyVector3 ( J1 + GI2__JA_MIN, p ); if ( body1 ) { dCopyNegatedVector3 ( J2 + GI2__JA_MIN, p ); } dCopyVector3 ( J1 + rowskip + GI2__JA_MIN, q ); if ( body1 ) { dCopyNegatedVector3 ( J2 + rowskip + GI2__JA_MIN, q ); // Some math for the RHS dVector3 ax2; dMultiply0_331 ( ax2, R2, axis2 ); dCalcVectorCross3( b, ax1, ax2 ); } else { // Some math for the RHS dCalcVectorCross3( b, ax1, axis2 ); } // RHS pairRhsCfm[GI2_RHS] = k * dCalcVectorDot3 ( p, b ); pairRhsCfm[pairskip + GI2_RHS] = k * dCalcVectorDot3 ( q, b ); // ====================================================================== // Work on the linear part (i.e row 2,3) // p2 + R2 anchor2' = p1 + R1 dist' // v2 + w2 R2 anchor2' + R2 d(anchor2')/dt = v1 + w1 R1 dist' + R1 d(dist')/dt // v2 + w2 x anchor2 = v1 + w1 x dist + v_p // v_p is speed of prismatic joint (i.e. elongation rate) // Since the constraints are perpendicular to v_p we have: // p . v_p = 0 and q . v_p = 0 // Along p and q we have (since sliding along the prismatic axis is disregarded): // u . ( v2 + w2 x anchor2 = v1 + w1 x dist + v_p) ( where u is p or q ) // Simplify // u . v2 + u. w2 x anchor2 = u . v1 + u . w1 x dist // or // u . v1 - u . v2 + u . w1 x dist - u2 . w2 x anchor2 = 0 // using the fact that (a x b = - b x a) // u . v1 - u . v2 - u . dist x w1 + u . anchor2 x w2 = 0 // With the help of the triple product: // i.e. a . b x c = b . c x a = c . a x b or a . b x c = a x b . c // Ref: http://mathworld.wolfram.com/ScalarTripleProduct.html // u . v1 - u . v2 - u x dist . w1 + u x anchor2 . w2 = 0 // u . v1 - u . v2 + dist x u . w1 - u x anchor2 . w2 = 0 // // Coeff for 1er line of: J1l => p, J2l => -p // Coeff for 2er line of: J1l => q, J2l => -q // Coeff for 1er line of: J1a => dist x p, J2a => p x anchor2 // Coeff for 2er line of: J1a => dist x q, J2a => q x anchor2 int currRowSkip = 2 * rowskip; { dCopyVector3 ( J1 + currRowSkip + GI2__JL_MIN, p ); dCalcVectorCross3( J1 + currRowSkip + GI2__JA_MIN, dist, p ); if ( body1 ) { // info->J2l[s2+i] = -p[i]; dCopyNegatedVector3 ( J2 + currRowSkip + GI2__JL_MIN, p ); // q x anchor2 instead of anchor2 x q since we want the negative value dCalcVectorCross3( J2 + currRowSkip + GI2__JA_MIN, p, lanchor2 ); } } currRowSkip += rowskip; { dCopyVector3 ( J1 + currRowSkip + GI2__JL_MIN, q ); dCalcVectorCross3( J1 + currRowSkip + GI2__JA_MIN, dist, q ); if ( body1 ) { // info->J2l[s3+i] = -q[i]; dCopyNegatedVector3 ( J2 + currRowSkip + GI2__JL_MIN, q ); // The cross product is in reverse order since we want the negative value dCalcVectorCross3( J2 + currRowSkip + GI2__JA_MIN, q, lanchor2 ); } } // We want to make correction for motion not in the line of the axis // We calculate the displacement w.r.t. the "anchor" pt. // i.e. Find the difference between the current position and the initial // position along the constrained axies (i.e. axis p and q). // The bodies can move w.r.t each other only along the prismatic axis // // Compute the RHS of rows 2 and 3 dVector3 err; dMultiply0_331 ( err, R1, anchor1 ); dSubtractVectors3( err, dist, err ); int currPairSkip = 2 * pairskip; { pairRhsCfm[currPairSkip + GI2_RHS] = k * dCalcVectorDot3 ( p, err ); } currPairSkip += pairskip; { pairRhsCfm[currPairSkip + GI2_RHS] = k * dCalcVectorDot3 ( q, err ); } currRowSkip += rowskip; currPairSkip += pairskip; if ( body1 || (flags & dJOINT_REVERSE) == 0 ) { if (limotP.addLimot ( this, worldFPS, J1 + currRowSkip, J2 + currRowSkip, pairRhsCfm + currPairSkip, pairLoHi + currPairSkip, ax1, 0 )) { currRowSkip += rowskip; currPairSkip += pairskip; } } else { dVector3 rAx1; dCopyNegatedVector3(rAx1, ax1); if (limotP.addLimot ( this, worldFPS, J1 + currRowSkip, J2 + currRowSkip, pairRhsCfm + currPairSkip, pairLoHi + currPairSkip, rAx1, 0 )) { currRowSkip += rowskip; currPairSkip += pairskip; } } limotR.addLimot ( this, worldFPS, J1 + currRowSkip, J2 + currRowSkip, pairRhsCfm + currPairSkip, pairLoHi + currPairSkip, ax1, 1 ); } void dJointSetPistonAnchor ( dJointID j, dReal x, dReal y, dReal z ) { dxJointPiston* joint = ( dxJointPiston* ) j; dUASSERT ( joint, "bad joint argument" ); checktype ( joint, Piston ); setAnchors ( joint, x, y, z, joint->anchor1, joint->anchor2 ); joint->computeInitialRelativeRotation(); } void dJointSetPistonAnchorOffset (dJointID j, dReal x, dReal y, dReal z, dReal dx, dReal dy, dReal dz) { dxJointPiston* joint = (dxJointPiston*) j; dUASSERT (joint,"bad joint argument"); checktype ( joint, Piston ); if (joint->flags & dJOINT_REVERSE) { dx = -dx; dy = -dy; dz = -dz; } if (joint->node[0].body) { joint->node[0].body->posr.pos[0] -= dx; joint->node[0].body->posr.pos[1] -= dy; joint->node[0].body->posr.pos[2] -= dz; } setAnchors (joint,x ,y, z, joint->anchor1, joint->anchor2); if (joint->node[0].body) { joint->node[0].body->posr.pos[0] += dx; joint->node[0].body->posr.pos[1] += dy; joint->node[0].body->posr.pos[2] += dz; } joint->computeInitialRelativeRotation(); } void dJointGetPistonAnchor ( dJointID j, dVector3 result ) { dxJointPiston* joint = ( dxJointPiston* ) j; dUASSERT ( joint, "bad joint argument" ); dUASSERT ( result, "bad result argument" ); checktype ( joint, Piston ); if ( joint->flags & dJOINT_REVERSE ) getAnchor2 ( joint, result, joint->anchor2 ); else getAnchor ( joint, result, joint->anchor1 ); } void dJointGetPistonAnchor2 ( dJointID j, dVector3 result ) { dxJointPiston* joint = ( dxJointPiston* ) j; dUASSERT ( joint, "bad joint argument" ); dUASSERT ( result, "bad result argument" ); checktype ( joint, Piston ); if ( joint->flags & dJOINT_REVERSE ) getAnchor ( joint, result, joint->anchor1 ); else getAnchor2 ( joint, result, joint->anchor2 ); } void dJointSetPistonAxis ( dJointID j, dReal x, dReal y, dReal z ) { dxJointPiston* joint = ( dxJointPiston* ) j; dUASSERT ( joint, "bad joint argument" ); checktype ( joint, Piston ); setAxes ( joint, x, y, z, joint->axis1, joint->axis2 ); joint->computeInitialRelativeRotation(); } void dJointSetPistonAxisDelta ( dJointID j, dReal x, dReal y, dReal z, dReal dx, dReal dy, dReal dz ) { dxJointPiston* joint = ( dxJointPiston* ) j; dUASSERT ( joint, "bad joint argument" ); checktype ( joint, Piston ); setAxes ( joint, x, y, z, joint->axis1, joint->axis2 ); joint->computeInitialRelativeRotation(); dVector3 c = {0,0,0}; if ( joint->node[1].body ) { c[0] = ( joint->node[0].body->posr.pos[0] - joint->node[1].body->posr.pos[0] - dx ); c[1] = ( joint->node[0].body->posr.pos[1] - joint->node[1].body->posr.pos[1] - dy ); c[2] = ( joint->node[0].body->posr.pos[2] - joint->node[1].body->posr.pos[2] - dz ); } else /*if ( joint->node[0].body )*/ // -- body[0] should always be present -- there is a matrix multiplication below { c[0] = joint->node[0].body->posr.pos[0] - dx; c[1] = joint->node[0].body->posr.pos[1] - dy; c[2] = joint->node[0].body->posr.pos[2] - dz; } // Convert into frame of body 1 dMultiply1_331 ( joint->anchor1, joint->node[0].body->posr.R, c ); } void dJointGetPistonAxis ( dJointID j, dVector3 result ) { dxJointPiston* joint = ( dxJointPiston* ) j; dUASSERT ( joint, "bad joint argument" ); dUASSERT ( result, "bad result argument" ); checktype ( joint, Piston ); getAxis ( joint, result, joint->axis1 ); } void dJointSetPistonParam ( dJointID j, int parameter, dReal value ) { dxJointPiston* joint = ( dxJointPiston* ) j; dUASSERT ( joint, "bad joint argument" ); checktype ( joint, Piston ); if ( ( parameter & 0xff00 ) == 0x100 ) { joint->limotR.set ( parameter & 0xff, value ); } else { joint->limotP.set ( parameter, value ); } } dReal dJointGetPistonParam ( dJointID j, int parameter ) { dxJointPiston* joint = ( dxJointPiston* ) j; dUASSERT ( joint, "bad joint argument" ); checktype ( joint, Piston ); if ( ( parameter & 0xff00 ) == 0x100 ) { return joint->limotR.get ( parameter & 0xff ); } else { return joint->limotP.get ( parameter ); } } void dJointAddPistonForce ( dJointID j, dReal force ) { dxJointPiston* joint = ( dxJointPiston* ) j; dUASSERT ( joint, "bad joint argument" ); checktype ( joint, Piston ); if ( joint->flags & dJOINT_REVERSE ) force -= force; dVector3 axis; getAxis ( joint, axis, joint->axis1 ); // axis[i] *= force dScaleVector3( axis, force ); if ( joint->node[0].body != 0 ) dBodyAddForce ( joint->node[0].body, axis[0], axis[1], axis[2] ); if ( joint->node[1].body != 0 ) dBodyAddForce ( joint->node[1].body, -axis[0], -axis[1], -axis[2] ); if ( joint->node[0].body != 0 && joint->node[1].body != 0 ) { // Case where we don't need ltd since center of mass of both bodies // pass by the anchor point '*' when travelling along the prismatic axis. // Body_2 // Body_1 ----- // --- |-- | | // | |---------------*-------------| | ---> prismatic axis // --- |-- | | // ----- // Body_2 // Case where we need ltd // Body_1 // --- // | |--------- // --- | // | |-- // -----*----- ---> prismatic axis // |-- | // | // | // | ----- // | | | // -------| | // | | // ----- // Body_2 // // In real life force apply at the '*' point // But in ODE the force are applied on the center of mass of Body_1 and Body_2 // So we have to add torques on both bodies to compensate for that when there // is an offset between the anchor point and the center of mass of both bodies. // // We need to add to each body T = r x F // Where r is the distance between the cm and '*' dVector3 ltd; // Linear Torque Decoupling vector (a torque) dVector3 c; // Distance of the body w.r.t the anchor // N.B. The distance along the prismatic axis might not // not be included in this variable since it won't add // anything to the ltd. // Calculate the distance of the body w.r.t the anchor // The anchor1 of body1 can be used since: // Real anchor = Position of body 1 + anchor + d* axis1 = anchor in world frame // d is the position of the prismatic joint (i.e. elongation) // Since axis1 x axis1 == 0 // We can do the following. dMultiply0_331 ( c, joint->node[0].body->posr.R, joint->anchor1 ); dCalcVectorCross3( ltd, c, axis ); dBodyAddTorque ( joint->node[0].body, ltd[0], ltd[1], ltd[2] ); dMultiply0_331 ( c, joint->node[1].body->posr.R, joint->anchor2 ); dCalcVectorCross3( ltd, c, axis ); dBodyAddTorque ( joint->node[1].body, ltd[0], ltd[1], ltd[2] ); } } dJointType dxJointPiston::type() const { return dJointTypePiston; } sizeint dxJointPiston::size() const { return sizeof ( *this ); } void dxJointPiston::setRelativeValues() { dVector3 vec; dJointGetPistonAnchor(this, vec); setAnchors( this, vec[0], vec[1], vec[2], anchor1, anchor2 ); dJointGetPistonAxis(this, vec); setAxes( this, vec[0], vec[1], vec[2], axis1, axis2 ); computeInitialRelativeRotation(); } void dxJointPiston::computeInitialRelativeRotation() { if ( node[0].body ) { if ( node[1].body ) { dQMultiply1 ( qrel, node[0].body->q, node[1].body->q ); } else { // set joint->qrel to the transpose of the first body q qrel[0] = node[0].body->q[0]; for ( int i = 1; i < 4; i++ ) qrel[i] = -node[0].body->q[i]; // WARNING do we need the - in -joint->node[0].body->q[i]; or not } } } ode-0.16/ode/src/joints/fixed.h0000664000175200017520000000462113403272463013261 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_JOINT_FIXED_H_ #define _ODE_JOINT_FIXED_H_ #include "joint.h" // fixed struct dxJointFixed : public dxJoint { dQuaternion qrel; // initial relative rotation body1 -> body2 dVector3 offset; // relative offset between the bodies dReal erp; // error reduction parameter dReal cfm; // constraint force mix-in void set ( int num, dReal value ); dReal get ( int num ); dxJointFixed ( dxWorld *w ); virtual void getSureMaxInfo( SureMaxInfo* info ); virtual void getInfo1 ( Info1* info ); virtual void getInfo2 ( dReal worldFPS, dReal worldERP, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dReal *pairLoHi, int *findex ); virtual dJointType type() const; virtual sizeint size() const; void computeInitialRelativeRotation(); }; #endif ode-0.16/ode/src/joints/joint.h0000664000175200017520000002557013403272463013313 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_JOINT_H_ #define _ODE_JOINT_H_ #include #include "../common.h" #include "../objects.h" #include "../obstack.h" // joint flags enum { // if this flag is set, the joint was allocated in a joint group dJOINT_INGROUP = 1, // if this flag is set, the joint was attached with arguments (0,body). // our convention is to treat all attaches as (body,0), i.e. so node[0].body // is always nonzero, so this flag records the fact that the arguments were // swapped. dJOINT_REVERSE = 2, // if this flag is set, the joint can not have just one body attached to it, // it must have either zero or two bodies attached. dJOINT_TWOBODIES = 4, dJOINT_DISABLED = 8 }; enum dJointConnectedBody { dJCB__MIN, dJCB_FIRST_BODY = dJCB__MIN, dJCB_SECOND_BODY, dJCB__MAX, }; static inline dJointConnectedBody EncodeJointOtherConnectedBody(dJointConnectedBody cbBodyKind) { dIASSERT(dIN_RANGE(cbBodyKind, dJCB__MIN, dJCB__MAX)); dSASSERT(dJCB__MAX == 2); return (dJointConnectedBody)(dJCB_FIRST_BODY + dJCB_SECOND_BODY - cbBodyKind); } /* joint body relativity enumeration */ enum dJointBodyRelativity { dJBR__MIN, dJBR_GLOBAL = dJBR__MIN, dJBR__BODIES_MIN, dJBR_BODY1 = dJBR__BODIES_MIN + dJCB_FIRST_BODY, dJBR_BODY2 = dJBR__BODIES_MIN + dJCB_SECOND_BODY, dJBR__BODIES_MAX = dJBR__BODIES_MIN + dJCB__MAX, dJBR__MAX, dJBR__DEFAULT = dJBR_GLOBAL, dJBR__BODIES_COUNT = dJBR__BODIES_MAX - dJBR__BODIES_MIN, }; ODE_PURE_INLINE int dJBREncodeBodyRelativityStatus(int relativity) { return dIN_RANGE(relativity, dJBR__BODIES_MIN, dJBR__BODIES_MAX); } ODE_PURE_INLINE dJointBodyRelativity dJBRSwapBodyRelativity(int relativity) { dIASSERT(dIN_RANGE(relativity, dJBR__BODIES_MIN, dJBR__BODIES_MAX)); return (dJointBodyRelativity)(dJBR_BODY1 + dJBR_BODY2 - relativity); } // there are two of these nodes in the joint, one for each connection to a // body. these are node of a linked list kept by each body of it's connecting // joints. but note that the body pointer in each node points to the body that // makes use of the *other* node, not this node. this trick makes it a bit // easier to traverse the body/joint graph. struct dxJointNode { dxJoint *joint; // pointer to enclosing dxJoint object dxBody *body; // *other* body this joint is connected to dxJointNode *next; // next node in body's list of connected joints }; struct dxJoint : public dObject { // naming convention: the "first" body this is connected to is node[0].body, // and the "second" body is node[1].body. if this joint is only connected // to one body then the second body is 0. // info returned by getInfo1 function. the constraint dimension is m (<=6). // i.e. that is the total number of rows in the jacobian. `nub' is the // number of unbounded variables (which have lo,hi = -/+ infinity). struct Info1 { // Structure size should not exceed sizeof(pointer) bytes to have // to have good memory pattern in dxQuickStepper() uint8 m, nub; }; // info returned by getInfo2 function enum { GI2__J_MIN, GI2__JL_MIN = GI2__J_MIN + dDA__L_MIN, GI2_JLX = GI2__J_MIN + dDA_LX, GI2_JLY = GI2__J_MIN + dDA_LY, GI2_JLZ = GI2__J_MIN + dDA_LZ, GI2__JL_MAX = GI2__J_MIN + dDA__L_MAX, GI2__JA_MIN = GI2__J_MIN + dDA__A_MIN, GI2_JAX = GI2__J_MIN + dDA_AX, GI2_JAY = GI2__J_MIN + dDA_AY, GI2_JAZ = GI2__J_MIN + dDA_AZ, GI2__JA_MAX = GI2__J_MIN + dDA__A_MAX, GI2__J_MAX = GI2__J_MIN + dDA__MAX, }; enum { GI2_RHS, GI2_CFM, GI2__RHS_CFM_MAX, }; enum { GI2_LO, GI2_HI, GI2__LO_HI_MAX, }; // info returned by getSureMaxInfo function. // The information is used for memory reservation in calculations. struct SureMaxInfo { // The value of `max_m' must ALWAYS be not less than the value of `m' // the getInfo1 call can generate in current joint state. Another // requirement is that the value should be provided very quickly, // without the excessive calculations. // If it is hard/impossible to quickly predict the maximal value of `m' // (which is the case for most joint types) the maximum for current // joint type in general should be returned. If it can be known the `m' // will be smaller, it can save a bit of memory from being reserved // for calculations if that smaller value is returned. uint8 max_m; // Estimate of maximal `m' in Info1 }; unsigned flags; // dJOINT_xxx flags dxJointNode node[2]; // connections to bodies. node[1].body can be 0 dJointFeedback *feedback; // optional feedback structure dReal lambda[6]; // lambda generated by last step dxJoint( dxWorld *w ); virtual ~dxJoint(); bool GetIsJointReverse() const { return (this->flags & dJOINT_REVERSE) != 0; } virtual void getInfo1( Info1* info ) = 0; // integrator parameters virtual void getInfo2( // fps=frames per second (1/stepsize), erp=default error reduction parameter (0..1) dReal worldFPS, dReal worldERP, // elements to jump from one row to the next in J's int rowskip, // for the first and second body, pointers to two (linear and angular) // n*3 jacobian sub matrices, stored by rows. these matrices will have // been initialized to 0 on entry. if the second body is zero then the // J2xx pointers may be 0. dReal *J1, dReal *J2, // elements to jump from one pair of scalars to the next int pairskip, // right hand sides of the equation J*v = c + cfm * lambda. cfm is the // "constraint force mixing" vector. c is set to zero on entry, cfm is // set to a constant value (typically very small or zero) value on entry. dReal *pairRhsCfm, // lo and hi limits for variables (set to -/+ infinity on entry). dReal *pairLoHi, // findex vector for variables. see the LCP solver interface for a // description of what this does. this is set to -1 on entry. // note that the returned indexes are relative to the first index of // the constraint. int *findex) = 0; // This call quickly!!! estimates maximum value of "m" that could be returned by getInfo1() // See comments at definition of SureMaxInfo for details. virtual void getSureMaxInfo( SureMaxInfo* info ) = 0; virtual dJointType type() const = 0; virtual sizeint size() const = 0; /// Set values which are relative with respect to bodies. /// Each dxJoint should redefine it if needed. virtual void setRelativeValues(); // Test if this joint should be used in the simulation step // (has the enabled flag set, and is attached to at least one dynamic body) bool isEnabled() const; }; // joint group. NOTE: any joints in the group that have their world destroyed // will have their world pointer set to 0. struct dxJointGroup : public dBase { dxJointGroup(): m_num(0), m_stack() {} template T *alloc(dWorldID w) { T *j = (T *)m_stack.alloc(sizeof(T)); if (j != NULL) { ++m_num; new(j) T(w); j->flags |= dJOINT_INGROUP; } return j; } sizeint getJointCount() const { return m_num; } sizeint exportJoints(dxJoint **jlist); void *beginEnum() { return m_stack.rewind(); } void *continueEnum(sizeint num_bytes) { return m_stack.next(num_bytes); } void freeAll(); private: sizeint m_num; // number of joints on the stack dObStack m_stack; // a stack of (possibly differently sized) dxJoint objects. }; // common limit and motor information for a single joint axis of movement struct dxJointLimitMotor { dReal vel, fmax; // powered joint: velocity, max force dReal lostop, histop; // joint limits, relative to initial position dReal fudge_factor; // when powering away from joint limits dReal normal_cfm; // cfm to use when not at a stop dReal stop_erp, stop_cfm; // erp and cfm for when at joint limit dReal bounce; // restitution factor // variables used between getInfo1() and getInfo2() int limit; // 0=free, 1=at lo limit, 2=at hi limit dReal limit_err; // if at limit, amount over limit void init( dxWorld * ); void set( int num, dReal value ); dReal get( int num ) const; bool testRotationalLimit( dReal angle ); enum { GI2__JL_MIN = dxJoint::GI2__JL_MIN, GI2__JA_MIN = dxJoint::GI2__JA_MIN, GI2_JAX = dxJoint::GI2_JAX, GI2_JAY = dxJoint::GI2_JAY, GI2_JAZ = dxJoint::GI2_JAZ, GI2_RHS = dxJoint::GI2_RHS, GI2_CFM = dxJoint::GI2_CFM, GI2_LO = dxJoint::GI2_LO, GI2_HI = dxJoint::GI2_HI, }; bool addLimot( dxJoint *joint, dReal fps, dReal *J1, dReal *J2, dReal *pairRhsCfm, dReal *pairLoHi, const dVector3 ax1, int rotational ); bool addTwoPointLimot( dxJoint *joint, dReal fps, dReal *J1, dReal *J2, dReal *pairRhsCfm, dReal *pairLoHi, const dVector3 ax1, const dVector3 pt1, const dVector3 pt2 ); }; #endif // Local Variables: // mode:c++ // c-basic-offset:4 // End: ode-0.16/ode/src/joints/plane2d.h0000664000175200017520000000446213403272463013512 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_JOINT_PLANE2D_H_ #define _ODE_JOINT_PLANE2D_H_ #include "joint.h" // 2d joint, constrains to z == 0 struct dxJointPlane2D : public dxJoint { int row_motor_x; int row_motor_y; int row_motor_angle; dxJointLimitMotor motor_x; dxJointLimitMotor motor_y; dxJointLimitMotor motor_angle; dxJointPlane2D( dxWorld *w ); virtual void getSureMaxInfo( SureMaxInfo* info ); virtual void getInfo1( Info1* info ); virtual void getInfo2( dReal worldFPS, dReal worldERP, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dReal *pairLoHi, int *findex ); virtual dJointType type() const; virtual sizeint size() const; }; #endif ode-0.16/ode/src/joints/dhinge.h0000664000175200017520000000411713403272463013420 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_JOINT_DHINGE_ #define _ODE_JOINT_DHINGE_ #include "dball.h" struct dxJointDHinge : public dxJointDBall { dVector3 axis1, axis2; dxJointDHinge(dxWorld *w); virtual void getSureMaxInfo( SureMaxInfo* info ); virtual void getInfo1( Info1* info ); virtual void getInfo2( dReal worldFPS, dReal worldERP, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dReal *pairLoHi, int *findex ); virtual dJointType type() const; virtual sizeint size() const; }; #endif ode-0.16/ode/src/joints/Makefile.am0000664000175200017520000000214613403272463014045 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/include \ -I$(top_builddir)/include \ -I$(top_srcdir)/ode/src \ -D__ODE__ if ENABLE_OU AM_CPPFLAGS += -I$(top_srcdir)/ou/include endif noinst_LTLIBRARIES = libjoints.la libjoints_la_SOURCES = joints.h \ joint.h joint.cpp \ joint_internal.h \ ball.h ball.cpp \ dball.h dball.cpp \ dhinge.h dhinge.cpp \ transmission.h transmission.cpp \ hinge.h hinge.cpp \ slider.h slider.cpp \ contact.h contact.cpp \ universal.h universal.cpp \ hinge2.h hinge2.cpp \ fixed.h fixed.cpp \ null.h null.cpp \ amotor.h amotor.cpp \ lmotor.h lmotor.cpp \ plane2d.h plane2d.cpp \ pu.h pu.cpp \ pr.h pr.cpp \ piston.h piston.cpp ode-0.16/ode/src/joints/contact.cpp0000664000175200017520000003030313403272463014144 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include "config.h" #include "contact.h" #include "joint_internal.h" //**************************************************************************** // contact dxJointContact::dxJointContact(dxWorld *w) : dxJoint(w) { } void dxJointContact::getSureMaxInfo(SureMaxInfo* info) { // ...as the actual m is very likely to hit the maximum info->max_m = (contact.surface.mode&dContactRolling) ? 6 : 3; } void dxJointContact::getInfo1(dxJoint::Info1 *info) { // make sure mu's >= 0, then calculate number of constraint rows and number // of unbounded rows. int m = 1, nub = 0; // Anisotropic sliding and rolling and spinning friction if (contact.surface.mode & dContactAxisDep) { if (contact.surface.mu < 0) { contact.surface.mu = 0; } else if (contact.surface.mu > 0) { if (contact.surface.mu == dInfinity) { nub++; } m++; } if (contact.surface.mu2 < 0) { contact.surface.mu2 = 0; } else if (contact.surface.mu2 > 0) { if (contact.surface.mu2 == dInfinity) { nub++; } m++; } if ((contact.surface.mode & dContactRolling) != 0) { if (contact.surface.rho < 0) { contact.surface.rho = 0; } else { if (contact.surface.rho == dInfinity) { nub++; } m++; } if (contact.surface.rho2 < 0) { contact.surface.rho2 = 0; } else { if (contact.surface.rho2 == dInfinity) { nub++; } m++; } if (contact.surface.rhoN < 0) { contact.surface.rhoN = 0; } else { if (contact.surface.rhoN == dInfinity) { nub++; } m++; } } } else { if (contact.surface.mu < 0) { contact.surface.mu = 0; } else if (contact.surface.mu > 0) { if (contact.surface.mu == dInfinity) { nub += 2; } m += 2; } if ((contact.surface.mode & dContactRolling) != 0) { if (contact.surface.rho < 0) { contact.surface.rho = 0; } else { if (contact.surface.rho == dInfinity) { nub += 3; } m += 3; } } } the_m = m; info->m = m; info->nub = nub; } void dxJointContact::getInfo2(dReal worldFPS, dReal worldERP, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dReal *pairLoHi, int *findex) { enum { ROW_NORMAL, ROW__OPTIONAL_MIN, }; const int surface_mode = contact.surface.mode; // set right hand side and cfm value for normal dReal erp = (surface_mode & dContactSoftERP) != 0 ? contact.surface.soft_erp : worldERP; dReal k = worldFPS * erp; dReal depth = contact.geom.depth - world->contactp.min_depth; if (depth < 0) depth = 0; dReal motionN = (surface_mode & dContactMotionN) != 0 ? contact.surface.motionN : REAL(0.0); const dReal pushout = k * depth + motionN; bool apply_bounce = (surface_mode & dContactBounce) != 0 && contact.surface.bounce_vel >= 0; dReal outgoing = 0; // note: this cap should not limit bounce velocity const dReal maxvel = world->contactp.max_vel; dReal c = pushout > maxvel ? maxvel : pushout; // c1,c2 = contact points with respect to body PORs dVector3 c1, c2 = { 0, }; // get normal, with sign adjusted for body1/body2 polarity dVector3 normal; if ((flags & dJOINT_REVERSE) != 0) { dCopyNegatedVector3(normal, contact.geom.normal); } else { dCopyVector3(normal, contact.geom.normal); } dxBody *b1 = node[1].body; if (b1) { dSubtractVectors3(c2, contact.geom.pos, b1->posr.pos); // set Jacobian for b1 normal dCopyNegatedVector3(J2 + ROW_NORMAL * rowskip + GI2__JL_MIN, normal); dCalcVectorCross3(J2 + ROW_NORMAL * rowskip + GI2__JA_MIN, normal, c2); //== dCalcVectorCross3( J2 + GI2__JA_MIN, c2, normal ); dNegateVector3( J2 + GI2__JA_MIN ); if (apply_bounce) { outgoing /*+*/= dCalcVectorDot3(J2 + ROW_NORMAL * rowskip + GI2__JA_MIN, node[1].body->avel) - dCalcVectorDot3(normal, node[1].body->lvel); } } dxBody *b0 = node[0].body; dSubtractVectors3(c1, contact.geom.pos, b0->posr.pos); // set Jacobian for b0 normal dCopyVector3(J1 + ROW_NORMAL * rowskip + GI2__JL_MIN, normal); dCalcVectorCross3(J1 + ROW_NORMAL * rowskip + GI2__JA_MIN, c1, normal); if (apply_bounce) { // calculate outgoing velocity (-ve for incoming contact) outgoing += dCalcVectorDot3(J1 + ROW_NORMAL * rowskip + GI2__JA_MIN, node[0].body->avel) + dCalcVectorDot3(normal, node[0].body->lvel); } // deal with bounce if (apply_bounce) { dReal negated_outgoing = motionN - outgoing; // only apply bounce if the outgoing velocity is greater than the // threshold, and if the resulting c[rowNormal] exceeds what we already have. dIASSERT(contact.surface.bounce_vel >= 0); if (/*contact.surface.bounce_vel >= 0 &&*/ negated_outgoing > contact.surface.bounce_vel) { const dReal newc = contact.surface.bounce * negated_outgoing + motionN; if (newc > c) { c = newc; } } } pairRhsCfm[ROW_NORMAL * pairskip + GI2_RHS] = c; if ((surface_mode & dContactSoftCFM) != 0) { pairRhsCfm[ROW_NORMAL * pairskip + GI2_CFM] = contact.surface.soft_cfm; } // set LCP limits for normal pairLoHi[ROW_NORMAL * pairskip + GI2_LO] = 0; pairLoHi[ROW_NORMAL * pairskip + GI2_HI] = dInfinity; if (the_m > 1) { // if no friction, there is nothing else to do // now do jacobian for tangential forces dVector3 t1, t2; // two vectors tangential to normal if ((surface_mode & dContactFDir1) != 0) { // use fdir1 ? dCopyVector3(t1, contact.fdir1); dCalcVectorCross3(t2, normal, t1); } else { dPlaneSpace(normal, t1, t2); } int row = ROW__OPTIONAL_MIN; int currRowSkip = row * rowskip, currPairSkip = row * pairskip; // first friction direction const dReal mu = contact.surface.mu; if (mu > 0) { dCopyVector3(J1 + currRowSkip + GI2__JL_MIN, t1); dCalcVectorCross3(J1 + currRowSkip + GI2__JA_MIN, c1, t1); if (node[1].body) { dCopyNegatedVector3(J2 + currRowSkip + GI2__JL_MIN, t1); dCalcVectorCross3(J2 + currRowSkip + GI2__JA_MIN, t1, c2); //== dCalcVectorCross3( J2 + rowskip + GI2__JA_MIN, c2, t1 ); dNegateVector3( J2 + rowskip + GI2__JA_MIN ); } // set right hand side if ((surface_mode & dContactMotion1) != 0) { pairRhsCfm[currPairSkip + GI2_RHS] = contact.surface.motion1; } // set slip (constraint force mixing) if ((surface_mode & dContactSlip1) != 0) { pairRhsCfm[currPairSkip + GI2_CFM] = contact.surface.slip1; } // set LCP bounds and friction index. this depends on the approximation // mode pairLoHi[currPairSkip + GI2_LO] = -mu; pairLoHi[currPairSkip + GI2_HI] = mu; if ((surface_mode & dContactApprox1_1) != 0) { findex[row] = 0; } ++row; currRowSkip += rowskip; currPairSkip += pairskip; } // second friction direction const dReal mu2 = (surface_mode & dContactMu2) != 0 ? contact.surface.mu2 : mu; if (mu2 > 0) { dCopyVector3(J1 + currRowSkip + GI2__JL_MIN, t2); dCalcVectorCross3(J1 + currRowSkip + GI2__JA_MIN, c1, t2); if (node[1].body) { dCopyNegatedVector3(J2 + currRowSkip + GI2__JL_MIN, t2); dCalcVectorCross3(J2 + currRowSkip + GI2__JA_MIN, t2, c2); //== dCalcVectorCross3( J2 + currRowSkip + GI2__JA_MIN, c2, t2 ); dNegateVector3( J2 + currRowSkip + GI2__JA_MIN ); } // set right hand side if ((surface_mode & dContactMotion2) != 0) { pairRhsCfm[currPairSkip + GI2_RHS] = contact.surface.motion2; } // set slip (constraint force mixing) if ((surface_mode & dContactSlip2) != 0) { pairRhsCfm[currPairSkip + GI2_CFM] = contact.surface.slip2; } // set LCP bounds and friction index. this depends on the approximation // mode pairLoHi[currPairSkip + GI2_LO] = -mu2; pairLoHi[currPairSkip + GI2_HI] = mu2; if ((surface_mode & dContactApprox1_2) != 0) { findex[row] = 0; } ++row; currRowSkip += rowskip; currPairSkip += pairskip; } // Handle rolling/spinning friction if ((surface_mode & dContactRolling) != 0) { const dReal *const ax[3] = { t1, // Rolling around t1 creates movement parallel to t2 t2, normal // Spinning axis }; const int approx_bits[3] = { dContactApprox1_1, dContactApprox1_2, dContactApprox1_N }; // Get the coefficients dReal rho[3]; rho[0] = contact.surface.rho; if ((surface_mode & dContactAxisDep) != 0) { rho[1] = contact.surface.rho2; rho[2] = contact.surface.rhoN; } else { rho[1] = rho[0]; rho[2] = rho[0]; } for (int i = 0; i != 3; ++i) { if (rho[i] > 0) { // Set the angular axis dCopyVector3(J1 + currRowSkip + GI2__JA_MIN, ax[i]); if (b1) { dCopyNegatedVector3(J2 + currRowSkip + GI2__JA_MIN, ax[i]); } // Set the lcp limits pairLoHi[currPairSkip + GI2_LO] = -rho[i]; pairLoHi[currPairSkip + GI2_HI] = rho[i]; // Should we use proportional force? if ((surface_mode & approx_bits[i]) != 0) { // Make limits proportional to normal force findex[row] = 0; } ++row; currRowSkip += rowskip; currPairSkip += pairskip; } } } } } dJointType dxJointContact::type() const { return dJointTypeContact; } sizeint dxJointContact::size() const { return sizeof(*this); } ode-0.16/ode/src/joints/pu.h0000664000175200017520000000766313403272463012617 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_JOINT_PU_H_ #define _ODE_JOINT_PU_H_ #include "universal.h" /** * Component of a Prismatic -- Universal joint. * The axisP must be perpendicular to axis1. * The second axis of the universal joint is perpendicular to axis1. * * Since the PU joint is derived from the Universal joint. Some variable * are reused. * * anchor1: Vector from body1 to the anchor point * This vector is calculated when the body are attached or * when the anchor point is set. It is like the offset of the Slider * joint. Since their is a prismatic between the anchor and the body1 * the distance might change as the simulation goes on. * anchor2: Vector from body2 to the anchor point. *
 *                                                 Body 2
 *                                                 +-------------+
 *                                                 |      x      |
 *                                                 +------------\+
 *          Prismatic articulation                   ..     ..
 *                                |                ..     ..
 *          Body 1                v             ..      ..
 *          +--------------+    --|        __..      ..  anchor2
 * <--------|      x       | .....|.......(__)     ..
 * axisP    +--------------+    --|         ^     <
 *                 |----------------------->|
 *                     anchor1              |--- Universal articulation
 *                                               axis1 going out of the plane
 *                                               axis2 is perpendicular to axis1
 *                                               (i.e. 2 rotoides)
 * 
*/ struct dxJointPU : public dxJointUniversal { /// @brief Axis for the prismatic articulation w.r.t first body. /// @note This is considered as axis2 from the parameter view dVector3 axisP1; dxJointLimitMotor limotP; ///< limit and motor information for the prismatic articulation. dxJointPU( dxWorld *w ); virtual void getSureMaxInfo( SureMaxInfo* info ); virtual void getInfo1( Info1* info ); virtual void getInfo2( dReal worldFPS, dReal worldERP, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dReal *pairLoHi, int *findex ); virtual dJointType type() const; virtual sizeint size() const; virtual void setRelativeValues(); }; #endif ode-0.16/ode/src/joints/ball.cpp0000664000175200017520000001206413403272463013427 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include "config.h" #include "ball.h" #include "joint_internal.h" //**************************************************************************** // ball and socket dxJointBall::dxJointBall( dxWorld *w ) : dxJoint( w ) { dSetZero( anchor1, 4 ); dSetZero( anchor2, 4 ); erp = world->global_erp; cfm = world->global_cfm; } void dxJointBall::getSureMaxInfo( SureMaxInfo* info ) { info->max_m = 3; } void dxJointBall::getInfo1( dxJoint::Info1 *info ) { info->m = 3; info->nub = 3; } void dxJointBall::getInfo2( dReal worldFPS, dReal /*worldERP*/, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dReal *pairLoHi, int *findex ) { pairRhsCfm[GI2_CFM] = cfm; pairRhsCfm[pairskip + GI2_CFM] = cfm; pairRhsCfm[2 * pairskip + GI2_CFM] = cfm; setBall( this, worldFPS, this->erp, rowskip, J1, J2, pairskip, pairRhsCfm, anchor1, anchor2 ); } void dJointSetBallAnchor( dJointID j, dReal x, dReal y, dReal z ) { dxJointBall* joint = ( dxJointBall* )j; dUASSERT( joint, "bad joint argument" ); checktype( joint, Ball ); setAnchors( joint, x, y, z, joint->anchor1, joint->anchor2 ); } void dJointSetBallAnchor2( dJointID j, dReal x, dReal y, dReal z ) { dxJointBall* joint = ( dxJointBall* )j; dUASSERT( joint, "bad joint argument" ); checktype( joint, Ball ); joint->anchor2[0] = x; joint->anchor2[1] = y; joint->anchor2[2] = z; joint->anchor2[3] = 0; } void dJointGetBallAnchor( dJointID j, dVector3 result ) { dxJointBall* joint = ( dxJointBall* )j; dUASSERT( joint, "bad joint argument" ); dUASSERT( result, "bad result argument" ); checktype( joint, Ball ); if ( joint->flags & dJOINT_REVERSE ) getAnchor2( joint, result, joint->anchor2 ); else getAnchor( joint, result, joint->anchor1 ); } void dJointGetBallAnchor2( dJointID j, dVector3 result ) { dxJointBall* joint = ( dxJointBall* )j; dUASSERT( joint, "bad joint argument" ); dUASSERT( result, "bad result argument" ); checktype( joint, Ball ); if ( joint->flags & dJOINT_REVERSE ) getAnchor( joint, result, joint->anchor1 ); else getAnchor2( joint, result, joint->anchor2 ); } void dxJointBall::set( int num, dReal value ) { switch ( num ) { case dParamCFM: cfm = value; break; case dParamERP: erp = value; break; } } dReal dxJointBall::get( int num ) { switch ( num ) { case dParamCFM: return cfm; case dParamERP: return erp; default: return 0; } } void dJointSetBallParam( dJointID j, int parameter, dReal value ) { dxJointBall* joint = ( dxJointBall* )j; dUASSERT( joint, "bad joint argument" ); checktype( joint, Ball ); joint->set( parameter, value ); } dReal dJointGetBallParam( dJointID j, int parameter ) { dxJointBall* joint = ( dxJointBall* )j; dUASSERT( joint, "bad joint argument" ); checktype( joint, Ball ); return joint->get( parameter ); } dJointType dxJointBall::type() const { return dJointTypeBall; } sizeint dxJointBall::size() const { return sizeof( *this ); } void dxJointBall::setRelativeValues() { dVector3 anchor; dJointGetBallAnchor(this, anchor); setAnchors( this, anchor[0], anchor[1], anchor[2], anchor1, anchor2 ); } ode-0.16/ode/src/joints/universal.cpp0000664000175200017520000005761013403272463014533 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include "config.h" #include "universal.h" #include "joint_internal.h" //**************************************************************************** // universal // I just realized that the universal joint is equivalent to a hinge 2 joint with // perfectly stiff suspension. By comparing the hinge 2 implementation to // the universal implementation, you may be able to improve this // implementation (or, less likely, the hinge2 implementation). dxJointUniversal::dxJointUniversal( dxWorld *w ) : dxJoint( w ) { dSetZero( anchor1, 4 ); dSetZero( anchor2, 4 ); dSetZero( axis1, 4 ); axis1[0] = 1; dSetZero( axis2, 4 ); axis2[1] = 1; dSetZero( qrel1, 4 ); dSetZero( qrel2, 4 ); limot1.init( world ); limot2.init( world ); } void dxJointUniversal::getAxes( dVector3 ax1, dVector3 ax2 ) { // This says "ax1 = joint->node[0].body->posr.R * joint->axis1" dMultiply0_331( ax1, node[0].body->posr.R, axis1 ); if ( node[1].body ) { dMultiply0_331( ax2, node[1].body->posr.R, axis2 ); } else { ax2[0] = axis2[0]; ax2[1] = axis2[1]; ax2[2] = axis2[2]; } } void dxJointUniversal::getAngles( dReal *angle1, dReal *angle2 ) { if ( node[0].body ) { // length 1 joint axis in global coordinates, from each body dVector3 ax1, ax2; dMatrix3 R; dQuaternion qcross, qq, qrel; getAxes( ax1, ax2 ); // It should be possible to get both angles without explicitly // constructing the rotation matrix of the cross. Basically, // orientation of the cross about axis1 comes from body 2, // about axis 2 comes from body 1, and the perpendicular // axis can come from the two bodies somehow. (We don't really // want to assume it's 90 degrees, because in general the // constraints won't be perfectly satisfied, or even very well // satisfied.) // // However, we'd need a version of getHingeAngleFromRElativeQuat() // that CAN handle when its relative quat is rotated along a direction // other than the given axis. What I have here works, // although it's probably much slower than need be. dRFrom2Axes( R, ax1[0], ax1[1], ax1[2], ax2[0], ax2[1], ax2[2] ); dRtoQ( R, qcross ); // This code is essentialy the same as getHingeAngle(), see the comments // there for details. // get qrel = relative rotation between node[0] and the cross dQMultiply1( qq, node[0].body->q, qcross ); dQMultiply2( qrel, qq, qrel1 ); *angle1 = getHingeAngleFromRelativeQuat( qrel, axis1 ); // This is equivalent to // dRFrom2Axes(R, ax2[0], ax2[1], ax2[2], ax1[0], ax1[1], ax1[2]); // You see that the R is constructed from the same 2 axis as for angle1 // but the first and second axis are swapped. // So we can take the first R and rapply a rotation to it. // The rotation is around the axis between the 2 axes (ax1 and ax2). // We do a rotation of 180deg. dQuaternion qcross2; // Find the vector between ax1 and ax2 (i.e. in the middle) // We need to turn around this vector by 180deg // The 2 axes should be normalize so to find the vector between the 2. // Add and devide by 2 then normalize or simply normalize // ax2 // ^ // | // | /// *------------> ax1 // We want the vector a 45deg // // N.B. We don't need to normalize the ax1 and ax2 since there are // normalized when we set them. // We set the quaternion q = [cos(theta), dir*sin(theta)] = [w, x, y, Z] qrel[0] = 0; // equivalent to cos(Pi/2) qrel[1] = ax1[0] + ax2[0]; // equivalent to x*sin(Pi/2); since sin(Pi/2) = 1 qrel[2] = ax1[1] + ax2[1]; qrel[3] = ax1[2] + ax2[2]; dReal l = dRecip( sqrt( qrel[1] * qrel[1] + qrel[2] * qrel[2] + qrel[3] * qrel[3] ) ); qrel[1] *= l; qrel[2] *= l; qrel[3] *= l; dQMultiply0( qcross2, qrel, qcross ); if ( node[1].body ) { dQMultiply1( qq, node[1].body->q, qcross2 ); dQMultiply2( qrel, qq, qrel2 ); } else { // pretend joint->node[1].body->q is the identity dQMultiply2( qrel, qcross2, qrel2 ); } *angle2 = - getHingeAngleFromRelativeQuat( qrel, axis2 ); } else { *angle1 = 0; *angle2 = 0; } } dReal dxJointUniversal::getAngle1() { if ( node[0].body ) { // length 1 joint axis in global coordinates, from each body dVector3 ax1, ax2; dMatrix3 R; dQuaternion qcross, qq, qrel; getAxes( ax1, ax2 ); // It should be possible to get both angles without explicitly // constructing the rotation matrix of the cross. Basically, // orientation of the cross about axis1 comes from body 2, // about axis 2 comes from body 1, and the perpendicular // axis can come from the two bodies somehow. (We don't really // want to assume it's 90 degrees, because in general the // constraints won't be perfectly satisfied, or even very well // satisfied.) // // However, we'd need a version of getHingeAngleFromRElativeQuat() // that CAN handle when its relative quat is rotated along a direction // other than the given axis. What I have here works, // although it's probably much slower than need be. dRFrom2Axes( R, ax1[0], ax1[1], ax1[2], ax2[0], ax2[1], ax2[2] ); dRtoQ( R, qcross ); // This code is essential the same as getHingeAngle(), see the comments // there for details. // get qrel = relative rotation between node[0] and the cross dQMultiply1( qq, node[0].body->q, qcross ); dQMultiply2( qrel, qq, qrel1 ); return getHingeAngleFromRelativeQuat( qrel, axis1 ); } return 0; } dReal dxJointUniversal::getAngle2() { if ( node[0].body ) { // length 1 joint axis in global coordinates, from each body dVector3 ax1, ax2; dMatrix3 R; dQuaternion qcross, qq, qrel; getAxes( ax1, ax2 ); // It should be possible to get both angles without explicitly // constructing the rotation matrix of the cross. Basically, // orientation of the cross about axis1 comes from body 2, // about axis 2 comes from body 1, and the perpendicular // axis can come from the two bodies somehow. (We don't really // want to assume it's 90 degrees, because in general the // constraints won't be perfectly satisfied, or even very well // satisfied.) // // However, we'd need a version of getHingeAngleFromRElativeQuat() // that CAN handle when its relative quat is rotated along a direction // other than the given axis. What I have here works, // although it's probably much slower than need be. dRFrom2Axes( R, ax2[0], ax2[1], ax2[2], ax1[0], ax1[1], ax1[2] ); dRtoQ( R, qcross ); if ( node[1].body ) { dQMultiply1( qq, node[1].body->q, qcross ); dQMultiply2( qrel, qq, qrel2 ); } else { // pretend joint->node[1].body->q is the identity dQMultiply2( qrel, qcross, qrel2 ); } return - getHingeAngleFromRelativeQuat( qrel, axis2 ); } return 0; } void dxJointUniversal::getSureMaxInfo( SureMaxInfo* info ) { info->max_m = 6; } void dxJointUniversal::getInfo1( dxJoint::Info1 *info ) { info->nub = 4; info->m = 4; bool limiting1 = ( limot1.lostop >= -M_PI || limot1.histop <= M_PI ) && limot1.lostop <= limot1.histop; bool limiting2 = ( limot2.lostop >= -M_PI || limot2.histop <= M_PI ) && limot2.lostop <= limot2.histop; // We need to call testRotationLimit() even if we're motored, since it // records the result. limot1.limit = 0; limot2.limit = 0; if ( limiting1 || limiting2 ) { dReal angle1, angle2; getAngles( &angle1, &angle2 ); if ( limiting1 ) limot1.testRotationalLimit( angle1 ); if ( limiting2 ) limot2.testRotationalLimit( angle2 ); } if ( limot1.limit || limot1.fmax > 0 ) info->m++; if ( limot2.limit || limot2.fmax > 0 ) info->m++; } void dxJointUniversal::getInfo2( dReal worldFPS, dReal worldERP, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dReal *pairLoHi, int *findex ) { // set the three ball-and-socket rows setBall( this, worldFPS, worldERP, rowskip, J1, J2, pairskip, pairRhsCfm, anchor1, anchor2 ); // set the universal joint row. the angular velocity about an axis // perpendicular to both joint axes should be equal. thus the constraint // equation is // p*w1 - p*w2 = 0 // where p is a vector normal to both joint axes, and w1 and w2 // are the angular velocity vectors of the two bodies. // length 1 joint axis in global coordinates, from each body dVector3 ax1, ax2; // length 1 vector perpendicular to ax1 and ax2. Neither body can rotate // about this. dVector3 p; // Since axis1 and axis2 may not be perpendicular // we find a axis2_tmp which is really perpendicular to axis1 // and in the plane of axis1 and axis2 getAxes( ax1, ax2 ); dReal k = dCalcVectorDot3( ax1, ax2 ); dVector3 ax2_temp; dAddVectorScaledVector3(ax2_temp, ax2, ax1, -k); dCalcVectorCross3( p, ax1, ax2_temp ); dNormalize3( p ); int currRowSkip = 3 * rowskip; { dCopyVector3( J1 + currRowSkip + GI2__JA_MIN, p); if ( node[1].body ) { dCopyNegatedVector3( J2 + currRowSkip + GI2__JA_MIN, p); } } // compute the right hand side of the constraint equation. set relative // body velocities along p to bring the axes back to perpendicular. // If ax1, ax2 are unit length joint axes as computed from body1 and // body2, we need to rotate both bodies along the axis p. If theta // is the angle between ax1 and ax2, we need an angular velocity // along p to cover the angle erp * (theta - Pi/2) in one step: // // |angular_velocity| = angle/time = erp*(theta - Pi/2) / stepsize // = (erp*fps) * (theta - Pi/2) // // if theta is close to Pi/2, // theta - Pi/2 ~= cos(theta), so // |angular_velocity| ~= (erp*fps) * (ax1 dot ax2) int currPairSkip = 3 * pairskip; { pairRhsCfm[currPairSkip + GI2_RHS] = worldFPS * worldERP * (-k); } currRowSkip += rowskip; currPairSkip += pairskip; // if the first angle is powered, or has joint limits, add in the stuff if (limot1.addLimot( this, worldFPS, J1 + currRowSkip, J2 + currRowSkip, pairRhsCfm + currPairSkip, pairLoHi + currPairSkip, ax1, 1 )) { currRowSkip += rowskip; currPairSkip += pairskip; } // if the second angle is powered, or has joint limits, add in more stuff limot2.addLimot( this, worldFPS, J1 + currRowSkip, J2 + currRowSkip, pairRhsCfm + currPairSkip, pairLoHi + currPairSkip, ax2, 1 ); } void dxJointUniversal::computeInitialRelativeRotations() { if ( node[0].body ) { dVector3 ax1, ax2; dMatrix3 R; dQuaternion qcross; getAxes( ax1, ax2 ); // Axis 1. dRFrom2Axes( R, ax1[0], ax1[1], ax1[2], ax2[0], ax2[1], ax2[2] ); dRtoQ( R, qcross ); dQMultiply1( qrel1, node[0].body->q, qcross ); // Axis 2. dRFrom2Axes( R, ax2[0], ax2[1], ax2[2], ax1[0], ax1[1], ax1[2] ); dRtoQ( R, qcross ); if ( node[1].body ) { dQMultiply1( qrel2, node[1].body->q, qcross ); } else { // set joint->qrel to qcross for ( int i = 0; i < 4; i++ ) qrel2[i] = qcross[i]; } } } void dJointSetUniversalAnchor( dJointID j, dReal x, dReal y, dReal z ) { dxJointUniversal* joint = ( dxJointUniversal* )j; dUASSERT( joint, "bad joint argument" ); checktype( joint, Universal ); setAnchors( joint, x, y, z, joint->anchor1, joint->anchor2 ); joint->computeInitialRelativeRotations(); } void dJointSetUniversalAxis1( dJointID j, dReal x, dReal y, dReal z ) { dxJointUniversal* joint = ( dxJointUniversal* )j; dUASSERT( joint, "bad joint argument" ); checktype( joint, Universal ); if ( joint->flags & dJOINT_REVERSE ) setAxes( joint, x, y, z, NULL, joint->axis2 ); else setAxes( joint, x, y, z, joint->axis1, NULL ); joint->computeInitialRelativeRotations(); } void dJointSetUniversalAxis1Offset( dJointID j, dReal x, dReal y, dReal z, dReal offset1, dReal offset2 ) { dxJointUniversal* joint = ( dxJointUniversal* )j; dUASSERT( joint, "bad joint argument" ); checktype( joint, Universal ); if ( joint->flags & dJOINT_REVERSE ) { setAxes( joint, x, y, z, NULL, joint->axis2 ); offset1 = -offset1; offset2 = -offset2; } else setAxes( joint, x, y, z, joint->axis1, NULL ); joint->computeInitialRelativeRotations(); dVector3 ax2; getAxis2( joint, ax2, joint->axis2 ); { dVector3 ax1; joint->getAxes(ax1, ax2); } dQuaternion qAngle; dQFromAxisAndAngle(qAngle, x, y, z, offset1); dMatrix3 R; dRFrom2Axes( R, x, y, z, ax2[0], ax2[1], ax2[2] ); dQuaternion qcross; dRtoQ( R, qcross ); dQuaternion qOffset; dQMultiply0(qOffset, qAngle, qcross); dQMultiply1( joint->qrel1, joint->node[0].body->q, qOffset ); // Calculating the second offset dQFromAxisAndAngle(qAngle, ax2[0], ax2[1], ax2[2], offset2); dRFrom2Axes( R, ax2[0], ax2[1], ax2[2], x, y, z ); dRtoQ( R, qcross ); dQMultiply1(qOffset, qAngle, qcross); if ( joint->node[1].body ) { dQMultiply1( joint->qrel2, joint->node[1].body->q, qOffset ); } else { joint->qrel2[0] = qcross[0]; joint->qrel2[1] = qcross[1]; joint->qrel2[2] = qcross[2]; joint->qrel2[3] = qcross[3]; } } void dJointSetUniversalAxis2( dJointID j, dReal x, dReal y, dReal z ) { dxJointUniversal* joint = ( dxJointUniversal* )j; dUASSERT( joint, "bad joint argument" ); checktype( joint, Universal ); if ( joint->flags & dJOINT_REVERSE ) setAxes( joint, x, y, z, joint->axis1, NULL ); else setAxes( joint, x, y, z, NULL, joint->axis2 ); joint->computeInitialRelativeRotations(); } void dJointSetUniversalAxis2Offset( dJointID j, dReal x, dReal y, dReal z, dReal offset1, dReal offset2 ) { dxJointUniversal* joint = ( dxJointUniversal* )j; dUASSERT( joint, "bad joint argument" ); checktype( joint, Universal ); if ( joint->flags & dJOINT_REVERSE ) { setAxes( joint, x, y, z, joint->axis1, NULL ); offset1 = -offset2; offset2 = -offset1; } else setAxes( joint, x, y, z, NULL, joint->axis2 ); joint->computeInitialRelativeRotations(); // It is easier to retreive the 2 axes here since // when there is only one body B2 (the axes switch position) // Doing this way eliminate the need to write the code differently // for both case. dVector3 ax1, ax2; joint->getAxes(ax1, ax2 ); dQuaternion qAngle; dQFromAxisAndAngle(qAngle, ax1[0], ax1[1], ax1[2], offset1); dMatrix3 R; dRFrom2Axes( R, ax1[0], ax1[1], ax1[2], ax2[0], ax2[1], ax2[2]); dQuaternion qcross; dRtoQ( R, qcross ); dQuaternion qOffset; dQMultiply0(qOffset, qAngle, qcross); dQMultiply1( joint->qrel1, joint->node[0].body->q, qOffset ); // Calculating the second offset dQFromAxisAndAngle(qAngle, ax2[0], ax2[1], ax2[2], offset2); dRFrom2Axes( R, ax2[0], ax2[1], ax2[2], ax1[0], ax1[1], ax1[2]); dRtoQ( R, qcross ); dQMultiply1(qOffset, qAngle, qcross); if ( joint->node[1].body ) { dQMultiply1( joint->qrel2, joint->node[1].body->q, qOffset ); } else { joint->qrel2[0] = qcross[0]; joint->qrel2[1] = qcross[1]; joint->qrel2[2] = qcross[2]; joint->qrel2[3] = qcross[3]; } } void dJointGetUniversalAnchor( dJointID j, dVector3 result ) { dxJointUniversal* joint = ( dxJointUniversal* )j; dUASSERT( joint, "bad joint argument" ); dUASSERT( result, "bad result argument" ); checktype( joint, Universal ); if ( joint->flags & dJOINT_REVERSE ) getAnchor2( joint, result, joint->anchor2 ); else getAnchor( joint, result, joint->anchor1 ); } void dJointGetUniversalAnchor2( dJointID j, dVector3 result ) { dxJointUniversal* joint = ( dxJointUniversal* )j; dUASSERT( joint, "bad joint argument" ); dUASSERT( result, "bad result argument" ); checktype( joint, Universal ); if ( joint->flags & dJOINT_REVERSE ) getAnchor( joint, result, joint->anchor1 ); else getAnchor2( joint, result, joint->anchor2 ); } void dJointGetUniversalAxis1( dJointID j, dVector3 result ) { dxJointUniversal* joint = ( dxJointUniversal* )j; dUASSERT( joint, "bad joint argument" ); dUASSERT( result, "bad result argument" ); checktype( joint, Universal ); if ( joint->flags & dJOINT_REVERSE ) getAxis2( joint, result, joint->axis2 ); else getAxis( joint, result, joint->axis1 ); } void dJointGetUniversalAxis2( dJointID j, dVector3 result ) { dxJointUniversal* joint = ( dxJointUniversal* )j; dUASSERT( joint, "bad joint argument" ); dUASSERT( result, "bad result argument" ); checktype( joint, Universal ); if ( joint->flags & dJOINT_REVERSE ) getAxis( joint, result, joint->axis1 ); else getAxis2( joint, result, joint->axis2 ); } void dJointSetUniversalParam( dJointID j, int parameter, dReal value ) { dxJointUniversal* joint = ( dxJointUniversal* )j; dUASSERT( joint, "bad joint argument" ); checktype( joint, Universal ); if (( parameter & 0xff00 ) == 0x100 ) { joint->limot2.set( parameter & 0xff, value ); } else { joint->limot1.set( parameter, value ); } } dReal dJointGetUniversalParam( dJointID j, int parameter ) { dxJointUniversal* joint = ( dxJointUniversal* )j; dUASSERT( joint, "bad joint argument" ); checktype( joint, Universal ); if (( parameter & 0xff00 ) == 0x100 ) { return joint->limot2.get( parameter & 0xff ); } else { return joint->limot1.get( parameter ); } } void dJointGetUniversalAngles( dJointID j, dReal *angle1, dReal *angle2 ) { dxJointUniversal* joint = ( dxJointUniversal* )j; dUASSERT( joint, "bad joint argument" ); checktype( joint, Universal ); if ( joint->flags & dJOINT_REVERSE ) { joint->getAngles( angle2, angle1 ); *angle2 = -(*angle2); return; } else return joint->getAngles( angle1, angle2 ); } dReal dJointGetUniversalAngle1( dJointID j ) { dxJointUniversal* joint = ( dxJointUniversal* )j; dUASSERT( joint, "bad joint argument" ); checktype( joint, Universal ); if ( joint->flags & dJOINT_REVERSE ) return joint->getAngle2(); else return joint->getAngle1(); } dReal dJointGetUniversalAngle2( dJointID j ) { dxJointUniversal* joint = ( dxJointUniversal* )j; dUASSERT( joint, "bad joint argument" ); checktype( joint, Universal ); if ( joint->flags & dJOINT_REVERSE ) return -joint->getAngle1(); else return joint->getAngle2(); } dReal dJointGetUniversalAngle1Rate( dJointID j ) { dxJointUniversal* joint = ( dxJointUniversal* )j; dUASSERT( joint, "bad joint argument" ); checktype( joint, Universal ); if ( joint->node[0].body ) { dVector3 axis; if ( joint->flags & dJOINT_REVERSE ) getAxis2( joint, axis, joint->axis2 ); else getAxis( joint, axis, joint->axis1 ); dReal rate = dCalcVectorDot3( axis, joint->node[0].body->avel ); if ( joint->node[1].body ) rate -= dCalcVectorDot3( axis, joint->node[1].body->avel ); return rate; } return 0; } dReal dJointGetUniversalAngle2Rate( dJointID j ) { dxJointUniversal* joint = ( dxJointUniversal* )j; dUASSERT( joint, "bad joint argument" ); checktype( joint, Universal ); if ( joint->node[0].body ) { dVector3 axis; if ( joint->flags & dJOINT_REVERSE ) getAxis( joint, axis, joint->axis1 ); else getAxis2( joint, axis, joint->axis2 ); dReal rate = dCalcVectorDot3( axis, joint->node[0].body->avel ); if ( joint->node[1].body ) rate -= dCalcVectorDot3( axis, joint->node[1].body->avel ); return rate; } return 0; } void dJointAddUniversalTorques( dJointID j, dReal torque1, dReal torque2 ) { dxJointUniversal* joint = ( dxJointUniversal* )j; dVector3 axis1, axis2; dAASSERT( joint ); checktype( joint, Universal ); if ( joint->flags & dJOINT_REVERSE ) { dReal temp = torque1; torque1 = - torque2; torque2 = - temp; } getAxis( joint, axis1, joint->axis1 ); getAxis2( joint, axis2, joint->axis2 ); axis1[0] = axis1[0] * torque1 + axis2[0] * torque2; axis1[1] = axis1[1] * torque1 + axis2[1] * torque2; axis1[2] = axis1[2] * torque1 + axis2[2] * torque2; if ( joint->node[0].body != 0 ) dBodyAddTorque( joint->node[0].body, axis1[0], axis1[1], axis1[2] ); if ( joint->node[1].body != 0 ) dBodyAddTorque( joint->node[1].body, -axis1[0], -axis1[1], -axis1[2] ); } dJointType dxJointUniversal::type() const { return dJointTypeUniversal; } sizeint dxJointUniversal::size() const { return sizeof( *this ); } void dxJointUniversal::setRelativeValues() { dVector3 anchor; dJointGetUniversalAnchor(this, anchor); setAnchors( this, anchor[0], anchor[1], anchor[2], anchor1, anchor2 ); dVector3 ax1,ax2; dJointGetUniversalAxis1(this, ax1); dJointGetUniversalAxis2(this, ax2); if ( flags & dJOINT_REVERSE ) { setAxes( this, ax1[0],ax1[1],ax1[2], NULL, axis2 ); setAxes( this, ax2[0],ax2[1],ax2[2], axis1, NULL ); } else { setAxes( this, ax1[0],ax1[1],ax1[2], axis1, NULL ); setAxes( this, ax2[0],ax2[1],ax2[2], NULL, axis2 ); } computeInitialRelativeRotations(); } ode-0.16/ode/src/joints/ball.h0000664000175200017520000000463513403272463013101 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_JOINT_BALL_H_ #define _ODE_JOINT_BALL_H_ #include "joint.h" // ball and socket struct dxJointBall : public dxJoint { dVector3 anchor1; // anchor w.r.t first body dVector3 anchor2; // anchor w.r.t second body dReal erp; // error reduction dReal cfm; // constraint force mix in void set( int num, dReal value ); dReal get( int num ); dxJointBall( dxWorld *w ); virtual void getSureMaxInfo( SureMaxInfo* info ); virtual void getInfo1( Info1* info ); virtual void getInfo2( dReal worldFPS, dReal worldERP, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dReal *pairLoHi, int *findex ); virtual dJointType type() const; virtual sizeint size() const; virtual void setRelativeValues(); }; #endif ode-0.16/ode/src/joints/dball.cpp0000664000175200017520000002152513403272463013575 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include "config.h" #include "dball.h" #include "joint_internal.h" /* * Double Ball joint: tries to maintain a fixed distance between two anchor * points. */ dxJointDBall::dxJointDBall(dxWorld *w) : dxJoint(w) { dSetZero(anchor1, 3); dSetZero(anchor2, 3); targetDistance = 0; erp = world->global_erp; cfm = world->global_cfm; } void dxJointDBall::getSureMaxInfo( SureMaxInfo* info ) { info->max_m = 1; } void dxJointDBall::getInfo1( dxJoint::Info1 *info ) { info->m = 1; info->nub = 1; } void dxJointDBall::getInfo2( dReal worldFPS, dReal /*worldERP*/, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dReal *pairLoHi, int *findex ) { dVector3 globalA1, globalA2; dBodyGetRelPointPos(node[0].body, anchor1[0], anchor1[1], anchor1[2], globalA1); if (node[1].body) { dBodyGetRelPointPos(node[1].body, anchor2[0], anchor2[1], anchor2[2], globalA2); } else { dCopyVector3(globalA2, anchor2); } dVector3 q; dSubtractVectors3(q, globalA1, globalA2); #ifdef dSINGLE const dReal MIN_LENGTH = REAL(1e-7); #else const dReal MIN_LENGTH = REAL(1e-12); #endif if (dCalcVectorLength3(q) < MIN_LENGTH) { // too small, let's choose an arbitrary direction // heuristic: difference in velocities at anchors dVector3 v1, v2; dBodyGetPointVel(node[0].body, globalA1[0], globalA1[1], globalA1[2], v1); if (node[1].body) { dBodyGetPointVel(node[1].body, globalA2[0], globalA2[1], globalA2[2], v2); } else { dZeroVector3(v2); } dSubtractVectors3(q, v1, v2); if (dCalcVectorLength3(q) < MIN_LENGTH) { // this direction is as good as any dAssignVector3(q, 1, 0, 0); } } dNormalize3(q); dCopyVector3(J1 + GI2__JL_MIN, q); dVector3 relA1; dBodyVectorToWorld(node[0].body, anchor1[0], anchor1[1], anchor1[2], relA1); dMatrix3 a1m; dZeroMatrix3(a1m); dSetCrossMatrixMinus(a1m, relA1, 4); dMultiply1_331(J1 + GI2__JA_MIN, a1m, q); if (node[1].body) { dCopyNegatedVector3(J2 + GI2__JL_MIN, q); dVector3 relA2; dBodyVectorToWorld(node[1].body, anchor2[0], anchor2[1], anchor2[2], relA2); dMatrix3 a2m; dZeroMatrix3(a2m); dSetCrossMatrixPlus(a2m, relA2, 4); dMultiply1_331(J2 + GI2__JA_MIN, a2m, q); } const dReal k = worldFPS * this->erp; pairRhsCfm[GI2_RHS] = k * (targetDistance - dCalcPointsDistance3(globalA1, globalA2)); pairRhsCfm[GI2_CFM] = this->cfm; } void dxJointDBall::updateTargetDistance() { dVector3 p1, p2; if (node[0].body) dBodyGetRelPointPos(node[0].body, anchor1[0], anchor1[1], anchor1[2], p1); else dCopyVector3(p1, anchor1); if (node[1].body) dBodyGetRelPointPos(node[1].body, anchor2[0], anchor2[1], anchor2[2], p2); else dCopyVector3(p2, anchor2); targetDistance = dCalcPointsDistance3(p1, p2); } void dJointSetDBallAnchor1( dJointID j, dReal x, dReal y, dReal z ) { dxJointDBall* joint = static_cast(j); dUASSERT( joint, "bad joint argument" ); if ( joint->flags & dJOINT_REVERSE ) { if (joint->node[1].body) dBodyGetPosRelPoint(joint->node[1].body, x, y, z, joint->anchor2); else { joint->anchor2[0] = x; joint->anchor2[1] = y; joint->anchor2[2] = z; } } else { if (joint->node[0].body) dBodyGetPosRelPoint(joint->node[0].body, x, y, z, joint->anchor1); else { joint->anchor1[0] = x; joint->anchor1[1] = y; joint->anchor1[2] = z; } } joint->updateTargetDistance(); } void dJointSetDBallAnchor2( dJointID j, dReal x, dReal y, dReal z ) { dxJointDBall* joint = static_cast(j); dUASSERT( joint, "bad joint argument" ); if ( joint->flags & dJOINT_REVERSE ) { if (joint->node[0].body) dBodyGetPosRelPoint(joint->node[0].body, x, y, z, joint->anchor1); else { joint->anchor1[0] = x; joint->anchor1[1] = y; joint->anchor1[2] = z; } } else { if (joint->node[1].body) dBodyGetPosRelPoint(joint->node[1].body, x, y, z, joint->anchor2); else { joint->anchor2[0] = x; joint->anchor2[1] = y; joint->anchor2[2] = z; } } joint->updateTargetDistance(); } dReal dJointGetDBallDistance(dJointID j) { dxJointDBall* joint = static_cast(j); dUASSERT( joint, "bad joint argument" ); return joint->targetDistance; } void dJointSetDBallDistance(dJointID j, dReal dist) { dxJointDBall* joint = static_cast(j); dUASSERT( joint, "bad joint argument" ); dUASSERT( dist>=0, "target distance must be non-negative" ); joint->targetDistance = dist; } void dJointGetDBallAnchor1( dJointID j, dVector3 result ) { dxJointDBall* joint = static_cast(j); dUASSERT( joint, "bad joint argument" ); dUASSERT( result, "bad result argument" ); if ( joint->flags & dJOINT_REVERSE ) { if (joint->node[1].body) dBodyGetRelPointPos(joint->node[1].body, joint->anchor2[0], joint->anchor2[1], joint->anchor2[2], result); else dCopyVector3(result, joint->anchor2); } else { if (joint->node[0].body) dBodyGetRelPointPos(joint->node[0].body, joint->anchor1[0], joint->anchor1[1], joint->anchor1[2], result); else dCopyVector3(result, joint->anchor1); } } void dJointGetDBallAnchor2( dJointID j, dVector3 result ) { dxJointDBall* joint = static_cast(j); dUASSERT( joint, "bad joint argument" ); dUASSERT( result, "bad result argument" ); if ( joint->flags & dJOINT_REVERSE ) { if (joint->node[0].body) dBodyGetRelPointPos(joint->node[0].body, joint->anchor1[0], joint->anchor1[1], joint->anchor1[2], result); else dCopyVector3(result, joint->anchor1); } else { if (joint->node[1].body) dBodyGetRelPointPos(joint->node[1].body, joint->anchor2[0], joint->anchor2[1], joint->anchor2[2], result); else dCopyVector3(result, joint->anchor2); } } void dJointSetDBallParam( dJointID j, int parameter, dReal value ) { dxJointDBall* joint = static_cast(j); dUASSERT( joint, "bad joint argument" ); switch ( parameter ) { case dParamCFM: joint->cfm = value; break; case dParamERP: joint->erp = value; break; } } dReal dJointGetDBallParam( dJointID j, int parameter ) { dxJointDBall* joint = static_cast(j); dUASSERT( joint, "bad joint argument" ); switch ( parameter ) { case dParamCFM: return joint->cfm; case dParamERP: return joint->erp; default: return 0; } } dJointType dxJointDBall::type() const { return dJointTypeDBall; } sizeint dxJointDBall::size() const { return sizeof( *this ); } void dxJointDBall::setRelativeValues() { updateTargetDistance(); } ode-0.16/ode/src/joints/contact.h0000664000175200017520000000421413403272463013613 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_JOINT_CONTACT_H_ #define _ODE_JOINT_CONTACT_H_ #include "joint.h" // contact struct dxJointContact : public dxJoint { int the_m; // number of rows computed by getInfo1 dContact contact; dxJointContact( dxWorld* w ); virtual void getSureMaxInfo( SureMaxInfo* info ); virtual void getInfo1( Info1* info ); virtual void getInfo2( dReal worldFPS, dReal worldERP, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dReal *pairLoHi, int *findex); virtual dJointType type() const; virtual sizeint size() const; }; #endif ode-0.16/ode/src/joints/pr.cpp0000664000175200017520000004576213403272463013151 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include "config.h" #include "pr.h" #include "joint_internal.h" //**************************************************************************** // Prismatic and Rotoide dxJointPR::dxJointPR( dxWorld *w ) : dxJoint( w ) { // Default Position // Z^ // | Body 1 P R Body2 // |+---------+ _ _ +-----------+ // || |----|----(_)--------+ | // |+---------+ - +-----------+ // | // X.-----------------------------------------> Y // N.B. X is comming out of the page dSetZero( anchor2, 4 ); dSetZero( axisR1, 4 ); axisR1[0] = 1; dSetZero( axisR2, 4 ); axisR2[0] = 1; dSetZero( axisP1, 4 ); axisP1[1] = 1; dSetZero( qrel, 4 ); dSetZero( offset, 4 ); limotR.init( world ); limotP.init( world ); } dReal dJointGetPRPosition( dJointID j ) { dxJointPR* joint = ( dxJointPR* ) j; dUASSERT( joint, "bad joint argument" ); checktype( joint, PR ); dVector3 q; // get the offset in global coordinates dMultiply0_331( q, joint->node[0].body->posr.R, joint->offset ); if ( joint->node[1].body ) { dVector3 anchor2; // get the anchor2 in global coordinates dMultiply0_331( anchor2, joint->node[1].body->posr.R, joint->anchor2 ); q[0] = (( joint->node[0].body->posr.pos[0] + q[0] ) - ( joint->node[1].body->posr.pos[0] + anchor2[0] ) ); q[1] = (( joint->node[0].body->posr.pos[1] + q[1] ) - ( joint->node[1].body->posr.pos[1] + anchor2[1] ) ); q[2] = (( joint->node[0].body->posr.pos[2] + q[2] ) - ( joint->node[1].body->posr.pos[2] + anchor2[2] ) ); } else { //N.B. When there is no body 2 the joint->anchor2 is already in // global coordinates q[0] = (( joint->node[0].body->posr.pos[0] + q[0] ) - ( joint->anchor2[0] ) ); q[1] = (( joint->node[0].body->posr.pos[1] + q[1] ) - ( joint->anchor2[1] ) ); q[2] = (( joint->node[0].body->posr.pos[2] + q[2] ) - ( joint->anchor2[2] ) ); if ( joint->flags & dJOINT_REVERSE ) { q[0] = -q[0]; q[1] = -q[1]; q[2] = -q[2]; } } dVector3 axP; // get prismatic axis in global coordinates dMultiply0_331( axP, joint->node[0].body->posr.R, joint->axisP1 ); return dCalcVectorDot3( axP, q ); } dReal dJointGetPRPositionRate( dJointID j ) { dxJointPR* joint = ( dxJointPR* ) j; dUASSERT( joint, "bad joint argument" ); checktype( joint, PR ); // get axis1 in global coordinates dVector3 ax1; dMultiply0_331( ax1, joint->node[0].body->posr.R, joint->axisP1 ); if ( joint->node[1].body ) { dVector3 lv2; dBodyGetRelPointVel( joint->node[1].body, joint->anchor2[0], joint->anchor2[1], joint->anchor2[2], lv2 ); return dCalcVectorDot3( ax1, joint->node[0].body->lvel ) - dCalcVectorDot3( ax1, lv2 ); } else { dReal rate = dCalcVectorDot3( ax1, joint->node[0].body->lvel ); return ( (joint->flags & dJOINT_REVERSE) ? -rate : rate); } } dReal dJointGetPRAngle( dJointID j ) { dxJointPR* joint = ( dxJointPR* )j; dAASSERT( joint ); checktype( joint, PR ); if ( joint->node[0].body ) { dReal ang = getHingeAngle( joint->node[0].body, joint->node[1].body, joint->axisR1, joint->qrel ); if ( joint->flags & dJOINT_REVERSE ) return -ang; else return ang; } else return 0; } dReal dJointGetPRAngleRate( dJointID j ) { dxJointPR* joint = ( dxJointPR* )j; dAASSERT( joint ); checktype( joint, PR ); if ( joint->node[0].body ) { dVector3 axis; dMultiply0_331( axis, joint->node[0].body->posr.R, joint->axisR1 ); dReal rate = dCalcVectorDot3( axis, joint->node[0].body->avel ); if ( joint->node[1].body ) rate -= dCalcVectorDot3( axis, joint->node[1].body->avel ); if ( joint->flags & dJOINT_REVERSE ) rate = -rate; return rate; } else return 0; } void dxJointPR::getSureMaxInfo( SureMaxInfo* info ) { info->max_m = 6; } void dxJointPR::getInfo1( dxJoint::Info1 *info ) { info->nub = 4; info->m = 4; // see if we're at a joint limit. limotP.limit = 0; if (( limotP.lostop > -dInfinity || limotP.histop < dInfinity ) && limotP.lostop <= limotP.histop ) { // measure joint position dReal pos = dJointGetPRPosition( this ); limotP.testRotationalLimit( pos ); // N.B. The function is ill named } // powered needs an extra constraint row if ( limotP.limit || limotP.fmax > 0 ) info->m++; // see if we're at a joint limit. limotR.limit = 0; if (( limotR.lostop >= -M_PI || limotR.histop <= M_PI ) && limotR.lostop <= limotR.histop ) { dReal angle = getHingeAngle( node[0].body, node[1].body, axisR1, qrel ); limotR.testRotationalLimit( angle ); } // powered morit or at limits needs an extra constraint row if ( limotR.limit || limotR.fmax > 0 ) info->m++; } void dxJointPR::getInfo2( dReal worldFPS, dReal worldERP, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dReal *pairLoHi, int *findex ) { dReal k = worldFPS * worldERP; dVector3 q; // plane space of axP and after that axR // pull out pos and R for both bodies. also get the `connection' // vector pos2-pos1. dReal *pos2 = NULL, *R2 = NULL; dReal *pos1 = node[0].body->posr.pos; dReal *R1 = node[0].body->posr.R; dxBody *body1 = node[1].body; if ( body1 ) { pos2 = body1->posr.pos; R2 = body1->posr.R; } dVector3 axP; // Axis of the prismatic joint in global frame dMultiply0_331( axP, R1, axisP1 ); // distance between the body1 and the anchor2 in global frame // Calculated in the same way as the offset dVector3 wanchor2 = {0, 0, 0}, dist; if ( body1 ) { // Calculate anchor2 in world coordinate dMultiply0_331( wanchor2, R2, anchor2 ); dist[0] = wanchor2[0] + pos2[0] - pos1[0]; dist[1] = wanchor2[1] + pos2[1] - pos1[1]; dist[2] = wanchor2[2] + pos2[2] - pos1[2]; } else { if ( (flags & dJOINT_REVERSE) != 0 ) { dSubtractVectors3(dist, pos1, anchor2); // Invert the value } else { dSubtractVectors3(dist, anchor2, pos1); // Invert the value } } // ====================================================================== // Work on the Rotoide part (i.e. row 0, 1 and maybe 4 if rotoide powered // Set the two rotoide rows. The rotoide axis should be the only unconstrained // rotational axis, the angular velocity of the two bodies perpendicular to // the rotoide axis should be equal. Thus the constraint equations are // p*w1 - p*w2 = 0 // q*w1 - q*w2 = 0 // where p and q are unit vectors normal to the rotoide axis, and w1 and w2 // are the angular velocity vectors of the two bodies. dVector3 ax2; dVector3 ax1; dMultiply0_331( ax1, R1, axisR1 ); dCalcVectorCross3( q , ax1, axP ); dCopyVector3(J1 + GI2__JA_MIN, axP); if ( body1 ) { dCopyNegatedVector3(J2 + GI2__JA_MIN, axP); } dCopyVector3(J1 + rowskip + GI2__JA_MIN, q); if ( body1 ) { dCopyNegatedVector3(J2 + rowskip + GI2__JA_MIN, q); } // Compute the right hand side of the constraint equation set. Relative // body velocities along p and q to bring the rotoide back into alignment. // ax1,ax2 are the unit length rotoide axes of body1 and body2 in world frame. // We need to rotate both bodies along the axis u = (ax1 x ax2). // if `theta' is the angle between ax1 and ax2, we need an angular velocity // along u to cover angle erp*theta in one step : // |angular_velocity| = angle/time = erp*theta / stepsize // = (erp*fps) * theta // angular_velocity = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2| // = (erp*fps) * theta * (ax1 x ax2) / sin(theta) // ...as ax1 and ax2 are unit length. if theta is smallish, // theta ~= sin(theta), so // angular_velocity = (erp*fps) * (ax1 x ax2) // ax1 x ax2 is in the plane space of ax1, so we project the angular // velocity to p and q to find the right hand side. if ( body1 ) { dMultiply0_331( ax2, R2, axisR2 ); } else { dCopyVector3(ax2, axisR2); } dVector3 b; dCalcVectorCross3( b, ax1, ax2 ); pairRhsCfm[GI2_RHS] = k * dCalcVectorDot3( b, axP ); pairRhsCfm[pairskip + GI2_RHS] = k * dCalcVectorDot3( b, q ); // ========================== // Work on the Prismatic part (i.e row 2,3 and 4 if only the prismatic is powered // or 5 if rotoide and prismatic powered // two rows. we want: vel2 = vel1 + w1 x c ... but this would // result in three equations, so we project along the planespace vectors // so that sliding along the prismatic axis is disregarded. for symmetry we // also substitute (w1+w2)/2 for w1, as w1 is supposed to equal w2. // p1 + R1 dist' = p2 + R2 anchor2' ## OLD ## p1 + R1 anchor1' = p2 + R2 dist' // v1 + w1 x R1 dist' + v_p = v2 + w2 x R2 anchor2'## OLD v1 + w1 x R1 anchor1' = v2 + w2 x R2 dist' + v_p // v_p is speed of prismatic joint (i.e. elongation rate) // Since the constraints are perpendicular to v_p we have: // p dot v_p = 0 and q dot v_p = 0 // ax1 dot ( v1 + w1 x dist = v2 + w2 x anchor2 ) // q dot ( v1 + w1 x dist = v2 + w2 x anchor2 ) // == // ax1 . v1 + ax1 . w1 x dist = ax1 . v2 + ax1 . w2 x anchor2 ## OLD ## ax1 . v1 + ax1 . w1 x anchor1 = ax1 . v2 + ax1 . w2 x dist // since a . (b x c) = - b . (a x c) = - (a x c) . b // and a x b = - b x a // ax1 . v1 - ax1 x dist . w1 - ax1 . v2 - (- ax1 x anchor2 . w2) = 0 // ax1 . v1 + dist x ax1 . w1 - ax1 . v2 - anchor2 x ax1 . w2 = 0 // Coeff for 1er line of: J1l => ax1, J2l => -ax1 // Coeff for 2er line of: J1l => q, J2l => -q // Coeff for 1er line of: J1a => dist x ax1, J2a => - anchor2 x ax1 // Coeff for 2er line of: J1a => dist x q, J2a => - anchor2 x q int currRowSkip = 2 * rowskip; { dCopyVector3( J1 + currRowSkip + GI2__JL_MIN, ax1 ); dCalcVectorCross3( J1 + currRowSkip + GI2__JA_MIN, dist, ax1 ); if ( body1 ) { dCopyNegatedVector3( J2 + currRowSkip + GI2__JL_MIN, ax1 ); // ax2 x anchor2 instead of anchor2 x ax2 since we want the negative value dCalcVectorCross3( J2 + currRowSkip + GI2__JA_MIN, ax2, wanchor2 ); // since ax1 == ax2 } } currRowSkip += rowskip; { dCopyVector3( J1 + currRowSkip + GI2__JL_MIN, q ); dCalcVectorCross3(J1 + currRowSkip + GI2__JA_MIN, dist, q ); if ( body1 ) { dCopyNegatedVector3( J2 + currRowSkip + GI2__JL_MIN, q); // The cross product is in reverse order since we want the negative value dCalcVectorCross3( J2 + currRowSkip + GI2__JA_MIN, q, wanchor2 ); } } // We want to make correction for motion not in the line of the axisP // We calculate the displacement w.r.t. the anchor pt. // // compute the elements 2 and 3 of right hand side. // we want to align the offset point (in body 2's frame) with the center of body 1. // The position should be the same when we are not along the prismatic axis dVector3 err; dMultiply0_331( err, R1, offset ); dSubtractVectors3(err, dist, err); int currPairSkip = 2 * pairskip; { pairRhsCfm[currPairSkip + GI2_RHS] = k * dCalcVectorDot3( ax1, err ); } currPairSkip += pairskip; { pairRhsCfm[currPairSkip + GI2_RHS] = k * dCalcVectorDot3( q, err ); } currRowSkip += rowskip; currPairSkip += pairskip; if ( body1 || (flags & dJOINT_REVERSE) == 0 ) { if (limotP.addLimot ( this, worldFPS, J1 + currRowSkip, J2 + currRowSkip, pairRhsCfm + currPairSkip, pairLoHi + currPairSkip, axP, 0 )) { currRowSkip += rowskip; currPairSkip += pairskip; } } else { dVector3 rAxP; dCopyNegatedVector3(rAxP, axP); if (limotP.addLimot ( this, worldFPS, J1 + currRowSkip, J2 + currRowSkip, pairRhsCfm + currPairSkip, pairLoHi + currPairSkip, rAxP, 0 )) { currRowSkip += rowskip; currPairSkip += pairskip; } } limotR.addLimot ( this, worldFPS, J1 + currRowSkip, J2 + currRowSkip, pairRhsCfm + currPairSkip, pairLoHi + currPairSkip, ax1, 1 ); } // compute initial relative rotation body1 -> body2, or env -> body1 void dxJointPR::computeInitialRelativeRotation() { if ( node[0].body ) { if ( node[1].body ) { dQMultiply1( qrel, node[0].body->q, node[1].body->q ); } else { // set joint->qrel to the transpose of the first body q qrel[0] = node[0].body->q[0]; for ( int i = 1; i < 4; i++ ) qrel[i] = -node[0].body->q[i]; // WARNING do we need the - in -joint->node[0].body->q[i]; or not } } } void dJointSetPRAnchor( dJointID j, dReal x, dReal y, dReal z ) { dxJointPR* joint = ( dxJointPR* ) j; dUASSERT( joint, "bad joint argument" ); checktype( joint, PR ); setAnchors( joint, x, y, z, joint->offset, joint->anchor2 ); } void dJointSetPRAxis1( dJointID j, dReal x, dReal y, dReal z ) { dxJointPR* joint = ( dxJointPR* ) j; dUASSERT( joint, "bad joint argument" ); checktype( joint, PR ); setAxes( joint, x, y, z, joint->axisP1, 0 ); joint->computeInitialRelativeRotation(); } void dJointSetPRAxis2( dJointID j, dReal x, dReal y, dReal z ) { dxJointPR* joint = ( dxJointPR* ) j; dUASSERT( joint, "bad joint argument" ); checktype( joint, PR ); setAxes( joint, x, y, z, joint->axisR1, joint->axisR2 ); joint->computeInitialRelativeRotation(); } void dJointSetPRParam( dJointID j, int parameter, dReal value ) { dxJointPR* joint = ( dxJointPR* ) j; dUASSERT( joint, "bad joint argument" ); checktype( joint, PR ); if (( parameter & 0xff00 ) == 0x100 ) { joint->limotR.set( parameter & 0xff, value ); // Take only lower part of the } // parameter alue else { joint->limotP.set( parameter, value ); } } void dJointGetPRAnchor( dJointID j, dVector3 result ) { dxJointPR* joint = ( dxJointPR* ) j; dUASSERT( joint, "bad joint argument" ); dUASSERT( result, "bad result argument" ); checktype( joint, PR ); if ( joint->node[1].body ) getAnchor2( joint, result, joint->anchor2 ); else { result[0] = joint->anchor2[0]; result[1] = joint->anchor2[1]; result[2] = joint->anchor2[2]; } } void dJointGetPRAxis1( dJointID j, dVector3 result ) { dxJointPR* joint = ( dxJointPR* ) j; dUASSERT( joint, "bad joint argument" ); dUASSERT( result, "bad result argument" ); checktype( joint, PR ); getAxis( joint, result, joint->axisP1 ); } void dJointGetPRAxis2( dJointID j, dVector3 result ) { dxJointPR* joint = ( dxJointPR* ) j; dUASSERT( joint, "bad joint argument" ); dUASSERT( result, "bad result argument" ); checktype( joint, PR ); getAxis( joint, result, joint->axisR1 ); } dReal dJointGetPRParam( dJointID j, int parameter ) { dxJointPR* joint = ( dxJointPR* ) j; dUASSERT( joint, "bad joint argument" ); checktype( joint, PR ); if (( parameter & 0xff00 ) == 0x100 ) { return joint->limotR.get( parameter & 0xff ); } else { return joint->limotP.get( parameter ); } } void dJointAddPRTorque( dJointID j, dReal torque ) { dxJointPR* joint = ( dxJointPR* ) j; dVector3 axis; dAASSERT( joint ); checktype( joint, PR ); if ( joint->flags & dJOINT_REVERSE ) torque = -torque; getAxis( joint, axis, joint->axisR1 ); axis[0] *= torque; axis[1] *= torque; axis[2] *= torque; if ( joint->node[0].body != 0 ) dBodyAddTorque( joint->node[0].body, axis[0], axis[1], axis[2] ); if ( joint->node[1].body != 0 ) dBodyAddTorque( joint->node[1].body, -axis[0], -axis[1], -axis[2] ); } dJointType dxJointPR::type() const { return dJointTypePR; } sizeint dxJointPR::size() const { return sizeof( *this ); } void dxJointPR::setRelativeValues() { dVector3 anchor; dJointGetPRAnchor(this, anchor); setAnchors( this, anchor[0], anchor[1], anchor[2], offset, anchor2 ); dVector3 axis; dJointGetPRAxis1(this, axis); setAxes( this, axis[0], axis[1], axis[2], axisP1, 0 ); dJointGetPRAxis2(this, axis); setAxes( this, axis[0], axis[1], axis[2], axisR1, axisR2 ); computeInitialRelativeRotation(); } ode-0.16/ode/src/joints/hinge2.cpp0000664000175200017520000004054413403272463013675 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include "config.h" #include "hinge2.h" #include "joint_internal.h" //**************************************************************************** // hinge 2. note that this joint must be attached to two bodies for it to work dReal dxJointHinge2::measureAngle1() const { // bring axis 2 into first body's reference frame dVector3 p, q; if (node[1].body) dMultiply0_331( p, node[1].body->posr.R, axis2 ); else dCopyVector3(p, axis2); if (node[0].body) dMultiply1_331( q, node[0].body->posr.R, p ); else dCopyVector3(q, p); dReal x = dCalcVectorDot3( v1, q ); dReal y = dCalcVectorDot3( v2, q ); return -dAtan2( y, x ); } dReal dxJointHinge2::measureAngle2() const { // bring axis 1 into second body's reference frame dVector3 p, q; if (node[0].body) dMultiply0_331( p, node[0].body->posr.R, axis1 ); else dCopyVector3(p, axis1); if (node[1].body) dMultiply1_331( q, node[1].body->posr.R, p ); else dCopyVector3(q, p); dReal x = dCalcVectorDot3( w1, q ); dReal y = dCalcVectorDot3( w2, q ); return -dAtan2( y, x ); } dxJointHinge2::dxJointHinge2( dxWorld *w ) : dxJoint( w ) { dSetZero( anchor1, 4 ); dSetZero( anchor2, 4 ); dSetZero( axis1, 4 ); axis1[0] = 1; dSetZero( axis2, 4 ); axis2[1] = 1; c0 = 0; s0 = 0; dSetZero( v1, 4 ); v1[0] = 1; dSetZero( v2, 4 ); v2[1] = 1; limot1.init( world ); limot2.init( world ); susp_erp = world->global_erp; susp_cfm = world->global_cfm; flags |= dJOINT_TWOBODIES; } void dxJointHinge2::getSureMaxInfo( SureMaxInfo* info ) { info->max_m = 6; } void dxJointHinge2::getInfo1( dxJoint::Info1 *info ) { info->m = 4; info->nub = 4; // see if we're powered or at a joint limit for axis 1 limot1.limit = 0; if (( limot1.lostop >= -M_PI || limot1.histop <= M_PI ) && limot1.lostop <= limot1.histop ) { dReal angle = measureAngle1(); limot1.testRotationalLimit( angle ); } if ( limot1.limit || limot1.fmax > 0 ) info->m++; // see if we're powering axis 2 (we currently never limit this axis) limot2.limit = 0; if ( limot2.fmax > 0 ) info->m++; } //////////////////////////////////////////////////////////////////////////////// /// Function that computes ax1,ax2 = axis 1 and 2 in global coordinates (they are /// relative to body 1 and 2 initially) and then computes the constrained /// rotational axis as the cross product of ax1 and ax2. /// the sin and cos of the angle between axis 1 and 2 is computed, this comes /// from dot and cross product rules. /// /// @param ax1 Will contain the joint axis1 in world frame /// @param ax2 Will contain the joint axis2 in world frame /// @param axis Will contain the cross product of ax1 x ax2 /// @param sin_angle /// @param cos_angle //////////////////////////////////////////////////////////////////////////////// void dxJointHinge2::getAxisInfo(dVector3 ax1, dVector3 ax2, dVector3 axCross, dReal &sin_angle, dReal &cos_angle) const { dMultiply0_331 (ax1, node[0].body->posr.R, axis1); dMultiply0_331 (ax2, node[1].body->posr.R, axis2); dCalcVectorCross3(axCross,ax1,ax2); sin_angle = dSqrt (axCross[0]*axCross[0] + axCross[1]*axCross[1] + axCross[2]*axCross[2]); cos_angle = dCalcVectorDot3 (ax1,ax2); } void dxJointHinge2::getInfo2( dReal worldFPS, dReal worldERP, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dReal *pairLoHi, int *findex ) { // get information we need to set the hinge row dReal s, c; dVector3 q; dVector3 ax1, ax2; getAxisInfo( ax1, ax2, q, s, c ); dNormalize3( q ); // @@@ quicker: divide q by s ? // set the three ball-and-socket rows (aligned to the suspension axis ax1) setBall2( this, worldFPS, worldERP, rowskip, J1, J2, pairskip, pairRhsCfm, anchor1, anchor2, ax1, susp_erp ); // set parameter for the suspension pairRhsCfm[GI2_CFM] = susp_cfm; // set the hinge row int currRowSkip = 3 * rowskip; dCopyVector3(J1 + currRowSkip + GI2__JA_MIN, q); if ( node[1].body ) { dCopyNegatedVector3(J2 + currRowSkip + GI2__JA_MIN, q); } // compute the right hand side for the constrained rotational DOF. // axis 1 and axis 2 are separated by an angle `theta'. the desired // separation angle is theta0. sin(theta0) and cos(theta0) are recorded // in the joint structure. the correcting angular velocity is: // |angular_velocity| = angle/time = erp*(theta0-theta) / stepsize // = (erp*fps) * (theta0-theta) // (theta0-theta) can be computed using the following small-angle-difference // approximation: // theta0-theta ~= tan(theta0-theta) // = sin(theta0-theta)/cos(theta0-theta) // = (c*s0 - s*c0) / (c*c0 + s*s0) // = c*s0 - s*c0 assuming c*c0 + s*s0 ~= 1 // where c = cos(theta), s = sin(theta) // c0 = cos(theta0), s0 = sin(theta0) dReal k = worldFPS * worldERP; int currPairSkip = 3 * pairskip; pairRhsCfm[currPairSkip + GI2_RHS] = k * ( c0 * s - this->s0 * c ); currRowSkip += rowskip; currPairSkip += pairskip; // if the axis1 hinge is powered, or has joint limits, add in more stuff if (limot1.addLimot( this, worldFPS, J1 + currRowSkip, J2 + currRowSkip, pairRhsCfm + currPairSkip, pairLoHi + currPairSkip, ax1, 1 )) { currRowSkip += rowskip; currPairSkip += pairskip; } // if the axis2 hinge is powered, add in more stuff limot2.addLimot( this, worldFPS, J1 + currRowSkip, J2 + currRowSkip, pairRhsCfm + currPairSkip, pairLoHi + currPairSkip, ax2, 1 ); } // compute vectors v1 and v2 (embedded in body1), used to measure angle // between body 1 and body 2 void dxJointHinge2::makeV1andV2() { if ( node[0].body ) { // get axis 1 and 2 in global coords dVector3 ax1, ax2, v; dMultiply0_331( ax1, node[0].body->posr.R, axis1 ); dMultiply0_331( ax2, node[1].body->posr.R, axis2 ); // modify axis 2 so it's perpendicular to axis 1 dReal k = dCalcVectorDot3( ax1, ax2 ); dAddVectorScaledVector3(ax2, ax2, ax1, -k); if (dxSafeNormalize3( ax2 )) { // make v1 = modified axis2, v2 = axis1 x (modified axis2) dCalcVectorCross3( v, ax1, ax2 ); dMultiply1_331( v1, node[0].body->posr.R, ax2 ); dMultiply1_331( v2, node[0].body->posr.R, v ); } else { dUASSERT(false, "Hinge2 axes must be chosen to be linearly independent"); } } } // same as above, but for the second axis void dxJointHinge2::makeW1andW2() { if ( node[1].body ) { // get axis 1 and 2 in global coords dVector3 ax1, ax2, w; dMultiply0_331( ax1, node[0].body->posr.R, axis1 ); dMultiply0_331( ax2, node[1].body->posr.R, axis2 ); // modify axis 1 so it's perpendicular to axis 2 dReal k = dCalcVectorDot3( ax2, ax1 ); dAddVectorScaledVector3(ax1, ax1, ax2, -k); if (dxSafeNormalize3( ax1 )) { // make w1 = modified axis1, w2 = axis2 x (modified axis1) dCalcVectorCross3( w, ax2, ax1 ); dMultiply1_331( w1, node[1].body->posr.R, ax1 ); dMultiply1_331( w2, node[1].body->posr.R, w ); } else { dUASSERT(false, "Hinge2 axes must be chosen to be linearly independent"); } } } /*ODE_API */ void dJointSetHinge2Anchor( dJointID j, dReal x, dReal y, dReal z ) { dxJointHinge2* joint = ( dxJointHinge2* )j; dUASSERT( joint, "bad joint argument" ); checktype( joint, Hinge2 ); setAnchors( joint, x, y, z, joint->anchor1, joint->anchor2 ); joint->makeV1andV2(); joint->makeW1andW2(); } /*ODE_API */ void dJointSetHinge2Axes (dJointID j, const dReal *axis1/*=[dSA__MAX],=NULL*/, const dReal *axis2/*=[dSA__MAX],=NULL*/) { dxJointHinge2* joint = ( dxJointHinge2* )j; dUASSERT( joint, "bad joint argument" ); checktype( joint, Hinge2 ); dAASSERT(axis1 != NULL || axis2 != NULL); dAASSERT(joint->node[0].body != NULL || axis1 == NULL); dAASSERT(joint->node[1].body != NULL || axis2 == NULL); if ( axis1 != NULL ) { setAxes(joint, axis1[dSA_X], axis1[dSA_Y], axis1[dSA_Z], joint->axis1, NULL); } if ( axis2 != NULL ) { setAxes(joint, axis2[dSA_X], axis2[dSA_Y], axis2[dSA_Z], NULL, joint->axis2); } // compute the sin and cos of the angle between axis 1 and axis 2 dVector3 ax1, ax2, ax; joint->getAxisInfo( ax1, ax2, ax, joint->s0, joint->c0 ); joint->makeV1andV2(); joint->makeW1andW2(); } /*ODE_API_DEPRECATED ODE_API */ void dJointSetHinge2Axis1( dJointID j, dReal x, dReal y, dReal z ) { dVector3 axis1; axis1[dSA_X] = x; axis1[dSA_Y] = y; axis1[dSA_Z] = z; dJointSetHinge2Axes(j, axis1, NULL); } /*ODE_API_DEPRECATED ODE_API */ void dJointSetHinge2Axis2( dJointID j, dReal x, dReal y, dReal z ) { dVector3 axis2; axis2[dSA_X] = x; axis2[dSA_Y] = y; axis2[dSA_Z] = z; dJointSetHinge2Axes(j, NULL, axis2); } void dJointSetHinge2Param( dJointID j, int parameter, dReal value ) { dxJointHinge2* joint = ( dxJointHinge2* )j; dUASSERT( joint, "bad joint argument" ); checktype( joint, Hinge2 ); if (( parameter & 0xff00 ) == 0x100 ) { joint->limot2.set( parameter & 0xff, value ); } else { if ( parameter == dParamSuspensionERP ) joint->susp_erp = value; else if ( parameter == dParamSuspensionCFM ) joint->susp_cfm = value; else joint->limot1.set( parameter, value ); } } void dJointGetHinge2Anchor( dJointID j, dVector3 result ) { dxJointHinge2* joint = ( dxJointHinge2* )j; dUASSERT( joint, "bad joint argument" ); dUASSERT( result, "bad result argument" ); checktype( joint, Hinge2 ); if ( joint->flags & dJOINT_REVERSE ) getAnchor2( joint, result, joint->anchor2 ); else getAnchor( joint, result, joint->anchor1 ); } void dJointGetHinge2Anchor2( dJointID j, dVector3 result ) { dxJointHinge2* joint = ( dxJointHinge2* )j; dUASSERT( joint, "bad joint argument" ); dUASSERT( result, "bad result argument" ); checktype( joint, Hinge2 ); if ( joint->flags & dJOINT_REVERSE ) getAnchor( joint, result, joint->anchor1 ); else getAnchor2( joint, result, joint->anchor2 ); } void dJointGetHinge2Axis1( dJointID j, dVector3 result ) { dxJointHinge2* joint = ( dxJointHinge2* )j; dUASSERT( joint, "bad joint argument" ); dUASSERT( result, "bad result argument" ); checktype( joint, Hinge2 ); if ( joint->node[0].body ) { dMultiply0_331( result, joint->node[0].body->posr.R, joint->axis1 ); } else { dZeroVector3(result); dUASSERT( false, "the joint does not have first body attached" ); } } void dJointGetHinge2Axis2( dJointID j, dVector3 result ) { dxJointHinge2* joint = ( dxJointHinge2* )j; dUASSERT( joint, "bad joint argument" ); dUASSERT( result, "bad result argument" ); checktype( joint, Hinge2 ); if ( joint->node[1].body ) { dMultiply0_331( result, joint->node[1].body->posr.R, joint->axis2 ); } else { dZeroVector3(result); dUASSERT( false, "the joint does not have second body attached" ); } } dReal dJointGetHinge2Param( dJointID j, int parameter ) { dxJointHinge2* joint = ( dxJointHinge2* )j; dUASSERT( joint, "bad joint argument" ); checktype( joint, Hinge2 ); if (( parameter & 0xff00 ) == 0x100 ) { return joint->limot2.get( parameter & 0xff ); } else { if ( parameter == dParamSuspensionERP ) return joint->susp_erp; else if ( parameter == dParamSuspensionCFM ) return joint->susp_cfm; else return joint->limot1.get( parameter ); } } dReal dJointGetHinge2Angle1( dJointID j ) { dxJointHinge2* joint = ( dxJointHinge2* )j; dUASSERT( joint, "bad joint argument" ); checktype( joint, Hinge2 ); return joint->measureAngle1(); } dReal dJointGetHinge2Angle2( dJointID j ) { dxJointHinge2* joint = ( dxJointHinge2* )j; dUASSERT( joint, "bad joint argument" ); checktype( joint, Hinge2 ); return joint->measureAngle2(); } dReal dJointGetHinge2Angle1Rate( dJointID j ) { dxJointHinge2* joint = ( dxJointHinge2* )j; dUASSERT( joint, "bad joint argument" ); checktype( joint, Hinge2 ); if ( joint->node[0].body ) { dVector3 axis; dMultiply0_331( axis, joint->node[0].body->posr.R, joint->axis1 ); dReal rate = dCalcVectorDot3( axis, joint->node[0].body->avel ); if ( joint->node[1].body ) rate -= dCalcVectorDot3( axis, joint->node[1].body->avel ); return rate; } else return 0; } dReal dJointGetHinge2Angle2Rate( dJointID j ) { dxJointHinge2* joint = ( dxJointHinge2* )j; dUASSERT( joint, "bad joint argument" ); checktype( joint, Hinge2 ); if ( joint->node[0].body && joint->node[1].body ) { dVector3 axis; dMultiply0_331( axis, joint->node[1].body->posr.R, joint->axis2 ); dReal rate = dCalcVectorDot3( axis, joint->node[0].body->avel ); if ( joint->node[1].body ) rate -= dCalcVectorDot3( axis, joint->node[1].body->avel ); return rate; } else return 0; } void dJointAddHinge2Torques( dJointID j, dReal torque1, dReal torque2 ) { dxJointHinge2* joint = ( dxJointHinge2* )j; dVector3 axis1, axis2; dUASSERT( joint, "bad joint argument" ); checktype( joint, Hinge2 ); if ( joint->node[0].body && joint->node[1].body ) { dMultiply0_331( axis1, joint->node[0].body->posr.R, joint->axis1 ); dMultiply0_331( axis2, joint->node[1].body->posr.R, joint->axis2 ); axis1[0] = axis1[0] * torque1 + axis2[0] * torque2; axis1[1] = axis1[1] * torque1 + axis2[1] * torque2; axis1[2] = axis1[2] * torque1 + axis2[2] * torque2; dBodyAddTorque( joint->node[0].body, axis1[0], axis1[1], axis1[2] ); dBodyAddTorque( joint->node[1].body, -axis1[0], -axis1[1], -axis1[2] ); } } dJointType dxJointHinge2::type() const { return dJointTypeHinge2; } sizeint dxJointHinge2::size() const { return sizeof( *this ); } void dxJointHinge2::setRelativeValues() { dVector3 anchor; dJointGetHinge2Anchor(this, anchor); setAnchors( this, anchor[0], anchor[1], anchor[2], anchor1, anchor2 ); dVector3 axis; if ( node[0].body ) { dJointGetHinge2Axis1(this, axis); setAxes( this, axis[0],axis[1],axis[2], axis1, NULL ); } if ( node[0].body ) { dJointGetHinge2Axis2(this, axis); setAxes( this, axis[0],axis[1],axis[2], NULL, axis2 ); } dVector3 ax1, ax2; getAxisInfo( ax1, ax2, axis, s0, c0 ); makeV1andV2(); makeW1andW2(); } ode-0.16/ode/src/joints/null.h0000664000175200017520000000411013403272463013125 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_JOINT_NULL_H_ #define _ODE_JOINT_NULL_H_ #include "joint.h" // null joint, for testing only struct dxJointNull : public dxJoint { dxJointNull( dxWorld *w ); virtual void getSureMaxInfo( SureMaxInfo* info ); virtual void getInfo1( Info1* info ); virtual void getInfo2( dReal worldFPS, dReal worldERP, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dReal *pairLoHi, int *findex ); virtual dJointType type() const; virtual sizeint size() const; }; #endif ode-0.16/ode/src/joints/pr.h0000664000175200017520000000767313403272463012615 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_JOINT_PR_H_ #define _ODE_JOINT_PR_H_ #include "joint.h" /** * The axisP must be perpendicular to axis2 *
 *                                        +-------------+
 *                                        |      x      |
 *                                        +------------\+
 * Prismatic articulation                   ..     ..
 *                       |                ..     ..
 *                      \/              ..      ..
 * +--------------+    --|        __..      ..  anchor2
 * |      x       | .....|.......(__)     ..
 * +--------------+    --|         ^     <
 *        |----------------------->|
 *            Offset               |--- Rotoide articulation
 * 
*/ struct dxJointPR : public dxJoint { /// @brief Position of the rotoide articulation w.r.t second body. /// @note Position of body 2 in world frame + anchor2 in world frame give /// the position of the rotoide articulation dVector3 anchor2; /// axis of the rotoide articulation w.r.t first body. /// @note This is considered as axis1 from the parameter view. dVector3 axisR1; /// axis of the rotoide articulation w.r.t second body. /// @note This is considered also as axis1 from the parameter view dVector3 axisR2; /// axis for the prismatic articulation w.r.t first body. /// @note This is considered as axis2 in from the parameter view dVector3 axisP1; dQuaternion qrel; ///< initial relative rotation body1 -> body2. /// @brief vector between the body1 and the rotoide articulation. /// /// Going from the first to the second in the frame of body1. /// That should be aligned with body1 center along axisP. /// This is calculated when the axis are set. dVector3 offset; dxJointLimitMotor limotR; ///< limit and motor information for the rotoide articulation. dxJointLimitMotor limotP; ///< limit and motor information for the prismatic articulation. void computeInitialRelativeRotation(); dxJointPR( dxWorld *w ); virtual void getSureMaxInfo( SureMaxInfo* info ); virtual void getInfo1( Info1* info ); virtual void getInfo2( dReal worldFPS, dReal worldERP, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dReal *pairLoHi, int *findex ); virtual dJointType type() const; virtual sizeint size() const; virtual void setRelativeValues(); }; #endif ode-0.16/ode/src/joints/slider.cpp0000664000175200017520000003116513403272463014002 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include "config.h" #include "slider.h" #include "joint_internal.h" //**************************************************************************** // slider dxJointSlider::dxJointSlider ( dxWorld *w ) : dxJoint ( w ) { dSetZero ( axis1, 4 ); axis1[0] = 1; dSetZero ( qrel, 4 ); dSetZero ( offset, 4 ); limot.init ( world ); } dReal dJointGetSliderPosition ( dJointID j ) { dxJointSlider* joint = ( dxJointSlider* ) j; dUASSERT ( joint, "bad joint argument" ); checktype ( joint, Slider ); // get axis1 in global coordinates dVector3 ax1, q; dMultiply0_331 ( ax1, joint->node[0].body->posr.R, joint->axis1 ); if ( joint->node[1].body ) { // get body2 + offset point in global coordinates dMultiply0_331 ( q, joint->node[1].body->posr.R, joint->offset ); for ( int i = 0; i < 3; i++ ) q[i] = joint->node[0].body->posr.pos[i] - q[i] - joint->node[1].body->posr.pos[i]; } else { q[0] = joint->node[0].body->posr.pos[0] - joint->offset[0]; q[1] = joint->node[0].body->posr.pos[1] - joint->offset[1]; q[2] = joint->node[0].body->posr.pos[2] - joint->offset[2]; if ( joint->flags & dJOINT_REVERSE ) { // N.B. it could have been simplier to only inverse the sign of // the dCalcVectorDot3 result but this case is exceptional and doing // the check for all case can decrease the performance. ax1[0] = -ax1[0]; ax1[1] = -ax1[1]; ax1[2] = -ax1[2]; } } return dCalcVectorDot3 ( ax1, q ); } dReal dJointGetSliderPositionRate ( dJointID j ) { dxJointSlider* joint = ( dxJointSlider* ) j; dUASSERT ( joint, "bad joint argument" ); checktype ( joint, Slider ); // get axis1 in global coordinates dVector3 ax1; dMultiply0_331 ( ax1, joint->node[0].body->posr.R, joint->axis1 ); if ( joint->node[1].body ) { return dCalcVectorDot3 ( ax1, joint->node[0].body->lvel ) - dCalcVectorDot3 ( ax1, joint->node[1].body->lvel ); } else { dReal rate = dCalcVectorDot3 ( ax1, joint->node[0].body->lvel ); if ( joint->flags & dJOINT_REVERSE ) rate = - rate; return rate; } } void dxJointSlider::getSureMaxInfo( SureMaxInfo* info ) { info->max_m = 6; } void dxJointSlider::getInfo1 ( dxJoint::Info1 *info ) { info->nub = 5; // see if joint is powered if ( limot.fmax > 0 ) info->m = 6; // powered slider needs an extra constraint row else info->m = 5; // see if we're at a joint limit. limot.limit = 0; if ( ( limot.lostop > -dInfinity || limot.histop < dInfinity ) && limot.lostop <= limot.histop ) { // measure joint position dReal pos = dJointGetSliderPosition ( this ); if ( pos <= limot.lostop ) { limot.limit = 1; limot.limit_err = pos - limot.lostop; info->m = 6; } else if ( pos >= limot.histop ) { limot.limit = 2; limot.limit_err = pos - limot.histop; info->m = 6; } } } void dxJointSlider::getInfo2 ( dReal worldFPS, dReal worldERP, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dReal *pairLoHi, int *findex ) { // 3 rows to make body rotations equal setFixedOrientation ( this, worldFPS, worldERP, rowskip, J1, J2, pairskip, pairRhsCfm, qrel ); // pull out pos and R for both bodies. also get the `connection' // vector pos2-pos1. dVector3 c; dReal *pos2 = NULL, *R2 = NULL; dReal *pos1 = node[0].body->posr.pos; dReal *R1 = node[0].body->posr.R; dVector3 ax1; // joint axis in global coordinates (unit length) dVector3 p, q; // plane space of ax1 dMultiply0_331 ( ax1, R1, axis1 ); dPlaneSpace ( ax1, p, q ); dxBody *body1 = node[1].body; if ( body1 ) { R2 = body1->posr.R; pos2 = body1->posr.pos; dSubtractVectors3( c, pos2, pos1 ); } // remaining two rows. we want: vel2 = vel1 + w1 x c ... but this would // result in three equations, so we project along the planespace vectors // so that sliding along the slider axis is disregarded. for symmetry we // also substitute (w1+w2)/2 for w1, as w1 is supposed to equal w2. int currRowSkip = 3 * rowskip, currPairSkip = 3 * pairskip; { dCopyVector3( J1 + currRowSkip + GI2__JL_MIN, p ); if ( body1 ) { dVector3 tmp; dCopyNegatedVector3(J2 + currRowSkip + GI2__JL_MIN, p); dCalcVectorCross3( tmp, c, p ); dCopyScaledVector3( J1 + currRowSkip + GI2__JA_MIN, tmp, REAL(0.5) ); dCopyVector3( J2 + currRowSkip + GI2__JA_MIN, J1 + currRowSkip + GI2__JA_MIN ); } } currRowSkip += rowskip; { dCopyVector3( J1 + currRowSkip + GI2__JL_MIN, q ); if ( body1 ) { dVector3 tmp; dCopyNegatedVector3(J2 + currRowSkip + GI2__JL_MIN, q); dCalcVectorCross3( tmp, c, q ); dCopyScaledVector3( J1 + currRowSkip + GI2__JA_MIN, tmp, REAL(0.5) ); dCopyVector3( J2 + currRowSkip + GI2__JA_MIN, J1 + currRowSkip + GI2__JA_MIN ); } } // compute last two elements of right hand side. we want to align the offset // point (in body 2's frame) with the center of body 1. dReal k = worldFPS * worldERP; if ( body1 ) { dVector3 ofs; // offset point in global coordinates dMultiply0_331 ( ofs, R2, offset ); dAddVectors3(c, c, ofs); pairRhsCfm[currPairSkip + GI2_RHS] = k * dCalcVectorDot3 ( p, c ); currPairSkip += pairskip; pairRhsCfm[currPairSkip + GI2_RHS] = k * dCalcVectorDot3 ( q, c ); } else { dVector3 ofs; // offset point in global coordinates dSubtractVectors3(ofs, offset, pos1); pairRhsCfm[currPairSkip + GI2_RHS] = k * dCalcVectorDot3 ( p, ofs ); currPairSkip += pairskip; pairRhsCfm[currPairSkip + GI2_RHS] = k * dCalcVectorDot3 ( q, ofs ); if ( (flags & dJOINT_REVERSE) != 0 ) { dNegateVector3(ax1); } } // if the slider is powered, or has joint limits, add in the extra row currRowSkip += rowskip; currPairSkip += pairskip; limot.addLimot ( this, worldFPS, J1 + currRowSkip, J2 + currRowSkip, pairRhsCfm + currPairSkip, pairLoHi + currPairSkip, ax1, 0 ); } void dJointSetSliderAxis ( dJointID j, dReal x, dReal y, dReal z ) { dxJointSlider* joint = ( dxJointSlider* ) j; dUASSERT ( joint, "bad joint argument" ); checktype ( joint, Slider ); setAxes ( joint, x, y, z, joint->axis1, 0 ); joint->computeOffset(); joint->computeInitialRelativeRotation(); } void dJointSetSliderAxisDelta ( dJointID j, dReal x, dReal y, dReal z, dReal dx, dReal dy, dReal dz ) { dxJointSlider* joint = ( dxJointSlider* ) j; dUASSERT ( joint, "bad joint argument" ); checktype ( joint, Slider ); setAxes ( joint, x, y, z, joint->axis1, 0 ); joint->computeOffset(); // compute initial relative rotation body1 -> body2, or env -> body1 // also compute center of body1 w.r.t body 2 if ( !(joint->node[1].body) ) { joint->offset[0] += dx; joint->offset[1] += dy; joint->offset[2] += dz; } joint->computeInitialRelativeRotation(); } void dJointGetSliderAxis ( dJointID j, dVector3 result ) { dxJointSlider* joint = ( dxJointSlider* ) j; dUASSERT ( joint, "bad joint argument" ); dUASSERT ( result, "bad result argument" ); checktype ( joint, Slider ); getAxis ( joint, result, joint->axis1 ); } void dJointSetSliderParam ( dJointID j, int parameter, dReal value ) { dxJointSlider* joint = ( dxJointSlider* ) j; dUASSERT ( joint, "bad joint argument" ); checktype ( joint, Slider ); joint->limot.set ( parameter, value ); } dReal dJointGetSliderParam ( dJointID j, int parameter ) { dxJointSlider* joint = ( dxJointSlider* ) j; dUASSERT ( joint, "bad joint argument" ); checktype ( joint, Slider ); return joint->limot.get ( parameter ); } void dJointAddSliderForce ( dJointID j, dReal force ) { dxJointSlider* joint = ( dxJointSlider* ) j; dVector3 axis; dUASSERT ( joint, "bad joint argument" ); checktype ( joint, Slider ); if ( joint->flags & dJOINT_REVERSE ) force = -force; getAxis ( joint, axis, joint->axis1 ); axis[0] *= force; axis[1] *= force; axis[2] *= force; if ( joint->node[0].body != 0 ) dBodyAddForce ( joint->node[0].body, axis[0], axis[1], axis[2] ); if ( joint->node[1].body != 0 ) dBodyAddForce ( joint->node[1].body, -axis[0], -axis[1], -axis[2] ); if ( joint->node[0].body != 0 && joint->node[1].body != 0 ) { // linear torque decoupling: // we have to compensate the torque, that this slider force may generate // if body centers are not aligned along the slider axis dVector3 ltd; // Linear Torque Decoupling vector (a torque) dVector3 c; c[0] = REAL ( 0.5 ) * ( joint->node[1].body->posr.pos[0] - joint->node[0].body->posr.pos[0] ); c[1] = REAL ( 0.5 ) * ( joint->node[1].body->posr.pos[1] - joint->node[0].body->posr.pos[1] ); c[2] = REAL ( 0.5 ) * ( joint->node[1].body->posr.pos[2] - joint->node[0].body->posr.pos[2] ); dCalcVectorCross3( ltd, c, axis ); dBodyAddTorque ( joint->node[0].body, ltd[0], ltd[1], ltd[2] ); dBodyAddTorque ( joint->node[1].body, ltd[0], ltd[1], ltd[2] ); } } dJointType dxJointSlider::type() const { return dJointTypeSlider; } sizeint dxJointSlider::size() const { return sizeof ( *this ); } void dxJointSlider::setRelativeValues() { computeOffset(); computeInitialRelativeRotation(); } /// Compute initial relative rotation body1 -> body2, or env -> body1 void dxJointSlider::computeInitialRelativeRotation() { if ( node[0].body ) { // compute initial relative rotation body1 -> body2, or env -> body1 // also compute center of body1 w.r.t body 2 if ( node[1].body ) { dQMultiply1 ( qrel, node[0].body->q, node[1].body->q ); } else { // set qrel to the transpose of the first body's q qrel[0] = node[0].body->q[0]; qrel[1] = -node[0].body->q[1]; qrel[2] = -node[0].body->q[2]; qrel[3] = -node[0].body->q[3]; } } } /// Compute center of body1 w.r.t body 2 void dxJointSlider::computeOffset() { if ( node[1].body ) { dVector3 c; c[0] = node[0].body->posr.pos[0] - node[1].body->posr.pos[0]; c[1] = node[0].body->posr.pos[1] - node[1].body->posr.pos[1]; c[2] = node[0].body->posr.pos[2] - node[1].body->posr.pos[2]; dMultiply1_331 ( offset, node[1].body->posr.R, c ); } else if ( node[0].body ) { offset[0] = node[0].body->posr.pos[0]; offset[1] = node[0].body->posr.pos[1]; offset[2] = node[0].body->posr.pos[2]; } } ode-0.16/ode/src/joints/plane2d.cpp0000664000175200017520000001325713403272463014047 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include "config.h" #include "plane2d.h" #include "joint_internal.h" //**************************************************************************** // Plane2D /* This code is part of the Plane2D ODE joint by psero@gmx.de Wed Apr 23 18:53:43 CEST 2003 */ static const dReal Midentity[3][3] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1, } }; dxJointPlane2D::dxJointPlane2D( dxWorld *w ) : dxJoint( w ) { motor_x.init( world ); motor_y.init( world ); motor_angle.init( world ); } void dxJointPlane2D::getSureMaxInfo( SureMaxInfo* info ) { info->max_m = 6; } void dxJointPlane2D::getInfo1( dxJoint::Info1 *info ) { info->nub = 3; info->m = 3; if ( motor_x.fmax > 0 ) row_motor_x = info->m++; else row_motor_x = 0; if ( motor_y.fmax > 0 ) row_motor_y = info->m++; else row_motor_y = 0; if ( motor_angle.fmax > 0 ) row_motor_angle = info->m++; else row_motor_angle = 0; } void dxJointPlane2D::getInfo2( dReal worldFPS, dReal worldERP, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dReal *pairLoHi, int *findex ) { dReal eps = worldFPS * worldERP; /* v = v1, w = omega1 (v2, omega2 not important (== static environment)) constraint equations: vz = 0 wx = 0 wy = 0 <=> ( 0 0 1 ) (vx) ( 0 0 0 ) (wx) ( 0 ) ( 0 0 0 ) (vy) + ( 1 0 0 ) (wy) = ( 0 ) ( 0 0 0 ) (vz) ( 0 1 0 ) (wz) ( 0 ) J1/J1l Omega1/J1a */ // fill in linear and angular coeff. for left hand side: J1[GI2_JLZ] = 1; J1[rowskip + GI2_JAX] = 1; J1[2 * rowskip + GI2_JAY] = 1; // error correction (against drift): // a) linear vz, so that z (== pos[2]) == 0 pairRhsCfm[GI2_RHS] = eps * -node[0].body->posr.pos[2]; # if 0 // b) angular correction? -> left to application !!! dReal *body_z_axis = &node[0].body->R[8]; pairRhsCfm[pairskip + GI2_RHS] = eps * + atan2( body_z_axis[1], body_z_axis[2] ); // wx error pairRhsCfm[2 * pairskip + GI2_RHS] = eps * -atan2( body_z_axis[0], body_z_axis[2] ); // wy error # endif // if the slider is powered, or has joint limits, add in the extra row: if ( row_motor_x > 0 ) { int currRowSkip = row_motor_x * rowskip, currPairSkip = row_motor_x * pairskip; motor_x.addLimot( this, worldFPS, J1 + currRowSkip, J2 + currRowSkip, pairRhsCfm + currPairSkip, pairLoHi + currPairSkip, Midentity[0], 0 ); } if ( row_motor_y > 0 ) { int currRowSkip = row_motor_y * rowskip, currPairSkip = row_motor_y * pairskip; motor_y.addLimot( this, worldFPS, J1 + currRowSkip, J2 + currRowSkip, pairRhsCfm + currPairSkip, pairLoHi + currPairSkip, Midentity[1], 0 ); } if ( row_motor_angle > 0 ) { int currRowSkip = row_motor_angle * rowskip, currPairSkip = row_motor_angle * pairskip; motor_angle.addLimot( this, worldFPS, J1 + currRowSkip, J2 + currRowSkip, pairRhsCfm + currPairSkip, pairLoHi + currPairSkip, Midentity[2], 1 ); } } dJointType dxJointPlane2D::type() const { return dJointTypePlane2D; } sizeint dxJointPlane2D::size() const { return sizeof( *this ); } void dJointSetPlane2DXParam( dxJoint *joint, int parameter, dReal value ) { dUASSERT( joint, "bad joint argument" ); checktype( joint, Plane2D ); dxJointPlane2D* joint2d = ( dxJointPlane2D* )( joint ); joint2d->motor_x.set( parameter, value ); } void dJointSetPlane2DYParam( dxJoint *joint, int parameter, dReal value ) { dUASSERT( joint, "bad joint argument" ); checktype( joint, Plane2D ); dxJointPlane2D* joint2d = ( dxJointPlane2D* )( joint ); joint2d->motor_y.set( parameter, value ); } void dJointSetPlane2DAngleParam( dxJoint *joint, int parameter, dReal value ) { dUASSERT( joint, "bad joint argument" ); checktype( joint, Plane2D ); dxJointPlane2D* joint2d = ( dxJointPlane2D* )( joint ); joint2d->motor_angle.set( parameter, value ); } ode-0.16/ode/src/joints/hinge2.h0000664000175200017520000000564513403272463013345 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_JOINT_HINGE2_H_ #define _ODE_JOINT_HINGE2_H_ #include "joint.h" // hinge 2 struct dxJointHinge2 : public dxJoint { dVector3 anchor1; // anchor w.r.t first body dVector3 anchor2; // anchor w.r.t second body dVector3 axis1; // axis 1 w.r.t first body dVector3 axis2; // axis 2 w.r.t second body dReal c0, s0; // cos,sin of desired angle between axis 1,2 dVector3 v1, v2; // angle ref vectors embedded in first body dVector3 w1, w2; // angle ref vectors embedded in second body dxJointLimitMotor limot1; // limit+motor info for axis 1 dxJointLimitMotor limot2; // limit+motor info for axis 2 dReal susp_erp, susp_cfm; // suspension parameters (erp,cfm) dReal measureAngle1() const; dReal measureAngle2() const; void makeV1andV2(); void makeW1andW2(); void getAxisInfo(dVector3 ax1, dVector3 ax2, dVector3 axis, dReal &sin_angle, dReal &cos_Angle) const; dxJointHinge2( dxWorld *w ); virtual void getSureMaxInfo( SureMaxInfo* info ); virtual void getInfo1( Info1* info ); virtual void getInfo2( dReal worldFPS, dReal worldERP, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dReal *pairLoHi, int *findex ); virtual dJointType type() const; virtual sizeint size() const; virtual void setRelativeValues(); }; #endif ode-0.16/ode/src/joints/amotor.h0000664000175200017520000001077213403272463013467 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_JOINT_AMOTOR_H_ #define _ODE_JOINT_AMOTOR_H_ #include "joint.h" // angular motor typedef dxJoint dxJointAMotor_Parent; class dxJointAMotor: public dxJointAMotor_Parent { public: dxJointAMotor(dxWorld *w); virtual ~dxJointAMotor(); public: virtual void getSureMaxInfo(SureMaxInfo* info); virtual void getInfo1(Info1* info); virtual void getInfo2(dReal worldFPS, dReal worldERP, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dReal *pairLoHi, int *findex); virtual dJointType type() const; virtual sizeint size() const; public: void setOperationMode(int mode); int getOperationMode() const { return m_mode; } void setNumAxes(unsigned num); int getNumAxes() const { return m_num; } dJointBodyRelativity getAxisBodyRelativity(unsigned anum) const; void setAxisValue(unsigned anum, dJointBodyRelativity rel, dReal x, dReal y, dReal z); void getAxisValue(dVector3 result, unsigned anum) const; private: void doGetUserAxis(dVector3 result, unsigned anum) const; void doGetEulerAxis(dVector3 result, unsigned anum) const; public: void setAngleValue(unsigned anum, dReal angle); dReal getAngleValue(unsigned anum) const { dAASSERT(dIN_RANGE(anum, dSA__MIN, dSA__MAX)); return m_angle[anum]; } dReal calculateAngleRate(unsigned anum) const; void setLimotParameter(unsigned anum, int limotParam, dReal value) { dAASSERT(dIN_RANGE(anum, dSA__MIN, dSA__MAX)); m_limot[anum].set(limotParam, value); } dReal getLimotParameter(unsigned anum, int limotParam) const { dAASSERT(dIN_RANGE(anum, dSA__MIN, dSA__MAX)); return m_limot[anum].get(limotParam); } public: void addTorques(dReal torque1, dReal torque2, dReal torque3); private: void computeGlobalAxes(dVector3 ax[dSA__MAX]) const; void doComputeGlobalUserAxes(dVector3 ax[dSA__MAX]) const; void doComputeGlobalEulerAxes(dVector3 ax[dSA__MAX]) const; void computeEulerAngles(dVector3 ax[dSA__MAX]); void setEulerReferenceVectors(); private: inline dSpaceAxis BuildFirstBodyEulerAxis() const; inline dJointConnectedBody BuildFirstEulerAxisBody() const; private: friend struct dxAMotorJointPrinter; private: int m_mode; // a dAMotorXXX constant unsigned m_num; // number of axes (0..3) dJointBodyRelativity m_rel[dSA__MAX]; // what the axes are relative to (global,b1,b2) dVector3 m_axis[dSA__MAX]; // three axes // these vectors are used for calculating Euler angles dVector3 m_references[dJCB__MAX]; // original axis[2], relative to body 1; original axis[0], relative to body 2 dReal m_angle[dSA__MAX]; // user-supplied angles for axes dxJointLimitMotor m_limot[dJBR__MAX]; // limit+motor info for axes }; #endif ode-0.16/ode/src/joints/hinge.h0000664000175200017520000000472313403272463013257 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_JOINT_HINGE_H_ #define _ODE_JOINT_HINGE_H_ #include "joint.h" // hinge struct dxJointHinge : public dxJoint { dVector3 anchor1; // anchor w.r.t first body dVector3 anchor2; // anchor w.r.t second body dVector3 axis1; // axis w.r.t first body dVector3 axis2; // axis w.r.t second body dQuaternion qrel; // initial relative rotation body1 -> body2 dxJointLimitMotor limot; // limit and motor information dxJointHinge( dxWorld *w ); virtual void getSureMaxInfo( SureMaxInfo* info ); virtual void getInfo1( Info1* info ); virtual void getInfo2( dReal worldFPS, dReal worldERP, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dReal *pairLoHi, int *findex ); virtual dJointType type() const; virtual sizeint size() const; virtual void setRelativeValues(); void computeInitialRelativeRotation(); }; #endif ode-0.16/ode/src/joints/transmission.h0000664000175200017520000000453213403272463014714 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_JOINT_TRANSMISSION_ #define _ODE_JOINT_TRANSMISSION_ #include "joint.h" struct dxJointTransmission : public dxJoint { int mode, update; dVector3 contacts[2], axes[2], anchors[2]; dMatrix3 reference[2]; dReal phase[2], radii[2], backlash; dReal ratio; // transmission ratio dReal erp; // error reduction dReal cfm; // constraint force mix in dxJointTransmission(dxWorld *w); virtual void getSureMaxInfo( SureMaxInfo* info ); virtual void getInfo1( Info1* info ); virtual void getInfo2( dReal worldFPS, dReal worldERP, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dReal *pairLoHi, int *findex ); virtual dJointType type() const; virtual sizeint size() const; }; #endif ode-0.16/ode/src/joints/amotor.cpp0000664000175200017520000005475013403272463014026 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include "config.h" #include "common.h" #include "amotor.h" #include "joint_internal.h" #include "odeou.h" /*extern */ void dJointSetAMotorNumAxes(dJointID j, int num) { dxJointAMotor* joint = (dxJointAMotor*)j; dAASSERT(joint != NULL); dAASSERT(dIN_RANGE(num, dSA__MIN, dSA__MAX + 1)); checktype(joint, AMotor); num = dCLAMP(num, dSA__MIN, dSA__MAX); joint->setNumAxes(num); } /*extern */ void dJointSetAMotorAxis(dJointID j, int anum, int rel/*=dJointBodyRelativity*/, dReal x, dReal y, dReal z) { dxJointAMotor* joint = (dxJointAMotor*)j; dAASSERT(joint != NULL); dAASSERT(dIN_RANGE(anum, dSA__MIN, dSA__MAX)); dAASSERT(dIN_RANGE(rel, dJBR__MIN, dJBR__MAX)); checktype(joint, AMotor); anum = dCLAMP(anum, dSA__MIN, dSA__MAX - 1); joint->setAxisValue(anum, (dJointBodyRelativity)rel, x, y, z); } /*extern */ void dJointSetAMotorAngle(dJointID j, int anum, dReal angle) { dxJointAMotor* joint = (dxJointAMotor*)j; dAASSERT(joint != NULL); dAASSERT(dIN_RANGE(anum, dSA__MIN, dSA__MAX)); checktype(joint, AMotor); anum = dCLAMP(anum, dSA__MIN, dSA__MAX - 1); joint->setAngleValue(anum, angle); } /*extern */ void dJointSetAMotorParam(dJointID j, int parameter, dReal value) { dxJointAMotor* joint = (dxJointAMotor*)j; dAASSERT(joint != NULL); checktype(joint, AMotor); int anum = parameter >> 8; dAASSERT(dIN_RANGE(anum, dSA__MIN, dSA__MAX)); anum = dCLAMP(anum, dSA__MIN, dSA__MAX - 1); int limotParam = parameter & 0xff; joint->setLimotParameter(anum, limotParam, value); } /*extern */ void dJointSetAMotorMode(dJointID j, int mode) { dxJointAMotor* joint = (dxJointAMotor*)j; dAASSERT(joint != NULL); checktype(joint, AMotor); joint->setOperationMode(mode); } /*extern */ int dJointGetAMotorNumAxes(dJointID j) { dxJointAMotor* joint = (dxJointAMotor*)j; dAASSERT(joint != NULL); checktype(joint, AMotor); return joint->getNumAxes(); } /*extern */ void dJointGetAMotorAxis(dJointID j, int anum, dVector3 result) { dxJointAMotor* joint = (dxJointAMotor*)j; dAASSERT(joint != NULL); dAASSERT(dIN_RANGE(anum, dSA__MIN, dSA__MAX)); checktype(joint, AMotor); anum = dCLAMP(anum, dSA__MIN, dSA__MAX - 1); joint->getAxisValue(result, anum); } /*extern */ int dJointGetAMotorAxisRel(dJointID j, int anum) { dxJointAMotor* joint = (dxJointAMotor*)j; dAASSERT(joint != NULL); dAASSERT(dIN_RANGE(anum, dSA__MIN, dSA__MAX)); checktype(joint, AMotor); anum = dCLAMP(anum, dSA__MIN, dSA__MAX - 1); int result = joint->getAxisBodyRelativity(anum); return result; } /*extern */ dReal dJointGetAMotorAngle(dJointID j, int anum) { dxJointAMotor* joint = (dxJointAMotor*)j; dAASSERT(joint != NULL); dAASSERT(dIN_RANGE(anum, dSA__MIN, dSA__MAX)); checktype(joint, AMotor); anum = dCLAMP(anum, dSA__MIN, dSA__MAX - 1); dReal result = joint->getAngleValue(anum); return result; } /*extern */ dReal dJointGetAMotorAngleRate(dJointID j, int anum) { dxJointAMotor* joint = (dxJointAMotor*)j; dAASSERT(joint != NULL); dAASSERT(dIN_RANGE(anum, dSA__MIN, dSA__MAX)); checktype(joint, AMotor); anum = dCLAMP(anum, dSA__MIN, dSA__MAX - 1); dReal result = joint->calculateAngleRate(anum); return result; } /*extern */ dReal dJointGetAMotorParam(dJointID j, int parameter) { dxJointAMotor* joint = (dxJointAMotor*)j; dAASSERT(joint != NULL); checktype(joint, AMotor); int anum = parameter >> 8; dAASSERT(dIN_RANGE(anum, dSA__MIN, dSA__MAX)); anum = dCLAMP(anum, dSA__MIN, dSA__MAX - 1); int limotParam = parameter & 0xff; dReal result = joint->getLimotParameter(anum, limotParam); return result; } /*extern */ int dJointGetAMotorMode(dJointID j) { dxJointAMotor* joint = (dxJointAMotor*)j; dAASSERT(joint != NULL); checktype(joint, AMotor); int result = joint->getOperationMode(); return result; } /*extern */ void dJointAddAMotorTorques(dJointID j, dReal torque1, dReal torque2, dReal torque3) { dxJointAMotor* joint = (dxJointAMotor*)j; dAASSERT(joint != NULL); checktype(joint, AMotor); joint->addTorques(torque1, torque2, torque3); } //**************************************************************************** BEGIN_NAMESPACE_OU(); template<> const dJointBodyRelativity CEnumUnsortedElementArray::m_aetElementArray[] = { dJBR_BODY1, // dSA_X, dJBR_GLOBAL, // dSA_Y, dJBR_BODY2, // dSA_Z, }; END_NAMESPACE_OU(); static const CEnumUnsortedElementArray g_abrEulerAxisAllowedBodyRelativities; static inline dSpaceAxis EncodeJointConnectedBodyEulerAxis(dJointConnectedBody cbBodyIndex) { dSASSERT(dJCB__MAX == 2); return cbBodyIndex == dJCB_FIRST_BODY ? dSA_X : dSA_Z; } static inline dSpaceAxis EncodeOtherEulerAxis(dSpaceAxis saOneAxis) { dIASSERT(saOneAxis == EncodeJointConnectedBodyEulerAxis(dJCB_FIRST_BODY) || saOneAxis == EncodeJointConnectedBodyEulerAxis(dJCB_SECOND_BODY)); dSASSERT(dJCB__MAX == 2); return (dSpaceAxis)(dSA_X + dSA_Z - saOneAxis); } //**************************************************************************** // angular motor dxJointAMotor::dxJointAMotor(dxWorld *w) : dxJointAMotor_Parent(w), m_mode(dAMotorUser), m_num(0) { std::fill(m_rel, m_rel + dARRAY_SIZE(m_rel), dJBR__DEFAULT); { for (int i = 0; i != dARRAY_SIZE(m_axis); ++i) { dZeroVector3(m_axis[i]); } } { for (int i = 0; i != dARRAY_SIZE(m_references); ++i) { dZeroVector3(m_references[i]); } } std::fill(m_angle, m_angle + dARRAY_SIZE(m_angle), REAL(0.0)); { for (int i = 0; i != dARRAY_SIZE(m_limot); ++i) { m_limot[i].init(w); } } } /*virtual */ dxJointAMotor::~dxJointAMotor() { // The virtual destructor } /*virtual */ void dxJointAMotor::getSureMaxInfo(SureMaxInfo* info) { info->max_m = m_num; } /*virtual */ void dxJointAMotor::getInfo1(dxJoint::Info1 *info) { info->m = 0; info->nub = 0; // compute the axes and angles, if in Euler mode if (m_mode == dAMotorEuler) { dVector3 ax[dSA__MAX]; computeGlobalAxes(ax); computeEulerAngles(ax); } // see if we're powered or at a joint limit for each axis const unsigned num = m_num; for (unsigned i = 0; i != num; ++i) { if (m_limot[i].testRotationalLimit(m_angle[i]) || m_limot[i].fmax > 0) { info->m++; } } } /*virtual */ void dxJointAMotor::getInfo2(dReal worldFPS, dReal /*worldERP*/, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dReal *pairLoHi, int *findex) { // compute the axes (if not global) dVector3 ax[dSA__MAX]; computeGlobalAxes(ax); // in Euler angle mode we do not actually constrain the angular velocity // along the axes axis[0] and axis[2] (although we do use axis[1]) : // // to get constrain w2-w1 along ...not // ------ --------------------- ------ // d(angle[0])/dt = 0 ax[1] x ax[2] ax[0] // d(angle[1])/dt = 0 ax[1] // d(angle[2])/dt = 0 ax[0] x ax[1] ax[2] // // constraining w2-w1 along an axis 'a' means that a'*(w2-w1)=0. // to prove the result for angle[0], write the expression for angle[0] from // GetInfo1 then take the derivative. to prove this for angle[2] it is // easier to take the Euler rate expression for d(angle[2])/dt with respect // to the components of w and set that to 0. dVector3 *axptr[dSA__MAX]; for (int j = dSA__MIN; j != dSA__MAX; ++j) { axptr[j] = &ax[j]; } dVector3 ax0_cross_ax1; dVector3 ax1_cross_ax2; if (m_mode == dAMotorEuler) { dCalcVectorCross3(ax0_cross_ax1, ax[dSA_X], ax[dSA_Y]); axptr[dSA_Z] = &ax0_cross_ax1; dCalcVectorCross3(ax1_cross_ax2, ax[dSA_Y], ax[dSA_Z]); axptr[dSA_X] = &ax1_cross_ax2; } sizeint rowTotalSkip = 0, pairTotalSkip = 0; const unsigned num = m_num; for (unsigned i = 0; i != num; ++i) { if (m_limot[i].addLimot(this, worldFPS, J1 + rowTotalSkip, J2 + rowTotalSkip, pairRhsCfm + pairTotalSkip, pairLoHi + pairTotalSkip, *(axptr[i]), 1)) { rowTotalSkip += rowskip; pairTotalSkip += pairskip; } } } /*virtual */ dJointType dxJointAMotor::type() const { return dJointTypeAMotor; } /*virtual */ sizeint dxJointAMotor::size() const { return sizeof(*this); } void dxJointAMotor::setOperationMode(int mode) { m_mode = mode; if (mode == dAMotorEuler) { m_num = dSA__MAX; setEulerReferenceVectors(); } } void dxJointAMotor::setNumAxes(unsigned num) { if (m_mode == dAMotorEuler) { m_num = dSA__MAX; } else { m_num = num; } } dJointBodyRelativity dxJointAMotor::getAxisBodyRelativity(unsigned anum) const { dAASSERT(dIN_RANGE(anum, dSA__MIN, dSA__MAX)); dJointBodyRelativity rel = m_rel[anum]; if (dJBREncodeBodyRelativityStatus(rel) && GetIsJointReverse()) { rel = dJBRSwapBodyRelativity(rel); // turns 1 into 2, 2 into 1 } return rel; } void dxJointAMotor::setAxisValue(unsigned anum, dJointBodyRelativity rel, dReal x, dReal y, dReal z) { dAASSERT(dIN_RANGE(anum, dSA__MIN, dSA__MAX)); dAASSERT(m_mode != dAMotorEuler || !dJBREncodeBodyRelativityStatus(rel) || rel == g_abrEulerAxisAllowedBodyRelativities.Encode((dSpaceAxis)anum)); // x,y,z is always in global coordinates regardless of rel, so we may have // to convert it to be relative to a body dVector3 r; dAssignVector3(r, x, y, z); // adjust rel to match the internal body order if (dJBREncodeBodyRelativityStatus(rel) && GetIsJointReverse()) { rel = dJBRSwapBodyRelativity(rel); // turns 1 into 2, 2, into 1 } m_rel[anum] = rel; bool assigned = false; if (dJBREncodeBodyRelativityStatus(rel)) { if (rel == dJBR_BODY1) { dMultiply1_331(m_axis[anum], this->node[0].body->posr.R, r); assigned = true; } // rel == 2 else if (this->node[1].body != NULL) { dIASSERT(rel == dJBR_BODY2); dMultiply1_331(m_axis[anum], this->node[1].body->posr.R, r); assigned = true; } } if (!assigned) { dCopyVector3(m_axis[anum], r); } dNormalize3(m_axis[anum]); if (m_mode == dAMotorEuler) { setEulerReferenceVectors(); } } void dxJointAMotor::getAxisValue(dVector3 result, unsigned anum) const { dAASSERT(dIN_RANGE(anum, dSA__MIN, dSA__MAX)); switch (m_mode) { case dAMotorUser: { doGetUserAxis(result, anum); break; } case dAMotorEuler: { doGetEulerAxis(result, anum); break; } default: { dIASSERT(false); break; } } } void dxJointAMotor::doGetUserAxis(dVector3 result, unsigned anum) const { bool retrieved = false; if (dJBREncodeBodyRelativityStatus(m_rel[anum])) { if (m_rel[anum] == dJBR_BODY1) { dMultiply0_331(result, this->node[0].body->posr.R, m_axis[anum]); retrieved = true; } else if (this->node[1].body != NULL) { dMultiply0_331(result, this->node[1].body->posr.R, m_axis[anum]); retrieved = true; } } if (!retrieved) { dCopyVector3(result, m_axis[anum]); } } void dxJointAMotor::doGetEulerAxis(dVector3 result, unsigned anum) const { // If we're in Euler mode, joint->axis[1] doesn't // have anything sensible in it. So don't just return // that, find the actual effective axis. // Likewise, the actual axis of rotation for the // the other axes is different from what's stored. dVector3 axes[dSA__MAX]; computeGlobalAxes(axes); if (anum == dSA_Y) { dCopyVector3(result, axes[dSA_Y]); } else if (anum < dSA_Y) // Comparing against the same constant lets compiler reuse EFLAGS register for another conditional jump { dSASSERT(dSA_X < dSA_Y); // Otherwise the condition above is incorrect dIASSERT(anum == dSA_X); // This won't be unit length in general, // but it's what's used in getInfo2 // This may be why things freak out as // the body-relative axes get close to each other. dCalcVectorCross3(result, axes[dSA_Y], axes[dSA_Z]); } else { dSASSERT(dSA_Z > dSA_Y); // Otherwise the condition above is incorrect dIASSERT(anum == dSA_Z); // Same problem as above. dCalcVectorCross3(result, axes[dSA_X], axes[dSA_Y]); } } void dxJointAMotor::setAngleValue(unsigned anum, dReal angle) { dAASSERT(dIN_RANGE(anum, dSA__MIN, dSA__MAX)); dAASSERT(m_mode == dAMotorUser); // This only works for the dAMotorUser if (m_mode == dAMotorUser) { m_angle[anum] = angle; } } dReal dxJointAMotor::calculateAngleRate(unsigned anum) const { dAASSERT(dIN_RANGE(anum, dSA__MIN, dSA__MAX)); dAASSERT(this->node[0].body != NULL); // Don't call for angle rate before the joint is set up dVector3 axis; getAxisValue(axis, anum); // NOTE! // For reverse joints, the rate is negated at the function exit to create swapped bodies effect dReal rate = dDOT(axis, this->node[0].body->avel); if (this->node[1].body != NULL) { rate -= dDOT(axis, this->node[1].body->avel); } // Negating the rate for reverse joints creates an effect of body swapping dReal result = !GetIsJointReverse() ? rate : -rate; return result; } void dxJointAMotor::addTorques(dReal torque1, dReal torque2, dReal torque3) { unsigned num = getNumAxes(); dAASSERT(dIN_RANGE(num, dSA__MIN, dSA__MAX + 1)); dVector3 sum; dVector3 torqueVector; dVector3 axes[dSA__MAX]; if (num != dSA__MIN) { computeGlobalAxes(axes); if (!GetIsJointReverse()) { dAssignVector3(torqueVector, torque1, torque2, torque3); } else { // Negating torques creates an effect of swapped bodies later dAssignVector3(torqueVector, -torque1, -torque2, -torque3); } } switch (num) { case dSA_Z + 1: { dAddThreeScaledVectors3(sum, axes[dSA_Z], axes[dSA_Y], axes[dSA_X], torqueVector[dSA_Z], torqueVector[dSA_Y], torqueVector[dSA_X]); break; } case dSA_Y + 1: { dAddScaledVectors3(sum, axes[dSA_Y], axes[dSA_X], torqueVector[dSA_Y], torqueVector[dSA_X]); break; } case dSA_X + 1: { dCopyScaledVector3(sum, axes[dSA_X], torqueVector[dSA_X]); break; } default: { dSASSERT(dSA_Z > dSA_Y); // Otherwise the addends order needs to be switched dSASSERT(dSA_Y > dSA_X); // Do nothing break; } } if (num != dSA__MIN) { dAASSERT(this->node[0].body != NULL); // Don't add torques unless you set the joint up first! // NOTE! // For reverse joints, the torqueVector negated at function entry produces the effect of swapped bodies dBodyAddTorque(this->node[0].body, sum[dV3E_X], sum[dV3E_Y], sum[dV3E_Z]); if (this->node[1].body != NULL) { dBodyAddTorque(this->node[1].body, -sum[dV3E_X], -sum[dV3E_Y], -sum[dV3E_Z]); } } } // compute the 3 axes in global coordinates void dxJointAMotor::computeGlobalAxes(dVector3 ax[dSA__MAX]) const { switch (m_mode) { case dAMotorUser: { doComputeGlobalUserAxes(ax); break; } case dAMotorEuler: { doComputeGlobalEulerAxes(ax); break; } default: { dIASSERT(false); break; } } } void dxJointAMotor::doComputeGlobalUserAxes(dVector3 ax[dSA__MAX]) const { unsigned num = m_num; for (unsigned i = 0; i != num; ++i) { bool assigned = false; if (m_rel[i] == dJBR_BODY1) { // relative to b1 dMultiply0_331(ax[i], this->node[0].body->posr.R, m_axis[i]); assigned = true; } else if (m_rel[i] == dJBR_BODY2) { // relative to b2 if (this->node[1].body != NULL) { dMultiply0_331(ax[i], this->node[1].body->posr.R, m_axis[i]); assigned = true; } } if (!assigned) { // global - just copy it dCopyVector3(ax[i], m_axis[i]); } } } void dxJointAMotor::doComputeGlobalEulerAxes(dVector3 ax[dSA__MAX]) const { // special handling for Euler mode dSpaceAxis firstBodyAxis = BuildFirstBodyEulerAxis(); dMultiply0_331(ax[firstBodyAxis], this->node[0].body->posr.R, m_axis[firstBodyAxis]); dSpaceAxis secondBodyAxis = EncodeOtherEulerAxis(firstBodyAxis); if (this->node[1].body != NULL) { dMultiply0_331(ax[secondBodyAxis], this->node[1].body->posr.R, m_axis[secondBodyAxis]); } else { dCopyVector3(ax[secondBodyAxis], m_axis[secondBodyAxis]); } dCalcVectorCross3(ax[dSA_Y], ax[dSA_Z], ax[dSA_X]); dNormalize3(ax[dSA_Y]); } void dxJointAMotor::computeEulerAngles(dVector3 ax[dSA__MAX]) { // assumptions: // global axes already calculated --> ax // axis[0] is relative to body 1 --> global ax[0] // axis[2] is relative to body 2 --> global ax[2] // ax[1] = ax[2] x ax[0] // original ax[0] and ax[2] are perpendicular // reference1 is perpendicular to ax[0] (in body 1 frame) // reference2 is perpendicular to ax[2] (in body 2 frame) // all ax[] and reference vectors are unit length // calculate references in global frame dVector3 refs[dJCB__MAX]; dMultiply0_331(refs[dJCB_FIRST_BODY], this->node[0].body->posr.R, m_references[dJCB_FIRST_BODY]); if (this->node[1].body != NULL) { dMultiply0_331(refs[dJCB_SECOND_BODY], this->node[1].body->posr.R, m_references[dJCB_SECOND_BODY]); } else { dCopyVector3(refs[dJCB_SECOND_BODY], m_references[dJCB_SECOND_BODY]); } // get q perpendicular to both ax[0] and ref1, get first euler angle dVector3 q; dJointConnectedBody firstAxisBody = BuildFirstEulerAxisBody(); dCalcVectorCross3(q, ax[dSA_X], refs[firstAxisBody]); m_angle[dSA_X] = -dAtan2(dCalcVectorDot3(ax[dSA_Z], q), dCalcVectorDot3(ax[dSA_Z], refs[firstAxisBody])); // get q perpendicular to both ax[0] and ax[1], get second euler angle dCalcVectorCross3(q, ax[dSA_X], ax[dSA_Y]); m_angle[dSA_Y] = -dAtan2(dCalcVectorDot3(ax[dSA_Z], ax[dSA_X]), dCalcVectorDot3(ax[dSA_Z], q)); dJointConnectedBody secondAxisBody = EncodeJointOtherConnectedBody(firstAxisBody); // get q perpendicular to both ax[1] and ax[2], get third euler angle dCalcVectorCross3(q, ax[dSA_Y], ax[dSA_Z]); m_angle[dSA_Z] = -dAtan2(dCalcVectorDot3(refs[secondAxisBody], ax[dSA_Y]), dCalcVectorDot3(refs[secondAxisBody], q)); } // set the reference vectors as follows: // * reference1 = current axis[2] relative to body 1 // * reference2 = current axis[0] relative to body 2 // this assumes that: // * axis[0] is relative to body 1 // * axis[2] is relative to body 2 void dxJointAMotor::setEulerReferenceVectors() { if (/*this->node[0].body != NULL && */this->node[1].body != NULL) { dIASSERT(this->node[0].body != NULL); dVector3 r; // axis[2] and axis[0] in global coordinates dSpaceAxis firstBodyAxis = BuildFirstBodyEulerAxis(); dMultiply0_331(r, this->node[0].body->posr.R, m_axis[firstBodyAxis]); dMultiply1_331(m_references[dJCB_SECOND_BODY], this->node[1].body->posr.R, r); dSpaceAxis secondBodyAxis = EncodeOtherEulerAxis(firstBodyAxis); dMultiply0_331(r, this->node[1].body->posr.R, m_axis[secondBodyAxis]); dMultiply1_331(m_references[dJCB_FIRST_BODY], this->node[0].body->posr.R, r); } else { // We want to handle angular motors attached to passive geoms // Replace missing node.R with identity if (this->node[0].body != NULL) { dSpaceAxis firstBodyAxis = BuildFirstBodyEulerAxis(); dMultiply0_331(m_references[dJCB_SECOND_BODY], this->node[0].body->posr.R, m_axis[firstBodyAxis]); dSpaceAxis secondBodyAxis = EncodeOtherEulerAxis(firstBodyAxis); dMultiply1_331(m_references[dJCB_FIRST_BODY], this->node[0].body->posr.R, m_axis[secondBodyAxis]); } } } /*inline */ dSpaceAxis dxJointAMotor::BuildFirstBodyEulerAxis() const { return EncodeJointConnectedBodyEulerAxis(BuildFirstEulerAxisBody()); } /*inline */ dJointConnectedBody dxJointAMotor::BuildFirstEulerAxisBody() const { return !GetIsJointReverse() ? dJCB_FIRST_BODY : dJCB_SECOND_BODY; } ode-0.16/ode/src/joints/transmission.cpp0000664000175200017520000005437013403272463015254 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include "config.h" #include "transmission.h" #include "joint_internal.h" namespace { static inline dReal clamp(dReal x, dReal minX, dReal maxX) { return x < minX ? minX : (x > maxX ? maxX : x); } } /* * Transmission joint */ dxJointTransmission::dxJointTransmission(dxWorld* w) : dxJoint(w) { int i; flags |= dJOINT_TWOBODIES; mode = dTransmissionParallelAxes; cfm = world->global_cfm; erp = world->global_erp; for (i = 0 ; i < 2 ; i += 1) { dSetZero( anchors[i], 4 ); dSetZero( axes[i], 4 ); axes[i][0] = 1; radii[i] = 0; } backlash = 0; ratio = 1; update = 1; } void dxJointTransmission::getSureMaxInfo( SureMaxInfo* info ) { info->max_m = 1; } void dxJointTransmission::getInfo1( dxJoint::Info1* info ) { // If there's backlash in the gears then constraint must be // unilateral, that is the driving gear can only push the driven // gear in one direction. In order to push it in the other it // first needs to traverse the backlash gap. info->m = 1; info->nub = backlash > 0 ? 0 : 1; } void dxJointTransmission::getInfo2( dReal worldFPS, dReal /*worldERP*/, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dReal *pairLoHi, int *findex ) { dVector3 a[2], n[2], l[2], r[2], c[2], s, t, O, d, z, u, v; dReal theta, delta, nn, na_0, na_1, cosphi, sinphi, m; const dReal *p[2], *omega[2]; int i; // Transform all needed quantities to the global frame. for (i = 0 ; i < 2 ; i += 1) { dBodyGetRelPointPos(node[i].body, anchors[i][0], anchors[i][1], anchors[i][2], a[i]); dBodyVectorToWorld(node[i].body, axes[i][0], axes[i][1], axes[i][2], n[i]); p[i] = dBodyGetPosition(node[i].body); omega[i] = dBodyGetAngularVel(node[i].body); } if (update) { // Make sure both gear reference frames end up with the same // handedness. if (dCalcVectorDot3(n[0], n[1]) < 0) { dNegateVector3(axes[0]); dNegateVector3(n[0]); } } // Calculate the mesh geometry based on the current mode. switch (mode) { case dTransmissionParallelAxes: // Simply calculate the contact point as the point on the // baseline that will yield the correct ratio. dIASSERT (ratio > 0); dSubtractVectors3(d, a[1], a[0]); dAddVectorScaledVector3(c[0], a[0], d, ratio / (1 + ratio)); dCopyVector3(c[1], c[0]); dNormalize3(d); for (i = 0 ; i < 2 ; i += 1) { dCalcVectorCross3(l[i], d, n[i]); } break; case dTransmissionIntersectingAxes: // Calculate the line of intersection between the planes of the // gears. dCalcVectorCross3(l[0], n[0], n[1]); dCopyVector3(l[1], l[0]); nn = dCalcVectorDot3(n[0], n[1]); dIASSERT(fabs(nn) != 1); na_0 = dCalcVectorDot3(n[0], a[0]); na_1 = dCalcVectorDot3(n[1], a[1]); dAddScaledVectors3(O, n[0], n[1], (na_0 - na_1 * nn) / (1 - nn * nn), (na_1 - na_0 * nn) / (1 - nn * nn)); // Find the contact point as: // // c = ((r_a - O) . l) l + O // // where r_a the anchor point of either gear and l, O the tangent // line direction and origin. for (i = 0 ; i < 2 ; i += 1) { dSubtractVectors3(d, a[i], O); m = dCalcVectorDot3(d, l[i]); dAddVectorScaledVector3(c[i], O, l[i], m); } break; case dTransmissionChainDrive: dSubtractVectors3(d, a[0], a[1]); m = dCalcVectorLength3(d); dIASSERT(m > 0); // Caclulate the angle of the contact point relative to the // baseline. cosphi = clamp((radii[1] - radii[0]) / m, REAL(-1.0), REAL(1.0)); // Force into range to fix possible computation errors sinphi = dSqrt (REAL(1.0) - cosphi * cosphi); dNormalize3(d); for (i = 0 ; i < 2 ; i += 1) { // Calculate the contact radius in the local reference // frame of the chain. This has axis x pointing along the // baseline, axis y pointing along the sprocket axis and // the remaining axis normal to both. u[0] = radii[i] * cosphi; u[1] = 0; u[2] = radii[i] * sinphi; // Transform the contact radius into the global frame. dCalcVectorCross3(z, d, n[i]); v[0] = dCalcVectorDot3(d, u); v[1] = dCalcVectorDot3(n[i], u); v[2] = dCalcVectorDot3(z, u); // Finally calculate contact points and l. dAddVectors3(c[i], a[i], v); dCalcVectorCross3(l[i], v, n[i]); dNormalize3(l[i]); // printf ("%d: %f, %f, %f\n", // i, l[i][0], l[i][1], l[i][2]); } break; } if (update) { // We need to calculate an initial reference frame for each // wheel which we can measure the current phase against. This // frame will have the initial contact radius as the x axis, // the wheel axis as the z axis and their cross product as the // y axis. for (i = 0 ; i < 2 ; i += 1) { dSubtractVectors3 (r[i], c[i], a[i]); radii[i] = dCalcVectorLength3(r[i]); dIASSERT(radii[i] > 0); dBodyVectorFromWorld(node[i].body, r[i][0], r[i][1], r[i][2], reference[i]); dNormalize3(reference[i]); dCopyVector3(reference[i] + 8, axes[i]); dCalcVectorCross3(reference[i] + 4, reference[i] + 8, reference[i]); // printf ("%f\n", dDOT(r[i], n[i])); // printf ("(%f, %f, %f,\n %f, %f, %f,\n %f, %f, %f)\n", // reference[i][0],reference[i][1],reference[i][2], // reference[i][4],reference[i][5],reference[i][6], // reference[i][8],reference[i][9],reference[i][10]); phase[i] = 0; } ratio = radii[0] / radii[1]; update = 0; } for (i = 0 ; i < 2 ; i += 1) { dReal phase_hat; dSubtractVectors3 (r[i], c[i], a[i]); // Transform the (global) contact radius into the gear's // reference frame. dBodyVectorFromWorld (node[i].body, r[i][0], r[i][1], r[i][2], s); dMultiply0_331(t, reference[i], s); // Now simply calculate its angle on the plane relative to the // x-axis which is the initial contact radius. This will be // an angle between -pi and pi that is coterminal with the // actual phase of the wheel. To find the real phase we // estimate it by adding omega * dt to the old phase and then // find the closest angle to that, that is coterminal to // theta. theta = atan2(t[1], t[0]); phase_hat = phase[i] + dCalcVectorDot3(omega[i], n[i]) / worldFPS; if (phase_hat > M_PI_2) { if (theta < 0) { theta += (dReal)(2 * M_PI); } theta += (dReal)(floor(phase_hat / (2 * M_PI)) * (2 * M_PI)); } else if (phase_hat < -M_PI_2) { if (theta > 0) { theta -= (dReal)(2 * M_PI); } theta += (dReal)(ceil(phase_hat / (2 * M_PI)) * (2 * M_PI)); } if (phase_hat - theta > M_PI) { phase[i] = theta + (dReal)(2 * M_PI); } else if (phase_hat - theta < -M_PI) { phase[i] = theta - (dReal)(2 * M_PI); } else { phase[i] = theta; } dIASSERT(fabs(phase_hat - phase[i]) < M_PI); } // Calculate the phase error. Depending on the mode the condition // is that the distances traveled by each contact point must be // either equal (chain and sprockets) or opposite (gears). if (mode == dTransmissionChainDrive) { delta = (dCalcVectorLength3(r[0]) * phase[0] - dCalcVectorLength3(r[1]) * phase[1]); } else { delta = (dCalcVectorLength3(r[0]) * phase[0] + dCalcVectorLength3(r[1]) * phase[1]); } // When in chain mode a torque reversal, signified by the change // in sign of the wheel phase difference, has the added effect of // switching the active chain branch. We must therefore reflect // the contact points and tangents across the baseline. if (mode == dTransmissionChainDrive && delta < 0) { dVector3 d; dSubtractVectors3(d, a[0], a[1]); for (i = 0 ; i < 2 ; i += 1) { dVector3 nn; dReal a; dCalcVectorCross3(nn, n[i], d); a = dCalcVectorDot3(nn, nn); dIASSERT(a > 0); dAddScaledVectors3(c[i], c[i], nn, 1, -2 * dCalcVectorDot3(c[i], nn) / a); dAddScaledVectors3(l[i], l[i], nn, -1, 2 * dCalcVectorDot3(l[i], nn) / a); } } // Do not add the constraint if there's backlash and we're in the // backlash gap. if (backlash == 0 || fabs(delta) > backlash) { // The constraint is satisfied if the absolute velocity of the // contact point projected onto the tangent of the wheels is equal // for both gears. This velocity can be calculated as: // // u = v + omega x r_c // // The constraint therefore becomes: // (v_1 + omega_1 x r_c1) . l = (v_2 + omega_2 x r_c2) . l <=> // (v_1 . l + (r_c1 x l) . omega_1 = v_2 . l + (r_c2 x l) . omega_2 for (i = 0 ; i < 2 ; i += 1) { dSubtractVectors3 (r[i], c[i], p[i]); } dCopyVector3(J1 + GI2__JL_MIN, l[0]); dCalcVectorCross3(J1 + GI2__JA_MIN, r[0], l[0]); dCopyNegatedVector3(J2 + GI2__JL_MIN, l[1]); dCalcVectorCross3(J2 + GI2__JA_MIN, l[1], r[1]); if (delta > 0) { if (backlash > 0) { pairLoHi[GI2_LO] = -dInfinity; pairLoHi[GI2_HI] = 0; } pairRhsCfm[GI2_RHS] = -worldFPS * erp * (delta - backlash); } else { if (backlash > 0) { pairLoHi[GI2_LO] = 0; pairLoHi[GI2_HI] = dInfinity; } pairRhsCfm[GI2_RHS] = -worldFPS * erp * (delta + backlash); } } pairRhsCfm[GI2_CFM] = cfm; // printf ("%f, %f, %f, %f, %f\n", delta, phase[0], phase[1], -phase[1] / phase[0], ratio); // Cache the contact point (in world coordinates) to avoid // recalculation if requested by the user. dCopyVector3(contacts[0], c[0]); dCopyVector3(contacts[1], c[1]); } void dJointSetTransmissionAxis( dJointID j, dReal x, dReal y, dReal z ) { dxJointTransmission* joint = static_cast(j); int i; dUASSERT( joint, "bad joint argument" ); dUASSERT(joint->mode == dTransmissionParallelAxes || joint->mode == dTransmissionChainDrive , "axes must be set individualy in current mode" ); for (i = 0 ; i < 2 ; i += 1) { if (joint->node[i].body) { dBodyVectorFromWorld(joint->node[i].body, x, y, z, joint->axes[i]); dNormalize3(joint->axes[i]); } } joint->update = 1; } void dJointSetTransmissionAxis1( dJointID j, dReal x, dReal y, dReal z ) { dxJointTransmission* joint = static_cast(j); dUASSERT( joint, "bad joint argument" ); dUASSERT(joint->mode == dTransmissionIntersectingAxes, "can't set individual axes in current mode" ); if (joint->node[0].body) { dBodyVectorFromWorld(joint->node[0].body, x, y, z, joint->axes[0]); dNormalize3(joint->axes[0]); } joint->update = 1; } void dJointSetTransmissionAxis2( dJointID j, dReal x, dReal y, dReal z ) { dxJointTransmission* joint = static_cast(j); dUASSERT( joint, "bad joint argument" ); dUASSERT(joint->mode == dTransmissionIntersectingAxes, "can't set individual axes in current mode" ); if (joint->node[1].body) { dBodyVectorFromWorld(joint->node[1].body, x, y, z, joint->axes[1]); dNormalize3(joint->axes[1]); } joint->update = 1; } void dJointSetTransmissionAnchor1( dJointID j, dReal x, dReal y, dReal z ) { dxJointTransmission* joint = static_cast(j); dUASSERT( joint, "bad joint argument" ); if (joint->node[0].body) { dBodyGetPosRelPoint(joint->node[0].body, x, y, z, joint->anchors[0]); } joint->update = 1; } void dJointSetTransmissionAnchor2( dJointID j, dReal x, dReal y, dReal z ) { dxJointTransmission* joint = static_cast(j); dUASSERT( joint, "bad joint argument" ); if (joint->node[1].body) { dBodyGetPosRelPoint(joint->node[1].body, x, y, z, joint->anchors[1]); } joint->update = 1; } void dJointGetTransmissionContactPoint1( dJointID j, dVector3 result ) { dxJointTransmission* joint = static_cast(j); dUASSERT( joint, "bad joint argument" ); dUASSERT( result, "bad result argument" ); dCopyVector3(result, joint->contacts[0]); } void dJointGetTransmissionContactPoint2( dJointID j, dVector3 result ) { dxJointTransmission* joint = static_cast(j); dUASSERT( joint, "bad joint argument" ); dUASSERT( result, "bad result argument" ); dCopyVector3(result, joint->contacts[1]); } void dJointGetTransmissionAxis( dJointID j, dVector3 result ) { dxJointTransmission* joint = static_cast(j); dUASSERT( joint, "bad joint argument" ); dUASSERT( result, "bad result argument" ); dUASSERT(joint->mode == dTransmissionParallelAxes, "axes must be queried individualy in current mode" ); if (joint->node[0].body) { dBodyVectorToWorld(joint->node[0].body, joint->axes[0][0], joint->axes[0][1], joint->axes[0][2], result); } } void dJointGetTransmissionAxis1( dJointID j, dVector3 result ) { dxJointTransmission* joint = static_cast(j); dUASSERT( joint, "bad joint argument" ); dUASSERT( result, "bad result argument" ); if (joint->node[0].body) { dBodyVectorToWorld(joint->node[0].body, joint->axes[0][0], joint->axes[0][1], joint->axes[0][2], result); } } void dJointGetTransmissionAxis2( dJointID j, dVector3 result ) { dxJointTransmission* joint = static_cast(j); dUASSERT( joint, "bad joint argument" ); dUASSERT( result, "bad result argument" ); if (joint->node[1].body) { dBodyVectorToWorld(joint->node[1].body, joint->axes[1][0], joint->axes[1][1], joint->axes[1][2], result); } } void dJointGetTransmissionAnchor1( dJointID j, dVector3 result ) { dxJointTransmission* joint = static_cast(j); dUASSERT( joint, "bad joint argument" ); dUASSERT( result, "bad result argument" ); if (joint->node[0].body) { dBodyGetRelPointPos(joint->node[0].body, joint->anchors[0][0], joint->anchors[0][1], joint->anchors[0][2], result); } } void dJointGetTransmissionAnchor2( dJointID j, dVector3 result ) { dxJointTransmission* joint = static_cast(j); dUASSERT( joint, "bad joint argument" ); dUASSERT( result, "bad result argument" ); if (joint->node[1].body) { dBodyGetRelPointPos(joint->node[1].body, joint->anchors[1][0], joint->anchors[1][1], joint->anchors[1][2], result); } } void dJointSetTransmissionParam( dJointID j, int parameter, dReal value ) { dxJointTransmission* joint = static_cast(j); dUASSERT( joint, "bad joint argument" ); switch ( parameter ) { case dParamCFM: joint->cfm = value; break; case dParamERP: joint->erp = value; break; } } dReal dJointGetTransmissionParam( dJointID j, int parameter ) { dxJointTransmission* joint = static_cast(j); dUASSERT( joint, "bad joint argument" ); switch ( parameter ) { case dParamCFM: return joint->cfm; case dParamERP: return joint->erp; default: return 0; } } void dJointSetTransmissionMode( dJointID j, int mode ) { dxJointTransmission* joint = static_cast(j); dUASSERT( joint, "bad joint argument" ); dUASSERT( mode == dTransmissionParallelAxes || mode == dTransmissionIntersectingAxes || mode == dTransmissionChainDrive, "invalid joint mode" ); joint->mode = mode; } int dJointGetTransmissionMode( dJointID j ) { dxJointTransmission* joint = static_cast(j); dUASSERT( joint, "bad joint argument" ); return joint->mode; } void dJointSetTransmissionRatio( dJointID j, dReal ratio ) { dxJointTransmission* joint = static_cast(j); dUASSERT( joint, "bad joint argument" ); dUASSERT( joint->mode == dTransmissionParallelAxes, "can't set ratio explicitly in current mode" ); dUASSERT( ratio > 0, "ratio must be positive" ); joint->ratio = ratio; } dReal dJointGetTransmissionRatio( dJointID j ) { dxJointTransmission* joint = static_cast(j); dUASSERT( joint, "bad joint argument" ); return joint->ratio; } dReal dJointGetTransmissionAngle1( dJointID j ) { dxJointTransmission* joint = static_cast(j); dUASSERT( joint, "bad joint argument" ); return joint->phase[0]; } dReal dJointGetTransmissionAngle2( dJointID j ) { dxJointTransmission* joint = static_cast(j); dUASSERT( joint, "bad joint argument" ); return joint->phase[1]; } dReal dJointGetTransmissionRadius1( dJointID j ) { dxJointTransmission* joint = static_cast(j); dUASSERT( joint, "bad joint argument" ); return joint->radii[0]; } dReal dJointGetTransmissionRadius2( dJointID j ) { dxJointTransmission* joint = static_cast(j); dUASSERT( joint, "bad joint argument" ); return joint->radii[1]; } void dJointSetTransmissionRadius1( dJointID j, dReal radius ) { dxJointTransmission* joint = static_cast(j); dUASSERT( joint, "bad joint argument" ); dUASSERT( joint->mode == dTransmissionChainDrive, "can't set wheel radius explicitly in current mode" ); joint->radii[0] = radius; } void dJointSetTransmissionRadius2( dJointID j, dReal radius ) { dxJointTransmission* joint = static_cast(j); dUASSERT( joint, "bad joint argument" ); dUASSERT( joint->mode == dTransmissionChainDrive, "can't set wheel radius explicitly in current mode" ); joint->radii[1] = radius; } dReal dJointGetTransmissionBacklash( dJointID j ) { dxJointTransmission* joint = static_cast(j); dUASSERT( joint, "bad joint argument" ); return joint->backlash; } void dJointSetTransmissionBacklash( dJointID j, dReal backlash ) { dxJointTransmission* joint = static_cast(j); dUASSERT( joint, "bad joint argument" ); joint->backlash = backlash; } dJointType dxJointTransmission::type() const { return dJointTypeTransmission; } sizeint dxJointTransmission::size() const { return sizeof( *this ); } ode-0.16/ode/src/joints/joints.h0000664000175200017520000000373513403272463013475 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_JOINTS_H_ #define _ODE_JOINTS_H_ #include #include "joint.h" #include "ball.h" #include "dball.h" #include "dhinge.h" #include "transmission.h" #include "hinge.h" #include "slider.h" #include "contact.h" #include "universal.h" #include "hinge2.h" #include "fixed.h" #include "null.h" #include "amotor.h" #include "lmotor.h" #include "plane2d.h" #include "pu.h" #include "pr.h" #include "piston.h" #endif ode-0.16/ode/src/joints/null.cpp0000664000175200017520000000451113403272463013465 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include "config.h" #include "null.h" #include "joint_internal.h" //**************************************************************************** // null joint dxJointNull::dxJointNull( dxWorld *w ) : dxJoint( w ) { } void dxJointNull::getSureMaxInfo( SureMaxInfo* info ) { info->max_m = 0; } void dxJointNull::getInfo1( dxJoint::Info1 *info ) { info->m = 0; info->nub = 0; } void dxJointNull::getInfo2( dReal /*worldFPS*/, dReal /*worldERP*/, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dReal *pairLoHi, int *findex ) { dDebug( 0, "this should never get called" ); } dJointType dxJointNull::type() const { return dJointTypeNull; } sizeint dxJointNull::size() const { return sizeof( *this ); } ode-0.16/ode/src/joints/lmotor.cpp0000664000175200017520000001412113403272463014025 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include "config.h" #include "lmotor.h" #include "joint_internal.h" //**************************************************************************** // lmotor joint dxJointLMotor::dxJointLMotor( dxWorld *w ) : dxJoint( w ) { int i; num = 0; for ( i = 0;i < 3;i++ ) { dSetZero( axis[i], 4 ); limot[i].init( world ); } } void dxJointLMotor::computeGlobalAxes( dVector3 ax[3] ) { for ( int i = 0; i < num; i++ ) { if ( rel[i] == 1 ) { dMultiply0_331( ax[i], node[0].body->posr.R, axis[i] ); } else if ( rel[i] == 2 ) { if ( node[1].body ) // jds: don't assert, just ignore { dMultiply0_331( ax[i], node[1].body->posr.R, axis[i] ); } } else { ax[i][0] = axis[i][0]; ax[i][1] = axis[i][1]; ax[i][2] = axis[i][2]; } } } void dxJointLMotor::getSureMaxInfo( SureMaxInfo* info ) { info->max_m = num; } void dxJointLMotor::getInfo1( dxJoint::Info1 *info ) { info->m = 0; info->nub = 0; for ( int i = 0; i < num; i++ ) { if ( limot[i].fmax > 0 ) { info->m++; } } } void dxJointLMotor::getInfo2( dReal worldFPS, dReal /*worldERP*/, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dReal *pairLoHi, int *findex ) { dVector3 ax[3]; computeGlobalAxes( ax ); int currRowSkip = 0, currPairSkip = 0; for ( int i = 0; i < num; ++i ) { if (limot[i].addLimot( this, worldFPS, J1 + currRowSkip, J2 + currRowSkip, pairRhsCfm + currPairSkip, pairLoHi + currPairSkip, ax[i], 0 )) { currRowSkip += rowskip; currPairSkip += pairskip; } } } void dJointSetLMotorAxis( dJointID j, int anum, int rel, dReal x, dReal y, dReal z ) { dxJointLMotor* joint = ( dxJointLMotor* )j; //for now we are ignoring rel! dAASSERT( joint && anum >= 0 && anum <= 2 && rel >= 0 && rel <= 2 ); checktype( joint, LMotor ); if ( anum < 0 ) anum = 0; if ( anum > 2 ) anum = 2; if ( !joint->node[1].body && rel == 2 ) rel = 1; //ref 1 joint->rel[anum] = rel; dVector3 r; r[0] = x; r[1] = y; r[2] = z; r[3] = 0; if ( rel > 0 ) { if ( rel == 1 ) { dMultiply1_331( joint->axis[anum], joint->node[0].body->posr.R, r ); } else { //second body has to exists thanks to ref 1 line dMultiply1_331( joint->axis[anum], joint->node[1].body->posr.R, r ); } } else { joint->axis[anum][0] = r[0]; joint->axis[anum][1] = r[1]; joint->axis[anum][2] = r[2]; } dNormalize3( joint->axis[anum] ); } void dJointSetLMotorNumAxes( dJointID j, int num ) { dxJointLMotor* joint = ( dxJointLMotor* )j; dAASSERT( joint && num >= 0 && num <= 3 ); checktype( joint, LMotor ); if ( num < 0 ) num = 0; if ( num > 3 ) num = 3; joint->num = num; } void dJointSetLMotorParam( dJointID j, int parameter, dReal value ) { dxJointLMotor* joint = ( dxJointLMotor* )j; dAASSERT( joint ); checktype( joint, LMotor ); int anum = parameter >> 8; if ( anum < 0 ) anum = 0; if ( anum > 2 ) anum = 2; parameter &= 0xff; joint->limot[anum].set( parameter, value ); } int dJointGetLMotorNumAxes( dJointID j ) { dxJointLMotor* joint = ( dxJointLMotor* )j; dAASSERT( joint ); checktype( joint, LMotor ); return joint->num; } void dJointGetLMotorAxis( dJointID j, int anum, dVector3 result ) { dxJointLMotor* joint = ( dxJointLMotor* )j; dAASSERT( joint && anum >= 0 && anum < 3 ); checktype( joint, LMotor ); if ( anum < 0 ) anum = 0; if ( anum > 2 ) anum = 2; result[0] = joint->axis[anum][0]; result[1] = joint->axis[anum][1]; result[2] = joint->axis[anum][2]; } dReal dJointGetLMotorParam( dJointID j, int parameter ) { dxJointLMotor* joint = ( dxJointLMotor* )j; dAASSERT( joint ); checktype( joint, LMotor ); int anum = parameter >> 8; if ( anum < 0 ) anum = 0; if ( anum > 2 ) anum = 2; parameter &= 0xff; return joint->limot[anum].get( parameter ); } dJointType dxJointLMotor::type() const { return dJointTypeLMotor; } sizeint dxJointLMotor::size() const { return sizeof( *this ); } ode-0.16/ode/src/joints/pu.cpp0000664000175200017520000005662613403272463013155 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include "config.h" #include "pu.h" #include "joint_internal.h" //**************************************************************************** // Prismatic and Universal dxJointPU::dxJointPU( dxWorld *w ) : dxJointUniversal( w ) { // Default Position // Y ^ Axis2 // ^ | // / | ^ Axis1 // Z^ / | / // | / Body 2 | / Body 1 // | / +---------+ | / +-----------+ // | / / /| | / / /| // | / / / + _/ - / / + // | / / /-/--------(_)----|--- /-----------/-------> AxisP // | / +---------+ / - +-----------+ / // | / | |/ | |/ // | / +---------+ +-----------+ // |/ // .-----------------------------------------> X // |-----------------> // Anchor2 <--------------| // Anchor1 // // Setting member variables which are w.r.t body2 dSetZero( axis1, 4 ); axis1[1] = 1; // Setting member variables which are w.r.t body2 dSetZero( anchor2, 4 ); dSetZero( axis2, 4 ); axis2[2] = 1; dSetZero( axisP1, 4 ); axisP1[0] = 1; dSetZero( qrel1, 4 ); dSetZero( qrel2, 4 ); limotP.init( world ); limot1.init( world ); limot2.init( world ); } dReal dJointGetPUPosition( dJointID j ) { dxJointPU* joint = ( dxJointPU* ) j; dUASSERT( joint, "bad joint argument" ); checktype( joint, PU ); dVector3 q; // get the offset in global coordinates dMultiply0_331( q, joint->node[0].body->posr.R, joint->anchor1 ); if ( joint->node[1].body ) { dVector3 anchor2; // get the anchor2 in global coordinates dMultiply0_331( anchor2, joint->node[1].body->posr.R, joint->anchor2 ); q[0] = (( joint->node[0].body->posr.pos[0] + q[0] ) - ( joint->node[1].body->posr.pos[0] + anchor2[0] ) ); q[1] = (( joint->node[0].body->posr.pos[1] + q[1] ) - ( joint->node[1].body->posr.pos[1] + anchor2[1] ) ); q[2] = (( joint->node[0].body->posr.pos[2] + q[2] ) - ( joint->node[1].body->posr.pos[2] + anchor2[2] ) ); } else { //N.B. When there is no body 2 the joint->anchor2 is already in // global coordinates q[0] = (( joint->node[0].body->posr.pos[0] + q[0] ) - ( joint->anchor2[0] ) ); q[1] = (( joint->node[0].body->posr.pos[1] + q[1] ) - ( joint->anchor2[1] ) ); q[2] = (( joint->node[0].body->posr.pos[2] + q[2] ) - ( joint->anchor2[2] ) ); if ( joint->flags & dJOINT_REVERSE ) { q[0] = -q[0]; q[1] = -q[1]; q[2] = -q[2]; } } dVector3 axP; // get prismatic axis in global coordinates dMultiply0_331( axP, joint->node[0].body->posr.R, joint->axisP1 ); return dCalcVectorDot3( axP, q ); } dReal dJointGetPUPositionRate( dJointID j ) { dxJointPU* joint = ( dxJointPU* ) j; dUASSERT( joint, "bad joint argument" ); checktype( joint, PU ); if ( joint->node[0].body ) { // We want to find the rate of change of the prismatic part of the joint // We can find it by looking at the speed difference between body1 and the // anchor point. // r will be used to find the distance between body1 and the anchor point dVector3 r; dVector3 anchor2 = {0,0,0}; if ( joint->node[1].body ) { // Find joint->anchor2 in global coordinates dMultiply0_331( anchor2, joint->node[1].body->posr.R, joint->anchor2 ); r[0] = ( joint->node[0].body->posr.pos[0] - ( anchor2[0] + joint->node[1].body->posr.pos[0] ) ); r[1] = ( joint->node[0].body->posr.pos[1] - ( anchor2[1] + joint->node[1].body->posr.pos[1] ) ); r[2] = ( joint->node[0].body->posr.pos[2] - ( anchor2[2] + joint->node[1].body->posr.pos[2] ) ); } else { //N.B. When there is no body 2 the joint->anchor2 is already in // global coordinates // r = joint->node[0].body->posr.pos - joint->anchor2; dSubtractVectors3( r, joint->node[0].body->posr.pos, joint->anchor2 ); } // The body1 can have velocity coming from the rotation of // the rotoide axis. We need to remove this. // N.B. We do vel = r X w instead of vel = w x r to have vel negative // since we want to remove it from the linear velocity of the body dVector3 lvel1; dCalcVectorCross3( lvel1, r, joint->node[0].body->avel ); // lvel1 += joint->node[0].body->lvel; dAddVectors3( lvel1, lvel1, joint->node[0].body->lvel ); // Since we want rate of change along the prismatic axis // get axisP1 in global coordinates and get the component // along this axis only dVector3 axP1; dMultiply0_331( axP1, joint->node[0].body->posr.R, joint->axisP1 ); if ( joint->node[1].body ) { // Find the contribution of the angular rotation to the linear speed // N.B. We do vel = r X w instead of vel = w x r to have vel negative // since we want to remove it from the linear velocity of the body dVector3 lvel2; dCalcVectorCross3( lvel2, anchor2, joint->node[1].body->avel ); // lvel1 -= lvel2 + joint->node[1].body->lvel; dVector3 tmp; dAddVectors3( tmp, lvel2, joint->node[1].body->lvel ); dSubtractVectors3( lvel1, lvel1, tmp ); return dCalcVectorDot3( axP1, lvel1 ); } else { dReal rate = dCalcVectorDot3( axP1, lvel1 ); return ( (joint->flags & dJOINT_REVERSE) ? -rate : rate); } } return 0.0; } void dxJointPU::getSureMaxInfo( SureMaxInfo* info ) { info->max_m = 6; } void dxJointPU::getInfo1( dxJoint::Info1 *info ) { info->m = 3; info->nub = 3; // powered needs an extra constraint row // see if we're at a joint limit. limotP.limit = 0; if (( limotP.lostop > -dInfinity || limotP.histop < dInfinity ) && limotP.lostop <= limotP.histop ) { // measure joint position dReal pos = dJointGetPUPosition( this ); limotP.testRotationalLimit( pos ); // N.B. The function is ill named } if ( limotP.limit || limotP.fmax > 0 ) info->m++; bool limiting1 = ( limot1.lostop >= -M_PI || limot1.histop <= M_PI ) && limot1.lostop <= limot1.histop; bool limiting2 = ( limot2.lostop >= -M_PI || limot2.histop <= M_PI ) && limot2.lostop <= limot2.histop; // We need to call testRotationLimit() even if we're motored, since it // records the result. limot1.limit = 0; limot2.limit = 0; if ( limiting1 || limiting2 ) { dReal angle1, angle2; getAngles( &angle1, &angle2 ); if ( limiting1 ) limot1.testRotationalLimit( angle1 ); if ( limiting2 ) limot2.testRotationalLimit( angle2 ); } if ( limot1.limit || limot1.fmax > 0 ) info->m++; if ( limot2.limit || limot2.fmax > 0 ) info->m++; } void dxJointPU::getInfo2( dReal worldFPS, dReal worldERP, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dReal *pairLoHi, int *findex ) { const dReal k = worldFPS * worldERP; // ====================================================================== // The angular constraint // dVector3 ax1, ax2; // Global axes of rotation getAxis(this, ax1, axis1); getAxis2(this,ax2, axis2); dVector3 uniPerp; // Axis perpendicular to axes of rotation dCalcVectorCross3(uniPerp,ax1,ax2); dNormalize3( uniPerp ); dCopyVector3( J1 + GI2__JA_MIN, uniPerp ); dxBody *body1 = node[1].body; if ( body1 ) { dCopyNegatedVector3( J2 + GI2__JA_MIN , uniPerp ); } // Corrective velocity attempting to keep uni axes perpendicular dReal val = dCalcVectorDot3( ax1, ax2 ); // Small angle approximation : // theta = asin(val) // theta is approximately val when val is near zero. pairRhsCfm[GI2_RHS] = -k * val; // ========================================================================== // Handle axes orthogonal to the prismatic dVector3 an1, an2; // Global anchor positions dVector3 axP, sep; // Prismatic axis and separation vector getAnchor(this, an1, anchor1); getAnchor2(this, an2, anchor2); if (flags & dJOINT_REVERSE) { getAxis2(this, axP, axisP1); } else { getAxis(this, axP, axisP1); } dSubtractVectors3(sep, an2, an1); dVector3 p, q; dPlaneSpace(axP, p, q); dCopyVector3( J1 + rowskip + GI2__JL_MIN, p ); dCopyVector3( J1 + 2 * rowskip + GI2__JL_MIN, q ); // Make the anchors be body local // Aliasing isn't a problem here. dSubtractVectors3(an1, an1, node[0].body->posr.pos); dCalcVectorCross3( J1 + rowskip + GI2__JA_MIN, an1, p ); dCalcVectorCross3( J1 + 2 * rowskip + GI2__JA_MIN, an1, q ); if (body1) { dCopyNegatedVector3( J2 + rowskip + GI2__JL_MIN, p ); dCopyNegatedVector3( J2 + 2 * rowskip + GI2__JL_MIN, q ); dSubtractVectors3(an2, an2, body1->posr.pos); dCalcVectorCross3( J2 + rowskip + GI2__JA_MIN, p, an2 ); dCalcVectorCross3( J2 + 2 * rowskip + GI2__JA_MIN, q, an2 ); } pairRhsCfm[pairskip + GI2_RHS] = k * dCalcVectorDot3( p, sep ); pairRhsCfm[2 * pairskip + GI2_RHS] = k * dCalcVectorDot3( q, sep ); // ========================================================================== // Handle the limits/motors int currRowSkip = 3 * rowskip, currPairSkip = 3 * pairskip; if (limot1.addLimot( this, worldFPS, J1 + currRowSkip, J2 + currRowSkip, pairRhsCfm + currPairSkip, pairLoHi + currPairSkip, ax1, 1 )) { currRowSkip += rowskip; currPairSkip += pairskip; } if (limot2.addLimot( this, worldFPS, J1 + currRowSkip, J2 + currRowSkip, pairRhsCfm + currPairSkip, pairLoHi + currPairSkip, ax2, 1 )) { currRowSkip += rowskip; currPairSkip += pairskip; } if ( body1 || (flags & dJOINT_REVERSE) == 0 ) { limotP.addTwoPointLimot( this, worldFPS, J1 + currRowSkip, J2 + currRowSkip, pairRhsCfm + currPairSkip, pairLoHi + currPairSkip, axP, an1, an2 ); } else { dNegateVector3(axP); limotP.addTwoPointLimot ( this, worldFPS, J1 + currRowSkip, J2 + currRowSkip, pairRhsCfm + currPairSkip, pairLoHi + currPairSkip, axP, an1, an2 ); } } void dJointSetPUAnchor( dJointID j, dReal x, dReal y, dReal z ) { dxJointPU* joint = ( dxJointPU* ) j; dUASSERT( joint, "bad joint argument" ); checktype( joint, PU ); setAnchors( joint, x, y, z, joint->anchor1, joint->anchor2 ); joint->computeInitialRelativeRotations(); } /** * This function initialize the anchor and the relative position of each body * as if body2 was at its current position + [dx,dy,dy]. * Ex: *
 * dReal offset = 1;
 * dVector3 dir;
 * dJointGetPUAxis3(jId, dir);
 * dJointSetPUAnchor(jId, 0, 0, 0);
 * // If you request the position you will have: dJointGetPUPosition(jId) == 0
 * dJointSetPUAnchorDelta(jId, 0, 0, 0, dir[X]*offset, dir[Y]*offset, dir[Z]*offset);
 * // If you request the position you will have: dJointGetPUPosition(jId) == -offset
 * 
* @param j The PU joint for which the anchor point will be set * @param x The X position of the anchor point in world frame * @param y The Y position of the anchor point in world frame * @param z The Z position of the anchor point in world frame * @param dx A delta to be added to the X position as if the anchor was set * when body1 was at current_position[X] + dx * @param dx A delta to be added to the Y position as if the anchor was set * when body1 was at current_position[Y] + dy * @param dx A delta to be added to the Z position as if the anchor was set * when body1 was at current_position[Z] + dz * @note Should have the same meaning as dJointSetSliderAxisDelta */ void dJointSetPUAnchorDelta( dJointID j, dReal x, dReal y, dReal z, dReal dx, dReal dy, dReal dz ) { dxJointPU* joint = ( dxJointPU* ) j; dUASSERT( joint, "bad joint argument" ); checktype( joint, PU ); if ( joint->node[0].body ) { joint->node[0].body->posr.pos[0] += dx; joint->node[0].body->posr.pos[1] += dy; joint->node[0].body->posr.pos[2] += dz; } setAnchors( joint, x, y, z, joint->anchor1, joint->anchor2 ); if ( joint->node[0].body ) { joint->node[0].body->posr.pos[0] -= dx; joint->node[0].body->posr.pos[1] -= dy; joint->node[0].body->posr.pos[2] -= dz; } joint->computeInitialRelativeRotations(); } /** * \brief This function initialize the anchor and the relative position of each body * such that dJointGetPUPosition will return the dot product of axis and [dx,dy,dy]. * * The body 1 is moved to [-dx, -dy, -dx] then the anchor is set. This will be the * position 0 for the prismatic part of the joint. Then the body 1 is moved to its * original position. * * Ex: *
 * dReal offset = 1;
 * dVector3 dir;
 * dJointGetPUAxis3(jId, dir);
 * dJointSetPUAnchor(jId, 0, 0, 0);
 * // If you request the position you will have: dJointGetPUPosition(jId) == 0
 * dJointSetPUAnchorDelta(jId, 0, 0, 0, dir[X]*offset, dir[Y]*offset, dir[Z]*offset);
 * // If you request the position you will have: dJointGetPUPosition(jId) == offset
 * 
* @param j The PU joint for which the anchor point will be set * @param x The X position of the anchor point in world frame * @param y The Y position of the anchor point in world frame * @param z The Z position of the anchor point in world frame * @param dx A delta to be added to the X position as if the anchor was set * when body1 was at current_position[X] + dx * @param dx A delta to be added to the Y position as if the anchor was set * when body1 was at current_position[Y] + dy * @param dx A delta to be added to the Z position as if the anchor was set * when body1 was at current_position[Z] + dz * @note Should have the same meaning as dJointSetSliderAxisDelta */ void dJointSetPUAnchorOffset( dJointID j, dReal x, dReal y, dReal z, dReal dx, dReal dy, dReal dz ) { dxJointPU* joint = ( dxJointPU* ) j; dUASSERT( joint, "bad joint argument" ); checktype( joint, PU ); if (joint->flags & dJOINT_REVERSE) { dx = -dx; dy = -dy; dz = -dz; } if ( joint->node[0].body ) { joint->node[0].body->posr.pos[0] -= dx; joint->node[0].body->posr.pos[1] -= dy; joint->node[0].body->posr.pos[2] -= dz; } setAnchors( joint, x, y, z, joint->anchor1, joint->anchor2 ); if ( joint->node[0].body ) { joint->node[0].body->posr.pos[0] += dx; joint->node[0].body->posr.pos[1] += dy; joint->node[0].body->posr.pos[2] += dz; } joint->computeInitialRelativeRotations(); } void dJointSetPUAxis1( dJointID j, dReal x, dReal y, dReal z ) { dxJointPU* joint = ( dxJointPU* ) j; dUASSERT( joint, "bad joint argument" ); checktype( joint, PU ); if ( joint->flags & dJOINT_REVERSE ) setAxes( joint, x, y, z, NULL, joint->axis2 ); else setAxes( joint, x, y, z, joint->axis1, NULL ); joint->computeInitialRelativeRotations(); } void dJointSetPUAxis2( dJointID j, dReal x, dReal y, dReal z ) { dxJointPU* joint = ( dxJointPU* ) j; dUASSERT( joint, "bad joint argument" ); checktype( joint, PU ); if ( joint->flags & dJOINT_REVERSE ) setAxes( joint, x, y, z, joint->axis1, NULL ); else setAxes( joint, x, y, z, NULL, joint->axis2 ); joint->computeInitialRelativeRotations(); } void dJointSetPUAxisP( dJointID id, dReal x, dReal y, dReal z ) { dJointSetPUAxis3( id, x, y, z ); } void dJointSetPUAxis3( dJointID j, dReal x, dReal y, dReal z ) { dxJointPU* joint = ( dxJointPU* ) j; dUASSERT( joint, "bad joint argument" ); checktype( joint, PU ); setAxes( joint, x, y, z, joint->axisP1, 0 ); joint->computeInitialRelativeRotations(); } void dJointGetPUAngles( dJointID j, dReal *angle1, dReal *angle2 ) { dxJointUniversal* joint = ( dxJointUniversal* ) j; dUASSERT( joint, "bad joint argument" ); checktype( joint, PU ); if ( joint->flags & dJOINT_REVERSE ) joint->getAngles( angle2, angle1 ); else joint->getAngles( angle1, angle2 ); } dReal dJointGetPUAngle1( dJointID j ) { dxJointUniversal* joint = ( dxJointUniversal* ) j; dUASSERT( joint, "bad joint argument" ); checktype( joint, PU ); if ( joint->flags & dJOINT_REVERSE ) return joint->getAngle2(); else return joint->getAngle1(); } dReal dJointGetPUAngle2( dJointID j ) { dxJointUniversal* joint = ( dxJointUniversal* ) j; dUASSERT( joint, "bad joint argument" ); checktype( joint, PU ); if ( joint->flags & dJOINT_REVERSE ) return joint->getAngle1(); else return joint->getAngle2(); } dReal dJointGetPUAngle1Rate( dJointID j ) { dxJointPU* joint = ( dxJointPU* ) j; dUASSERT( joint, "bad joint argument" ); checktype( joint, PU ); if ( joint->node[0].body ) { dVector3 axis; if ( joint->flags & dJOINT_REVERSE ) getAxis2( joint, axis, joint->axis2 ); else getAxis( joint, axis, joint->axis1 ); dReal rate = dCalcVectorDot3( axis, joint->node[0].body->avel ); if ( joint->node[1].body ) rate -= dCalcVectorDot3( axis, joint->node[1].body->avel ); return rate; } return 0; } dReal dJointGetPUAngle2Rate( dJointID j ) { dxJointPU* joint = ( dxJointPU* ) j; dUASSERT( joint, "bad joint argument" ); checktype( joint, PU ); if ( joint->node[0].body ) { dVector3 axis; if ( joint->flags & dJOINT_REVERSE ) getAxis( joint, axis, joint->axis1 ); else getAxis2( joint, axis, joint->axis2 ); dReal rate = dCalcVectorDot3( axis, joint->node[0].body->avel ); if ( joint->node[1].body ) rate -= dCalcVectorDot3( axis, joint->node[1].body->avel ); return rate; } return 0; } void dJointSetPUParam( dJointID j, int parameter, dReal value ) { dxJointPU* joint = ( dxJointPU* ) j; dUASSERT( joint, "bad joint argument" ); checktype( joint, PU ); switch ( parameter & 0xff00 ) { case dParamGroup1: joint->limot1.set( parameter, value ); break; case dParamGroup2: joint->limot2.set( parameter & 0xff, value ); break; case dParamGroup3: joint->limotP.set( parameter & 0xff, value ); break; } } void dJointGetPUAnchor( dJointID j, dVector3 result ) { dxJointPU* joint = ( dxJointPU* ) j; dUASSERT( joint, "bad joint argument" ); dUASSERT( result, "bad result argument" ); checktype( joint, PU ); if ( joint->node[1].body ) getAnchor2( joint, result, joint->anchor2 ); else { // result[i] = joint->anchor2[i]; dCopyVector3( result, joint->anchor2 ); } } void dJointGetPUAxis1( dJointID j, dVector3 result ) { dxJointPU* joint = ( dxJointPU* ) j; dUASSERT( joint, "bad joint argument" ); dUASSERT( result, "bad result argument" ); checktype( joint, PU ); if ( joint->flags & dJOINT_REVERSE ) getAxis2( joint, result, joint->axis2 ); else getAxis( joint, result, joint->axis1 ); } void dJointGetPUAxis2( dJointID j, dVector3 result ) { dxJointPU* joint = ( dxJointPU* ) j; dUASSERT( joint, "bad joint argument" ); dUASSERT( result, "bad result argument" ); checktype( joint, PU ); if ( joint->flags & dJOINT_REVERSE ) getAxis( joint, result, joint->axis1 ); else getAxis2( joint, result, joint->axis2 ); } /** * @brief Get the prismatic axis * @ingroup joints * * @note This function was added for convenience it is the same as * dJointGetPUAxis3 */ void dJointGetPUAxisP( dJointID id, dVector3 result ) { dJointGetPUAxis3( id, result ); } void dJointGetPUAxis3( dJointID j, dVector3 result ) { dxJointPU* joint = ( dxJointPU* ) j; dUASSERT( joint, "bad joint argument" ); dUASSERT( result, "bad result argument" ); checktype( joint, PU ); getAxis( joint, result, joint->axisP1 ); } dReal dJointGetPUParam( dJointID j, int parameter ) { dxJointPU* joint = ( dxJointPU* ) j; dUASSERT( joint, "bad joint argument" ); checktype( joint, PU ); switch ( parameter & 0xff00 ) { case dParamGroup1: return joint->limot1.get( parameter ); break; case dParamGroup2: return joint->limot2.get( parameter & 0xff ); break; case dParamGroup3: return joint->limotP.get( parameter & 0xff ); break; } return 0; } dJointType dxJointPU::type() const { return dJointTypePU; } sizeint dxJointPU::size() const { return sizeof( *this ); } void dxJointPU::setRelativeValues() { dVector3 anchor; dJointGetPUAnchor(this, anchor); setAnchors( this, anchor[0], anchor[1], anchor[2], anchor1, anchor2 ); dVector3 ax1, ax2, ax3; dJointGetPUAxis1(this, ax1); dJointGetPUAxis2(this, ax2); dJointGetPUAxis3(this, ax3); if ( flags & dJOINT_REVERSE ) { setAxes( this, ax1[0], ax1[1], ax1[2], NULL, axis2 ); setAxes( this, ax2[0], ax2[1], ax2[2], axis1, NULL ); } else { setAxes( this, ax1[0], ax1[1], ax1[2], axis1, NULL ); setAxes( this, ax2[0], ax2[1], ax2[2], NULL, axis2 ); } setAxes( this, ax3[0], ax3[1], ax3[2], axisP1, NULL ); computeInitialRelativeRotations(); } ode-0.16/ode/src/joints/lmotor.h0000664000175200017520000000426213403272463013477 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_JOINT_LMOTOR_H_ #define _ODE_JOINT_LMOTOR_H_ #include "joint.h" struct dxJointLMotor : public dxJoint { int num; int rel[3]; dVector3 axis[3]; dxJointLimitMotor limot[3]; void computeGlobalAxes( dVector3 ax[3] ); dxJointLMotor( dxWorld *w ); virtual void getSureMaxInfo( SureMaxInfo* info ); virtual void getInfo1( Info1* info ); virtual void getInfo2( dReal worldFPS, dReal worldERP, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dReal *pairLoHi, int *findex ); virtual dJointType type() const; virtual sizeint size() const; }; #endif ode-0.16/ode/src/joints/fixed.cpp0000664000175200017520000001414713403272463013620 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include "config.h" #include "fixed.h" #include "joint_internal.h" //**************************************************************************** // fixed joint dxJointFixed::dxJointFixed ( dxWorld *w ) : dxJoint ( w ) { dSetZero ( offset, 4 ); dSetZero ( qrel, 4 ); erp = world->global_erp; cfm = world->global_cfm; } void dxJointFixed::getSureMaxInfo( SureMaxInfo* info ) { info->max_m = 6; } void dxJointFixed::getInfo1 ( dxJoint::Info1 *info ) { info->m = 6; info->nub = 6; } void dxJointFixed::getInfo2 ( dReal worldFPS, dReal worldERP, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dReal *pairLoHi, int *findex ) { // Three rows for orientation setFixedOrientation ( this, worldFPS, worldERP, rowskip, J1 + dSA__MAX * rowskip, J2 + dSA__MAX * rowskip, pairskip, pairRhsCfm + dSA__MAX * pairskip, qrel ); // Three rows for position. // set Jacobian J1[GI2_JLX] = 1; J1[rowskip + GI2_JLY] = 1; J1[2 * rowskip + GI2_JLZ] = 1; dReal k = worldFPS * this->erp; dxBody *b0 = node[0].body, *b1 = node[1].body; dVector3 ofs; dMultiply0_331 ( ofs, b0->posr.R, offset ); if ( b1 ) { dSetCrossMatrixPlus( J1 + GI2__JA_MIN, ofs, rowskip ); J2[GI2_JLX] = -1; J2[rowskip + GI2_JLY] = -1; J2[2 * rowskip + GI2_JLZ] = -1; } // set right hand side for the first three rows (linear) if ( b1 ) { for ( int j = 0, currPairSkip = 0; j < 3; currPairSkip += pairskip, ++j ) { pairRhsCfm[currPairSkip + GI2_RHS] = k * ( b1->posr.pos[j] - b0->posr.pos[j] + ofs[j] ); } } else { for ( int j = 0, currPairSkip = 0; j < 3; currPairSkip += pairskip, ++j ) { pairRhsCfm[currPairSkip + GI2_RHS] = k * ( offset[j] - b0->posr.pos[j] ); } } dReal cfm = this->cfm; pairRhsCfm[GI2_CFM] = cfm; pairRhsCfm[pairskip + GI2_CFM] = cfm; pairRhsCfm[2 * pairskip + GI2_CFM] = cfm; } void dJointSetFixed ( dJointID j ) { dxJointFixed* joint = ( dxJointFixed* ) j; dUASSERT ( joint, "bad joint argument" ); checktype ( joint, Fixed ); int i; // This code is taken from dJointSetSliderAxis(), we should really put the // common code in its own function. // compute the offset between the bodies if ( joint->node[0].body ) { if ( joint->node[1].body ) { dReal ofs[4]; for ( i = 0; i < 4; i++ ) ofs[i] = joint->node[0].body->posr.pos[i] - joint->node[1].body->posr.pos[i]; dMultiply1_331 ( joint->offset, joint->node[0].body->posr.R, ofs ); } else { joint->offset[0] = joint->node[0].body->posr.pos[0]; joint->offset[1] = joint->node[0].body->posr.pos[1]; joint->offset[2] = joint->node[0].body->posr.pos[2]; } } joint->computeInitialRelativeRotation(); } void dxJointFixed::set ( int num, dReal value ) { switch ( num ) { case dParamCFM: cfm = value; break; case dParamERP: erp = value; break; } } dReal dxJointFixed::get ( int num ) { switch ( num ) { case dParamCFM: return cfm; case dParamERP: return erp; default: return 0; } } void dJointSetFixedParam ( dJointID j, int parameter, dReal value ) { dxJointFixed* joint = ( dxJointFixed* ) j; dUASSERT ( joint, "bad joint argument" ); checktype ( joint, Fixed ); joint->set ( parameter, value ); } dReal dJointGetFixedParam ( dJointID j, int parameter ) { dxJointFixed* joint = ( dxJointFixed* ) j; dUASSERT ( joint, "bad joint argument" ); checktype ( joint, Fixed ); return joint->get ( parameter ); } dJointType dxJointFixed::type() const { return dJointTypeFixed; } sizeint dxJointFixed::size() const { return sizeof ( *this ); } void dxJointFixed::computeInitialRelativeRotation() { if (node[0].body ) { if (node[1].body ) { dQMultiply1 (qrel, node[0].body->q, node[1].body->q ); } else { // set qrel to the transpose of the first body q qrel[0] = node[0].body->q[0]; qrel[1] = -node[0].body->q[1]; qrel[2] = -node[0].body->q[2]; qrel[3] = -node[0].body->q[3]; } } } ode-0.16/ode/src/joints/piston.h0000664000175200017520000001245513403272463013502 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_JOINT_PISTON_H_ #define _ODE_JOINT_PISTON_H_ #include "joint.h" //////////////////////////////////////////////////////////////////////////////// /// Component of a Piston joint ///
///                              |- Anchor point
///      Body_1                  |                       Body_2
///      +---------------+       V                       +------------------+
///     /               /|                             /                  /|
///    /               / +       |--      ______      /                  / +
///   /      x        /./........x.......(_____()..../         x        /.......> axis
///  +---------------+ /         |--                +------------------+ /
///  |               |/                             |                  |/
///  +---------------+                              +------------------+
///          |                                                 |
///          |                                                 |
///          |------------------> <----------------------------|
///              anchor1                  anchor2
///
///
/// 
/// /// When the prismatic joint as been elongated (i.e. dJointGetPistonPosition) /// return a value > 0 ///
///                                   |- Anchor point
///      Body_1                       |                       Body_2
///      +---------------+            V                       +------------------+
///     /               /|                                  /                  /|
///    /               / +            |--      ______      /                  / +
///   /      x        /./........_____x.......(_____()..../         x        /.......> axis
///  +---------------+ /              |--                +------------------+ /
///  |               |/                                  |                  |/
///  +---------------+                                   +------------------+
///          |                                                      |
///          |                                                      |
///          |------------------>      <----------------------------|
///              anchor1         |----|         anchor2
///                                ^
///                                |-- This is what dJointGetPistonPosition will
///                                    return
/// 
//////////////////////////////////////////////////////////////////////////////// struct dxJointPiston : public dxJoint { dVector3 axis1; ///< Axis of the prismatic and rotoide w.r.t first body dVector3 axis2; ///< Axis of the prismatic and rotoide w.r.t second body dQuaternion qrel; ///< Initial relative rotation body1 -> body2 /// Anchor w.r.t first body. /// This is the same as the offset for the Slider joint /// @note To find the position of the anchor when the body 1 has moved /// you must add the position of the prismatic joint /// i.e anchor = R1 * anchor1 + dJointGetPistonPosition() * (R1 * axis1) dVector3 anchor1; dVector3 anchor2; //< anchor w.r.t second body /// limit and motor information for the prismatic /// part of the joint dxJointLimitMotor limotP; /// limit and motor information for the rotoide /// part of the joint dxJointLimitMotor limotR; dxJointPiston( dxWorld *w ); virtual void getSureMaxInfo( SureMaxInfo* info ); virtual void getInfo1( Info1* info ); virtual void getInfo2( dReal worldFPS, dReal worldERP, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dReal *pairLoHi, int *findex ); virtual dJointType type() const; virtual sizeint size() const; virtual void setRelativeValues(); void computeInitialRelativeRotation(); }; #endif ode-0.16/ode/src/joints/universal.h0000664000175200017520000000545413403272463014177 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_JOINT_UNIVERSAL_H_ #define _ODE_JOINT_UNIVERSAL_H_ #include "joint.h" // universal struct dxJointUniversal : public dxJoint { dVector3 anchor1; // anchor w.r.t first body dVector3 anchor2; // anchor w.r.t second body dVector3 axis1; // axis w.r.t first body dVector3 axis2; // axis w.r.t second body dQuaternion qrel1; // initial relative rotation body1 -> virtual cross piece dQuaternion qrel2; // initial relative rotation virtual cross piece -> body2 dxJointLimitMotor limot1; // limit and motor information for axis1 dxJointLimitMotor limot2; // limit and motor information for axis2 void getAxes( dVector3 ax1, dVector3 ax2 ); void getAngles( dReal *angle1, dReal *angle2 ); dReal getAngle1(); dReal getAngle2(); void computeInitialRelativeRotations(); dxJointUniversal( dxWorld *w ); virtual void getSureMaxInfo( SureMaxInfo* info ); virtual void getInfo1( Info1* info ); virtual void getInfo2( dReal worldFPS, dReal worldERP, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dReal *pairLoHi, int *findex); virtual dJointType type() const; virtual sizeint size() const; virtual void setRelativeValues(); }; #endif ode-0.16/ode/src/joints/hinge.cpp0000664000175200017520000003006013403272463013603 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include "config.h" #include "hinge.h" #include "joint_internal.h" //**************************************************************************** // hinge dxJointHinge::dxJointHinge( dxWorld *w ) : dxJoint( w ) { dSetZero( anchor1, 4 ); dSetZero( anchor2, 4 ); dSetZero( axis1, 4 ); axis1[0] = 1; dSetZero( axis2, 4 ); axis2[0] = 1; dSetZero( qrel, 4 ); limot.init( world ); } void dxJointHinge::getSureMaxInfo( SureMaxInfo* info ) { info->max_m = 6; } void dxJointHinge::getInfo1( dxJoint::Info1 *info ) { info->nub = 5; // see if joint is powered if ( limot.fmax > 0 ) info->m = 6; // powered hinge needs an extra constraint row else info->m = 5; // see if we're at a joint limit. if (( limot.lostop >= -M_PI || limot.histop <= M_PI ) && limot.lostop <= limot.histop ) { dReal angle = getHingeAngle( node[0].body, node[1].body, axis1, qrel ); if ( limot.testRotationalLimit( angle ) ) info->m = 6; } } void dxJointHinge::getInfo2( dReal worldFPS, dReal worldERP, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dReal *pairLoHi, int *findex ) { // set the three ball-and-socket rows setBall( this, worldFPS, worldERP, rowskip, J1, J2, pairskip, pairRhsCfm, anchor1, anchor2 ); // set the two hinge rows. the hinge axis should be the only unconstrained // rotational axis, the angular velocity of the two bodies perpendicular to // the hinge axis should be equal. thus the constraint equations are // p*w1 - p*w2 = 0 // q*w1 - q*w2 = 0 // where p and q are unit vectors normal to the hinge axis, and w1 and w2 // are the angular velocity vectors of the two bodies. dVector3 ax1; // length 1 joint axis in global coordinates, from 1st body dVector3 p, q; // plane space vectors for ax1 dMultiply0_331( ax1, node[0].body->posr.R, axis1 ); dPlaneSpace( ax1, p, q ); dxBody *body1 = node[1].body; int currRowSkip = 3 * rowskip; dCopyVector3(J1 + currRowSkip + GI2__JA_MIN, p); if ( body1 ) { dCopyNegatedVector3(J2 + currRowSkip + GI2__JA_MIN, p); } currRowSkip += rowskip; dCopyVector3(J1 + currRowSkip + GI2__JA_MIN, q); if ( body1 ) { dCopyNegatedVector3(J2 + currRowSkip + GI2__JA_MIN, q); } // compute the right hand side of the constraint equation. set relative // body velocities along p and q to bring the hinge back into alignment. // if ax1,ax2 are the unit length hinge axes as computed from body1 and // body2, we need to rotate both bodies along the axis u = (ax1 x ax2). // if `theta' is the angle between ax1 and ax2, we need an angular velocity // along u to cover angle erp*theta in one step : // |angular_velocity| = angle/time = erp*theta / stepsize // = (erp*fps) * theta // angular_velocity = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2| // = (erp*fps) * theta * (ax1 x ax2) / sin(theta) // ...as ax1 and ax2 are unit length. if theta is smallish, // theta ~= sin(theta), so // angular_velocity = (erp*fps) * (ax1 x ax2) // ax1 x ax2 is in the plane space of ax1, so we project the angular // velocity to p and q to find the right hand side. dVector3 b; if ( body1 ) { dVector3 ax2; dMultiply0_331( ax2, body1->posr.R, axis2 ); dCalcVectorCross3( b, ax1, ax2 ); } else { dCalcVectorCross3( b, ax1, axis2 ); } dReal k = worldFPS * worldERP; int currPairSkip = 3 * pairskip; pairRhsCfm[currPairSkip + GI2_RHS] = k * dCalcVectorDot3( b, p ); currPairSkip += pairskip; pairRhsCfm[currPairSkip + GI2_RHS] = k * dCalcVectorDot3( b, q ); // if the hinge is powered, or has joint limits, add in the stuff currRowSkip += rowskip; currPairSkip += pairskip; limot.addLimot( this, worldFPS, J1 + currRowSkip, J2 + currRowSkip, pairRhsCfm + currPairSkip, pairLoHi + currPairSkip, ax1, 1 ); } void dJointSetHingeAnchor( dJointID j, dReal x, dReal y, dReal z ) { dxJointHinge* joint = ( dxJointHinge* )j; dUASSERT( joint, "bad joint argument" ); checktype( joint, Hinge ); setAnchors( joint, x, y, z, joint->anchor1, joint->anchor2 ); joint->computeInitialRelativeRotation(); } void dJointSetHingeAnchorDelta( dJointID j, dReal x, dReal y, dReal z, dReal dx, dReal dy, dReal dz ) { dxJointHinge* joint = ( dxJointHinge* )j; dUASSERT( joint, "bad joint argument" ); checktype( joint, Hinge ); if ( joint->node[0].body ) { dReal q[4]; q[0] = x - joint->node[0].body->posr.pos[0]; q[1] = y - joint->node[0].body->posr.pos[1]; q[2] = z - joint->node[0].body->posr.pos[2]; q[3] = 0; dMultiply1_331( joint->anchor1, joint->node[0].body->posr.R, q ); if ( joint->node[1].body ) { q[0] = x - joint->node[1].body->posr.pos[0]; q[1] = y - joint->node[1].body->posr.pos[1]; q[2] = z - joint->node[1].body->posr.pos[2]; q[3] = 0; dMultiply1_331( joint->anchor2, joint->node[1].body->posr.R, q ); } else { // Move the relative displacement between the passive body and the // anchor in the same direction as the passive body has just moved joint->anchor2[0] = x + dx; joint->anchor2[1] = y + dy; joint->anchor2[2] = z + dz; } } joint->anchor1[3] = 0; joint->anchor2[3] = 0; joint->computeInitialRelativeRotation(); } void dJointSetHingeAxis( dJointID j, dReal x, dReal y, dReal z ) { dxJointHinge* joint = ( dxJointHinge* )j; dUASSERT( joint, "bad joint argument" ); checktype( joint, Hinge ); setAxes( joint, x, y, z, joint->axis1, joint->axis2 ); joint->computeInitialRelativeRotation(); } void dJointSetHingeAxisOffset( dJointID j, dReal x, dReal y, dReal z, dReal dangle ) { dxJointHinge* joint = ( dxJointHinge* )j; dUASSERT( joint, "bad joint argument" ); checktype( joint, Hinge ); setAxes( joint, x, y, z, joint->axis1, joint->axis2 ); joint->computeInitialRelativeRotation(); if ( joint->flags & dJOINT_REVERSE ) dangle = -dangle; dQuaternion qAngle, qOffset; dQFromAxisAndAngle(qAngle, x, y, z, dangle); dQMultiply3(qOffset, qAngle, joint->qrel); joint->qrel[0] = qOffset[0]; joint->qrel[1] = qOffset[1]; joint->qrel[2] = qOffset[2]; joint->qrel[3] = qOffset[3]; } void dJointGetHingeAnchor( dJointID j, dVector3 result ) { dxJointHinge* joint = ( dxJointHinge* )j; dUASSERT( joint, "bad joint argument" ); dUASSERT( result, "bad result argument" ); checktype( joint, Hinge ); if ( joint->flags & dJOINT_REVERSE ) getAnchor2( joint, result, joint->anchor2 ); else getAnchor( joint, result, joint->anchor1 ); } void dJointGetHingeAnchor2( dJointID j, dVector3 result ) { dxJointHinge* joint = ( dxJointHinge* )j; dUASSERT( joint, "bad joint argument" ); dUASSERT( result, "bad result argument" ); checktype( joint, Hinge ); if ( joint->flags & dJOINT_REVERSE ) getAnchor( joint, result, joint->anchor1 ); else getAnchor2( joint, result, joint->anchor2 ); } void dJointGetHingeAxis( dJointID j, dVector3 result ) { dxJointHinge* joint = ( dxJointHinge* )j; dUASSERT( joint, "bad joint argument" ); dUASSERT( result, "bad result argument" ); checktype( joint, Hinge ); getAxis( joint, result, joint->axis1 ); } void dJointSetHingeParam( dJointID j, int parameter, dReal value ) { dxJointHinge* joint = ( dxJointHinge* )j; dUASSERT( joint, "bad joint argument" ); checktype( joint, Hinge ); joint->limot.set( parameter, value ); } dReal dJointGetHingeParam( dJointID j, int parameter ) { dxJointHinge* joint = ( dxJointHinge* )j; dUASSERT( joint, "bad joint argument" ); checktype( joint, Hinge ); return joint->limot.get( parameter ); } dReal dJointGetHingeAngle( dJointID j ) { dxJointHinge* joint = ( dxJointHinge* )j; dAASSERT( joint ); checktype( joint, Hinge ); if ( joint->node[0].body ) { dReal ang = getHingeAngle( joint->node[0].body, joint->node[1].body, joint->axis1, joint->qrel ); if ( joint->flags & dJOINT_REVERSE ) return -ang; else return ang; } else return 0; } dReal dJointGetHingeAngleRate( dJointID j ) { dxJointHinge* joint = ( dxJointHinge* )j; dAASSERT( joint ); checktype( joint, Hinge ); if ( joint->node[0].body ) { dVector3 axis; dMultiply0_331( axis, joint->node[0].body->posr.R, joint->axis1 ); dReal rate = dCalcVectorDot3( axis, joint->node[0].body->avel ); if ( joint->node[1].body ) rate -= dCalcVectorDot3( axis, joint->node[1].body->avel ); if ( joint->flags & dJOINT_REVERSE ) rate = - rate; return rate; } else return 0; } void dJointAddHingeTorque( dJointID j, dReal torque ) { dxJointHinge* joint = ( dxJointHinge* )j; dVector3 axis; dAASSERT( joint ); checktype( joint, Hinge ); if ( joint->flags & dJOINT_REVERSE ) torque = -torque; getAxis( joint, axis, joint->axis1 ); axis[0] *= torque; axis[1] *= torque; axis[2] *= torque; if ( joint->node[0].body != 0 ) dBodyAddTorque( joint->node[0].body, axis[0], axis[1], axis[2] ); if ( joint->node[1].body != 0 ) dBodyAddTorque( joint->node[1].body, -axis[0], -axis[1], -axis[2] ); } dJointType dxJointHinge::type() const { return dJointTypeHinge; } sizeint dxJointHinge::size() const { return sizeof( *this ); } void dxJointHinge::setRelativeValues() { dVector3 vec; dJointGetHingeAnchor(this, vec); setAnchors( this, vec[0], vec[1], vec[2], anchor1, anchor2 ); dJointGetHingeAxis(this, vec); setAxes( this, vec[0], vec[1], vec[2], axis1, axis2 ); computeInitialRelativeRotation(); } /// Compute initial relative rotation body1 -> body2, or env -> body1 void dxJointHinge::computeInitialRelativeRotation() { if ( node[0].body ) { if ( node[1].body ) { dQMultiply1( qrel, node[0].body->q, node[1].body->q ); } else { // set qrel to the transpose of the first body q qrel[0] = node[0].body->q[0]; qrel[1] = -node[0].body->q[1]; qrel[2] = -node[0].body->q[2]; qrel[3] = -node[0].body->q[3]; } } } ode-0.16/ode/src/joints/Makefile.in0000664000175200017520000005150713403272663014065 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @ENABLE_OU_TRUE@am__append_1 = -I$(top_srcdir)/ou/include subdir = ode/src/joints ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/ode/src/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libjoints_la_LIBADD = am_libjoints_la_OBJECTS = joint.lo ball.lo dball.lo dhinge.lo \ transmission.lo hinge.lo slider.lo contact.lo universal.lo \ hinge2.lo fixed.lo null.lo amotor.lo lmotor.lo plane2d.lo \ pu.lo pr.lo piston.lo libjoints_la_OBJECTS = $(am_libjoints_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/ode/src depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) AM_V_CXX = $(am__v_CXX_@AM_V@) am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libjoints_la_SOURCES) DIST_SOURCES = $(libjoints_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CCD_CFLAGS = @CCD_CFLAGS@ CCD_LIBS = @CCD_LIBS@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXTRA_LIBTOOL_LDFLAGS = @EXTRA_LIBTOOL_LDFLAGS@ FGREP = @FGREP@ GL_LIBS = @GL_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSTDCXX = @LIBSTDCXX@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ ODE_PRECISION = @ODE_PRECISION@ ODE_VERSION = @ODE_VERSION@ ODE_VERSION_INFO = @ODE_VERSION_INFO@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ WINDRES = @WINDRES@ X11_CFLAGS = @X11_CFLAGS@ X11_LIBS = @X11_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_WINDRES = @ac_ct_WINDRES@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include \ -I$(top_srcdir)/ode/src -D__ODE__ $(am__append_1) noinst_LTLIBRARIES = libjoints.la libjoints_la_SOURCES = joints.h \ joint.h joint.cpp \ joint_internal.h \ ball.h ball.cpp \ dball.h dball.cpp \ dhinge.h dhinge.cpp \ transmission.h transmission.cpp \ hinge.h hinge.cpp \ slider.h slider.cpp \ contact.h contact.cpp \ universal.h universal.cpp \ hinge2.h hinge2.cpp \ fixed.h fixed.cpp \ null.h null.cpp \ amotor.h amotor.cpp \ lmotor.h lmotor.cpp \ plane2d.h plane2d.cpp \ pu.h pu.cpp \ pr.h pr.cpp \ piston.h piston.cpp all: all-am .SUFFIXES: .SUFFIXES: .cpp .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign ode/src/joints/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign ode/src/joints/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libjoints.la: $(libjoints_la_OBJECTS) $(libjoints_la_DEPENDENCIES) $(EXTRA_libjoints_la_DEPENDENCIES) $(AM_V_CXXLD)$(CXXLINK) $(libjoints_la_OBJECTS) $(libjoints_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amotor.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ball.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/contact.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dball.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dhinge.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fixed.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hinge.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hinge2.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/joint.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmotor.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/null.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/piston.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plane2d.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pu.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/slider.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transmission.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/universal.Plo@am__quote@ .cpp.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cpp.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cpp.lo: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ode-0.16/ode/src/joints/joint.cpp0000664000175200017520000007727313403272463013655 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* design note: the general principle for giving a joint the option of connecting to the static environment (i.e. the absolute frame) is to check the second body (joint->node[1].body), and if it is zero then behave as if its body transform is the identity. */ #include #include #include "config.h" #include "matrix.h" #include "odemath.h" #include "joint.h" #include "joint_internal.h" #include "util.h" extern void addObjectToList( dObject *obj, dObject **first ); dxJoint::dxJoint( dxWorld *w ) : dObject( w ) { //printf("constructing %p\n", this); dIASSERT( w ); flags = 0; node[0].joint = this; node[0].body = 0; node[0].next = 0; node[1].joint = this; node[1].body = 0; node[1].next = 0; dSetZero( lambda, 6 ); addObjectToList( this, ( dObject ** ) &w->firstjoint ); w->nj++; feedback = 0; } dxJoint::~dxJoint() { } /*virtual */ void dxJoint::setRelativeValues() { // Do nothing } bool dxJoint::isEnabled() const { return ( (flags & dJOINT_DISABLED) == 0 && (node[0].body->invMass > 0 || (node[1].body && node[1].body->invMass > 0)) ); } sizeint dxJointGroup::exportJoints(dxJoint **jlist) { sizeint i=0; dxJoint *j = (dxJoint*) m_stack.rewind(); while (j != NULL) { jlist[i++] = j; j = (dxJoint*) (m_stack.next (j->size())); } return i; } void dxJointGroup::freeAll() { m_num = 0; m_stack.freeAll(); } //**************************************************************************** // externs // extern "C" void dBodyAddTorque (dBodyID, dReal fx, dReal fy, dReal fz); // extern "C" void dBodyAddForce (dBodyID, dReal fx, dReal fy, dReal fz); //**************************************************************************** // utility // set three "ball-and-socket" rows in the constraint equation, and the // corresponding right hand side. void setBall( dxJoint *joint, dReal fps, dReal erp, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dVector3 anchor1, dVector3 anchor2 ) { // anchor points in global coordinates with respect to body PORs. dVector3 a1, a2; // set Jacobian J1[dxJoint::GI2_JLX] = 1; J1[rowskip + dxJoint::GI2_JLY] = 1; J1[2 * rowskip + dxJoint::GI2_JLZ] = 1; dMultiply0_331( a1, joint->node[0].body->posr.R, anchor1 ); dSetCrossMatrixMinus( J1 + dxJoint::GI2__JA_MIN, a1, rowskip ); dxBody *b1 = joint->node[1].body; if ( b1 ) { J2[dxJoint::GI2_JLX] = -1; J2[rowskip + dxJoint::GI2_JLY] = -1; J2[2 * rowskip + dxJoint::GI2_JLZ] = -1; dMultiply0_331( a2, b1->posr.R, anchor2 ); dSetCrossMatrixPlus( J2 + dxJoint::GI2__JA_MIN, a2, rowskip ); } // set right hand side dReal k = fps * erp; dxBody *b0 = joint->node[0].body; if ( b1 ) { dReal *currRhsCfm = pairRhsCfm; for ( int j = dSA__MIN; j != dSA__MAX; j++ ) { currRhsCfm[dxJoint::GI2_RHS] = k * ( a2[j] + b1->posr.pos[j] - a1[j] - b0->posr.pos[j] ); currRhsCfm += pairskip; } } else { dReal *currRhsCfm = pairRhsCfm; for ( int j = dSA__MIN; j != dSA__MAX; j++ ) { currRhsCfm[dxJoint::GI2_RHS] = k * ( anchor2[j] - a1[j] - b0->posr.pos[j] ); currRhsCfm += pairskip; } } } // this is like setBall(), except that `axis' is a unit length vector // (in global coordinates) that should be used for the first jacobian // position row (the other two row vectors will be derived from this). // `erp1' is the erp value to use along the axis. void setBall2( dxJoint *joint, dReal fps, dReal erp, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dVector3 anchor1, dVector3 anchor2, dVector3 axis, dReal erp1 ) { // anchor points in global coordinates with respect to body PORs. dVector3 a1, a2; // get vectors normal to the axis. in setBall() axis,q1,q2 is [1 0 0], // [0 1 0] and [0 0 1], which makes everything much easier. dVector3 q1, q2; dPlaneSpace( axis, q1, q2 ); // set Jacobian dCopyVector3(J1 + dxJoint::GI2__JL_MIN, axis); dCopyVector3(J1 + rowskip + dxJoint::GI2__JL_MIN, q1); dCopyVector3(J1 + 2 * rowskip + dxJoint::GI2__JL_MIN, q2); dMultiply0_331( a1, joint->node[0].body->posr.R, anchor1 ); dCalcVectorCross3( J1 + dxJoint::GI2__JA_MIN, a1, axis ); dCalcVectorCross3( J1 + rowskip + dxJoint::GI2__JA_MIN, a1, q1 ); dCalcVectorCross3( J1 + 2 * rowskip + dxJoint::GI2__JA_MIN, a1, q2 ); dxBody *b0 = joint->node[0].body; dAddVectors3(a1, a1, b0->posr.pos); // set right hand side - measure error along (axis,q1,q2) dReal k1 = fps * erp1; dReal k = fps * erp; dxBody *b1 = joint->node[1].body; if ( b1 ) { dCopyNegatedVector3(J2 + dxJoint::GI2__JL_MIN, axis); dCopyNegatedVector3(J2 + rowskip + dxJoint::GI2__JL_MIN, q1); dCopyNegatedVector3(J2 + 2 * rowskip + dxJoint::GI2__JL_MIN, q2); dMultiply0_331( a2, b1->posr.R, anchor2 ); dCalcVectorCross3( J2 + dxJoint::GI2__JA_MIN, axis, a2 ); //== dCalcVectorCross3( J2 + dxJoint::GI2__J2A_MIN, a2, axis ); dNegateVector3( J2 + dxJoint::GI2__J2A_MIN ); dCalcVectorCross3( J2 + rowskip + dxJoint::GI2__JA_MIN, q1, a2 ); //== dCalcVectorCross3( J2 + rowskip + dxJoint::GI2__J2A_MIN, a2, q1 ); dNegateVector3( J2 + rowskip + dxJoint::GI2__J2A_MIN ); dCalcVectorCross3( J2 + 2 * rowskip + dxJoint::GI2__JA_MIN, q2, a2 ); //== dCalcVectorCross3( J2 + 2 * rowskip + dxJoint::GI2__J2A_MIN, a2, q2 ); dNegateVector3( J2 + 2 * rowskip + dxJoint::GI2__J2A_MIN ); dAddVectors3(a2, a2, b1->posr.pos); dVector3 a2_minus_a1; dSubtractVectors3(a2_minus_a1, a2, a1); pairRhsCfm[dxJoint::GI2_RHS] = k1 * dCalcVectorDot3( axis, a2_minus_a1 ); pairRhsCfm[pairskip + dxJoint::GI2_RHS] = k * dCalcVectorDot3( q1, a2_minus_a1 ); pairRhsCfm[2 * pairskip + dxJoint::GI2_RHS] = k * dCalcVectorDot3( q2, a2_minus_a1 ); } else { dVector3 anchor2_minus_a1; dSubtractVectors3(anchor2_minus_a1, anchor2, a1); pairRhsCfm[dxJoint::GI2_RHS] = k1 * dCalcVectorDot3( axis, anchor2_minus_a1 ); pairRhsCfm[pairskip + dxJoint::GI2_RHS] = k * dCalcVectorDot3( q1, anchor2_minus_a1 ); pairRhsCfm[2 * pairskip + dxJoint::GI2_RHS] = k * dCalcVectorDot3( q2, anchor2_minus_a1 ); } } // set three orientation rows in the constraint equation, and the // corresponding right hand side. void setFixedOrientation( dxJoint *joint, dReal fps, dReal erp, int rowskip, dReal *J1, dReal *J2, int pairskip, dReal *pairRhsCfm, dQuaternion qrel ) { // 3 rows to make body rotations equal J1[dxJoint::GI2_JAX] = 1; J1[rowskip + dxJoint::GI2_JAY] = 1; J1[2 * rowskip + dxJoint::GI2_JAZ] = 1; dxBody *b1 = joint->node[1].body; if ( b1 ) { J2[dxJoint::GI2_JAX] = -1; J2[rowskip + dxJoint::GI2_JAY] = -1; J2[2 * rowskip + dxJoint::GI2_JAZ] = -1; } // compute the right hand side. the first three elements will result in // relative angular velocity of the two bodies - this is set to bring them // back into alignment. the correcting angular velocity is // |angular_velocity| = angle/time = erp*theta / stepsize // = (erp*fps) * theta // angular_velocity = |angular_velocity| * u // = (erp*fps) * theta * u // where rotation along unit length axis u by theta brings body 2's frame // to qrel with respect to body 1's frame. using a small angle approximation // for sin(), this gives // angular_velocity = (erp*fps) * 2 * v // where the quaternion of the relative rotation between the two bodies is // q = [cos(theta/2) sin(theta/2)*u] = [s v] // get qerr = relative rotation (rotation error) between two bodies dQuaternion qerr, e; dxBody *b0 = joint->node[0].body; if ( b1 ) { dQuaternion qq; dQMultiply1( qq, b0->q, b1->q ); dQMultiply2( qerr, qq, qrel ); } else { dQMultiply3( qerr, b0->q, qrel ); } if ( qerr[0] < 0 ) { qerr[1] = -qerr[1]; // adjust sign of qerr to make theta small qerr[2] = -qerr[2]; qerr[3] = -qerr[3]; } dMultiply0_331( e, b0->posr.R, qerr + 1 ); // @@@ bad SIMD padding! dReal k_mul_2 = fps * erp * REAL(2.0); pairRhsCfm[dxJoint::GI2_RHS] = k_mul_2 * e[dSA_X]; pairRhsCfm[pairskip + dxJoint::GI2_RHS] = k_mul_2 * e[dSA_Y]; pairRhsCfm[2 * pairskip + dxJoint::GI2_RHS] = k_mul_2 * e[dSA_Z]; } // compute anchor points relative to bodies void setAnchors( dxJoint *j, dReal x, dReal y, dReal z, dVector3 anchor1, dVector3 anchor2 ) { dxBody *b0 = j->node[0].body; if ( b0 ) { dReal q[4]; q[0] = x - b0->posr.pos[0]; q[1] = y - b0->posr.pos[1]; q[2] = z - b0->posr.pos[2]; q[3] = 0; dMultiply1_331( anchor1, b0->posr.R, q ); dxBody *b1 = j->node[1].body; if ( b1 ) { q[0] = x - b1->posr.pos[0]; q[1] = y - b1->posr.pos[1]; q[2] = z - b1->posr.pos[2]; q[3] = 0; dMultiply1_331( anchor2, b1->posr.R, q ); } else { anchor2[0] = x; anchor2[1] = y; anchor2[2] = z; } } anchor1[3] = 0; anchor2[3] = 0; } // compute axes relative to bodies. either axis1 or axis2 can be 0. void setAxes( dxJoint *j, dReal x, dReal y, dReal z, dVector3 axis1, dVector3 axis2 ) { dxBody *b0 = j->node[0].body; if ( b0 ) { dReal q[4]; q[0] = x; q[1] = y; q[2] = z; q[3] = 0; dNormalize3( q ); if ( axis1 ) { dMultiply1_331( axis1, b0->posr.R, q ); axis1[3] = 0; } if ( axis2 ) { dxBody *b1 = j->node[1].body; if ( b1 ) { dMultiply1_331( axis2, b1->posr.R, q ); } else { axis2[0] = x; axis2[1] = y; axis2[2] = z; } axis2[3] = 0; } } } void getAnchor( dxJoint *j, dVector3 result, dVector3 anchor1 ) { dxBody *b0 = j->node[0].body; if ( b0 ) { dMultiply0_331( result, b0->posr.R, anchor1 ); result[0] += b0->posr.pos[0]; result[1] += b0->posr.pos[1]; result[2] += b0->posr.pos[2]; } } void getAnchor2( dxJoint *j, dVector3 result, dVector3 anchor2 ) { dxBody *b1 = j->node[1].body; if ( b1 ) { dMultiply0_331( result, b1->posr.R, anchor2 ); result[0] += b1->posr.pos[0]; result[1] += b1->posr.pos[1]; result[2] += b1->posr.pos[2]; } else { result[0] = anchor2[0]; result[1] = anchor2[1]; result[2] = anchor2[2]; } } void getAxis( dxJoint *j, dVector3 result, dVector3 axis1 ) { dxBody *b0 = j->node[0].body; if ( b0 ) { dMultiply0_331( result, b0->posr.R, axis1 ); } } void getAxis2( dxJoint *j, dVector3 result, dVector3 axis2 ) { dxBody *b1 = j->node[1].body; if ( b1 ) { dMultiply0_331( result, b1->posr.R, axis2 ); } else { result[0] = axis2[0]; result[1] = axis2[1]; result[2] = axis2[2]; } } dReal getHingeAngleFromRelativeQuat( dQuaternion qrel, dVector3 axis ) { // the angle between the two bodies is extracted from the quaternion that // represents the relative rotation between them. recall that a quaternion // q is: // [s,v] = [ cos(theta/2) , sin(theta/2) * u ] // where s is a scalar and v is a 3-vector. u is a unit length axis and // theta is a rotation along that axis. we can get theta/2 by: // theta/2 = atan2 ( sin(theta/2) , cos(theta/2) ) // but we can't get sin(theta/2) directly, only its absolute value, i.e.: // |v| = |sin(theta/2)| * |u| // = |sin(theta/2)| // using this value will have a strange effect. recall that there are two // quaternion representations of a given rotation, q and -q. typically as // a body rotates along the axis it will go through a complete cycle using // one representation and then the next cycle will use the other // representation. this corresponds to u pointing in the direction of the // hinge axis and then in the opposite direction. the result is that theta // will appear to go "backwards" every other cycle. here is a fix: if u // points "away" from the direction of the hinge (motor) axis (i.e. more // than 90 degrees) then use -q instead of q. this represents the same // rotation, but results in the cos(theta/2) value being sign inverted. // extract the angle from the quaternion. cost2 = cos(theta/2), // sint2 = |sin(theta/2)| dReal cost2 = qrel[0]; dReal sint2 = dSqrt( qrel[1] * qrel[1] + qrel[2] * qrel[2] + qrel[3] * qrel[3] ); dReal theta = ( dCalcVectorDot3( qrel + 1, axis ) >= 0 ) ? // @@@ padding assumptions ( 2 * dAtan2( sint2, cost2 ) ) : // if u points in direction of axis ( 2 * dAtan2( sint2, -cost2 ) ); // if u points in opposite direction // the angle we get will be between 0..2*pi, but we want to return angles // between -pi..pi if ( theta > M_PI ) theta -= ( dReal )( 2 * M_PI ); // the angle we've just extracted has the wrong sign theta = -theta; return theta; } // given two bodies (body1,body2), the hinge axis that they are connected by // w.r.t. body1 (axis), and the initial relative orientation between them // (q_initial), return the relative rotation angle. the initial relative // orientation corresponds to an angle of zero. if body2 is 0 then measure the // angle between body1 and the static frame. // // this will not return the correct angle if the bodies rotate along any axis // other than the given hinge axis. dReal getHingeAngle( dxBody *body1, dxBody *body2, dVector3 axis, dQuaternion q_initial ) { // get qrel = relative rotation between the two bodies dQuaternion qrel; if ( body2 ) { dQuaternion qq; dQMultiply1( qq, body1->q, body2->q ); dQMultiply2( qrel, qq, q_initial ); } else { // pretend body2->q is the identity dQMultiply3( qrel, body1->q, q_initial ); } return getHingeAngleFromRelativeQuat( qrel, axis ); } //**************************************************************************** // dxJointLimitMotor void dxJointLimitMotor::init( dxWorld *world ) { vel = 0; fmax = 0; lostop = -dInfinity; histop = dInfinity; fudge_factor = 1; normal_cfm = world->global_cfm; stop_erp = world->global_erp; stop_cfm = world->global_cfm; bounce = 0; limit = 0; limit_err = 0; } void dxJointLimitMotor::set( int num, dReal value ) { switch ( num ) { case dParamLoStop: lostop = value; break; case dParamHiStop: histop = value; break; case dParamVel: vel = value; break; case dParamFMax: if ( value >= 0 ) fmax = value; break; case dParamFudgeFactor: if ( value >= 0 && value <= 1 ) fudge_factor = value; break; case dParamBounce: bounce = value; break; case dParamCFM: normal_cfm = value; break; case dParamStopERP: stop_erp = value; break; case dParamStopCFM: stop_cfm = value; break; } } dReal dxJointLimitMotor::get( int num ) const { switch ( num ) { case dParamLoStop: return lostop; case dParamHiStop: return histop; case dParamVel: return vel; case dParamFMax: return fmax; case dParamFudgeFactor: return fudge_factor; case dParamBounce: return bounce; case dParamCFM: return normal_cfm; case dParamStopERP: return stop_erp; case dParamStopCFM: return stop_cfm; default: return 0; } } bool dxJointLimitMotor::testRotationalLimit( dReal angle ) { if ( angle <= lostop ) { limit = 1; limit_err = angle - lostop; return true; } else if ( angle >= histop ) { limit = 2; limit_err = angle - histop; return true; } else { limit = 0; return false; } } bool dxJointLimitMotor::addLimot( dxJoint *joint, dReal fps, dReal *J1, dReal *J2, dReal *pairRhsCfm, dReal *pairLoHi, const dVector3 ax1, int rotational ) { // if the joint is powered, or has joint limits, add in the extra row int powered = fmax > 0; if ( powered || limit ) { dReal *J1Used = rotational ? J1 + GI2__JA_MIN : J1 + GI2__JL_MIN; dReal *J2Used = rotational ? J2 + GI2__JA_MIN : J2 + GI2__JL_MIN; dCopyVector3(J1Used, ax1); dxBody *b1 = joint->node[1].body; if ( b1 ) { dCopyNegatedVector3(J2Used, ax1); } // linear limot torque decoupling step: // // if this is a linear limot (e.g. from a slider), we have to be careful // that the linear constraint forces (+/- ax1) applied to the two bodies // do not create a torque couple. in other words, the points that the // constraint force is applied at must lie along the same ax1 axis. // a torque couple will result in powered or limited slider-jointed free // bodies from gaining angular momentum. // the solution used here is to apply the constraint forces at the point // halfway between the body centers. there is no penalty (other than an // extra tiny bit of computation) in doing this adjustment. note that we // only need to do this if the constraint connects two bodies. dVector3 ltd = {0,0,0}; // Linear Torque Decoupling vector (a torque) if ( !rotational && b1 ) { dxBody *b0 = joint->node[0].body; dVector3 c; c[0] = REAL( 0.5 ) * ( b1->posr.pos[0] - b0->posr.pos[0] ); c[1] = REAL( 0.5 ) * ( b1->posr.pos[1] - b0->posr.pos[1] ); c[2] = REAL( 0.5 ) * ( b1->posr.pos[2] - b0->posr.pos[2] ); dCalcVectorCross3( ltd, c, ax1 ); dCopyVector3(J1 + dxJoint::GI2__JA_MIN, ltd); dCopyVector3(J2 + dxJoint::GI2__JA_MIN, ltd); } // if we're limited low and high simultaneously, the joint motor is // ineffective if ( limit && ( lostop == histop ) ) powered = 0; if ( powered ) { pairRhsCfm[GI2_CFM] = normal_cfm; if ( ! limit ) { pairRhsCfm[GI2_RHS] = vel; pairLoHi[GI2_LO] = -fmax; pairLoHi[GI2_HI] = fmax; } else { // the joint is at a limit, AND is being powered. if the joint is // being powered into the limit then we apply the maximum motor force // in that direction, because the motor is working against the // immovable limit. if the joint is being powered away from the limit // then we have problems because actually we need *two* lcp // constraints to handle this case. so we fake it and apply some // fraction of the maximum force. the fraction to use can be set as // a fudge factor. dReal fm = fmax; if (( vel > 0 ) || ( vel == 0 && limit == 2 ) ) fm = -fm; // if we're powering away from the limit, apply the fudge factor if (( limit == 1 && vel > 0 ) || ( limit == 2 && vel < 0 ) ) fm *= fudge_factor; dReal fm_ax1_0 = fm*ax1[0], fm_ax1_1 = fm*ax1[1], fm_ax1_2 = fm*ax1[2]; dxBody *b0 = joint->node[0].body; dxWorldProcessContext *world_process_context = b0->world->unsafeGetWorldProcessingContext(); world_process_context->LockForAddLimotSerialization(); if ( rotational ) { dxBody *b1 = joint->node[1].body; if ( b1 != NULL ) { dBodyAddTorque( b1, fm_ax1_0, fm_ax1_1, fm_ax1_2 ); } dBodyAddTorque( b0, -fm_ax1_0, -fm_ax1_1, -fm_ax1_2 ); } else { dxBody *b1 = joint->node[1].body; if ( b1 != NULL ) { // linear limot torque decoupling step: refer to above discussion dReal neg_fm_ltd_0 = -fm*ltd[0], neg_fm_ltd_1 = -fm*ltd[1], neg_fm_ltd_2 = -fm*ltd[2]; dBodyAddTorque( b0, neg_fm_ltd_0, neg_fm_ltd_1, neg_fm_ltd_2 ); dBodyAddTorque( b1, neg_fm_ltd_0, neg_fm_ltd_1, neg_fm_ltd_2 ); dBodyAddForce( b1, fm_ax1_0, fm_ax1_1, fm_ax1_2 ); } dBodyAddForce( b0, -fm_ax1_0, -fm_ax1_1, -fm_ax1_2 ); } world_process_context->UnlockForAddLimotSerialization(); } } if ( limit ) { dReal k = fps * stop_erp; pairRhsCfm[GI2_RHS] = -k * limit_err; pairRhsCfm[GI2_CFM] = stop_cfm; if ( lostop == histop ) { // limited low and high simultaneously pairLoHi[GI2_LO] = -dInfinity; pairLoHi[GI2_HI] = dInfinity; } else { if ( limit == 1 ) { // low limit pairLoHi[GI2_LO] = 0; pairLoHi[GI2_HI] = dInfinity; } else { // high limit pairLoHi[GI2_LO] = -dInfinity; pairLoHi[GI2_HI] = 0; } // deal with bounce if ( bounce > 0 ) { // calculate joint velocity dReal vel; if ( rotational ) { vel = dCalcVectorDot3( joint->node[0].body->avel, ax1 ); if ( joint->node[1].body ) vel -= dCalcVectorDot3( joint->node[1].body->avel, ax1 ); } else { vel = dCalcVectorDot3( joint->node[0].body->lvel, ax1 ); if ( joint->node[1].body ) vel -= dCalcVectorDot3( joint->node[1].body->lvel, ax1 ); } // only apply bounce if the velocity is incoming, and if the // resulting c[] exceeds what we already have. if ( limit == 1 ) { // low limit if ( vel < 0 ) { dReal newc = -bounce * vel; if ( newc > pairRhsCfm[GI2_RHS] ) pairRhsCfm[GI2_RHS] = newc; } } else { // high limit - all those computations are reversed if ( vel > 0 ) { dReal newc = -bounce * vel; if ( newc < pairRhsCfm[GI2_RHS] ) pairRhsCfm[GI2_RHS] = newc; } } } } } return true; } return false; } /** This function generalizes the "linear limot torque decoupling" in addLimot to use anchor points provided by the caller. This makes it so that the appropriate torques are applied to a body when it's being linearly motored or limited using anchor points that aren't at the center of mass. pt1 and pt2 are centered in body coordinates but use global directions. I.e., they are conveniently found within joint code with: getAxis(joint,pt1,anchor1); getAxis2(joint,pt2,anchor2); */ bool dxJointLimitMotor::addTwoPointLimot( dxJoint *joint, dReal fps, dReal *J1, dReal *J2, dReal *pairRhsCfm, dReal *pairLoHi, const dVector3 ax1, const dVector3 pt1, const dVector3 pt2 ) { // if the joint is powered, or has joint limits, add in the extra row int powered = fmax > 0; if ( powered || limit ) { // Set the linear portion dCopyVector3(J1 + GI2__JL_MIN, ax1); // Set the angular portion (to move the linear constraint // away from the center of mass). dCalcVectorCross3(J1 + GI2__JA_MIN, pt1, ax1); // Set the constraints for the second body if ( joint->node[1].body ) { dCopyNegatedVector3(J2 + GI2__JL_MIN, ax1); dCalcVectorCross3(J2 + GI2__JA_MIN, pt2, J2 + GI2__JL_MIN); } // if we're limited low and high simultaneously, the joint motor is // ineffective if ( limit && ( lostop == histop ) ) powered = 0; if ( powered ) { pairRhsCfm[GI2_CFM] = normal_cfm; if ( ! limit ) { pairRhsCfm[GI2_RHS] = vel; pairLoHi[GI2_LO] = -fmax; pairLoHi[GI2_HI] = fmax; } else { // the joint is at a limit, AND is being powered. if the joint is // being powered into the limit then we apply the maximum motor force // in that direction, because the motor is working against the // immovable limit. if the joint is being powered away from the limit // then we have problems because actually we need *two* lcp // constraints to handle this case. so we fake it and apply some // fraction of the maximum force. the fraction to use can be set as // a fudge factor. dReal fm = fmax; if (( vel > 0 ) || ( vel == 0 && limit == 2 ) ) fm = -fm; // if we're powering away from the limit, apply the fudge factor if (( limit == 1 && vel > 0 ) || ( limit == 2 && vel < 0 ) ) fm *= fudge_factor; const dReal* tAx1 = J1 + GI2__JA_MIN; dBodyAddForce( joint->node[0].body, -fm*ax1[dSA_X], -fm*ax1[dSA_Y], -fm*ax1[dSA_Z] ); dBodyAddTorque( joint->node[0].body, -fm*tAx1[dSA_X], -fm*tAx1[dSA_Y], -fm*tAx1[dSA_Z] ); if ( joint->node[1].body ) { const dReal* tAx2 = J2 + GI2__JA_MIN; dBodyAddForce( joint->node[1].body, fm*ax1[dSA_X], fm*ax1[dSA_Y], fm*ax1[dSA_Z] ); dBodyAddTorque( joint->node[1].body, -fm*tAx2[dSA_X], -fm*tAx2[dSA_Y], -fm*tAx2[dSA_Z] ); } } } if ( limit ) { dReal k = fps * stop_erp; pairRhsCfm[GI2_RHS] = -k * limit_err; pairRhsCfm[GI2_CFM] = stop_cfm; if ( lostop == histop ) { // limited low and high simultaneously pairLoHi[GI2_LO] = -dInfinity; pairLoHi[GI2_HI] = dInfinity; } else { if ( limit == 1 ) { // low limit pairLoHi[GI2_LO] = 0; pairLoHi[GI2_HI] = dInfinity; } else { // high limit pairLoHi[GI2_LO] = -dInfinity; pairLoHi[GI2_HI] = 0; } // deal with bounce if ( bounce > 0 ) { // calculate relative velocity of the two anchor points dReal vel = dCalcVectorDot3( joint->node[0].body->lvel, J1 + GI2__JL_MIN ) + dCalcVectorDot3( joint->node[0].body->avel, J1 + GI2__JA_MIN ); if (joint->node[1].body) { vel += dCalcVectorDot3( joint->node[1].body->lvel, J2 + GI2__JL_MIN ) + dCalcVectorDot3( joint->node[1].body->avel, J2 + GI2__JA_MIN ); } // only apply bounce if the velocity is incoming, and if the // resulting c[] exceeds what we already have. if ( limit == 1 ) { // low limit if ( vel < 0 ) { dReal newc = -bounce * vel; if ( newc > pairRhsCfm[GI2_RHS] ) pairRhsCfm[GI2_RHS] = newc; } } else { // high limit - all those computations are reversed if ( vel > 0 ) { dReal newc = -bounce * vel; if ( newc < pairRhsCfm[GI2_RHS] ) pairRhsCfm[GI2_RHS] = newc; } } } } } return true; } return false; } // Local Variables: // mode:c++ // c-basic-offset:4 // End: ode-0.16/ode/src/capsule.cpp0000664000175200017520000003701313403272463012644 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* standard ODE geometry primitives: public API and pairwise collision functions. the rule is that only the low level primitive collision functions should set dContactGeom::g1 and dContactGeom::g2. */ #include #include #include #include "config.h" #include "matrix.h" #include "odemath.h" #include "collision_kernel.h" #include "collision_std.h" #include "collision_util.h" #ifdef _MSC_VER #pragma warning(disable:4291) // for VC++, no complaints about "no matching operator delete found" #endif //**************************************************************************** // capped cylinder public API dxCapsule::dxCapsule (dSpaceID space, dReal _radius, dReal _length) : dxGeom (space,1) { dAASSERT (_radius >= 0 && _length >= 0); type = dCapsuleClass; radius = _radius; lz = _length; updateZeroSizedFlag(!_radius/* || !_length -- zero length capsule is not a zero sized capsule*/); } void dxCapsule::computeAABB() { const dMatrix3& R = final_posr->R; const dVector3& pos = final_posr->pos; dReal xrange = dFabs(R[2] * lz) * REAL(0.5) + radius; dReal yrange = dFabs(R[6] * lz) * REAL(0.5) + radius; dReal zrange = dFabs(R[10] * lz) * REAL(0.5) + radius; aabb[0] = pos[0] - xrange; aabb[1] = pos[0] + xrange; aabb[2] = pos[1] - yrange; aabb[3] = pos[1] + yrange; aabb[4] = pos[2] - zrange; aabb[5] = pos[2] + zrange; } dGeomID dCreateCapsule (dSpaceID space, dReal radius, dReal length) { return new dxCapsule (space,radius,length); } void dGeomCapsuleSetParams (dGeomID g, dReal radius, dReal length) { dUASSERT (g && g->type == dCapsuleClass,"argument not a ccylinder"); dAASSERT (radius >= 0 && length >= 0); dxCapsule *c = (dxCapsule*) g; c->radius = radius; c->lz = length; c->updateZeroSizedFlag(!radius/* || !length -- zero length capsule is not a zero sized capsule*/); dGeomMoved (g); } void dGeomCapsuleGetParams (dGeomID g, dReal *radius, dReal *length) { dUASSERT (g && g->type == dCapsuleClass,"argument not a ccylinder"); dxCapsule *c = (dxCapsule*) g; *radius = c->radius; *length = c->lz; } dReal dGeomCapsulePointDepth (dGeomID g, dReal x, dReal y, dReal z) { dUASSERT (g && g->type == dCapsuleClass,"argument not a ccylinder"); g->recomputePosr(); dxCapsule *c = (dxCapsule*) g; const dReal* R = g->final_posr->R; const dReal* pos = g->final_posr->pos; dVector3 a; a[0] = x - pos[0]; a[1] = y - pos[1]; a[2] = z - pos[2]; dReal beta = dCalcVectorDot3_14(a,R+2); dReal lz2 = c->lz*REAL(0.5); if (beta < -lz2) beta = -lz2; else if (beta > lz2) beta = lz2; a[0] = c->final_posr->pos[0] + beta*R[0*4+2]; a[1] = c->final_posr->pos[1] + beta*R[1*4+2]; a[2] = c->final_posr->pos[2] + beta*R[2*4+2]; return c->radius - dSqrt ((x-a[0])*(x-a[0]) + (y-a[1])*(y-a[1]) + (z-a[2])*(z-a[2])); } int dCollideCapsuleSphere (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) { dIASSERT (skip >= (int)sizeof(dContactGeom)); dIASSERT (o1->type == dCapsuleClass); dIASSERT (o2->type == dSphereClass); dIASSERT ((flags & NUMC_MASK) >= 1); dxCapsule *ccyl = (dxCapsule*) o1; dxSphere *sphere = (dxSphere*) o2; contact->g1 = o1; contact->g2 = o2; contact->side1 = -1; contact->side2 = -1; // find the point on the cylinder axis that is closest to the sphere dReal alpha = o1->final_posr->R[2] * (o2->final_posr->pos[0] - o1->final_posr->pos[0]) + o1->final_posr->R[6] * (o2->final_posr->pos[1] - o1->final_posr->pos[1]) + o1->final_posr->R[10] * (o2->final_posr->pos[2] - o1->final_posr->pos[2]); dReal lz2 = ccyl->lz * REAL(0.5); if (alpha > lz2) alpha = lz2; if (alpha < -lz2) alpha = -lz2; // collide the spheres dVector3 p; p[0] = o1->final_posr->pos[0] + alpha * o1->final_posr->R[2]; p[1] = o1->final_posr->pos[1] + alpha * o1->final_posr->R[6]; p[2] = o1->final_posr->pos[2] + alpha * o1->final_posr->R[10]; return dCollideSpheres (p,ccyl->radius,o2->final_posr->pos,sphere->radius,contact); } int dCollideCapsuleBox (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) { dIASSERT (skip >= (int)sizeof(dContactGeom)); dIASSERT (o1->type == dCapsuleClass); dIASSERT (o2->type == dBoxClass); dIASSERT ((flags & NUMC_MASK) >= 1); dxCapsule *cyl = (dxCapsule*) o1; dxBox *box = (dxBox*) o2; contact->g1 = o1; contact->g2 = o2; contact->side1 = -1; contact->side2 = -1; // get p1,p2 = cylinder axis endpoints, get radius dVector3 p1,p2; dReal clen = cyl->lz * REAL(0.5); p1[0] = o1->final_posr->pos[0] + clen * o1->final_posr->R[2]; p1[1] = o1->final_posr->pos[1] + clen * o1->final_posr->R[6]; p1[2] = o1->final_posr->pos[2] + clen * o1->final_posr->R[10]; p2[0] = o1->final_posr->pos[0] - clen * o1->final_posr->R[2]; p2[1] = o1->final_posr->pos[1] - clen * o1->final_posr->R[6]; p2[2] = o1->final_posr->pos[2] - clen * o1->final_posr->R[10]; dReal radius = cyl->radius; // copy out box center, rotation matrix, and side array dReal *c = o2->final_posr->pos; dReal *R = o2->final_posr->R; const dReal *side = box->side; // get the closest point between the cylinder axis and the box dVector3 pl,pb; dClosestLineBoxPoints (p1,p2,c,R,side,pl,pb); // if the capsule is penetrated further than radius // then pl and pb are equal (up to mindist) -> unknown normal // use normal vector of closest box surface #ifdef dSINGLE dReal mindist = REAL(1e-6); #else dReal mindist = REAL(1e-15); #endif if (dCalcPointsDistance3(pl, pb)lz + radiusMul2}; int num = dBoxBox (c, R, side, o1->final_posr->pos, o1->final_posr->R, capboxside, normal, &depth, &code, flags, contact, skip); for (int i=0; inormal[0] = normal[0]; currContact->normal[1] = normal[1]; currContact->normal[2] = normal[2]; currContact->g1 = o1; currContact->g2 = o2; currContact->side1 = -1; currContact->side2 = -1; } return num; } else { // generate contact point return dCollideSpheres (pl,radius,pb,0,contact); } } int dCollideCapsuleCapsule (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) { dIASSERT (skip >= (int)sizeof(dContactGeom)); dIASSERT (o1->type == dCapsuleClass); dIASSERT (o2->type == dCapsuleClass); dIASSERT ((flags & NUMC_MASK) >= 1); int i; const dReal tolerance = REAL(1e-5); dxCapsule *cyl1 = (dxCapsule*) o1; dxCapsule *cyl2 = (dxCapsule*) o2; contact->g1 = o1; contact->g2 = o2; contact->side1 = -1; contact->side2 = -1; // copy out some variables, for convenience dReal lz1 = cyl1->lz * REAL(0.5); dReal lz2 = cyl2->lz * REAL(0.5); dReal *pos1 = o1->final_posr->pos; dReal *pos2 = o2->final_posr->pos; dReal axis1[3],axis2[3]; axis1[0] = o1->final_posr->R[2]; axis1[1] = o1->final_posr->R[6]; axis1[2] = o1->final_posr->R[10]; axis2[0] = o2->final_posr->R[2]; axis2[1] = o2->final_posr->R[6]; axis2[2] = o2->final_posr->R[10]; // if the cylinder axes are close to parallel, we'll try to detect up to // two contact points along the body of the cylinder. if we can't find any // points then we'll fall back to the closest-points algorithm. note that // we are not treating this special case for reasons of degeneracy, but // because we want two contact points in some situations. the closet-points // algorithm is robust in all casts, but it can return only one contact. dVector3 sphere1,sphere2; dReal a1a2 = dCalcVectorDot3 (axis1,axis2); dReal det = REAL(1.0)-a1a2*a1a2; if (det < tolerance) { // the cylinder axes (almost) parallel, so we will generate up to two // contacts. alpha1 and alpha2 (line position parameters) are related by: // alpha2 = alpha1 + (pos1-pos2)'*axis1 (if axis1==axis2) // or alpha2 = -(alpha1 + (pos1-pos2)'*axis1) (if axis1==-axis2) // first compute where the two cylinders overlap in alpha1 space: if (a1a2 < 0) { axis2[0] = -axis2[0]; axis2[1] = -axis2[1]; axis2[2] = -axis2[2]; } dReal q[3]; for (i=0; i<3; i++) q[i] = pos1[i]-pos2[i]; dReal k = dCalcVectorDot3 (axis1,q); dReal a1lo = -lz1; dReal a1hi = lz1; dReal a2lo = -lz2 - k; dReal a2hi = lz2 - k; dReal lo = (a1lo > a2lo) ? a1lo : a2lo; dReal hi = (a1hi < a2hi) ? a1hi : a2hi; if (lo <= hi) { int num_contacts = flags & NUMC_MASK; if (num_contacts >= 2 && lo < hi) { // generate up to two contacts. if one of those contacts is // not made, fall back on the one-contact strategy. for (i=0; i<3; i++) sphere1[i] = pos1[i] + lo*axis1[i]; for (i=0; i<3; i++) sphere2[i] = pos2[i] + (lo+k)*axis2[i]; int n1 = dCollideSpheres (sphere1,cyl1->radius, sphere2,cyl2->radius,contact); if (n1) { for (i=0; i<3; i++) sphere1[i] = pos1[i] + hi*axis1[i]; for (i=0; i<3; i++) sphere2[i] = pos2[i] + (hi+k)*axis2[i]; dContactGeom *c2 = CONTACT(contact,skip); int n2 = dCollideSpheres (sphere1,cyl1->radius, sphere2,cyl2->radius, c2); if (n2) { c2->g1 = o1; c2->g2 = o2; c2->side1 = -1; c2->side2 = -1; return 2; } } } // just one contact to generate, so put it in the middle of // the range dReal alpha1 = (lo + hi) * REAL(0.5); dReal alpha2 = alpha1 + k; for (i=0; i<3; i++) sphere1[i] = pos1[i] + alpha1*axis1[i]; for (i=0; i<3; i++) sphere2[i] = pos2[i] + alpha2*axis2[i]; return dCollideSpheres (sphere1,cyl1->radius, sphere2,cyl2->radius,contact); } } // use the closest point algorithm dVector3 a1,a2,b1,b2; a1[0] = o1->final_posr->pos[0] + axis1[0]*lz1; a1[1] = o1->final_posr->pos[1] + axis1[1]*lz1; a1[2] = o1->final_posr->pos[2] + axis1[2]*lz1; a2[0] = o1->final_posr->pos[0] - axis1[0]*lz1; a2[1] = o1->final_posr->pos[1] - axis1[1]*lz1; a2[2] = o1->final_posr->pos[2] - axis1[2]*lz1; b1[0] = o2->final_posr->pos[0] + axis2[0]*lz2; b1[1] = o2->final_posr->pos[1] + axis2[1]*lz2; b1[2] = o2->final_posr->pos[2] + axis2[2]*lz2; b2[0] = o2->final_posr->pos[0] - axis2[0]*lz2; b2[1] = o2->final_posr->pos[1] - axis2[1]*lz2; b2[2] = o2->final_posr->pos[2] - axis2[2]*lz2; dClosestLineSegmentPoints (a1,a2,b1,b2,sphere1,sphere2); return dCollideSpheres (sphere1,cyl1->radius,sphere2,cyl2->radius,contact); } int dCollideCapsulePlane (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) { dIASSERT (skip >= (int)sizeof(dContactGeom)); dIASSERT (o1->type == dCapsuleClass); dIASSERT (o2->type == dPlaneClass); dIASSERT ((flags & NUMC_MASK) >= 1); dxCapsule *ccyl = (dxCapsule*) o1; dxPlane *plane = (dxPlane*) o2; // collide the deepest capping sphere with the plane dReal sign = (dCalcVectorDot3_14 (plane->p,o1->final_posr->R+2) > 0) ? REAL(-1.0) : REAL(1.0); dVector3 p; p[0] = o1->final_posr->pos[0] + o1->final_posr->R[2] * ccyl->lz * REAL(0.5) * sign; p[1] = o1->final_posr->pos[1] + o1->final_posr->R[6] * ccyl->lz * REAL(0.5) * sign; p[2] = o1->final_posr->pos[2] + o1->final_posr->R[10] * ccyl->lz * REAL(0.5) * sign; dReal k = dCalcVectorDot3 (p,plane->p); dReal depth = plane->p[3] - k + ccyl->radius; if (depth < 0) return 0; contact->normal[0] = plane->p[0]; contact->normal[1] = plane->p[1]; contact->normal[2] = plane->p[2]; contact->pos[0] = p[0] - plane->p[0] * ccyl->radius; contact->pos[1] = p[1] - plane->p[1] * ccyl->radius; contact->pos[2] = p[2] - plane->p[2] * ccyl->radius; contact->depth = depth; int ncontacts = 1; if ((flags & NUMC_MASK) >= 2) { // collide the other capping sphere with the plane p[0] = o1->final_posr->pos[0] - o1->final_posr->R[2] * ccyl->lz * REAL(0.5) * sign; p[1] = o1->final_posr->pos[1] - o1->final_posr->R[6] * ccyl->lz * REAL(0.5) * sign; p[2] = o1->final_posr->pos[2] - o1->final_posr->R[10] * ccyl->lz * REAL(0.5) * sign; k = dCalcVectorDot3 (p,plane->p); depth = plane->p[3] - k + ccyl->radius; if (depth >= 0) { dContactGeom *c2 = CONTACT(contact,skip); c2->normal[0] = plane->p[0]; c2->normal[1] = plane->p[1]; c2->normal[2] = plane->p[2]; c2->pos[0] = p[0] - plane->p[0] * ccyl->radius; c2->pos[1] = p[1] - plane->p[1] * ccyl->radius; c2->pos[2] = p[2] - plane->p[2] * ccyl->radius; c2->depth = depth; ncontacts = 2; } } for (int i=0; i < ncontacts; i++) { dContactGeom *currContact = CONTACT(contact,i*skip); currContact->g1 = o1; currContact->g2 = o2; currContact->side1 = -1; currContact->side2 = -1; } return ncontacts; } ode-0.16/ode/src/collision_util.h0000664000175200017520000002442013403272463013703 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* some useful collision utility stuff. */ #ifndef _ODE_COLLISION_UTIL_H_ #define _ODE_COLLISION_UTIL_H_ #include #include #include #include "odemath.h" // given a pointer `p' to a dContactGeom, return the dContactGeom at // p + skip bytes. #define CONTACT(p,skip) ((dContactGeom*) (((char*)p) + (skip))) #if 1 #include "collision_kernel.h" // Fetches a contact static inline dContactGeom* SAFECONTACT(int Flags, dContactGeom* Contacts, int Index, int Stride){ dIASSERT(Index >= 0 && Index < (Flags & NUMC_MASK)); return ((dContactGeom*)(((char*)Contacts) + (Index * Stride))); } #endif // if the spheres (p1,r1) and (p2,r2) collide, set the contact `c' and // return 1, else return 0. int dCollideSpheres (dVector3 p1, dReal r1, dVector3 p2, dReal r2, dContactGeom *c); // given two lines // qa = pa + alpha* ua // qb = pb + beta * ub // where pa,pb are two points, ua,ub are two unit length vectors, and alpha, // beta go from [-inf,inf], return alpha and beta such that qa and qb are // as close as possible void dLineClosestApproach (const dVector3 pa, const dVector3 ua, const dVector3 pb, const dVector3 ub, dReal *alpha, dReal *beta); // given a line segment p1-p2 and a box (center 'c', rotation 'R', side length // vector 'side'), compute the points of closest approach between the box // and the line. return these points in 'lret' (the point on the line) and // 'bret' (the point on the box). if the line actually penetrates the box // then the solution is not unique, but only one solution will be returned. // in this case the solution points will coincide. void dClosestLineBoxPoints (const dVector3 p1, const dVector3 p2, const dVector3 c, const dMatrix3 R, const dVector3 side, dVector3 lret, dVector3 bret); // 20 Apr 2004 // Start code by Nguyen Binh int dClipEdgeToPlane(dVector3 &vEpnt0, dVector3 &vEpnt1, const dVector4& plPlane); // clip polygon with plane and generate new polygon points void dClipPolyToPlane(const dVector3 avArrayIn[], const int ctIn, dVector3 avArrayOut[], int &ctOut, const dVector4 &plPlane ); void dClipPolyToCircle(const dVector3 avArrayIn[], const int ctIn, dVector3 avArrayOut[], int &ctOut, const dVector4 &plPlane ,dReal fRadius); // Some vector math static inline void dVector3Subtract(const dVector3& a,const dVector3& b,dVector3& c) { dSubtractVectors3(c, a, b); } static inline void dVector3Scale(dVector3& a,dReal nScale) { dScaleVector3(a, nScale); } static inline void dVector3Add(const dVector3& a,const dVector3& b,dVector3& c) { dAddVectors3(c, a, b); } static inline void dVector3Copy(const dVector3& a,dVector3& c) { dCopyVector3(c, a); } static inline void dVector4Copy(const dVector4& a,dVector4& c) { dCopyVector4(c, a); } static inline void dVector3Cross(const dVector3& a,const dVector3& b,dVector3& c) { dCalcVectorCross3(c, a, b); } static inline dReal dVector3Length(const dVector3& a) { return dCalcVectorLength3(a); } static inline dReal dVector3LengthSquare(const dVector3& a) { return dCalcVectorLengthSquare3(a); } static inline dReal dVector3Dot(const dVector3& a,const dVector3& b) { return dCalcVectorDot3(a, b); } static inline void dVector3Inv(dVector3& a) { dNegateVector3(a); } static inline void dMat3GetCol(const dMatrix3& m,const int col, dVector3& v) { dGetMatrixColumn3(v, m, col); } static inline void dVector3CrossMat3Col(const dMatrix3& m,const int col,const dVector3& v,dVector3& r) { dCalcVectorCross3_114(r, v, m + col); } static inline void dMat3ColCrossVector3(const dMatrix3& m,const int col,const dVector3& v,dVector3& r) { dCalcVectorCross3_141(r, m + col, v); } static inline void dMultiplyMat3Vec3(const dMatrix3& m,const dVector3& v, dVector3& r) { dMultiply0_331(r, m, v); } static inline dReal dPointPlaneDistance(const dVector3& point,const dVector4& plane) { return (plane[0]*point[0] + plane[1]*point[1] + plane[2]*point[2] + plane[3]); } static inline void dConstructPlane(const dVector3& normal,const dReal& distance, dVector4& plane) { plane[0] = normal[0]; plane[1] = normal[1]; plane[2] = normal[2]; plane[3] = distance; } static inline void dMatrix3Copy(const dReal* source,dMatrix3& dest) { dCopyMatrix4x3(dest, source); } static inline dReal dMatrix3Det( const dMatrix3& mat ) { dReal det; det = mat[0] * ( mat[5]*mat[10] - mat[9]*mat[6] ) - mat[1] * ( mat[4]*mat[10] - mat[8]*mat[6] ) + mat[2] * ( mat[4]*mat[9] - mat[8]*mat[5] ); return( det ); } static inline void dMatrix3Inv( const dMatrix3& ma, dMatrix3& dst ) { dReal det = dMatrix3Det( ma ); if ( dFabs( det ) < REAL(0.0005) ) { dRSetIdentity( dst ); return; } double detRecip = REAL(1.0) / det; dst[0] = (dReal)(( ma[5]*ma[10] - ma[6]*ma[9] ) * detRecip); dst[1] = (dReal)(( ma[9]*ma[2] - ma[1]*ma[10] ) * detRecip); dst[2] = (dReal)(( ma[1]*ma[6] - ma[5]*ma[2] ) * detRecip); dst[4] = (dReal)(( ma[6]*ma[8] - ma[4]*ma[10] ) * detRecip); dst[5] = (dReal)(( ma[0]*ma[10] - ma[8]*ma[2] ) * detRecip); dst[6] = (dReal)(( ma[4]*ma[2] - ma[0]*ma[6] ) * detRecip); dst[8] = (dReal)(( ma[4]*ma[9] - ma[8]*ma[5] ) * detRecip); dst[9] = (dReal)(( ma[8]*ma[1] - ma[0]*ma[9] ) * detRecip); dst[10] = (dReal)(( ma[0]*ma[5] - ma[1]*ma[4] ) * detRecip); } static inline void dQuatTransform(const dQuaternion& quat,const dVector3& source,dVector3& dest) { // Nguyen Binh : this code seem to be the fastest. dReal x0 = source[0] * quat[0] + source[2] * quat[2] - source[1] * quat[3]; dReal x1 = source[1] * quat[0] + source[0] * quat[3] - source[2] * quat[1]; dReal x2 = source[2] * quat[0] + source[1] * quat[1] - source[0] * quat[2]; dReal x3 = source[0] * quat[1] + source[1] * quat[2] + source[2] * quat[3]; dest[0] = quat[0] * x0 + quat[1] * x3 + quat[2] * x2 - quat[3] * x1; dest[1] = quat[0] * x1 + quat[2] * x3 + quat[3] * x0 - quat[1] * x2; dest[2] = quat[0] * x2 + quat[3] * x3 + quat[1] * x1 - quat[2] * x0; /* // nVidia SDK implementation dVector3 uv, uuv; dVector3 qvec; qvec[0] = quat[1]; qvec[1] = quat[2]; qvec[2] = quat[3]; dVector3Cross(qvec,source,uv); dVector3Cross(qvec,uv,uuv); dVector3Scale(uv,REAL(2.0)*quat[0]); dVector3Scale(uuv,REAL(2.0)); dest[0] = source[0] + uv[0] + uuv[0]; dest[1] = source[1] + uv[1] + uuv[1]; dest[2] = source[2] + uv[2] + uuv[2]; */ } static inline void dQuatInvTransform(const dQuaternion& quat,const dVector3& source,dVector3& dest) { dReal norm = quat[0]*quat[0] + quat[1]*quat[1] + quat[2]*quat[2] + quat[3]*quat[3]; if (norm > REAL(0.0)) { dQuaternion invQuat; invQuat[0] = quat[0] / norm; invQuat[1] = -quat[1] / norm; invQuat[2] = -quat[2] / norm; invQuat[3] = -quat[3] / norm; dQuatTransform(invQuat,source,dest); } else { // Singular -> return identity dVector3Copy(source,dest); } } static inline void dGetEulerAngleFromRot(const dMatrix3& mRot,dReal& rX,dReal& rY,dReal& rZ) { rY = asin(mRot[0 * 4 + 2]); if (rY < M_PI /2) { if (rY > -M_PI /2) { rX = atan2(-mRot[1*4 + 2], mRot[2*4 + 2]); rZ = atan2(-mRot[0*4 + 1], mRot[0*4 + 0]); } else { // not unique rX = -atan2(mRot[1*4 + 0], mRot[1*4 + 1]); rZ = REAL(0.0); } } else { // not unique rX = atan2(mRot[1*4 + 0], mRot[1*4 + 1]); rZ = REAL(0.0); } } static inline void dQuatInv(const dQuaternion& source, dQuaternion& dest) { dReal norm = source[0]*source[0] + source[1]*source[1] + source[2]*source[2] + source[3]*source[3]; if (norm > 0.0f) { dReal neg_norm_recip = -REAL(1.0) / norm; dest[0] = -source[0] * neg_norm_recip; dest[1] = source[1] * neg_norm_recip; dest[2] = source[2] * neg_norm_recip; dest[3] = source[3] * neg_norm_recip; } else { // Singular -> return identity dest[0] = REAL(1.0); dest[1] = REAL(0.0); dest[2] = REAL(0.0); dest[3] = REAL(0.0); } } // Finds barycentric static inline void GetPointFromBarycentric(const dVector3 dv[3], dReal u, dReal v, dVector3 Out){ dReal w = REAL(1.0) - u - v; Out[0] = (dv[0][0] * w) + (dv[1][0] * u) + (dv[2][0] * v); Out[1] = (dv[0][1] * w) + (dv[1][1] * u) + (dv[2][1] * v); Out[2] = (dv[0][2] * w) + (dv[1][2] * u) + (dv[2][2] * v); Out[3] = (dv[0][3] * w) + (dv[1][3] * u) + (dv[2][3] * v); } #endif ode-0.16/ode/src/collision_transform.cpp0000664000175200017520000001631613403272463015301 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* geom transform */ #include #include #include "config.h" #include "matrix.h" #include "odemath.h" #include "collision_transform.h" #include "collision_util.h" #ifdef _MSC_VER #pragma warning(disable:4291) // for VC++, no complaints about "no matching operator delete found" #endif //**************************************************************************** // dxGeomTransform class struct dxGeomTransform : public dxGeom { dxGeom *obj; // object that is being transformed int cleanup; // 1 to destroy obj when destroyed int infomode; // 1 to put Tx geom in dContactGeom g1 // cached final object transform (body tx + relative tx). this is set by // computeAABB(), and it is valid while the AABB is valid. dxPosR transform_posr; dxGeomTransform (dSpaceID space); ~dxGeomTransform(); void computeAABB(); void computeFinalTx(); }; /* void RunMe() { printf("sizeof body = %i\n", sizeof(dxBody)); printf("sizeof geom = %i\n", sizeof(dxGeom)); printf("sizeof geomtransform = %i\n", sizeof(dxGeomTransform)); printf("sizeof posr = %i\n", sizeof(dxPosR)); } */ dxGeomTransform::dxGeomTransform (dSpaceID space) : dxGeom (space,1) { type = dGeomTransformClass; obj = 0; cleanup = 0; infomode = 0; dSetZero (transform_posr.pos,4); dRSetIdentity (transform_posr.R); } dxGeomTransform::~dxGeomTransform() { if (obj && cleanup) delete obj; } void dxGeomTransform::computeAABB() { if (!obj) { dSetZero (aabb,6); return; } // backup the relative pos and R pointers of the encapsulated geom object dxPosR* posr_bak = obj->final_posr; // compute temporary pos and R for the encapsulated geom object computeFinalTx(); obj->final_posr = &transform_posr; // compute the AABB obj->computeAABB(); memcpy (aabb,obj->aabb,6*sizeof(dReal)); // restore the pos and R obj->final_posr = posr_bak; } // utility function for dCollideTransform() : compute final pos and R // for the encapsulated geom object void dxGeomTransform::computeFinalTx() { dMultiply0_331 (transform_posr.pos,final_posr->R,obj->final_posr->pos); transform_posr.pos[0] += final_posr->pos[0]; transform_posr.pos[1] += final_posr->pos[1]; transform_posr.pos[2] += final_posr->pos[2]; dMultiply0_333 (transform_posr.R,final_posr->R,obj->final_posr->R); } //**************************************************************************** // collider function: // this collides a transformed geom with another geom. the other geom can // also be a transformed geom, but this case is not handled specially. int dCollideTransform (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) { dIASSERT (skip >= (int)sizeof(dContactGeom)); dIASSERT (o1->type == dGeomTransformClass); dxGeomTransform *tr = (dxGeomTransform*) o1; if (!tr->obj) return 0; dUASSERT (tr->obj->parent_space==0, "GeomTransform encapsulated object must not be in a space"); dUASSERT (tr->obj->body==0, "GeomTransform encapsulated object must not be attached " "to a body"); // backup the relative pos and R pointers of the encapsulated geom object, // and the body pointer dxPosR *posr_bak = tr->obj->final_posr; dxBody *bodybak = tr->obj->body; // compute temporary pos and R for the encapsulated geom object. // note that final_pos and final_R are valid if no GEOM_AABB_BAD flag, // because computeFinalTx() will have already been called in // dxGeomTransform::computeAABB() if (tr->gflags & GEOM_AABB_BAD) tr->computeFinalTx(); tr->obj->final_posr = &tr->transform_posr; tr->obj->body = o1->body; // do the collision int n = dCollide (tr->obj,o2,flags,contact,skip); // if required, adjust the 'g1' values in the generated contacts so that // thay indicated the GeomTransform object instead of the encapsulated // object. if (tr->infomode) { for (int i=0; ig1 = o1; } } // restore the pos, R and body tr->obj->final_posr = posr_bak; tr->obj->body = bodybak; return n; } //**************************************************************************** // public API dGeomID dCreateGeomTransform (dSpaceID space) { return new dxGeomTransform (space); } void dGeomTransformSetGeom (dGeomID g, dGeomID obj) { dUASSERT (g && g->type == dGeomTransformClass, "argument not a geom transform"); dxGeomTransform *tr = (dxGeomTransform*) g; if (tr->obj && tr->cleanup) delete tr->obj; tr->obj = obj; } dGeomID dGeomTransformGetGeom (dGeomID g) { dUASSERT (g && g->type == dGeomTransformClass, "argument not a geom transform"); dxGeomTransform *tr = (dxGeomTransform*) g; return tr->obj; } void dGeomTransformSetCleanup (dGeomID g, int mode) { dUASSERT (g && g->type == dGeomTransformClass, "argument not a geom transform"); dxGeomTransform *tr = (dxGeomTransform*) g; tr->cleanup = mode; } int dGeomTransformGetCleanup (dGeomID g) { dUASSERT (g && g->type == dGeomTransformClass, "argument not a geom transform"); dxGeomTransform *tr = (dxGeomTransform*) g; return tr->cleanup; } void dGeomTransformSetInfo (dGeomID g, int mode) { dUASSERT (g && g->type == dGeomTransformClass, "argument not a geom transform"); dxGeomTransform *tr = (dxGeomTransform*) g; tr->infomode = mode; } int dGeomTransformGetInfo (dGeomID g) { dUASSERT (g && g->type == dGeomTransformClass, "argument not a geom transform"); dxGeomTransform *tr = (dxGeomTransform*) g; return tr->infomode; } ode-0.16/ode/src/collision_cylinder_trimesh.cpp0000664000175200017520000011207113403272463016625 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* * Cylinder-trimesh collider by Alen Ladavac * Ported to ODE by Nguyen Binh */ #include #include #include "config.h" #include "matrix.h" #include "odemath.h" #include "collision_util.h" #include "collision_trimesh_internal.h" #include "util.h" #if dTRIMESH_ENABLED #define MAX_REAL dInfinity static const int nCYLINDER_AXIS = 2; static const int nCYLINDER_CIRCLE_SEGMENTS = 8; static const int nMAX_CYLINDER_TRIANGLE_CLIP_POINTS = 12; #define OPTIMIZE_CONTACTS 1 // Local contacts data typedef struct _sLocalContactData { dVector3 vPos; dVector3 vNormal; dReal fDepth; int triIndex; int nFlags; // 0 = filtered out, 1 = OK }sLocalContactData; struct sCylinderTrimeshColliderData { sCylinderTrimeshColliderData(int flags, int skip): m_iFlags(flags), m_iSkip(skip), m_nContacts(0), m_gLocalContacts(NULL) {} #ifdef OPTIMIZE_CONTACTS void _OptimizeLocalContacts(); #endif void _InitCylinderTrimeshData(dxGeom *Cylinder, dxTriMesh *Trimesh); int _ProcessLocalContacts(dContactGeom *contact, dxGeom *Cylinder, dxTriMesh *Trimesh); bool _cldTestAxis(const dVector3 &v0, const dVector3 &v1, const dVector3 &v2, dVector3& vAxis, int iAxis, bool bNoFlip = false); bool _cldTestCircleToEdgeAxis( const dVector3 &v0, const dVector3 &v1, const dVector3 &v2, const dVector3 &vCenterPoint, const dVector3 &vCylinderAxis1, const dVector3 &vVx0, const dVector3 &vVx1, int iAxis); bool _cldTestSeparatingAxes(const dVector3 &v0, const dVector3 &v1, const dVector3 &v2); bool _cldClipCylinderEdgeToTriangle(const dVector3 &v0, const dVector3 &v1, const dVector3 &v2); void _cldClipCylinderToTriangle(const dVector3 &v0, const dVector3 &v1, const dVector3 &v2); void TestOneTriangleVsCylinder(const dVector3 &v0, const dVector3 &v1, const dVector3 &v2, const bool bDoubleSided); int TestCollisionForSingleTriangle(int ctContacts0, int Triint, dVector3 dv[3], bool &bOutFinishSearching); // cylinder data dMatrix3 m_mCylinderRot; dQuaternion m_qCylinderRot; dQuaternion m_qInvCylinderRot; dVector3 m_vCylinderPos; dVector3 m_vCylinderAxis; dReal m_fCylinderRadius; dReal m_fCylinderSize; dVector3 m_avCylinderNormals[nCYLINDER_CIRCLE_SEGMENTS]; // mesh data dQuaternion m_qTrimeshRot; dQuaternion m_qInvTrimeshRot; dMatrix3 m_mTrimeshRot; dVector3 m_vTrimeshPos; // global collider data dVector3 m_vBestPoint; dReal m_fBestDepth; dReal m_fBestCenter; dReal m_fBestrt; int m_iBestAxis; dVector3 m_vContactNormal; dVector3 m_vNormal; dVector3 m_vE0; dVector3 m_vE1; dVector3 m_vE2; // ODE stuff int m_iFlags; int m_iSkip; int m_nContacts;// = 0; sLocalContactData* m_gLocalContacts; }; #ifdef OPTIMIZE_CONTACTS // Use to classify contacts to be "near" in position static const dReal fSameContactPositionEpsilon = REAL(0.0001); // 1e-4 // Use to classify contacts to be "near" in normal direction static const dReal fSameContactNormalEpsilon = REAL(0.0001); // 1e-4 // If this two contact can be classified as "near" inline int _IsNearContacts(sLocalContactData& c1,sLocalContactData& c2) { int bPosNear = 0; int bSameDir = 0; dVector3 vDiff; // First check if they are "near" in position dVector3Subtract(c1.vPos,c2.vPos,vDiff); if ( (dFabs(vDiff[0]) < fSameContactPositionEpsilon) &&(dFabs(vDiff[1]) < fSameContactPositionEpsilon) &&(dFabs(vDiff[2]) < fSameContactPositionEpsilon)) { bPosNear = 1; } // Second check if they are "near" in normal direction dVector3Subtract(c1.vNormal,c2.vNormal,vDiff); if ( (dFabs(vDiff[0]) < fSameContactNormalEpsilon) &&(dFabs(vDiff[1]) < fSameContactNormalEpsilon) &&(dFabs(vDiff[2]) < fSameContactNormalEpsilon) ) { bSameDir = 1; } // Will be "near" if position and normal direction are "near" return (bPosNear && bSameDir); } inline int _IsBetter(sLocalContactData& c1,sLocalContactData& c2) { // The not better will be throw away // You can change the selection criteria here return (c1.fDepth > c2.fDepth); } // iterate through gLocalContacts and filtered out "near contact" void sCylinderTrimeshColliderData::_OptimizeLocalContacts() { int nContacts = m_nContacts; for (int i = 0; i < nContacts-1; i++) { for (int j = i+1; j < nContacts; j++) { if (_IsNearContacts(m_gLocalContacts[i],m_gLocalContacts[j])) { // If they are seem to be the same then filtered // out the least penetrate one if (_IsBetter(m_gLocalContacts[j],m_gLocalContacts[i])) { m_gLocalContacts[i].nFlags = 0; // filtered 1st contact } else { m_gLocalContacts[j].nFlags = 0; // filtered 2nd contact } // NOTE // There is other way is to add two depth together but // it not work so well. Why??? } } } } #endif // OPTIMIZE_CONTACTS int sCylinderTrimeshColliderData::_ProcessLocalContacts(dContactGeom *contact, dxGeom *Cylinder, dxTriMesh *Trimesh) { #ifdef OPTIMIZE_CONTACTS if (m_nContacts > 1 && !(m_iFlags & CONTACTS_UNIMPORTANT)) { // Can be optimized... _OptimizeLocalContacts(); } #endif int iContact = 0; dContactGeom* Contact = 0; int nFinalContact = 0; for (iContact = 0; iContact < m_nContacts; iContact ++) { if (1 == m_gLocalContacts[iContact].nFlags) { Contact = SAFECONTACT(m_iFlags, contact, nFinalContact, m_iSkip); Contact->depth = m_gLocalContacts[iContact].fDepth; dVector3Copy(m_gLocalContacts[iContact].vNormal,Contact->normal); dVector3Copy(m_gLocalContacts[iContact].vPos,Contact->pos); Contact->g1 = Cylinder; Contact->g2 = Trimesh; Contact->side1 = -1; Contact->side2 = m_gLocalContacts[iContact].triIndex; dVector3Inv(Contact->normal); nFinalContact++; } } // debug //if (nFinalContact != m_nContacts) //{ // printf("[Info] %d contacts generated,%d filtered.\n",m_nContacts,m_nContacts-nFinalContact); //} return nFinalContact; } bool sCylinderTrimeshColliderData::_cldTestAxis( const dVector3 &v0, const dVector3 &v1, const dVector3 &v2, dVector3& vAxis, int iAxis, bool bNoFlip/* = false*/) { // calculate length of separating axis vector dReal fL = dVector3Length(vAxis); // if not long enough if ( fL < REAL(1e-5) ) { // do nothing return true; } // otherwise normalize it vAxis[0] /= fL; vAxis[1] /= fL; vAxis[2] /= fL; dReal fdot1 = dVector3Dot(m_vCylinderAxis,vAxis); // project capsule on vAxis dReal frc; if (dFabs(fdot1) > REAL(1.0) ) { // fdot1 = REAL(1.0); frc = dFabs(m_fCylinderSize* REAL(0.5)); } else { frc = dFabs((m_fCylinderSize* REAL(0.5)) * fdot1) + m_fCylinderRadius * dSqrt(REAL(1.0)-(fdot1*fdot1)); } dVector3 vV0; dVector3Subtract(v0,m_vCylinderPos,vV0); dVector3 vV1; dVector3Subtract(v1,m_vCylinderPos,vV1); dVector3 vV2; dVector3Subtract(v2,m_vCylinderPos,vV2); // project triangle on vAxis dReal afv[3]; afv[0] = dVector3Dot( vV0 , vAxis ); afv[1] = dVector3Dot( vV1 , vAxis ); afv[2] = dVector3Dot( vV2 , vAxis ); dReal fMin = MAX_REAL; dReal fMax = -MAX_REAL; // for each vertex for(int i = 0; i < 3; i++) { // find minimum if (afv[i]fMax) { fMax = afv[i]; } } // find capsule's center of interval on axis dReal fCenter = (fMin+fMax)* REAL(0.5); // calculate triangles halfinterval dReal fTriangleRadius = (fMax-fMin)*REAL(0.5); // if they do not overlap, if( dFabs(fCenter) > (frc+fTriangleRadius) ) { // exit, we have no intersection return false; } // calculate depth dReal fDepth = -(dFabs(fCenter) - (frc + fTriangleRadius ) ); // if greater then best found so far if ( fDepth < m_fBestDepth ) { // remember depth m_fBestDepth = fDepth; m_fBestCenter = fCenter; m_fBestrt = frc; dVector3Copy(vAxis,m_vContactNormal); m_iBestAxis = iAxis; // flip normal if interval is wrong faced if ( fCenter< REAL(0.0) && !bNoFlip) { dVector3Inv(m_vContactNormal); m_fBestCenter = -fCenter; } } return true; } // intersection test between edge and circle bool sCylinderTrimeshColliderData::_cldTestCircleToEdgeAxis( const dVector3 &v0, const dVector3 &v1, const dVector3 &v2, const dVector3 &vCenterPoint, const dVector3 &vCylinderAxis1, const dVector3 &vVx0, const dVector3 &vVx1, int iAxis) { // calculate direction of edge dVector3 vkl; dVector3Subtract( vVx1 , vVx0 , vkl); dNormalize3(vkl); // starting point of edge dVector3 vol; dVector3Copy(vVx0,vol); // calculate angle cosine between cylinder axis and edge dReal fdot2 = dVector3Dot(vkl , vCylinderAxis1); // if edge is perpendicular to cylinder axis if(dFabs(fdot2) so save some cycles here dVector3Subtract(v0 ,v2 , m_vE2); // calculate caps centers in absolute space dVector3 vCp0; vCp0[0] = m_vCylinderPos[0] + m_vCylinderAxis[0]*(m_fCylinderSize* REAL(0.5)); vCp0[1] = m_vCylinderPos[1] + m_vCylinderAxis[1]*(m_fCylinderSize* REAL(0.5)); vCp0[2] = m_vCylinderPos[2] + m_vCylinderAxis[2]*(m_fCylinderSize* REAL(0.5)); #if 0 dVector3 vCp1; vCp1[0] = m_vCylinderPos[0] - m_vCylinderAxis[0]*(m_fCylinderSize* REAL(0.5)); vCp1[1] = m_vCylinderPos[1] - m_vCylinderAxis[1]*(m_fCylinderSize* REAL(0.5)); vCp1[2] = m_vCylinderPos[2] - m_vCylinderAxis[2]*(m_fCylinderSize* REAL(0.5)); #endif // reset best axis m_iBestAxis = 0; dVector3 vAxis; // axis m_vNormal //vAxis = -m_vNormal; vAxis[0] = -m_vNormal[0]; vAxis[1] = -m_vNormal[1]; vAxis[2] = -m_vNormal[2]; if (!_cldTestAxis(v0, v1, v2, vAxis, 1, true)) { return false; } // axis CxE0 // vAxis = ( m_vCylinderAxis cross m_vE0 ); dVector3Cross(m_vCylinderAxis, m_vE0,vAxis); if (!_cldTestAxis(v0, v1, v2, vAxis, 2)) { return false; } // axis CxE1 // vAxis = ( m_vCylinderAxis cross m_vE1 ); dVector3Cross(m_vCylinderAxis, m_vE1,vAxis); if (!_cldTestAxis(v0, v1, v2, vAxis, 3)) { return false; } // axis CxE2 // vAxis = ( m_vCylinderAxis cross m_vE2 ); dVector3Cross(m_vCylinderAxis, m_vE2,vAxis); if (!_cldTestAxis(v0, v1, v2, vAxis, 4)) { return false; } // first vertex on triangle // axis ((V0-Cp0) x C) x C //vAxis = ( ( v0-vCp0 ) cross m_vCylinderAxis ) cross m_vCylinderAxis; _CalculateAxis(v0 , vCp0 , m_vCylinderAxis , vAxis); if (!_cldTestAxis(v0, v1, v2, vAxis, 11)) { return false; } // second vertex on triangle // axis ((V1-Cp0) x C) x C // vAxis = ( ( v1-vCp0 ) cross m_vCylinderAxis ) cross m_vCylinderAxis; _CalculateAxis(v1 , vCp0 , m_vCylinderAxis , vAxis); if (!_cldTestAxis(v0, v1, v2, vAxis, 12)) { return false; } // third vertex on triangle // axis ((V2-Cp0) x C) x C //vAxis = ( ( v2-vCp0 ) cross m_vCylinderAxis ) cross m_vCylinderAxis; _CalculateAxis(v2 , vCp0 , m_vCylinderAxis , vAxis); if (!_cldTestAxis(v0, v1, v2, vAxis, 13)) { return false; } // test cylinder axis // vAxis = m_vCylinderAxis; dVector3Copy(m_vCylinderAxis , vAxis); if (!_cldTestAxis(v0, v1, v2, vAxis, 14)) { return false; } // Test top and bottom circle ring of cylinder for separation dVector3 vccATop; vccATop[0] = m_vCylinderPos[0] + m_vCylinderAxis[0]*(m_fCylinderSize * REAL(0.5)); vccATop[1] = m_vCylinderPos[1] + m_vCylinderAxis[1]*(m_fCylinderSize * REAL(0.5)); vccATop[2] = m_vCylinderPos[2] + m_vCylinderAxis[2]*(m_fCylinderSize * REAL(0.5)); dVector3 vccABottom; vccABottom[0] = m_vCylinderPos[0] - m_vCylinderAxis[0]*(m_fCylinderSize * REAL(0.5)); vccABottom[1] = m_vCylinderPos[1] - m_vCylinderAxis[1]*(m_fCylinderSize * REAL(0.5)); vccABottom[2] = m_vCylinderPos[2] - m_vCylinderAxis[2]*(m_fCylinderSize * REAL(0.5)); if (!_cldTestCircleToEdgeAxis(v0, v1, v2, vccATop, m_vCylinderAxis, v0, v1, 15)) { return false; } if (!_cldTestCircleToEdgeAxis(v0, v1, v2, vccATop, m_vCylinderAxis, v1, v2, 16)) { return false; } if (!_cldTestCircleToEdgeAxis(v0, v1, v2, vccATop, m_vCylinderAxis, v0, v2, 17)) { return false; } if (!_cldTestCircleToEdgeAxis(v0, v1, v2, vccABottom, m_vCylinderAxis, v0, v1, 18)) { return false; } if (!_cldTestCircleToEdgeAxis(v0, v1, v2, vccABottom, m_vCylinderAxis, v1, v2, 19)) { return false; } if (!_cldTestCircleToEdgeAxis(v0, v1, v2, vccABottom, m_vCylinderAxis, v0, v2, 20)) { return false; } return true; } bool sCylinderTrimeshColliderData::_cldClipCylinderEdgeToTriangle( const dVector3 &v0, const dVector3 &/*v1*/, const dVector3 &/*v2*/) { // translate cylinder dReal fTemp = dVector3Dot(m_vCylinderAxis , m_vContactNormal); dVector3 vN2; vN2[0] = m_vContactNormal[0] - m_vCylinderAxis[0]*fTemp; vN2[1] = m_vContactNormal[1] - m_vCylinderAxis[1]*fTemp; vN2[2] = m_vContactNormal[2] - m_vCylinderAxis[2]*fTemp; fTemp = dVector3Length(vN2); if (fTemp < REAL(1e-5)) { return false; } // Normalize it vN2[0] /= fTemp; vN2[1] /= fTemp; vN2[2] /= fTemp; // calculate caps centers in absolute space dVector3 vCposTrans; vCposTrans[0] = m_vCylinderPos[0] + vN2[0]*m_fCylinderRadius; vCposTrans[1] = m_vCylinderPos[1] + vN2[1]*m_fCylinderRadius; vCposTrans[2] = m_vCylinderPos[2] + vN2[2]*m_fCylinderRadius; dVector3 vCEdgePoint0; vCEdgePoint0[0] = vCposTrans[0] + m_vCylinderAxis[0] * (m_fCylinderSize* REAL(0.5)); vCEdgePoint0[1] = vCposTrans[1] + m_vCylinderAxis[1] * (m_fCylinderSize* REAL(0.5)); vCEdgePoint0[2] = vCposTrans[2] + m_vCylinderAxis[2] * (m_fCylinderSize* REAL(0.5)); dVector3 vCEdgePoint1; vCEdgePoint1[0] = vCposTrans[0] - m_vCylinderAxis[0] * (m_fCylinderSize* REAL(0.5)); vCEdgePoint1[1] = vCposTrans[1] - m_vCylinderAxis[1] * (m_fCylinderSize* REAL(0.5)); vCEdgePoint1[2] = vCposTrans[2] - m_vCylinderAxis[2] * (m_fCylinderSize* REAL(0.5)); // transform cylinder edge points into triangle space vCEdgePoint0[0] -= v0[0]; vCEdgePoint0[1] -= v0[1]; vCEdgePoint0[2] -= v0[2]; vCEdgePoint1[0] -= v0[0]; vCEdgePoint1[1] -= v0[1]; vCEdgePoint1[2] -= v0[2]; dVector4 plPlane; dVector3 vPlaneNormal; // triangle plane //plPlane = Plane4f( -m_vNormal, 0); vPlaneNormal[0] = -m_vNormal[0]; vPlaneNormal[1] = -m_vNormal[1]; vPlaneNormal[2] = -m_vNormal[2]; dConstructPlane(vPlaneNormal,REAL(0.0),plPlane); if(!dClipEdgeToPlane( vCEdgePoint0, vCEdgePoint1, plPlane )) { return false; } // plane with edge 0 //plPlane = Plane4f( ( m_vNormal cross m_vE0 ), REAL(1e-5)); dVector3Cross(m_vNormal,m_vE0,vPlaneNormal); dConstructPlane(vPlaneNormal,REAL(1e-5),plPlane); if(!dClipEdgeToPlane( vCEdgePoint0, vCEdgePoint1, plPlane )) { return false; } // plane with edge 1 //dVector3 vTemp = ( m_vNormal cross m_vE1 ); dVector3Cross(m_vNormal,m_vE1,vPlaneNormal); fTemp = dVector3Dot(m_vE0 , vPlaneNormal) - REAL(1e-5); //plPlane = Plane4f( vTemp, -(( m_vE0 dot vTemp )-REAL(1e-5))); dConstructPlane(vPlaneNormal,-fTemp,plPlane); if(!dClipEdgeToPlane( vCEdgePoint0, vCEdgePoint1, plPlane )) { return false; } // plane with edge 2 // plPlane = Plane4f( ( m_vNormal cross m_vE2 ), REAL(1e-5)); dVector3Cross(m_vNormal,m_vE2,vPlaneNormal); dConstructPlane(vPlaneNormal,REAL(1e-5),plPlane); if(!dClipEdgeToPlane( vCEdgePoint0, vCEdgePoint1, plPlane )) { return false; } // return capsule edge points into absolute space vCEdgePoint0[0] += v0[0]; vCEdgePoint0[1] += v0[1]; vCEdgePoint0[2] += v0[2]; vCEdgePoint1[0] += v0[0]; vCEdgePoint1[1] += v0[1]; vCEdgePoint1[2] += v0[2]; // calculate depths for both contact points dVector3 vTemp; dVector3Subtract(vCEdgePoint0,m_vCylinderPos, vTemp); dReal fRestDepth0 = -dVector3Dot(vTemp,m_vContactNormal) + m_fBestrt; dVector3Subtract(vCEdgePoint1,m_vCylinderPos, vTemp); dReal fRestDepth1 = -dVector3Dot(vTemp,m_vContactNormal) + m_fBestrt; dReal fDepth0 = m_fBestDepth - (fRestDepth0); dReal fDepth1 = m_fBestDepth - (fRestDepth1); // clamp depths to zero if(fDepth0 < REAL(0.0) ) { fDepth0 = REAL(0.0); } if(fDepth1= (m_iFlags & NUMC_MASK)) return true; } // Generate contact 1 { // generate contacts m_gLocalContacts[m_nContacts].fDepth = fDepth1; dVector3Copy(m_vContactNormal,m_gLocalContacts[m_nContacts].vNormal); dVector3Copy(vCEdgePoint1,m_gLocalContacts[m_nContacts].vPos); m_gLocalContacts[m_nContacts].nFlags = 1; m_nContacts++; } return true; } void sCylinderTrimeshColliderData::_cldClipCylinderToTriangle( const dVector3 &v0, const dVector3 &v1, const dVector3 &v2) { int i = 0; dVector3 avPoints[3]; dVector3 avTempArray1[nMAX_CYLINDER_TRIANGLE_CLIP_POINTS]; dVector3 avTempArray2[nMAX_CYLINDER_TRIANGLE_CLIP_POINTS]; dSetZero(&avTempArray1[0][0],nMAX_CYLINDER_TRIANGLE_CLIP_POINTS * 4); dSetZero(&avTempArray2[0][0],nMAX_CYLINDER_TRIANGLE_CLIP_POINTS * 4); // setup array of triangle vertices dVector3Copy(v0,avPoints[0]); dVector3Copy(v1,avPoints[1]); dVector3Copy(v2,avPoints[2]); dVector3 vCylinderCirclePos, vCylinderCircleNormal_Rel; dSetZero(vCylinderCircleNormal_Rel,4); // check which circle from cylinder we take for clipping if ( dVector3Dot(m_vCylinderAxis , m_vContactNormal) > REAL(0.0)) { // get top circle vCylinderCirclePos[0] = m_vCylinderPos[0] + m_vCylinderAxis[0]*(m_fCylinderSize*REAL(0.5)); vCylinderCirclePos[1] = m_vCylinderPos[1] + m_vCylinderAxis[1]*(m_fCylinderSize*REAL(0.5)); vCylinderCirclePos[2] = m_vCylinderPos[2] + m_vCylinderAxis[2]*(m_fCylinderSize*REAL(0.5)); vCylinderCircleNormal_Rel[nCYLINDER_AXIS] = REAL(-1.0); } else { // get bottom circle vCylinderCirclePos[0] = m_vCylinderPos[0] - m_vCylinderAxis[0]*(m_fCylinderSize*REAL(0.5)); vCylinderCirclePos[1] = m_vCylinderPos[1] - m_vCylinderAxis[1]*(m_fCylinderSize*REAL(0.5)); vCylinderCirclePos[2] = m_vCylinderPos[2] - m_vCylinderAxis[2]*(m_fCylinderSize*REAL(0.5)); vCylinderCircleNormal_Rel[nCYLINDER_AXIS] = REAL(1.0); } dVector3 vTemp; dQuatInv(m_qCylinderRot , m_qInvCylinderRot); // transform triangle points to space of cylinder circle for(i=0; i<3; i++) { dVector3Subtract(avPoints[i] , vCylinderCirclePos , vTemp); dQuatTransform(m_qInvCylinderRot,vTemp,avPoints[i]); } int iTmpCounter1 = 0; int iTmpCounter2 = 0; dVector4 plPlane; // plane of cylinder that contains circle for intersection //plPlane = Plane4f( vCylinderCircleNormal_Rel, 0.0f ); dConstructPlane(vCylinderCircleNormal_Rel,REAL(0.0),plPlane); dClipPolyToPlane(avPoints, 3, avTempArray1, iTmpCounter1, plPlane); // Body of base circle of Cylinder int nCircleSegment = 0; for (nCircleSegment = 0; nCircleSegment < nCYLINDER_CIRCLE_SEGMENTS; nCircleSegment++) { dConstructPlane(m_avCylinderNormals[nCircleSegment],m_fCylinderRadius,plPlane); if (0 == (nCircleSegment % 2)) { dClipPolyToPlane( avTempArray1 , iTmpCounter1 , avTempArray2, iTmpCounter2, plPlane); } else { dClipPolyToPlane( avTempArray2, iTmpCounter2, avTempArray1 , iTmpCounter1 , plPlane ); } dIASSERT( iTmpCounter1 >= 0 && iTmpCounter1 <= nMAX_CYLINDER_TRIANGLE_CLIP_POINTS ); dIASSERT( iTmpCounter2 >= 0 && iTmpCounter2 <= nMAX_CYLINDER_TRIANGLE_CLIP_POINTS ); } // back transform clipped points to absolute space dReal ftmpdot; dReal fTempDepth; dVector3 vPoint; if (nCircleSegment %2) { for( i=0; i REAL(0.0)) { m_gLocalContacts[m_nContacts].fDepth = fTempDepth; dVector3Copy(m_vContactNormal,m_gLocalContacts[m_nContacts].vNormal); dVector3Copy(vPoint,m_gLocalContacts[m_nContacts].vPos); m_gLocalContacts[m_nContacts].nFlags = 1; m_nContacts++; if(m_nContacts >= (m_iFlags & NUMC_MASK)) return;; } } } else { for( i=0; i REAL(0.0)) { m_gLocalContacts[m_nContacts].fDepth = fTempDepth; dVector3Copy(m_vContactNormal,m_gLocalContacts[m_nContacts].vNormal); dVector3Copy(vPoint,m_gLocalContacts[m_nContacts].vPos); m_gLocalContacts[m_nContacts].nFlags = 1; m_nContacts++; if(m_nContacts >= (m_iFlags & NUMC_MASK)) return;; } } } } void sCylinderTrimeshColliderData::TestOneTriangleVsCylinder( const dVector3 &v0, const dVector3 &v1, const dVector3 &v2, const bool bDoubleSided) { // calculate triangle normal dVector3Subtract( v2 , v1 , m_vE1); dVector3 vTemp; dVector3Subtract( v0 , v1 ,vTemp); dVector3Cross(m_vE1 , vTemp , m_vNormal ); // Even though all triangles might be initially valid, // a triangle may degenerate into a segment after applying // space transformation. if (!dSafeNormalize3( m_vNormal)) { return; } // create plane from triangle //Plane4f plTrianglePlane = Plane4f( vPolyNormal, v0 ); dReal plDistance = -dVector3Dot(v0, m_vNormal); dVector4 plTrianglePlane; dConstructPlane( m_vNormal,plDistance,plTrianglePlane); // calculate sphere distance to plane dReal fDistanceCylinderCenterToPlane = dPointPlaneDistance(m_vCylinderPos , plTrianglePlane); // Sphere must be over positive side of triangle if(fDistanceCylinderCenterToPlane < 0 && !bDoubleSided) { // if not don't generate contacts return; } dVector3 vPnt0; dVector3 vPnt1; dVector3 vPnt2; if (fDistanceCylinderCenterToPlane < REAL(0.0) ) { // flip it dVector3Copy(v0 , vPnt0); dVector3Copy(v1 , vPnt2); dVector3Copy(v2 , vPnt1); } else { dVector3Copy(v0 , vPnt0); dVector3Copy(v1 , vPnt1); dVector3Copy(v2 , vPnt2); } m_fBestDepth = MAX_REAL; // do intersection test and find best separating axis if(!_cldTestSeparatingAxes(vPnt0, vPnt1, vPnt2) ) { // if not found do nothing return; } // if best separation axis is not found if ( m_iBestAxis == 0 ) { // this should not happen (the function should have already returned in this case) dIASSERT(false); // do nothing return; } dReal fdot = dVector3Dot( m_vContactNormal , m_vCylinderAxis ); // choose which clipping method are we going to apply if (dFabs(fdot) < REAL(0.9) ) { if (!_cldClipCylinderEdgeToTriangle(vPnt0, vPnt1, vPnt2)) { return; } } else { _cldClipCylinderToTriangle(vPnt0, vPnt1, vPnt2); } } void sCylinderTrimeshColliderData::_InitCylinderTrimeshData(dxGeom *Cylinder, dxTriMesh *Trimesh) { // get cylinder information // Rotation const dReal* pRotCyc = dGeomGetRotation(Cylinder); dMatrix3Copy(pRotCyc,m_mCylinderRot); dGeomGetQuaternion(Cylinder,m_qCylinderRot); // Position const dVector3* pPosCyc = (const dVector3*)dGeomGetPosition(Cylinder); dVector3Copy(*pPosCyc,m_vCylinderPos); // Cylinder axis dMat3GetCol(m_mCylinderRot,nCYLINDER_AXIS,m_vCylinderAxis); // get cylinder radius and size dGeomCylinderGetParams(Cylinder,&m_fCylinderRadius,&m_fCylinderSize); // get trimesh position and orientation const dReal* pRotTris = dGeomGetRotation(Trimesh); dMatrix3Copy(pRotTris,m_mTrimeshRot); dGeomGetQuaternion(Trimesh,m_qTrimeshRot); // Position const dVector3* pPosTris = (const dVector3*)dGeomGetPosition(Trimesh); dVector3Copy(*pPosTris,m_vTrimeshPos); // calculate basic angle for 8-gon dReal fAngle = (dReal) (M_PI / nCYLINDER_CIRCLE_SEGMENTS); // calculate angle increment dReal fAngleIncrement = fAngle*REAL(2.0); // calculate plane normals // axis dependant code for(int i=0; i= (m_iFlags & NUMC_MASK)); return ctContacts0; } // OPCODE version of cylinder to mesh collider #if dTRIMESH_OPCODE static void dQueryCTLPotentialCollisionTriangles(OBBCollider &Collider, sCylinderTrimeshColliderData &cData, dxGeom *Cylinder, dxTriMesh *Trimesh, OBBCache &BoxCache) { Matrix4x4 MeshMatrix; const dVector3 vZeroVector3 = { REAL(0.0), }; MakeMatrix(vZeroVector3, cData.m_mTrimeshRot, MeshMatrix); const dVector3 &vCylinderPos = cData.m_vCylinderPos; const dMatrix3 &mCylinderRot = cData.m_mCylinderRot; dVector3 vCylinderOffsetPos; dSubtractVectors3(vCylinderOffsetPos, vCylinderPos, cData.m_vTrimeshPos); const dReal fCylinderRadius = cData.m_fCylinderRadius, fCylinderHalfAxis = cData.m_fCylinderSize * REAL(0.5); OBB obbCylinder; obbCylinder.mCenter.Set(vCylinderOffsetPos[0], vCylinderOffsetPos[1], vCylinderOffsetPos[2]); obbCylinder.mExtents.Set( 0 == nCYLINDER_AXIS ? fCylinderHalfAxis : fCylinderRadius, 1 == nCYLINDER_AXIS ? fCylinderHalfAxis : fCylinderRadius, 2 == nCYLINDER_AXIS ? fCylinderHalfAxis : fCylinderRadius); obbCylinder.mRot.Set( mCylinderRot[0], mCylinderRot[4], mCylinderRot[8], mCylinderRot[1], mCylinderRot[5], mCylinderRot[9], mCylinderRot[2], mCylinderRot[6], mCylinderRot[10]); // TC results if (Trimesh->getDoTC(dxTriMesh::TTC_BOX)) { dxTriMesh::BoxTC* BoxTC = 0; const int iBoxCacheSize = Trimesh->m_BoxTCCache.size(); for (int i = 0; i != iBoxCacheSize; i++) { if (Trimesh->m_BoxTCCache[i].Geom == Cylinder) { BoxTC = &Trimesh->m_BoxTCCache[i]; break; } } if (!BoxTC) { Trimesh->m_BoxTCCache.push(dxTriMesh::BoxTC()); BoxTC = &Trimesh->m_BoxTCCache[Trimesh->m_BoxTCCache.size() - 1]; BoxTC->Geom = Cylinder; BoxTC->FatCoeff = REAL(1.0); } // Intersect Collider.SetTemporalCoherence(true); Collider.Collide(*BoxTC, obbCylinder, Trimesh->retrieveMeshBVTreeRef(), null, &MeshMatrix); } else { Collider.SetTemporalCoherence(false); Collider.Collide(BoxCache, obbCylinder, Trimesh->retrieveMeshBVTreeRef(), null, &MeshMatrix); } } int dCollideCylinderTrimesh(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) { dIASSERT( skip >= (int)sizeof( dContactGeom ) ); dIASSERT( o1->type == dCylinderClass ); dIASSERT( o2->type == dTriMeshClass ); dIASSERT ((flags & NUMC_MASK) >= 1); int nContactCount = 0; dxGeom *Cylinder = o1; dxTriMesh *Trimesh = (dxTriMesh *)o2; // Main data holder sCylinderTrimeshColliderData cData(flags, skip); cData._InitCylinderTrimeshData(Cylinder, Trimesh); const unsigned uiTLSKind = Trimesh->getParentSpaceTLSKind(); dIASSERT(uiTLSKind == Cylinder->getParentSpaceTLSKind()); // The colliding spaces must use matching cleanup method TrimeshCollidersCache *pccColliderCache = GetTrimeshCollidersCache(uiTLSKind); OBBCollider& Collider = pccColliderCache->m_OBBCollider; dQueryCTLPotentialCollisionTriangles(Collider, cData, Cylinder, Trimesh, pccColliderCache->m_DefaultBoxCache); // Retrieve data int TriCount = Collider.GetNbTouchedPrimitives(); if (TriCount != 0) { const int* Triangles = (const int*)Collider.GetTouchedPrimitives(); if (Trimesh->m_ArrayCallback != NULL) { Trimesh->m_ArrayCallback(Trimesh, Cylinder, Triangles, TriCount); } // allocate buffer for local contacts on stack cData.m_gLocalContacts = (sLocalContactData*)dALLOCA16(sizeof(sLocalContactData)*(cData.m_iFlags & NUMC_MASK)); int ctContacts0 = 0; // loop through all intersecting triangles for (int i = 0; i < TriCount; i++) { const int Triint = Triangles[i]; if (!Trimesh->invokeCallback(Cylinder, Triint)) continue; dVector3 dv[3]; Trimesh->fetchMeshTriangle(dv, Triint, cData.m_vTrimeshPos, cData.m_mTrimeshRot); bool bFinishSearching; ctContacts0 = cData.TestCollisionForSingleTriangle(ctContacts0, Triint, dv, bFinishSearching); if (bFinishSearching) { break; } } if (cData.m_nContacts != 0) { nContactCount = cData._ProcessLocalContacts(contact, Cylinder, Trimesh); } } return nContactCount; } #endif // GIMPACT version of cylinder to mesh collider #if dTRIMESH_GIMPACT int dCollideCylinderTrimesh(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) { dIASSERT( skip >= (int)sizeof( dContactGeom ) ); dIASSERT( o1->type == dCylinderClass ); dIASSERT( o2->type == dTriMeshClass ); dIASSERT ((flags & NUMC_MASK) >= 1); int nContactCount = 0; dxGeom *Cylinder = o1; dxTriMesh *Trimesh = (dxTriMesh *)o2; // Main data holder sCylinderTrimeshColliderData cData(flags, skip); cData._InitCylinderTrimeshData(Cylinder, Trimesh); //*****at first , collide box aabb******// aabb3f test_aabb(o1->aabb[0], o1->aabb[1], o1->aabb[2], o1->aabb[3], o1->aabb[4], o1->aabb[5]); GDYNAMIC_ARRAY collision_result; GIM_CREATE_BOXQUERY_LIST(collision_result); gim_aabbset_box_collision(&test_aabb, &Trimesh->m_collision_trimesh.m_aabbset , &collision_result); if (collision_result.m_size != 0) { //*****Set globals for box collision******// int ctContacts0 = 0; cData.m_gLocalContacts = (sLocalContactData*)dALLOCA16(sizeof(sLocalContactData)*(cData.m_iFlags & NUMC_MASK)); GUINT32 * boxesresult = GIM_DYNARRAY_POINTER(GUINT32,collision_result); GIM_TRIMESH * ptrimesh = &Trimesh->m_collision_trimesh; gim_trimesh_locks_work_data(ptrimesh); for(unsigned int i=0;i #include #include #include "config.h" #include "matrix.h" #include "collision_kernel.h" #include "collision_space_internal.h" // Reference counting helper for radix sort global data. //static void RadixSortRef(); //static void RadixSortDeref(); // -------------------------------------------------------------------------- // Radix Sort Context // -------------------------------------------------------------------------- struct RaixSortContext { public: RaixSortContext(): mCurrentSize(0), mCurrentUtilization(0), mRanksValid(false), mRanksBuffer(NULL), mPrimaryRanks(NULL) {} ~RaixSortContext() { FreeRanks(); } // OPCODE's Radix Sorting, returns a list of indices in sorted order const uint32* RadixSort( const float* input2, uint32 nb ); private: void FreeRanks(); void AllocateRanks(sizeint nNewSize); void ReallocateRanksIfNecessary(sizeint nNewSize); private: void SetCurrentSize(sizeint nValue) { mCurrentSize = nValue; } sizeint GetCurrentSize() const { return mCurrentSize; } void SetCurrentUtilization(sizeint nValue) { mCurrentUtilization = nValue; } sizeint GetCurrentUtilization() const { return mCurrentUtilization; } uint32 *GetRanks1() const { return mPrimaryRanks; } uint32 *GetRanks2() const { return mRanksBuffer + ((mRanksBuffer + mCurrentSize) - mPrimaryRanks); } void SwapRanks() { mPrimaryRanks = GetRanks2(); } bool AreRanksValid() const { return mRanksValid; } void InvalidateRanks() { mRanksValid = false; } void ValidateRanks() { mRanksValid = true; } private: sizeint mCurrentSize; //!< Current size of the indices list sizeint mCurrentUtilization; //!< Current utilization of the indices list bool mRanksValid; uint32* mRanksBuffer; //!< Two lists allocated sequentially in a single block uint32* mPrimaryRanks; }; void RaixSortContext::AllocateRanks(sizeint nNewSize) { dIASSERT(GetCurrentSize() == 0); mRanksBuffer = new uint32[2 * nNewSize]; mPrimaryRanks = mRanksBuffer; SetCurrentSize(nNewSize); } void RaixSortContext::FreeRanks() { SetCurrentSize(0); delete[] mRanksBuffer; } void RaixSortContext::ReallocateRanksIfNecessary(sizeint nNewSize) { sizeint nCurUtilization = GetCurrentUtilization(); if (nNewSize != nCurUtilization) { sizeint nCurSize = GetCurrentSize(); if ( nNewSize > nCurSize ) { // Free previously used ram FreeRanks(); // Get some fresh one AllocateRanks(nNewSize); } InvalidateRanks(); SetCurrentUtilization(nNewSize); } } // -------------------------------------------------------------------------- // SAP space code // -------------------------------------------------------------------------- struct dxSAPSpace : public dxSpace { // Constructor / Destructor dxSAPSpace( dSpaceID _space, int sortaxis ); ~dxSAPSpace(); // dxSpace virtual dxGeom* getGeom(int i); virtual void add(dxGeom* g); virtual void remove(dxGeom* g); virtual void dirty(dxGeom* g); virtual void computeAABB(); virtual void cleanGeoms(); virtual void collide( void *data, dNearCallback *callback ); virtual void collide2( void *data, dxGeom *geom, dNearCallback *callback ); private: //-------------------------------------------------------------------------- // Local Declarations //-------------------------------------------------------------------------- //! A generic couple structure struct Pair { uint32 id0; //!< First index of the pair uint32 id1; //!< Second index of the pair // Default and Value Constructor Pair() {} Pair( uint32 i0, uint32 i1 ) : id0( i0 ), id1( i1 ) {} }; //-------------------------------------------------------------------------- // Helpers //-------------------------------------------------------------------------- /** * Complete box pruning. * Returns a list of overlapping pairs of boxes, each box of the pair * belongs to the same set. * * @param count [in] number of boxes. * @param geoms [in] geoms of boxes. * @param pairs [out] array of overlapping pairs. */ void BoxPruning( int count, const dxGeom** geoms, dArray< Pair >& pairs ); //-------------------------------------------------------------------------- // Implementation Data //-------------------------------------------------------------------------- // We have two lists (arrays of pointers) to dirty and clean // geoms. Each geom knows it's index into the corresponding list // (see macros above). dArray DirtyList; // dirty geoms dArray GeomList; // clean geoms // For SAP, we ultimately separate "normal" geoms and the ones that have // infinite AABBs. No point doing SAP on infinite ones (and it doesn't handle // infinite geoms anyway). dArray TmpGeomList; // temporary for normal geoms dArray TmpInfGeomList; // temporary for geoms with infinite AABBs // Our sorting axes. (X,Z,Y is often best). Stored *2 for minor speedup // Axis indices into geom's aabb are: min=idx, max=idx+1 uint32 ax0idx; uint32 ax1idx; uint32 ax2idx; // pruning position array scratch pad // NOTE: this is float not dReal because of the OPCODE radix sorter dArray< float > poslist; RaixSortContext sortContext; }; // Creation dSpaceID dSweepAndPruneSpaceCreate( dxSpace* space, int axisorder ) { return new dxSAPSpace( space, axisorder ); } //============================================================================== #define GEOM_ENABLED(g) (((g)->gflags & GEOM_ENABLE_TEST_MASK) == GEOM_ENABLE_TEST_VALUE) // HACK: We abuse 'next' and 'tome' members of dxGeom to store indices into dirty/geom lists. #define GEOM_SET_DIRTY_IDX(g,idx) { (g)->next_ex = (dxGeom*)(sizeint)(idx); } #define GEOM_SET_GEOM_IDX(g,idx) { (g)->tome_ex = (dxGeom**)(sizeint)(idx); } #define GEOM_GET_DIRTY_IDX(g) ((int)(sizeint)(g)->next_ex) #define GEOM_GET_GEOM_IDX(g) ((int)(sizeint)(g)->tome_ex) #define GEOM_INVALID_IDX (-1) /* * A bit of repetitive work - similar to collideAABBs, but doesn't check * if AABBs intersect (because SAP returns pairs with overlapping AABBs). */ static void collideGeomsNoAABBs( dxGeom *g1, dxGeom *g2, void *data, dNearCallback *callback ) { dIASSERT( (g1->gflags & GEOM_AABB_BAD)==0 ); dIASSERT( (g2->gflags & GEOM_AABB_BAD)==0 ); // no contacts if both geoms on the same body, and the body is not 0 if (g1->body == g2->body && g1->body) return; // test if the category and collide bitfields match if ( ((g1->category_bits & g2->collide_bits) || (g2->category_bits & g1->collide_bits)) == 0) { return; } dReal *bounds1 = g1->aabb; dReal *bounds2 = g2->aabb; // check if either object is able to prove that it doesn't intersect the // AABB of the other if (g1->AABBTest (g2,bounds2) == 0) return; if (g2->AABBTest (g1,bounds1) == 0) return; // the objects might actually intersect - call the space callback function callback (data,g1,g2); } dxSAPSpace::dxSAPSpace( dSpaceID _space, int axisorder ) : dxSpace( _space ) { type = dSweepAndPruneSpaceClass; // Init AABB to infinity aabb[0] = -dInfinity; aabb[1] = dInfinity; aabb[2] = -dInfinity; aabb[3] = dInfinity; aabb[4] = -dInfinity; aabb[5] = dInfinity; ax0idx = ( ( axisorder ) & 3 ) << 1; ax1idx = ( ( axisorder >> 2 ) & 3 ) << 1; ax2idx = ( ( axisorder >> 4 ) & 3 ) << 1; } dxSAPSpace::~dxSAPSpace() { CHECK_NOT_LOCKED(this); if ( cleanup ) { // note that destroying each geom will call remove() for ( ; DirtyList.size(); dGeomDestroy( DirtyList[ 0 ] ) ) {} for ( ; GeomList.size(); dGeomDestroy( GeomList[ 0 ] ) ) {} } else { // just unhook them for ( ; DirtyList.size(); remove( DirtyList[ 0 ] ) ) {} for ( ; GeomList.size(); remove( GeomList[ 0 ] ) ) {} } } dxGeom* dxSAPSpace::getGeom( int i ) { dUASSERT( i >= 0 && i < count, "index out of range" ); int dirtySize = DirtyList.size(); if( i < dirtySize ) return DirtyList[i]; else return GeomList[i-dirtySize]; } void dxSAPSpace::add( dxGeom* g ) { CHECK_NOT_LOCKED (this); dAASSERT(g); dUASSERT(g->tome_ex == 0 && g->next_ex == 0, "geom is already in a space"); // add to dirty list GEOM_SET_DIRTY_IDX( g, DirtyList.size() ); GEOM_SET_GEOM_IDX( g, GEOM_INVALID_IDX ); DirtyList.push( g ); dxSpace::add(g); } void dxSAPSpace::remove( dxGeom* g ) { CHECK_NOT_LOCKED(this); dAASSERT(g); dUASSERT(g->parent_space == this,"object is not in this space"); // remove int dirtyIdx = GEOM_GET_DIRTY_IDX(g); int geomIdx = GEOM_GET_GEOM_IDX(g); // must be in one list, not in both dUASSERT( (dirtyIdx==GEOM_INVALID_IDX && geomIdx>=0 && geomIdx=0 && dirtyIdxparent_space == this, "object is not in this space"); // check if already dirtied int dirtyIdx = GEOM_GET_DIRTY_IDX(g); if( dirtyIdx != GEOM_INVALID_IDX ) return; int geomIdx = GEOM_GET_GEOM_IDX(g); dUASSERT( geomIdx>=0 && geomIdxcleanGeoms(); } g->recomputeAABB(); dIASSERT((g->gflags & GEOM_AABB_BAD) == 0); g->gflags &= ~GEOM_DIRTY; // remove from dirty list, add to geom list GEOM_SET_DIRTY_IDX( g, GEOM_INVALID_IDX ); GEOM_SET_GEOM_IDX( g, geomSize + i ); GeomList[geomSize+i] = g; } // clear dirty list DirtyList.setSize( 0 ); lock_count--; } void dxSAPSpace::collide( void *data, dNearCallback *callback ) { dAASSERT (callback); lock_count++; cleanGeoms(); // by now all geoms are in GeomList, and DirtyList must be empty int geom_count = GeomList.size(); dUASSERT( geom_count == count, "geom counts messed up" ); // separate all ENABLED geoms into infinite AABBs and normal AABBs TmpGeomList.setSize(0); TmpInfGeomList.setSize(0); int axis0max = ax0idx + 1; for( int i = 0; i < geom_count; ++i ) { dxGeom* g = GeomList[i]; if( !GEOM_ENABLED(g) ) // skip disabled ones continue; const dReal& amax = g->aabb[axis0max]; if( amax == dInfinity ) // HACK? probably not... TmpInfGeomList.push( g ); else TmpGeomList.push( g ); } // do SAP on normal AABBs dArray< Pair > overlapBoxes; int tmp_geom_count = TmpGeomList.size(); if ( tmp_geom_count > 0 ) { // Generate a list of overlapping boxes BoxPruning( tmp_geom_count, (const dxGeom**)TmpGeomList.data(), overlapBoxes ); } // collide overlapping int overlapCount = overlapBoxes.size(); for( int j = 0; j < overlapCount; ++j ) { const Pair& pair = overlapBoxes[ j ]; dxGeom* g1 = TmpGeomList[ pair.id0 ]; dxGeom* g2 = TmpGeomList[ pair.id1 ]; collideGeomsNoAABBs( g1, g2, data, callback ); } int infSize = TmpInfGeomList.size(); int normSize = TmpGeomList.size(); int m, n; for ( m = 0; m < infSize; ++m ) { dxGeom* g1 = TmpInfGeomList[ m ]; // collide infinite ones for( n = m+1; n < infSize; ++n ) { dxGeom* g2 = TmpInfGeomList[n]; collideGeomsNoAABBs( g1, g2, data, callback ); } // collide infinite ones with normal ones for( n = 0; n < normSize; ++n ) { dxGeom* g2 = TmpGeomList[n]; collideGeomsNoAABBs( g1, g2, data, callback ); } } lock_count--; } void dxSAPSpace::collide2( void *data, dxGeom *geom, dNearCallback *callback ) { dAASSERT (geom && callback); // TODO: This is just a simple N^2 implementation lock_count++; cleanGeoms(); geom->recomputeAABB(); // intersect bounding boxes int geom_count = GeomList.size(); for ( int i = 0; i < geom_count; ++i ) { dxGeom* g = GeomList[i]; if ( GEOM_ENABLED(g) ) collideAABBs (g,geom,data,callback); } lock_count--; } void dxSAPSpace::BoxPruning( int count, const dxGeom** geoms, dArray< Pair >& pairs ) { // Size the poslist (+1 for infinity end cap) poslist.setSize( count ); // 1) Build main list using the primary axis // NOTE: uses floats instead of dReals because that's what radix sort wants for( int i = 0; i < count; ++i ) poslist[ i ] = (float)TmpGeomList[i]->aabb[ ax0idx ]; // 2) Sort the list const uint32* Sorted = sortContext.RadixSort( poslist.data(), count ); // 3) Prune the list const uint32* const LastSorted = Sorted + count; const uint32* RunningAddress = Sorted; bool bExitLoop; Pair IndexPair; while ( Sorted < LastSorted ) { IndexPair.id0 = *Sorted++; // empty, this loop just advances RunningAddress for (bExitLoop = false; poslist[*RunningAddress++] < poslist[IndexPair.id0]; ) { if (RunningAddress == LastSorted) { bExitLoop = true; break; } } if ( bExitLoop || RunningAddress == LastSorted) // Not a bug!!! { break; } const float idx0ax0max = (float)geoms[IndexPair.id0]->aabb[ax0idx+1]; // To avoid wrong decisions caused by rounding errors, cast the AABB element to float similarly as we did at the function beginning const dReal idx0ax1max = geoms[IndexPair.id0]->aabb[ax1idx+1]; const dReal idx0ax2max = geoms[IndexPair.id0]->aabb[ax2idx+1]; for (const uint32* RunningAddress2 = RunningAddress; poslist[ IndexPair.id1 = *RunningAddress2++ ] <= idx0ax0max; ) { const dReal* aabb0 = geoms[ IndexPair.id0 ]->aabb; const dReal* aabb1 = geoms[ IndexPair.id1 ]->aabb; // Intersection? if ( idx0ax1max >= aabb1[ax1idx] && aabb1[ax1idx+1] >= aabb0[ax1idx] && idx0ax2max >= aabb1[ax2idx] && aabb1[ax2idx+1] >= aabb0[ax2idx] ) { pairs.push( IndexPair ); } if (RunningAddress2 == LastSorted) { break; } } } // while ( RunningAddress < LastSorted && Sorted < LastSorted ) } //============================================================================== //------------------------------------------------------------------------------ // Radix Sort //------------------------------------------------------------------------------ #define CHECK_PASS_VALIDITY(pass) \ /* Shortcut to current counters */ \ const uint32* CurCount = &mHistogram[pass<<8]; \ \ /* Reset flag. The sorting pass is supposed to be performed. (default) */ \ bool PerformPass = true; \ \ /* Check pass validity */ \ \ /* If all values have the same byte, sorting is useless. */ \ /* It may happen when sorting bytes or words instead of dwords. */ \ /* This routine actually sorts words faster than dwords, and bytes */ \ /* faster than words. Standard running time (O(4*n))is reduced to O(2*n) */ \ /* for words and O(n) for bytes. Running time for floats depends on actual values... */ \ \ /* Get first byte */ \ uint8 UniqueVal = *(((const uint8*)input)+pass); \ \ /* Check that byte's counter */ \ if(CurCount[UniqueVal]==nb) PerformPass=false; // WARNING ONLY SORTS IEEE FLOATING-POINT VALUES const uint32* RaixSortContext::RadixSort( const float* input2, uint32 nb ) { union _type_cast_union { _type_cast_union(const float *floats): asFloats(floats) {} _type_cast_union(const uint32 *uints32): asUInts32(uints32) {} const float *asFloats; const uint32 *asUInts32; const uint8 *asUInts8; }; const uint32* input = _type_cast_union(input2).asUInts32; // Resize lists if needed ReallocateRanksIfNecessary(nb); // Allocate histograms & offsets on the stack uint32 mHistogram[256*4]; uint32* mLink[256]; // Create histograms (counters). Counters for all passes are created in one run. // Pros: read input buffer once instead of four times // Cons: mHistogram is 4Kb instead of 1Kb // Floating-point values are always supposed to be signed values, so there's only one code path there. // Please note the floating point comparison needed for temporal coherence! Although the resulting asm code // is dreadful, this is surprisingly not such a performance hit - well, I suppose that's a big one on first // generation Pentiums....We can't make comparison on integer representations because, as Chris said, it just // wouldn't work with mixed positive/negative values.... { /* Clear counters/histograms */ memset(mHistogram, 0, 256*4*sizeof(uint32)); /* Prepare to count */ const uint8* p = _type_cast_union(input).asUInts8; const uint8* pe = &p[nb*4]; uint32* h0= &mHistogram[0]; /* Histogram for first pass (LSB) */ uint32* h1= &mHistogram[256]; /* Histogram for second pass */ uint32* h2= &mHistogram[512]; /* Histogram for third pass */ uint32* h3= &mHistogram[768]; /* Histogram for last pass (MSB) */ bool AlreadySorted = true; /* Optimism... */ if (!AreRanksValid()) { /* Prepare for temporal coherence */ const float* Running = input2; float PrevVal = *Running; while(p!=pe) { /* Read input input2 in previous sorted order */ float Val = *Running++; /* Check whether already sorted or not */ if(Val>24; // Radix byte, same as above. AND is useless here (uint32). // ### cmp to be killed. Not good. Later. if(Radix<128) *mLink[Radix]++ = i; // Number is positive, same as above else *(--mLink[Radix]) = i; // Number is negative, flip the sorting order } ValidateRanks(); } else { uint32* const Ranks1 = GetRanks1(); for(uint32 i=0;i>24; // Radix byte, same as above. AND is useless here (uint32). // ### cmp to be killed. Not good. Later. if(Radix<128) *mLink[Radix]++ = Ranks1[i]; // Number is positive, same as above else *(--mLink[Radix]) = Ranks1[i]; // Number is negative, flip the sorting order } } // Swap pointers for next pass. Valid indices - the most recent ones - are in mRanks after the swap. SwapRanks(); } else { // The pass is useless, yet we still have to reverse the order of current list if all values are negative. if(UniqueVal>=128) { if (!AreRanksValid()) { uint32* const Ranks2 = GetRanks2(); // ###Possible? for(uint32 i=0;i /*static */ void dxTriDataBase::retrieveTriangleVertexPoints(dVector3 out_Points[dMTV__MAX], unsigned triangleIndex, const tcoordfloat *vertexInstances, int vertexStride, const tindexint *triangleVertexIndices, int triangleStride) { const tindexint *triangleIndicesOfInterest = (const tindexint *)((uint8 *)triangleVertexIndices + (sizeint)triangleIndex * triangleStride); for (unsigned trianglePoint = dMTV__MIN; trianglePoint != dMTV__MAX; ++trianglePoint) { unsigned vertexIndex = triangleIndicesOfInterest[trianglePoint]; tcoordfloat *pointVertex = (tcoordfloat *)((uint8 *)vertexInstances + (sizeint)vertexIndex * vertexStride); dAssignVector3(out_Points[trianglePoint], (dReal)pointVertex[dSA_X], (dReal)pointVertex[dSA_Y], (dReal)pointVertex[dSA_Z]); dSASSERT(dSA_X == 0); dSASSERT(dSA_Y == 1); dSASSERT(dSA_Z == 2); } } template /*static */ void dxTriDataBase::meaningfulPreprocess_SetupEdgeRecords(EdgeRecord *edges, sizeint numEdges, const TMeshDataAccessor &dataAccessor) { unsigned vertexIndices[dMTV__MAX]; // Make a list of every edge in the mesh unsigned triangleIdx = 0; for (sizeint edgeIdx = 0; edgeIdx != numEdges; ++triangleIdx, edgeIdx += dMTV__MAX) { dataAccessor.getTriangleVertexIndices(vertexIndices, triangleIdx); edges[edgeIdx + dMTV_FIRST].setupEdge(dMTV_FIRST, triangleIdx, vertexIndices); edges[edgeIdx + dMTV_SECOND].setupEdge(dMTV_SECOND, triangleIdx, vertexIndices); edges[edgeIdx + dMTV_THIRD].setupEdge(dMTV_THIRD, triangleIdx, vertexIndices); } } template /*static */ void dxTriDataBase::meaningfulPreprocess_buildEdgeFlags(uint8 *useFlags/*=NULL*/, IFaceAngleStorageControl *faceAngles/*=NULL*/, EdgeRecord *edges, sizeint numEdges, VertexRecord *vertices, const dReal *externalNormals/*=NULL*/, const TMeshDataAccessor &dataAccessor) { dIASSERT(useFlags != NULL || faceAngles != NULL); dIASSERT(numEdges != 0); const bool negativeAnglesStored = faceAngles != NULL && faceAngles->areNegativeAnglesStored(); // Go through the sorted list of edges and flag all the edges and vertices that we need to use EdgeRecord *const lastEdge = edges + (numEdges - 1); for (EdgeRecord *currEdge = edges; ; ++currEdge) { // Handle the last edge separately to have an optimizer friendly loop if (currEdge >= lastEdge) { // This is a boundary edge if (currEdge == lastEdge) { if (faceAngles != NULL) { buildBoundaryEdgeAngle(faceAngles, currEdge); } if (useFlags != NULL) { // For the last element EdgeRecord::kAbsVertexUsed assignment can be skipped as noone is going to need it any more useFlags[currEdge[0].m_triIdx] |= ((edges[currEdge[0].m_vertIdx1].m_absVertexFlags & EdgeRecord::AVF_VERTEX_USED) == 0 ? currEdge[0].m_vert1Flags : 0) | ((edges[currEdge[0].m_vertIdx2].m_absVertexFlags & EdgeRecord::AVF_VERTEX_USED) == 0 ? currEdge[0].m_vert2Flags : 0) | currEdge[0].m_edgeFlags; } } break; } unsigned vertIdx1 = currEdge[0].m_vertIdx1; unsigned vertIdx2 = currEdge[0].m_vertIdx2; if (vertIdx2 == currEdge[1].m_vertIdx2 // Check second vertex first as it is more likely to change taking the sorting rules into account && vertIdx1 == currEdge[1].m_vertIdx1) { // We let the dot threshold for concavity get slightly negative to allow for rounding errors const float kConcaveThreshold = 0.000001f; const dVector3 *pSecondTriangleEdgeToUse = NULL, *pFirstTriangleToUse = NULL; dVector3 secondTriangleMatchingEdge; dVector3 firstTriangle[dMTV__MAX]; dVector3 secondOppositeVertexSegment, triangleNormal; dReal lengthSquareProduct, secondOppositeSegmentLengthSquare; // Calculate orthogonal vector from the matching edge of the second triangle to its opposite point { dVector3 secondTriangle[dMTV__MAX]; dataAccessor.getTriangleVertexPoints(secondTriangle, currEdge[1].m_triIdx); // Get the vertex opposite this edge in the second triangle dMeshTriangleVertex secondOppositeVertex = currEdge[1].getOppositeVertexIndex(); dMeshTriangleVertex secondEdgeStart = secondOppositeVertex + 1 != dMTV__MAX ? (dMeshTriangleVertex)(secondOppositeVertex + 1) : dMTV__MIN; dMeshTriangleVertex secondEdgeEnd = (dMeshTriangleVertex)(dMTV_FIRST + dMTV_SECOND + dMTV_THIRD - secondEdgeStart - secondOppositeVertex); dSubtractVectors3(secondTriangleMatchingEdge, secondTriangle[secondEdgeEnd], secondTriangle[secondEdgeStart]); if (dSafeNormalize3(secondTriangleMatchingEdge)) { pSecondTriangleEdgeToUse = &secondTriangleMatchingEdge; dVector3 secondTriangleOppositeEdge; dSubtractVectors3(secondTriangleOppositeEdge, secondTriangle[secondOppositeVertex], secondTriangle[secondEdgeStart]); dReal dProjectionLength = dCalcVectorDot3(secondTriangleOppositeEdge, secondTriangleMatchingEdge); dAddVectorScaledVector3(secondOppositeVertexSegment, secondTriangleOppositeEdge, secondTriangleMatchingEdge, -dProjectionLength); } else { dSubtractVectors3(secondOppositeVertexSegment, secondTriangle[secondOppositeVertex], secondTriangle[secondEdgeStart]); } secondOppositeSegmentLengthSquare = dCalcVectorLengthSquare3(secondOppositeVertexSegment); } // Either calculate the normal from triangle vertices... if (externalNormals == NULL) { // Get the normal of the first triangle dataAccessor.getTriangleVertexPoints(firstTriangle, currEdge[0].m_triIdx); pFirstTriangleToUse = &firstTriangle[dMTV__MIN]; dVector3 firstEdge, secondEdge; dSubtractVectors3(secondEdge, firstTriangle[dMTV_THIRD], firstTriangle[dMTV_SECOND]); dSubtractVectors3(firstEdge, firstTriangle[dMTV_FIRST], firstTriangle[dMTV_SECOND]); dCalcVectorCross3(triangleNormal, secondEdge, firstEdge); dReal normalLengthSuqare = dCalcVectorLengthSquare3(triangleNormal); lengthSquareProduct = secondOppositeSegmentLengthSquare * normalLengthSuqare; } // ...or use the externally supplied normals else { const dReal *pTriangleExternalNormal = externalNormals + currEdge[0].m_triIdx * dSA__MAX; dAssignVector3(triangleNormal, pTriangleExternalNormal[dSA_X], pTriangleExternalNormal[dSA_Y], pTriangleExternalNormal[dSA_Z]); // normalLengthSuqare = REAL(1.0); dUASSERT(dFabs(dCalcVectorLengthSquare3(triangleNormal) - REAL(1.0)) < REAL(0.25) * kConcaveThreshold * kConcaveThreshold, "Mesh triangle normals must be normalized"); lengthSquareProduct = secondOppositeSegmentLengthSquare/* * normalLengthSuqare*/; } dReal normalSegmentDot = dCalcVectorDot3(triangleNormal, secondOppositeVertexSegment); // This is a concave edge, leave it for the next pass // OD: This is the "dot >= kConcaveThresh" check, but since the vectros were not normalized to save on roots and divisions, // the check against zero is performed first and then the dot product is squared and compared against the threshold multiplied by lengths' squares // OD: Originally, there was dot > -kConcaveThresh check, but this does not seem to be a good idea // as it can mark all edges on potentially large (nearly) flat surfaces concave. if (normalSegmentDot > REAL(0.0) && normalSegmentDot * normalSegmentDot >= kConcaveThreshold * kConcaveThreshold * lengthSquareProduct) { if (faceAngles != NULL) { buildConcaveEdgeAngle(faceAngles, negativeAnglesStored, currEdge, normalSegmentDot, lengthSquareProduct, triangleNormal, secondOppositeVertexSegment, pSecondTriangleEdgeToUse, pFirstTriangleToUse, dataAccessor); } if (useFlags != NULL) { // Mark the vertices of a concave edge to prevent their use unsigned absVertexFlags1 = edges[vertIdx1].m_absVertexFlags; edges[vertIdx1].m_absVertexFlags |= absVertexFlags1 | EdgeRecord::AVF_VERTEX_HAS_CONCAVE_EDGE | EdgeRecord::AVF_VERTEX_USED; if ((absVertexFlags1 & (EdgeRecord::AVF_VERTEX_HAS_CONCAVE_EDGE | EdgeRecord::AVF_VERTEX_USED)) == EdgeRecord::AVF_VERTEX_USED) { // If the vertex was already used from other triangles but then discovered // to have a concave edge, unmark the previous use unsigned usedFromEdgeIndex = vertices[vertIdx1].m_UsedFromEdgeIndex; const EdgeRecord *usedFromEdge = edges + usedFromEdgeIndex; unsigned usedInTriangleIndex = usedFromEdge->m_triIdx; uint8 usedVertFlags = usedFromEdge->m_vertIdx1 == vertIdx1 ? usedFromEdge->m_vert1Flags : usedFromEdge->m_vert2Flags; useFlags[usedInTriangleIndex] ^= usedVertFlags; dIASSERT((useFlags[usedInTriangleIndex] & usedVertFlags) == 0); } unsigned absVertexFlags2 = edges[vertIdx2].m_absVertexFlags; edges[vertIdx2].m_absVertexFlags = absVertexFlags2 | EdgeRecord::AVF_VERTEX_HAS_CONCAVE_EDGE | EdgeRecord::AVF_VERTEX_USED; if ((absVertexFlags2 & (EdgeRecord::AVF_VERTEX_HAS_CONCAVE_EDGE | EdgeRecord::AVF_VERTEX_USED)) == EdgeRecord::AVF_VERTEX_USED) { // Similarly unmark the possible previous use of the edge's second vertex unsigned usedFromEdgeIndex = vertices[vertIdx2].m_UsedFromEdgeIndex; const EdgeRecord *usedFromEdge = edges + usedFromEdgeIndex; unsigned usedInTriangleIndex = usedFromEdge->m_triIdx; uint8 usedVertFlags = usedFromEdge->m_vertIdx1 == vertIdx2 ? usedFromEdge->m_vert1Flags : usedFromEdge->m_vert2Flags; useFlags[usedInTriangleIndex] ^= usedVertFlags; dIASSERT((useFlags[usedInTriangleIndex] & usedVertFlags) == 0); } } } // If this is a convex edge, mark its vertices and edge as used else { if (faceAngles != NULL) { buildConvexEdgeAngle(faceAngles, currEdge, normalSegmentDot, lengthSquareProduct, triangleNormal, secondOppositeVertexSegment, pSecondTriangleEdgeToUse, pFirstTriangleToUse, dataAccessor); } if (useFlags != NULL) { EdgeRecord *edgeToUse = currEdge; unsigned triIdx = edgeToUse[0].m_triIdx; unsigned triIdx1 = edgeToUse[1].m_triIdx; unsigned triUseFlags = useFlags[triIdx]; unsigned triUseFlags1 = useFlags[triIdx1]; // Choose to add flags to the bitmask that already has more edges // (to group flags in selected triangles rather than scattering them evenly) if ((triUseFlags1 & CUF__USE_ALL_EDGES) > (triUseFlags & CUF__USE_ALL_EDGES)) { triIdx = triIdx1; triUseFlags = triUseFlags1; edgeToUse = edgeToUse + 1; } if ((edges[vertIdx1].m_absVertexFlags & EdgeRecord::AVF_VERTEX_USED) == 0) { // Only add each vertex once and set a mark to prevent further additions edges[vertIdx1].m_absVertexFlags |= EdgeRecord::AVF_VERTEX_USED; // Also remember the index the vertex flags are going to be applied to // to allow easily clear the vertex from the use flags if any concave edges are found to connect to it vertices[vertIdx1].m_UsedFromEdgeIndex = (unsigned)(edgeToUse - edges); triUseFlags |= edgeToUse[0].m_vert1Flags; } // Same processing for the second vertex... if ((edges[vertIdx2].m_absVertexFlags & EdgeRecord::AVF_VERTEX_USED) == 0) { edges[vertIdx2].m_absVertexFlags |= EdgeRecord::AVF_VERTEX_USED; vertices[vertIdx2].m_UsedFromEdgeIndex = (unsigned)(edgeToUse - edges); triUseFlags |= edgeToUse[0].m_vert2Flags; } // And finally store the use flags adding the edge flags in useFlags[triIdx] = triUseFlags | edgeToUse[0].m_edgeFlags; } } // Skip the second edge ++currEdge; } // This is a boundary edge else { if (faceAngles != NULL) { buildBoundaryEdgeAngle(faceAngles, currEdge); } if (useFlags != NULL) { unsigned triIdx = currEdge[0].m_triIdx; unsigned triUseExtraFlags = 0; if ((edges[vertIdx1].m_absVertexFlags & EdgeRecord::AVF_VERTEX_USED) == 0) { edges[vertIdx1].m_absVertexFlags |= EdgeRecord::AVF_VERTEX_USED; vertices[vertIdx1].m_UsedFromEdgeIndex = (unsigned)(currEdge - edges); triUseExtraFlags |= currEdge[0].m_vert1Flags; } if ((edges[vertIdx2].m_absVertexFlags & EdgeRecord::AVF_VERTEX_USED) == 0) { edges[vertIdx2].m_absVertexFlags |= EdgeRecord::AVF_VERTEX_USED; vertices[vertIdx2].m_UsedFromEdgeIndex = (unsigned)(currEdge - edges); triUseExtraFlags |= currEdge[0].m_vert2Flags; } useFlags[triIdx] |= triUseExtraFlags | currEdge[0].m_edgeFlags; } } } } /*static */ void dxTriDataBase::buildBoundaryEdgeAngle(IFaceAngleStorageControl *faceAngles, EdgeRecord *currEdge) { const dReal faceAngle = REAL(0.0); dMeshTriangleVertex firstVertexStartIndex = currEdge[0].getEdgeStartVertexIndex(); faceAngles->assignFacesAngleIntoStorage(currEdge[0].m_triIdx, firstVertexStartIndex, faceAngle); // -- For boundary edges, only the first element is valid // dMeshTriangleVertex secondVertexStartIndex = currEdge[1].getEdgeStartVertexIndex(); // faceAngles->assignFacesAngleIntoStorage(currEdge[1].m_TriIdx, secondVertexStartIndex, faceAngle); } template /*static */ void dxTriDataBase::buildConcaveEdgeAngle(IFaceAngleStorageControl *faceAngles, bool negativeAnglesStored, EdgeRecord *currEdge, const dReal &normalSegmentDot, const dReal &lengthSquareProduct, const dVector3 &triangleNormal, const dVector3 &secondOppositeVertexSegment, const dVector3 *pSecondTriangleMatchingEdge/*=NULL*/, const dVector3 *pFirstTriangle/*=NULL*/, const TMeshDataAccessor &dataAccessor) { dReal faceAngle; dMeshTriangleVertex firstVertexStartIndex = currEdge[0].getEdgeStartVertexIndex(); // Check if concave angles are stored at all if (negativeAnglesStored) { // The length square product can become zero due to precision loss // when both the normal and the opposite edge vectors are very small. if (lengthSquareProduct != REAL(0.0)) { faceAngle = -calculateEdgeAngleValidated(firstVertexStartIndex, currEdge, normalSegmentDot, lengthSquareProduct, triangleNormal, secondOppositeVertexSegment, pSecondTriangleMatchingEdge, pFirstTriangle, dataAccessor); } else { faceAngle = REAL(0.0); } } else { // If concave angles ate not stored, set an arbitrary negative value faceAngle = -(dReal)M_PI; } faceAngles->assignFacesAngleIntoStorage(currEdge[0].m_triIdx, firstVertexStartIndex, faceAngle); dMeshTriangleVertex secondVertexStartIndex = currEdge[1].getEdgeStartVertexIndex(); faceAngles->assignFacesAngleIntoStorage(currEdge[1].m_triIdx, secondVertexStartIndex, faceAngle); } template /*static */ void dxTriDataBase::buildConvexEdgeAngle(IFaceAngleStorageControl *faceAngles, EdgeRecord *currEdge, const dReal &normalSegmentDot, const dReal &lengthSquareProduct, const dVector3 &triangleNormal, const dVector3 &secondOppositeVertexSegment, const dVector3 *pSecondTriangleMatchingEdge/*=NULL*/, const dVector3 *pFirstTriangle/*=NULL*/, const TMeshDataAccessor &dataAccessor) { dReal faceAngle; dMeshTriangleVertex firstVertexStartIndex = currEdge[0].getEdgeStartVertexIndex(); // The length square product can become zero due to precision loss // when both the normal and the opposite edge vectors are very small. if (normalSegmentDot < REAL(0.0) && lengthSquareProduct != REAL(0.0)) { faceAngle = calculateEdgeAngleValidated(firstVertexStartIndex, currEdge, -normalSegmentDot, lengthSquareProduct, triangleNormal, secondOppositeVertexSegment, pSecondTriangleMatchingEdge, pFirstTriangle, dataAccessor); } else { faceAngle = REAL(0.0); } faceAngles->assignFacesAngleIntoStorage(currEdge[0].m_triIdx, firstVertexStartIndex, faceAngle); dMeshTriangleVertex secondVertexStartIndex = currEdge[1].getEdgeStartVertexIndex(); faceAngles->assignFacesAngleIntoStorage(currEdge[1].m_triIdx, secondVertexStartIndex, faceAngle); } template /*static */ dReal dxTriDataBase::calculateEdgeAngleValidated(unsigned firstVertexStartIndex, EdgeRecord *currEdge, const dReal &normalSegmentDot, const dReal &lengthSquareProduct, const dVector3 &triangleNormal, const dVector3 &secondOppositeVertexSegment, const dVector3 *pSecondTriangleMatchingEdge/*=NULL*/, const dVector3 *pFirstTriangle/*=NULL*/, const TMeshDataAccessor &dataAccessor) { dIASSERT(lengthSquareProduct >= REAL(0.0)); dReal result; dReal angleCosine = normalSegmentDot / dSqrt(lengthSquareProduct); if (angleCosine < REAL(1.0)) { dVector3 normalSecondOppositeSegmentCross; dCalcVectorCross3(normalSecondOppositeSegmentCross, triangleNormal, secondOppositeVertexSegment); dReal secondTriangleEdgeDirectionCheck; if (pSecondTriangleMatchingEdge != NULL) { // Check the cross product against the second triangle edge, if possible... secondTriangleEdgeDirectionCheck = dCalcVectorDot3(normalSecondOppositeSegmentCross, *pSecondTriangleMatchingEdge); } else { // ...if not, calculate the supposed direction of the second triangle's edge // as negative of first triangle edge. For that cross-multiply the precomputed // first triangle normal by vector from the degenerate edge to its opposite vertex. // Retrieve the first triangle points if necessary dVector3 firstTriangleStorage[dMTV__MAX]; const dVector3 *pFirstTriangleToUse = pFirstTriangle; if (pFirstTriangle == NULL) { dataAccessor.getTriangleVertexPoints(firstTriangleStorage, currEdge[0].m_triIdx); pFirstTriangleToUse = &firstTriangleStorage[dMTV__MIN]; } // Calculate the opposite vector unsigned firstTriangleOppositeIndex = firstVertexStartIndex != dMTV__MIN ? firstVertexStartIndex - 1 : dMTV__MAX - 1; dVector3 firstOppositeVertexSegment; dSubtractVectors3(firstOppositeVertexSegment, pFirstTriangleToUse[firstTriangleOppositeIndex], pFirstTriangleToUse[firstVertexStartIndex]); dVector3 normalFirstOppositeSegmentCross; dCalcVectorCross3(normalFirstOppositeSegmentCross, triangleNormal, firstOppositeVertexSegment); // And finally calculate the dot product to compare vector directions secondTriangleEdgeDirectionCheck = dCalcVectorDot3(normalSecondOppositeSegmentCross, normalFirstOppositeSegmentCross); } // Negative product means the angle absolute value is less than M_PI_2, positive - greater. result = secondTriangleEdgeDirectionCheck < REAL(0.0) ? dAsin(angleCosine) : (dReal)M_PI_2 + dAcos(angleCosine); } else { result = (dReal)M_PI_2; dIASSERT(angleCosine - REAL(1.0) < 1e-4); // The computational error can not be too high because the dot product had been verified to be greater than the concave threshold above } return result; } #endif // #if dTRIMESH_ENABLED #endif // #ifndef _ODE_COLLISION_TRIMESH_INTERNAL_IMPL_H_ ode-0.16/ode/src/collision_libccd.cpp0000664000175200017520000011443013403272463014502 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include #include "ccdcustom/vec3.h" #include "ccdcustom/quat.h" #include "config.h" #include "odemath.h" #include "collision_libccd.h" #include "collision_trimesh_internal.h" #include "collision_std.h" #include "collision_util.h" #include "error.h" struct _ccd_obj_t { ccd_vec3_t pos; ccd_quat_t rot, rot_inv; }; typedef struct _ccd_obj_t ccd_obj_t; struct _ccd_box_t { ccd_obj_t o; ccd_real_t dim[3]; }; typedef struct _ccd_box_t ccd_box_t; struct _ccd_cap_t { ccd_obj_t o; ccd_real_t radius; ccd_vec3_t axis; ccd_vec3_t p1; ccd_vec3_t p2; }; typedef struct _ccd_cap_t ccd_cap_t; struct _ccd_cyl_t { ccd_obj_t o; ccd_real_t radius; ccd_vec3_t axis; ccd_vec3_t p1; ccd_vec3_t p2; }; typedef struct _ccd_cyl_t ccd_cyl_t; struct _ccd_sphere_t { ccd_obj_t o; ccd_real_t radius; }; typedef struct _ccd_sphere_t ccd_sphere_t; struct _ccd_convex_t { ccd_obj_t o; dxConvex *convex; }; typedef struct _ccd_convex_t ccd_convex_t; struct _ccd_triangle_t { ccd_obj_t o; ccd_vec3_t vertices[3]; }; typedef struct _ccd_triangle_t ccd_triangle_t; /** Transforms geom to ccd struct */ static void ccdGeomToObj(const dGeomID g, ccd_obj_t *); static void ccdGeomToBox(const dGeomID g, ccd_box_t *); static void ccdGeomToCap(const dGeomID g, ccd_cap_t *); static void ccdGeomToCyl(const dGeomID g, ccd_cyl_t *); static void ccdGeomToSphere(const dGeomID g, ccd_sphere_t *); static void ccdGeomToConvex(const dGeomID g, ccd_convex_t *); /** Support functions */ static void ccdSupportBox(const void *obj, const ccd_vec3_t *_dir, ccd_vec3_t *v); static void ccdSupportCap(const void *obj, const ccd_vec3_t *_dir, ccd_vec3_t *v); static void ccdSupportCyl(const void *obj, const ccd_vec3_t *_dir, ccd_vec3_t *v); static void ccdSupportSphere(const void *obj, const ccd_vec3_t *_dir, ccd_vec3_t *v); static void ccdSupportConvex(const void *obj, const ccd_vec3_t *_dir, ccd_vec3_t *v); /** Center function */ static void ccdCenter(const void *obj, ccd_vec3_t *c); /** General collide function */ static int ccdCollide(dGeomID o1, dGeomID o2, int flags, dContactGeom *contact, int skip, void *obj1, ccd_support_fn supp1, ccd_center_fn cen1, void *obj2, ccd_support_fn supp2, ccd_center_fn cen2); static int collideCylCyl(dxGeom *o1, dxGeom *o2, ccd_cyl_t* cyl1, ccd_cyl_t* cyl2, int flags, dContactGeom *contacts, int skip); static bool testAndPrepareDiscContactForAngle(dReal angle, dReal radius, dReal length, dReal lSum, ccd_cyl_t *priCyl, ccd_cyl_t *secCyl, ccd_vec3_t &p, dReal &out_depth); // Adds a contact between 2 cylinders static int addCylCylContact(dxGeom *o1, dxGeom *o2, ccd_vec3_t* axis, dContactGeom *contacts, ccd_vec3_t* p, dReal normaldir, dReal depth, int j, int flags, int skip); static unsigned addTrianglePerturbedContacts(dxGeom *o1, dxGeom *o2, IFaceAngleStorageView *meshFaceAngleView, const int *indices, unsigned numIndices, int flags, dContactGeom *contacts, int skip, ccd_convex_t *c1, ccd_triangle_t *c2, dVector3 *triangle, dContactGeom *contact, unsigned contacCount); static bool correctTriangleContactNormal(ccd_triangle_t *t, dContactGeom *contact, IFaceAngleStorageView *meshFaceAngleView, const int *indices, unsigned numIndices); static unsigned addUniqueContact(dContactGeom *contacts, dContactGeom *c, unsigned contactcount, unsigned maxcontacts, int flags, int skip); static void setObjPosToTriangleCenter(ccd_triangle_t *t); static void ccdSupportTriangle(const void *obj, const ccd_vec3_t *_dir, ccd_vec3_t *v); static void ccdGeomToObj(const dGeomID g, ccd_obj_t *o) { const dReal *ode_pos; dQuaternion ode_rot; ode_pos = dGeomGetPosition(g); dGeomGetQuaternion(g, ode_rot); ccdVec3Set(&o->pos, ode_pos[0], ode_pos[1], ode_pos[2]); ccdQuatSet(&o->rot, ode_rot[1], ode_rot[2], ode_rot[3], ode_rot[0]); ccdQuatInvert2(&o->rot_inv, &o->rot); } static void ccdGeomToBox(const dGeomID g, ccd_box_t *box) { dVector3 dim; ccdGeomToObj(g, (ccd_obj_t *)box); dGeomBoxGetLengths(g, dim); box->dim[0] = (ccd_real_t)(dim[0] * 0.5); box->dim[1] = (ccd_real_t)(dim[1] * 0.5); box->dim[2] = (ccd_real_t)(dim[2] * 0.5); } static void ccdGeomToCap(const dGeomID g, ccd_cap_t *cap) { dReal r, h; ccdGeomToObj(g, (ccd_obj_t *)cap); dGeomCapsuleGetParams(g, &r, &h); cap->radius = r; ccdVec3Set(&cap->axis, 0.0, 0.0, h / 2); ccdQuatRotVec(&cap->axis, &cap->o.rot); ccdVec3Copy(&cap->p1, &cap->axis); ccdVec3Copy(&cap->p2, &cap->axis); ccdVec3Scale(&cap->p2, -1.0); ccdVec3Add(&cap->p1, &cap->o.pos); ccdVec3Add(&cap->p2, &cap->o.pos); } static void ccdGeomToCyl(const dGeomID g, ccd_cyl_t *cyl) { dReal r, h; ccdGeomToObj(g, (ccd_obj_t *)cyl); dGeomCylinderGetParams(g, &r, &h); cyl->radius = r; ccdVec3Set(&cyl->axis, 0.0, 0.0, h / 2); ccdQuatRotVec(&cyl->axis, &cyl->o.rot); ccdVec3Copy(&cyl->p1, &cyl->axis); ccdVec3Copy(&cyl->p2, &cyl->axis); int cylAxisNormalizationResult = ccdVec3SafeNormalize(&cyl->axis); dUVERIFY(cylAxisNormalizationResult == 0, "Invalid cylinder has been passed"); ccdVec3Scale(&cyl->p2, -1.0); ccdVec3Add(&cyl->p1, &cyl->o.pos); ccdVec3Add(&cyl->p2, &cyl->o.pos); } static void ccdGeomToSphere(const dGeomID g, ccd_sphere_t *s) { ccdGeomToObj(g, (ccd_obj_t *)s); s->radius = dGeomSphereGetRadius(g); } static void ccdGeomToConvex(const dGeomID g, ccd_convex_t *c) { ccdGeomToObj(g, (ccd_obj_t *)c); c->convex = (dxConvex *)g; } static void ccdSupportBox(const void *obj, const ccd_vec3_t *_dir, ccd_vec3_t *v) { const ccd_box_t *o = (const ccd_box_t *)obj; ccd_vec3_t dir; ccdVec3Copy(&dir, _dir); ccdQuatRotVec(&dir, &o->o.rot_inv); ccdVec3Set(v, ccdSign(ccdVec3X(&dir)) * o->dim[0], ccdSign(ccdVec3Y(&dir)) * o->dim[1], ccdSign(ccdVec3Z(&dir)) * o->dim[2]); // transform support vertex ccdQuatRotVec(v, &o->o.rot); ccdVec3Add(v, &o->o.pos); } static void ccdSupportCap(const void *obj, const ccd_vec3_t *_dir, ccd_vec3_t *v) { const ccd_cap_t *o = (const ccd_cap_t *)obj; ccdVec3Copy(v, _dir); ccdVec3Scale(v, o->radius); if (ccdVec3Dot(_dir, &o->axis) > 0.0){ ccdVec3Add(v, &o->p1); }else{ ccdVec3Add(v, &o->p2); } } static void ccdSupportCyl(const void *obj, const ccd_vec3_t *_dir, ccd_vec3_t *v) { const ccd_cyl_t *cyl = (const ccd_cyl_t *)obj; ccd_vec3_t dir; ccd_real_t len; ccd_real_t dot = ccdVec3Dot(_dir, &cyl->axis); if (dot > 0.0){ ccdVec3Copy(v, &cyl->p1); } else{ ccdVec3Copy(v, &cyl->p2); } // project dir onto cylinder's 'top'/'bottom' plane ccdVec3Copy(&dir, &cyl->axis); ccdVec3Scale(&dir, -dot); ccdVec3Add(&dir, _dir); len = CCD_SQRT(ccdVec3Len2(&dir)); if (!ccdIsZero(len)) { ccdVec3Scale(&dir, cyl->radius / len); ccdVec3Add(v, &dir); } } static void ccdSupportSphere(const void *obj, const ccd_vec3_t *_dir, ccd_vec3_t *v) { const ccd_sphere_t *s = (const ccd_sphere_t *)obj; ccdVec3Copy(v, _dir); ccdVec3Scale(v, s->radius); dIASSERT(dFabs(CCD_SQRT(ccdVec3Len2(_dir)) - REAL(1.0)) < 1e-6); // ccdVec3Scale(v, CCD_ONE / CCD_SQRT(ccdVec3Len2(_dir))); ccdVec3Add(v, &s->o.pos); } static void ccdSupportConvex(const void *obj, const ccd_vec3_t *_dir, ccd_vec3_t *v) { const ccd_convex_t *c = (const ccd_convex_t *)obj; ccd_vec3_t dir, p; ccd_real_t maxdot, dot; sizeint i; const dReal *curp; ccdVec3Copy(&dir, _dir); ccdQuatRotVec(&dir, &c->o.rot_inv); maxdot = -CCD_REAL_MAX; curp = c->convex->points; for (i = 0; i < c->convex->pointcount; i++, curp += 3){ ccdVec3Set(&p, curp[0], curp[1], curp[2]); dot = ccdVec3Dot(&dir, &p); if (dot > maxdot){ ccdVec3Copy(v, &p); maxdot = dot; } } // transform support vertex ccdQuatRotVec(v, &c->o.rot); ccdVec3Add(v, &c->o.pos); } static void ccdCenter(const void *obj, ccd_vec3_t *c) { const ccd_obj_t *o = (const ccd_obj_t *)obj; ccdVec3Copy(c, &o->pos); } static int ccdCollide( dGeomID o1, dGeomID o2, int flags, dContactGeom *contact, int skip, void *obj1, ccd_support_fn supp1, ccd_center_fn cen1, void *obj2, ccd_support_fn supp2, ccd_center_fn cen2) { ccd_t ccd; int res; ccd_real_t depth; ccd_vec3_t dir, pos; int max_contacts = (flags & NUMC_MASK); if (max_contacts < 1) return 0; CCD_INIT(&ccd); ccd.support1 = supp1; ccd.support2 = supp2; ccd.center1 = cen1; ccd.center2 = cen2; ccd.max_iterations = 500; ccd.mpr_tolerance = (ccd_real_t)1E-6; if (flags & CONTACTS_UNIMPORTANT){ if (ccdMPRIntersect(obj1, obj2, &ccd)){ return 1; }else{ return 0; } } res = ccdMPRPenetration(obj1, obj2, &ccd, &depth, &dir, &pos); if (res == 0){ contact->g1 = o1; contact->g2 = o2; contact->side1 = contact->side2 = -1; contact->depth = depth; contact->pos[0] = ccdVec3X(&pos); contact->pos[1] = ccdVec3Y(&pos); contact->pos[2] = ccdVec3Z(&pos); ccdVec3Scale(&dir, -1.); contact->normal[0] = ccdVec3X(&dir); contact->normal[1] = ccdVec3Y(&dir); contact->normal[2] = ccdVec3Z(&dir); return 1; } return 0; } /*extern */ int dCollideBoxCylinderCCD(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) { ccd_cyl_t cyl; ccd_box_t box; ccdGeomToBox(o1, &box); ccdGeomToCyl(o2, &cyl); return ccdCollide(o1, o2, flags, contact, skip, &box, ccdSupportBox, ccdCenter, &cyl, ccdSupportCyl, ccdCenter); } /*extern */ int dCollideCapsuleCylinder(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) { ccd_cap_t cap; ccd_cyl_t cyl; ccdGeomToCap(o1, &cap); ccdGeomToCyl(o2, &cyl); return ccdCollide(o1, o2, flags, contact, skip, &cap, ccdSupportCap, ccdCenter, &cyl, ccdSupportCyl, ccdCenter); } /*extern */ int dCollideConvexBoxCCD(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) { ccd_box_t box; ccd_convex_t conv; ccdGeomToConvex(o1, &conv); ccdGeomToBox(o2, &box); return ccdCollide(o1, o2, flags, contact, skip, &conv, ccdSupportConvex, ccdCenter, &box, ccdSupportBox, ccdCenter); } /*extern */ int dCollideConvexCapsuleCCD(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) { ccd_cap_t cap; ccd_convex_t conv; ccdGeomToConvex(o1, &conv); ccdGeomToCap(o2, &cap); return ccdCollide(o1, o2, flags, contact, skip, &conv, ccdSupportConvex, ccdCenter, &cap, ccdSupportCap, ccdCenter); } /*extern */ int dCollideConvexSphereCCD(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) { ccd_sphere_t sphere; ccd_convex_t conv; ccdGeomToConvex(o1, &conv); ccdGeomToSphere(o2, &sphere); return ccdCollide(o1, o2, flags, contact, skip, &conv, ccdSupportConvex, ccdCenter, &sphere, ccdSupportSphere, ccdCenter); } /*extern */ int dCollideConvexCylinderCCD(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) { ccd_cyl_t cyl; ccd_convex_t conv; ccdGeomToConvex(o1, &conv); ccdGeomToCyl(o2, &cyl); return ccdCollide(o1, o2, flags, contact, skip, &conv, ccdSupportConvex, ccdCenter, &cyl, ccdSupportCyl, ccdCenter); } /*extern */ int dCollideConvexConvexCCD(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) { ccd_convex_t c1, c2; ccdGeomToConvex(o1, &c1); ccdGeomToConvex(o2, &c2); return ccdCollide(o1, o2, flags, contact, skip, &c1, ccdSupportConvex, ccdCenter, &c2, ccdSupportConvex, ccdCenter); } /*extern */ int dCollideCylinderCylinder(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) { ccd_cyl_t cyl1, cyl2; ccdGeomToCyl(o1, &cyl1); ccdGeomToCyl(o2, &cyl2); int numContacts = collideCylCyl(o1, o2, &cyl1, &cyl2, flags, contact, skip); if (numContacts < 0) { numContacts = ccdCollide(o1, o2, flags, contact, skip, &cyl1, ccdSupportCyl, ccdCenter, &cyl2, ccdSupportCyl, ccdCenter); } return numContacts; } static int collideCylCyl(dxGeom *o1, dxGeom *o2, ccd_cyl_t* cyl1, ccd_cyl_t* cyl2, int flags, dContactGeom *contacts, int skip) { int maxContacts = (flags & NUMC_MASK); dAASSERT(maxContacts != 0); maxContacts = maxContacts > 8 ? 8 : maxContacts; dReal axesProd = dFabs(ccdVec3Dot(&cyl1->axis, &cyl2->axis)); // Check if cylinders' axes are in line if (REAL(1.0) - axesProd < 1e-3f) { ccd_vec3_t p, proj; dReal r1, l1; dReal r2, l2; dGeomCylinderGetParams(o1, &r1, &l1); dGeomCylinderGetParams(o2, &r2, &l2); l1 *= 0.5f; l2 *= 0.5f; // Determine the cylinder with smaller radius (minCyl) and bigger radius (maxCyl) and their respective properties: radius, length bool r1IsMin; dReal rmin, rmax; ccd_cyl_t *minCyl, *maxCyl; if (r1 <= r2) { rmin = r1; rmax = r2; minCyl = cyl1; maxCyl = cyl2; r1IsMin = true; } else { rmin = r2; rmax = r1; minCyl = cyl2; maxCyl = cyl1; r1IsMin = false; } dReal lSum = l1 + l2; ccdVec3Copy(&p, &minCyl->o.pos); ccdVec3Sub(&p, &maxCyl->o.pos); dReal dot = ccdVec3Dot(&p, &maxCyl->axis); // Maximum possible contact depth dReal depth_v = lSum - dFabs(dot) + dSqrt(dMax(0, REAL(1.0) - axesProd * axesProd)) * rmin; if (depth_v < 0) { return 0; } // Project the smaller cylinder's center onto the larger cylinder's plane ccdVec3Copy(&proj, &maxCyl->axis); ccdVec3Scale(&proj, -dot); ccdVec3Add(&proj, &p); dReal radiiDiff = (dReal)sqrt(ccdVec3Len2(&proj)); dReal depth_h = r1 + r2 - radiiDiff; // Check the distance between cylinders' centers if (depth_h < 0) { return 0; } // Check if "vertical" contact depth is less than "horizontal" contact depth if (depth_v < depth_h) { int contactCount = 0; dReal dot2 = -ccdVec3Dot(&p, &minCyl->axis); // lmin, lmax - distances from cylinders' centers to potential contact points relative to cylinders' axes dReal lmax = r1IsMin ? l2 : l1; dReal lmin = r1IsMin ? l1 : l2; lmin = dot2 < 0 ? -lmin : lmin; lmax = dot < 0 ? -lmax : lmax; // Contact normal direction, relative to o1's axis dReal normaldir = (dot < 0) != r1IsMin ? REAL(1.0) : -REAL(1.0); if (rmin + radiiDiff <= rmax) { // Case 1: The smaller disc is fully contained within the larger one // Simply generate N points on the rim of the smaller disc dReal maxContactsRecip = (dReal)(0 < maxContacts ? (2.0 * M_PI / maxContacts) : (2.0 * M_PI)); // The 'else' value does not matter. Just try helping the optimizer. for (int i = 0; i < maxContacts; i++) { dReal depth; dReal a = maxContactsRecip * i; if (testAndPrepareDiscContactForAngle(a, rmin, lmin, lSum, minCyl, maxCyl, p, depth)) { contactCount = addCylCylContact(o1, o2, &maxCyl->axis, contacts, &p, normaldir, depth, contactCount, flags, skip); if ((flags & CONTACTS_UNIMPORTANT) != 0) { dIASSERT(contactCount != 0); break; } } } return contactCount; } else { // Case 2: Discs intersect // Firstly, find intersections assuming the larger cylinder is placed at (0,0,0) // http://math.stackexchange.com/questions/256100/how-can-i-find-the-points-at-which-two-circles-intersect ccd_vec3_t proj2; ccdVec3Copy(&proj2, &proj); ccdQuatRotVec(&proj, &maxCyl->o.rot_inv); dReal d = dSqrt(ccdVec3X(&proj) * ccdVec3X(&proj) + ccdVec3Y(&proj) * ccdVec3Y(&proj)); dIASSERT(d != REAL(0.0)); dReal dRecip = REAL(1.0) / d; dReal rmaxSquare = rmax * rmax, rminSquare = rmin * rmin, dSquare = d * d; dReal minA, diffA, minB, diffB; { dReal l = (rmaxSquare - rminSquare + dSquare) * (REAL(0.5) * dRecip); dReal h = dSqrt(rmaxSquare - l * l); dReal divLbyD = l * dRecip, divHbyD = h * dRecip; dReal x1 = divLbyD * ccdVec3X(&proj) + divHbyD * ccdVec3Y(&proj); dReal y1 = divLbyD * ccdVec3Y(&proj) - divHbyD * ccdVec3X(&proj); dReal x2 = divLbyD * ccdVec3X(&proj) - divHbyD * ccdVec3Y(&proj); dReal y2 = divLbyD * ccdVec3Y(&proj) + divHbyD * ccdVec3X(&proj); // Map the intersection points to angles dReal ap1 = dAtan2(y1, x1); dReal ap2 = dAtan2(y2, x2); minA = dMin(ap1, ap2); dReal maxA = dMax(ap1, ap2); // If the segment connecting cylinders' centers does not intersect the arc, change the angles dReal a = dAtan2(ccdVec3Y(&proj), ccdVec3X(&proj)); if (a < minA || a > maxA) { a = maxA; maxA = (dReal)(minA + M_PI * 2.0); minA = a; } diffA = maxA - minA; } // Do the same for the smaller cylinder assuming it is placed at (0,0,0) now ccdVec3Copy(&proj, &proj2); ccdVec3Scale(&proj, -1); ccdQuatRotVec(&proj, &minCyl->o.rot_inv); { dReal l = (rminSquare - rmaxSquare + dSquare) * (REAL(0.5) * dRecip); dReal h = dSqrt(rminSquare - l * l); dReal divLbyD = l * dRecip, divHbyD = h * dRecip; dReal x1 = divLbyD * ccdVec3X(&proj) + divHbyD * ccdVec3Y(&proj); dReal y1 = divLbyD * ccdVec3Y(&proj) - divHbyD * ccdVec3X(&proj); dReal x2 = divLbyD * ccdVec3X(&proj) - divHbyD * ccdVec3Y(&proj); dReal y2 = divLbyD * ccdVec3Y(&proj) + divHbyD * ccdVec3X(&proj); dReal ap1 = dAtan2(y1, x1); dReal ap2 = dAtan2(y2, x2); minB = dMin(ap1, ap2); dReal maxB = dMax(ap1, ap2); dReal a = dAtan2(ccdVec3Y(&proj), ccdVec3X(&proj)); if (a < minB || a > maxB) { a = maxB; maxB = (dReal)(minB + M_PI * 2.0); minB = a; } diffB = maxB - minB; } // Find contact point distribution ratio based on arcs lengths dReal ratio = diffA * rmax / (diffA * rmax + diffB * rmin); dIASSERT(ratio <= REAL(1.0)); dIASSERT(ratio >= REAL(0.0)); int nMax = (int)dFloor(ratio * maxContacts + REAL(0.5)); int nMin = maxContacts - nMax; dIASSERT(nMax <= maxContacts); // Make sure there is at least one point on the smaller radius rim if (nMin < 1) { nMin = 1; nMax -= 1; } // Otherwise transfer one point to the larger radius rim as it is going to fill the rim intersection points else if (nMin > 1) { nMin -= 1; nMax += 1; } // Smaller disc first, skipping the overlapping points dReal nMinRecip = 0 < nMin ? diffB / (nMin + 1) : diffB; // The 'else' value does not matter. Just try helping the optimizer. for (int i = 1; i <= nMin; i++) { dReal depth; dReal a = minB + nMinRecip * i; if (testAndPrepareDiscContactForAngle(a, rmin, lmin, lSum, minCyl, maxCyl, p, depth)) { contactCount = addCylCylContact(o1, o2, &maxCyl->axis, contacts, &p, normaldir, depth, contactCount, flags, skip); if ((flags & CONTACTS_UNIMPORTANT) != 0) { dIASSERT(contactCount != 0); break; } } } if (contactCount == 0 || (flags & CONTACTS_UNIMPORTANT) == 0) { // Then the larger disc, + additional point as the start/end points of arcs overlap // (or a single contact at the arc middle point if just one is required) dReal nMaxRecip = nMax > 1 ? diffA / (nMax - 1) : diffA; // The 'else' value does not matter. Just try helping the optimizer. dReal adjustedMinA = nMax == 1 ? minA + REAL(0.5) * diffA : minA; for (int i = 0; i < nMax; i++) { dReal depth; dReal a = adjustedMinA + nMaxRecip * i; if (testAndPrepareDiscContactForAngle(a, rmax, lmax, lSum, maxCyl, minCyl, p, depth)) { contactCount = addCylCylContact(o1, o2, &maxCyl->axis, contacts, &p, normaldir, depth, contactCount, flags, skip); if ((flags & CONTACTS_UNIMPORTANT) != 0) { dIASSERT(contactCount != 0); break; } } } } return contactCount; } } } return -1; } static bool testAndPrepareDiscContactForAngle(dReal angle, dReal radius, dReal length, dReal lSum, ccd_cyl_t *priCyl, ccd_cyl_t *secCyl, ccd_vec3_t &p, dReal &out_depth) { bool ret = false; ccd_vec3_t p2; ccdVec3Set(&p, dCos(angle) * radius, dSin(angle) * radius, 0); ccdQuatRotVec(&p, &priCyl->o.rot); ccdVec3Add(&p, &priCyl->o.pos); ccdVec3Copy(&p2, &p); ccdVec3Sub(&p2, &secCyl->o.pos); dReal depth = lSum - dFabs(ccdVec3Dot(&p2, &secCyl->axis)); if (depth >= 0) { ccdVec3Copy(&p2, &priCyl->axis); ccdVec3Scale(&p2, length); ccdVec3Add(&p, &p2); out_depth = depth; ret = true; } return ret; } static int addCylCylContact(dxGeom *o1, dxGeom *o2, ccd_vec3_t* axis, dContactGeom *contacts, ccd_vec3_t* p, dReal normaldir, dReal depth, int j, int flags, int skip) { dIASSERT(depth >= 0); dContactGeom* contact = SAFECONTACT(flags, contacts, j, skip); contact->g1 = o1; contact->g2 = o2; contact->side1 = -1; contact->side2 = -1; contact->normal[0] = normaldir * ccdVec3X(axis); contact->normal[1] = normaldir * ccdVec3Y(axis); contact->normal[2] = normaldir * ccdVec3Z(axis); contact->depth = depth; contact->pos[0] = ccdVec3X(p); contact->pos[1] = ccdVec3Y(p); contact->pos[2] = ccdVec3Z(p); return j + 1; } #if dTRIMESH_ENABLED const static float CONTACT_DEPTH_EPSILON = 0.0001f; const static float CONTACT_POS_EPSILON = 0.0001f; const static float CONTACT_PERTURBATION_ANGLE = 0.001f; const static float NORMAL_PROJ_EPSILON = 0.0001f; /*extern */ unsigned dCollideConvexTrimeshTrianglesCCD(dxGeom *o1, dxGeom *o2, const int *indices, unsigned numIndices, int flags, dContactGeom *contacts, int skip) { ccd_convex_t c1; ccd_triangle_t c2; dVector3 triangle[dMTV__MAX]; unsigned maxContacts = (flags & NUMC_MASK); unsigned contactCount = 0; ccdGeomToConvex(o1, &c1); ccdGeomToObj(o2, (ccd_obj_t *)&c2); IFaceAngleStorageView *meshFaceAngleView = dxGeomTriMeshGetFaceAngleView(o2); dUASSERT(meshFaceAngleView != NULL, "Please preprocess the trimesh data with dTRIDATAPREPROCESS_BUILD_FACE_ANGLES"); for (unsigned i = 0; i != numIndices; ++i) { dContactGeom tempContact; dGeomTriMeshGetTriangle(o2, indices[i], &triangle[dMTV_FIRST], &triangle[dMTV_SECOND], &triangle[dMTV_THIRD]); for (unsigned j = dMTV__MIN; j != dMTV__MAX; ++j) { ccdVec3Set(&c2.vertices[j], (ccd_real_t)triangle[j][dV3E_X], (ccd_real_t)triangle[j][dV3E_Y], (ccd_real_t)triangle[j][dV3E_Z]); } setObjPosToTriangleCenter(&c2); if (ccdCollide(o1, o2, flags, &tempContact, skip, &c1, &ccdSupportConvex, &ccdCenter, &c2, &ccdSupportTriangle, &ccdCenter) == 1) { tempContact.side2 = i; if (meshFaceAngleView == NULL || correctTriangleContactNormal(&c2, &tempContact, meshFaceAngleView, indices, numIndices)) { contactCount = addUniqueContact(contacts, &tempContact, contactCount, maxContacts, flags, skip); if ((flags & CONTACTS_UNIMPORTANT) != 0) { break; } } } } if ((flags & CONTACTS_UNIMPORTANT) == 0 && contactCount == 1) { dContactGeom *contact = SAFECONTACT(flags, contacts, 0, skip); dGeomTriMeshGetTriangle(o2, contact->side2, &triangle[dMTV_FIRST], &triangle[dMTV_SECOND], &triangle[dMTV_THIRD]); contactCount = addTrianglePerturbedContacts(o1, o2, meshFaceAngleView, indices, numIndices, flags, contacts, skip, &c1, &c2, triangle, contact, contactCount); } // Normalize accumulated normals, if necessary for (unsigned k = 0; k != contactCount; ) { dContactGeom *contact = SAFECONTACT(flags, contacts, k, skip); bool stayWithinThisIndex = false; // Only the merged contact normals need to be normalized if (*_const_type_cast_union(&contact->normal[dV3E_PAD])) { if (!dxSafeNormalize3(contact->normal)) { // If the contact normals have added up to zero, erase the contact // Normally the time step is to be shorter so that the objects do not get into each other that deep --contactCount; if (k != contactCount) { dContactGeom *lastContact = SAFECONTACT(flags, contacts, contactCount, skip); *contact = *lastContact; } stayWithinThisIndex = true; } } if (!stayWithinThisIndex) { ++k; } } return contactCount; } static unsigned addTrianglePerturbedContacts(dxGeom *o1, dxGeom *o2, IFaceAngleStorageView *meshFaceAngleView, const int *indices, unsigned numIndices, int flags, dContactGeom *contacts, int skip, ccd_convex_t *c1, ccd_triangle_t *c2, dVector3 *triangle, dContactGeom *contact, unsigned contacCount) { unsigned maxContacts = (flags & NUMC_MASK); dVector3 pos; dCopyVector3(pos, contact->pos); dQuaternion q1[2], q2[2]; dReal perturbationAngle = CONTACT_PERTURBATION_ANGLE; dVector3 upAxis; bool upAvailable = false; if (fabs(contact->normal[dV3E_Y]) > 0.7) { dAssignVector3(upAxis, 0, 0, 1); } else { dAssignVector3(upAxis, 0, 1, 0); } dVector3 cross; dCalcVectorCross3(cross, contact->normal, upAxis); if (dSafeNormalize3(cross)) { dCalcVectorCross3(upAxis, cross, contact->normal); if (dSafeNormalize3(upAxis)) { upAvailable = true; } } for (unsigned j = upAvailable ? 0 : 2; j != 2; ++j) { dQFromAxisAndAngle(q1[j], upAxis[dV3E_X], upAxis[dV3E_Y], upAxis[dV3E_Z], perturbationAngle); dQFromAxisAndAngle(q2[j], cross[dV3E_X], cross[dV3E_Y], cross[dV3E_Z], perturbationAngle); perturbationAngle = -perturbationAngle; } for (unsigned k = upAvailable ? 0 : 4; k != 4; ++k) { dQuaternion qr; dQMultiply0(qr, q1[k % 2], q2[k / 2]); for (unsigned j = dMTV__MIN; j != dMTV__MAX; ++j) { dVector3 p, perturbed; dSubtractVectors3(p, triangle[j], pos); dQuatTransform(qr, p, perturbed); dAddVectors3(perturbed, perturbed, pos); ccdVec3Set(&c2->vertices[j], (ccd_real_t)perturbed[dV3E_X], (ccd_real_t)perturbed[dV3E_Y], (ccd_real_t)perturbed[dV3E_Z]); } dContactGeom perturbedContact; setObjPosToTriangleCenter(c2); if (ccdCollide(o1, o2, flags, &perturbedContact, skip, c1, &ccdSupportConvex, &ccdCenter, c2, &ccdSupportTriangle, &ccdCenter) == 1) { perturbedContact.side2 = contact->side2; if (meshFaceAngleView == NULL || correctTriangleContactNormal(c2, &perturbedContact, meshFaceAngleView, indices, numIndices)) { contacCount = addUniqueContact(contacts, &perturbedContact, contacCount, maxContacts, flags, skip); } } } return contacCount; } static bool correctTriangleContactNormal(ccd_triangle_t *t, dContactGeom *contact, IFaceAngleStorageView *meshFaceAngleView, const int *indices, unsigned numIndices) { dIASSERT(meshFaceAngleView != NULL); bool anyFault = false; ccd_vec3_t cntOrigNormal, cntNormal; ccdVec3Set(&cntNormal, contact->normal[0], contact->normal[1], contact->normal[2]); ccdVec3Copy(&cntOrigNormal, &cntNormal); // Check if the contact point is located close to any edge - move it back and forth // and check the resulting segment for intersection with the edge plane ccd_vec3_t cntScaledNormal; ccdVec3CopyScaled(&cntScaledNormal, &cntNormal, contact->depth); ccd_vec3_t edges[dMTV__MAX]; ccdVec3Sub2(&edges[dMTV_THIRD], &t->vertices[0], &t->vertices[2]); ccdVec3Sub2(&edges[dMTV_SECOND], &t->vertices[2], &t->vertices[1]); ccdVec3Sub2(&edges[dMTV_FIRST], &t->vertices[1], &t->vertices[0]); dSASSERT(dMTV__MAX == 3); bool contactGenerated = false, contactPreserved = false; // Triangle face normal ccd_vec3_t triNormal; ccdVec3Cross(&triNormal, &edges[dMTV_FIRST], &edges[dMTV_SECOND]); if (ccdVec3SafeNormalize(&triNormal) != 0) { anyFault = true; } // Check the edges to see if one of them is involved for (unsigned testEdgeIndex = !anyFault ? dMTV__MIN : dMTV__MAX; testEdgeIndex != dMTV__MAX; ++testEdgeIndex) { ccd_vec3_t edgeNormal, vertexToPos, v; ccd_vec3_t &edgeAxis = edges[testEdgeIndex]; // Edge axis if (ccdVec3SafeNormalize(&edgeAxis) != 0) { // This should not happen normally as in the case on of edges is degenerated // the triangle normal calculation would have to fail above. If for some // reason the above calculation succeeds and this one would not, it is // OK to break as this point as well. anyFault = true; break; } // Edge Normal ccdVec3Cross(&edgeNormal, &edgeAxis, &triNormal); // ccdVec3Normalize(&edgeNormal); -- the two vectors above were already normalized and perpendicular // Check if the contact point is located close to any edge - move it back and forth // and check the resulting segment for intersection with the edge plane ccdVec3Set(&vertexToPos, contact->pos[0], contact->pos[1], contact->pos[2]); ccdVec3Sub(&vertexToPos, &t->vertices[testEdgeIndex]); ccdVec3Sub2(&v, &vertexToPos, &cntScaledNormal); if (ccdVec3Dot(&edgeNormal, &v) < 0) { ccdVec3Add2(&v, &vertexToPos, &cntScaledNormal); if (ccdVec3Dot(&edgeNormal, &v) > 0) { // This is an edge contact ccd_real_t x = ccdVec3Dot(&triNormal, &cntNormal); ccd_real_t y = ccdVec3Dot(&edgeNormal, &cntNormal); ccd_real_t contactNormalToTriangleNormalAngle = CCD_ATAN2(y, x); dReal angleValueAsDRead; FaceAngleDomain angleDomain = meshFaceAngleView->retrieveFacesAngleFromStorage(angleValueAsDRead, contact->side2, (dMeshTriangleVertex)testEdgeIndex); ccd_real_t angleValue = (ccd_real_t)angleValueAsDRead; ccd_real_t targetAngle; contactGenerated = false, contactPreserved = false; // re-assign to make optimizer's task easier if (angleDomain != FAD_CONCAVE) { // Convex or flat - ensure the contact normal is within the allowed range // formed by the two triangles' normals. if (contactNormalToTriangleNormalAngle < CCD_ZERO) { targetAngle = CCD_ZERO; } else if (contactNormalToTriangleNormalAngle > angleValue) { targetAngle = angleValue; } else { contactPreserved = true; } } else { // Concave - rotate the contact normal to the face angle bisect plane // (or to triangle normal-edge plane if negative angles are not stored) targetAngle = angleValue != 0 ? CCD_REAL(0.5) * angleValue : CCD_ZERO; // There is little chance the normal will initially match the correct plane, but still, a small check could save lots of calculations if (contactNormalToTriangleNormalAngle == targetAngle) { contactPreserved = true; } } if (!contactPreserved) { ccd_quat_t q; ccdQuatSetAngleAxis(&q, targetAngle - contactNormalToTriangleNormalAngle, &edgeAxis); ccdQuatRotVec2(&cntNormal, &cntNormal, &q); contactGenerated = true; } // Calculated successfully break; } } } if (!anyFault && !contactPreserved) { // No edge contact detected, set contact normal to triangle normal const ccd_vec3_t &cntNormalToUse = !contactGenerated ? triNormal : cntNormal; contact->normal[dV3E_X] = ccdVec3X(&cntNormalToUse); contact->normal[dV3E_Y] = ccdVec3Y(&cntNormalToUse); contact->normal[dV3E_Z] = ccdVec3Z(&cntNormalToUse); contact->depth *= CCD_FMAX(0.0, ccdVec3Dot(&cntOrigNormal, &cntNormalToUse)); } bool result = !anyFault; return result; } static unsigned addUniqueContact(dContactGeom *contacts, dContactGeom *c, unsigned contactcount, unsigned maxcontacts, int flags, int skip) { dReal minDepth = c->depth; unsigned index = contactcount; bool isDuplicate = false; dReal c_posX = c->pos[dV3E_X], c_posY = c->pos[dV3E_Y], c_posZ = c->pos[dV3E_Z]; for (unsigned k = 0; k != contactcount; k++) { dContactGeom* pc = SAFECONTACT(flags, contacts, k, skip); if (fabs(c_posX - pc->pos[dV3E_X]) < CONTACT_POS_EPSILON && fabs(c_posY - pc->pos[dV3E_Y]) < CONTACT_POS_EPSILON && fabs(c_posZ - pc->pos[dV3E_Z]) < CONTACT_POS_EPSILON) { dSASSERT(dV3E__AXES_MAX - dV3E__AXES_MIN == 3); // Accumulate similar contacts dAddVectors3(pc->normal, pc->normal, c->normal); pc->depth = dMax(pc->depth, c->depth); *_type_cast_union(&pc->normal[dV3E_PAD]) = true; // Mark the contact as a merged one isDuplicate = true; break; } if (contactcount == maxcontacts && pc->depth < minDepth) { minDepth = pc->depth; index = k; } } if (!isDuplicate && index < maxcontacts) { dContactGeom* contact = SAFECONTACT(flags, contacts, index, skip); contact->g1 = c->g1; contact->g2 = c->g2; contact->depth = c->depth; contact->side1 = c->side1; contact->side2 = c->side2; dCopyVector3(contact->pos, c->pos); dCopyVector3(contact->normal, c->normal); *_type_cast_union(&contact->normal[dV3E_PAD]) = false; // Indicates whether the contact is merged or not contactcount = index == contactcount ? contactcount + 1 : contactcount; } return contactcount; } static void setObjPosToTriangleCenter(ccd_triangle_t *t) { ccdVec3Set(&t->o.pos, 0, 0, 0); for (int j = 0; j < 3; j++) { ccdVec3Add(&t->o.pos, &t->vertices[j]); } ccdVec3Scale(&t->o.pos, 1.0f / 3.0f); } static void ccdSupportTriangle(const void *obj, const ccd_vec3_t *_dir, ccd_vec3_t *v) { const ccd_triangle_t* o = (ccd_triangle_t *) obj; ccd_real_t maxdot, dot; maxdot = -CCD_REAL_MAX; for (unsigned i = 0; i != 3; i++) { dot = ccdVec3Dot(_dir, &o->vertices[i]); if (dot > maxdot) { ccdVec3Copy(v, &o->vertices[i]); maxdot = dot; } } } #endif // dTRIMESH_ENABLED ode-0.16/ode/src/threadingutils.h0000664000175200017520000001303213403272463013676 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_THREADINGUTILS_H_ #define _ODE_THREADINGUTILS_H_ #include "odeou.h" #if !dTHREADING_INTF_DISABLED static inline bool ThrsafeCompareExchange(volatile atomicord32 *paoDestination, atomicord32 aoComparand, atomicord32 aoExchange) { return AtomicCompareExchange(paoDestination, aoComparand, aoExchange); } static inline atomicord32 ThrsafeExchange(volatile atomicord32 *paoDestination, atomicord32 aoExchange) { return AtomicExchange(paoDestination, aoExchange); } static inline void ThrsafeAdd(volatile atomicord32 *paoDestination, atomicord32 aoAddend) { AtomicExchangeAddNoResult(paoDestination, aoAddend); } static inline atomicord32 ThrsafeExchangeAdd(volatile atomicord32 *paoDestination, atomicord32 aoAddend) { return AtomicExchangeAdd(paoDestination, aoAddend); } static inline bool ThrsafeCompareExchangePointer(volatile atomicptr *papDestination, atomicptr apComparand, atomicptr apExchange) { return AtomicCompareExchangePointer(papDestination, apComparand, apExchange); } static inline atomicptr ThrsafeExchangePointer(volatile atomicptr *papDestination, atomicptr apExchange) { return AtomicExchangePointer(papDestination, apExchange); } #else // #if dTHREADING_INTF_DISABLED static inline bool ThrsafeCompareExchange(volatile atomicord32 *paoDestination, atomicord32 aoComparand, atomicord32 aoExchange) { return (*paoDestination == aoComparand) ? ((*paoDestination = aoExchange), true) : false; } static inline atomicord32 ThrsafeExchange(volatile atomicord32 *paoDestination, atomicord32 aoExchange) { atomicord32 aoDestinationValue = *paoDestination; *paoDestination = aoExchange; return aoDestinationValue; } static inline void ThrsafeAdd(volatile atomicord32 *paoDestination, atomicord32 aoAddend) { *paoDestination += aoAddend; } static inline atomicord32 ThrsafeExchangeAdd(volatile atomicord32 *paoDestination, atomicord32 aoAddend) { atomicord32 aoDestinationValue = *paoDestination; *paoDestination += aoAddend; return aoDestinationValue; } static inline bool ThrsafeCompareExchangePointer(volatile atomicptr *papDestination, atomicptr apComparand, atomicptr apExchange) { return (*papDestination == apComparand) ? ((*papDestination = apExchange), true) : false; } static inline atomicptr ThrsafeExchangePointer(volatile atomicptr *papDestination, atomicptr apExchange) { atomicptr apDestinationValue = *papDestination; *papDestination = apExchange; return apDestinationValue; } #endif // #if dTHREADING_INTF_DISABLED static inline unsigned int ThrsafeIncrementIntUpToLimit(volatile atomicord32 *storagePointer, unsigned int limitValue) { unsigned int resultValue; while (true) { resultValue = *storagePointer; // The ">=" comparison is used here to allow continuing incrementing the destination // without waiting for all the threads to pass the barrier of checking its value if (resultValue >= limitValue) { resultValue = limitValue; break; } if (ThrsafeCompareExchange(storagePointer, (atomicord32)resultValue, (atomicord32)(resultValue + 1))) { break; } } return resultValue; } static inline sizeint ThrsafeIncrementSizeUpToLimit(volatile sizeint *storagePointer, sizeint limitValue) { sizeint resultValue; while (true) { resultValue = *storagePointer; // The ">=" comparison is not required here at present ("==" could be used). // It is just used this way to match the other function above. if (resultValue >= limitValue) { resultValue = limitValue; break; } if (ThrsafeCompareExchangePointer((volatile atomicptr *)storagePointer, (atomicptr)resultValue, (atomicptr)(resultValue + 1))) { break; } } return resultValue; } #endif // _ODE_THREADINGUTILS_H_ ode-0.16/ode/src/threading_impl.h0000664000175200017520000000411013403272463013633 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * Threading implementation private header file. * * Copyright (C) 2011-2012 Oleh Derevenko. All rights reserved. * * e-mail: odar@eleks.com (change all "a" to "e") * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* * Threading implementation header for library private functions. */ #ifndef _ODE__PRIVATE_THREADING_IMPL_H_ #define _ODE__PRIVATE_THREADING_IMPL_H_ #include #endif // #ifndef _ODE__PRIVATE_THREADING_IMPL_H_ ode-0.16/ode/src/matrix.cpp0000664000175200017520000004242013403272463012512 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include "config.h" #include "matrix.h" #include "objects.h" #include "threaded_solver_ldlt.h" #include // misc defines #define ALLOCA dALLOCA16 #define STACK_ALLOC_MAX 8192U /*extern */ void dxMultiply0(dReal *A, const dReal *B, const dReal *C, unsigned p, unsigned q, unsigned r) { dAASSERT (A && B && C && p>0 && q>0 && r>0); const unsigned qskip = dPAD(q); const unsigned rskip = dPAD(r); dReal *aa = A; const dReal *bb = B; for (unsigned i = p; i != 0; aa+=rskip, bb+=qskip, --i) { dReal *a = aa; const dReal *cc = C, *ccend = C + r; for (; cc != ccend; ++a, ++cc) { dReal sum = REAL(0.0); const dReal *c = cc; const dReal *b = bb, *bend = bb + q; for (; b != bend; c+=rskip, ++b) { sum += (*b) * (*c); } (*a) = sum; } } } /*extern */ void dxMultiply1(dReal *A, const dReal *B, const dReal *C, unsigned p, unsigned q, unsigned r) { dAASSERT (A && B && C && p>0 && q>0 && r>0); const unsigned pskip = dPAD(p); const unsigned rskip = dPAD(r); dReal *aa = A; const dReal *bb = B, *bbend = B + p; for (; bb != bbend; aa += rskip, ++bb) { dReal *a = aa; const dReal *cc = C, *ccend = C + r; for (; cc != ccend; ++a, ++cc) { dReal sum = REAL(0.0); const dReal *b = bb, *c = cc; for (unsigned k = q; k != 0; b += pskip, c += rskip, --k) { sum += (*b) * (*c); } (*a) = sum; } } } /*extern */ void dxMultiply2(dReal *A, const dReal *B, const dReal *C, unsigned p, unsigned q, unsigned r) { dAASSERT (A && B && C && p>0 && q>0 && r>0); const unsigned rskip = dPAD(r); const unsigned qskip = dPAD(q); dReal *aa = A; const dReal *bb = B; for (unsigned i = p; i != 0; aa += rskip, bb += qskip, --i) { dReal *a = aa, *aend = aa + r; const dReal *cc = C; for (; a != aend; cc+=qskip, ++a) { dReal sum = REAL(0.0); const dReal *b = bb, *c = cc, *cend = cc + q; for (; c != cend; ++b, ++c) { sum += (*b) * (*c); } (*a) = sum; } } } /*extern */ int dxFactorCholesky(dReal *A, unsigned n, void *tmpBuf/*[n]*/) { dAASSERT (n > 0 && A); bool failure = false; dReal *alloctedBuf = NULL; sizeint allocatedSize; const unsigned nskip = dPAD (n); dReal *recip = (dReal *)tmpBuf; if (tmpBuf == NULL) { allocatedSize = n * sizeof(dReal); alloctedBuf = allocatedSize > STACK_ALLOC_MAX ? (dReal *)dAlloc(allocatedSize) : NULL; recip = alloctedBuf != NULL ? alloctedBuf : (dReal*)ALLOCA(allocatedSize); } dReal *aa = A; for (unsigned i = 0; i < n; aa += nskip, ++i) { dReal *cc = aa; { const dReal *bb = A; for (unsigned j = 0; j < i; bb += nskip, ++cc, ++j) { dReal sum = *cc; const dReal *a = aa, *b = bb, *bend = bb + j; for (; b != bend; ++a, ++b) { sum -= (*a) * (*b); } *cc = sum * recip[j]; } } { dReal sum = *cc; dReal *a = aa, *aend = aa + i; for (; a != aend; ++a) { sum -= (*a)*(*a); } if (sum <= REAL(0.0)) { failure = true; break; } dReal sumsqrt = dSqrt(sum); *cc = sumsqrt; recip[i] = dRecip (sumsqrt); } } if (alloctedBuf != NULL) { dFree(alloctedBuf, allocatedSize); } return failure ? 0 : 1; } /*extern */ void dxSolveCholesky(const dReal *L, dReal *b, unsigned n, void *tmpBuf/*[n]*/) { dAASSERT (n > 0 && L && b); dReal *alloctedBuf = NULL; sizeint allocatedSize; const unsigned nskip = dPAD (n); dReal *y = (dReal *)tmpBuf; if (tmpBuf == NULL) { allocatedSize = n * sizeof(dReal); alloctedBuf = allocatedSize > STACK_ALLOC_MAX ? (dReal *)dAlloc(allocatedSize) : NULL; y = alloctedBuf != NULL ? alloctedBuf : (dReal*)ALLOCA(allocatedSize); } { const dReal *ll = L; for (unsigned i = 0; i < n; ll += nskip, ++i) { dReal sum = REAL(0.0); for (unsigned k = 0; k < i; ++k) { sum += ll[k] * y[k]; } dIASSERT(ll[i] != dReal(0.0)); y[i] = (b[i] - sum) / ll[i]; } } { const dReal *ll = L + (n - 1) * (nskip + 1); for (unsigned i = n; i > 0; ll -= nskip + 1) { --i; dReal sum = REAL(0.0); const dReal *l = ll + nskip; for (unsigned k = i + 1; k < n; l += nskip, ++k) { sum += (*l) * b[k]; } dIASSERT(*ll != dReal(0.0)); b[i] = (y[i] - sum) / (*ll); } } if (alloctedBuf != NULL) { dFree(alloctedBuf, allocatedSize); } } /*extern */ int dxInvertPDMatrix(const dReal *A, dReal *Ainv, unsigned n, void *tmpBuf/*[nskip*(n+2)]*/) { dAASSERT (n > 0 && A && Ainv); bool success = false; dReal *alloctedBuf = NULL; sizeint allocatedSize; sizeint choleskyFactorSize = dxEstimateFactorCholeskyTmpbufSize(n); sizeint choleskySolveSize = dxEstimateSolveCholeskyTmpbufSize(n); sizeint choleskyMaxSize = dMACRO_MAX(choleskyFactorSize, choleskySolveSize); dIASSERT(choleskyMaxSize % sizeof(dReal) == 0); const unsigned nskip = dPAD (n); const sizeint nskip_mul_n = (sizeint)nskip * n; dReal *tmp = (dReal *)tmpBuf; if (tmpBuf == NULL) { allocatedSize = choleskyMaxSize + (nskip + nskip_mul_n) * sizeof(dReal); alloctedBuf = allocatedSize > STACK_ALLOC_MAX ? (dReal *)dAlloc(allocatedSize) : NULL; tmp = alloctedBuf != NULL ? alloctedBuf : (dReal*)ALLOCA(allocatedSize); } dReal *X = (dReal *)((char *)tmp + choleskyMaxSize); dReal *L = X + nskip; memcpy (L, A, nskip_mul_n * sizeof(dReal)); if (dxFactorCholesky(L, n, tmp)) { dSetZero (Ainv, nskip_mul_n); // make sure all padding elements set to 0 dReal *aa = Ainv, *xi = X, *xiend = X + n; for (; xi != xiend; ++aa, ++xi) { dSetZero(X, n); *xi = REAL(1.0); dxSolveCholesky(L, X, n, tmp); dReal *a = aa; const dReal *x = X, *xend = X + n; for (; x != xend; a += nskip, ++x) { *a = *x; } } success = true; } if (alloctedBuf != NULL) { dFree(alloctedBuf, allocatedSize); } return success ? 1 : 0; } /*extern */ int dxIsPositiveDefinite(const dReal *A, unsigned n, void *tmpBuf/*[nskip*(n+1)]*/) { dAASSERT (n > 0 && A); dReal *alloctedBuf = NULL; sizeint allocatedSize; sizeint choleskyFactorSize = dxEstimateFactorCholeskyTmpbufSize(n); dIASSERT(choleskyFactorSize % sizeof(dReal) == 0); const unsigned nskip = dPAD (n); const sizeint nskip_mul_n = (sizeint)nskip * n; dReal *tmp = (dReal *)tmpBuf; if (tmpBuf == NULL) { allocatedSize = choleskyFactorSize + nskip_mul_n * sizeof(dReal); alloctedBuf = allocatedSize > STACK_ALLOC_MAX ? (dReal *)dAlloc(allocatedSize) : NULL; tmp = alloctedBuf != NULL ? alloctedBuf : (dReal*)ALLOCA(allocatedSize); } dReal *Acopy = (dReal *)((char *)tmp + choleskyFactorSize); memcpy(Acopy, A, nskip_mul_n * sizeof(dReal)); int factorResult = dxFactorCholesky (Acopy, n, tmp); if (alloctedBuf != NULL) { dFree(alloctedBuf, allocatedSize); } return factorResult; } /*extern */ void dxLDLTAddTL(dReal *L, dReal *d, const dReal *a, unsigned n, unsigned nskip, void *tmpBuf/*[2*nskip]*/) { dAASSERT(L && d && a && n > 0 && nskip >= n); if (n < 2) return; dReal *alloctedBuf = NULL; sizeint allocatedSize; dReal *W1 = (dReal *)tmpBuf; if (tmpBuf == NULL) { allocatedSize = nskip * (2 * sizeof(dReal)); alloctedBuf = allocatedSize > STACK_ALLOC_MAX ? (dReal *)dAlloc(allocatedSize) : NULL; W1 = alloctedBuf != NULL ? alloctedBuf : (dReal*)ALLOCA(allocatedSize); } dReal *W2 = W1 + nskip; W1[0] = REAL(0.0); W2[0] = REAL(0.0); for (unsigned j = 1; j < n; ++j) { W1[j] = W2[j] = (dReal) (a[j] * M_SQRT1_2); } dReal W11 = (dReal) ((REAL(0.5)*a[0]+1)*M_SQRT1_2); dReal W21 = (dReal) ((REAL(0.5)*a[0]-1)*M_SQRT1_2); dReal alpha1 = REAL(1.0); dReal alpha2 = REAL(1.0); { dReal dee = d[0]; dReal alphanew = alpha1 + (W11*W11)*dee; dIASSERT(alphanew != dReal(0.0)); dee /= alphanew; dReal gamma1 = W11 * dee; dee *= alpha1; alpha1 = alphanew; alphanew = alpha2 - (W21*W21)*dee; dee /= alphanew; //dReal gamma2 = W21 * dee; alpha2 = alphanew; dReal k1 = REAL(1.0) - W21*gamma1; dReal k2 = W21*gamma1*W11 - W21; dReal *ll = L + nskip; for (unsigned p = 1; p < n; ll += nskip, ++p) { dReal Wp = W1[p]; dReal ell = *ll; W1[p] = Wp - W11*ell; W2[p] = k1*Wp + k2*ell; } } dReal *ll = L + (nskip + 1); for (unsigned j = 1; j < n; ll += nskip + 1, ++j) { dReal k1 = W1[j]; dReal k2 = W2[j]; dReal dee = d[j]; dReal alphanew = alpha1 + (k1*k1)*dee; dIASSERT(alphanew != dReal(0.0)); dee /= alphanew; dReal gamma1 = k1 * dee; dee *= alpha1; alpha1 = alphanew; alphanew = alpha2 - (k2*k2)*dee; dee /= alphanew; dReal gamma2 = k2 * dee; dee *= alpha2; d[j] = dee; alpha2 = alphanew; dReal *l = ll + nskip; for (unsigned p = j + 1; p < n; l += nskip, ++p) { dReal ell = *l; dReal Wp = W1[p] - k1 * ell; ell += gamma1 * Wp; W1[p] = Wp; Wp = W2[p] - k2 * ell; ell -= gamma2 * Wp; W2[p] = Wp; *l = ell; } } if (alloctedBuf != NULL) { dFree(alloctedBuf, allocatedSize); } } // macros for dLDLTRemove() for accessing A - either access the matrix // directly or access it via row pointers. we are only supposed to reference // the lower triangle of A (it is symmetric), but indexes i and j come from // permutation vectors so they are not predictable. so do a test on the // indexes - this should not slow things down too much, as we don't do this // in an inner loop. #define _GETA(i,j) (A[i][j]) //#define _GETA(i,j) (A[(i)*nskip+(j)]) #define GETA(i,j) ((i > j) ? _GETA(i,j) : _GETA(j,i)) /*extern */ void dxLDLTRemove(dReal **A, const unsigned *p, dReal *L, dReal *d, unsigned n1, unsigned n2, unsigned r, unsigned nskip, void *tmpBuf/*n2 + 2*nskip*/) { dAASSERT(A && p && L && d && n1 > 0 && n2 > 0 /*&& r >= 0 */&& r < n2 && n1 >= n2 && nskip >= n1); #ifndef dNODEBUG for (unsigned i = 0; i < n2; ++i) dIASSERT(p[i] >= 0 && p[i] < n1); #endif if (r == n2 - 1) { return; // deleting the last row/col is easy } dReal *alloctedBuf = NULL; sizeint allocatedSize; sizeint LDLTAddTLSize = dxEstimateLDLTAddTLTmpbufSize(nskip); dIASSERT(LDLTAddTLSize % sizeof(dReal) == 0); dReal *tmp = (dReal *)tmpBuf; if (tmpBuf == NULL) { allocatedSize = LDLTAddTLSize + n2 * sizeof(dReal); alloctedBuf = allocatedSize > STACK_ALLOC_MAX ? (dReal *)dAlloc(allocatedSize) : NULL; tmp = alloctedBuf != NULL ? alloctedBuf : (dReal*)ALLOCA(allocatedSize); } if (r == 0) { dReal *a = (dReal *)((char *)tmp + LDLTAddTLSize); const unsigned p_0 = p[0]; for (unsigned i = 0; i < n2; ++i) { a[i] = -GETA(p[i],p_0); } a[0] += REAL(1.0); dxLDLTAddTL (L, d, a, n2, nskip, tmp); } else { dReal *t = (dReal *)((char *)tmp + LDLTAddTLSize); { dReal *Lcurr = L + r*nskip; for (unsigned i = 0; i < r; ++Lcurr, ++i) { dIASSERT(d[i] != dReal(0.0)); t[i] = *Lcurr / d[i]; } } dReal *a = t + r; { dReal *Lcurr = L + r * nskip; const unsigned *pp_r = p + r, p_r = *pp_r; const unsigned n2_minus_r = n2 - r; for (unsigned i = 0; i < n2_minus_r; Lcurr += nskip, ++i) { a[i] = dDot(Lcurr, t, r) - GETA(pp_r[i], p_r); } } a[0] += REAL(1.0); dxLDLTAddTL (L + (sizeint)(nskip + 1) * r, d + r, a, n2 - r, nskip, tmp); } // snip out row/column r from L and d dxRemoveRowCol (L, n2, nskip, r); if (r < (n2 - 1)) memmove (d + r, d + r + 1, (n2 - r - 1) * sizeof(dReal)); if (alloctedBuf != NULL) { dFree(alloctedBuf, allocatedSize); } } /*extern */ void dxRemoveRowCol(dReal *A, unsigned n, unsigned nskip, unsigned r) { dAASSERT(A && n > 0 && nskip >= n && r >= 0 && r < n); if (r >= n - 1) return; if (r > 0) { { const sizeint move_size = (n - r - 1) * sizeof(dReal); dReal *Adst = A + r; for (unsigned i = 0; i < r; Adst += nskip, ++i) { dReal *Asrc = Adst + 1; memmove (Adst, Asrc, move_size); } } { const sizeint cpy_size = r * sizeof(dReal); dReal *Adst = A + (sizeint)nskip * r; unsigned n1 = n - 1; for (unsigned i = r; i < n1; ++i) { dReal *Asrc = Adst + nskip; memcpy (Adst, Asrc, cpy_size); Adst = Asrc; } } } { const sizeint cpy_size = (n - r - 1) * sizeof(dReal); dReal *Adst = A + (sizeint)(nskip + 1) * r; unsigned n1 = n - 1; for (unsigned i = r; i < n1; ++i) { dReal *Asrc = Adst + (nskip + 1); memcpy (Adst, Asrc, cpy_size); Adst = Asrc - 1; } } } #undef dSetZero #undef dSetValue //#undef dDot #undef dMultiply0 #undef dMultiply1 #undef dMultiply2 #undef dFactorCholesky #undef dSolveCholesky #undef dInvertPDMatrix #undef dIsPositiveDefinite #undef dLDLTAddTL #undef dLDLTRemove #undef dRemoveRowCol /*extern ODE_API */ void dSetZero(dReal *a, int n) { dxSetZero(a, n); } /*extern ODE_API */ void dSetValue(dReal *a, int n, dReal value) { dxSetValue(a, n, value); } // dReal dDot (const dReal *a, const dReal *b, int n); /*extern ODE_API */ void dMultiply0(dReal *A, const dReal *B, const dReal *C, int p,int q,int r) { dxMultiply0(A, B, C, p, q, r); } /*extern ODE_API */ void dMultiply1(dReal *A, const dReal *B, const dReal *C, int p,int q,int r) { dxMultiply1(A, B, C, p, q, r); } /*extern ODE_API */ void dMultiply2(dReal *A, const dReal *B, const dReal *C, int p,int q,int r) { dxMultiply2(A, B, C, p, q, r); } /*extern ODE_API */ int dFactorCholesky(dReal *A, int n) { return dxFactorCholesky(A, n, NULL); } /*extern ODE_API */ void dSolveCholesky(const dReal *L, dReal *b, int n) { dxSolveCholesky(L, b, n, NULL); } /*extern ODE_API */ int dInvertPDMatrix (const dReal *A, dReal *Ainv, int n) { return dxInvertPDMatrix(A, Ainv, n, NULL); } /*extern ODE_API */ int dIsPositiveDefinite(const dReal *A, int n) { return dxIsPositiveDefinite(A, n, NULL); } /*extern ODE_API */ void dLDLTAddTL(dReal *L, dReal *d, const dReal *a, int n, int nskip) { dxLDLTAddTL(L, d, a, n, nskip, NULL); } /*extern ODE_API */ void dLDLTRemove(dReal **A, const int *p, dReal *L, dReal *d, int n1, int n2, int r, int nskip) { dxLDLTRemove(A, (const unsigned *)p, L, d, n1, n2, r, nskip, NULL); dSASSERT(sizeof(unsigned) == sizeof(*p)); } /*extern ODE_API */ void dRemoveRowCol(dReal *A, int n, int nskip, int r) { dxRemoveRowCol(A, n, nskip, r); } ode-0.16/ode/src/heightfield.h0000664000175200017520000002006713403272463013132 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ // dHeightfield Collider // Martijn Buijs 2006 http://home.planet.nl/~buijs512/ // Based on Terrain & Cone contrib by: // Benoit CHAPEROT 2003-2004 http://www.jstarlab.com #ifndef _DHEIGHTFIELD_H_ #define _DHEIGHTFIELD_H_ //------------------------------------------------------------------------------ #include #include "collision_kernel.h" #define HEIGHTFIELDMAXCONTACTPERCELL 10 class HeightFieldVertex; class HeightFieldEdge; class HeightFieldTriangle; // // dxHeightfieldData // // Heightfield Data structure // struct dxHeightfieldData { dReal m_fWidth; // World space heightfield dimension on X axis dReal m_fDepth; // World space heightfield dimension on Z axis dReal m_fSampleWidth; // Vertex spacing on X axis edge (== m_vWidth / (m_nWidthSamples-1)) dReal m_fSampleDepth; // Vertex spacing on Z axis edge (== m_vDepth / (m_nDepthSamples-1)) dReal m_fSampleZXAspect; // Relation of Z axis spacing to X axis spacing (== m_fSampleDepth / m_fSampleWidth) dReal m_fInvSampleWidth; // Cache of inverse Vertex count on X axis edge (== m_vWidth / (m_nWidthSamples-1)) dReal m_fInvSampleDepth; // Cache of inverse Vertex count on Z axis edge (== m_vDepth / (m_nDepthSamples-1)) dReal m_fHalfWidth; // Cache of half of m_fWidth dReal m_fHalfDepth; // Cache of half of m_fDepth dReal m_fMinHeight; // Min sample height value (scaled and offset) dReal m_fMaxHeight; // Max sample height value (scaled and offset) dReal m_fThickness; // Surface thickness (added to bottom AABB) dReal m_fScale; // Sample value multiplier dReal m_fOffset; // Vertical sample offset int m_nWidthSamples; // Vertex count on X axis edge (number of samples) int m_nDepthSamples; // Vertex count on Z axis edge (number of samples) int m_bCopyHeightData; // Do we own the sample data? int m_bWrapMode; // Heightfield wrapping mode (0=finite, 1=infinite) int m_nGetHeightMode; // GetHeight mode ( 0=callback, 1=byte, 2=short, 3=float ) const void* m_pHeightData; // Sample data array void* m_pUserData; // Callback user data dContactGeom m_contacts[HEIGHTFIELDMAXCONTACTPERCELL]; dHeightfieldGetHeight* m_pGetHeightCallback; // Callback pointer. dxHeightfieldData(); ~dxHeightfieldData(); void SetData( int nWidthSamples, int nDepthSamples, dReal fWidth, dReal fDepth, dReal fScale, dReal fOffset, dReal fThickness, int bWrapMode ); void ComputeHeightBounds(); bool IsOnHeightfield2 ( const HeightFieldVertex * const CellCorner, const dReal * const pos, const bool isABC) const; dReal GetHeight(int x, int z); dReal GetHeight(dReal x, dReal z); }; typedef int HeightFieldVertexCoords[2]; class HeightFieldVertex { public: HeightFieldVertex(){}; dVector3 vertex; HeightFieldVertexCoords coords; bool state; }; class HeightFieldEdge { public: HeightFieldEdge(){}; HeightFieldVertex *vertices[2]; }; class HeightFieldTriangle { public: HeightFieldTriangle(){}; inline void setMinMax() { maxAAAB = vertices[0]->vertex[1] > vertices[1]->vertex[1] ? vertices[0]->vertex[1] : vertices[1]->vertex[1]; maxAAAB = vertices[2]->vertex[1] > maxAAAB ? vertices[2]->vertex[1] : maxAAAB; }; HeightFieldVertex *vertices[3]; dReal planeDef[4]; dReal maxAAAB; bool isUp; bool state; }; class HeightFieldPlane { public: HeightFieldPlane(): trianglelist(0), trianglelistReservedSize(0), trianglelistCurrentSize(0) { } ~HeightFieldPlane() { delete [] trianglelist; } inline void setMinMax() { const sizeint asize = trianglelistCurrentSize; if (asize > 0) { maxAAAB = trianglelist[0]->maxAAAB; for (sizeint k = 1; asize > k; k++) { if (trianglelist[k]->maxAAAB > maxAAAB) maxAAAB = trianglelist[k]->maxAAAB; } } }; void resetTriangleListSize(const sizeint newSize) { if (trianglelistReservedSize < newSize) { delete [] trianglelist; trianglelistReservedSize = newSize; trianglelist = new HeightFieldTriangle *[newSize]; } trianglelistCurrentSize = 0; } void addTriangle(HeightFieldTriangle *tri) { dIASSERT(trianglelistCurrentSize < trianglelistReservedSize); trianglelist[trianglelistCurrentSize++] = tri; } HeightFieldTriangle **trianglelist; sizeint trianglelistReservedSize; sizeint trianglelistCurrentSize; dReal maxAAAB; dReal planeDef[4]; }; // // dxHeightfield // // Heightfield geom structure // struct dxHeightfield : public dxGeom { dxHeightfieldData* m_p_data; dxHeightfield( dSpaceID space, dHeightfieldDataID data, int bPlaceable ); ~dxHeightfield(); void computeAABB(); int dCollideHeightfieldZone( const int minX, const int maxX, const int minZ, const int maxZ, dxGeom *o2, const int numMaxContacts, int flags, dContactGeom *contact, int skip ); enum { TEMP_PLANE_BUFFER_ELEMENT_COUNT_ALIGNMENT = 4, TEMP_HEIGHT_BUFFER_ELEMENT_COUNT_ALIGNMENT_X = 4, TEMP_HEIGHT_BUFFER_ELEMENT_COUNT_ALIGNMENT_Z = 4, TEMP_TRIANGLE_BUFFER_ELEMENT_COUNT_ALIGNMENT = 1 // Triangles are easy to reallocate and hard to predict }; static inline sizeint AlignBufferSize(sizeint value, sizeint alignment) { dIASSERT((alignment & (alignment - 1)) == 0); return (value + (alignment - 1)) & ~(alignment - 1); } void allocateTriangleBuffer(sizeint numTri); void resetTriangleBuffer(); void allocatePlaneBuffer(sizeint numTri); void resetPlaneBuffer(); void allocateHeightBuffer(sizeint numX, sizeint numZ); void resetHeightBuffer(); void sortPlanes(const sizeint numPlanes); HeightFieldPlane **tempPlaneBuffer; HeightFieldPlane *tempPlaneInstances; sizeint tempPlaneBufferSize; HeightFieldTriangle *tempTriangleBuffer; sizeint tempTriangleBufferSize; HeightFieldVertex **tempHeightBuffer; HeightFieldVertex *tempHeightInstances; sizeint tempHeightBufferSizeX; sizeint tempHeightBufferSizeZ; }; //------------------------------------------------------------------------------ #endif //_DHEIGHTFIELD_H_ ode-0.16/ode/src/threading_impl_win.h0000664000175200017520000002126113403272463014516 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * Threading Windows implementation file. * * Copyright (C) 2011-2012 Oleh Derevenko. All rights reserved. * * e-mail: odar@eleks.com (change all "a" to "e") * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* * Threading Windows implementation for built-in threading support provider. */ #ifndef _ODE_THREADING_IMPL_WIN_H_ #define _ODE_THREADING_IMPL_WIN_H_ #include #if defined(_WIN32) #if dBUILTIN_THREADING_IMPL_ENABLED #if !defined(_WIN32_WINNT) #define _WIN32_WINNT 0x0400 #endif #include #endif // #if dBUILTIN_THREADING_IMPL_ENABLED #include "threading_impl_templates.h" #include "threading_fake_sync.h" #include "threading_atomics_provs.h" #if dBUILTIN_THREADING_IMPL_ENABLED /************************************************************************/ /* dxEventWakeup class implementation */ /************************************************************************/ class dxEventWakeup { public: dxEventWakeup(): m_state_is_permanent(false), m_event_handle(NULL) {} ~dxEventWakeup() { DoFinalizeObject(); } bool InitializeObject() { return DoInitializeObject(); } private: bool DoInitializeObject(); void DoFinalizeObject(); public: void ResetWakeup(); void WakeupAThread(); void WakeupAllThreads(); bool WaitWakeup(const dThreadedWaitTime *timeout_time_ptr); private: bool m_state_is_permanent; HANDLE m_event_handle; }; bool dxEventWakeup::DoInitializeObject() { dIASSERT(m_event_handle == NULL); bool init_result = false; do { HANDLE event_handle = CreateEvent(NULL, FALSE, FALSE, NULL); if (event_handle == NULL) { break; } m_event_handle = event_handle; init_result = true; } while (false); return init_result; } void dxEventWakeup::DoFinalizeObject() { HANDLE event_handle = m_event_handle; if (event_handle != NULL) { BOOL close_result = CloseHandle(event_handle); dICHECK(close_result != FALSE); m_event_handle = NULL; } } void dxEventWakeup::ResetWakeup() { // Order of assignment and resetting event is not important but it is preferable to be performed this way. m_state_is_permanent = false; BOOL event_set_result = ResetEvent(m_event_handle); dICHECK(event_set_result); } void dxEventWakeup::WakeupAThread() { dIASSERT(!m_state_is_permanent); // Wakeup should not be used after permanent signal BOOL event_reset_result = SetEvent(m_event_handle); dICHECK(event_reset_result); } void dxEventWakeup::WakeupAllThreads() { // Order of assignment and setting event is important! m_state_is_permanent = true; BOOL event_set_result = SetEvent(m_event_handle); dICHECK(event_set_result); } bool dxEventWakeup::WaitWakeup(const dThreadedWaitTime *timeout_time_ptr) { bool wait_result; if (timeout_time_ptr == NULL) { DWORD event_wait_result = WaitForSingleObject(m_event_handle, INFINITE); dICHECK(event_wait_result == WAIT_OBJECT_0); wait_result = true; } else if (timeout_time_ptr->wait_sec == 0 && timeout_time_ptr->wait_nsec == 0) { DWORD event_wait_result = WaitForSingleObject(m_event_handle, 0); wait_result = event_wait_result == WAIT_OBJECT_0; dICHECK(wait_result || event_wait_result == WAIT_TIMEOUT); } else { dIASSERT(timeout_time_ptr->wait_nsec < 1000000000UL); const DWORD max_wait_seconds_in_a_shot = ((INFINITE - 1) / 1000U) - 1; time_t timeout_seconds_remaining = timeout_time_ptr->wait_sec; DWORD wait_timeout = timeout_time_ptr->wait_nsec != 0 ? ((timeout_time_ptr->wait_nsec + 999999UL) / 1000000UL) : 0; while (true) { if (timeout_seconds_remaining >= (time_t)max_wait_seconds_in_a_shot) { wait_timeout += max_wait_seconds_in_a_shot * 1000U; timeout_seconds_remaining -= max_wait_seconds_in_a_shot; } else { wait_timeout += (DWORD)timeout_seconds_remaining * 1000U; timeout_seconds_remaining = 0; } DWORD event_wait_result = WaitForSingleObject(m_event_handle, wait_timeout); if (event_wait_result == WAIT_OBJECT_0) { wait_result = true; break; } dICHECK(event_wait_result == WAIT_TIMEOUT); if (timeout_seconds_remaining == 0) { wait_result = false; break; } wait_timeout = 0; } } if (wait_result && m_state_is_permanent) { // Since event is automatic it is necessary to set it back for the upcoming waiters BOOL event_set_result = SetEvent(m_event_handle); dICHECK(event_set_result); } return wait_result; } /************************************************************************/ /* dxCriticalSectionMutex class implementation */ /************************************************************************/ class dxCriticalSectionMutex { public: dxCriticalSectionMutex() { InitializeCriticalSection(&m_critical_section); } ~dxCriticalSectionMutex() { DeleteCriticalSection(&m_critical_section); } bool InitializeObject() { return true; } public: void LockMutex() { EnterCriticalSection(&m_critical_section); } bool TryLockMutex() { return TryEnterCriticalSection(&m_critical_section) != FALSE; } void UnlockMutex() { LeaveCriticalSection(&m_critical_section); } private: CRITICAL_SECTION m_critical_section; }; #endif // #if dBUILTIN_THREADING_IMPL_ENABLED /************************************************************************/ /* Self-threaded job list definition */ /************************************************************************/ typedef dxtemplateJobListContainer dxSelfThreadedJobListContainer; typedef dxtemplateJobListSelfHandler dxSelfThreadedJobListHandler; typedef dxtemplateThreadingImplementation dxSelfThreadedThreading; #if dBUILTIN_THREADING_IMPL_ENABLED /************************************************************************/ /* Multi-threaded job list definition */ /************************************************************************/ typedef dxtemplateJobListContainer, dxCriticalSectionMutex, dxOUAtomicsProvider> dxMultiThreadedJobListContainer; typedef dxtemplateJobListThreadedHandler dxMultiThreadedJobListHandler; typedef dxtemplateThreadingImplementation dxMultiThreadedThreading; #endif // #if dBUILTIN_THREADING_IMPL_ENABLED #endif // #if defined(_WIN32) #endif // #ifndef _ODE_THREADING_IMPL_WIN_H_ ode-0.16/ode/src/fastltsolve_impl.h0000664000175200017520000016460713403272463014256 00000000000000 /************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* * Code style improvements and optimizations by Oleh Derevenko ????-2017 * L1Transposed cooperative solving code of ThreadedEquationSolverLDLT copyright (c) 2017 Oleh Derevenko, odar@eleks.com (change all "a" to "e") */ #ifndef _ODE_FASTLTSOLVE_IMPL_H_ #define _ODE_FASTLTSOLVE_IMPL_H_ /* solve L^T * x=b, with b containing 1 right hand side. * L is an n*n lower triangular matrix with ones on the diagonal. * L is stored by rows and its leading dimension is rowSkip. * b is an n*1 matrix that contains the right hand side. * b is overwritten with x. * this processes blocks of 4. */ template void solveL1Transposed(const dReal *L, dReal *B, unsigned rowCount, unsigned rowSkip) { dIASSERT(rowCount != 0); /* special handling for L and B because we're solving L1 *transpose* */ const dReal *lastLElement = L + (sizeint)(rowCount - 1) * (rowSkip + 1); dReal *lastBElement = B + (sizeint)(rowCount - 1) * b_stride; /* compute rows at end that are not a multiple of block size */ const unsigned loopX1RowCount = rowCount % 4; unsigned blockStartRow = loopX1RowCount; bool subsequentPass = false; /* compute rightmost bottom X(i) block */ if (loopX1RowCount != 0) { subsequentPass = true; const dReal *ptrLElement = lastLElement; dReal *ptrBElement = lastBElement; dReal Y11 = ptrBElement[0 * b_stride]/* - Z11*/; // ptrBElement[0 * b_stride] = Y11; -- unchanged if (loopX1RowCount >= 2) { dReal p2 = ptrLElement[-1]; dReal Y21 = ptrBElement[-1 * (int)b_stride]/* - Z21 */- p2 * Y11; ptrBElement[-1 * (int)b_stride] = Y21; if (loopX1RowCount > 2) { dReal p3 = ptrLElement[-2]; dReal p3_1 = (ptrLElement - rowSkip)[-2]; dReal Y31 = ptrBElement[-2 * (int)b_stride]/* - Z31 */- p3 * Y11 - p3_1 * Y21; ptrBElement[-2 * (int)b_stride] = Y31; } } } /* compute all 4 x 1 blocks of X */ for (; !subsequentPass || blockStartRow < rowCount; subsequentPass = true, blockStartRow += 4) { /* compute all 4 x 1 block of X, from rows i..i+4-1 */ /* declare variables - Z matrix, p and q vectors, etc */ const dReal *ptrLElement; dReal *ptrBElement; dReal Z41, Z31, Z21, Z11; if (subsequentPass) { ptrLElement = lastLElement - blockStartRow; ptrBElement = lastBElement; /* set the Z matrix to 0 */ Z41 = 0; Z31 = 0; Z21 = 0; Z11 = 0; unsigned rowCounter = blockStartRow; if (rowCounter % 2 != 0) { dReal q1, p4, p3, p2, p1; /* load p and q values */ q1 = ptrBElement[0 * (int)b_stride]; p4 = ptrLElement[-3]; p3 = ptrLElement[-2]; p2 = ptrLElement[-1]; p1 = ptrLElement[0]; ptrLElement -= rowSkip; /* compute outer product and add it to the Z matrix */ Z41 += p4 * q1; Z31 += p3 * q1; Z21 += p2 * q1; Z11 += p1 * q1; ptrBElement -= 1 * b_stride; rowCounter -= 1; } if (rowCounter % 4 != 0) { dReal q1, p4, p3, p2, p1; /* load p and q values */ q1 = ptrBElement[0 * (int)b_stride]; p4 = ptrLElement[-3]; p3 = ptrLElement[-2]; p2 = ptrLElement[-1]; p1 = ptrLElement[0]; ptrLElement -= rowSkip; /* compute outer product and add it to the Z matrix */ Z41 += p4 * q1; Z31 += p3 * q1; Z21 += p2 * q1; Z11 += p1 * q1; /* load p and q values */ q1 = ptrBElement[-1 * (int)b_stride]; p4 = ptrLElement[-3]; p3 = ptrLElement[-2]; p2 = ptrLElement[-1]; p1 = ptrLElement[0]; ptrLElement -= rowSkip; /* compute outer product and add it to the Z matrix */ Z41 += p4 * q1; Z31 += p3 * q1; Z21 += p2 * q1; Z11 += p1 * q1; ptrBElement -= 2 * b_stride; rowCounter -= 2; } /* the inner loop that computes outer products and adds them to Z */ for (bool exitLoop = rowCounter == 0; !exitLoop; exitLoop = false) { dReal q1, p4, p3, p2, p1; /* load p and q values */ q1 = ptrBElement[0 * (int)b_stride]; p4 = ptrLElement[-3]; p3 = ptrLElement[-2]; p2 = ptrLElement[-1]; p1 = ptrLElement[0]; ptrLElement -= rowSkip; /* compute outer product and add it to the Z matrix */ Z41 += p4 * q1; Z31 += p3 * q1; Z21 += p2 * q1; Z11 += p1 * q1; /* load p and q values */ q1 = ptrBElement[-1 * (int)b_stride]; p4 = ptrLElement[-3]; p3 = ptrLElement[-2]; p2 = ptrLElement[-1]; p1 = ptrLElement[0]; ptrLElement -= rowSkip; /* compute outer product and add it to the Z matrix */ Z41 += p4 * q1; Z31 += p3 * q1; Z21 += p2 * q1; Z11 += p1 * q1; /* load p and q values */ q1 = ptrBElement[-2 * (int)b_stride]; p4 = ptrLElement[-3]; p3 = ptrLElement[-2]; p2 = ptrLElement[-1]; p1 = ptrLElement[0]; ptrLElement -= rowSkip; /* compute outer product and add it to the Z matrix */ Z41 += p4 * q1; Z31 += p3 * q1; Z21 += p2 * q1; Z11 += p1 * q1; /* load p and q values */ q1 = ptrBElement[-3 * (int)b_stride]; p4 = ptrLElement[-3]; p3 = ptrLElement[-2]; p2 = ptrLElement[-1]; p1 = ptrLElement[0]; ptrLElement -= rowSkip; /* compute outer product and add it to the Z matrix */ Z41 += p4 * q1; Z31 += p3 * q1; Z21 += p2 * q1; Z11 += p1 * q1; if (rowCounter > 12) { rowCounter -= 12; ptrBElement -= 12 * b_stride; /* load p and q values */ q1 = ptrBElement[8 * b_stride]; p4 = ptrLElement[-3]; p3 = ptrLElement[-2]; p2 = ptrLElement[-1]; p1 = ptrLElement[0]; ptrLElement -= rowSkip; /* compute outer product and add it to the Z matrix */ Z41 += p4 * q1; Z31 += p3 * q1; Z21 += p2 * q1; Z11 += p1 * q1; /* load p and q values */ q1 = ptrBElement[7 * b_stride]; p4 = ptrLElement[-3]; p3 = ptrLElement[-2]; p2 = ptrLElement[-1]; p1 = ptrLElement[0]; ptrLElement -= rowSkip; /* compute outer product and add it to the Z matrix */ Z41 += p4 * q1; Z31 += p3 * q1; Z21 += p2 * q1; Z11 += p1 * q1; /* load p and q values */ q1 = ptrBElement[6 * b_stride]; p4 = ptrLElement[-3]; p3 = ptrLElement[-2]; p2 = ptrLElement[-1]; p1 = ptrLElement[0]; ptrLElement -= rowSkip; /* compute outer product and add it to the Z matrix */ Z41 += p4 * q1; Z31 += p3 * q1; Z21 += p2 * q1; Z11 += p1 * q1; /* load p and q values */ q1 = ptrBElement[5 * b_stride]; p4 = ptrLElement[-3]; p3 = ptrLElement[-2]; p2 = ptrLElement[-1]; p1 = ptrLElement[0]; ptrLElement -= rowSkip; /* compute outer product and add it to the Z matrix */ Z41 += p4 * q1; Z31 += p3 * q1; Z21 += p2 * q1; Z11 += p1 * q1; /* load p and q values */ q1 = ptrBElement[4 * b_stride]; p4 = ptrLElement[-3]; p3 = ptrLElement[-2]; p2 = ptrLElement[-1]; p1 = ptrLElement[0]; ptrLElement -= rowSkip; /* compute outer product and add it to the Z matrix */ Z41 += p4 * q1; Z31 += p3 * q1; Z21 += p2 * q1; Z11 += p1 * q1; /* load p and q values */ q1 = ptrBElement[3 * b_stride]; p4 = ptrLElement[-3]; p3 = ptrLElement[-2]; p2 = ptrLElement[-1]; p1 = ptrLElement[0]; ptrLElement -= rowSkip; /* compute outer product and add it to the Z matrix */ Z41 += p4 * q1; Z31 += p3 * q1; Z21 += p2 * q1; Z11 += p1 * q1; /* load p and q values */ q1 = ptrBElement[2 * b_stride]; p4 = ptrLElement[-3]; p3 = ptrLElement[-2]; p2 = ptrLElement[-1]; p1 = ptrLElement[0]; ptrLElement -= rowSkip; /* compute outer product and add it to the Z matrix */ Z41 += p4 * q1; Z31 += p3 * q1; Z21 += p2 * q1; Z11 += p1 * q1; /* load p and q values */ q1 = ptrBElement[1 * b_stride]; p4 = ptrLElement[-3]; p3 = ptrLElement[-2]; p2 = ptrLElement[-1]; p1 = ptrLElement[0]; ptrLElement -= rowSkip; /* compute outer product and add it to the Z matrix */ Z41 += p4 * q1; Z31 += p3 * q1; Z21 += p2 * q1; Z11 += p1 * q1; } else { ptrBElement -= 4 * b_stride; if ((rowCounter -= 4) == 0) { break; } } /* end of inner loop */ } } else { ptrLElement = lastLElement/* - blockStartRow*/; dIASSERT(blockStartRow == 0); ptrBElement = lastBElement; /* set the Z matrix to 0 */ Z41 = 0; Z31 = 0; Z21 = 0; Z11 = 0; } /* finish computing the X(i) block */ dReal Y11, Y21, Y31, Y41; { Y11 = ptrBElement[0 * b_stride] - Z11; ptrBElement[0 * b_stride] = Y11; } { dReal p2 = ptrLElement[-1]; Y21 = ptrBElement[-1 * (int)b_stride] - Z21 - p2 * Y11; ptrBElement[-1 * (int)b_stride] = Y21; } { dReal p3 = ptrLElement[-2]; dReal p3_1 = (ptrLElement - rowSkip)[-2]; Y31 = ptrBElement[-2 * (int)b_stride] - Z31 - p3 * Y11 - p3_1 * Y21; ptrBElement[-2 * (int)b_stride] = Y31; } { dReal p4 = ptrLElement[-3]; dReal p4_1 = (ptrLElement - rowSkip)[-3]; dReal p4_2 = (ptrLElement - rowSkip * 2)[-3]; Y41 = ptrBElement[-3 * (int)b_stride] - Z41 - p4 * Y11 - p4_1 * Y21 - p4_2 * Y31; ptrBElement[-3 * (int)b_stride] = Y41; } /* end of outer loop */ } } template /*static */ sizeint ThreadedEquationSolverLDLT::estimateCooperativelySolvingL1TransposedMemoryRequirement(unsigned rowCount, SolvingL1TransposedMemoryEstimates &ref_solvingMemoryEstimates) { unsigned blockCount = deriveSolvingL1TransposedBlockCount(rowCount, block_step); sizeint descriptorSizeRequired = dEFFICIENT_SIZE(sizeof(cellindexint) * blockCount); sizeint contextSizeRequired = dEFFICIENT_SIZE(sizeof(SolveL1TransposedCellContext) * (CCI__MAX + 1) * blockCount); ref_solvingMemoryEstimates.assignData(descriptorSizeRequired, contextSizeRequired); sizeint totalSizeRequired = descriptorSizeRequired + contextSizeRequired; return totalSizeRequired; } template /*static */ void ThreadedEquationSolverLDLT::initializeCooperativelySolveL1TransposedMemoryStructures(unsigned rowCount, atomicord32 &out_blockCompletionProgress, cellindexint *blockProgressDescriptors, SolveL1TransposedCellContext *dUNUSED(cellContexts)) { unsigned blockCount = deriveSolvingL1TransposedBlockCount(rowCount, block_step); out_blockCompletionProgress = 0; memset(blockProgressDescriptors, 0, blockCount * sizeof(*blockProgressDescriptors)); } template /*static */ void ThreadedEquationSolverLDLT::participateSolvingL1Transposed(const dReal *L, dReal *B, unsigned rowCount, unsigned rowSkip, volatile atomicord32 &refBlockCompletionProgress/*=0*/, volatile cellindexint *blockProgressDescriptors/*=[blockCount]*/, SolveL1TransposedCellContext *cellContexts/*=[CCI__MAX x blockCount] + [blockCount]*/, unsigned ownThreadIndex) { const unsigned lookaheadRange = 32; const unsigned blockCount = deriveSolvingL1TransposedBlockCount(rowCount, block_step); /* compute rows at end that are not a multiple of block size */ const unsigned loopX1RowCount = rowCount % block_step; /* special handling for L and B because we're solving L1 *transpose* */ const dReal *lastLElement = L + (rowCount - 1) * ((sizeint)rowSkip + 1); dReal *lastBElement = B + (rowCount - 1) * (sizeint)b_stride; /* elements adjusted as if the last block was full block_step elements */ unsigned x1AdjustmentElements = (block_step - loopX1RowCount) % block_step; const dReal *columnAdjustedLastLElement = lastLElement + x1AdjustmentElements; const dReal *fullyAdjustedLastLElement = columnAdjustedLastLElement + (sizeint)rowSkip * x1AdjustmentElements; dReal *adjustedLastBElement = lastBElement + b_stride * x1AdjustmentElements; BlockProcessingState blockProcessingState = BPS_NO_BLOCKS_PROCESSED; unsigned completedBlocks = refBlockCompletionProgress; unsigned currentBlock = completedBlocks; dIASSERT(completedBlocks <= blockCount); for (bool exitLoop = completedBlocks == blockCount; !exitLoop; exitLoop = false) { bool goForLockedBlockPrimaryCalculation = false, goForLockedBlockDuplicateCalculation = false; bool goAssigningTheResult = false, stayWithinTheBlock = false; dReal Z[block_step]; dReal Y[block_step]; dReal *ptrBElement; CellContextInstance previousContextInstance; unsigned completedRowBlock; bool partialBlock; for (cellindexint testDescriptor = blockProgressDescriptors[currentBlock]; ; ) { if (testDescriptor == INVALID_CELLDESCRIPTOR) { // Invalid descriptor is the indication that the row has been fully calculated // Test if this was the last row and break out if so. if (currentBlock + 1 == blockCount) { exitLoop = true; break; } // Treat detected row advancement as a row processed // blockProcessingState = BPS_SOME_BLOCKS_PROCESSED; <-- performs better without it break; } CooperativeAtomics::AtomicReadReorderBarrier(); // It is necessary to read up to date completedBblocks value after the descriptor retrieval // as otherwise the logic below breaks completedBlocks = refBlockCompletionProgress; if (!GET_CELLDESCRIPTOR_ISLOCKED(testDescriptor)) { completedRowBlock = GET_CELLDESCRIPTOR_COLUMNINDEX(testDescriptor); dIASSERT(completedRowBlock < currentBlock || (completedRowBlock == currentBlock && currentBlock == 0)); // Otherwise, why would the calculation have had stopped if the final column is reachable??? dIASSERT(completedRowBlock <= completedBlocks); // Since the descriptor is not locked if (completedRowBlock == completedBlocks && currentBlock != completedBlocks) { dIASSERT(completedBlocks < currentBlock); break; } if (CooperativeAtomics::AtomicCompareExchangeCellindexint(&blockProgressDescriptors[currentBlock], testDescriptor, MARK_CELLDESCRIPTOR_LOCKED(testDescriptor))) { if (completedRowBlock != 0) { CellContextInstance contextInstance = GET_CELLDESCRIPTOR_CONTEXTINSTANCE(testDescriptor); previousContextInstance = contextInstance; const SolveL1TransposedCellContext &sourceContext = buildBlockContextRef(cellContexts, currentBlock, contextInstance); sourceContext.loadPrecalculatedZs(Z); } else { previousContextInstance = CCI__MIN; SolveL1TransposedCellContext::initializePrecalculatedZs(Z); } goForLockedBlockPrimaryCalculation = true; break; } if (blockProcessingState != BPS_COMPETING_FOR_A_BLOCK) { break; } testDescriptor = blockProgressDescriptors[currentBlock]; } else { if (blockProcessingState != BPS_COMPETING_FOR_A_BLOCK) { break; } cellindexint verificativeDescriptor; bool verificationFailure = false; completedRowBlock = GET_CELLDESCRIPTOR_COLUMNINDEX(testDescriptor); dIASSERT(completedRowBlock != currentBlock || currentBlock == 0); // There is no reason for computations to stop at the very end other than being the initial value at the very first block if (completedRowBlock != 0) { CellContextInstance contextInstance = GET_CELLDESCRIPTOR_CONTEXTINSTANCE(testDescriptor); const SolveL1TransposedCellContext &sourceContext = buildBlockContextRef(cellContexts, currentBlock, contextInstance); sourceContext.loadPrecalculatedZs(Z); } else { SolveL1TransposedCellContext::initializePrecalculatedZs(Z); } if (completedRowBlock != 0 && completedRowBlock <= currentBlock) { // Make sure the descriptor is re-read after the precalculates CooperativeAtomics::AtomicReadReorderBarrier(); } if (completedRowBlock <= currentBlock) { verificativeDescriptor = blockProgressDescriptors[currentBlock]; verificationFailure = verificativeDescriptor != testDescriptor; } if (!verificationFailure) { dIASSERT(completedRowBlock <= currentBlock + 1); goForLockedBlockDuplicateCalculation = true; break; } testDescriptor = verificativeDescriptor; } } if (exitLoop) { break; } if (goForLockedBlockPrimaryCalculation) { blockProcessingState = BPS_SOME_BLOCKS_PROCESSED; // Declare and assign the variables at the top to not interfere with any branching -- the compiler is going to eliminate them anyway. bool handleComputationTakenOver = false, columnEndReached = false; const dReal *ptrLElement; unsigned finalRowBlock; /* check if this is not the partial block of fewer rows */ if (currentBlock != 0 || loopX1RowCount == 0) { partialBlock = false; ptrLElement = completedRowBlock != 0 ? fullyAdjustedLastLElement - currentBlock * block_step - (sizeint)(completedRowBlock * block_step) * rowSkip : columnAdjustedLastLElement - currentBlock * block_step; ptrBElement = completedRowBlock != 0 ? adjustedLastBElement - (sizeint)(completedRowBlock * block_step) * b_stride : lastBElement; finalRowBlock = dMACRO_MIN(currentBlock, completedBlocks); dIASSERT(finalRowBlock != completedRowBlock || finalRowBlock == 0); unsigned rowCounter = finalRowBlock - completedRowBlock; bool exitLoop = rowCounter == 0; if (exitLoop) { columnEndReached = true; } else if (completedRowBlock == 0 && currentBlock != 0 && loopX1RowCount != 0) { if ((loopX1RowCount & 1) != 0) { dReal q1, p4, p3, p2, p1; /* load p and q values */ q1 = ptrBElement[0 * (int)b_stride]; p4 = ptrLElement[-3]; p3 = ptrLElement[-2]; p2 = ptrLElement[-1]; p1 = ptrLElement[0]; ptrLElement -= rowSkip; /* compute outer product and add it to the Z matrix */ Z[3] += p4 * q1; Z[2] += p3 * q1; Z[1] += p2 * q1; Z[0] += p1 * q1; ptrBElement -= 1 * b_stride; } if ((loopX1RowCount & 2) != 0) { dReal q1, p4, p3, p2, p1; /* load p and q values */ q1 = ptrBElement[0 * (int)b_stride]; p4 = ptrLElement[-3]; p3 = ptrLElement[-2]; p2 = ptrLElement[-1]; p1 = ptrLElement[0]; ptrLElement -= rowSkip; /* compute outer product and add it to the Z matrix */ Z[3] += p4 * q1; Z[2] += p3 * q1; Z[1] += p2 * q1; Z[0] += p1 * q1; /* load p and q values */ q1 = ptrBElement[-1 * (int)b_stride]; p4 = ptrLElement[-3]; p3 = ptrLElement[-2]; p2 = ptrLElement[-1]; p1 = ptrLElement[0]; ptrLElement -= rowSkip; /* compute outer product and add it to the Z matrix */ Z[3] += p4 * q1; Z[2] += p3 * q1; Z[1] += p2 * q1; Z[0] += p1 * q1; ptrBElement -= 2 * b_stride; } dSASSERT(block_step == 4); if (--rowCounter == 0) { do { if (finalRowBlock == currentBlock) { columnEndReached = true; exitLoop = true; break; } // Take a look if any more columns have been completed... completedBlocks = refBlockCompletionProgress; dIASSERT(completedBlocks >= finalRowBlock); if (completedBlocks == finalRowBlock) { exitLoop = true; break; } // ...continue if so. unsigned rowCompletedSoFar = finalRowBlock; finalRowBlock = dMACRO_MIN(currentBlock, completedBlocks); rowCounter = finalRowBlock - rowCompletedSoFar; } while (false); } } for (; !exitLoop; exitLoop = false) { dReal q1, p4, p3, p2, p1; /* load p and q values */ q1 = ptrBElement[0 * (int)b_stride]; p4 = ptrLElement[-3]; p3 = ptrLElement[-2]; p2 = ptrLElement[-1]; p1 = ptrLElement[0]; ptrLElement -= rowSkip; /* compute outer product and add it to the Z matrix */ Z[3] += p4 * q1; Z[2] += p3 * q1; Z[1] += p2 * q1; Z[0] += p1 * q1; /* load p and q values */ q1 = ptrBElement[-1 * (int)b_stride]; p4 = ptrLElement[-3]; p3 = ptrLElement[-2]; p2 = ptrLElement[-1]; p1 = ptrLElement[0]; ptrLElement -= rowSkip; /* compute outer product and add it to the Z matrix */ Z[3] += p4 * q1; Z[2] += p3 * q1; Z[1] += p2 * q1; Z[0] += p1 * q1; /* load p and q values */ q1 = ptrBElement[-2 * (int)b_stride]; p4 = ptrLElement[-3]; p3 = ptrLElement[-2]; p2 = ptrLElement[-1]; p1 = ptrLElement[0]; ptrLElement -= rowSkip; /* compute outer product and add it to the Z matrix */ Z[3] += p4 * q1; Z[2] += p3 * q1; Z[1] += p2 * q1; Z[0] += p1 * q1; /* load p and q values */ q1 = ptrBElement[-3 * (int)b_stride]; p4 = ptrLElement[-3]; p3 = ptrLElement[-2]; p2 = ptrLElement[-1]; p1 = ptrLElement[0]; ptrLElement -= rowSkip; /* compute outer product and add it to the Z matrix */ Z[3] += p4 * q1; Z[2] += p3 * q1; Z[1] += p2 * q1; Z[0] += p1 * q1; dSASSERT(block_step == 4); if (rowCounter > 3) { rowCounter -= 3; ptrBElement -= 3 * block_step * b_stride; /* load p and q values */ q1 = ptrBElement[8 * b_stride]; p4 = ptrLElement[-3]; p3 = ptrLElement[-2]; p2 = ptrLElement[-1]; p1 = ptrLElement[0]; ptrLElement -= rowSkip; /* compute outer product and add it to the Z matrix */ Z[3] += p4 * q1; Z[2] += p3 * q1; Z[1] += p2 * q1; Z[0] += p1 * q1; /* load p and q values */ q1 = ptrBElement[7 * b_stride]; p4 = ptrLElement[-3]; p3 = ptrLElement[-2]; p2 = ptrLElement[-1]; p1 = ptrLElement[0]; ptrLElement -= rowSkip; /* compute outer product and add it to the Z matrix */ Z[3] += p4 * q1; Z[2] += p3 * q1; Z[1] += p2 * q1; Z[0] += p1 * q1; /* load p and q values */ q1 = ptrBElement[6 * b_stride]; p4 = ptrLElement[-3]; p3 = ptrLElement[-2]; p2 = ptrLElement[-1]; p1 = ptrLElement[0]; ptrLElement -= rowSkip; /* compute outer product and add it to the Z matrix */ Z[3] += p4 * q1; Z[2] += p3 * q1; Z[1] += p2 * q1; Z[0] += p1 * q1; /* load p and q values */ q1 = ptrBElement[5 * b_stride]; p4 = ptrLElement[-3]; p3 = ptrLElement[-2]; p2 = ptrLElement[-1]; p1 = ptrLElement[0]; ptrLElement -= rowSkip; /* compute outer product and add it to the Z matrix */ Z[3] += p4 * q1; Z[2] += p3 * q1; Z[1] += p2 * q1; Z[0] += p1 * q1; /* load p and q values */ q1 = ptrBElement[4 * b_stride]; p4 = ptrLElement[-3]; p3 = ptrLElement[-2]; p2 = ptrLElement[-1]; p1 = ptrLElement[0]; ptrLElement -= rowSkip; /* compute outer product and add it to the Z matrix */ Z[3] += p4 * q1; Z[2] += p3 * q1; Z[1] += p2 * q1; Z[0] += p1 * q1; /* load p and q values */ q1 = ptrBElement[3 * b_stride]; p4 = ptrLElement[-3]; p3 = ptrLElement[-2]; p2 = ptrLElement[-1]; p1 = ptrLElement[0]; ptrLElement -= rowSkip; /* compute outer product and add it to the Z matrix */ Z[3] += p4 * q1; Z[2] += p3 * q1; Z[1] += p2 * q1; Z[0] += p1 * q1; /* load p and q values */ q1 = ptrBElement[2 * b_stride]; p4 = ptrLElement[-3]; p3 = ptrLElement[-2]; p2 = ptrLElement[-1]; p1 = ptrLElement[0]; ptrLElement -= rowSkip; /* compute outer product and add it to the Z matrix */ Z[3] += p4 * q1; Z[2] += p3 * q1; Z[1] += p2 * q1; Z[0] += p1 * q1; /* load p and q values */ q1 = ptrBElement[1 * b_stride]; p4 = ptrLElement[-3]; p3 = ptrLElement[-2]; p2 = ptrLElement[-1]; p1 = ptrLElement[0]; ptrLElement -= rowSkip; /* compute outer product and add it to the Z matrix */ Z[3] += p4 * q1; Z[2] += p3 * q1; Z[1] += p2 * q1; Z[0] += p1 * q1; dSASSERT(block_step == 4); } else { ptrBElement -= block_step * b_stride; if (--rowCounter == 0) { if (finalRowBlock == currentBlock) { columnEndReached = true; break; } // Take a look if any more columns have been completed... completedBlocks = refBlockCompletionProgress; dIASSERT(completedBlocks >= finalRowBlock); if (completedBlocks == finalRowBlock) { break; } // ...continue if so. unsigned rowCompletedSoFar = finalRowBlock; finalRowBlock = dMACRO_MIN(currentBlock, completedBlocks); rowCounter = finalRowBlock - rowCompletedSoFar; } } /* end of inner loop */ } } else /* compute rightmost bottom X(i) block */ { partialBlock = true; ptrLElement = lastLElement; ptrBElement = lastBElement; dIASSERT(completedRowBlock == 0); columnEndReached = true; } if (columnEndReached) { // Check whether there is still a need to proceed or if the computation has been taken over by another thread cellindexint oldDescriptor = MAKE_CELLDESCRIPTOR(completedRowBlock, previousContextInstance, true); if (blockProgressDescriptors[currentBlock] == oldDescriptor) { if (partialBlock) { Y[0] = ptrBElement[0 * b_stride]/* - Z[0]*/; if (loopX1RowCount >= 2) { dReal p2 = ptrLElement[-1]; Y[1] = ptrBElement[-1 * (int)b_stride]/* - Z[1] */- p2 * Y[0]; if (loopX1RowCount > 2) { dReal p3 = ptrLElement[-2]; dReal p3_1 = (ptrLElement - rowSkip)[-2]; Y[2] = ptrBElement[-2 * (int)b_stride]/* - Z[2] */- p3 * Y[0] - p3_1 * Y[1]; } } dSASSERT(block_step == 4); } else { Y[0] = ptrBElement[0 * b_stride] - Z[0]; dReal p2 = ptrLElement[-1]; Y[1] = ptrBElement[-1 * (int)b_stride] - Z[1] - p2 * Y[0]; dReal p3 = ptrLElement[-2]; dReal p3_1 = (ptrLElement - rowSkip)[-2]; Y[2] = ptrBElement[-2 * (int)b_stride] - Z[2] - p3 * Y[0] - p3_1 * Y[1]; dReal p4 = ptrLElement[-3]; dReal p4_1 = (ptrLElement - rowSkip)[-3]; dReal p4_2 = (ptrLElement - rowSkip * 2)[-3]; Y[3] = ptrBElement[-3 * (int)b_stride] - Z[3] - p4 * Y[0] - p4_1 * Y[1] - p4_2 * Y[2]; dSASSERT(block_step == 4); } // Use atomic memory barrier to make sure memory reads of ptrBElement[] and blockProgressDescriptors[] are not swapped CooperativeAtomics::AtomicReadReorderBarrier(); // The descriptor has not been altered yet - this means the ptrBElement[] values used above were not modified yet // and the computation result is valid. if (blockProgressDescriptors[currentBlock] == oldDescriptor) { // Assign the results to the result context (possibly in parallel with other threads // that could and ought to be assigning exactly the same values) SolveL1TransposedCellContext &resultContext = buildResultContextRef(cellContexts, currentBlock, blockCount); resultContext.storePrecalculatedZs(Y); // Assign the result assignment progress descriptor cellindexint newDescriptor = MAKE_CELLDESCRIPTOR(currentBlock + 1, CCI__MIN, true); CooperativeAtomics::AtomicCompareExchangeCellindexint(&blockProgressDescriptors[currentBlock], oldDescriptor, newDescriptor); // the result is to be ignored // Whether succeeded or not, the result is valid, so go on trying to assign it to the matrix goAssigningTheResult = true; } else { // Otherwise, go on competing for copying the results handleComputationTakenOver = true; } } else { handleComputationTakenOver = true; } } else { // If the final column has not been reached yet, store current values to the context. // Select the other context instance as the previous one might be read by other threads. CellContextInstance nextContextInstance = buildNextContextInstance(previousContextInstance); SolveL1TransposedCellContext &destinationContext = buildBlockContextRef(cellContexts, currentBlock, nextContextInstance); destinationContext.storePrecalculatedZs(Z); // Unlock the row until more columns can be used cellindexint oldDescriptor = MAKE_CELLDESCRIPTOR(completedRowBlock, previousContextInstance, true); cellindexint newDescriptor = MAKE_CELLDESCRIPTOR(finalRowBlock, nextContextInstance, false); // The descriptor might have been updated by a competing thread if (!CooperativeAtomics::AtomicCompareExchangeCellindexint(&blockProgressDescriptors[currentBlock], oldDescriptor, newDescriptor)) { // Adjust the ptrBElement to point to the result area... ptrBElement = adjustedLastBElement - (sizeint)(currentBlock * block_step) * b_stride; dIASSERT(currentBlock != 0 || adjustedLastBElement == lastBElement); // ...and go on handling the case handleComputationTakenOver = true; } } if (handleComputationTakenOver) { cellindexint existingDescriptor = blockProgressDescriptors[currentBlock]; // This can only happen if the row was (has become) the uppermost not fully completed one // and the competing thread is at final stage of calculation (i.e., it has reached the currentBlock column). if (existingDescriptor != INVALID_CELLDESCRIPTOR) { // If not fully completed this must be the final stage of the result assignment into the matrix dIASSERT(existingDescriptor == MAKE_CELLDESCRIPTOR(currentBlock + 1, CCI__MIN, true)); // Go on competing copying the result as anyway the block is the topmost not completed one // and since there was competition for it, there is no other work that can be done right now. const SolveL1TransposedCellContext &resultContext = buildResultContextRef(cellContexts, currentBlock, blockCount); resultContext.loadPrecalculatedZs(Y); goAssigningTheResult = true; } else { // everything is over -- just go handling next blocks } } } else if (goForLockedBlockDuplicateCalculation) { blockProcessingState = BPS_SOME_BLOCKS_PROCESSED; bool skipToHandlingSubsequentRows = false, skiptoCopyingResult = false; /* declare variables */ const dReal *ptrLElement; if (completedRowBlock < currentBlock) { partialBlock = false; ptrLElement = completedRowBlock != 0 ? fullyAdjustedLastLElement - currentBlock * block_step - (sizeint)(completedRowBlock * block_step) * rowSkip : columnAdjustedLastLElement - currentBlock * block_step; ptrBElement = completedRowBlock != 0 ? adjustedLastBElement - (sizeint)(completedRowBlock * block_step) * b_stride : lastBElement; unsigned finalRowBlock = currentBlock/*std::min(currentBlock, completedBlocks)*/; dIASSERT(currentBlock == completedBlocks); // Why would we be competing for a row otherwise? bool exitInnerLoop = false; unsigned lastCompletedRow = completedRowBlock; unsigned rowCounter = finalRowBlock - completedRowBlock; if (completedRowBlock == 0/* && currentBlock != 0 */&& loopX1RowCount != 0) { if ((loopX1RowCount & 1) != 0) { dReal q1, p4, p3, p2, p1; /* load p and q values */ q1 = ptrBElement[0 * (int)b_stride]; p4 = ptrLElement[-3]; p3 = ptrLElement[-2]; p2 = ptrLElement[-1]; p1 = ptrLElement[0]; ptrLElement -= rowSkip; /* compute outer product and add it to the Z matrix */ Z[3] += p4 * q1; Z[2] += p3 * q1; Z[1] += p2 * q1; Z[0] += p1 * q1; ptrBElement -= 1 * b_stride; } if ((loopX1RowCount & 2) != 0) { dReal q1, p4, p3, p2, p1; /* load p and q values */ q1 = ptrBElement[0 * (int)b_stride]; p4 = ptrLElement[-3]; p3 = ptrLElement[-2]; p2 = ptrLElement[-1]; p1 = ptrLElement[0]; ptrLElement -= rowSkip; /* compute outer product and add it to the Z matrix */ Z[3] += p4 * q1; Z[2] += p3 * q1; Z[1] += p2 * q1; Z[0] += p1 * q1; /* load p and q values */ q1 = ptrBElement[-1 * (int)b_stride]; p4 = ptrLElement[-3]; p3 = ptrLElement[-2]; p2 = ptrLElement[-1]; p1 = ptrLElement[0]; ptrLElement -= rowSkip; /* compute outer product and add it to the Z matrix */ Z[3] += p4 * q1; Z[2] += p3 * q1; Z[1] += p2 * q1; Z[0] += p1 * q1; ptrBElement -= 2 * b_stride; } dSASSERT(block_step == 4); if (--rowCounter == 0) { exitInnerLoop = true; } } for (; !exitInnerLoop; exitInnerLoop = --rowCounter == 0) { dReal q1, p4, p3, p2, p1; /* load p and q values */ q1 = ptrBElement[0 * (int)b_stride]; p4 = ptrLElement[-3]; p3 = ptrLElement[-2]; p2 = ptrLElement[-1]; p1 = ptrLElement[0]; ptrLElement -= rowSkip; /* compute outer product and add it to the Z matrix */ Z[3] += p4 * q1; Z[2] += p3 * q1; Z[1] += p2 * q1; Z[0] += p1 * q1; /* load p and q values */ q1 = ptrBElement[-1 * (int)b_stride]; p4 = ptrLElement[-3]; p3 = ptrLElement[-2]; p2 = ptrLElement[-1]; p1 = ptrLElement[0]; ptrLElement -= rowSkip; /* compute outer product and add it to the Z matrix */ Z[3] += p4 * q1; Z[2] += p3 * q1; Z[1] += p2 * q1; Z[0] += p1 * q1; /* load p and q values */ q1 = ptrBElement[-2 * (int)b_stride]; p4 = ptrLElement[-3]; p3 = ptrLElement[-2]; p2 = ptrLElement[-1]; p1 = ptrLElement[0]; ptrLElement -= rowSkip; /* compute outer product and add it to the Z matrix */ Z[3] += p4 * q1; Z[2] += p3 * q1; Z[1] += p2 * q1; Z[0] += p1 * q1; /* load p and q values */ q1 = ptrBElement[-3 * (int)b_stride]; p4 = ptrLElement[-3]; p3 = ptrLElement[-2]; p2 = ptrLElement[-1]; p1 = ptrLElement[0]; ptrLElement -= rowSkip; /* compute outer product and add it to the Z matrix */ Z[3] += p4 * q1; Z[2] += p3 * q1; Z[1] += p2 * q1; Z[0] += p1 * q1; dSASSERT(block_step == 4); // Check if the primary solver thread has not made any progress cellindexint descriptorVerification = blockProgressDescriptors[currentBlock]; unsigned newCompletedRow = GET_CELLDESCRIPTOR_COLUMNINDEX(descriptorVerification); if (newCompletedRow != lastCompletedRow) { // Check, this is the first change the current thread detects. // There is absolutely no reason in code for the computation to stop/resume twice // while the current thread is competing. dIASSERT(lastCompletedRow == completedRowBlock); if (descriptorVerification == INVALID_CELLDESCRIPTOR) { skipToHandlingSubsequentRows = true; break; } if (newCompletedRow == currentBlock + 1) { skiptoCopyingResult = true; break; } // Check if the current thread is behind if (newCompletedRow > finalRowBlock - rowCounter) { // If so, go starting over one more time blockProcessingState = BPS_COMPETING_FOR_A_BLOCK; stayWithinTheBlock = true; skipToHandlingSubsequentRows = true; break; } // If current thread is ahead, just save new completed column for further comparisons and go on calculating lastCompletedRow = newCompletedRow; } /* advance pointers */ ptrBElement -= block_step * b_stride; /* end of inner loop */ } } else if (completedRowBlock > currentBlock) { dIASSERT(completedRowBlock == currentBlock + 1); partialBlock = currentBlock == 0 && loopX1RowCount != 0; skiptoCopyingResult = true; } else { dIASSERT(currentBlock == 0); // Execution can get here within the very first block only partialBlock = /*currentBlock == 0 && */loopX1RowCount != 0; /* just assign the pointers appropriately and go on computing the results */ ptrLElement = lastLElement; ptrBElement = lastBElement; } if (!skipToHandlingSubsequentRows) { if (!skiptoCopyingResult) { if (partialBlock) { Y[0] = ptrBElement[0 * b_stride]/* - Z[0]*/; if (loopX1RowCount >= 2) { dReal p2 = ptrLElement[-1]; Y[1] = ptrBElement[-1 * (int)b_stride]/* - Z[1] */- p2 * Y[0]; if (loopX1RowCount > 2) { dReal p3 = ptrLElement[-2]; dReal p3_1 = (ptrLElement - rowSkip)[-2]; Y[2] = ptrBElement[-2 * (int)b_stride]/* - Z[2] */- p3 * Y[0] - p3_1 * Y[1]; } } dSASSERT(block_step == 4); } else { Y[0] = ptrBElement[0 * b_stride] - Z[0]; dReal p2 = ptrLElement[-1]; Y[1] = ptrBElement[-1 * (int)b_stride] - Z[1] - p2 * Y[0]; dReal p3 = ptrLElement[-2]; dReal p3_1 = (ptrLElement - rowSkip)[-2]; Y[2] = ptrBElement[-2 * (int)b_stride] - Z[2] - p3 * Y[0] - p3_1 * Y[1]; dReal p4 = ptrLElement[-3]; dReal p4_1 = (ptrLElement - rowSkip)[-3]; dReal p4_2 = (ptrLElement - rowSkip * 2)[-3]; Y[3] = ptrBElement[-3 * (int)b_stride] - Z[3] - p4 * Y[0] - p4_1 * Y[1] - p4_2 * Y[2]; dSASSERT(block_step == 4); } // Use atomic memory barrier to make sure memory reads of ptrBElement[] and blockProgressDescriptors[] are not swapped CooperativeAtomics::AtomicReadReorderBarrier(); cellindexint existingDescriptor = blockProgressDescriptors[currentBlock]; if (existingDescriptor == INVALID_CELLDESCRIPTOR) { // Everything is over -- proceed to subsequent rows skipToHandlingSubsequentRows = true; } else if (existingDescriptor == MAKE_CELLDESCRIPTOR(currentBlock + 1, CCI__MIN, true)) { // The values computed above may not be valid. Copy the values already in the result context. skiptoCopyingResult = true; } else { // The descriptor has not been altered yet - this means the ptrBElement[] values used above were not modified yet // and the computation result is valid. cellindexint newDescriptor = MAKE_CELLDESCRIPTOR(currentBlock + 1, CCI__MIN, true); // put the computation at the top so that the evaluation result from the expression above is reused // Assign the results to the result context (possibly in parallel with other threads // that could and ought to be assigning exactly the same values) SolveL1TransposedCellContext &resultContext = buildResultContextRef(cellContexts, currentBlock, blockCount); resultContext.storePrecalculatedZs(Y); // Assign the result assignment progress descriptor CooperativeAtomics::AtomicCompareExchangeCellindexint(&blockProgressDescriptors[currentBlock], existingDescriptor, newDescriptor); // the result is to be ignored // Whether succeeded or not, the result is valid, so go on trying to assign it to the matrix } } if (!skipToHandlingSubsequentRows) { if (skiptoCopyingResult) { // Extract the result values stored in the result context const SolveL1TransposedCellContext &resultContext = buildResultContextRef(cellContexts, currentBlock, blockCount); resultContext.loadPrecalculatedZs(Y); ptrBElement = currentBlock != 0 ? adjustedLastBElement - (sizeint)(currentBlock * block_step) * b_stride : lastBElement; } goAssigningTheResult = true; } } } if (goAssigningTheResult) { cellindexint existingDescriptor = blockProgressDescriptors[currentBlock]; // Check if the assignment has not been completed yet if (existingDescriptor != INVALID_CELLDESCRIPTOR) { // Assign the computation results to B vector if (partialBlock) { // ptrBElement[0 * b_stride] = Y[0]; -- unchanged if (loopX1RowCount >= 2) { ptrBElement[-1 * (int)b_stride] = Y[1]; if (loopX1RowCount > 2) { ptrBElement[-2 * (int)b_stride] = Y[2]; } } dSASSERT(block_step == 4); } else { ptrBElement[0 * b_stride] = Y[0]; ptrBElement[-1 * (int)b_stride] = Y[1]; ptrBElement[-2 * (int)b_stride] = Y[2]; ptrBElement[-3 * (int)b_stride] = Y[3]; dSASSERT(block_step == 4); } ThrsafeIncrementIntUpToLimit(&refBlockCompletionProgress, currentBlock + 1); dIASSERT(refBlockCompletionProgress >= currentBlock + 1); // And assign the completed status no matter what CooperativeAtomics::AtomicStoreCellindexint(&blockProgressDescriptors[currentBlock], INVALID_CELLDESCRIPTOR); } else { // everything is over -- just go handling next blocks } } if (!stayWithinTheBlock) { completedBlocks = refBlockCompletionProgress; if (completedBlocks == blockCount) { break; } currentBlock += 1; bool lookaheadBoundaryReached = false; if (currentBlock == blockCount || completedBlocks == 0) { lookaheadBoundaryReached = true; } else if (currentBlock >= completedBlocks + lookaheadRange) { lookaheadBoundaryReached = blockProcessingState > BPS_NO_BLOCKS_PROCESSED; } else if (currentBlock < completedBlocks) { // Treat detected row advancement as a row processed // blockProcessingState = BPS_SOME_BLOCKS_PROCESSED; <-- performs better without it currentBlock = completedBlocks; } if (lookaheadBoundaryReached) { dIASSERT(blockProcessingState != BPS_COMPETING_FOR_A_BLOCK); // Why did not we compete??? // If no row has been processed in the previous pass, compete for the next row to avoid cycling uselessly if (blockProcessingState <= BPS_NO_BLOCKS_PROCESSED) { // Abandon job if too few blocks remain if (blockCount - completedBlocks <= ownThreadIndex) { break; } blockProcessingState = BPS_COMPETING_FOR_A_BLOCK; } else { // If there was some progress, just continue to the next pass blockProcessingState = BPS_NO_BLOCKS_PROCESSED; } currentBlock = completedBlocks; } } } } #endif ode-0.16/ode/src/quickstep.cpp0000664000175200017520000043703113403272463013224 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include #include #include #include #include "config.h" #include "matrix.h" #include "odemath.h" #include "objects.h" #include "joints/joint.h" #include "lcp.h" #include "util.h" #include "threadingutils.h" #include //*************************************************************************** // configuration // for the SOR and CG methods: // uncomment the following line to use warm starting. this definitely // help for motor-driven joints. unfortunately it appears to hurt // with high-friction contacts using the SOR method. use with care // #define WARM_STARTING 1 #define REORDERING_METHOD__DONT_REORDER 0 #define REORDERING_METHOD__BY_ERROR 1 #define REORDERING_METHOD__RANDOMLY 2 // for the SOR method: // uncomment the following line to determine a new constraint-solving // order for each iteration. however, the qsort per iteration is expensive, // and the optimal order is somewhat problem dependent. // @@@ try the leaf->root ordering. // #define CONSTRAINTS_REORDERING_METHOD REORDERING_METHOD__BY_ERROR // for the SOR method: // uncomment the following line to randomly reorder constraint rows // during the solution. depending on the situation, this can help a lot // or hardly at all, but it doesn't seem to hurt. #define CONSTRAINTS_REORDERING_METHOD REORDERING_METHOD__RANDOMLY #if !defined(CONSTRAINTS_REORDERING_METHOD) #define CONSTRAINTS_REORDERING_METHOD REORDERING_METHOD__DONT_REORDER #endif #if CONSTRAINTS_REORDERING_METHOD == REORDERING_METHOD__RANDOMLY #if !defined(RANDOM_CONSTRAINTS_REORDERING_FREQUENCY) #define RANDOM_CONSTRAINTS_REORDERING_FREQUENCY 8U #endif dSASSERT(RANDOM_CONSTRAINTS_REORDERING_FREQUENCY != 0); #endif enum dxRandomReorderStage { RRS__MIN, RRS_REORDERING = RRS__MIN, RRS__MAX, }; //*************************************************************************** // macros, typedefs, forwards and inlines struct IndexError; #define dMIN(A,B) ((A)>(B) ? (B) : (A)) #define dMAX(A,B) ((B)>(A) ? (B) : (A)) #define dxQUICKSTEPISLAND_STAGE2B_STEP 16U #define dxQUICKSTEPISLAND_STAGE2C_STEP 32U #ifdef WARM_STARTING #define dxQUICKSTEPISLAND_STAGE4A_STEP 256U #else #define dxQUICKSTEPISLAND_STAGE4A_STEP 512U #endif #define dxQUICKSTEPISLAND_STAGE4LCP_IMJ_STEP 8U #define dxQUICKSTEPISLAND_STAGE4LCP_AD_STEP 8U #ifdef WARM_STARTING #define dxQUICKSTEPISLAND_STAGE4LCP_FC_STEP 128U #define dxQUICKSTEPISLAND_STAGE4LCP_FC_COMPLETE_TO_PREPARE_COMPLEXITY_DIVISOR 4 #define dxQUICKSTEPISLAND_STAGE4LCP_FC_STEP_PREPARE (dxQUICKSTEPISLAND_STAGE4LCP_FC_STEP * dxQUICKSTEPISLAND_STAGE4LCP_FC_COMPLETE_TO_PREPARE_COMPLEXITY_DIVISOR) #define dxQUICKSTEPISLAND_STAGE4LCP_FC_STEP_COMPLETE (dxQUICKSTEPISLAND_STAGE4LCP_FC_STEP) #else #define dxQUICKSTEPISLAND_STAGE4LCP_FC_STEP (dxQUICKSTEPISLAND_STAGE4A_STEP / 2) // Average info.m is 3 for stage4a, while there are 6 reals per index in fc #endif #define dxQUICKSTEPISLAND_STAGE4B_STEP 256U #define dxQUICKSTEPISLAND_STAGE6A_STEP 16U #define dxQUICKSTEPISLAND_STAGE6B_STEP 1U template inline unsigned int CalculateOptimalThreadsCount(unsigned int complexity, unsigned int max_threads) { unsigned int raw_threads = dMAX(complexity, step_size) / step_size; // Round down on division unsigned int optimum = dMIN(raw_threads, max_threads); return optimum; } #define dxENCODE_INDEX(index) ((unsigned int)((index) + 1)) #define dxDECODE_INDEX(code) ((unsigned int)((code) - 1)) #define dxHEAD_INDEX 0 //**************************************************************************** // special matrix multipliers // multiply block of B matrix (q x 6) with 12 dReal per row with C vector (q) static inline void Multiply1_12q1 (dReal *A, const dReal *B, const dReal *C, unsigned int q) { dIASSERT (q>0 && A && B && C); dReal a = 0; dReal b = 0; dReal c = 0; dReal d = 0; dReal e = 0; dReal f = 0; dReal s; for(unsigned int i=0, k = 0; i void compute_invM_JT (volatile atomicord32 *mi_storage, dReal *iMJ, unsigned int m, const dReal *J, const dxJBodiesItem *jb, dxBody * const *body, const dReal *invI) { unsigned int m_steps = (m + (step_size - 1)) / step_size; unsigned mi_step; while ((mi_step = ThrsafeIncrementIntUpToLimit(mi_storage, m_steps)) != m_steps) { unsigned int mi = mi_step * step_size; const unsigned int miend = mi + dMIN(step_size, m - mi); dReal *iMJ_ptr = iMJ + (sizeint)mi * IMJ__MAX; const dReal *J_ptr = J + (sizeint)mi * JME__MAX; while (true) { int b1 = jb[mi].first; int b2 = jb[mi].second; dReal k1 = body[(unsigned)b1]->invMass; for (unsigned int j = 0; j != JVE__L_COUNT; j++) iMJ_ptr[IMJ__1L_MIN + j] = k1 * J_ptr[JME__J1L_MIN + j]; const dReal *invIrow1 = invI + (sizeint)(unsigned)b1 * IIE__MAX + IIE__MATRIX_MIN; dMultiply0_331 (iMJ_ptr + IMJ__1A_MIN, invIrow1, J_ptr + JME__J1A_MIN); if (b2 != -1) { dReal k2 = body[(unsigned)b2]->invMass; for (unsigned int j = 0; j != JVE__L_COUNT; ++j) iMJ_ptr[IMJ__2L_MIN + j] = k2 * J_ptr[JME__J2L_MIN + j]; const dReal *invIrow2 = invI + (sizeint)(unsigned)b2 * IIE__MAX + IIE__MATRIX_MIN; dMultiply0_331 (iMJ_ptr + IMJ__2A_MIN, invIrow2, J_ptr + JME__J2A_MIN); } if (++mi == miend) { break; } iMJ_ptr += IMJ__MAX; J_ptr += JME__MAX; } } } #ifdef WARM_STARTING static void multiply_invM_JT_init_array(unsigned int nb, atomicord32 *bi_links/*=[nb]*/) { // const unsigned businessIndex_none = dxENCODE_INDEX(-1); // for (unsigned int bi = 0; bi != nb; ++bi) { // bi_links[bi] = businessIndex_none; // } memset(bi_links, 0, nb * sizeof(bi_links[0])); } // compute out = inv(M)*J'*in. template void multiply_invM_JT_prepare(volatile atomicord32 *mi_storage, unsigned int m, const dxJBodiesItem *jb, atomicord32 *bi_links/*=[nb]*/, atomicord32 *mi_links/*=[2*m]*/) { unsigned int m_steps = (m + (step_size - 1)) / step_size; unsigned mi_step; while ((mi_step = ThrsafeIncrementIntUpToLimit(mi_storage, m_steps)) != m_steps) { unsigned int mi = mi_step * step_size; const unsigned int miend = mi + dMIN(step_size, m - mi); while (true) { int b1 = jb[mi].first; int b2 = jb[mi].second; const unsigned encoded_mi = dxENCODE_INDEX(mi); unsigned oldIndex_b1 = ThrsafeExchange(&bi_links[b1], encoded_mi); mi_links[(sizeint)mi * 2] = oldIndex_b1; if (b2 != -1) { unsigned oldIndex_b2 = ThrsafeExchange(&bi_links[b2], encoded_mi); mi_links[(sizeint)mi * 2 + 1] = oldIndex_b2; } if (++mi == miend) { break; } } } } template void multiply_invM_JT_complete(volatile atomicord32 *bi_storage, dReal *out, unsigned int nb, const dReal *iMJ, const dxJBodiesItem *jb, const dReal *in, atomicord32 *bi_links/*=[nb]*/, atomicord32 *mi_links/*=[2*m]*/) { const unsigned businessIndex_none = dxENCODE_INDEX(-1); unsigned int nb_steps = (nb + (step_size - 1)) / step_size; unsigned bi_step; while ((bi_step = ThrsafeIncrementIntUpToLimit(bi_storage, nb_steps)) != nb_steps) { unsigned int bi = bi_step * step_size; const unsigned int biend = bi + dMIN(step_size, nb - bi); dReal *out_ptr = out + (sizeint)bi * out_stride + out_offset; while (true) { dReal psum0 = REAL(0.0), psum1 = REAL(0.0), psum2 = REAL(0.0), psum3 = REAL(0.0), psum4 = REAL(0.0), psum5 = REAL(0.0); unsigned businessIndex = bi_links[bi]; while (businessIndex != businessIndex_none) { unsigned int mi = dxDECODE_INDEX(businessIndex); const dReal *iMJ_ptr; if (bi == jb[mi].first) { iMJ_ptr = iMJ + (sizeint)mi * IMJ__MAX + IMJ__1_MIN; businessIndex = mi_links[(sizeint)mi * 2]; } else { dIASSERT(bi == jb[mi].second); iMJ_ptr = iMJ + (sizeint)mi * IMJ__MAX + IMJ__2_MIN; businessIndex = mi_links[(sizeint)mi * 2 + 1]; } const dReal in_i = in[mi]; psum0 += in_i * iMJ_ptr[JVE_LX]; psum1 += in_i * iMJ_ptr[JVE_LY]; psum2 += in_i * iMJ_ptr[JVE_LZ]; psum3 += in_i * iMJ_ptr[JVE_AX]; psum4 += in_i * iMJ_ptr[JVE_AY]; psum5 += in_i * iMJ_ptr[JVE_AZ]; } out_ptr[dDA_LX] = psum0; out_ptr[dDA_LY] = psum1; out_ptr[dDA_LZ] = psum2; out_ptr[dDA_AX] = psum3; out_ptr[dDA_AY] = psum4; out_ptr[dDA_AZ] = psum5; if (++bi == biend) { break; } out_ptr += out_stride; } } } template void _multiply_invM_JT (dReal *out, unsigned int m, unsigned int nb, dReal *iMJ, const dxJBodiesItem *jb, const dReal *in) { dSetZero (out, (sizeint)nb * out_stride); const dReal *iMJ_ptr = iMJ; for (unsigned int i=0; i= JVE__MAX); dSASSERT(JVE__MAX == (int)dDA__MAX); if (b2 != -1) { out_ptr = out + (sizeint)(unsigned)b2 * out_stride + out_offset; for (unsigned int j = JVE__MIN; j != JVE__MAX; j++) out_ptr[j - JVE__MIN] += iMJ_ptr[IMJ__2_MIN + j] * in_i; dSASSERT(out_stride - out_offset >= JVE__MAX); dSASSERT(JVE__MAX == (int)dDA__MAX); } iMJ_ptr += IMJ__MAX; } } #endif // compute out = J*in. template void multiplyAdd_J (volatile atomicord32 *mi_storage, unsigned int m, dReal *J, const dxJBodiesItem *jb, const dReal *in) { unsigned int m_steps = (m + (step_size - 1)) / step_size; unsigned mi_step; while ((mi_step = ThrsafeIncrementIntUpToLimit(mi_storage, m_steps)) != m_steps) { unsigned int mi = mi_step * step_size; const unsigned int miend = mi + dMIN(step_size, m - mi); dReal *J_ptr = J + (sizeint)mi * JME__MAX; while (true) { int b1 = jb[mi].first; int b2 = jb[mi].second; dReal sum = REAL(0.0); const dReal *in_ptr = in + (sizeint)(unsigned)b1 * in_stride + in_offset; for (unsigned int j = 0; j != JME__J1_COUNT; ++j) sum += J_ptr[j + JME__J1_MIN] * in_ptr[j]; dSASSERT(in_offset + JME__J1_COUNT <= in_stride); if (b2 != -1) { in_ptr = in + (sizeint)(unsigned)b2 * in_stride + in_offset; for (unsigned int j = 0; j != JME__J2_COUNT; ++j) sum += J_ptr[j + JME__J2_MIN] * in_ptr[j]; dSASSERT(in_offset + JME__J2_COUNT <= in_stride); } J_ptr[JME_RHS] += sum; if (++mi == miend) { break; } J_ptr += JME__MAX; } } } struct IndexError { #if CONSTRAINTS_REORDERING_METHOD == REORDERING_METHOD__BY_ERROR dReal error; // error to sort on #endif int index; // row index }; #if CONSTRAINTS_REORDERING_METHOD == REORDERING_METHOD__BY_ERROR static int compare_index_error (const void *a, const void *b) { const IndexError *i1 = (IndexError*) a; const IndexError *i2 = (IndexError*) b; if (i1->error < i2->error) return -1; if (i1->error > i2->error) return 1; return 0; } #endif // #if CONSTRAINTS_REORDERING_METHOD == REORDERING_METHOD__BY_ERROR static inline bool IsSORConstraintsReorderRequiredForIteration(unsigned iteration) { bool result = false; #if CONSTRAINTS_REORDERING_METHOD == REORDERING_METHOD__BY_ERROR result = true; #elif CONSTRAINTS_REORDERING_METHOD == REORDERING_METHOD__RANDOMLY // This logic is intended to skip randomization on the very first iteration if (!dIN_RANGE(iteration, 0, RANDOM_CONSTRAINTS_REORDERING_FREQUENCY) ? dIN_RANGE(iteration % RANDOM_CONSTRAINTS_REORDERING_FREQUENCY, RRS__MIN, RRS__MAX) : iteration == 0) { result = true; } #else // #if CONSTRAINTS_REORDERING_METHOD != REORDERING_METHOD__BY_ERROR && CONSTRAINTS_REORDERING_METHOD != REORDERING_METHOD__RANDOMLY if (iteration == 0) { result = true; } #endif return result; } /*extern */ void dxQuickStepIsland(const dxStepperProcessingCallContext *callContext) { dxWorldProcessMemArena *memarena = callContext->m_stepperArena; unsigned int nb = callContext->m_islandBodiesCount; unsigned int _nj = callContext->m_islandJointsCount; dReal *invI = memarena->AllocateOveralignedArray((sizeint)nb * IIE__MAX, INVI_ALIGNMENT); dJointWithInfo1 *const jointinfos = memarena->AllocateArray(_nj); const unsigned allowedThreads = callContext->m_stepperAllowedThreads; dIASSERT(allowedThreads != 0); void *stagesMemArenaState = memarena->SaveState(); dxQuickStepperStage1CallContext *stage1CallContext = (dxQuickStepperStage1CallContext *)memarena->AllocateBlock(sizeof(dxQuickStepperStage1CallContext)); stage1CallContext->Initialize(callContext, stagesMemArenaState, invI, jointinfos); dxQuickStepperStage0BodiesCallContext *stage0BodiesCallContext = (dxQuickStepperStage0BodiesCallContext *)memarena->AllocateBlock(sizeof(dxQuickStepperStage0BodiesCallContext)); stage0BodiesCallContext->Initialize(callContext, invI); dxQuickStepperStage0JointsCallContext *stage0JointsCallContext = (dxQuickStepperStage0JointsCallContext *)memarena->AllocateBlock(sizeof(dxQuickStepperStage0JointsCallContext)); stage0JointsCallContext->Initialize(callContext, jointinfos, &stage1CallContext->m_stage0Outputs); if (allowedThreads == 1) { IFTIMING(dTimerStart("preprocessing")); dxQuickStepIsland_Stage0_Bodies(stage0BodiesCallContext); dxQuickStepIsland_Stage0_Joints(stage0JointsCallContext); dxQuickStepIsland_Stage1(stage1CallContext); } else { unsigned bodyThreads = CalculateOptimalThreadsCount<1U>(nb, allowedThreads); unsigned jointThreads = 1; dxWorld *world = callContext->m_world; dCallReleaseeID stage1CallReleasee; world->PostThreadedCallForUnawareReleasee(NULL, &stage1CallReleasee, bodyThreads + jointThreads, callContext->m_finalReleasee, NULL, &dxQuickStepIsland_Stage1_Callback, stage1CallContext, 0, "QuickStepIsland Stage1"); // It is preferable to post single threaded task first to be started sooner world->PostThreadedCall(NULL, NULL, 0, stage1CallReleasee, NULL, &dxQuickStepIsland_Stage0_Joints_Callback, stage0JointsCallContext, 0, "QuickStepIsland Stage0-Joints"); dIASSERT(jointThreads == 1); if (bodyThreads > 1) { world->PostThreadedCallsGroup(NULL, bodyThreads - 1, stage1CallReleasee, &dxQuickStepIsland_Stage0_Bodies_Callback, stage0BodiesCallContext, "QuickStepIsland Stage0-Bodies"); } dxQuickStepIsland_Stage0_Bodies(stage0BodiesCallContext); world->AlterThreadedCallDependenciesCount(stage1CallReleasee, -1); } } static int dxQuickStepIsland_Stage0_Bodies_Callback(void *_callContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused (void)callThisReleasee; // unused dxQuickStepperStage0BodiesCallContext *callContext = (dxQuickStepperStage0BodiesCallContext *)_callContext; dxQuickStepIsland_Stage0_Bodies(callContext); return 1; } static void dxQuickStepIsland_Stage0_Bodies(dxQuickStepperStage0BodiesCallContext *callContext) { dxBody * const *body = callContext->m_stepperCallContext->m_islandBodiesStart; unsigned int nb = callContext->m_stepperCallContext->m_islandBodiesCount; if (ThrsafeExchange(&callContext->m_tagsTaken, 1) == 0) { // number all bodies in the body list - set their tag values for (unsigned int i=0; itag = i; } if (ThrsafeExchange(&callContext->m_gravityTaken, 1) == 0) { dxWorld *world = callContext->m_stepperCallContext->m_world; // add the gravity force to all bodies // since gravity does normally have only one component it's more efficient // to run three loops for each individual component dxBody *const *const bodyend = body + nb; dReal gravity_x = world->gravity[0]; if (gravity_x) { for (dxBody *const *bodycurr = body; bodycurr != bodyend; bodycurr++) { dxBody *b = *bodycurr; if ((b->flags & dxBodyNoGravity) == 0) { b->facc[0] += b->mass.mass * gravity_x; } } } dReal gravity_y = world->gravity[1]; if (gravity_y) { for (dxBody *const *bodycurr = body; bodycurr != bodyend; bodycurr++) { dxBody *b = *bodycurr; if ((b->flags & dxBodyNoGravity) == 0) { b->facc[1] += b->mass.mass * gravity_y; } } } dReal gravity_z = world->gravity[2]; if (gravity_z) { for (dxBody *const *bodycurr = body; bodycurr != bodyend; bodycurr++) { dxBody *b = *bodycurr; if ((b->flags & dxBodyNoGravity) == 0) { b->facc[2] += b->mass.mass * gravity_z; } } } } // for all bodies, compute the inertia tensor and its inverse in the global // frame, and compute the rotational force and add it to the torque // accumulator. I and invI are a vertical stack of 3x4 matrices, one per body. { dReal *invI = callContext->m_invI; unsigned int bodyIndex; while ((bodyIndex = ThrsafeIncrementIntUpToLimit(&callContext->m_inertiaBodyIndex, nb)) != nb) { dReal *invIrow = invI + (sizeint)bodyIndex * IIE__MAX; dxBody *b = body[bodyIndex]; dMatrix3 tmp; // compute inverse inertia tensor in global frame dMultiply2_333 (tmp, b->invI, b->posr.R); dMultiply0_333 (invIrow + IIE__MATRIX_MIN, b->posr.R, tmp); // Don't apply gyroscopic torques to bodies // if not flagged or the body is kinematic if ((b->flags & dxBodyGyroscopic) && (b->invMass > 0)) { dMatrix3 I; // compute inertia tensor in global frame dMultiply2_333 (tmp, b->mass.I, b->posr.R); dMultiply0_333 (I, b->posr.R, tmp); // compute rotational force #if 0 // Explicit computation dMultiply0_331 (tmp, I, b->avel); dSubtractVectorCross3(b->tacc, b->avel, tmp); #else // Do the implicit computation based on //"Stabilizing Gyroscopic Forces in Rigid Multibody Simulations" // (Lacoursière 2006) dReal h = callContext->m_stepperCallContext->m_stepSize; // Step size dVector3 L; // Compute angular momentum dMultiply0_331(L, I, b->avel); // Compute a new effective 'inertia tensor' // for the implicit step: the cross-product // matrix of the angular momentum plus the // old tensor scaled by the timestep. // Itild may not be symmetric pos-definite, // but we can still use it to compute implicit // gyroscopic torques. dMatrix3 Itild = { 0 }; dSetCrossMatrixMinus(Itild, L, 4); for (int ii = dM3E__MIN; ii < dM3E__MAX; ++ii) { Itild[ii] = Itild[ii] * h + I[ii]; } // Scale momentum by inverse time to get // a sort of "torque" dScaleVector3(L, dRecip(h)); // Invert the pseudo-tensor dMatrix3 itInv; // This is a closed-form inversion. // It's probably not numerically stable // when dealing with small masses with // a large asymmetry. // An LU decomposition might be better. if (dInvertMatrix3(itInv, Itild) != 0) { // "Divide" the original tensor // by the pseudo-tensor (on the right) dMultiply0_333(Itild, I, itInv); // Subtract an identity matrix Itild[dM3E_XX] -= 1; Itild[dM3E_YY] -= 1; Itild[dM3E_ZZ] -= 1; // This new inertia matrix rotates the // momentum to get a new set of torques // that will work correctly when applied // to the old inertia matrix as explicit // torques with a semi-implicit update // step. dVector3 tau0; dMultiply0_331(tau0, Itild, L); // Add the gyro torques to the torque // accumulator dAddVectors3(b->tacc, b->tacc, tau0); } #endif } } } } static int dxQuickStepIsland_Stage0_Joints_Callback(void *_callContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused (void)callThisReleasee; // unused dxQuickStepperStage0JointsCallContext *callContext = (dxQuickStepperStage0JointsCallContext *)_callContext; dxQuickStepIsland_Stage0_Joints(callContext); return 1; } static void dxQuickStepIsland_Stage0_Joints(dxQuickStepperStage0JointsCallContext *callContext) { dxJoint * const *_joint = callContext->m_stepperCallContext->m_islandJointsStart; unsigned int _nj = callContext->m_stepperCallContext->m_islandJointsCount; // get joint information (m = total constraint dimension, nub = number of unbounded variables). // joints with m=0 are inactive and are removed from the joints array // entirely, so that the code that follows does not consider them. { unsigned int mcurr = 0, mfbcurr = 0; dJointWithInfo1 *jicurr = callContext->m_jointinfos; dxJoint *const *const _jend = _joint + _nj; for (dxJoint *const *_jcurr = _joint; _jcurr != _jend; _jcurr++) { // jicurr=dest, _jcurr=src dxJoint *j = *_jcurr; j->getInfo1 (&jicurr->info); dIASSERT (/*jicurr->info.m >= 0 && */jicurr->info.m <= 6 && /*jicurr->info.nub >= 0 && */jicurr->info.nub <= jicurr->info.m); unsigned int jm = jicurr->info.m; if (jm != 0) { mcurr += jm; if (j->feedback != NULL) { mfbcurr += jm; } jicurr->joint = j; jicurr++; } } callContext->m_stage0Outputs->m = mcurr; callContext->m_stage0Outputs->mfb = mfbcurr; callContext->m_stage0Outputs->nj = (unsigned int)(jicurr - callContext->m_jointinfos); dIASSERT((sizeint)(jicurr - callContext->m_jointinfos) < UINT_MAX || (sizeint)(jicurr - callContext->m_jointinfos) == UINT_MAX); // to avoid "...always evaluates to true" warnings } } static int dxQuickStepIsland_Stage1_Callback(void *_stage1CallContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused (void)callThisReleasee; // unused dxQuickStepperStage1CallContext *stage1CallContext = (dxQuickStepperStage1CallContext *)_stage1CallContext; dxQuickStepIsland_Stage1(stage1CallContext); return 1; } static void dxQuickStepIsland_Stage1(dxQuickStepperStage1CallContext *stage1CallContext) { const dxStepperProcessingCallContext *callContext = stage1CallContext->m_stepperCallContext; dReal *invI = stage1CallContext->m_invI; dJointWithInfo1 *jointinfos = stage1CallContext->m_jointinfos; unsigned int nj = stage1CallContext->m_stage0Outputs.nj; unsigned int m = stage1CallContext->m_stage0Outputs.m; unsigned int mfb = stage1CallContext->m_stage0Outputs.mfb; dxWorldProcessMemArena *memarena = callContext->m_stepperArena; memarena->RestoreState(stage1CallContext->m_stageMemArenaState); stage1CallContext = NULL; // WARNING! _stage1CallContext is not valid after this point! dIVERIFY(stage1CallContext == NULL); // To suppress unused variable assignment warnings { unsigned int _nj = callContext->m_islandJointsCount; memarena->ShrinkArray(jointinfos, _nj, nj); } dxMIndexItem *mindex = NULL; dxJBodiesItem *jb = NULL; int *findex = NULL; dReal *J = NULL, *Jcopy = NULL; // if there are constraints, compute the constraint force if (m > 0) { mindex = memarena->AllocateArray(nj + 1); { dxMIndexItem *mcurr = mindex; unsigned int moffs = 0, mfboffs = 0; mcurr->mIndex = moffs; mcurr->fbIndex = mfboffs; ++mcurr; const dJointWithInfo1 *const jiend = jointinfos + nj; for (const dJointWithInfo1 *jicurr = jointinfos; jicurr != jiend; ++jicurr) { dxJoint *joint = jicurr->joint; moffs += jicurr->info.m; if (joint->feedback) { mfboffs += jicurr->info.m; } mcurr->mIndex = moffs; mcurr->fbIndex = mfboffs; ++mcurr; } } jb = memarena->AllocateArray(m); findex = memarena->AllocateArray(m); J = memarena->AllocateOveralignedArray((sizeint)m * JME__MAX, JACOBIAN_ALIGNMENT); Jcopy = memarena->AllocateOveralignedArray((sizeint)mfb * JCE__MAX, JCOPY_ALIGNMENT); } dxQuickStepperLocalContext *localContext = (dxQuickStepperLocalContext *)memarena->AllocateBlock(sizeof(dxQuickStepperLocalContext)); localContext->Initialize(invI, jointinfos, nj, m, mfb, mindex, jb, findex, J, Jcopy); void *stage1MemarenaState = memarena->SaveState(); dxQuickStepperStage3CallContext *stage3CallContext = (dxQuickStepperStage3CallContext*)memarena->AllocateBlock(sizeof(dxQuickStepperStage3CallContext)); stage3CallContext->Initialize(callContext, localContext, stage1MemarenaState); if (m > 0) { unsigned int nb = callContext->m_islandBodiesCount; // create a constraint equation right hand side vector `rhs', a constraint // force mixing vector `cfm', and LCP low and high bound vectors, and an // 'findex' vector. dReal *rhs_tmp = memarena->AllocateArray((sizeint)nb * RHS__MAX); dxQuickStepperStage2CallContext *stage2CallContext = (dxQuickStepperStage2CallContext*)memarena->AllocateBlock(sizeof(dxQuickStepperStage2CallContext)); stage2CallContext->Initialize(callContext, localContext, rhs_tmp); const unsigned allowedThreads = callContext->m_stepperAllowedThreads; dIASSERT(allowedThreads != 0); if (allowedThreads == 1) { IFTIMING (dTimerNow ("create J")); dxQuickStepIsland_Stage2a(stage2CallContext); IFTIMING (dTimerNow ("compute rhs_tmp")); dxQuickStepIsland_Stage2b(stage2CallContext); dxQuickStepIsland_Stage2c(stage2CallContext); dxQuickStepIsland_Stage3(stage3CallContext); } else { dxWorld *world = callContext->m_world; dCallReleaseeID stage3CallReleasee; world->PostThreadedCallForUnawareReleasee(NULL, &stage3CallReleasee, 1, callContext->m_finalReleasee, NULL, &dxQuickStepIsland_Stage3_Callback, stage3CallContext, 0, "QuickStepIsland Stage3"); dCallReleaseeID stage2bSyncReleasee; world->PostThreadedCall(NULL, &stage2bSyncReleasee, 1, stage3CallReleasee, NULL, &dxQuickStepIsland_Stage2bSync_Callback, stage2CallContext, 0, "QuickStepIsland Stage2b Sync"); unsigned stage2a_allowedThreads = CalculateOptimalThreadsCount<1U>(nj, allowedThreads); dCallReleaseeID stage2aSyncReleasee; world->PostThreadedCall(NULL, &stage2aSyncReleasee, stage2a_allowedThreads, stage2bSyncReleasee, NULL, &dxQuickStepIsland_Stage2aSync_Callback, stage2CallContext, 0, "QuickStepIsland Stage2a Sync"); if (stage2a_allowedThreads > 1) { world->PostThreadedCallsGroup(NULL, stage2a_allowedThreads - 1, stage2aSyncReleasee, &dxQuickStepIsland_Stage2a_Callback, stage2CallContext, "QuickStepIsland Stage2a"); } dxQuickStepIsland_Stage2a(stage2CallContext); world->AlterThreadedCallDependenciesCount(stage2aSyncReleasee, -1); } } else { dxQuickStepIsland_Stage3(stage3CallContext); } } static int dxQuickStepIsland_Stage2a_Callback(void *_stage2CallContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused (void)callThisReleasee; // unused dxQuickStepperStage2CallContext *stage2CallContext = (dxQuickStepperStage2CallContext *)_stage2CallContext; dxQuickStepIsland_Stage2a(stage2CallContext); return 1; } static void dxQuickStepIsland_Stage2a(dxQuickStepperStage2CallContext *stage2CallContext) { const dxStepperProcessingCallContext *callContext = stage2CallContext->m_stepperCallContext; dxQuickStepperLocalContext *localContext = stage2CallContext->m_localContext; dJointWithInfo1 *jointinfos = localContext->m_jointinfos; unsigned int nj = localContext->m_nj; const dxMIndexItem *mindex = localContext->m_mindex; const dReal stepsizeRecip = dRecip(callContext->m_stepSize); { int *findex = localContext->m_findex; dReal *J = localContext->m_J; dReal *JCopy = localContext->m_Jcopy; // get jacobian data from constraints. an m*16 matrix will be created // to store the two jacobian blocks from each constraint. it has this // format: // // l1 l1 l1 a1 a1 a1 rhs cfm l2 l2 l2 a2 a2 a2 lo hi \ . // l1 l1 l1 a1 a1 a1 rhs cfm l2 l2 l2 a2 a2 a2 lo hi }-- jacobian for joint 0, body 1 and body 2 (3 rows) // l1 l1 l1 a1 a1 a1 rhs cfm l2 l2 l2 a2 a2 a2 lo hi / // l1 l1 l1 a1 a1 a1 rhs cfm l2 l2 l2 a2 a2 a2 lo hi }--- jacobian for joint 1, body 1 and body 2 (3 rows) // etc... // // (lll) = linear jacobian data // (aaa) = angular jacobian data // dxWorld *world = callContext->m_world; const dReal worldERP = world->global_erp; const dReal worldCFM = world->global_cfm; unsigned validFIndices = 0; unsigned ji; while ((ji = ThrsafeIncrementIntUpToLimit(&stage2CallContext->m_ji_J, nj)) != nj) { const unsigned ofsi = mindex[ji].mIndex; const unsigned int infom = mindex[ji + 1].mIndex - ofsi; dReal *const JRow = J + (sizeint)ofsi * JME__MAX; { dReal *const JEnd = JRow + infom * JME__MAX; for (dReal *JCurr = JRow; JCurr != JEnd; JCurr += JME__MAX) { dSetZero(JCurr + JME__J1_MIN, JME__J1_COUNT); JCurr[JME_RHS] = REAL(0.0); JCurr[JME_CFM] = worldCFM; dSetZero(JCurr + JME__J2_MIN, JME__J2_COUNT); JCurr[JME_LO] = -dInfinity; JCurr[JME_HI] = dInfinity; dSASSERT(JME__J1_COUNT + 2 + JME__J2_COUNT + 2 == JME__MAX); } } int *findexRow = findex + ofsi; dSetValue(findexRow, infom, -1); dxJoint *joint = jointinfos[ji].joint; joint->getInfo2(stepsizeRecip, worldERP, JME__MAX, JRow + JME__J1_MIN, JRow + JME__J2_MIN, JME__MAX, JRow + JME__RHS_CFM_MIN, JRow + JME__LO_HI_MIN, findexRow); // findex iteration is compact and is not going to pollute caches - do it first { // adjust returned findex values for global index numbering int *const findicesEnd = findexRow + infom; for (int *findexCurr = findexRow; findexCurr != findicesEnd; ++findexCurr) { int fival = *findexCurr; if (fival != -1) { *findexCurr = fival + ofsi; ++validFIndices; } } } { dReal *const JEnd = JRow + infom * JME__MAX; for (dReal *JCurr = JRow; JCurr != JEnd; JCurr += JME__MAX) { JCurr[JME_RHS] *= stepsizeRecip; JCurr[JME_CFM] *= stepsizeRecip; } } { // we need a copy of Jacobian for joint feedbacks // because it gets destroyed by SOR solver // instead of saving all Jacobian, we can save just rows // for joints, that requested feedback (which is normally much less) unsigned mfbIndex = mindex[ji].fbIndex; if (mfbIndex != mindex[ji + 1].fbIndex) { dReal *const JEnd = JRow + infom * JME__MAX; dReal *JCopyRow = JCopy + mfbIndex * JCE__MAX; // Random access by mfbIndex here! Do not optimize! for (const dReal *JCurr = JRow; ; ) { for (unsigned i = 0; i != JME__J1_COUNT; ++i) { JCopyRow[i + JCE__J1_MIN] = JCurr[i + JME__J1_MIN]; } for (unsigned j = 0; j != JME__J2_COUNT; ++j) { JCopyRow[j + JCE__J2_MIN] = JCurr[j + JME__J2_MIN]; } JCopyRow += JCE__MAX; dSASSERT((unsigned)JCE__J1_COUNT == JME__J1_COUNT); dSASSERT((unsigned)JCE__J2_COUNT == JME__J2_COUNT); dSASSERT(JCE__J1_COUNT + JCE__J2_COUNT == JCE__MAX); if ((JCurr += JME__MAX) == JEnd) { break; } } } } } if (validFIndices != 0) { ThrsafeAdd(&localContext->m_valid_findices, validFIndices); } } { dxJBodiesItem *jb = localContext->m_jb; // create an array of body numbers for each joint row unsigned ji; while ((ji = ThrsafeIncrementIntUpToLimit(&stage2CallContext->m_ji_jb, nj)) != nj) { dxJoint *joint = jointinfos[ji].joint; int b1 = (joint->node[0].body) ? (joint->node[0].body->tag) : -1; int b2 = (joint->node[1].body) ? (joint->node[1].body->tag) : -1; dxJBodiesItem *const jb_end = jb + mindex[ji + 1].mIndex; dxJBodiesItem *jb_ptr = jb + mindex[ji].mIndex; for (; jb_ptr != jb_end; ++jb_ptr) { jb_ptr->first = b1; jb_ptr->second = b2; } } } } static int dxQuickStepIsland_Stage2aSync_Callback(void *_stage2CallContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused dxQuickStepperStage2CallContext *stage2CallContext = (dxQuickStepperStage2CallContext *)_stage2CallContext; const dxStepperProcessingCallContext *callContext = stage2CallContext->m_stepperCallContext; const unsigned int nb = callContext->m_islandBodiesCount; const unsigned allowedThreads = callContext->m_stepperAllowedThreads; unsigned int stage2b_allowedThreads = CalculateOptimalThreadsCount(nb, allowedThreads); if (stage2b_allowedThreads > 1) { dxWorld *world = callContext->m_world; world->AlterThreadedCallDependenciesCount(callThisReleasee, stage2b_allowedThreads - 1); world->PostThreadedCallsGroup(NULL, stage2b_allowedThreads - 1, callThisReleasee, &dxQuickStepIsland_Stage2b_Callback, stage2CallContext, "QuickStepIsland Stage2b"); } dxQuickStepIsland_Stage2b(stage2CallContext); return 1; } static int dxQuickStepIsland_Stage2b_Callback(void *_stage2CallContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused (void)callThisReleasee; // unused dxQuickStepperStage2CallContext *stage2CallContext = (dxQuickStepperStage2CallContext *)_stage2CallContext; dxQuickStepIsland_Stage2b(stage2CallContext); return 1; } static void dxQuickStepIsland_Stage2b(dxQuickStepperStage2CallContext *stage2CallContext) { const dxStepperProcessingCallContext *callContext = stage2CallContext->m_stepperCallContext; const dxQuickStepperLocalContext *localContext = stage2CallContext->m_localContext; const dReal stepsizeRecip = dRecip(callContext->m_stepSize); { // Warning!!! // This code reads facc/tacc fields of body objects which (the fields) // may be modified by dxJoint::getInfo2(). Therefore the code must be // in different sub-stage from Jacobian construction in Stage2a // to ensure proper synchronization and avoid accessing numbers being modified. // Warning!!! dxBody * const *const body = callContext->m_islandBodiesStart; const unsigned int nb = callContext->m_islandBodiesCount; const dReal *invI = localContext->m_invI; dReal *rhs_tmp = stage2CallContext->m_rhs_tmp; // compute the right hand side `rhs' const unsigned int step_size = dxQUICKSTEPISLAND_STAGE2B_STEP; unsigned int nb_steps = (nb + (step_size - 1)) / step_size; // put -(v/h + invM*fe) into rhs_tmp unsigned bi_step; while ((bi_step = ThrsafeIncrementIntUpToLimit(&stage2CallContext->m_bi, nb_steps)) != nb_steps) { unsigned int bi = bi_step * step_size; const unsigned int biend = bi + dMIN(step_size, nb - bi); dReal *rhscurr = rhs_tmp + (sizeint)bi * RHS__MAX; const dReal *invIrow = invI + (sizeint)bi * IIE__MAX; while (true) { dxBody *b = body[bi]; dReal body_invMass = b->invMass; for (unsigned int j = dSA__MIN; j != dSA__MAX; ++j) rhscurr[RHS__L_MIN + j] = -(b->facc[dV3E__AXES_MIN + j] * body_invMass + b->lvel[dV3E__AXES_MIN + j] * stepsizeRecip); dMultiply0_331 (rhscurr + RHS__A_MIN, invIrow + IIE__MATRIX_MIN, b->tacc); for (unsigned int k = dSA__MIN; k != dSA__MAX; ++k) rhscurr[RHS__A_MIN + k] = -(b->avel[dV3E__AXES_MIN + k] * stepsizeRecip) - rhscurr[RHS__A_MIN + k]; if (++bi == biend) { break; } rhscurr += RHS__MAX; invIrow += IIE__MAX; } } } } static int dxQuickStepIsland_Stage2bSync_Callback(void *_stage2CallContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused dxQuickStepperStage2CallContext *stage2CallContext = (dxQuickStepperStage2CallContext *)_stage2CallContext; const dxStepperProcessingCallContext *callContext = stage2CallContext->m_stepperCallContext; const unsigned allowedThreads = callContext->m_stepperAllowedThreads; const dxQuickStepperLocalContext *localContext = stage2CallContext->m_localContext; unsigned int m = localContext->m_m; unsigned int stage2c_allowedThreads = CalculateOptimalThreadsCount(m, allowedThreads); if (stage2c_allowedThreads > 1) { dxWorld *world = callContext->m_world; world->AlterThreadedCallDependenciesCount(callThisReleasee, stage2c_allowedThreads - 1); world->PostThreadedCallsGroup(NULL, stage2c_allowedThreads - 1, callThisReleasee, &dxQuickStepIsland_Stage2c_Callback, stage2CallContext, "QuickStepIsland Stage2c"); } dxQuickStepIsland_Stage2c(stage2CallContext); return 1; } static int dxQuickStepIsland_Stage2c_Callback(void *_stage2CallContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused (void)callThisReleasee; // unused dxQuickStepperStage2CallContext *stage2CallContext = (dxQuickStepperStage2CallContext *)_stage2CallContext; dxQuickStepIsland_Stage2c(stage2CallContext); return 1; } static void dxQuickStepIsland_Stage2c(dxQuickStepperStage2CallContext *stage2CallContext) { //const dxStepperProcessingCallContext *callContext = stage2CallContext->m_stepperCallContext; const dxQuickStepperLocalContext *localContext = stage2CallContext->m_localContext; //const dReal stepsizeRecip = dRecip(callContext->m_stepSize); { // Warning!!! // This code depends on rhs_tmp and therefore must be in different sub-stage // from rhs_tmp calculation in Stage2b to ensure proper synchronization // and avoid accessing numbers being modified. // Warning!!! dReal *J = localContext->m_J; const dxJBodiesItem *jb = localContext->m_jb; const dReal *rhs_tmp = stage2CallContext->m_rhs_tmp; const unsigned int m = localContext->m_m; // add J*rhs_tmp to rhs multiplyAdd_J(&stage2CallContext->m_Jrhsi, m, J, jb, rhs_tmp); } } static int dxQuickStepIsland_Stage3_Callback(void *_stage3CallContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused (void)callThisReleasee; // unused dxQuickStepperStage3CallContext *stage3CallContext = (dxQuickStepperStage3CallContext *)_stage3CallContext; dxQuickStepIsland_Stage3(stage3CallContext); return 1; } static void dxQuickStepIsland_Stage3(dxQuickStepperStage3CallContext *stage3CallContext) { const dxStepperProcessingCallContext *callContext = stage3CallContext->m_stepperCallContext; const dxQuickStepperLocalContext *localContext = stage3CallContext->m_localContext; dxWorldProcessMemArena *memarena = callContext->m_stepperArena; memarena->RestoreState(stage3CallContext->m_stage1MemArenaState); stage3CallContext = NULL; // WARNING! stage3CallContext is not valid after this point! dIVERIFY(stage3CallContext == NULL); // To suppress unused variable assignment warnings void *stage3MemarenaState = memarena->SaveState(); dxQuickStepperStage5CallContext *stage5CallContext = (dxQuickStepperStage5CallContext *)memarena->AllocateBlock(sizeof(dxQuickStepperStage5CallContext)); stage5CallContext->Initialize(callContext, localContext, stage3MemarenaState); unsigned int m = localContext->m_m; if (m > 0) { // load lambda from the value saved on the previous iteration dReal *lambda = memarena->AllocateArray(m); unsigned int nb = callContext->m_islandBodiesCount; dReal *cforce = memarena->AllocateArray((sizeint)nb * CFE__MAX); dReal *iMJ = memarena->AllocateOveralignedArray((sizeint)m * IMJ__MAX, INVMJ_ALIGNMENT); // order to solve constraint rows in IndexError *order = memarena->AllocateArray(m); dReal *last_lambda = NULL; #if CONSTRAINTS_REORDERING_METHOD == REORDERING_METHOD__BY_ERROR // the lambda computed at the previous iteration. // this is used to measure error for when we are reordering the indexes. last_lambda = memarena->AllocateArray(m); #endif const unsigned allowedThreads = callContext->m_stepperAllowedThreads; bool singleThreadedExecution = allowedThreads == 1; dIASSERT(allowedThreads >= 1); atomicord32 *bi_links_or_mi_levels = NULL; atomicord32 *mi_links = NULL; #if !dTHREADING_INTF_DISABLED bi_links_or_mi_levels = memarena->AllocateArray(dMAX(nb, m)); mi_links = memarena->AllocateArray(2 * ((sizeint)m + 1)); #else dIASSERT(singleThreadedExecution); #endif dxQuickStepperStage4CallContext *stage4CallContext = (dxQuickStepperStage4CallContext *)memarena->AllocateBlock(sizeof(dxQuickStepperStage4CallContext)); stage4CallContext->Initialize(callContext, localContext, lambda, cforce, iMJ, order, last_lambda, bi_links_or_mi_levels, mi_links); if (singleThreadedExecution) { dxQuickStepIsland_Stage4a(stage4CallContext); IFTIMING (dTimerNow ("solving LCP problem")); dxQuickStepIsland_Stage4LCP_iMJComputation(stage4CallContext); dxQuickStepIsland_Stage4LCP_STfcComputation(stage4CallContext); dxQuickStepIsland_Stage4LCP_AdComputation(stage4CallContext); dxQuickStepIsland_Stage4LCP_ReorderPrep(stage4CallContext); dxWorld *world = callContext->m_world; const unsigned int num_iterations = world->qs.num_iterations; for (unsigned int iteration=0; iteration < num_iterations; iteration++) { if (IsSORConstraintsReorderRequiredForIteration(iteration)) { stage4CallContext->ResetSOR_ConstraintsReorderVariables(0); dxQuickStepIsland_Stage4LCP_ConstraintsShuffling(stage4CallContext, iteration); } dxQuickStepIsland_Stage4LCP_STIteration(stage4CallContext); } dxQuickStepIsland_Stage4b(stage4CallContext); dxQuickStepIsland_Stage5(stage5CallContext); } else { dxWorld *world = callContext->m_world; dCallReleaseeID stage5CallReleasee; world->PostThreadedCallForUnawareReleasee(NULL, &stage5CallReleasee, 1, callContext->m_finalReleasee, NULL, &dxQuickStepIsland_Stage5_Callback, stage5CallContext, 0, "QuickStepIsland Stage5"); dCallReleaseeID stage4LCP_IterationSyncReleasee; world->PostThreadedCall(NULL, &stage4LCP_IterationSyncReleasee, 1, stage5CallReleasee, NULL, &dxQuickStepIsland_Stage4LCP_IterationSync_Callback, stage4CallContext, 0, "QuickStepIsland Stage4LCP_Iteration Sync"); unsigned int stage4LCP_Iteration_allowedThreads = CalculateOptimalThreadsCount<1U>(m, allowedThreads); stage4CallContext->AssignLCP_IterationData(stage4LCP_IterationSyncReleasee, stage4LCP_Iteration_allowedThreads); dCallReleaseeID stage4LCP_IterationStartReleasee; world->PostThreadedCall(NULL, &stage4LCP_IterationStartReleasee, 3, stage4LCP_IterationSyncReleasee, NULL, &dxQuickStepIsland_Stage4LCP_IterationStart_Callback, stage4CallContext, 0, "QuickStepIsland Stage4LCP_Iteration Start"); unsigned int nj = localContext->m_nj; unsigned int stage4a_allowedThreads = CalculateOptimalThreadsCount(nj, allowedThreads); dCallReleaseeID stage4LCP_fcStartReleasee; // Note: It is unnecessary to make fc dependent on 4a if there is no WARM_STARTING // However I'm doing so to minimize use of preprocessor conditions in sources unsigned stage4LCP_fcDependenciesCountToUse = stage4a_allowedThreads; #ifdef WARM_STARTING // Posted with extra dependency to be removed from dxQuickStepIsland_Stage4LCP_iMJSync_Callback stage4LCP_fcDependenciesCountToUse += 1; #endif world->PostThreadedCall(NULL, &stage4LCP_fcStartReleasee, stage4LCP_fcDependenciesCountToUse, stage4LCP_IterationStartReleasee, NULL, &dxQuickStepIsland_Stage4LCP_fcStart_Callback, stage4CallContext, 0, "QuickStepIsland Stage4LCP_fc Start"); #ifdef WARM_STARTING stage4CallContext->AssignLCP_fcStartReleasee(stage4LCP_fcStartReleasee); #endif unsigned stage4LCP_iMJ_allowedThreads = CalculateOptimalThreadsCount(m, allowedThreads); dCallReleaseeID stage4LCP_iMJSyncReleasee; world->PostThreadedCall(NULL, &stage4LCP_iMJSyncReleasee, stage4LCP_iMJ_allowedThreads, stage4LCP_IterationStartReleasee, NULL, &dxQuickStepIsland_Stage4LCP_iMJSync_Callback, stage4CallContext, 0, "QuickStepIsland Stage4LCP_iMJ Sync"); world->PostThreadedCall(NULL, NULL, 0, stage4LCP_IterationStartReleasee, NULL, &dxQuickStepIsland_Stage4LCP_ReorderPrep_Callback, stage4CallContext, 0, "QuickStepIsland Stage4LCP_ReorderPrep"); world->PostThreadedCallsGroup(NULL, stage4a_allowedThreads, stage4LCP_fcStartReleasee, &dxQuickStepIsland_Stage4a_Callback, stage4CallContext, "QuickStepIsland Stage4a"); if (stage4LCP_iMJ_allowedThreads > 1) { world->PostThreadedCallsGroup(NULL, stage4LCP_iMJ_allowedThreads - 1, stage4LCP_iMJSyncReleasee, &dxQuickStepIsland_Stage4LCP_iMJ_Callback, stage4CallContext, "QuickStepIsland Stage4LCP_iMJ"); } dxQuickStepIsland_Stage4LCP_iMJComputation(stage4CallContext); world->AlterThreadedCallDependenciesCount(stage4LCP_iMJSyncReleasee, -1); } } else { dxQuickStepIsland_Stage5(stage5CallContext); } } static int dxQuickStepIsland_Stage4a_Callback(void *_stage4CallContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused (void)callThisReleasee; // unused dxQuickStepperStage4CallContext *stage4CallContext = (dxQuickStepperStage4CallContext *)_stage4CallContext; dxQuickStepIsland_Stage4a(stage4CallContext); return 1; } static void dxQuickStepIsland_Stage4a(dxQuickStepperStage4CallContext *stage4CallContext) { const dxQuickStepperLocalContext *localContext = stage4CallContext->m_localContext; dReal *lambda = stage4CallContext->m_lambda; const dxMIndexItem *mindex = localContext->m_mindex; #ifdef WARM_STARTING dJointWithInfo1 *jointinfos = localContext->m_jointinfos; #endif unsigned int nj = localContext->m_nj; const unsigned int step_size = dxQUICKSTEPISLAND_STAGE4A_STEP; unsigned int nj_steps = (nj + (step_size - 1)) / step_size; unsigned ji_step; while ((ji_step = ThrsafeIncrementIntUpToLimit(&stage4CallContext->m_ji_4a, nj_steps)) != nj_steps) { unsigned int ji = ji_step * step_size; dReal *lambdacurr = lambda + mindex[ji].mIndex; #ifdef WARM_STARTING const dJointWithInfo1 *jicurr = jointinfos + ji; const dJointWithInfo1 *const jiend = jicurr + dMIN(step_size, nj - ji); do { const dReal *joint_lambdas = jicurr->joint->lambda; dReal *const lambdsnext = lambdacurr + jicurr->info.m; while (true) { // for warm starting, multiplication by 0.9 seems to be necessary to prevent // jerkiness in motor-driven joints. I have no idea why this works. *lambdacurr = *joint_lambdas * 0.9; if (++lambdacurr == lambdsnext) { break; } ++joint_lambdas; } } while (++jicurr != jiend); #else dReal *lambdsnext = lambda + mindex[ji + dMIN(step_size, nj - ji)].mIndex; dSetZero(lambdacurr, lambdsnext - lambdacurr); #endif } } static int dxQuickStepIsland_Stage4LCP_iMJ_Callback(void *_stage4CallContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused (void)callThisReleasee; // unused dxQuickStepperStage4CallContext *stage4CallContext = (dxQuickStepperStage4CallContext *)_stage4CallContext; dxQuickStepIsland_Stage4LCP_iMJComputation(stage4CallContext); return 1; } static void dxQuickStepIsland_Stage4LCP_iMJComputation(dxQuickStepperStage4CallContext *stage4CallContext) { const dxStepperProcessingCallContext *callContext = stage4CallContext->m_stepperCallContext; const dxQuickStepperLocalContext *localContext = stage4CallContext->m_localContext; dReal *iMJ = stage4CallContext->m_iMJ; unsigned int m = localContext->m_m; dReal *J = localContext->m_J; const dxJBodiesItem *jb = localContext->m_jb; dxBody * const *body = callContext->m_islandBodiesStart; dReal *invI = localContext->m_invI; // precompute iMJ = inv(M)*J' compute_invM_JT(&stage4CallContext->m_mi_iMJ, iMJ, m, J, jb, body, invI); } static int dxQuickStepIsland_Stage4LCP_iMJSync_Callback(void *_stage4CallContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused dxQuickStepperStage4CallContext *stage4CallContext = (dxQuickStepperStage4CallContext *)_stage4CallContext; const dxStepperProcessingCallContext *callContext = stage4CallContext->m_stepperCallContext; const dxQuickStepperLocalContext *localContext = stage4CallContext->m_localContext; unsigned int m = localContext->m_m; const unsigned allowedThreads = callContext->m_stepperAllowedThreads; unsigned int stage4LCP_Ad_allowedThreads = CalculateOptimalThreadsCount(m, allowedThreads); #ifdef WARM_STARTING { dxWorld *world = callContext->m_world; world->AlterThreadedCallDependenciesCount(stage4CallContext->m_LCP_fcStartReleasee, -1); } #endif if (stage4LCP_Ad_allowedThreads > 1) { dxWorld *world = callContext->m_world; world->AlterThreadedCallDependenciesCount(callThisReleasee, stage4LCP_Ad_allowedThreads - 1); world->PostThreadedCallsGroup(NULL, stage4LCP_Ad_allowedThreads - 1, callThisReleasee, &dxQuickStepIsland_Stage4LCP_Ad_Callback, stage4CallContext, "QuickStepIsland Stage4LCP_Ad"); } dxQuickStepIsland_Stage4LCP_AdComputation(stage4CallContext); return 1; } static int dxQuickStepIsland_Stage4LCP_fcStart_Callback(void *_stage4CallContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused dxQuickStepperStage4CallContext *stage4CallContext = (dxQuickStepperStage4CallContext *)_stage4CallContext; const dxStepperProcessingCallContext *callContext = stage4CallContext->m_stepperCallContext; const dxQuickStepperLocalContext *localContext = stage4CallContext->m_localContext; unsigned int fcPrepareComplexity, fcCompleteComplexity; #ifdef WARM_STARTING fcPrepareComplexity = localContext->m_m / dxQUICKSTEPISLAND_STAGE4LCP_FC_COMPLETE_TO_PREPARE_COMPLEXITY_DIVISOR; fcCompleteComplexity = callContext->m_islandBodiesCount; #else fcPrepareComplexity = localContext->m_m; fcCompleteComplexity = 0; #endif const unsigned allowedThreads = callContext->m_stepperAllowedThreads; unsigned int stage4LCP_fcPrepare_allowedThreads = CalculateOptimalThreadsCount(fcPrepareComplexity, allowedThreads); unsigned int stage4LCP_fcComplete_allowedThreads = CalculateOptimalThreadsCount(fcCompleteComplexity, allowedThreads); stage4CallContext->AssignLCP_fcAllowedThreads(stage4LCP_fcPrepare_allowedThreads, stage4LCP_fcComplete_allowedThreads); #ifdef WARM_STARTING dxQuickStepIsland_Stage4LCP_MTfcComputation_warmZeroArrays(stage4CallContext); #endif if (stage4LCP_fcPrepare_allowedThreads > 1) { dxWorld *world = callContext->m_world; world->AlterThreadedCallDependenciesCount(callThisReleasee, stage4LCP_fcPrepare_allowedThreads - 1); world->PostThreadedCallsGroup(NULL, stage4LCP_fcPrepare_allowedThreads - 1, callThisReleasee, &dxQuickStepIsland_Stage4LCP_fc_Callback, stage4CallContext, "QuickStepIsland Stage4LCP_fc"); } dxQuickStepIsland_Stage4LCP_MTfcComputation(stage4CallContext, callThisReleasee); return 1; } static int dxQuickStepIsland_Stage4LCP_fc_Callback(void *_stage4CallContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused dxQuickStepperStage4CallContext *stage4CallContext = (dxQuickStepperStage4CallContext *)_stage4CallContext; dxQuickStepIsland_Stage4LCP_MTfcComputation(stage4CallContext, callThisReleasee); return 1; } static void dxQuickStepIsland_Stage4LCP_MTfcComputation(dxQuickStepperStage4CallContext *stage4CallContext, dCallReleaseeID callThisReleasee) { #ifdef WARM_STARTING dxQuickStepIsland_Stage4LCP_MTfcComputation_warm(stage4CallContext, callThisReleasee); #else (void)callThisReleasee; // unused dxQuickStepIsland_Stage4LCP_MTfcComputation_cold(stage4CallContext); #endif } #ifdef WARM_STARTING static void dxQuickStepIsland_Stage4LCP_MTfcComputation_warm(dxQuickStepperStage4CallContext *stage4CallContext, dCallReleaseeID callThisReleasee) { dxQuickStepIsland_Stage4LCP_MTfcComputation_warmPrepare(stage4CallContext); if (ThrsafeExchangeAdd(&stage4CallContext->m_LCP_fcPrepareThreadsRemaining, (atomicord32)(-1)) == 1) { stage4CallContext->ResetLCP_fcComputationIndex(); const dxStepperProcessingCallContext *callContext = stage4CallContext->m_stepperCallContext; unsigned int stage4LCP_fcComplete_allowedThreads = stage4CallContext->m_LCP_fcCompleteThreadsTotal; if (stage4LCP_fcComplete_allowedThreads > 1) { dxWorld *world = callContext->m_world; world->AlterThreadedCallDependenciesCount(callThisReleasee, stage4LCP_fcComplete_allowedThreads - 1); world->PostThreadedCallsGroup(NULL, stage4LCP_fcComplete_allowedThreads - 1, callThisReleasee, &dxQuickStepIsland_Stage4LCP_fcWarmComplete_Callback, stage4CallContext, "QuickStepIsland Stage4LCP_fcWarmComplete"); } dxQuickStepIsland_Stage4LCP_MTfcComputation_warmComplete(stage4CallContext); } } static void dxQuickStepIsland_Stage4LCP_MTfcComputation_warmZeroArrays(dxQuickStepperStage4CallContext *stage4CallContext) { const dxStepperProcessingCallContext *callContext = stage4CallContext->m_stepperCallContext; unsigned int nb = callContext->m_islandBodiesCount; atomicord32 *bi_links = stage4CallContext->m_bi_links_or_mi_levels; multiply_invM_JT_init_array(nb, bi_links); } static void dxQuickStepIsland_Stage4LCP_MTfcComputation_warmPrepare(dxQuickStepperStage4CallContext *stage4CallContext) { const dxStepperProcessingCallContext *callContext = stage4CallContext->m_stepperCallContext; const dxQuickStepperLocalContext *localContext = stage4CallContext->m_localContext; unsigned int m = localContext->m_m; const dxJBodiesItem *jb = localContext->m_jb; // Prepare to compute fc=(inv(M)*J')*lambda. we will incrementally maintain fc // as we change lambda. multiply_invM_JT_prepare(&stage4CallContext->m_mi_fc, m, jb, stage4CallContext->m_bi_links_or_mi_levels, stage4CallContext->m_mi_links); } static int dxQuickStepIsland_Stage4LCP_fcWarmComplete_Callback(void *_stage4CallContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused (void)callThisReleasee; // unused dxQuickStepperStage4CallContext *stage4CallContext = (dxQuickStepperStage4CallContext *)_stage4CallContext; dxQuickStepIsland_Stage4LCP_MTfcComputation_warmComplete(stage4CallContext); return 1; } static void dxQuickStepIsland_Stage4LCP_MTfcComputation_warmComplete(dxQuickStepperStage4CallContext *stage4CallContext) { const dxStepperProcessingCallContext *callContext = stage4CallContext->m_stepperCallContext; const dxQuickStepperLocalContext *localContext = stage4CallContext->m_localContext; dReal *fc = stage4CallContext->m_cforce; unsigned int nb = callContext->m_islandBodiesCount; dReal *iMJ = stage4CallContext->m_iMJ; const dxJBodiesItem *jb = localContext->m_jb; dReal *lambda = stage4CallContext->m_lambda; // Complete computation of fc=(inv(M)*J')*lambda. we will incrementally maintain fc // as we change lambda. multiply_invM_JT_complete(&stage4CallContext->m_mi_fc, fc, nb, iMJ, jb, lambda, stage4CallContext->m_bi_links_or_mi_levels, stage4CallContext->m_mi_links); } #else // #ifndef WARM_STARTING static void dxQuickStepIsland_Stage4LCP_MTfcComputation_cold(dxQuickStepperStage4CallContext *stage4CallContext) { const dxStepperProcessingCallContext *callContext = stage4CallContext->m_stepperCallContext; dReal *fc = stage4CallContext->m_cforce; unsigned int nb = callContext->m_islandBodiesCount; const unsigned int step_size = dxQUICKSTEPISLAND_STAGE4LCP_FC_STEP; unsigned int nb_steps = (nb + (step_size - 1)) / step_size; unsigned bi_step; while ((bi_step = ThrsafeIncrementIntUpToLimit(&stage4CallContext->m_mi_fc, nb_steps)) != nb_steps) { unsigned int bi = bi_step * step_size; unsigned int bicnt = dMIN(step_size, nb - bi); dSetZero(fc + (sizeint)bi * CFE__MAX, (sizeint)bicnt * CFE__MAX); } } #endif // #ifndef WARM_STARTING static void dxQuickStepIsland_Stage4LCP_STfcComputation(dxQuickStepperStage4CallContext *stage4CallContext) { #ifdef WARM_STARTING const dxStepperProcessingCallContext *callContext = stage4CallContext->m_stepperCallContext; const dxQuickStepperLocalContext *localContext = stage4CallContext->m_localContext; dReal *fc = stage4CallContext->m_cforce; unsigned int m = localContext->m_m; unsigned int nb = callContext->m_islandBodiesCount; dReal *iMJ = stage4CallContext->m_iMJ; const dxJBodiesItem *jb = localContext->m_jb; dReal *lambda = stage4CallContext->m_lambda; // compute fc=(inv(M)*J')*lambda. we will incrementally maintain fc // as we change lambda. _multiply_invM_JT(fc, m, nb, iMJ, jb, lambda); #else dReal *fc = stage4CallContext->m_cforce; const dxStepperProcessingCallContext *callContext = stage4CallContext->m_stepperCallContext; unsigned int nb = callContext->m_islandBodiesCount; dSetZero(fc, (sizeint)nb * CFE__MAX); #endif } static int dxQuickStepIsland_Stage4LCP_Ad_Callback(void *_stage4CallContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused (void)callThisReleasee; // unused dxQuickStepperStage4CallContext *stage4CallContext = (dxQuickStepperStage4CallContext *)_stage4CallContext; dxQuickStepIsland_Stage4LCP_AdComputation(stage4CallContext); return 1; } static void dxQuickStepIsland_Stage4LCP_AdComputation(dxQuickStepperStage4CallContext *stage4CallContext) { const dxStepperProcessingCallContext *callContext = stage4CallContext->m_stepperCallContext; const dxQuickStepperLocalContext *localContext = stage4CallContext->m_localContext; const dxJBodiesItem *jb = localContext->m_jb; dReal *J = localContext->m_J; unsigned int m = localContext->m_m; dxWorld *world = callContext->m_world; dxQuickStepParameters *qs = &world->qs; const dReal sor_w = qs->w; // SOR over-relaxation parameter dReal *iMJ = stage4CallContext->m_iMJ; const unsigned int step_size = dxQUICKSTEPISLAND_STAGE4LCP_AD_STEP; unsigned int m_steps = (m + (step_size - 1)) / step_size; unsigned mi_step; while ((mi_step = ThrsafeIncrementIntUpToLimit(&stage4CallContext->m_mi_Ad, m_steps)) != m_steps) { unsigned int mi = mi_step * step_size; const unsigned int miend = mi + dMIN(step_size, m - mi); const dReal *iMJ_ptr = iMJ + (sizeint)mi * IMJ__MAX; dReal *J_ptr = J + (sizeint)mi * JME__MAX; while (true) { dReal sum = REAL(0.0); { for (unsigned int j = JVE__MIN; j != JVE__MAX; ++j) sum += iMJ_ptr[IMJ__1_MIN + j] * J_ptr[JME__J1_MIN + j]; dSASSERT(JME__J1_COUNT == (int)JVE__MAX); } int b2 = jb[mi].second; if (b2 != -1) { for (unsigned int k = JVE__MIN; k != JVE__MAX; ++k) sum += iMJ_ptr[IMJ__2_MIN + k] * J_ptr[JME__J2_MIN + k]; dSASSERT(JME__J2_COUNT == (int)JVE__MAX); } dReal cfm_i = J_ptr[JME_CFM]; dReal Ad_i = sor_w / (sum + cfm_i); // NOTE: This may seem unnecessary but it's indeed an optimization // to move multiplication by Ad[i] and cfm[i] out of iteration loop. // scale cfm, J and b by Ad J_ptr[JME_CFM] = cfm_i * Ad_i; J_ptr[JME_RHS] *= Ad_i; { for (unsigned int j = JVE__MIN; j != JVE__MAX; ++j) J_ptr[JME__J1_MIN + j] *= Ad_i; dSASSERT(JME__J1_COUNT == (int)JVE__MAX); } if (b2 != -1) { for (unsigned int k = JVE__MIN; k != JVE__MAX; ++k) J_ptr[JME__J2_MIN + k] *= Ad_i; dSASSERT(JME__J2_COUNT == (int)JVE__MAX); } if (++mi == miend) { break; } iMJ_ptr += IMJ__MAX; J_ptr += JME__MAX; } } } static int dxQuickStepIsland_Stage4LCP_ReorderPrep_Callback(void *_stage4CallContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused (void)callThisReleasee; // unused dxQuickStepperStage4CallContext *stage4CallContext = (dxQuickStepperStage4CallContext *)_stage4CallContext; dxQuickStepIsland_Stage4LCP_ReorderPrep(stage4CallContext); return 1; } static void dxQuickStepIsland_Stage4LCP_ReorderPrep(dxQuickStepperStage4CallContext *stage4CallContext) { const dxQuickStepperLocalContext *localContext = stage4CallContext->m_localContext; unsigned int m = localContext->m_m; unsigned int valid_findices = localContext->m_valid_findices; IndexError *order = stage4CallContext->m_order; { // make sure constraints with findex < 0 come first. IndexError *orderhead = order, *ordertail = order + (m - valid_findices); const int *findex = localContext->m_findex; // Fill the array from both ends for (unsigned int i = 0; i != m; ++i) { if (findex[i] == -1) { orderhead->index = i; // Place them at the front ++orderhead; } else { ordertail->index = i; // Place them at the end ++ordertail; } } dIASSERT(orderhead == order + (m - valid_findices)); dIASSERT(ordertail == order + m); } } static int dxQuickStepIsland_Stage4LCP_IterationStart_Callback(void *_stage4CallContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused (void)callThisReleasee; // unused dxQuickStepperStage4CallContext *stage4CallContext = (dxQuickStepperStage4CallContext *)_stage4CallContext; const dxStepperProcessingCallContext *callContext = stage4CallContext->m_stepperCallContext; dxWorld *world = callContext->m_world; dxQuickStepParameters *qs = &world->qs; const unsigned int num_iterations = qs->num_iterations; unsigned iteration = stage4CallContext->m_LCP_iteration; if (iteration < num_iterations) { dCallReleaseeID nextReleasee; dCallReleaseeID stage4LCP_IterationSyncReleasee = stage4CallContext->m_LCP_IterationSyncReleasee; unsigned int stage4LCP_Iteration_allowedThreads = stage4CallContext->m_LCP_IterationAllowedThreads; bool reorderRequired = false; if (IsSORConstraintsReorderRequiredForIteration(iteration)) { reorderRequired = true; } unsigned syncCallDependencies = reorderRequired ? 1 : stage4LCP_Iteration_allowedThreads; // Increment iterations counter in advance as anyway it needs to be incremented // before independent tasks (the reordering or the iteration) are posted // (otherwise next iteration may complete before the increment // and the same iteration index may be used again). stage4CallContext->m_LCP_iteration = iteration + 1; if (iteration + 1 != num_iterations) { dCallReleaseeID stage4LCP_IterationStartReleasee; world->PostThreadedCallForUnawareReleasee(NULL, &stage4LCP_IterationStartReleasee, syncCallDependencies, stage4LCP_IterationSyncReleasee, NULL, &dxQuickStepIsland_Stage4LCP_IterationStart_Callback, stage4CallContext, 0, "QuickStepIsland Stage4LCP_Iteration Start"); nextReleasee = stage4LCP_IterationStartReleasee; } else { world->AlterThreadedCallDependenciesCount(stage4LCP_IterationSyncReleasee, syncCallDependencies); nextReleasee = stage4LCP_IterationSyncReleasee; } if (reorderRequired) { const unsigned int reorderThreads = 2; dIASSERT(callContext->m_stepperAllowedThreads >= 2); // Otherwise the single-threaded execution path would be taken stage4CallContext->ResetSOR_ConstraintsReorderVariables(reorderThreads); dCallReleaseeID stage4LCP_ConstraintsReorderingSyncReleasee; world->PostThreadedCall(NULL, &stage4LCP_ConstraintsReorderingSyncReleasee, reorderThreads, nextReleasee, NULL, &dxQuickStepIsland_Stage4LCP_ConstraintsReorderingSync_Callback, stage4CallContext, 0, "QuickStepIsland Stage4LCP_ConstraintsReordering Sync"); if (reorderThreads > 1) { world->PostThreadedCallsGroup(NULL, reorderThreads - 1, stage4LCP_ConstraintsReorderingSyncReleasee, &dxQuickStepIsland_Stage4LCP_ConstraintsReordering_Callback, stage4CallContext, "QuickStepIsland Stage4LCP_ConstraintsReordering"); } dxQuickStepIsland_Stage4LCP_ConstraintsReordering(stage4CallContext); world->AlterThreadedCallDependenciesCount(stage4LCP_ConstraintsReorderingSyncReleasee, -1); } else { dIASSERT(iteration != 0); { dxQuickStepIsland_Stage4LCP_DependencyMapFromSavedLevelsReconstruction(stage4CallContext); } stage4CallContext->RecordLCP_IterationStart(stage4LCP_Iteration_allowedThreads, nextReleasee); unsigned knownToBeCompletedLevel = dxHEAD_INDEX; if (stage4LCP_Iteration_allowedThreads > 1) { world->PostThreadedCallsIndexOverridenGroup(NULL, stage4LCP_Iteration_allowedThreads - 1, nextReleasee, &dxQuickStepIsland_Stage4LCP_Iteration_Callback, stage4CallContext, knownToBeCompletedLevel, "QuickStepIsland Stage4LCP_Iteration"); } dxQuickStepIsland_Stage4LCP_MTIteration(stage4CallContext, knownToBeCompletedLevel); world->AlterThreadedCallDependenciesCount(nextReleasee, -1); } } return 1; } static int dxQuickStepIsland_Stage4LCP_ConstraintsReordering_Callback(void *_stage4CallContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused (void)callThisReleasee; // unused dxQuickStepperStage4CallContext *stage4CallContext = (dxQuickStepperStage4CallContext *)_stage4CallContext; dxQuickStepIsland_Stage4LCP_ConstraintsReordering(stage4CallContext); return 1; } static void dxQuickStepIsland_Stage4LCP_ConstraintsReordering(dxQuickStepperStage4CallContext *stage4CallContext) { unsigned int iteration = stage4CallContext->m_LCP_iteration - 1; // Iteration is pre-incremented before scheduled tasks are released for execution if (dxQuickStepIsland_Stage4LCP_ConstraintsShuffling(stage4CallContext, iteration)) { dxQuickStepIsland_Stage4LCP_LinksArraysZeroing(stage4CallContext); if (ThrsafeExchangeAdd(&stage4CallContext->m_SOR_reorderThreadsRemaining, (atomicord32)(-1)) == 1) { // If last thread has exited the reordering routine... // Rebuild the object dependency map dxQuickStepIsland_Stage4LCP_DependencyMapForNewOrderRebuilding(stage4CallContext); } } else { // NOTE: So far, this branch is only called in CONSTRAINTS_REORDERING_METHOD == REORDERING_METHOD__BY_ERROR case if (ThrsafeExchangeAdd(&stage4CallContext->m_SOR_reorderThreadsRemaining, (atomicord32)(-1)) == 1) { // If last thread has exited the reordering routine... dIASSERT(iteration != 0); dxQuickStepIsland_Stage4LCP_DependencyMapFromSavedLevelsReconstruction(stage4CallContext); } } } static bool dxQuickStepIsland_Stage4LCP_ConstraintsShuffling(dxQuickStepperStage4CallContext *stage4CallContext, unsigned int iteration) { bool result = false; #if CONSTRAINTS_REORDERING_METHOD == REORDERING_METHOD__BY_ERROR struct ConstraintsReorderingHelper { void operator ()(dxQuickStepperStage4CallContext *stage4CallContext, unsigned int startIndex, unsigned int endIndex) { const dReal *lambda = stage4CallContext->m_lambda; dReal *last_lambda = stage4CallContext->m_last_lambda; IndexError *order = stage4CallContext->m_order; for (unsigned int index = startIndex; index != endIndex; ++index) { unsigned int i = order[index].index; dReal lambda_i = lambda[i]; if (lambda_i != REAL(0.0)) { //@@@ relative error: order[i].error = dFabs(lambda[i]-last_lambda[i])/max; order[index].error = dFabs(lambda_i - last_lambda[i]); } else if (last_lambda[i] != REAL(0.0)) { //@@@ relative error: order[i].error = dFabs(lambda[i]-last_lambda[i])/max; order[index].error = dFabs(/*lambda_i - */last_lambda[i]); // lambda_i == 0 } else { order[index].error = dInfinity; } // Finally copy the lambda for the next iteration last_lambda[i] = lambda_i; } qsort (order + startIndex, endIndex - startIndex, sizeof(IndexError), &compare_index_error); } }; if (iteration > 1) { // Only reorder starting from iteration #2 // sort the constraints so that the ones converging slowest // get solved last. use the absolute (not relative) error. /* * Full reorder needs to be done. * Even though this contradicts the initial idea of moving dependent constraints * to the order end the algorithm does not work the other way well. * It looks like the iterative method needs a shake after it already found * some initial approximations and those incurred errors help it to converge even better. */ if (ThrsafeExchange(&stage4CallContext->m_SOR_reorderHeadTaken, 1) == 0) { // Process the head const dxQuickStepperLocalContext *localContext = stage4CallContext->m_localContext; ConstraintsReorderingHelper()(stage4CallContext, 0, localContext->m_m); } result = true; } else if (iteration == 1) { if (ThrsafeExchange(&stage4CallContext->m_SOR_reorderHeadTaken, 1) == 0) { // Process the first half const dxQuickStepperLocalContext *localContext = stage4CallContext->m_localContext; unsigned int startIndex = 0; unsigned int indicesCount = localContext->m_m / 2; // Just copy the lambdas for the next iteration memcpy(stage4CallContext->m_last_lambda + startIndex, stage4CallContext->m_lambda + startIndex, indicesCount * sizeof(dReal)); } if (ThrsafeExchange(&stage4CallContext->m_SOR_reorderTailTaken, 1) == 0) { // Process the second half const dxQuickStepperLocalContext *localContext = stage4CallContext->m_localContext; unsigned int startIndex = localContext->m_m / 2; unsigned int indicesCount = localContext->m_m - startIndex; // Just copy the lambdas for the next iteration memcpy(stage4CallContext->m_last_lambda + startIndex, stage4CallContext->m_lambda + startIndex, indicesCount * sizeof(dReal)); } // result = false; -- already 'false' } else /*if (iteration < 1) */{ result = true; // return true on 0th iteration to build dependency map for the initial order } #elif CONSTRAINTS_REORDERING_METHOD == REORDERING_METHOD__RANDOMLY if (iteration != 0) { dIASSERT(!dIN_RANGE(iteration, 0, RANDOM_CONSTRAINTS_REORDERING_FREQUENCY)); dIASSERT(iteration % RANDOM_CONSTRAINTS_REORDERING_FREQUENCY == RRS_REORDERING); { struct ConstraintsReorderingHelper { void operator ()(dxQuickStepperStage4CallContext *stage4CallContext, unsigned int startIndex, unsigned int indicesCount) { IndexError *order = stage4CallContext->m_order + startIndex; for (unsigned int index = 1; index < indicesCount; ++index) { int swapIndex = dRandInt(index + 1); IndexError tmp = order[index]; order[index] = order[swapIndex]; order[swapIndex] = tmp; } } }; /* * Full reorder needs to be done. * Even though this contradicts the initial idea of moving dependent constraints * to the order end the algorithm does not work the other way well. * It looks like the iterative method needs a shake after it already found * some initial approximations and those incurred errors help it to converge even better. */ if (ThrsafeExchange(&stage4CallContext->m_SOR_reorderHeadTaken, 1) == 0) { // Process the head const dxQuickStepperLocalContext *localContext = stage4CallContext->m_localContext; ConstraintsReorderingHelper()(stage4CallContext, 0, localContext->m_m); } } dIASSERT((RRS__MAX, true)); // A reference to RRS__MAX to be located by Find in Files } else { // Just return true and skip the randomization for the very first iteration } result = true; #else // #if CONSTRAINTS_REORDERING_METHOD != REORDERING_METHOD__BY_ERROR && CONSTRAINTS_REORDERING_METHOD != REORDERING_METHOD__RANDOMLY dIASSERT(iteration == 0); // The reordering request is only returned for the first iteration result = true; #endif return result; } static void dxQuickStepIsland_Stage4LCP_LinksArraysZeroing(dxQuickStepperStage4CallContext *stage4CallContext) { const dxStepperProcessingCallContext *callContext = stage4CallContext->m_stepperCallContext; const dxQuickStepperLocalContext *localContext = stage4CallContext->m_localContext; if (ThrsafeExchange(&stage4CallContext->m_SOR_bi_zeroHeadTaken, 1) == 0) { atomicord32 *bi_links = stage4CallContext->m_bi_links_or_mi_levels;/*=[nb]*/ unsigned int nb = callContext->m_islandBodiesCount; memset(bi_links, 0, sizeof(bi_links[0]) * (nb / 2)); } if (ThrsafeExchange(&stage4CallContext->m_SOR_bi_zeroTailTaken, 1) == 0) { atomicord32 *bi_links = stage4CallContext->m_bi_links_or_mi_levels;/*=[nb]*/ unsigned int nb = callContext->m_islandBodiesCount; memset(bi_links + nb / 2, 0, sizeof(bi_links[0]) * (nb - nb / 2)); } if (ThrsafeExchange(&stage4CallContext->m_SOR_mi_zeroHeadTaken, 1) == 0) { atomicord32 *mi_links = stage4CallContext->m_mi_links;/*=[2*(m + 1)]*/ unsigned int m = localContext->m_m; memset(mi_links, 0, sizeof(mi_links[0]) * (m + 1)); } if (ThrsafeExchange(&stage4CallContext->m_SOR_mi_zeroTailTaken, 1) == 0) { atomicord32 *mi_links = stage4CallContext->m_mi_links;/*=[2*(m + 1)]*/ unsigned int m = localContext->m_m; memset(mi_links + (m + 1), 0, sizeof(mi_links[0]) * (m + 1)); } } static void dxQuickStepIsland_Stage4LCP_DependencyMapForNewOrderRebuilding(dxQuickStepperStage4CallContext *stage4CallContext) { const dxQuickStepperLocalContext *localContext = stage4CallContext->m_localContext; atomicord32 *bi_links = stage4CallContext->m_bi_links_or_mi_levels;/*=[nb]*/ atomicord32 *mi_links = stage4CallContext->m_mi_links;/*=[2*(m + 1)]*/ IndexError *order = stage4CallContext->m_order; const dxJBodiesItem *jb = localContext->m_jb; unsigned int m = localContext->m_m; for (unsigned int i = 0; i != m; ++i) { unsigned int index = order[i].index; int b1 = jb[index].first; int b2 = jb[index].second; unsigned int encioded_i = dxENCODE_INDEX(i); unsigned int encoded_depi = bi_links[(unsigned int)b1]; bi_links[(unsigned int)b1] = encioded_i; if (b2 != -1 && b2 != b1) { if (encoded_depi < (unsigned int)bi_links[(unsigned int)b2]) { encoded_depi = bi_links[(unsigned int)b2]; } bi_links[(unsigned int)b2] = encioded_i; } // OD: There is also a dependency on findex[index], // however the findex can only refer to the rows of the same joint // and hence that index is going to have the same bodies. Since the // indices are sorted in a way that the meaningful findex values // always come last, the dependency of findex[index] is going to // be implicitly satisfied via matching bodies at smaller "i"s. // Check that the dependency targets an earlier "i" dIASSERT(encoded_depi < encioded_i); unsigned encoded_downi = mi_links[(sizeint)encoded_depi * 2 + 1]; mi_links[(sizeint)encoded_depi * 2 + 1] = encioded_i; // Link i as down-dependency for depi mi_links[(sizeint)encioded_i * 2 + 0] = encoded_downi; // Link previous down-chain as the level-dependency with i } } static void dxQuickStepIsland_Stage4LCP_DependencyMapFromSavedLevelsReconstruction(dxQuickStepperStage4CallContext *stage4CallContext) { const dxQuickStepperLocalContext *localContext = stage4CallContext->m_localContext; atomicord32 *mi_levels = stage4CallContext->m_bi_links_or_mi_levels;/*=[m]*/ atomicord32 *mi_links = stage4CallContext->m_mi_links;/*=[2*(m + 1)]*/ // NOTE! // OD: The mi_links array is not zero-filled before the reconstruction. // Iteration ends with all the down links zeroed. And since down links // are moved to the next level links when parent-child relations are established, // the horizontal levels are properly terminated. // The leaf nodes had their links zero-initialized initially // and those zeros remain intact during the solving. This way the down links // are properly terminated as well. // This is very obscure and error prone and would need an assertion check at least // but the simplest assertion approach I can imagine would be // zero filling and building another tree with the memory buffer comparison afterwards. // That would be stupid, obviously. // // NOTE! // OD: This routine can be threaded. However having two threads messing // in one integer array with random access and kicking each other memory lines // out of cache would probably work worse than letting a single thread do the whole job. unsigned int m = localContext->m_m; for (unsigned int i = 0; i != m; ++i) { unsigned int currentLevelRoot = mi_levels[i]; unsigned int currentLevelFirstLink = mi_links[2 * (sizeint)currentLevelRoot + 1]; unsigned int encoded_i = dxENCODE_INDEX(i); mi_links[2 * (sizeint)currentLevelRoot + 1] = encoded_i; mi_links[2 * (sizeint)encoded_i + 0] = currentLevelFirstLink; } // Additionally reset available level root's list head mi_links[2 * dxHEAD_INDEX + 0] = dxHEAD_INDEX; } static int dxQuickStepIsland_Stage4LCP_ConstraintsReorderingSync_Callback(void *_stage4CallContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused (void)callThisReleasee; // unused dxQuickStepperStage4CallContext *stage4CallContext = (dxQuickStepperStage4CallContext *)_stage4CallContext; const dxStepperProcessingCallContext *callContext = stage4CallContext->m_stepperCallContext; unsigned int stage4LCP_Iteration_allowedThreads = stage4CallContext->m_LCP_IterationAllowedThreads; stage4CallContext->RecordLCP_IterationStart(stage4LCP_Iteration_allowedThreads, callThisReleasee); unsigned knownToBeCompletedLevel = dxHEAD_INDEX; if (stage4LCP_Iteration_allowedThreads > 1) { dxWorld *world = callContext->m_world; world->AlterThreadedCallDependenciesCount(callThisReleasee, stage4LCP_Iteration_allowedThreads - 1); world->PostThreadedCallsIndexOverridenGroup(NULL, stage4LCP_Iteration_allowedThreads - 1, callThisReleasee, &dxQuickStepIsland_Stage4LCP_Iteration_Callback, stage4CallContext, knownToBeCompletedLevel, "QuickStepIsland Stage4LCP_Iteration"); } dxQuickStepIsland_Stage4LCP_MTIteration(stage4CallContext, knownToBeCompletedLevel); return 1; } static int dxQuickStepIsland_Stage4LCP_Iteration_Callback(void *_stage4CallContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused (void)callThisReleasee; // unused dxQuickStepperStage4CallContext *stage4CallContext = (dxQuickStepperStage4CallContext *)_stage4CallContext; unsigned int initiallyKnownToBeCompletedLevel = (unsigned int)callInstanceIndex; dIASSERT(initiallyKnownToBeCompletedLevel == callInstanceIndex); // A truncation check... dxQuickStepIsland_Stage4LCP_MTIteration(stage4CallContext, initiallyKnownToBeCompletedLevel); return 1; } /* * +0 +0 * Root───┬─────────────────┬──... * +1│ +1│ * ┌┴â”+0 ┌─â”+0 . * │A├─────┤B├─... * └┬┘ └┬┘ * +1│ +1│ * ┌┴â”+0 . * │C├─... * └┬┘ * +1│ * . * * Lower tree levels depend on their parents. Same level nodes are independent with respect to each other. * * 1. B is linked in place of A * 2. A is processed * 3. C is inserted at the Root level * * The tree starts with a single child subtree at the root level ("down" link of slot #0 is used for that). * Then, additional "C" nodes are added to the root level by building horizontal link via slots of * their former parent "A"s that had become free. * The "level" link of slot #0 is used to find the root level head. * * Since the tree is altered during iteration, mi_levels record each node parents so that the tree could be reconstructed. */ static void dxQuickStepIsland_Stage4LCP_MTIteration(dxQuickStepperStage4CallContext *stage4CallContext, unsigned int initiallyKnownToBeCompletedLevel) { atomicord32 *mi_levels = stage4CallContext->m_bi_links_or_mi_levels; atomicord32 *mi_links = stage4CallContext->m_mi_links; unsigned int knownToBeCompletedLevel = initiallyKnownToBeCompletedLevel; while (true) { unsigned int initialLevelRoot = mi_links[2 * dxHEAD_INDEX + 0]; if (initialLevelRoot != dxHEAD_INDEX && initialLevelRoot == knownToBeCompletedLevel) { // No work is (currently) available break; } for (unsigned int currentLevelRoot = initialLevelRoot; ; currentLevelRoot = mi_links[2 * (sizeint)currentLevelRoot + 0]) { while (true) { const unsigned invalid_link = dxENCODE_INDEX(-1); unsigned currentLevelFirstLink = mi_links[2 * (sizeint)currentLevelRoot + 1]; if (currentLevelFirstLink == invalid_link) { break; } // Try to extract first record from linked list unsigned currentLevelNextLink = mi_links[2 * (sizeint)currentLevelFirstLink + 0]; if (ThrsafeCompareExchange(&mi_links[2 * (sizeint)currentLevelRoot + 1], currentLevelFirstLink, currentLevelNextLink)) { // if succeeded, execute selected iteration step... dxQuickStepIsland_Stage4LCP_IterationStep(stage4CallContext, dxDECODE_INDEX(currentLevelFirstLink)); // Check if there are any dependencies unsigned level0DownLink = mi_links[2 * (sizeint)currentLevelFirstLink + 1]; if (level0DownLink != invalid_link) { // ...and if yes, insert the record into the list of available level roots unsigned int levelRootsFirst; do { levelRootsFirst = mi_links[2 * dxHEAD_INDEX + 0]; mi_links[2 * (sizeint)currentLevelFirstLink + 0] = levelRootsFirst; } while (!ThrsafeCompareExchange(&mi_links[2 * dxHEAD_INDEX + 0], levelRootsFirst, currentLevelFirstLink)); // If another level was added and some threads have already exited... unsigned int threadsTotal = stage4CallContext->m_LCP_iterationThreadsTotal; unsigned int threadsRemaining = ThrsafeIncrementIntUpToLimit(&stage4CallContext->m_LCP_iterationThreadsRemaining, threadsTotal); if (threadsRemaining != threadsTotal) { // ...go on an schedule one more... const dxStepperProcessingCallContext *callContext = stage4CallContext->m_stepperCallContext; dxWorld *world = callContext->m_world; // ...passing knownToBeCompletedLevel as the initial one for the spawned call world->PostThreadedCallForUnawareReleasee(NULL, NULL, 0, stage4CallContext->m_LCP_iterationNextReleasee, NULL, &dxQuickStepIsland_Stage4LCP_Iteration_Callback, stage4CallContext, knownToBeCompletedLevel, "QuickStepIsland Stage4LCP_Iteration"); // NOTE: it's hard to predict whether it is reasonable to re-post a call // each time a new level is added (provided some calls have already exited, of course). // The efficiency very much depends on dependencies patterns between levels // (i.e. it depends on the amount of available work added with each level). // The strategy of re-posting exited calls as frequently as possible // leads to potential wasting execution cycles in some cores for the aid // of keeping other cores busy as much as possible and not letting all the // work be executed by just a partial cores subset. With emergency of large // available work amounts (the work that is not dependent on anything and // ready to be executed immediately) this strategy is going to transit into // full cores set being busy executing useful work. If amounts of work // emerging from added levels are small, the strategy should lead to // approximately the same efficiency as if the work was done by only a cores subset // with the remaining cores wasting (some) cycles for re-scheduling calls // to those busy cores rather than being idle or handling other islands. } } // Finally record the root index of current record's level mi_levels[dxDECODE_INDEX(currentLevelFirstLink)] = currentLevelRoot; } } if (currentLevelRoot == knownToBeCompletedLevel) { break; } dIASSERT(currentLevelRoot != dxHEAD_INDEX); // Zero level is expected to be the deepest one in the list and execution must not loop past it. } // Save the level root we started from as known to be completed knownToBeCompletedLevel = initialLevelRoot; } // Decrement running threads count on exit ThrsafeAdd(&stage4CallContext->m_LCP_iterationThreadsRemaining, (atomicord32)(-1)); } static void dxQuickStepIsland_Stage4LCP_STIteration(dxQuickStepperStage4CallContext *stage4CallContext) { const dxQuickStepperLocalContext *localContext = stage4CallContext->m_localContext; unsigned int m = localContext->m_m; for (unsigned int i = 0; i != m; ++i) { dxQuickStepIsland_Stage4LCP_IterationStep(stage4CallContext, i); } } //*************************************************************************** // SOR-LCP method // nb is the number of bodies in the body array. // J is an m*16 matrix of constraint rows with rhs, cfm, lo and hi in padding // jb is an array of first and second body numbers for each constraint row // invI is the global frame inverse inertia for each body (stacked 3x3 matrices) // // this returns lambda and fc (the constraint force). // note: fc is returned as inv(M)*J'*lambda, the constraint force is actually J'*lambda // // b, lo and hi are modified on exit static void dxQuickStepIsland_Stage4LCP_IterationStep(dxQuickStepperStage4CallContext *stage4CallContext, unsigned int i) { const dxQuickStepperLocalContext *localContext = stage4CallContext->m_localContext; IndexError *order = stage4CallContext->m_order; unsigned int index = order[i].index; dReal *fc_ptr1; dReal *fc_ptr2 = NULL; dReal delta; dReal *lambda = stage4CallContext->m_lambda; dReal old_lambda = lambda[index]; dReal *J = localContext->m_J; const dReal *J_ptr = J + (sizeint)index * JME__MAX; { delta = J_ptr[JME_RHS] - old_lambda * J_ptr[JME_CFM]; dReal *fc = stage4CallContext->m_cforce; const dxJBodiesItem *jb = localContext->m_jb; int b2 = jb[index].second; int b1 = jb[index].first; // @@@ potential optimization: SIMD-ize this and the b2 >= 0 case fc_ptr1 = fc + (sizeint)(unsigned)b1 * CFE__MAX; delta -= fc_ptr1[CFE_LX] * J_ptr[JME_J1LX] + fc_ptr1[CFE_LY] * J_ptr[JME_J1LY] + fc_ptr1[CFE_LZ] * J_ptr[JME_J1LZ] + fc_ptr1[CFE_AX] * J_ptr[JME_J1AX] + fc_ptr1[CFE_AY] * J_ptr[JME_J1AY] + fc_ptr1[CFE_AZ] * J_ptr[JME_J1AZ]; // @@@ potential optimization: handle 1-body constraints in a separate // loop to avoid the cost of test & jump? if (b2 != -1) { fc_ptr2 = fc + (sizeint)(unsigned)b2 * CFE__MAX; delta -= fc_ptr2[CFE_LX] * J_ptr[JME_J2LX] + fc_ptr2[CFE_LY] * J_ptr[JME_J2LY] + fc_ptr2[CFE_LZ] * J_ptr[JME_J2LZ] + fc_ptr2[CFE_AX] * J_ptr[JME_J2AX] + fc_ptr2[CFE_AY] * J_ptr[JME_J2AY] + fc_ptr2[CFE_AZ] * J_ptr[JME_J2AZ]; } } { dReal hi_act, lo_act; // set the limits for this constraint. // this is the place where the QuickStep method differs from the // direct LCP solving method, since that method only performs this // limit adjustment once per time step, whereas this method performs // once per iteration per constraint row. // the constraints are ordered so that all lambda[] values needed have // already been computed. const int *findex = localContext->m_findex; if (findex[index] != -1) { hi_act = dFabs (J_ptr[JME_HI] * lambda[(unsigned)findex[index]]); lo_act = -hi_act; } else { hi_act = J_ptr[JME_HI]; lo_act = J_ptr[JME_LO]; } // compute lambda and clamp it to [lo,hi]. // @@@ potential optimization: does SSE have clamping instructions // to save test+jump penalties here? dReal new_lambda = old_lambda + delta; if (new_lambda < lo_act) { delta = lo_act - old_lambda; lambda[index] = lo_act; } else if (new_lambda > hi_act) { delta = hi_act - old_lambda; lambda[index] = hi_act; } else { lambda[index] = new_lambda; } } //@@@ a trick that may or may not help //dReal ramp = (1-((dReal)(iteration+1)/(dReal)num_iterations)); //delta *= ramp; { dReal *iMJ = stage4CallContext->m_iMJ; const dReal *iMJ_ptr = iMJ + (sizeint)index * IMJ__MAX; // update fc. // @@@ potential optimization: SIMD for this and the b2 >= 0 case fc_ptr1[CFE_LX] += delta * iMJ_ptr[IMJ_1LX]; fc_ptr1[CFE_LY] += delta * iMJ_ptr[IMJ_1LY]; fc_ptr1[CFE_LZ] += delta * iMJ_ptr[IMJ_1LZ]; fc_ptr1[CFE_AX] += delta * iMJ_ptr[IMJ_1AX]; fc_ptr1[CFE_AY] += delta * iMJ_ptr[IMJ_1AY]; fc_ptr1[CFE_AZ] += delta * iMJ_ptr[IMJ_1AZ]; // @@@ potential optimization: handle 1-body constraints in a separate // loop to avoid the cost of test & jump? if (fc_ptr2) { fc_ptr2[CFE_LX] += delta * iMJ_ptr[IMJ_2LX]; fc_ptr2[CFE_LY] += delta * iMJ_ptr[IMJ_2LY]; fc_ptr2[CFE_LZ] += delta * iMJ_ptr[IMJ_2LZ]; fc_ptr2[CFE_AX] += delta * iMJ_ptr[IMJ_2AX]; fc_ptr2[CFE_AY] += delta * iMJ_ptr[IMJ_2AY]; fc_ptr2[CFE_AZ] += delta * iMJ_ptr[IMJ_2AZ]; } } } static inline bool IsStage4bJointInfosIterationRequired(const dxQuickStepperLocalContext *localContext) { return #ifdef WARM_STARTING true || #endif localContext->m_mfb > 0; } static int dxQuickStepIsland_Stage4LCP_IterationSync_Callback(void *_stage4CallContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused (void)callThisReleasee; // unused dxQuickStepperStage4CallContext *stage4CallContext = (dxQuickStepperStage4CallContext *)_stage4CallContext; const dxStepperProcessingCallContext *callContext = stage4CallContext->m_stepperCallContext; const dxQuickStepperLocalContext *localContext = stage4CallContext->m_localContext; unsigned int stage4b_allowedThreads = 1; if (IsStage4bJointInfosIterationRequired(localContext)) { unsigned int allowedThreads = callContext->m_stepperAllowedThreads; dIASSERT(allowedThreads >= stage4b_allowedThreads); stage4b_allowedThreads += CalculateOptimalThreadsCount(localContext->m_nj, allowedThreads - stage4b_allowedThreads); } if (stage4b_allowedThreads > 1) { dxWorld *world = callContext->m_world; world->AlterThreadedCallDependenciesCount(callThisReleasee, stage4b_allowedThreads - 1); world->PostThreadedCallsGroup(NULL, stage4b_allowedThreads - 1, callThisReleasee, &dxQuickStepIsland_Stage4b_Callback, stage4CallContext, "QuickStepIsland Stage4b"); } dxQuickStepIsland_Stage4b(stage4CallContext); return 1; } static int dxQuickStepIsland_Stage4b_Callback(void *_stage4CallContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused (void)callThisReleasee; // unused dxQuickStepperStage4CallContext *stage4CallContext = (dxQuickStepperStage4CallContext *)_stage4CallContext; dxQuickStepIsland_Stage4b(stage4CallContext); return 1; } static void dxQuickStepIsland_Stage4b(dxQuickStepperStage4CallContext *stage4CallContext) { const dxStepperProcessingCallContext *callContext = stage4CallContext->m_stepperCallContext; const dxQuickStepperLocalContext *localContext = stage4CallContext->m_localContext; if (ThrsafeExchange(&stage4CallContext->m_cf_4b, 1) == 0) { dxBody * const *body = callContext->m_islandBodiesStart; unsigned int nb = callContext->m_islandBodiesCount; const dReal *cforce = stage4CallContext->m_cforce; dReal stepsize = callContext->m_stepSize; // add stepsize * cforce to the body velocity const dReal *cforcecurr = cforce; dxBody *const *const bodyend = body + nb; for (dxBody *const *bodycurr = body; bodycurr != bodyend; cforcecurr += CFE__MAX, bodycurr++) { dxBody *b = *bodycurr; for (unsigned int j = dSA__MIN; j != dSA__MAX; j++) { b->lvel[dV3E__AXES_MIN + j] += stepsize * cforcecurr[CFE__L_MIN + j]; b->avel[dV3E__AXES_MIN + j] += stepsize * cforcecurr[CFE__A_MIN + j]; } } } // note that the SOR method overwrites rhs and J at this point, so // they should not be used again. if (IsStage4bJointInfosIterationRequired(localContext)) { dReal data[JVE__MAX]; const dReal *Jcopy = localContext->m_Jcopy; const dReal *lambda = stage4CallContext->m_lambda; const dxMIndexItem *mindex = localContext->m_mindex; dJointWithInfo1 *jointinfos = localContext->m_jointinfos; unsigned int nj = localContext->m_nj; const unsigned int step_size = dxQUICKSTEPISLAND_STAGE4B_STEP; unsigned int nj_steps = (nj + (step_size - 1)) / step_size; unsigned ji_step; while ((ji_step = ThrsafeIncrementIntUpToLimit(&stage4CallContext->m_ji_4b, nj_steps)) != nj_steps) { unsigned int ji = ji_step * step_size; const unsigned int jiend = ji + dMIN(step_size, nj - ji); const dReal *Jcopycurr = Jcopy + (sizeint)mindex[ji].fbIndex * JCE__MAX; while (true) { // straightforward computation of joint constraint forces: // multiply related lambdas with respective J' block for joints // where feedback was requested const unsigned int fb_infom = mindex[ji + 1].fbIndex - mindex[ji].fbIndex; if (fb_infom != 0) { dIASSERT(fb_infom == mindex[ji + 1].mIndex - mindex[ji].mIndex); const dReal *lambdacurr = lambda + mindex[ji].mIndex; dxJoint *joint = jointinfos[ji].joint; #ifdef WARM_STARTING memcpy(joint->lambda, lambdacurr, fb_infom * sizeof(dReal)); #endif dJointFeedback *fb = joint->feedback; if (joint->node[1].body) { Multiply1_12q1 (data, Jcopycurr + JCE__J2_MIN, lambdacurr, fb_infom); dSASSERT(JCE__MAX == 12); fb->f2[dSA_X] = data[JVE_LX]; fb->f2[dSA_Y] = data[JVE_LY]; fb->f2[dSA_Z] = data[JVE_LZ]; fb->t2[dSA_X] = data[JVE_AX]; fb->t2[dSA_Y] = data[JVE_AY]; fb->t2[dSA_Z] = data[JVE_AZ]; } Multiply1_12q1 (data, Jcopycurr + JCE__J1_MIN, lambdacurr, fb_infom); dSASSERT(JCE__MAX == 12); fb->f1[dSA_X] = data[JVE_LX]; fb->f1[dSA_Y] = data[JVE_LY]; fb->f1[dSA_Z] = data[JVE_LZ]; fb->t1[dSA_X] = data[JVE_AX]; fb->t1[dSA_Y] = data[JVE_AY]; fb->t1[dSA_Z] = data[JVE_AZ]; Jcopycurr += fb_infom * JCE__MAX; } else { #ifdef WARM_STARTING const dReal *lambdacurr = lambda + mindex[ji].mIndex; const unsigned int infom = mindex[ji + 1].mIndex - mindex[ji].mIndex; dxJoint *joint = jointinfos[ji].joint; memcpy(joint->lambda, lambdacurr, infom * sizeof(dReal)); #endif } if (++ji == jiend) { break; } } } } } static int dxQuickStepIsland_Stage5_Callback(void *_stage5CallContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused (void)callThisReleasee; // unused dxQuickStepperStage5CallContext *stage5CallContext = (dxQuickStepperStage5CallContext *)_stage5CallContext; dxQuickStepIsland_Stage5(stage5CallContext); return 1; } static void dxQuickStepIsland_Stage5(dxQuickStepperStage5CallContext *stage5CallContext) { const dxStepperProcessingCallContext *callContext = stage5CallContext->m_stepperCallContext; const dxQuickStepperLocalContext *localContext = stage5CallContext->m_localContext; dxWorldProcessMemArena *memarena = callContext->m_stepperArena; memarena->RestoreState(stage5CallContext->m_stage3MemArenaState); stage5CallContext = NULL; // WARNING! stage3CallContext is not valid after this point! dIVERIFY(stage5CallContext == NULL); // To suppress unused variable assignment warnings dxQuickStepperStage6CallContext *stage6CallContext = (dxQuickStepperStage6CallContext *)memarena->AllocateBlock(sizeof(dxQuickStepperStage6CallContext)); stage6CallContext->Initialize(callContext, localContext); const unsigned allowedThreads = callContext->m_stepperAllowedThreads; dIASSERT(allowedThreads >= 1); if (allowedThreads == 1) { IFTIMING (dTimerNow ("compute velocity update")); dxQuickStepIsland_Stage6a(stage6CallContext); dxQuickStepIsland_Stage6_VelocityCheck(stage6CallContext); IFTIMING (dTimerNow ("update position and tidy up")); dxQuickStepIsland_Stage6b(stage6CallContext); IFTIMING (dTimerEnd()); IFTIMING (if (m > 0) dTimerReport (stdout,1)); } else { unsigned int nb = callContext->m_islandBodiesCount; unsigned int stage6a_allowedThreads = CalculateOptimalThreadsCount(nb, allowedThreads); dxWorld *world = callContext->m_world; dCallReleaseeID stage6aSyncReleasee; world->PostThreadedCallForUnawareReleasee(NULL, &stage6aSyncReleasee, stage6a_allowedThreads, callContext->m_finalReleasee, NULL, &dxQuickStepIsland_Stage6aSync_Callback, stage6CallContext, 0, "QuickStepIsland Stage6a Sync"); if (stage6a_allowedThreads > 1) { world->PostThreadedCallsGroup(NULL, stage6a_allowedThreads - 1, stage6aSyncReleasee, &dxQuickStepIsland_Stage6a_Callback, stage6CallContext, "QuickStepIsland Stage6a"); } dxQuickStepIsland_Stage6a(stage6CallContext); world->AlterThreadedCallDependenciesCount(stage6aSyncReleasee, -1); } } static int dxQuickStepIsland_Stage6a_Callback(void *_stage6CallContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused (void)callThisReleasee; // unused dxQuickStepperStage6CallContext *stage6CallContext = (dxQuickStepperStage6CallContext *)_stage6CallContext; dxQuickStepIsland_Stage6a(stage6CallContext); return 1; } static void dxQuickStepIsland_Stage6a(dxQuickStepperStage6CallContext *stage6CallContext) { const dxStepperProcessingCallContext *callContext = stage6CallContext->m_stepperCallContext; const dxQuickStepperLocalContext *localContext = stage6CallContext->m_localContext; dReal stepsize = callContext->m_stepSize; dReal *invI = localContext->m_invI; dxBody * const *body = callContext->m_islandBodiesStart; unsigned int nb = callContext->m_islandBodiesCount; const unsigned int step_size = dxQUICKSTEPISLAND_STAGE6A_STEP; unsigned int nb_steps = (nb + (step_size - 1)) / step_size; unsigned bi_step; while ((bi_step = ThrsafeIncrementIntUpToLimit(&stage6CallContext->m_bi_6a, nb_steps)) != nb_steps) { unsigned int bi = bi_step * step_size; unsigned int bicnt = dMIN(step_size, nb - bi); const dReal *invIrow = invI + (sizeint)bi * IIE__MAX; dxBody *const *bodycurr = body + bi; dxBody *const *bodyend = bodycurr + bicnt; while (true) { // compute the velocity update: // add stepsize * invM * fe to the body velocity dxBody *b = *bodycurr; dReal body_invMass_mul_stepsize = stepsize * b->invMass; for (unsigned int j = dSA__MIN; j != dSA__MAX; ++j) { b->lvel[dV3E__AXES_MIN + j] += body_invMass_mul_stepsize * b->facc[dV3E__AXES_MIN + j]; b->tacc[dV3E__AXES_MIN + j] *= stepsize; } dMultiplyAdd0_331 (b->avel, invIrow + IIE__MATRIX_MIN, b->tacc); if (++bodycurr == bodyend) { break; } invIrow += IIE__MAX; } } } static int dxQuickStepIsland_Stage6aSync_Callback(void *_stage6CallContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused (void)callThisReleasee; // unused dxQuickStepperStage6CallContext *stage6CallContext = (dxQuickStepperStage6CallContext *)_stage6CallContext; dxQuickStepIsland_Stage6_VelocityCheck(stage6CallContext); const dxStepperProcessingCallContext *callContext = stage6CallContext->m_stepperCallContext; const unsigned allowedThreads = callContext->m_stepperAllowedThreads; unsigned int nb = callContext->m_islandBodiesCount; unsigned int stage6b_allowedThreads = CalculateOptimalThreadsCount(nb, allowedThreads); if (stage6b_allowedThreads > 1) { dxWorld *world = callContext->m_world; world->AlterThreadedCallDependenciesCount(callThisReleasee, stage6b_allowedThreads - 1); world->PostThreadedCallsGroup(NULL, stage6b_allowedThreads - 1, callThisReleasee, &dxQuickStepIsland_Stage6b_Callback, stage6CallContext, "QuickStepIsland Stage6b"); } dxQuickStepIsland_Stage6b(stage6CallContext); return 1; } static void dxQuickStepIsland_Stage6_VelocityCheck(dxQuickStepperStage6CallContext *stage6CallContext) { (void)stage6CallContext; // can be unused #ifdef CHECK_VELOCITY_OBEYS_CONSTRAINT const dxQuickStepperLocalContext *localContext = stage6CallContext->m_localContext; unsigned int m = localContext->m_m; if (m > 0) { const dxStepperProcessingCallContext *callContext = stage6CallContext->m_stepperCallContext; dxBody * const *body = callContext->m_islandBodiesStart; dReal *J = localContext->m_J; const dxJBodiesItem *jb = localContext->m_jb; dReal error = 0; const dReal* J_ptr = J; for (unsigned int i = 0; i < m; ++i) { int b1 = jb[i].first; int b2 = jb[i].second; dReal sum = 0; dxBody *bodycurr = body[(unsigned)b1]; for (unsigned int j = dSA__MIN; j != dSA__MAX; ++j) sum += J_ptr[JME__J1L_MIN + j] * bodycurr->lvel[dV3E__AXES_MIN + j] + J_ptr[JME__J1A_MIN + j] * bodycurr->avel[dV3E__AXES_MIN + j]; if (b2 != -1) { dxBody *bodycurr = body[(unsigned)b2]; for (unsigned int k = dSA__MIN; k != dSA__MAX; ++k) sum += J_ptr[JME__J2L_MIN + k] * bodycurr->lvel[dV3E__AXES_MIN + k] + J_ptr[JME__J2A_MIN + k] * bodycurr->avel[dV3E__AXES_MIN + k]; } J_ptr += JME__MAX; error += dFabs(sum); } printf ("velocity error = %10.6e\n", error); } #endif } static int dxQuickStepIsland_Stage6b_Callback(void *_stage6CallContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused (void)callThisReleasee; // unused dxQuickStepperStage6CallContext *stage6CallContext = (dxQuickStepperStage6CallContext *)_stage6CallContext; dxQuickStepIsland_Stage6b(stage6CallContext); return 1; } static void dxQuickStepIsland_Stage6b(dxQuickStepperStage6CallContext *stage6CallContext) { const dxStepperProcessingCallContext *callContext = stage6CallContext->m_stepperCallContext; dReal stepsize = callContext->m_stepSize; dxBody * const *body = callContext->m_islandBodiesStart; // update the position and orientation from the new linear/angular velocity // (over the given timestep) unsigned int nb = callContext->m_islandBodiesCount; const unsigned int step_size = dxQUICKSTEPISLAND_STAGE6B_STEP; unsigned int nb_steps = (nb + (step_size - 1)) / step_size; unsigned bi_step; while ((bi_step = ThrsafeIncrementIntUpToLimit(&stage6CallContext->m_bi_6b, nb_steps)) != nb_steps) { unsigned int bi = bi_step * step_size; unsigned int bicnt = dMIN(step_size, nb - bi); dxBody *const *bodycurr = body + bi; dxBody *const *bodyend = bodycurr + bicnt; while (true) { dxBody *b = *bodycurr; dxStepBody (b, stepsize); dZeroVector3 (b->facc); dZeroVector3 (b->tacc); if (++bodycurr == bodyend) { break; } } } } /*extern */ sizeint dxEstimateQuickStepMemoryRequirements (dxBody * const *body, unsigned int nb, dxJoint * const *_joint, unsigned int _nj) { (void)body; // unused unsigned int nj, m, mfb; { unsigned int njcurr = 0, mcurr = 0, mfbcurr = 0; dxJoint::SureMaxInfo info; dxJoint *const *const _jend = _joint + _nj; for (dxJoint *const *_jcurr = _joint; _jcurr != _jend; _jcurr++) { dxJoint *j = *_jcurr; j->getSureMaxInfo (&info); unsigned int jm = info.max_m; if (jm > 0) { njcurr++; mcurr += jm; if (j->feedback) mfbcurr += jm; } } nj = njcurr; m = mcurr; mfb = mfbcurr; } sizeint res = 0; res += dOVERALIGNED_SIZE(sizeof(dReal) * IIE__MAX * nb, INVI_ALIGNMENT); // for invI { sizeint sub1_res1 = dEFFICIENT_SIZE(sizeof(dJointWithInfo1) * _nj); // for initial jointinfos sizeint sub1_res2 = dEFFICIENT_SIZE(sizeof(dJointWithInfo1) * nj); // for shrunk jointinfos sub1_res2 += dEFFICIENT_SIZE(sizeof(dxQuickStepperLocalContext)); // for dxQuickStepLocalContext if (m > 0) { sub1_res2 += dEFFICIENT_SIZE(sizeof(dxMIndexItem) * (nj + 1)); // for mindex sub1_res2 += dEFFICIENT_SIZE(sizeof(dxJBodiesItem) * m); // for jb sub1_res2 += dEFFICIENT_SIZE(sizeof(int) * m); // for findex sub1_res2 += dOVERALIGNED_SIZE(sizeof(dReal) * JME__MAX * m, JACOBIAN_ALIGNMENT); // for J sub1_res2 += dOVERALIGNED_SIZE(sizeof(dReal) * JCE__MAX * mfb, JCOPY_ALIGNMENT); // for Jcopy { sizeint sub2_res1 = dEFFICIENT_SIZE(sizeof(dxQuickStepperStage3CallContext)); // for dxQuickStepperStage3CallContext sub2_res1 += dEFFICIENT_SIZE(sizeof(dReal) * RHS__MAX * nb); // for rhs_tmp sub2_res1 += dEFFICIENT_SIZE(sizeof(dxQuickStepperStage2CallContext)); // for dxQuickStepperStage2CallContext sizeint sub2_res2 = 0; { sizeint sub3_res1 = dEFFICIENT_SIZE(sizeof(dxQuickStepperStage5CallContext)); // for dxQuickStepperStage5CallContext; sub3_res1 += dEFFICIENT_SIZE(sizeof(dReal) * m); // for lambda sub3_res1 += dEFFICIENT_SIZE(sizeof(dReal) * CFE__MAX * nb); // for cforce sub3_res1 += dOVERALIGNED_SIZE(sizeof(dReal) * IMJ__MAX * m, INVMJ_ALIGNMENT); // for iMJ sub3_res1 += dEFFICIENT_SIZE(sizeof(IndexError) * m); // for order #if CONSTRAINTS_REORDERING_METHOD == REORDERING_METHOD__BY_ERROR sub3_res1 += dEFFICIENT_SIZE(sizeof(dReal) * m); // for last_lambda #endif #if !dTHREADING_INTF_DISABLED sub3_res1 += dEFFICIENT_SIZE(sizeof(atomicord32) * dMAX(nb, m)); // for bi_links_or_mi_levels sub3_res1 += dEFFICIENT_SIZE(sizeof(atomicord32) * 2 * ((sizeint)m + 1)); // for mi_links #endif sub3_res1 += dEFFICIENT_SIZE(sizeof(dxQuickStepperStage4CallContext)); // for dxQuickStepperStage4CallContext; sizeint sub3_res2 = dEFFICIENT_SIZE(sizeof(dxQuickStepperStage6CallContext)); // for dxQuickStepperStage6CallContext; sub2_res2 += dMAX(sub3_res1, sub3_res2); } sub1_res2 += dMAX(sub2_res1, sub2_res2); } } else { sub1_res2 += dEFFICIENT_SIZE(sizeof(dxQuickStepperStage3CallContext)); // for dxQuickStepperStage3CallContext } sizeint sub1_res12_max = dMAX(sub1_res1, sub1_res2); sizeint stage01_contexts = dEFFICIENT_SIZE(sizeof(dxQuickStepperStage0BodiesCallContext)) + dEFFICIENT_SIZE(sizeof(dxQuickStepperStage0JointsCallContext)) + dEFFICIENT_SIZE(sizeof(dxQuickStepperStage1CallContext)); res += dMAX(sub1_res12_max, stage01_contexts); } return res; } /*extern */ unsigned dxEstimateQuickStepMaxCallCount(unsigned activeThreadCount, unsigned allowedThreadCount) { (void)activeThreadCount; // unused unsigned result = 1 // dxQuickStepIsland itself + 5 + (2 * allowedThreadCount + 1) // for Stage4 related schedules + 1 // dxStepIsland_Stage5 + allowedThreadCount; // Reserve return result; } ode-0.16/ode/src/threading_fake_sync.h0000664000175200017520000001104413403272463014640 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * Threading fake synchronization objects file. * * Copyright (C) 2011-2012 Oleh Derevenko. All rights reserved. * * e-mail: odar@eleks.com (change all "a" to "e") * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* * Self-wakeup implementation for built-in threading support provider. * Fake mutex implementation for built-in threading support provider. * * The classes have been moved into a separate header as they are to be used * in both WIN and POSIX implementations. */ #ifndef _ODE_THREADING_FAKE_SYNC_H_ #define _ODE_THREADING_FAKE_SYNC_H_ #include #include /************************************************************************/ /* dxSelfWakeup class definition */ /************************************************************************/ class dxSelfWakeup { public: dxSelfWakeup(): m_wakeup_state(false), m_state_is_permanent(false) { } bool InitializeObject() { return true; } public: void ResetWakeup() { m_wakeup_state = false; m_state_is_permanent = false; } void WakeupAThread() { dIASSERT(!m_state_is_permanent); m_wakeup_state = true; } // Wakeup should not be used after permanent signal void WakeupAllThreads() { m_wakeup_state = true; m_state_is_permanent = true; } bool WaitWakeup(const dThreadedWaitTime *timeout_time_ptr); private: bool m_wakeup_state; bool m_state_is_permanent; }; bool dxSelfWakeup::WaitWakeup(const dThreadedWaitTime *timeout_time_ptr) { (void)timeout_time_ptr; // unused bool wait_result = m_wakeup_state; if (m_wakeup_state) { m_wakeup_state = m_state_is_permanent; } else { dICHECK(false); // Self-wakeup should only be used in cases when waiting is called after object is signaled } return wait_result; } /************************************************************************/ /* Fake mutex class implementation */ /************************************************************************/ class dxFakeMutex { public: dxFakeMutex() {} bool InitializeObject() { return true; } public: void LockMutex() { /* Do nothing */ } bool TryLockMutex() { /* Do nothing */ return true; } void UnlockMutex() { /* Do nothing */ } }; /************************************************************************/ /* Fake lull class implementation */ /************************************************************************/ class dxFakeLull { public: dxFakeLull() {} bool InitializeObject() { return true; } public: void RegisterToLull() { /* Do nothing */ } void WaitForLullAlarm() { dICHECK(false); } // Fake lull can't be waited void UnregisterFromLull() { /* Do nothing */ } void SignalLullAlarmIfAnyRegistrants() { /* Do nothing */ } }; #endif // #ifndef _ODE_THREADING_FAKE_SYNC_H_ ode-0.16/ode/src/fastldltsolve_impl.h0000664000175200017520000000433513403272463014565 00000000000000 /************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_MATRIX_IMPL_H_ #define _ODE_MATRIX_IMPL_H_ #include "fastlsolve_impl.h" #include "fastltsolve_impl.h" #include "fastvecscale_impl.h" template void solveEquationSystemWithLDLT(const dReal *L, const dReal *d, dReal *b, unsigned rowCount, unsigned rowSkip) { dAASSERT(L != NULL); dAASSERT(d != NULL); dAASSERT(b != NULL); dAASSERT(rowCount > 0); dAASSERT(rowSkip >= rowCount); solveL1Straight(L, b, rowCount, rowSkip); scaleLargeVector(b, d, rowCount); solveL1Transposed(L, b, rowCount, rowSkip); } #endif ode-0.16/ode/src/collision_trimesh_internal.cpp0000664000175200017520000006356313403272463016643 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ // TriMesh storage classes refactoring and face angle computation code by Oleh Derevenko (C) 2016-2017 #include #include #include "config.h" #include "matrix.h" #include "odemath.h" #if dTRIMESH_ENABLED #include "collision_trimesh_internal.h" #include "odeou.h" #include ////////////////////////////////////////////////////////////////////////// enum EdgeStorageSignInclusion { SSI__MIN, SSI_SIGNED_STORED = SSI__MIN, SSI_POSITIVE_STORED, SSI__MAX, }; template class FaceAngleStorageCodec; template class FaceAngleStorageCodec { public: typedef typename _make_signed::type storage_type; enum { STORAGE_TYPE_MAX = (typename _make_unsigned::type)(~(typename _make_unsigned::type)0) >> 1, }; static bool areNegativeAnglesCoded() { return true; } static storage_type encodeForStorage(dReal angleValue) { unsigned angleAsInt = (unsigned)dFloor(dFabs(angleValue) * (dReal)(STORAGE_TYPE_MAX / M_PI)); unsigned limitedAngleAsInt = dMACRO_MIN(angleAsInt, STORAGE_TYPE_MAX); storage_type result = angleValue < REAL(0.0) ? -(storage_type)limitedAngleAsInt : (storage_type)limitedAngleAsInt; return result; } static FaceAngleDomain classifyStorageValue(storage_type storedValue) { dSASSERT(EAD__MAX == 3); return storedValue < 0 ? FAD_CONCAVE : (storedValue == 0 ? FAD_FLAT : FAD_CONVEX); } static bool isAngleDomainStored(FaceAngleDomain domainValue) { return !dTMPL_IN_RANGE(domainValue, FAD__SIGNSTORED_IMPLICITVALUE_MIN, FAD__SIGNSTORED_IMPLICITVALUE_MAX); } static dReal decodeStorageValue(storage_type storedValue) { return storedValue * (dReal)(M_PI / STORAGE_TYPE_MAX); } }; template class FaceAngleStorageCodec { public: typedef typename _make_unsigned::type storage_type; enum { STORAGE_TYPE_MIN = 0, STORAGE_TYPE_MAX = (storage_type)(~(storage_type)0), }; static bool areNegativeAnglesCoded() { return false; } static storage_type encodeForStorage(dReal angleValue) { storage_type result = STORAGE_TYPE_MIN; if (angleValue >= REAL(0.0)) { unsigned angleAsInt = (unsigned)dFloor(angleValue * (dReal)(((STORAGE_TYPE_MAX - STORAGE_TYPE_MIN - 1) / M_PI))); result = (STORAGE_TYPE_MIN + 1) + dMACRO_MIN(angleAsInt, STORAGE_TYPE_MAX - STORAGE_TYPE_MIN - 1); } return result; } static FaceAngleDomain classifyStorageValue(storage_type storedValue) { dSASSERT(EAD__MAX == 3); return storedValue < STORAGE_TYPE_MIN + 1 ? FAD_CONCAVE : (storedValue == STORAGE_TYPE_MIN + 1 ? FAD_FLAT : FAD_CONVEX); } static bool isAngleDomainStored(FaceAngleDomain domainValue) { return dTMPL_IN_RANGE(domainValue, FAD__BYTEPOS_STORED_MIN, FAD__BYTEPOS_STORED_MAX); } static dReal decodeStorageValue(storage_type storedValue) { dIASSERT(storedValue >= (STORAGE_TYPE_MIN + 1)); return (storedValue - (STORAGE_TYPE_MIN + 1)) * (dReal)(M_PI / (STORAGE_TYPE_MAX - STORAGE_TYPE_MIN - 1)); } }; template class FaceAnglesWrapper: public IFaceAngleStorageControl, public IFaceAngleStorageView { protected: FaceAnglesWrapper(unsigned triangleCount) { setAllocatedTriangleCount(triangleCount); } public: virtual ~FaceAnglesWrapper(); static IFaceAngleStorageControl *allocateInstance(unsigned triangleCount, IFaceAngleStorageView *&out_storageView); static bool calculateInstanceSizeRequired(sizeint &out_sizeRequired, unsigned triangleCount); private: void freeInstance(); private: typedef typename TStorageCodec::storage_type storage_type; typedef storage_type TriangleFaceAngles[dMTV__MAX]; struct StorageRecord { StorageRecord(): m_triangleCount(0) {} unsigned m_triangleCount; TriangleFaceAngles m_triangleFaceAngles[1]; }; static sizeint calculateStorageSizeForTriangleCount(unsigned triangleCount) { const unsigned baseIncludedTriangleCount = dSTATIC_ARRAY_SIZE(FaceAnglesWrapper::StorageRecord, m_triangleFaceAngles); const sizeint singleTriangleSize = membersize(FaceAnglesWrapper::StorageRecord, m_triangleFaceAngles[0]); return sizeof(FaceAnglesWrapper) + (triangleCount > baseIncludedTriangleCount ? (triangleCount - baseIncludedTriangleCount) * singleTriangleSize : 0U); } static sizeint calculateTriangleCountForStorageSize(sizeint storageSize) { dIASSERT(storageSize >= sizeof(FaceAnglesWrapper)); const unsigned baseIncludedTriangleCount = dSTATIC_ARRAY_SIZE(FaceAnglesWrapper::StorageRecord, m_triangleFaceAngles); const sizeint singleTriangleSize = membersize(FaceAnglesWrapper::StorageRecord, m_triangleFaceAngles[0]); return (storageSize - sizeof(FaceAnglesWrapper)) / singleTriangleSize + baseIncludedTriangleCount; } private: // IFaceAngleStorageControl virtual void disposeStorage(); virtual bool areNegativeAnglesStored() const; virtual void assignFacesAngleIntoStorage(unsigned triangleIndex, dMeshTriangleVertex vertexIndex, dReal dAngleValue); private: // IFaceAngleStorageView virtual FaceAngleDomain retrieveFacesAngleFromStorage(dReal &out_angleValue, unsigned triangleIndex, dMeshTriangleVertex vertexIndex); public: void setFaceAngle(unsigned triangleIndex, dMeshTriangleVertex vertexIndex, dReal dAngleValue) { dIASSERT(dTMPL_IN_RANGE(triangleIndex, 0, getAllocatedTriangleCount())); dIASSERT(dTMPL_IN_RANGE(vertexIndex, dMTV__MIN, dMTV__MAX)); m_record.m_triangleFaceAngles[triangleIndex][vertexIndex] = TStorageCodec::encodeForStorage(dAngleValue); } FaceAngleDomain getFaceAngle(dReal &out_angleValue, unsigned triangleIndex, dMeshTriangleVertex vertexIndex) const { dIASSERT(dTMPL_IN_RANGE(triangleIndex, 0, getAllocatedTriangleCount())); dIASSERT(dTMPL_IN_RANGE(vertexIndex, dMTV__MIN, dMTV__MAX)); storage_type storedValue = m_record.m_triangleFaceAngles[triangleIndex][vertexIndex]; FaceAngleDomain resultDomain = TStorageCodec::classifyStorageValue(storedValue); out_angleValue = TStorageCodec::isAngleDomainStored(resultDomain) ? TStorageCodec::decodeStorageValue(storedValue) : REAL(0.0); return resultDomain; } private: unsigned getAllocatedTriangleCount() const { return m_record.m_triangleCount; } void setAllocatedTriangleCount(unsigned triangleCount) { m_record.m_triangleCount = triangleCount; } private: StorageRecord m_record; }; template FaceAnglesWrapper::~FaceAnglesWrapper() { } template /*static */ IFaceAngleStorageControl *FaceAnglesWrapper::allocateInstance(unsigned triangleCount, IFaceAngleStorageView *&out_storageView) { FaceAnglesWrapper *result = NULL; do { sizeint sizeRequired; if (!FaceAnglesWrapper::calculateInstanceSizeRequired(sizeRequired, triangleCount)) { break; } void *bufferPointer = dAlloc(sizeRequired); if (bufferPointer == NULL) { break; } result = (FaceAnglesWrapper *)bufferPointer; new(result) FaceAnglesWrapper(triangleCount); out_storageView = result; } while (false); return result; } template /*static */ bool FaceAnglesWrapper::calculateInstanceSizeRequired(sizeint &out_sizeRequired, unsigned triangleCount) { bool result = false; do { sizeint triangleMaximumCount = calculateTriangleCountForStorageSize(SIZE_MAX); dIASSERT(triangleCount <= triangleMaximumCount); if (triangleCount > triangleMaximumCount) // Check for overflow { break; } out_sizeRequired = calculateStorageSizeForTriangleCount(triangleCount); // Trailing alignment is going to be added by memory manager automatically result = true; } while (false); return result; } template void FaceAnglesWrapper::freeInstance() { unsigned triangleCount = getAllocatedTriangleCount(); this->FaceAnglesWrapper::~FaceAnglesWrapper(); sizeint memoryBlockSize = calculateStorageSizeForTriangleCount(triangleCount); dFree(this, memoryBlockSize); } template /*virtual */ void FaceAnglesWrapper::disposeStorage() { freeInstance(); } template /*virtual */ bool FaceAnglesWrapper::areNegativeAnglesStored() const { return TStorageCodec::areNegativeAnglesCoded(); } template /*virtual */ void FaceAnglesWrapper::assignFacesAngleIntoStorage(unsigned triangleIndex, dMeshTriangleVertex vertexIndex, dReal dAngleValue) { setFaceAngle(triangleIndex, vertexIndex, dAngleValue); } template /*virtual */ FaceAngleDomain FaceAnglesWrapper::retrieveFacesAngleFromStorage(dReal &out_angleValue, unsigned triangleIndex, dMeshTriangleVertex vertexIndex) { return getFaceAngle(out_angleValue, triangleIndex, vertexIndex); } typedef IFaceAngleStorageControl *(FAngleStorageAllocProc)(unsigned triangleCount, IFaceAngleStorageView *&out_storageView); BEGIN_NAMESPACE_OU(); template<> FAngleStorageAllocProc *const CEnumUnsortedElementArray::m_aetElementArray[] = { &FaceAnglesWrapper >::allocateInstance, // ASM_BYTE_SIGNED, &FaceAnglesWrapper >::allocateInstance, // ASM_BYTE_POSITIVE, &FaceAnglesWrapper >::allocateInstance, // ASM_WORD_SIGNED, }; END_NAMESPACE_OU(); static const CEnumUnsortedElementArray g_AngleStorageAllocProcs; ////////////////////////////////////////////////////////////////////////// dxTriDataBase::~dxTriDataBase() { freeFaceAngles(); } void dxTriDataBase::buildData(const void *vertices, int vertexStride, unsigned vertexCount, const void *indices, unsigned indexCount, int triStride, const void *normals, bool single) { dIASSERT(vertices); dIASSERT(indices); dIASSERT(vertexStride); dIASSERT(triStride); dIASSERT(indexCount); dIASSERT(indexCount % dMTV__MAX == 0); m_vertices = vertices; m_vertexStride = vertexStride; m_vertexCount = vertexCount; m_indices = indices; m_triangleCount = indexCount / dMTV__MAX; m_triStride = triStride; m_single = single; m_normals = normals; } bool dxTriDataBase::allocateFaceAngles(FaceAngleStorageMethod storageMethod) { bool result = false; dIASSERT(m_faceAngles == NULL); IFaceAngleStorageView *storageView; unsigned triangleCount = m_triangleCount; FAngleStorageAllocProc *allocProc = g_AngleStorageAllocProcs.Encode(storageMethod); IFaceAngleStorageControl *storageInstance = allocProc(triangleCount, storageView); if (storageInstance != NULL) { m_faceAngles = storageInstance; m_faceAngleView = storageView; result = true; } return result; } void dxTriDataBase::freeFaceAngles() { if (m_faceAngles != NULL) { m_faceAngles->disposeStorage(); m_faceAngles = NULL; m_faceAngleView = NULL; } } void dxTriDataBase::EdgeRecord::setupEdge(dMeshTriangleVertex edgeIdx, int triIdx, const unsigned vertexIndices[dMTV__MAX]) { if (edgeIdx < dMTV_SECOND) { dIASSERT(edgeIdx == dMTV_FIRST); m_edgeFlags = dxTriMeshData::CUF_USE_FIRST_EDGE; m_vert1Flags = dxTriMeshData::CUF_USE_FIRST_VERTEX; m_vert2Flags = dxTriMeshData::CUF_USE_SECOND_VERTEX; m_vertIdx1 = vertexIndices[dMTV_FIRST]; m_vertIdx2 = vertexIndices[dMTV_SECOND]; } else if (edgeIdx == dMTV_SECOND) { m_edgeFlags = dxTriMeshData::CUF_USE_SECOND_EDGE; m_vert1Flags = dxTriMeshData::CUF_USE_SECOND_VERTEX; m_vert2Flags = dxTriMeshData::CUF_USE_THIRD_VERTEX; m_vertIdx1 = vertexIndices[dMTV_SECOND]; m_vertIdx2 = vertexIndices[dMTV_THIRD]; } else { dIASSERT(edgeIdx == dMTV_THIRD); m_edgeFlags = dxTriMeshData::CUF_USE_THIRD_EDGE; m_vert1Flags = dxTriMeshData::CUF_USE_THIRD_VERTEX; m_vert2Flags = dxTriMeshData::CUF_USE_FIRST_VERTEX; m_vertIdx1 = vertexIndices[dMTV_THIRD]; m_vertIdx2 = vertexIndices[dMTV_FIRST]; } // Make sure vertex index 1 is less than index 2 (for easier sorting) if (m_vertIdx1 > m_vertIdx2) { dxSwap(m_vertIdx1, m_vertIdx2); dxSwap(m_vert1Flags, m_vert2Flags); } m_triIdx = triIdx; m_absVertexFlags = 0; } BEGIN_NAMESPACE_OU(); template<> const dMeshTriangleVertex CEnumUnsortedElementArray::m_aetElementArray[] = { dMTV_FIRST, // kVert0 / kVert_Base dMTV_SECOND, // kVert1 / kVert_Base dMTV__MAX, dMTV_THIRD, // kVert2 / kVert_Base }; END_NAMESPACE_OU(); /*extern */const CEnumUnsortedElementArray g_VertFlagOppositeIndices; BEGIN_NAMESPACE_OU(); template<> const dMeshTriangleVertex CEnumUnsortedElementArray::m_aetElementArray[] = { dMTV_SECOND, // kVert0 / kVert_Base dMTV_THIRD, // kVert1 / kVert_Base dMTV__MAX, dMTV_FIRST, // kVert2 / kVert_Base }; END_NAMESPACE_OU(); /*extern */const CEnumUnsortedElementArray g_VertFlagEdgeStartIndices; ////////////////////////////////////////////////////////////////////////// /*extern ODE_API */ void dGeomTriMeshDataBuildSimple1(dTriMeshDataID g, const dReal* Vertices, int VertexCount, const dTriIndex* Indices, int IndexCount, const int *Normals) { #ifdef dSINGLE dGeomTriMeshDataBuildSingle1(g, Vertices, 4 * sizeof(dReal), VertexCount, Indices, IndexCount, 3 * sizeof(dTriIndex), Normals); #else dGeomTriMeshDataBuildDouble1(g, Vertices, 4 * sizeof(dReal), VertexCount, Indices, IndexCount, 3 * sizeof(dTriIndex), Normals); #endif } /*extern ODE_API */ void dGeomTriMeshDataBuildSingle(dTriMeshDataID g, const void* Vertices, int VertexStride, int VertexCount, const void* Indices, int IndexCount, int TriStride) { dGeomTriMeshDataBuildSingle1(g, Vertices, VertexStride, VertexCount, Indices, IndexCount, TriStride, (const void *)NULL); } /*extern ODE_API */ void dGeomTriMeshDataBuildDouble(dTriMeshDataID g, const void* Vertices, int VertexStride, int VertexCount, const void* Indices, int IndexCount, int TriStride) { dGeomTriMeshDataBuildDouble1(g, Vertices, VertexStride, VertexCount, Indices, IndexCount, TriStride, NULL); } /*extern ODE_API */ void dGeomTriMeshDataBuildSimple(dTriMeshDataID g, const dReal* Vertices, int VertexCount, const dTriIndex* Indices, int IndexCount) { dGeomTriMeshDataBuildSimple1(g, Vertices, VertexCount, Indices, IndexCount, (int *)NULL); } /*extern ODE_API */ int dGeomTriMeshDataPreprocess(dTriMeshDataID g) { unsigned buildRequestFlags = (1U << dTRIDATAPREPROCESS_BUILD_CONCAVE_EDGES); return dGeomTriMeshDataPreprocess2(g, buildRequestFlags, NULL); } BEGIN_NAMESPACE_OU(); template<> const FaceAngleStorageMethod CEnumUnsortedElementArray::m_aetElementArray[] = { ASM_BYTE_POSITIVE, // dTRIDATAPREPROCESS_FACE_ANGLES_EXTRA_BYTE_POSITIVE, ASM_BYTE_SIGNED, // dTRIDATAPREPROCESS_FACE_ANGLES_EXTRA_BYTE_ALL, ASM_WORD_SIGNED, // dTRIDATAPREPROCESS_FACE_ANGLES_EXTRA_WORD_ALL, }; END_NAMESPACE_OU(); static const CEnumUnsortedElementArray g_TriMeshDataPreprocess_FaceAndlesExtraDataAngleStorageMethods; /*extern ODE_API */ int dGeomTriMeshDataPreprocess2(dTriMeshDataID g, unsigned int buildRequestFlags, const intptr *requestExtraData/*=NULL | const intptr (*)[dTRIDATAPREPROCESS_BUILD__MAX]*/) { dUASSERT(g, "The argument is not a trimesh data"); dAASSERT((buildRequestFlags & (1U << dTRIDATAPREPROCESS_BUILD_FACE_ANGLES)) == 0 || requestExtraData == NULL || dIN_RANGE(requestExtraData[dTRIDATAPREPROCESS_BUILD_FACE_ANGLES], dTRIDATAPREPROCESS_FACE_ANGLES_EXTRA__MIN, dTRIDATAPREPROCESS_FACE_ANGLES_EXTRA__MAX)); dxTriMeshData *data = g; bool buildUseFlags = (buildRequestFlags & (1U << dTRIDATAPREPROCESS_BUILD_CONCAVE_EDGES)) != 0; FaceAngleStorageMethod faceAnglesRequirement = (buildRequestFlags & (1U << dTRIDATAPREPROCESS_BUILD_FACE_ANGLES)) != 0 ? g_TriMeshDataPreprocess_FaceAndlesExtraDataAngleStorageMethods.Encode(requestExtraData != NULL && dIN_RANGE(requestExtraData[dTRIDATAPREPROCESS_BUILD_FACE_ANGLES], dTRIDATAPREPROCESS_FACE_ANGLES_EXTRA__MIN, dTRIDATAPREPROCESS_FACE_ANGLES_EXTRA__MAX) ? (unsigned)requestExtraData[dTRIDATAPREPROCESS_BUILD_FACE_ANGLES] : dTRIDATAPREPROCESS_FACE_ANGLES_EXTRA__DEFAULT) : ASM__INVALID; return data->preprocessData(buildUseFlags, faceAnglesRequirement); } /*extern ODE_API */ void dGeomTriMeshDataUpdate(dTriMeshDataID g) { dUASSERT(g, "The argument is not a trimesh data"); dxTriMeshData *data = g; data->updateData(); } ////////////////////////////////////////////////////////////////////////// /*extern ODE_API */ void dGeomTriMeshSetCallback(dGeomID g, dTriCallback* Callback) { dUASSERT(g && g->type == dTriMeshClass, "The argument is not a trimesh"); dxTriMesh *mesh = static_cast(g); mesh->assignCallback(Callback); } /*extern ODE_API */ dTriCallback* dGeomTriMeshGetCallback(dGeomID g) { dUASSERT(g && g->type == dTriMeshClass, "The argument is not a trimesh"); const dxTriMesh *mesh = static_cast(g); return mesh->retrieveCallback(); } /*extern ODE_API */ void dGeomTriMeshSetArrayCallback(dGeomID g, dTriArrayCallback* ArrayCallback) { dUASSERT(g && g->type == dTriMeshClass, "The argument is not a trimesh"); dxTriMesh *mesh = static_cast(g); mesh->assignArrayCallback(ArrayCallback); } /*extern ODE_API */ dTriArrayCallback *dGeomTriMeshGetArrayCallback(dGeomID g) { dUASSERT(g && g->type == dTriMeshClass, "The argument is not a trimesh"); const dxTriMesh *mesh = static_cast(g); return mesh->retrieveArrayCallback(); } /*extern ODE_API */ void dGeomTriMeshSetRayCallback(dGeomID g, dTriRayCallback* Callback) { dUASSERT(g && g->type == dTriMeshClass, "The argument is not a trimesh"); dxTriMesh *mesh = static_cast(g); mesh->assignRayCallback(Callback); } /*extern ODE_API */ dTriRayCallback* dGeomTriMeshGetRayCallback(dGeomID g) { dUASSERT(g && g->type == dTriMeshClass, "The argument is not a trimesh"); const dxTriMesh *mesh = static_cast(g); return mesh->retrieveRayCallback(); } /*extern ODE_API */ void dGeomTriMeshSetTriMergeCallback(dGeomID g, dTriTriMergeCallback* Callback) { dUASSERT(g && g->type == dTriMeshClass, "The argument is not a trimesh"); dxTriMesh *mesh = static_cast(g); mesh->assignTriMergeCallback(Callback); } /*extern ODE_API */ dTriTriMergeCallback *dGeomTriMeshGetTriMergeCallback(dGeomID g) { dUASSERT(g && g->type == dTriMeshClass, "The argument is not a trimesh"); const dxTriMesh *mesh = static_cast(g); return mesh->retrieveTriMergeCallback(); } /*extern ODE_API */ void dGeomTriMeshSetData(dGeomID g, dTriMeshDataID Data) { dUASSERT(g && g->type == dTriMeshClass, "The argument is not a trimesh"); dxTriMesh *mesh = static_cast(g); mesh->assignMeshData(Data); } /*extern ODE_API */ dTriMeshDataID dGeomTriMeshGetData(dGeomID g) { dUASSERT(g && g->type == dTriMeshClass, "The argument is not a trimesh"); const dxTriMesh *mesh = static_cast(g); return mesh->retrieveMeshData(); } BEGIN_NAMESPACE_OU(); template<> const int CEnumSortedElementArray::m_aetElementArray[] = { dSphereClass, // TTC_SPHERE, dBoxClass, // TTC_BOX, dCapsuleClass, // TTC_CAPSULE, }; END_NAMESPACE_OU(); static const CEnumSortedElementArray g_asiMeshTCGeomClasses; /*extern ODE_API */ void dGeomTriMeshEnableTC(dGeomID g, int geomClass, int enable) { dUASSERT(g && g->type == dTriMeshClass, "The argument is not a trimesh"); dxTriMesh *mesh = static_cast(g); dxTriMesh::TRIMESHTC tc = g_asiMeshTCGeomClasses.Decode(geomClass); if (g_asiMeshTCGeomClasses.IsValidDecode(tc)) { mesh->assignDoTC(tc, enable != 0); } } /*extern ODE_API */ int dGeomTriMeshIsTCEnabled(dGeomID g, int geomClass) { dUASSERT(g && g->type == dTriMeshClass, "The argument is not a trimesh"); const dxTriMesh *mesh = static_cast(g); dxTriMesh::TRIMESHTC tc = g_asiMeshTCGeomClasses.Decode(geomClass); bool result = g_asiMeshTCGeomClasses.IsValidDecode(tc) && mesh->retrieveDoTC(tc); return result; } /*extern ODE_API */ dTriMeshDataID dGeomTriMeshGetTriMeshDataID(dGeomID g) { dUASSERT(g && g->type == dTriMeshClass, "The argument is not a trimesh"); const dxTriMesh *mesh = static_cast(g); return mesh->retrieveMeshData(); } /*extern ODE_API */ void dGeomTriMeshClearTCCache(dGeomID g) { dUASSERT(g && g->type == dTriMeshClass, "The argument is not a trimesh"); dxTriMesh *mesh = static_cast(g); mesh->clearTCCache(); } /*extern ODE_API */ int dGeomTriMeshGetTriangleCount(dGeomID g) { dUASSERT(g && g->type == dTriMeshClass, "The argument is not a trimesh"); const dxTriMesh *mesh = static_cast(g); unsigned result = mesh->getMeshTriangleCount(); return result; } /*extern ODE_API */ void dGeomTriMeshGetTriangle(dGeomID g, int index, dVector3 *v0/*=NULL*/, dVector3 *v1/*=NULL*/, dVector3 *v2/*=NULL*/) { dUASSERT(g && g->type == dTriMeshClass, "The argument is not a trimesh"); dUASSERT(v0 != NULL || v1 != NULL || v2 != NULL, "A meaningless call"); dxTriMesh *mesh = static_cast(g); dVector3 *pv[3] = { v0, v1, v2 }; mesh->fetchMeshTransformedTriangle(pv, index); } /*extern ODE_API */ void dGeomTriMeshGetPoint(dGeomID g, int index, dReal u, dReal v, dVector3 Out) { dUASSERT(g && g->type == dTriMeshClass, "The argument is not a trimesh"); dxTriMesh *mesh = static_cast(g); dVector3 dv[3]; mesh->fetchMeshTransformedTriangle(dv, index); GetPointFromBarycentric(dv, u, v, Out); } /*extern */ IFaceAngleStorageView *dxGeomTriMeshGetFaceAngleView(dxGeom *triMeshGeom) { dUASSERT(triMeshGeom && triMeshGeom->type == dTriMeshClass, "The argument is not a trimesh"); dxTriMesh *mesh = static_cast(triMeshGeom); return mesh->retrieveFaceAngleView(); } #endif // #if dTRIMESH_ENABLED ////////////////////////////////////////////////////////////////////////// // Deprecated functions /*extern */ void dGeomTriMeshDataGetBuffer(dTriMeshDataID g, unsigned char **buf, int *bufLen) { sizeint dataSizeStorage; void *dataPointer = dGeomTriMeshDataGet2(g, dTRIMESHDATA_USE_FLAGS, (bufLen != NULL ? &dataSizeStorage : NULL)); if (bufLen != NULL) { *bufLen = (int)dataSizeStorage; } if (buf != NULL) { *buf = (unsigned char *)dataPointer; } } /*extern */ void dGeomTriMeshDataSetBuffer(dTriMeshDataID g, unsigned char* buf) { dGeomTriMeshDataSet(g, dTRIMESHDATA_USE_FLAGS, (void *)buf); } ode-0.16/ode/src/gimpact_gim_contact_accessor.h0000664000175200017520000000621313403272463016530 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_GIMPACT_GIM_CONTACT_ACCESSOR_H_ #define _ODE_GIMPACT_GIM_CONTACT_ACCESSOR_H_ struct dxGIMCContactAccessor { dxGIMCContactAccessor(GIM_CONTACT *ptrimeshcontacts, dGeomID g1, dGeomID g2) : m_ptrimeshcontacts(ptrimeshcontacts), m_g1(g1), m_g2(g2), m_gotside2ovr(false), m_side2ovr() {} dxGIMCContactAccessor(GIM_CONTACT *ptrimeshcontacts, dGeomID g1, dGeomID g2, int side2ovr) : m_ptrimeshcontacts(ptrimeshcontacts), m_g1(g1), m_g2(g2), m_gotside2ovr(true), m_side2ovr(side2ovr) {} dReal RetrieveDepthByIndex(unsigned index) const { return m_ptrimeshcontacts[index].m_depth; } void ExportContactGeomByIndex(dContactGeom *pcontact, unsigned index) const { const GIM_CONTACT *ptrimeshcontact = m_ptrimeshcontacts + index; pcontact->pos[0] = ptrimeshcontact->m_point[0]; pcontact->pos[1] = ptrimeshcontact->m_point[1]; pcontact->pos[2] = ptrimeshcontact->m_point[2]; pcontact->pos[3] = REAL(1.0); pcontact->normal[0] = ptrimeshcontact->m_normal[0]; pcontact->normal[1] = ptrimeshcontact->m_normal[1]; pcontact->normal[2] = ptrimeshcontact->m_normal[2]; pcontact->normal[3] = 0; pcontact->depth = ptrimeshcontact->m_depth; pcontact->g1 = m_g1; pcontact->g2 = m_g2; pcontact->side1 = ptrimeshcontact->m_feature1; pcontact->side2 = !m_gotside2ovr ? ptrimeshcontact->m_feature2 : m_side2ovr; } const GIM_CONTACT *m_ptrimeshcontacts; dGeomID m_g1, m_g2; bool m_gotside2ovr; int m_side2ovr; }; #endif //_ODE_GIMPACT_GIM_CONTACT_ACCESSOR_H_ ode-0.16/ode/src/odetls.cpp0000664000175200017520000001230313403272463012475 00000000000000/************************************************************************* * * * Thread local storage access stub for Open Dynamics Engine, * * Copyright (C) 2008 Oleh Derevenko. All rights reserved. * * Email: odar@eleks.com (change all "a" to "e") * * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* ODE Thread Local Storage access stub implementation. */ #include #include "config.h" #include "odemath.h" #include "odetls.h" #include "collision_trimesh_internal.h" #if dTLS_ENABLED using _OU_NAMESPACE::CTLSInitialization; ////////////////////////////////////////////////////////////////////////// // Class static fields HTLSKEY COdeTls::m_ahtkStorageKeys[OTK__MAX] = { 0 }; ////////////////////////////////////////////////////////////////////////// // Initialization and finalization bool COdeTls::Initialize(EODETLSKIND tkTLSKind) { dIASSERT(!m_ahtkStorageKeys[tkTLSKind]); bool bResult = false; unsigned uOUFlags = 0; if (tkTLSKind == OTK_MANUALCLEANUP) { uOUFlags |= CTLSInitialization::SIF_MANUAL_CLEANUP_ON_THREAD_EXIT; } if (CTLSInitialization::InitializeTLSAPI(m_ahtkStorageKeys[tkTLSKind], OTI__MAX, uOUFlags)) { bResult = true; } return bResult; } void COdeTls::Finalize(EODETLSKIND tkTLSKind) { CTLSInitialization::FinalizeTLSAPI(); m_ahtkStorageKeys[tkTLSKind] = 0; } void COdeTls::CleanupForThread() { if (m_ahtkStorageKeys[OTK_MANUALCLEANUP]) { CTLSInitialization::CleanupOnThreadExit(); } else { dIASSERT(false); // The class is not intended to be cleaned up manually } } ////////////////////////////////////////////////////////////////////////// // Value modifiers bool COdeTls::AssignDataAllocationFlags(EODETLSKIND tkTLSKind, unsigned uInitializationFlags) { bool bResult = CThreadLocalStorage::SetStorageValue(m_ahtkStorageKeys[tkTLSKind], OTI_DATA_ALLOCATION_FLAGS, (tlsvaluetype)(sizeint)uInitializationFlags); return bResult; } bool COdeTls::AssignTrimeshCollidersCache(EODETLSKIND tkTLSKind, TrimeshCollidersCache *pccInstance) { dIASSERT(!CThreadLocalStorage::GetStorageValue(m_ahtkStorageKeys[tkTLSKind], OTI_TRIMESH_TRIMESH_COLLIDER_CACHE)); bool bResult = CThreadLocalStorage::SetStorageValue(m_ahtkStorageKeys[tkTLSKind], OTI_TRIMESH_TRIMESH_COLLIDER_CACHE, (tlsvaluetype)pccInstance, &COdeTls::FreeTrimeshCollidersCache_Callback); return bResult; } void COdeTls::DestroyTrimeshCollidersCache(EODETLSKIND tkTLSKind) { TrimeshCollidersCache *pccCacheInstance = (TrimeshCollidersCache *)CThreadLocalStorage::GetStorageValue(m_ahtkStorageKeys[tkTLSKind], OTI_TRIMESH_TRIMESH_COLLIDER_CACHE); if (pccCacheInstance != NULL) { FreeTrimeshCollidersCache(pccCacheInstance); CThreadLocalStorage::UnsafeSetStorageValue(m_ahtkStorageKeys[tkTLSKind], OTI_TRIMESH_TRIMESH_COLLIDER_CACHE, (tlsvaluetype)NULL); } } ////////////////////////////////////////////////////////////////////////// // Value type destructors void COdeTls::FreeTrimeshCollidersCache(TrimeshCollidersCache *pccCacheInstance) { #if dTRIMESH_ENABLED delete pccCacheInstance; #else dIASSERT(pccCacheInstance == NULL); // The cache is not being allocated if the library is configured without trimeshes #endif } ////////////////////////////////////////////////////////////////////////// // Value type destructor callbacks void COdeTls::FreeTrimeshCollidersCache_Callback(tlsvaluetype vValueData) { TrimeshCollidersCache *pccCacheInstance = (TrimeshCollidersCache *)vValueData; FreeTrimeshCollidersCache(pccCacheInstance); } #endif // #if dTLS_ENABLED ode-0.16/ode/src/ode.cpp0000664000175200017520000015104413403272463011760 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifdef _MSC_VER #pragma warning(disable:4291) // for VC++, no complaints about "no matching operator delete found" #endif // this source file is mostly concerned with the data structures, not the // numerics. #include #include #include #include "config.h" #include "matrix.h" #include "odemath.h" #include "objects.h" #include "joints/joints.h" #include "step.h" #include "quickstep.h" #include "util.h" #include "odetls.h" // misc defines #define ALLOCA dALLOCA16 //**************************************************************************** // utility // add an object `obj' to the list who's head pointer is pointed to by `first'. void addObjectToList (dObject *obj, dObject **first) { obj->next = *first; obj->tome = first; if (*first) (*first)->tome = &obj->next; (*first) = obj; } // remove the object from the linked list static inline void removeObjectFromList (dObject *obj) { if (obj->next) obj->next->tome = obj->tome; *(obj->tome) = obj->next; // safeguard obj->next = NULL; obj->tome = NULL; } // remove the joint from neighbour lists of all connected bodies static void removeJointReferencesFromAttachedBodies (dxJoint *j) { for (int i=0; i<2; i++) { dxBody *body = j->node[i].body; if (body) { dxJointNode *n = body->firstjoint; dxJointNode *last = NULL; while (n) { if (n->joint == j) { if (last) last->next = n->next; else body->firstjoint = n->next; break; } last = n; n = n->next; } } } j->node[0].body = NULL; j->node[0].next = NULL; j->node[1].body = NULL; j->node[1].next = NULL; } //**************************************************************************** // debugging // see if an object list loops on itself (if so, it's bad). static int listHasLoops (dObject *first) { if (first==0 || first->next==0) return 0; dObject *a=first,*b=first->next; int skip=0; while (b) { if (a==b) return 1; b = b->next; if (skip) a = a->next; skip ^= 1; } return 0; } // check the validity of the world data structures static int g_world_check_tag_generator = 0; static inline int generateWorldCheckTag() { // Atomicity is not necessary here return ++g_world_check_tag_generator; } static void checkWorld (dxWorld *w) { dxBody *b; dxJoint *j; // check there are no loops if (listHasLoops (w->firstbody)) dDebug (0,"body list has loops"); if (listHasLoops (w->firstjoint)) dDebug (0,"joint list has loops"); // check lists are well formed (check `tome' pointers) for (b=w->firstbody; b; b=(dxBody*)b->next) { if (b->next && b->next->tome != &b->next) dDebug (0,"bad tome pointer in body list"); } for (j=w->firstjoint; j; j=(dxJoint*)j->next) { if (j->next && j->next->tome != &j->next) dDebug (0,"bad tome pointer in joint list"); } // check counts int n = 0; for (b=w->firstbody; b; b=(dxBody*)b->next) n++; if (w->nb != n) dDebug (0,"body count incorrect"); n = 0; for (j=w->firstjoint; j; j=(dxJoint*)j->next) n++; if (w->nj != n) dDebug (0,"joint count incorrect"); // set all tag values to a known value int count = generateWorldCheckTag(); for (b=w->firstbody; b; b=(dxBody*)b->next) b->tag = count; for (j=w->firstjoint; j; j=(dxJoint*)j->next) j->tag = count; // check all body/joint world pointers are ok for (b=w->firstbody; b; b=(dxBody*)b->next) if (b->world != w) dDebug (0,"bad world pointer in body list"); for (j=w->firstjoint; j; j=(dxJoint*)j->next) if (j->world != w) dDebug (0,"bad world pointer in joint list"); /* // check for half-connected joints - actually now these are valid for (j=w->firstjoint; j; j=(dxJoint*)j->next) { if (j->node[0].body || j->node[1].body) { if (!(j->node[0].body && j->node[1].body)) dDebug (0,"half connected joint found"); } } */ // check that every joint node appears in the joint lists of both bodies it // attaches for (j=w->firstjoint; j; j=(dxJoint*)j->next) { for (int i=0; i<2; i++) { if (j->node[i].body) { int ok = 0; for (dxJointNode *n=j->node[i].body->firstjoint; n; n=n->next) { if (n->joint == j) ok = 1; } if (ok==0) dDebug (0,"joint not in joint list of attached body"); } } } // check all body joint lists (correct body ptrs) for (b=w->firstbody; b; b=(dxBody*)b->next) { for (dxJointNode *n=b->firstjoint; n; n=n->next) { if (&n->joint->node[0] == n) { if (n->joint->node[1].body != b) dDebug (0,"bad body pointer in joint node of body list (1)"); } else { if (n->joint->node[0].body != b) dDebug (0,"bad body pointer in joint node of body list (2)"); } if (n->joint->tag != count) dDebug (0,"bad joint node pointer in body"); } } // check all body pointers in joints, check they are distinct for (j=w->firstjoint; j; j=(dxJoint*)j->next) { if (j->node[0].body && (j->node[0].body == j->node[1].body)) dDebug (0,"non-distinct body pointers in joint"); if ((j->node[0].body && j->node[0].body->tag != count) || (j->node[1].body && j->node[1].body->tag != count)) dDebug (0,"bad body pointer in joint"); } } void dWorldCheck (dxWorld *w) { checkWorld (w); } //**************************************************************************** // body dxBody::dxBody(dxWorld *w) : dObject(w) { } dxWorld* dBodyGetWorld (dxBody * b) { dAASSERT (b); return b->world; } dxBody *dBodyCreate (dxWorld *w) { dAASSERT (w); dxBody *b = new dxBody(w); b->firstjoint = NULL; b->flags = 0; b->geom = NULL; b->average_lvel_buffer = NULL; b->average_avel_buffer = NULL; dMassSetParameters (&b->mass,1,0,0,0,1,1,1,0,0,0); dSetZero (b->invI,4*3); b->invI[0] = 1; b->invI[5] = 1; b->invI[10] = 1; b->invMass = 1; dSetZero (b->posr.pos,4); dSetZero (b->q,4); b->q[0] = 1; dRSetIdentity (b->posr.R); dSetZero (b->lvel,4); dSetZero (b->avel,4); dSetZero (b->facc,4); dSetZero (b->tacc,4); dSetZero (b->finite_rot_axis,4); addObjectToList (b,(dObject **) &w->firstbody); w->nb++; // set auto-disable parameters b->average_avel_buffer = b->average_lvel_buffer = NULL; // no buffer at beginning dBodySetAutoDisableDefaults (b); // must do this after adding to world b->adis_stepsleft = b->adis.idle_steps; b->adis_timeleft = b->adis.idle_time; b->average_counter = 0; b->average_ready = 0; // average buffer not filled on the beginning dBodySetAutoDisableAverageSamplesCount(b, b->adis.average_samples); b->moved_callback = NULL; dBodySetDampingDefaults(b); // must do this after adding to world b->flags |= w->body_flags & dxBodyMaxAngularSpeed; b->max_angular_speed = w->max_angular_speed; b->flags |= dxBodyGyroscopic; return b; } void dBodyDestroy (dxBody *b) { dAASSERT (b); // all geoms that link to this body must be notified that the body is about // to disappear. note that the call to dGeomSetBody(geom,0) will result in // dGeomGetBodyNext() returning 0 for the body, so we must get the next body // before setting the body to 0. dxGeom *next_geom = NULL; for (dxGeom *geom = b->geom; geom; geom = next_geom) { next_geom = dGeomGetBodyNext (geom); dGeomSetBody (geom,0); } // detach all neighbouring joints, then delete this body. dxJointNode *n = b->firstjoint; while (n) { // sneaky trick to speed up removal of joint references (black magic) n->joint->node[(n == n->joint->node)].body = NULL; dxJointNode *next = n->next; n->next = NULL; removeJointReferencesFromAttachedBodies (n->joint); n = next; } removeObjectFromList (b); b->world->nb--; // delete the average buffers if(b->average_lvel_buffer) { delete[] (b->average_lvel_buffer); b->average_lvel_buffer = NULL; } if(b->average_avel_buffer) { delete[] (b->average_avel_buffer); b->average_avel_buffer = NULL; } delete b; } void dBodySetData (dBodyID b, void *data) { dAASSERT (b); b->userdata = data; } void *dBodyGetData (dBodyID b) { dAASSERT (b); return b->userdata; } void dBodySetPosition (dBodyID b, dReal x, dReal y, dReal z) { dAASSERT (b); b->posr.pos[0] = x; b->posr.pos[1] = y; b->posr.pos[2] = z; // notify all attached geoms that this body has moved for (dxGeom *geom = b->geom; geom; geom = dGeomGetBodyNext (geom)) dGeomMoved (geom); } void dBodySetRotation (dBodyID b, const dMatrix3 R) { dAASSERT (b && R); memcpy(b->posr.R, R, sizeof(dMatrix3)); bool bOrthogonalizeResult = dxOrthogonalizeR(b->posr.R); dAVERIFY(bOrthogonalizeResult); dRtoQ (R, b->q); dNormalize4 (b->q); // notify all attached geoms that this body has moved for (dxGeom *geom = b->geom; geom; geom = dGeomGetBodyNext (geom)) { dGeomMoved (geom); } } void dBodySetQuaternion (dBodyID b, const dQuaternion q) { dAASSERT (b && q); b->q[0] = q[0]; b->q[1] = q[1]; b->q[2] = q[2]; b->q[3] = q[3]; dNormalize4 (b->q); dQtoR (b->q,b->posr.R); // notify all attached geoms that this body has moved for (dxGeom *geom = b->geom; geom; geom = dGeomGetBodyNext (geom)) dGeomMoved (geom); } void dBodySetLinearVel (dBodyID b, dReal x, dReal y, dReal z) { dAASSERT (b); b->lvel[0] = x; b->lvel[1] = y; b->lvel[2] = z; } void dBodySetAngularVel (dBodyID b, dReal x, dReal y, dReal z) { dAASSERT (b); b->avel[0] = x; b->avel[1] = y; b->avel[2] = z; } const dReal * dBodyGetPosition (dBodyID b) { dAASSERT (b); return b->posr.pos; } void dBodyCopyPosition (dBodyID b, dVector3 pos) { dAASSERT (b); dReal* src = b->posr.pos; pos[0] = src[0]; pos[1] = src[1]; pos[2] = src[2]; } const dReal * dBodyGetRotation (dBodyID b) { dAASSERT (b); return b->posr.R; } void dBodyCopyRotation (dBodyID b, dMatrix3 R) { dAASSERT (b); const dReal* src = b->posr.R; R[0] = src[0]; R[1] = src[1]; R[2] = src[2]; R[3] = src[3]; R[4] = src[4]; R[5] = src[5]; R[6] = src[6]; R[7] = src[7]; R[8] = src[8]; R[9] = src[9]; R[10] = src[10]; R[11] = src[11]; } const dReal * dBodyGetQuaternion (dBodyID b) { dAASSERT (b); return b->q; } void dBodyCopyQuaternion (dBodyID b, dQuaternion quat) { dAASSERT (b); dReal* src = b->q; quat[0] = src[0]; quat[1] = src[1]; quat[2] = src[2]; quat[3] = src[3]; } const dReal * dBodyGetLinearVel (dBodyID b) { dAASSERT (b); return b->lvel; } const dReal * dBodyGetAngularVel (dBodyID b) { dAASSERT (b); return b->avel; } void dBodySetMass (dBodyID b, const dMass *mass) { dAASSERT (b && mass ); dIASSERT(dMassCheck(mass)); // The centre of mass must be at the origin. // Use dMassTranslate( mass, -mass->c[0], -mass->c[1], -mass->c[2] ) to correct it. dUASSERT( fabs( mass->c[0] ) <= dEpsilon && fabs( mass->c[1] ) <= dEpsilon && fabs( mass->c[2] ) <= dEpsilon, "The centre of mass must be at the origin." ); b->mass = *mass; if (dInvertPDMatrix (b->mass.I,b->invI,3,NULL)==0) { dDEBUGMSG ("inertia must be positive definite!"); dRSetIdentity (b->invI); } b->invMass = dRecip(b->mass.mass); } void dBodyGetMass (dBodyID b, dMass *mass) { dAASSERT (b && mass); *mass = b->mass; } void dBodyAddForce (dBodyID b, dReal fx, dReal fy, dReal fz) { dAASSERT (b); b->facc[0] += fx; b->facc[1] += fy; b->facc[2] += fz; } void dBodyAddTorque (dBodyID b, dReal fx, dReal fy, dReal fz) { dAASSERT (b); b->tacc[0] += fx; b->tacc[1] += fy; b->tacc[2] += fz; } void dBodyAddRelForce (dBodyID b, dReal fx, dReal fy, dReal fz) { dAASSERT (b); dVector3 t1,t2; t1[0] = fx; t1[1] = fy; t1[2] = fz; t1[3] = 0; dMultiply0_331 (t2,b->posr.R,t1); b->facc[0] += t2[0]; b->facc[1] += t2[1]; b->facc[2] += t2[2]; } void dBodyAddRelTorque (dBodyID b, dReal fx, dReal fy, dReal fz) { dAASSERT (b); dVector3 t1,t2; t1[0] = fx; t1[1] = fy; t1[2] = fz; t1[3] = 0; dMultiply0_331 (t2,b->posr.R,t1); b->tacc[0] += t2[0]; b->tacc[1] += t2[1]; b->tacc[2] += t2[2]; } void dBodyAddForceAtPos (dBodyID b, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz) { dAASSERT (b); b->facc[0] += fx; b->facc[1] += fy; b->facc[2] += fz; dVector3 f,q; f[0] = fx; f[1] = fy; f[2] = fz; q[0] = px - b->posr.pos[0]; q[1] = py - b->posr.pos[1]; q[2] = pz - b->posr.pos[2]; dAddVectorCross3(b->tacc,q,f); } void dBodyAddForceAtRelPos (dBodyID b, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz) { dAASSERT (b); dVector3 prel,f,p; f[0] = fx; f[1] = fy; f[2] = fz; f[3] = 0; prel[0] = px; prel[1] = py; prel[2] = pz; prel[3] = 0; dMultiply0_331 (p,b->posr.R,prel); b->facc[0] += f[0]; b->facc[1] += f[1]; b->facc[2] += f[2]; dAddVectorCross3(b->tacc,p,f); } void dBodyAddRelForceAtPos (dBodyID b, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz) { dAASSERT (b); dVector3 frel,f; frel[0] = fx; frel[1] = fy; frel[2] = fz; frel[3] = 0; dMultiply0_331 (f,b->posr.R,frel); b->facc[0] += f[0]; b->facc[1] += f[1]; b->facc[2] += f[2]; dVector3 q; q[0] = px - b->posr.pos[0]; q[1] = py - b->posr.pos[1]; q[2] = pz - b->posr.pos[2]; dAddVectorCross3(b->tacc,q,f); } void dBodyAddRelForceAtRelPos (dBodyID b, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz) { dAASSERT (b); dVector3 frel,prel,f,p; frel[0] = fx; frel[1] = fy; frel[2] = fz; frel[3] = 0; prel[0] = px; prel[1] = py; prel[2] = pz; prel[3] = 0; dMultiply0_331 (f,b->posr.R,frel); dMultiply0_331 (p,b->posr.R,prel); b->facc[0] += f[0]; b->facc[1] += f[1]; b->facc[2] += f[2]; dAddVectorCross3(b->tacc,p,f); } const dReal * dBodyGetForce (dBodyID b) { dAASSERT (b); return b->facc; } const dReal * dBodyGetTorque (dBodyID b) { dAASSERT (b); return b->tacc; } void dBodySetForce (dBodyID b, dReal x, dReal y, dReal z) { dAASSERT (b); b->facc[0] = x; b->facc[1] = y; b->facc[2] = z; } void dBodySetTorque (dBodyID b, dReal x, dReal y, dReal z) { dAASSERT (b); b->tacc[0] = x; b->tacc[1] = y; b->tacc[2] = z; } void dBodyGetRelPointPos (dBodyID b, dReal px, dReal py, dReal pz, dVector3 result) { dAASSERT (b); dVector3 prel,p; prel[0] = px; prel[1] = py; prel[2] = pz; prel[3] = 0; dMultiply0_331 (p,b->posr.R,prel); result[0] = p[0] + b->posr.pos[0]; result[1] = p[1] + b->posr.pos[1]; result[2] = p[2] + b->posr.pos[2]; } void dBodyGetRelPointVel (dBodyID b, dReal px, dReal py, dReal pz, dVector3 result) { dAASSERT (b); dVector3 prel,p; prel[0] = px; prel[1] = py; prel[2] = pz; prel[3] = 0; dMultiply0_331 (p,b->posr.R,prel); result[0] = b->lvel[0]; result[1] = b->lvel[1]; result[2] = b->lvel[2]; dAddVectorCross3(result,b->avel,p); } void dBodyGetPointVel (dBodyID b, dReal px, dReal py, dReal pz, dVector3 result) { dAASSERT (b); dVector3 p; p[0] = px - b->posr.pos[0]; p[1] = py - b->posr.pos[1]; p[2] = pz - b->posr.pos[2]; p[3] = 0; result[0] = b->lvel[0]; result[1] = b->lvel[1]; result[2] = b->lvel[2]; dAddVectorCross3(result,b->avel,p); } void dBodyGetPosRelPoint (dBodyID b, dReal px, dReal py, dReal pz, dVector3 result) { dAASSERT (b); dVector3 prel; prel[0] = px - b->posr.pos[0]; prel[1] = py - b->posr.pos[1]; prel[2] = pz - b->posr.pos[2]; prel[3] = 0; dMultiply1_331 (result,b->posr.R,prel); } void dBodyVectorToWorld (dBodyID b, dReal px, dReal py, dReal pz, dVector3 result) { dAASSERT (b); dVector3 p; p[0] = px; p[1] = py; p[2] = pz; p[3] = 0; dMultiply0_331 (result,b->posr.R,p); } void dBodyVectorFromWorld (dBodyID b, dReal px, dReal py, dReal pz, dVector3 result) { dAASSERT (b); dVector3 p; p[0] = px; p[1] = py; p[2] = pz; p[3] = 0; dMultiply1_331 (result,b->posr.R,p); } void dBodySetFiniteRotationMode (dBodyID b, int mode) { dAASSERT (b); b->flags &= ~(dxBodyFlagFiniteRotation | dxBodyFlagFiniteRotationAxis); if (mode) { b->flags |= dxBodyFlagFiniteRotation; if (b->finite_rot_axis[0] != 0 || b->finite_rot_axis[1] != 0 || b->finite_rot_axis[2] != 0) { b->flags |= dxBodyFlagFiniteRotationAxis; } } } void dBodySetFiniteRotationAxis (dBodyID b, dReal x, dReal y, dReal z) { dAASSERT (b); b->finite_rot_axis[0] = x; b->finite_rot_axis[1] = y; b->finite_rot_axis[2] = z; if (x != 0 || y != 0 || z != 0) { dNormalize3 (b->finite_rot_axis); b->flags |= dxBodyFlagFiniteRotationAxis; } else { b->flags &= ~dxBodyFlagFiniteRotationAxis; } } int dBodyGetFiniteRotationMode (dBodyID b) { dAASSERT (b); return ((b->flags & dxBodyFlagFiniteRotation) != 0); } void dBodyGetFiniteRotationAxis (dBodyID b, dVector3 result) { dAASSERT (b); result[0] = b->finite_rot_axis[0]; result[1] = b->finite_rot_axis[1]; result[2] = b->finite_rot_axis[2]; } int dBodyGetNumJoints (dBodyID b) { dAASSERT (b); int count=0; for (dxJointNode *n=b->firstjoint; n; n=n->next, count++); return count; } dJointID dBodyGetJoint (dBodyID b, int index) { dAASSERT (b); int i=0; for (dxJointNode *n=b->firstjoint; n; n=n->next, i++) { if (i == index) return n->joint; } return 0; } void dBodySetDynamic (dBodyID b) { dAASSERT (b); dBodySetMass(b,&b->mass); } void dBodySetKinematic (dBodyID b) { dAASSERT (b); dSetZero (b->invI,4*3); b->invMass = 0; } int dBodyIsKinematic (dBodyID b) { dAASSERT (b); return b->invMass == 0; } void dBodyEnable (dBodyID b) { dAASSERT (b); b->flags &= ~dxBodyDisabled; b->adis_stepsleft = b->adis.idle_steps; b->adis_timeleft = b->adis.idle_time; // no code for average-processing needed here } void dBodyDisable (dBodyID b) { dAASSERT (b); b->flags |= dxBodyDisabled; } int dBodyIsEnabled (dBodyID b) { dAASSERT (b); return ((b->flags & dxBodyDisabled) == 0); } void dBodySetGravityMode (dBodyID b, int mode) { dAASSERT (b); if (mode) b->flags &= ~dxBodyNoGravity; else b->flags |= dxBodyNoGravity; } int dBodyGetGravityMode (dBodyID b) { dAASSERT (b); return ((b->flags & dxBodyNoGravity) == 0); } // body auto-disable functions dReal dBodyGetAutoDisableLinearThreshold (dBodyID b) { dAASSERT(b); return dSqrt (b->adis.linear_average_threshold); } void dBodySetAutoDisableLinearThreshold (dBodyID b, dReal linear_average_threshold) { dAASSERT(b); b->adis.linear_average_threshold = linear_average_threshold * linear_average_threshold; } dReal dBodyGetAutoDisableAngularThreshold (dBodyID b) { dAASSERT(b); return dSqrt (b->adis.angular_average_threshold); } void dBodySetAutoDisableAngularThreshold (dBodyID b, dReal angular_average_threshold) { dAASSERT(b); b->adis.angular_average_threshold = angular_average_threshold * angular_average_threshold; } int dBodyGetAutoDisableAverageSamplesCount (dBodyID b) { dAASSERT(b); return b->adis.average_samples; } void dBodySetAutoDisableAverageSamplesCount (dBodyID b, unsigned int average_samples_count) { dAASSERT(b); b->adis.average_samples = average_samples_count; // update the average buffers if(b->average_lvel_buffer) { delete[] b->average_lvel_buffer; b->average_lvel_buffer = NULL; } if(b->average_avel_buffer) { delete[] b->average_avel_buffer; b->average_avel_buffer = NULL; } if(b->adis.average_samples > 0) { b->average_lvel_buffer = new dVector3[b->adis.average_samples]; b->average_avel_buffer = new dVector3[b->adis.average_samples]; } else { b->average_lvel_buffer = NULL; b->average_avel_buffer = NULL; } // new buffer is empty b->average_counter = 0; b->average_ready = 0; } int dBodyGetAutoDisableSteps (dBodyID b) { dAASSERT(b); return b->adis.idle_steps; } void dBodySetAutoDisableSteps (dBodyID b, int steps) { dAASSERT(b); b->adis.idle_steps = steps; } dReal dBodyGetAutoDisableTime (dBodyID b) { dAASSERT(b); return b->adis.idle_time; } void dBodySetAutoDisableTime (dBodyID b, dReal time) { dAASSERT(b); b->adis.idle_time = time; } int dBodyGetAutoDisableFlag (dBodyID b) { dAASSERT(b); return ((b->flags & dxBodyAutoDisable) != 0); } void dBodySetAutoDisableFlag (dBodyID b, int do_auto_disable) { dAASSERT(b); if (!do_auto_disable) { b->flags &= ~dxBodyAutoDisable; // (mg) we should also reset the IsDisabled state to correspond to the DoDisabling flag b->flags &= ~dxBodyDisabled; b->adis.idle_steps = dWorldGetAutoDisableSteps(b->world); b->adis.idle_time = dWorldGetAutoDisableTime(b->world); // resetting the average calculations too dBodySetAutoDisableAverageSamplesCount(b, dWorldGetAutoDisableAverageSamplesCount(b->world) ); } else { b->flags |= dxBodyAutoDisable; } } void dBodySetAutoDisableDefaults (dBodyID b) { dAASSERT(b); dWorldID w = b->world; dAASSERT(w); b->adis = w->adis; dBodySetAutoDisableFlag (b, w->body_flags & dxBodyAutoDisable); } // body damping functions dReal dBodyGetLinearDamping(dBodyID b) { dAASSERT(b); return b->dampingp.linear_scale; } void dBodySetLinearDamping(dBodyID b, dReal scale) { dAASSERT(b); if (scale) b->flags |= dxBodyLinearDamping; else b->flags &= ~dxBodyLinearDamping; b->dampingp.linear_scale = scale; } dReal dBodyGetAngularDamping(dBodyID b) { dAASSERT(b); return b->dampingp.angular_scale; } void dBodySetAngularDamping(dBodyID b, dReal scale) { dAASSERT(b); if (scale) b->flags |= dxBodyAngularDamping; else b->flags &= ~dxBodyAngularDamping; b->dampingp.angular_scale = scale; } void dBodySetDamping(dBodyID b, dReal linear_scale, dReal angular_scale) { dAASSERT(b); dBodySetLinearDamping(b, linear_scale); dBodySetAngularDamping(b, angular_scale); } dReal dBodyGetLinearDampingThreshold(dBodyID b) { dAASSERT(b); return dSqrt(b->dampingp.linear_threshold); } void dBodySetLinearDampingThreshold(dBodyID b, dReal threshold) { dAASSERT(b); b->dampingp.linear_threshold = threshold*threshold; } dReal dBodyGetAngularDampingThreshold(dBodyID b) { dAASSERT(b); return dSqrt(b->dampingp.angular_threshold); } void dBodySetAngularDampingThreshold(dBodyID b, dReal threshold) { dAASSERT(b); b->dampingp.angular_threshold = threshold*threshold; } void dBodySetDampingDefaults(dBodyID b) { dAASSERT(b); dWorldID w = b->world; dAASSERT(w); b->dampingp = w->dampingp; const unsigned mask = dxBodyLinearDamping | dxBodyAngularDamping; b->flags &= ~mask; // zero them b->flags |= w->body_flags & mask; } dReal dBodyGetMaxAngularSpeed(dBodyID b) { dAASSERT(b); return b->max_angular_speed; } void dBodySetMaxAngularSpeed(dBodyID b, dReal max_speed) { dAASSERT(b); if (max_speed < dInfinity) b->flags |= dxBodyMaxAngularSpeed; else b->flags &= ~dxBodyMaxAngularSpeed; b->max_angular_speed = max_speed; } void dBodySetMovedCallback(dBodyID b, void (*callback)(dBodyID)) { dAASSERT(b); b->moved_callback = callback; } dGeomID dBodyGetFirstGeom(dBodyID b) { dAASSERT(b); return b->geom; } dGeomID dBodyGetNextGeom(dGeomID geom) { dAASSERT(geom); return dGeomGetBodyNext(geom); } int dBodyGetGyroscopicMode(dBodyID b) { dAASSERT(b); return b->flags & dxBodyGyroscopic; } void dBodySetGyroscopicMode(dBodyID b, int enabled) { dAASSERT(b); if (enabled) b->flags |= dxBodyGyroscopic; else b->flags &= ~dxBodyGyroscopic; } //**************************************************************************** // joints template dxJoint* createJoint(dWorldID w, dJointGroupID group) { dxJoint *j; if (group) { j = group->alloc(w); } else { j = new T(w); } return j; } dxJoint * dJointCreateBall (dWorldID w, dJointGroupID group) { dAASSERT (w); return createJoint(w,group); } dxJoint * dJointCreateHinge (dWorldID w, dJointGroupID group) { dAASSERT (w); return createJoint(w,group); } dxJoint * dJointCreateSlider (dWorldID w, dJointGroupID group) { dAASSERT (w); return createJoint(w,group); } dxJoint * dJointCreateContact (dWorldID w, dJointGroupID group, const dContact *c) { dAASSERT (w && c); dxJointContact *j = (dxJointContact *) createJoint (w,group); j->contact = *c; return j; } dxJoint * dJointCreateHinge2 (dWorldID w, dJointGroupID group) { dAASSERT (w); return createJoint (w,group); } dxJoint * dJointCreateUniversal (dWorldID w, dJointGroupID group) { dAASSERT (w); return createJoint (w,group); } dxJoint * dJointCreatePR (dWorldID w, dJointGroupID group) { dAASSERT (w); return createJoint (w,group); } dxJoint * dJointCreatePU (dWorldID w, dJointGroupID group) { dAASSERT (w); return createJoint (w,group); } dxJoint * dJointCreatePiston (dWorldID w, dJointGroupID group) { dAASSERT (w); return createJoint (w,group); } dxJoint * dJointCreateFixed (dWorldID w, dJointGroupID group) { dAASSERT (w); return createJoint (w,group); } dxJoint * dJointCreateNull (dWorldID w, dJointGroupID group) { dAASSERT (w); return createJoint (w,group); } dxJoint * dJointCreateAMotor (dWorldID w, dJointGroupID group) { dAASSERT (w); return createJoint (w,group); } dxJoint * dJointCreateLMotor (dWorldID w, dJointGroupID group) { dAASSERT (w); return createJoint (w,group); } dxJoint * dJointCreatePlane2D (dWorldID w, dJointGroupID group) { dAASSERT (w); return createJoint (w,group); } dxJoint * dJointCreateDBall (dWorldID w, dJointGroupID group) { dAASSERT (w); return createJoint (w,group); } dxJoint * dJointCreateDHinge (dWorldID w, dJointGroupID group) { dAASSERT (w); return createJoint (w,group); } dxJoint * dJointCreateTransmission (dWorldID w, dJointGroupID group) { dAASSERT (w); return createJoint (w,group); } static void FinalizeAndDestroyJointInstance(dxJoint *j, bool delete_it) { // if any group joints have their world pointer set to 0, their world was // previously destroyed. no special handling is required for these joints. if (j->world != NULL) { removeJointReferencesFromAttachedBodies (j); removeObjectFromList (j); j->world->nj--; } if (delete_it) { delete j; } else { j->~dxJoint(); } } void dJointDestroy (dxJoint *j) { dAASSERT (j); if (!(j->flags & dJOINT_INGROUP)) { FinalizeAndDestroyJointInstance(j, true); } } dJointGroupID dJointGroupCreate (int /*max_size*/) { // not any more ... dUASSERT (max_size > 0,"max size must be > 0"); dxJointGroup *group = new dxJointGroup(); return group; } void dJointGroupDestroy (dJointGroupID group) { dAASSERT (group); dJointGroupEmpty (group); delete group; } void dJointGroupEmpty (dJointGroupID group) { dAASSERT (group); const sizeint num_joints = group->getJointCount(); if (num_joints != 0) { // Local array is used since ALLOCA leads to mysterious NULL values in first array element and crashes under VS2005 :) const sizeint max_stack_jlist_size = 1024; dxJoint *stack_jlist[max_stack_jlist_size]; const sizeint jlist_size = num_joints * sizeof(dxJoint*); dxJoint **jlist = num_joints <= max_stack_jlist_size ? stack_jlist : (dxJoint **)dAlloc(jlist_size); if (jlist != NULL) { // the joints in this group are detached starting from the most recently // added (at the top of the stack). this helps ensure that the various // linked lists are not traversed too much, as the joints will hopefully // be at the start of those lists. sizeint num_exported = group->exportJoints(jlist); dIVERIFY(num_exported == num_joints); for (sizeint i = num_joints; i != 0; ) { --i; dxJoint *j = jlist[i]; FinalizeAndDestroyJointInstance(j, false); } } else { // ...else if there is no memory, go on detaching the way it is possible sizeint joint_bytes; for (dxJoint *j = (dxJoint *)group->beginEnum(); j != NULL; j = (dxJoint *)group->continueEnum(joint_bytes)) { joint_bytes = j->size(); // Get size before object is destroyed! FinalizeAndDestroyJointInstance(j, false); } } group->freeAll(); if (jlist != stack_jlist && jlist != NULL) { dFree(jlist, jlist_size); } } } int dJointGetNumBodies(dxJoint *joint) { // check arguments dUASSERT (joint,"bad joint argument"); if ( !joint->node[0].body ) return 0; else if ( !joint->node[1].body ) return 1; else return 2; } void dJointAttach (dxJoint *joint, dxBody *body1, dxBody *body2) { // check arguments dUASSERT (joint,"bad joint argument"); dUASSERT (body1 == NULL || body1 != body2, "can't have body1==body2"); dxWorld *world = joint->world; dUASSERT ( (body1 == NULL || body1->world == world) && (body2 == NULL || body2->world == world), "joint and bodies must be in same world"); // check if the joint can not be attached to just one body dUASSERT (!((joint->flags & dJOINT_TWOBODIES) && ((body1 != NULL) != (body2 != NULL))), "joint can not be attached to just one body"); // remove any existing body attachments if (joint->node[0].body != NULL || joint->node[1].body != NULL) { removeJointReferencesFromAttachedBodies (joint); } // if a body is zero, make sure that it is body2, so 0 --> node[1].body if (body1 == NULL) { body1 = body2; body2 = NULL; joint->flags |= dJOINT_REVERSE; } else { joint->flags &= (~dJOINT_REVERSE); } // attach to new bodies joint->node[0].body = body1; joint->node[1].body = body2; if (body1 != NULL) { joint->node[1].next = body1->firstjoint; body1->firstjoint = &joint->node[1]; } else { joint->node[1].next = NULL; } if (body2 != NULL) { joint->node[0].next = body2->firstjoint; body2->firstjoint = &joint->node[0]; } else { joint->node[0].next = NULL; } // Since the bodies are now set. // Calculate the values depending on the bodies. // Only need to calculate relative value if a body exist if (body1 != NULL || body2 != NULL) { joint->setRelativeValues(); } } void dJointEnable (dxJoint *joint) { dAASSERT (joint); joint->flags &= ~dJOINT_DISABLED; } void dJointDisable (dxJoint *joint) { dAASSERT (joint); joint->flags |= dJOINT_DISABLED; } int dJointIsEnabled (dxJoint *joint) { dAASSERT (joint); return (joint->flags & dJOINT_DISABLED) == 0; } void dJointSetData (dxJoint *joint, void *data) { dAASSERT (joint); joint->userdata = data; } void *dJointGetData (dxJoint *joint) { dAASSERT (joint); return joint->userdata; } dJointType dJointGetType (dxJoint *joint) { dAASSERT (joint); return joint->type(); } dBodyID dJointGetBody (dxJoint *joint, int index) { dAASSERT (joint); if (index == 0 || index == 1) { if (joint->flags & dJOINT_REVERSE) return joint->node[1-index].body; else return joint->node[index].body; } else return 0; } void dJointSetFeedback (dxJoint *joint, dJointFeedback *f) { dAASSERT (joint); joint->feedback = f; } dJointFeedback *dJointGetFeedback (dxJoint *joint) { dAASSERT (joint); return joint->feedback; } dJointID dConnectingJoint (dBodyID in_b1, dBodyID in_b2) { dAASSERT (in_b1 || in_b2); dBodyID b1, b2; if (in_b1 == 0) { b1 = in_b2; b2 = in_b1; } else { b1 = in_b1; b2 = in_b2; } // look through b1's neighbour list for b2 for (dxJointNode *n=b1->firstjoint; n; n=n->next) { if (n->body == b2) return n->joint; } return 0; } int dConnectingJointList (dBodyID in_b1, dBodyID in_b2, dJointID* out_list) { dAASSERT (in_b1 || in_b2); dBodyID b1, b2; if (in_b1 == 0) { b1 = in_b2; b2 = in_b1; } else { b1 = in_b1; b2 = in_b2; } // look through b1's neighbour list for b2 int numConnectingJoints = 0; for (dxJointNode *n=b1->firstjoint; n; n=n->next) { if (n->body == b2) out_list[numConnectingJoints++] = n->joint; } return numConnectingJoints; } int dAreConnected (dBodyID b1, dBodyID b2) { dAASSERT (b1/* && b2*/); // b2 can be NULL to test for connection to environment // look through b1's neighbour list for b2 for (dxJointNode *n=b1->firstjoint; n; n=n->next) { if (n->body == b2) return 1; } return 0; } int dAreConnectedExcluding (dBodyID b1, dBodyID b2, int joint_type) { dAASSERT (b1/* && b2*/); // b2 can be NULL to test for connection to environment // look through b1's neighbour list for b2 for (dxJointNode *n=b1->firstjoint; n; n=n->next) { if (dJointGetType (n->joint) != joint_type && n->body == b2) return 1; } return 0; } //**************************************************************************** // world dxWorld * dWorldCreate() { dxWorld *w = new dxWorld(); return w; } void dWorldDestroy (dxWorld *w) { // delete all bodies and joints dAASSERT (w); dxBody *nextb, *b = w->firstbody; while (b) { nextb = (dxBody*) b->next; dBodyDestroy(b); // calling here dBodyDestroy for correct destroying! (i.e. the average buffers) b = nextb; } dxJoint *nextj, *j = w->firstjoint; while (j) { nextj = (dxJoint*)j->next; if (j->flags & dJOINT_INGROUP) { // the joint is part of a group, so "deactivate" it instead j->world = NULL; j->node[0].body = NULL; j->node[0].next = NULL; j->node[1].body = NULL; j->node[1].next = NULL; dMessage (0,"warning: destroying world containing grouped joints"); } else { // TODO: shouldn't we call dJointDestroy()? sizeint sz = j->size(); j->~dxJoint(); dFree (j,sz); } j = nextj; } delete w; } void dWorldSetData (dWorldID w, void *data) { dAASSERT (w); w->userdata = data; } void* dWorldGetData (dWorldID w) { dAASSERT (w); return w->userdata; } void dWorldSetGravity (dWorldID w, dReal x, dReal y, dReal z) { dAASSERT (w); w->gravity[0] = x; w->gravity[1] = y; w->gravity[2] = z; } void dWorldGetGravity (dWorldID w, dVector3 g) { dAASSERT (w); g[0] = w->gravity[0]; g[1] = w->gravity[1]; g[2] = w->gravity[2]; } void dWorldSetERP (dWorldID w, dReal erp) { dAASSERT (w); w->global_erp = erp; } dReal dWorldGetERP (dWorldID w) { dAASSERT (w); return w->global_erp; } void dWorldSetCFM (dWorldID w, dReal cfm) { dAASSERT (w); w->global_cfm = cfm; } dReal dWorldGetCFM (dWorldID w) { dAASSERT (w); return w->global_cfm; } void dWorldSetStepIslandsProcessingMaxThreadCount(dWorldID w, unsigned count) { dAASSERT (w); w->islands_max_threads = count; } unsigned dWorldGetStepIslandsProcessingMaxThreadCount(dWorldID w) { dAASSERT (w); return w->islands_max_threads; } int dWorldUseSharedWorkingMemory(dWorldID w, dWorldID from_world) { dUASSERT (w,"bad world argument"); bool result = false; if (from_world) { dUASSERT (!w->wmem, "world does already have working memory allocated"); // Prevent replacement of one memory object with another to avoid cases when smaller buffer replaces a larger one or memory manager changes. dxStepWorkingMemory *wmem = AllocateOnDemand(from_world->wmem); if (wmem) { // Even though there is an assertion check on entry still release existing // memory object for extra safety. if (w->wmem) { w->wmem->Release(); w->wmem = NULL; } wmem->Addref(); w->wmem = wmem; result = true; } } else { dxStepWorkingMemory *wmem = w->wmem; if (wmem) { wmem->Release(); w->wmem = NULL; } result = true; } return result; } void dWorldCleanupWorkingMemory(dWorldID w) { dUASSERT (w,"bad world argument"); dxStepWorkingMemory *wmem = w->wmem; if (wmem) { wmem->CleanupMemory(); } } int dWorldSetStepMemoryReservationPolicy(dWorldID w, const dWorldStepReserveInfo *policyinfo) { dUASSERT (w,"bad world argument"); dUASSERT (!policyinfo || (policyinfo->struct_size >= sizeof(*policyinfo) && policyinfo->reserve_factor >= 1.0f), "Bad policy info"); bool result = false; dxStepWorkingMemory *wmem = policyinfo ? AllocateOnDemand(w->wmem) : w->wmem; if (wmem) { if (policyinfo) { wmem->SetMemoryReserveInfo(policyinfo->reserve_factor, policyinfo->reserve_minimum); result = wmem->GetMemoryReserveInfo() != NULL; } else { wmem->ResetMemoryReserveInfoToDefault(); result = true; } } else if (!policyinfo) { result = true; } return result; } int dWorldSetStepMemoryManager(dWorldID w, const dWorldStepMemoryFunctionsInfo *memfuncs) { dUASSERT (w,"bad world argument"); dUASSERT (!memfuncs || memfuncs->struct_size >= sizeof(*memfuncs), "Bad memory functions info"); bool result = false; dxStepWorkingMemory *wmem = memfuncs ? AllocateOnDemand(w->wmem) : w->wmem; if (wmem) { if (memfuncs) { wmem->SetMemoryManager(memfuncs->alloc_block, memfuncs->shrink_block, memfuncs->free_block); result = wmem->GetMemoryManager() != NULL; } else { wmem->ResetMemoryManagerToDefault(); result = true; } } else if (!memfuncs) { result = true; } return result; } void dWorldSetStepThreadingImplementation(dWorldID w, const dxThreadingFunctionsInfo *functions_info, dThreadingImplementationID threading_impl) { dUASSERT (w,"bad world argument"); dUASSERT (!functions_info || functions_info->struct_size >= sizeof(*functions_info), "Bad threading functions info"); #if dTHREADING_INTF_DISABLED dUASSERT(functions_info == NULL && threading_impl == NULL, "Threading interface is not available"); #else w->assignThreadingImpl(functions_info, threading_impl); #endif } int dWorldStep (dWorldID w, dReal stepsize) { dUASSERT (w,"bad world argument"); dUASSERT (stepsize > 0,"stepsize must be > 0"); bool result = false; dxWorldProcessIslandsInfo islandsinfo; if (dxReallocateWorldProcessContext (w, islandsinfo, stepsize, &dxEstimateStepMemoryRequirements)) { if (dxProcessIslands (w, islandsinfo, stepsize, &dxStepIsland, &dxEstimateStepMaxCallCount)) { result = true; } } return result; } int dWorldQuickStep (dWorldID w, dReal stepsize) { dUASSERT (w,"bad world argument"); dUASSERT (stepsize > 0,"stepsize must be > 0"); bool result = false; dxWorldProcessIslandsInfo islandsinfo; if (dxReallocateWorldProcessContext (w, islandsinfo, stepsize, &dxEstimateQuickStepMemoryRequirements)) { if (dxProcessIslands (w, islandsinfo, stepsize, &dxQuickStepIsland, &dxEstimateQuickStepMaxCallCount)) { result = true; } } return result; } void dWorldImpulseToForce (dWorldID w, dReal stepsize, dReal ix, dReal iy, dReal iz, dVector3 force) { dAASSERT (w); stepsize = dRecip(stepsize); force[0] = stepsize * ix; force[1] = stepsize * iy; force[2] = stepsize * iz; // @@@ force[3] = 0; } // world auto-disable functions dReal dWorldGetAutoDisableLinearThreshold (dWorldID w) { dAASSERT(w); return dSqrt (w->adis.linear_average_threshold); } void dWorldSetAutoDisableLinearThreshold (dWorldID w, dReal linear_average_threshold) { dAASSERT(w); w->adis.linear_average_threshold = linear_average_threshold * linear_average_threshold; } dReal dWorldGetAutoDisableAngularThreshold (dWorldID w) { dAASSERT(w); return dSqrt (w->adis.angular_average_threshold); } void dWorldSetAutoDisableAngularThreshold (dWorldID w, dReal angular_average_threshold) { dAASSERT(w); w->adis.angular_average_threshold = angular_average_threshold * angular_average_threshold; } int dWorldGetAutoDisableAverageSamplesCount (dWorldID w) { dAASSERT(w); return w->adis.average_samples; } void dWorldSetAutoDisableAverageSamplesCount (dWorldID w, unsigned int average_samples_count) { dAASSERT(w); w->adis.average_samples = average_samples_count; } int dWorldGetAutoDisableSteps (dWorldID w) { dAASSERT(w); return w->adis.idle_steps; } void dWorldSetAutoDisableSteps (dWorldID w, int steps) { dAASSERT(w); w->adis.idle_steps = steps; } dReal dWorldGetAutoDisableTime (dWorldID w) { dAASSERT(w); return w->adis.idle_time; } void dWorldSetAutoDisableTime (dWorldID w, dReal time) { dAASSERT(w); w->adis.idle_time = time; } int dWorldGetAutoDisableFlag (dWorldID w) { dAASSERT(w); return w->body_flags & dxBodyAutoDisable; } void dWorldSetAutoDisableFlag (dWorldID w, int do_auto_disable) { dAASSERT(w); if (do_auto_disable) w->body_flags |= dxBodyAutoDisable; else w->body_flags &= ~dxBodyAutoDisable; } // world damping functions dReal dWorldGetLinearDampingThreshold(dWorldID w) { dAASSERT(w); return dSqrt(w->dampingp.linear_threshold); } void dWorldSetLinearDampingThreshold(dWorldID w, dReal threshold) { dAASSERT(w); w->dampingp.linear_threshold = threshold*threshold; } dReal dWorldGetAngularDampingThreshold(dWorldID w) { dAASSERT(w); return dSqrt(w->dampingp.angular_threshold); } void dWorldSetAngularDampingThreshold(dWorldID w, dReal threshold) { dAASSERT(w); w->dampingp.angular_threshold = threshold*threshold; } dReal dWorldGetLinearDamping(dWorldID w) { dAASSERT(w); return w->dampingp.linear_scale; } void dWorldSetLinearDamping(dWorldID w, dReal scale) { dAASSERT(w); if (scale) w->body_flags |= dxBodyLinearDamping; else w->body_flags &= ~dxBodyLinearDamping; w->dampingp.linear_scale = scale; } dReal dWorldGetAngularDamping(dWorldID w) { dAASSERT(w); return w->dampingp.angular_scale; } void dWorldSetAngularDamping(dWorldID w, dReal scale) { dAASSERT(w); if (scale) w->body_flags |= dxBodyAngularDamping; else w->body_flags &= ~dxBodyAngularDamping; w->dampingp.angular_scale = scale; } void dWorldSetDamping(dWorldID w, dReal linear_scale, dReal angular_scale) { dAASSERT(w); dWorldSetLinearDamping(w, linear_scale); dWorldSetAngularDamping(w, angular_scale); } dReal dWorldGetMaxAngularSpeed(dWorldID w) { dAASSERT(w); return w->max_angular_speed; } void dWorldSetMaxAngularSpeed(dWorldID w, dReal max_speed) { dAASSERT(w); if (max_speed < dInfinity) w->body_flags |= dxBodyMaxAngularSpeed; else w->body_flags &= ~dxBodyMaxAngularSpeed; w->max_angular_speed = max_speed; } void dWorldSetQuickStepNumIterations (dWorldID w, int num) { dAASSERT(w); w->qs.num_iterations = num; } int dWorldGetQuickStepNumIterations (dWorldID w) { dAASSERT(w); return w->qs.num_iterations; } void dWorldSetQuickStepW (dWorldID w, dReal param) { dAASSERT(w); w->qs.w = param; } dReal dWorldGetQuickStepW (dWorldID w) { dAASSERT(w); return w->qs.w; } void dWorldSetContactMaxCorrectingVel (dWorldID w, dReal vel) { dAASSERT(w); w->contactp.max_vel = vel; } dReal dWorldGetContactMaxCorrectingVel (dWorldID w) { dAASSERT(w); return w->contactp.max_vel; } void dWorldSetContactSurfaceLayer (dWorldID w, dReal depth) { dAASSERT(w); w->contactp.min_depth = depth; } dReal dWorldGetContactSurfaceLayer (dWorldID w) { dAASSERT(w); return w->contactp.min_depth; } //**************************************************************************** // testing #define NUM 100 #define DO(x) extern "C" void dTestDataStructures() { int i; DO(printf ("testDynamicsStuff()\n")); dBodyID body [NUM]; int nb = 0; dJointID joint [NUM]; int nj = 0; for (i=0; i 0.5) { DO(printf ("creating body\n")); body[nb] = dBodyCreate (w); DO(printf ("\t--> %p\n",body[nb])); nb++; checkWorld (w); DO(printf ("%d BODIES, %d JOINTS\n",nb,nj)); } if (nj < NUM && nb > 2 && dRandReal() > 0.5) { dBodyID b1 = body [dRand() % nb]; dBodyID b2 = body [dRand() % nb]; if (b1 != b2) { DO(printf ("creating joint, attaching to %p,%p\n",b1,b2)); joint[nj] = dJointCreateBall (w,0); DO(printf ("\t-->%p\n",joint[nj])); checkWorld (w); dJointAttach (joint[nj],b1,b2); nj++; checkWorld (w); DO(printf ("%d BODIES, %d JOINTS\n",nb,nj)); } } if (nj > 0 && nb > 2 && dRandReal() > 0.5) { dBodyID b1 = body [dRand() % nb]; dBodyID b2 = body [dRand() % nb]; if (b1 != b2) { int k = dRand() % nj; DO(printf ("reattaching joint %p\n",joint[k])); dJointAttach (joint[k],b1,b2); checkWorld (w); DO(printf ("%d BODIES, %d JOINTS\n",nb,nj)); } } if (nb > 0 && dRandReal() > 0.5) { int k = dRand() % nb; DO(printf ("destroying body %p\n",body[k])); dBodyDestroy (body[k]); checkWorld (w); for (; k < (NUM-1); k++) body[k] = body[k+1]; nb--; DO(printf ("%d BODIES, %d JOINTS\n",nb,nj)); } if (nj > 0 && dRandReal() > 0.5) { int k = dRand() % nj; DO(printf ("destroying joint %p\n",joint[k])); dJointDestroy (joint[k]); checkWorld (w); for (; k < (NUM-1); k++) joint[k] = joint[k+1]; nj--; DO(printf ("%d BODIES, %d JOINTS\n",nb,nj)); } } /* printf ("creating world\n"); dWorldID w = dWorldCreate(); checkWorld (w); printf ("creating body\n"); dBodyID b1 = dBodyCreate (w); checkWorld (w); printf ("creating body\n"); dBodyID b2 = dBodyCreate (w); checkWorld (w); printf ("creating joint\n"); dJointID j = dJointCreateBall (w); checkWorld (w); printf ("attaching joint\n"); dJointAttach (j,b1,b2); checkWorld (w); printf ("destroying joint\n"); dJointDestroy (j); checkWorld (w); printf ("destroying body\n"); dBodyDestroy (b1); checkWorld (w); printf ("destroying body\n"); dBodyDestroy (b2); checkWorld (w); printf ("destroying world\n"); dWorldDestroy (w); */ } //**************************************************************************** // configuration #if 1 #define REGISTER_EXTENSION( __a ) #__a " " #else #define REGISTER_EXTENSION( __a ) "__a " #endif static const char ode_configuration[] = "ODE " // EXTENSION LIST BEGIN //********************************** #ifdef dNODEBUG REGISTER_EXTENSION( ODE_EXT_no_debug ) #endif // dNODEBUG #if dTRIMESH_ENABLED REGISTER_EXTENSION( ODE_EXT_trimesh ) // tri-mesh extensions #if dTRIMESH_OPCODE REGISTER_EXTENSION( ODE_EXT_opcode ) // opcode extensions #if dTRIMESH_16BIT_INDICES REGISTER_EXTENSION( ODE_OPC_16bit_indices ) #endif #if !dTRIMESH_OPCODE_USE_OLD_TRIMESH_TRIMESH_COLLIDER REGISTER_EXTENSION( ODE_OPC_new_collider ) #endif #endif // dTRIMESH_OPCODE #if dTRIMESH_GIMPACT REGISTER_EXTENSION( ODE_EXT_gimpact ) // gimpact extensions #endif #endif // dTRIMESH_ENABLED #if dTLS_ENABLED REGISTER_EXTENSION( ODE_EXT_mt_collisions ) #endif // dTLS_ENABLED #if !dTHREADING_INTF_DISABLED REGISTER_EXTENSION( ODE_EXT_threading ) #if dBUILTIN_THREADING_IMPL_ENABLED REGISTER_EXTENSION( ODE_THR_builtin_impl ) #endif // #if dBUILTIN_THREADING_IMPL_ENABLED #endif // #if !dTHREADING_INTF_DISABLED //********************************** // EXTENSION LIST END // These tokens are mutually exclusive, and always present #ifdef dSINGLE "ODE_single_precision" #else "ODE_double_precision" #endif // dDOUBLE ; // END const char* dGetConfiguration (void) { return ode_configuration; } // Helper to check for a feature of ODE int dCheckConfiguration( const char* extension ) { const char *start; char *where, *terminator; /* Feature names should not have spaces. */ where = (char*)strchr(extension, ' '); if ( where || *extension == '\0') return 1; const char* config = dGetConfiguration(); const sizeint ext_length = strlen(extension); /* It takes a bit of care to be fool-proof. Don't be fooled by sub-strings, etc. */ start = config; for ( ; ; ) { where = (char*)strstr((const char *) start, extension); if (!where) break; terminator = where + ext_length; if ( (where == start || *(where - 1) == ' ') && (*terminator == ' ' || *terminator == '\0') ) { return 1; } start = terminator; } return 0; } // Local Variables: // c-basic-offset:4 // End: ode-0.16/ode/src/threading_impl.cpp0000664000175200017520000002702113403272463014174 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * Threading subsystem implementation file. * * Copyright (C) 2011-2012 Oleh Derevenko. All rights reserved. * * e-mail: odar@eleks.com (change all "a" to "e") * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* * Subsystem APIs implementation for built-in threading support provider. */ #include #include #include "config.h" #include "threading_impl_posix.h" #include "threading_impl_win.h" #include "threading_impl.h" static dMutexGroupID AllocMutexGroup(dThreadingImplementationID impl, dmutexindex_t Mutex_count, const char *const *Mutex_names_ptr/*=NULL*/); static void FreeMutexGroup(dThreadingImplementationID impl, dMutexGroupID mutex_group); static void LockMutexGroupMutex(dThreadingImplementationID impl, dMutexGroupID mutex_group, dmutexindex_t mutex_index); // static int TryLockMutexGroupMutex(dThreadingImplementationID impl, dMutexGroupID mutex_group, dmutexindex_t mutex_index); static void UnlockMutexGroupMutex(dThreadingImplementationID impl, dMutexGroupID mutex_group, dmutexindex_t mutex_index); static dCallWaitID AllocThreadedCallWait(dThreadingImplementationID impl); static void ResetThreadedCallWait(dThreadingImplementationID impl, dCallWaitID call_wait); static void FreeThreadedCallWait(dThreadingImplementationID impl, dCallWaitID call_wait); static void PostThreadedCall( dThreadingImplementationID impl, int *out_summary_fault/*=NULL*/, dCallReleaseeID *out_post_releasee/*=NULL*/, ddependencycount_t dependencies_count, dCallReleaseeID dependent_releasee/*=NULL*/, dCallWaitID call_wait/*=NULL*/, dThreadedCallFunction *call_func, void *call_context, dcallindex_t instance_index, const char *call_name/*=NULL*/); static void AlterThreadedCallDependenciesCount( dThreadingImplementationID impl, dCallReleaseeID target_releasee, ddependencychange_t dependencies_count_change); static void WaitThreadedCall( dThreadingImplementationID impl, int *out_wait_status/*=NULL*/, dCallWaitID call_wait, const dThreadedWaitTime *timeout_time_ptr/*=NULL*/, const char *wait_name/*=NULL*/); static unsigned RetrieveThreadingThreadCount(dThreadingImplementationID impl); static int PreallocateResourcesForThreadedCalls(dThreadingImplementationID impl, ddependencycount_t max_simultaneous_calls_estimate); static const dxThreadingFunctionsInfo g_builtin_threading_functions = { sizeof(dxThreadingFunctionsInfo), // unsigned struct_size; &AllocMutexGroup, // dMutexGroupAllocFunction *alloc_mutex_group; &FreeMutexGroup, // dMutexGroupFreeFunction *free_mutex_group; &LockMutexGroupMutex, // dMutexGroupMutexLockFunction *lock_group_mutex; &UnlockMutexGroupMutex, // dMutexGroupMutexUnlockFunction *unlock_group_mutex; &AllocThreadedCallWait, // dThreadedCallWaitAllocFunction *alloc_call_wait; &ResetThreadedCallWait, // dThreadedCallWaitResetFunction *reset_call_wait; &FreeThreadedCallWait, // dThreadedCallWaitFreeFunction *free_call_wait; &PostThreadedCall, // dThreadedCallPostFunction *post_call; &AlterThreadedCallDependenciesCount, // dThreadedCallDependenciesCountAlterFunction *alter_call_dependencies_count; &WaitThreadedCall, // dThreadedCallWaitFunction *wait_call; &RetrieveThreadingThreadCount, // dThreadingImplThreadCountRetrieveFunction *retrieve_thread_count; &PreallocateResourcesForThreadedCalls, // dThreadingImplResourcesForCallsPreallocateFunction *preallocate_resources_for_calls; // &TryLockMutexGroupMutex, // dMutexGroupMutexTryLockFunction *trylock_group_mutex; }; /*extern */dThreadingImplementationID dThreadingAllocateSelfThreadedImplementation() { dxSelfThreadedThreading *threading = new dxSelfThreadedThreading(); if (threading != NULL && !threading->InitializeObject()) { delete threading; threading = NULL; } dxIThreadingImplementation *impl = threading; return (dThreadingImplementationID)impl; } /*extern */dThreadingImplementationID dThreadingAllocateMultiThreadedImplementation() { #if dBUILTIN_THREADING_IMPL_ENABLED dxMultiThreadedThreading *threading = new dxMultiThreadedThreading(); if (threading != NULL && !threading->InitializeObject()) { delete threading; threading = NULL; } #else dxIThreadingImplementation *threading = NULL; #endif // #if dBUILTIN_THREADING_IMPL_ENABLED dxIThreadingImplementation *impl = threading; return (dThreadingImplementationID)impl; } /*extern */const dThreadingFunctionsInfo *dThreadingImplementationGetFunctions(dThreadingImplementationID impl) { #if dBUILTIN_THREADING_IMPL_ENABLED dAASSERT(impl != NULL); #endif // #if dBUILTIN_THREADING_IMPL_ENABLED const dThreadingFunctionsInfo *functions = NULL; #if !dBUILTIN_THREADING_IMPL_ENABLED if (impl != NULL) #endif // #if !dBUILTIN_THREADING_IMPL_ENABLED { functions = &g_builtin_threading_functions; } return functions; } /*extern */void dThreadingImplementationShutdownProcessing(dThreadingImplementationID impl) { #if dBUILTIN_THREADING_IMPL_ENABLED dAASSERT(impl != NULL); #endif // #if dBUILTIN_THREADING_IMPL_ENABLED #if !dBUILTIN_THREADING_IMPL_ENABLED if (impl != NULL) #endif // #if !dBUILTIN_THREADING_IMPL_ENABLED { ((dxIThreadingImplementation *)impl)->ShutdownProcessing(); } } /*extern */void dThreadingImplementationCleanupForRestart(dThreadingImplementationID impl) { #if dBUILTIN_THREADING_IMPL_ENABLED dAASSERT(impl != NULL); #endif // #if dBUILTIN_THREADING_IMPL_ENABLED #if !dBUILTIN_THREADING_IMPL_ENABLED if (impl != NULL) #endif // #if !dBUILTIN_THREADING_IMPL_ENABLED { ((dxIThreadingImplementation *)impl)->CleanupForRestart(); } } /*extern */void dThreadingFreeImplementation(dThreadingImplementationID impl) { if (impl != NULL) { ((dxIThreadingImplementation *)impl)->FreeInstance(); } } /*extern */void dExternalThreadingServeMultiThreadedImplementation(dThreadingImplementationID impl, dThreadReadyToServeCallback *readiness_callback/*=NULL*/, void *callback_context/*=NULL*/) { #if dBUILTIN_THREADING_IMPL_ENABLED dAASSERT(impl != NULL); #endif // #if dBUILTIN_THREADING_IMPL_ENABLED #if !dBUILTIN_THREADING_IMPL_ENABLED if (impl != NULL) #endif // #if !dBUILTIN_THREADING_IMPL_ENABLED { ((dxIThreadingImplementation *)impl)->StickToJobsProcessing(readiness_callback, callback_context); } } ////////////////////////////////////////////////////////////////////////// static dMutexGroupID AllocMutexGroup(dThreadingImplementationID impl, dmutexindex_t Mutex_count, const char *const *Mutex_names_ptr/*=NULL*/) { (void)Mutex_names_ptr; // unused dIMutexGroup *mutex_group = ((dxIThreadingImplementation *)impl)->AllocMutexGroup(Mutex_count); return (dMutexGroupID)mutex_group; } static void FreeMutexGroup(dThreadingImplementationID impl, dMutexGroupID mutex_group) { ((dxIThreadingImplementation *)impl)->FreeMutexGroup((dIMutexGroup *)mutex_group); } static void LockMutexGroupMutex(dThreadingImplementationID impl, dMutexGroupID mutex_group, dmutexindex_t mutex_index) { ((dxIThreadingImplementation *)impl)->LockMutexGroupMutex((dIMutexGroup *)mutex_group, mutex_index); } // static int TryLockMutexGroupMutex(dThreadingImplementationID impl, dMutexGroupID mutex_group, dmutexindex_t mutex_index) // { // bool trylock_result = ((dxIThreadingImplementation *)impl)->TryLockMutexGroupMutex((dIMutexGroup *)mutex_group, mutex_index); // return trylock_result; // } static void UnlockMutexGroupMutex(dThreadingImplementationID impl, dMutexGroupID mutex_group, dmutexindex_t mutex_index) { ((dxIThreadingImplementation *)impl)->UnlockMutexGroupMutex((dIMutexGroup *)mutex_group, mutex_index); } static dCallWaitID AllocThreadedCallWait(dThreadingImplementationID impl) { dxICallWait *call_wait = ((dxIThreadingImplementation *)impl)->AllocACallWait(); return (dCallWaitID)call_wait; } static void ResetThreadedCallWait(dThreadingImplementationID impl, dCallWaitID call_wait) { ((dxIThreadingImplementation *)impl)->ResetACallWait((dxICallWait *)call_wait); } static void FreeThreadedCallWait(dThreadingImplementationID impl, dCallWaitID call_wait) { ((dxIThreadingImplementation *)impl)->FreeACallWait((dxICallWait *)call_wait); } static void PostThreadedCall( dThreadingImplementationID impl, int *out_summary_fault/*=NULL*/, dCallReleaseeID *out_post_releasee/*=NULL*/, ddependencycount_t dependencies_count, dCallReleaseeID dependent_releasee/*=NULL*/, dCallWaitID call_wait/*=NULL*/, dThreadedCallFunction *call_func, void *call_context, dcallindex_t instance_index, const char *call_name/*=NULL*/) { (void)call_name; // unused ((dxIThreadingImplementation *)impl)->ScheduleNewJob(out_summary_fault, out_post_releasee, dependencies_count, dependent_releasee, (dxICallWait *)call_wait, call_func, call_context, instance_index); } static void AlterThreadedCallDependenciesCount( dThreadingImplementationID impl, dCallReleaseeID target_releasee, ddependencychange_t dependencies_count_change) { ((dxIThreadingImplementation *)impl)->AlterJobDependenciesCount(target_releasee, dependencies_count_change); } static void WaitThreadedCall( dThreadingImplementationID impl, int *out_wait_status/*=NULL*/, dCallWaitID call_wait, const dThreadedWaitTime *timeout_time_ptr/*=NULL*/, const char *wait_name/*=NULL*/) { (void)wait_name; // unused ((dxIThreadingImplementation *)impl)->WaitJobCompletion(out_wait_status, (dxICallWait *)call_wait, timeout_time_ptr); } static unsigned RetrieveThreadingThreadCount(dThreadingImplementationID impl) { return ((dxIThreadingImplementation *)impl)->RetrieveActiveThreadsCount(); } static int PreallocateResourcesForThreadedCalls(dThreadingImplementationID impl, ddependencycount_t max_simultaneous_calls_estimate) { return ((dxIThreadingImplementation *)impl)->PreallocateJobInfos(max_simultaneous_calls_estimate); } ode-0.16/ode/src/cylinder.cpp0000664000175200017520000000764713403272463013033 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* standard ODE geometry primitives: public API and pairwise collision functions. the rule is that only the low level primitive collision functions should set dContactGeom::g1 and dContactGeom::g2. */ #include #include #include #include "config.h" #include "matrix.h" #include "odemath.h" #include "collision_kernel.h" #include "collision_std.h" #include "collision_util.h" #ifdef _MSC_VER #pragma warning(disable:4291) // for VC++, no complaints about "no matching operator delete found" #endif #define dMAX(A,B) ((A)>(B) ? (A) : (B)) // flat cylinder public API dxCylinder::dxCylinder (dSpaceID space, dReal _radius, dReal _length) : dxGeom (space,1) { dAASSERT (_radius >= 0 && _length >= 0); type = dCylinderClass; radius = _radius; lz = _length; updateZeroSizedFlag(!_radius || !_length); } void dxCylinder::computeAABB() { const dMatrix3& R = final_posr->R; const dVector3& pos = final_posr->pos; dReal dOneMinusR2Square = (dReal)(REAL(1.0) - R[2]*R[2]); dReal xrange = dFabs(R[2]*lz*REAL(0.5)) + radius * dSqrt(dMAX(REAL(0.0), dOneMinusR2Square)); dReal dOneMinusR6Square = (dReal)(REAL(1.0) - R[6]*R[6]); dReal yrange = dFabs(R[6]*lz*REAL(0.5)) + radius * dSqrt(dMAX(REAL(0.0), dOneMinusR6Square)); dReal dOneMinusR10Square = (dReal)(REAL(1.0) - R[10]*R[10]); dReal zrange = dFabs(R[10]*lz*REAL(0.5)) + radius * dSqrt(dMAX(REAL(0.0), dOneMinusR10Square)); aabb[0] = pos[0] - xrange; aabb[1] = pos[0] + xrange; aabb[2] = pos[1] - yrange; aabb[3] = pos[1] + yrange; aabb[4] = pos[2] - zrange; aabb[5] = pos[2] + zrange; } dGeomID dCreateCylinder (dSpaceID space, dReal radius, dReal length) { return new dxCylinder (space,radius,length); } void dGeomCylinderSetParams (dGeomID cylinder, dReal radius, dReal length) { dUASSERT (cylinder && cylinder->type == dCylinderClass,"argument not a ccylinder"); dAASSERT (radius >= 0 && length >= 0); dxCylinder *c = (dxCylinder*) cylinder; c->radius = radius; c->lz = length; c->updateZeroSizedFlag(!radius || !length); dGeomMoved (cylinder); } void dGeomCylinderGetParams (dGeomID cylinder, dReal *radius, dReal *length) { dUASSERT (cylinder && cylinder->type == dCylinderClass,"argument not a ccylinder"); dxCylinder *c = (dxCylinder*) cylinder; *radius = c->radius; *length = c->lz; } ode-0.16/ode/src/odeinit.cpp0000664000175200017520000003232013403272463012637 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* ODE initialization/finalization code */ #include #include // included for dWorldQuickStepCleanup() #include #include "config.h" #include "odemath.h" #include "collision_kernel.h" #include "collision_trimesh_internal.h" #include "odetls.h" #include "odeou.h" #include "default_threading.h" //**************************************************************************** // Initialization tracking variables static unsigned int g_uiODEInitCounter = 0; static unsigned int g_uiODEInitModes = 0; #if dTRIMESH_ENABLED && dTRIMESH_OPCODE static void OPCODEAbort() { dICHECK(!"OPCODE Library Abort"); } #endif // #if dTRIMESH_ENABLED && dTRIMESH_OPCODE enum EODEINITMODE { OIM__MIN, OIM_AUTOTLSCLEANUP = OIM__MIN, OIM_MANUALTLSCLEANUP, OIM__MAX }; #if dTLS_ENABLED static const EODETLSKIND g_atkTLSKindsByInitMode[OIM__MAX] = { OTK_AUTOCLEANUP, // OIM_AUTOTLSCLEANUP, OTK_MANUALCLEANUP, // OIM_MANUALTLSCLEANUP, }; #endif // #if dTLS_ENABLED static inline bool IsODEModeInitialized(EODEINITMODE imInitMode) { return (g_uiODEInitModes & (1U << imInitMode)) != 0; } static inline void SetODEModeInitialized(EODEINITMODE imInitMode) { g_uiODEInitModes |= (1U << imInitMode); } static inline void ResetODEModeInitialized(EODEINITMODE imInitMode) { g_uiODEInitModes &= ~(1U << imInitMode); } static inline bool IsODEAnyModeInitialized() { return g_uiODEInitModes != 0; } enum { TLD_INTERNAL_COLLISIONDATA_ALLOCATED = 0x00000001 }; static bool AllocateThreadBasicDataIfNecessary(EODEINITMODE imInitMode) { bool bResult = false; do { #if dTLS_ENABLED EODETLSKIND tkTlsKind = g_atkTLSKindsByInitMode[imInitMode]; const unsigned uDataAllocationFlags = COdeTls::GetDataAllocationFlags(tkTlsKind); // If no flags are set it may mean that TLS slot is not allocated yet if (uDataAllocationFlags == 0) { // Assign zero flags to make sure that TLS slot has been allocated if (!COdeTls::AssignDataAllocationFlags(tkTlsKind, 0)) { break; } } #else (void)imInitMode; // unused #endif // #if dTLS_ENABLED bResult = true; } while (false); return bResult; } static void FreeThreadBasicDataOnFailureIfNecessary(EODEINITMODE imInitMode) { #if dTLS_ENABLED if (imInitMode == OIM_MANUALTLSCLEANUP) { EODETLSKIND tkTlsKind = g_atkTLSKindsByInitMode[imInitMode]; const unsigned uDataAllocationFlags = COdeTls::GetDataAllocationFlags(tkTlsKind); if (uDataAllocationFlags == 0) { // So far, only free TLS slot, if no subsystems have data allocated COdeTls::CleanupForThread(); } } #else (void)imInitMode; // unused #endif // #if dTLS_ENABLED } #if dTLS_ENABLED static bool AllocateThreadCollisionData(EODETLSKIND tkTlsKind) { bool bResult = false; do { dIASSERT(!(COdeTls::GetDataAllocationFlags(tkTlsKind) & TLD_INTERNAL_COLLISIONDATA_ALLOCATED)); #if dTRIMESH_ENABLED TrimeshCollidersCache *pccColliderCache = new TrimeshCollidersCache(); if (!COdeTls::AssignTrimeshCollidersCache(tkTlsKind, pccColliderCache)) { delete pccColliderCache; break; } #endif // dTRIMESH_ENABLED COdeTls::SignalDataAllocationFlags(tkTlsKind, TLD_INTERNAL_COLLISIONDATA_ALLOCATED); bResult = true; } while (false); return bResult; } #endif // dTLS_ENABLED static bool AllocateThreadCollisionDataIfNecessary(EODEINITMODE imInitMode, bool &bOutDataAllocated) { bool bResult = false; bOutDataAllocated = false; do { #if dTLS_ENABLED EODETLSKIND tkTlsKind = g_atkTLSKindsByInitMode[imInitMode]; const unsigned uDataAllocationFlags = COdeTls::GetDataAllocationFlags(tkTlsKind); if ((uDataAllocationFlags & TLD_INTERNAL_COLLISIONDATA_ALLOCATED) == 0) { if (!AllocateThreadCollisionData(tkTlsKind)) { break; } bOutDataAllocated = true; } #else (void)imInitMode; // unused #endif // #if dTLS_ENABLED bResult = true; } while (false); return bResult; } static void FreeThreadCollisionData(EODEINITMODE imInitMode) { #if dTLS_ENABLED EODETLSKIND tkTlsKind = g_atkTLSKindsByInitMode[imInitMode]; COdeTls::DestroyTrimeshCollidersCache(tkTlsKind); COdeTls::DropDataAllocationFlags(tkTlsKind, TLD_INTERNAL_COLLISIONDATA_ALLOCATED); #else (void)imInitMode; // unused #endif // dTLS_ENABLED } static bool InitODEForMode(EODEINITMODE imInitMode) { bool bResult = false; #if dOU_ENABLED bool bOUCustomizationsDone = false; #endif #if dATOMICS_ENABLED bool bAtomicsInitialized = false; #endif #if dTLS_ENABLED EODETLSKIND tkTLSKindToInit = g_atkTLSKindsByInitMode[imInitMode]; bool bTlsInitialized = false; #else (void)imInitMode; // unused #endif bool bWorldThreadingInitialized = false; do { bool bAnyModeAlreadyInitialized = IsODEAnyModeInitialized(); if (!bAnyModeAlreadyInitialized) { #if dOU_ENABLED if (!COdeOu::DoOUCustomizations()) { break; } bOUCustomizationsDone = true; #endif #if dATOMICS_ENABLED if (!COdeOu::InitializeAtomics()) { break; } bAtomicsInitialized = true; #endif } #if dTLS_ENABLED if (!COdeTls::Initialize(tkTLSKindToInit)) { break; } bTlsInitialized = true; #endif if (!bAnyModeAlreadyInitialized) { if (!DefaultThreadingHolder::initializeDefaultThreading()) { break; } bWorldThreadingInitialized = true; #if dTRIMESH_ENABLED && dTRIMESH_OPCODE if (!Opcode::InitOpcode(&OPCODEAbort)) { break; } #endif #if dTRIMESH_ENABLED && dTRIMESH_GIMPACT gimpact_init(); #endif dInitColliders(); } bResult = true; } while (false); if (!bResult) { if (bWorldThreadingInitialized) { DefaultThreadingHolder::finalizeDefaultThreading(); } #if dTLS_ENABLED if (bTlsInitialized) { COdeTls::Finalize(tkTLSKindToInit); } #endif #if dATOMICS_ENABLED if (bAtomicsInitialized) { COdeOu::FinalizeAtomics(); } #endif #if dOU_ENABLED if (bOUCustomizationsDone) { COdeOu::UndoOUCustomizations(); } #endif } return bResult; } static bool AllocateODEDataForThreadForMode(EODEINITMODE imInitMode, unsigned int uiAllocateFlags) { bool bResult = false; bool bCollisionDataAllocated = false; do { if (!AllocateThreadBasicDataIfNecessary(imInitMode)) { break; } if (uiAllocateFlags & dAllocateFlagCollisionData) { if (!AllocateThreadCollisionDataIfNecessary(imInitMode, bCollisionDataAllocated)) { break; } } bResult = true; } while (false); if (!bResult) { if (bCollisionDataAllocated) { FreeThreadCollisionData(imInitMode); } FreeThreadBasicDataOnFailureIfNecessary(imInitMode); } return bResult; } static void CloseODEForMode(EODEINITMODE imInitMode) { bool bAnyModeStillInitialized = IsODEAnyModeInitialized(); if (!bAnyModeStillInitialized) { dClearPosrCache(); dFinitUserClasses(); dFinitColliders(); #if dTRIMESH_ENABLED && dTRIMESH_GIMPACT gimpact_terminate(); #endif #if dTRIMESH_ENABLED && dTRIMESH_OPCODE extern void opcode_collider_cleanup(); // Free up static allocations in opcode opcode_collider_cleanup(); Opcode::CloseOpcode(); #endif DefaultThreadingHolder::finalizeDefaultThreading(); } #if dTLS_ENABLED EODETLSKIND tkTLSKindToFinalize = g_atkTLSKindsByInitMode[imInitMode]; COdeTls::Finalize(tkTLSKindToFinalize); #else (void)imInitMode; // unused #endif if (!bAnyModeStillInitialized) { #if dATOMICS_ENABLED COdeOu::FinalizeAtomics(); #endif #if dOU_ENABLED COdeOu::UndoOUCustomizations(); #endif } } //**************************************************************************** // internal initialization and close routine implementations static bool InternalInitODE(unsigned int uiInitFlags) { bool bResult = false; do { EODEINITMODE imInitMode = (uiInitFlags & dInitFlagManualThreadCleanup) ? OIM_MANUALTLSCLEANUP : OIM_AUTOTLSCLEANUP; if (!IsODEModeInitialized(imInitMode)) { if (!InitODEForMode(imInitMode)) { break; } SetODEModeInitialized(imInitMode); } ++g_uiODEInitCounter; bResult = true; } while (false); return bResult; } static void InternalCloseODE() { unsigned int uiCurrentMode = (--g_uiODEInitCounter == 0) ? OIM__MIN : OIM__MAX; for (; uiCurrentMode != OIM__MAX; ++uiCurrentMode) { if (IsODEModeInitialized((EODEINITMODE)uiCurrentMode)) { // Must be called before CloseODEForMode() ResetODEModeInitialized((EODEINITMODE)uiCurrentMode); // Must be called after ResetODEModeInitialized() CloseODEForMode((EODEINITMODE)uiCurrentMode); } } } static bool InternalAllocateODEDataForThread(unsigned int uiAllocateFlags) { bool bAnyFailure = false; for (unsigned uiCurrentMode = OIM__MIN; uiCurrentMode != OIM__MAX; ++uiCurrentMode) { if (IsODEModeInitialized((EODEINITMODE)uiCurrentMode)) { if (!AllocateODEDataForThreadForMode((EODEINITMODE)uiCurrentMode, uiAllocateFlags)) { bAnyFailure = true; break; } } } bool bResult = !bAnyFailure; return bResult; } static void InternalCleanupODEAllDataForThread() { #if dTLS_ENABLED COdeTls::CleanupForThread(); #endif } //**************************************************************************** // initialization and shutdown routines - allocate and initialize data, // cleanup before exiting void dInitODE() { int bInitResult = InternalInitODE(0); dIVERIFY(bInitResult); int ibAllocResult = InternalAllocateODEDataForThread(dAllocateMaskAll); dIVERIFY(ibAllocResult); } int dInitODE2(unsigned int uiInitFlags/*=0*/) { bool bResult = false; bool bODEInitialized = false; do { if (!InternalInitODE(uiInitFlags)) { break; } bODEInitialized = true; if (!InternalAllocateODEDataForThread(dAllocateFlagBasicData)) { break; } bResult = true; } while (false); if (!bResult) { if (bODEInitialized) { InternalCloseODE(); } } return bResult; } int dAllocateODEDataForThread(unsigned int uiAllocateFlags) { dUASSERT(g_uiODEInitCounter != 0, "Call dInitODE2 first"); bool bResult = InternalAllocateODEDataForThread(uiAllocateFlags); return bResult; } void dCleanupODEAllDataForThread() { dUASSERT(g_uiODEInitCounter != 0, "Call dInitODE2 first or delay dCloseODE until all threads exit"); InternalCleanupODEAllDataForThread(); } void dCloseODE() { dUASSERT(g_uiODEInitCounter != 0, "dCloseODE must not be called without dInitODE2 or if dInitODE2 fails"); // dCloseODE must not be called without dInitODE2 or if dInitODE2 fails InternalCloseODE(); } ode-0.16/ode/src/fastldltfactor.cpp0000664000175200017520000005501313403272463014224 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* * LDLT factorization related code of ThreadedEquationSolverLDLT * Copyright (c) 2017 Oleh Derevenko, odar@eleks.com (change all "a" to "e") */ #include #include #include #include "config.h" #include "threaded_solver_ldlt.h" #include "threading_base.h" #include "resource_control.h" #include "error.h" #include "fastldltfactor_impl.h" /*static */ void ThreadedEquationSolverLDLT::estimateCooperativeFactoringLDLTResourceRequirements( dxResourceRequirementDescriptor *summaryRequirementsDescriptor, unsigned allowedThreadCount, unsigned rowCount) { dxThreadingBase *threading = summaryRequirementsDescriptor->getrelatedThreading(); unsigned limitedThreadCount = restrictFactoringLDLTAllowedThreadCount(threading, allowedThreadCount, rowCount); if (limitedThreadCount > 1) { doEstimateCooperativeFactoringLDLTResourceRequirementsValidated(summaryRequirementsDescriptor, allowedThreadCount, rowCount); } } /*static */ void ThreadedEquationSolverLDLT::cooperativelyFactorLDLT( dxRequiredResourceContainer *resourceContainer, unsigned allowedThreadCount, dReal *A, dReal *d, unsigned rowCount, unsigned rowSkip) { dAASSERT(rowCount != 0); dxThreadingBase *threading = resourceContainer->getThreadingInstance(); unsigned limitedThreadCount = restrictFactoringLDLTAllowedThreadCount(threading, allowedThreadCount, rowCount); if (limitedThreadCount <= 1) { factorMatrixAsLDLT(A, d, rowCount, rowSkip); } else { doCooperativelyFactorLDLTValidated(resourceContainer, limitedThreadCount, A, d, rowCount, rowSkip); } } /*static */ unsigned ThreadedEquationSolverLDLT::restrictFactoringLDLTAllowedThreadCount( dxThreadingBase *threading, unsigned allowedThreadCount, unsigned rowCount) { unsigned limitedThreadCount = 1; #if dCOOPERATIVE_ENABLED const unsigned int solvingBlockStep = FSL1S_BLOCK_SIZE; // Required by the implementation unsigned solvingMaximalBlockCount = deriveSolvingL1StripeBlockCount(rowCount, solvingBlockStep); dIASSERT(deriveSolvingL1StripeThreadCount(FLDLT_COOPERATIVE_BLOCK_COUNT_MINIMUM - 1, 2) > 1); if (solvingMaximalBlockCount >= FLDLT_COOPERATIVE_BLOCK_COUNT_MINIMUM) { limitedThreadCount = threading->calculateThreadingLimitedThreadCount(allowedThreadCount, false); } #endif // #if dCOOPERATIVE_ENABLED return limitedThreadCount; } /*static */ void ThreadedEquationSolverLDLT::doEstimateCooperativeFactoringLDLTResourceRequirementsValidated( dxResourceRequirementDescriptor *summaryRequirementsDescriptor, unsigned allowedThreadCount, unsigned rowCount) { const unsigned int solvingBlockStep = FSL1S_BLOCK_SIZE; // Required by the implementation unsigned solvingTotalBlockCount = deriveSolvingL1StripeBlockCount(rowCount, solvingBlockStep); dIASSERT(solvingTotalBlockCount >= 1); unsigned solvingLastBlockIndex = solvingTotalBlockCount - 1; const unsigned factorizingBlockARows = FFL1S_REGULAR_A_ROWS; unsigned factorizingMaximalBlockCount = deriveScalingAndFactorizingL1StripeBlockCountFromSolvingBlockIndex(solvingLastBlockIndex, solvingBlockStep, factorizingBlockARows); unsigned blockSolvingMaximumThreads = deriveSolvingL1StripeThreadCount(solvingLastBlockIndex, allowedThreadCount); unsigned blockFactorizingMaximumThreads = deriveScalingAndFactorizingL1StripeThreadCount(factorizingMaximalBlockCount, allowedThreadCount); unsigned simultaneousCallCount = 1 // Final synchronization point + 2 // intermediate synchronization points + dMACRO_MAX(blockSolvingMaximumThreads, blockFactorizingMaximumThreads); FactorizationSolvingL1StripeMemoryEstimates solvingMemoryEstimates; FactorizationScalingAndFactorizingL1StripeMemoryEstimates scalingAndFactorizingEstimates; sizeint solvingMemoryRequired = estimateCooperativelySolvingL1Stripe_XMemoryRequirement(solvingTotalBlockCount, solvingMemoryEstimates); sizeint factorizingMemoryRequired = estimateCooperativelyScalingAndFactorizingL1Stripe_XMemoryRequirement(blockFactorizingMaximumThreads, scalingAndFactorizingEstimates); sizeint totalSizeRequired = solvingMemoryRequired + factorizingMemoryRequired; const unsigned memoryAlignmentRequired = ALLOCATION_DEFAULT_ALIGNMENT; unsigned featureRequirement = dxResourceRequirementDescriptor::STOCK_CALLWAIT_REQUIRED; summaryRequirementsDescriptor->mergeAnotherDescriptorIn(totalSizeRequired, memoryAlignmentRequired, simultaneousCallCount, featureRequirement); } /*static */ void ThreadedEquationSolverLDLT::doCooperativelyFactorLDLTValidated( dxRequiredResourceContainer *resourceContainer, unsigned allowedThreadCount, dReal *A, dReal *d, unsigned rowCount, unsigned rowSkip) { dIASSERT(allowedThreadCount > 1); const unsigned int solvingBlockStep = FSL1S_BLOCK_SIZE; // Required by the implementation unsigned solvingTotalBlockCount = deriveSolvingL1StripeBlockCount(rowCount, solvingBlockStep); dIASSERT(solvingTotalBlockCount >= 1); unsigned solvingLastBlockIndex = solvingTotalBlockCount - 1; const unsigned factorizingBlockARows = FFL1S_REGULAR_A_ROWS; unsigned factorizingMaximalBlockCount = deriveScalingAndFactorizingL1StripeBlockCountFromSolvingBlockIndex(solvingLastBlockIndex, solvingBlockStep, factorizingBlockARows); unsigned blockFactorizingMaximumThreads = deriveScalingAndFactorizingL1StripeThreadCount(factorizingMaximalBlockCount, allowedThreadCount); dCallWaitID completionWait = resourceContainer->getStockCallWait(); dAASSERT(completionWait != NULL); FactorizationSolvingL1StripeMemoryEstimates solvingMemoryEstimates; FactorizationScalingAndFactorizingL1StripeMemoryEstimates scalingAndFactorizingEstimates; sizeint solvingMemoryRequired = estimateCooperativelySolvingL1Stripe_XMemoryRequirement(solvingTotalBlockCount, solvingMemoryEstimates); sizeint factorizingMemoryRequired = estimateCooperativelyScalingAndFactorizingL1Stripe_XMemoryRequirement(blockFactorizingMaximumThreads, scalingAndFactorizingEstimates); sizeint totalSizeRequired = solvingMemoryRequired + factorizingMemoryRequired; dIASSERT(totalSizeRequired <= resourceContainer->getMemoryBufferSize()); void *bufferAllocated = resourceContainer->getMemoryBufferPointer(); dIASSERT(bufferAllocated != NULL); dIASSERT(dALIGN_PTR(bufferAllocated, ALLOCATION_DEFAULT_ALIGNMENT) == bufferAllocated); atomicord32 solvingBlockCompletionProgress; cellindexint *solvingBlockProgressDescriptors; FactorizationSolveL1StripeCellContext *solvingCellContexts; FactorizationFactorizeL1StripeContext *factorizingFactorizationContext; void *bufferCurrentLocation = bufferAllocated; bufferCurrentLocation = markCooperativelySolvingL1Stripe_XMemoryStructuresOut(bufferCurrentLocation, solvingMemoryEstimates, solvingBlockProgressDescriptors, solvingCellContexts); bufferCurrentLocation = markCooperativelyScalingAndFactorizingL1Stripe_XMemoryStructuresOut(bufferCurrentLocation, scalingAndFactorizingEstimates, factorizingFactorizationContext); dIVERIFY(bufferCurrentLocation <= (uint8 *)bufferAllocated + totalSizeRequired); dCallReleaseeID calculationFinishReleasee; dxThreadingBase *threading = resourceContainer->getThreadingInstance(); threading->PostThreadedCall(NULL, &calculationFinishReleasee, 1, NULL, completionWait, &factotLDLT_completion_callback, NULL, 0, "FactorLDLT Completion"); FactorLDLTWorkerContext workerContext(threading, allowedThreadCount, A, d, solvingTotalBlockCount, rowCount, rowSkip, solvingBlockCompletionProgress, solvingBlockProgressDescriptors, solvingCellContexts, factorizingFactorizationContext, calculationFinishReleasee); // The variable must exist in the outer scope dIASSERT(solvingTotalBlockCount >= FLDLT_COOPERATIVE_BLOCK_COUNT_MINIMUM); dSASSERT(FLDLT_COOPERATIVE_BLOCK_COUNT_MINIMUM > 2); scaleAndFactorizeL1FirstRowStripe_2(workerContext.m_ARow, workerContext.m_d, workerContext.m_rowSkip); workerContext.incrementForNextBlock(); const unsigned blockIndex = 1; dIASSERT(blockIndex == workerContext.m_solvingBlockIndex); initializeCooperativelySolvingL1Stripe_XMemoryStructures(blockIndex, solvingBlockCompletionProgress, solvingBlockProgressDescriptors, solvingCellContexts); unsigned secondBlockSolvingThreadCount = deriveSolvingL1StripeThreadCount(blockIndex, allowedThreadCount); dCallReleaseeID secondBlockSolvingSyncReleasee; threading->PostThreadedCall(NULL, &secondBlockSolvingSyncReleasee, secondBlockSolvingThreadCount, NULL, NULL, &factotLDLT_solvingCompleteSync_callback, &workerContext, 0, "FactorLDLT Solving Complete Sync"); if (secondBlockSolvingThreadCount > 1) { threading->PostThreadedCallsGroup(NULL, secondBlockSolvingThreadCount - 1, secondBlockSolvingSyncReleasee, &factotLDLT_solvingComplete_callback, &workerContext, "FactorLDLT Solving Complete"); } factotLDLT_solvingComplete(workerContext, secondBlockSolvingThreadCount - 1); threading->AlterThreadedCallDependenciesCount(secondBlockSolvingSyncReleasee, -1); threading->WaitThreadedCallExclusively(NULL, completionWait, NULL, "FactorLDLT End Wait"); } /*static */ int ThreadedEquationSolverLDLT::factotLDLT_solvingComplete_callback(void *callContext, dcallindex_t callInstanceIndex, dCallReleaseeID dUNUSED(callThisReleasee)) { FactorLDLTWorkerContext *ptrContext = (FactorLDLTWorkerContext *)callContext; factotLDLT_solvingComplete(*ptrContext, dCAST_TO_SMALLER(unsigned, callInstanceIndex)); return 1; } /*static */ void ThreadedEquationSolverLDLT::factotLDLT_solvingComplete(FactorLDLTWorkerContext &ref_context, unsigned ownThreadIndex) { participateSolvingL1Stripe_X(ref_context.m_A, ref_context.m_ARow, ref_context.m_solvingBlockIndex, ref_context.m_rowSkip, ref_context.m_refSolvingBlockCompletionProgress, ref_context.m_solvingBlockProgressDescriptors, ref_context.m_solvingCellContexts, ownThreadIndex); } /*static */ int ThreadedEquationSolverLDLT::factotLDLT_solvingCompleteSync_callback(void *callContext, dcallindex_t dUNUSED(callInstanceIndex), dCallReleaseeID dUNUSED(callThisReleasee)) { FactorLDLTWorkerContext *ptrContext = (FactorLDLTWorkerContext *)callContext; factotLDLT_solvingCompleteSync(*ptrContext); return 1; } /*static */ void ThreadedEquationSolverLDLT::factotLDLT_solvingCompleteSync(FactorLDLTWorkerContext &ref_workerContext) { unsigned solvingBlockIndex = ref_workerContext.m_solvingBlockIndex; FactorizationFactorizeL1StripeContext *factorizingFactorizationContext = ref_workerContext.m_factorizingFactorizationContext; const unsigned int solvingBlockStep = FSL1S_BLOCK_SIZE; const unsigned factorizingBlockARows = FFL1S_REGULAR_A_ROWS; unsigned factorizingBlockCount = deriveScalingAndFactorizingL1StripeBlockCountFromSolvingBlockIndex(solvingBlockIndex, solvingBlockStep, factorizingBlockARows); unsigned blockFactorizingThreadCount = deriveScalingAndFactorizingL1StripeThreadCount(factorizingBlockCount, ref_workerContext.m_allowedThreadCount); initializeCooperativelyScalingAndFactorizingL1Stripe_XMemoryStructures(factorizingFactorizationContext, blockFactorizingThreadCount); dCallReleaseeID blockFactorizingSyncReleasee; dxThreadingBase *threading = ref_workerContext.m_threading; if (solvingBlockIndex != ref_workerContext.m_totalBlockCount - 1) { threading->PostThreadedCall(NULL, &blockFactorizingSyncReleasee, blockFactorizingThreadCount, NULL, NULL, &factotLDLT_scalingAndFactorizingCompleteSync_callback, &ref_workerContext, 0, "FactorLDLT S'n'F Sync"); } else { blockFactorizingSyncReleasee = ref_workerContext.m_calculationFinishReleasee; if (blockFactorizingThreadCount > 1) { threading->AlterThreadedCallDependenciesCount(blockFactorizingSyncReleasee, blockFactorizingThreadCount - 1); } } if (blockFactorizingThreadCount > 1) { threading->PostThreadedCallsGroup(NULL, blockFactorizingThreadCount - 1, blockFactorizingSyncReleasee, &factotLDLT_scalingAndFactorizingComplete_callback, &ref_workerContext, "FactorLDLT S'n'F Complete"); } factotLDLT_scalingAndFactorizingComplete(ref_workerContext, blockFactorizingThreadCount - 1); threading->AlterThreadedCallDependenciesCount(blockFactorizingSyncReleasee, -1); } /*static */ int ThreadedEquationSolverLDLT::factotLDLT_scalingAndFactorizingComplete_callback(void *callContext, dcallindex_t callInstanceIndex, dCallReleaseeID dUNUSED(callThisReleasee)) { FactorLDLTWorkerContext *ptrContext = (FactorLDLTWorkerContext *)callContext; factotLDLT_scalingAndFactorizingComplete(*ptrContext, dCAST_TO_SMALLER(unsigned, callInstanceIndex)); return 1; } /*static */ void ThreadedEquationSolverLDLT::factotLDLT_scalingAndFactorizingComplete(FactorLDLTWorkerContext &ref_workerContext, unsigned ownThreadIndex) { unsigned factorizationRow = ref_workerContext.m_solvingBlockIndex * FSL1S_BLOCK_SIZE; participateScalingAndFactorizingL1Stripe_X(ref_workerContext.m_ARow, ref_workerContext.m_d, factorizationRow, ref_workerContext.m_rowSkip, ref_workerContext.m_factorizingFactorizationContext, ownThreadIndex); } /*static */ int ThreadedEquationSolverLDLT::factotLDLT_scalingAndFactorizingCompleteSync_callback(void *callContext, dcallindex_t dUNUSED(callInstanceIndex), dCallReleaseeID dUNUSED(callThisReleasee)) { FactorLDLTWorkerContext *ptrContext = (FactorLDLTWorkerContext *)callContext; factotLDLT_scalingAndFactorizingCompleteSync(*ptrContext); return 1; } /*static */ void ThreadedEquationSolverLDLT::factotLDLT_scalingAndFactorizingCompleteSync(FactorLDLTWorkerContext &ref_workerContext) { ref_workerContext.incrementForNextBlock(); unsigned blockIndex = ref_workerContext.m_solvingBlockIndex; dIASSERT(blockIndex < ref_workerContext.m_totalBlockCount); atomicord32 &refSolvingBlockCompletionProgress = ref_workerContext.m_refSolvingBlockCompletionProgress; cellindexint *solvingBlockProgressDescriptors = ref_workerContext.m_solvingBlockProgressDescriptors; FactorizationSolveL1StripeCellContext *solvingCellContexts = ref_workerContext.m_solvingCellContexts; initializeCooperativelySolvingL1Stripe_XMemoryStructures(blockIndex, refSolvingBlockCompletionProgress, solvingBlockProgressDescriptors, solvingCellContexts); unsigned blockSolvingThreadCount = deriveSolvingL1StripeThreadCount(blockIndex, ref_workerContext.m_allowedThreadCount); dCallReleaseeID blockSolvingSyncReleasee; dxThreadingBase *threading = ref_workerContext.m_threading; if (blockIndex != ref_workerContext.m_totalBlockCount - 1 || ref_workerContext.m_rowCount % FSL1S_REGULAR_B_ROWS == 0) { threading->PostThreadedCall(NULL, &blockSolvingSyncReleasee, blockSolvingThreadCount, NULL, NULL, &factotLDLT_solvingCompleteSync_callback, &ref_workerContext, 0, "FactorLDLT Solving Complete Sync"); if (blockSolvingThreadCount > 1) { threading->PostThreadedCallsGroup(NULL, blockSolvingThreadCount - 1, blockSolvingSyncReleasee, &factotLDLT_solvingComplete_callback, &ref_workerContext, "FactorLDLT Solving Complete"); } factotLDLT_solvingComplete(ref_workerContext, blockSolvingThreadCount - 1); } else { dSASSERT(FSL1S_REGULAR_B_ROWS == 2); dSASSERT(FSL1S_FINAL_B_ROWS == 1); threading->PostThreadedCall(NULL, &blockSolvingSyncReleasee, blockSolvingThreadCount, NULL, NULL, &factotLDLT_solvingFinalSync_callback, &ref_workerContext, 0, "FactorLDLT Solving Final Sync"); if (blockSolvingThreadCount > 1) { threading->PostThreadedCallsGroup(NULL, blockSolvingThreadCount - 1, blockSolvingSyncReleasee, &factotLDLT_solvingFinal_callback, &ref_workerContext, "FactorLDLT Solving Final"); } factotLDLT_solvingFinal(ref_workerContext, blockSolvingThreadCount - 1); } threading->AlterThreadedCallDependenciesCount(blockSolvingSyncReleasee, -1); } /*static */ int ThreadedEquationSolverLDLT::factotLDLT_solvingFinal_callback(void *callContext, dcallindex_t callInstanceIndex, dCallReleaseeID dUNUSED(callThisReleasee)) { FactorLDLTWorkerContext *ptrContext = (FactorLDLTWorkerContext *)callContext; factotLDLT_solvingFinal(*ptrContext, dCAST_TO_SMALLER(unsigned, callInstanceIndex)); return 1; } /*static */ void ThreadedEquationSolverLDLT::factotLDLT_solvingFinal(FactorLDLTWorkerContext &ref_context, unsigned ownThreadIndex) { participateSolvingL1Stripe_X(ref_context.m_A, ref_context.m_ARow, ref_context.m_solvingBlockIndex, ref_context.m_rowSkip, ref_context.m_refSolvingBlockCompletionProgress, ref_context.m_solvingBlockProgressDescriptors, ref_context.m_solvingCellContexts, ownThreadIndex); } /*static */ int ThreadedEquationSolverLDLT::factotLDLT_solvingFinalSync_callback(void *callContext, dcallindex_t dUNUSED(callInstanceIndex), dCallReleaseeID dUNUSED(callThisReleasee)) { FactorLDLTWorkerContext *ptrContext = (FactorLDLTWorkerContext *)callContext; factotLDLT_solvingFinalSync(*ptrContext); return 1; } /*static */ void ThreadedEquationSolverLDLT::factotLDLT_solvingFinalSync(FactorLDLTWorkerContext &ref_workerContext) { unsigned solvingBlockIndex = ref_workerContext.m_solvingBlockIndex; FactorizationFactorizeL1StripeContext *factorizingFactorizationContext = ref_workerContext.m_factorizingFactorizationContext; const unsigned int solvingBlockStep = FSL1S_BLOCK_SIZE; const unsigned factorizingBlockARows = FFL1S_FINAL_A_ROWS; unsigned factorizingBlockCount = deriveScalingAndFactorizingL1StripeBlockCountFromSolvingBlockIndex(solvingBlockIndex, solvingBlockStep, factorizingBlockARows); unsigned blockFactorizingThreadCount = deriveScalingAndFactorizingL1StripeThreadCount(factorizingBlockCount, ref_workerContext.m_allowedThreadCount); initializeCooperativelyScalingAndFactorizingL1Stripe_XMemoryStructures(factorizingFactorizationContext, blockFactorizingThreadCount); dCallReleaseeID blockFactorizingSyncReleasee = ref_workerContext.m_calculationFinishReleasee; dIASSERT(solvingBlockIndex == ref_workerContext.m_totalBlockCount - 1); dxThreadingBase *threading = ref_workerContext.m_threading; if (blockFactorizingThreadCount > 1) { threading->AlterThreadedCallDependenciesCount(blockFactorizingSyncReleasee, blockFactorizingThreadCount - 1); threading->PostThreadedCallsGroup(NULL, blockFactorizingThreadCount - 1, blockFactorizingSyncReleasee, &factotLDLT_scalingAndFactorizingFinal_callback, &ref_workerContext, "FactorLDLT S'n'F Final"); } factotLDLT_scalingAndFactorizingFinal(ref_workerContext, blockFactorizingThreadCount - 1); threading->AlterThreadedCallDependenciesCount(blockFactorizingSyncReleasee, -1); } /*static */ int ThreadedEquationSolverLDLT::factotLDLT_scalingAndFactorizingFinal_callback(void *callContext, dcallindex_t callInstanceIndex, dCallReleaseeID dUNUSED(callThisReleasee)) { FactorLDLTWorkerContext *ptrContext = (FactorLDLTWorkerContext *)callContext; factotLDLT_scalingAndFactorizingFinal(*ptrContext, dCAST_TO_SMALLER(unsigned, callInstanceIndex)); return 1; } /*static */ void ThreadedEquationSolverLDLT::factotLDLT_scalingAndFactorizingFinal(FactorLDLTWorkerContext &ref_workerContext, unsigned ownThreadIndex) { unsigned factorizationRow = ref_workerContext.m_solvingBlockIndex * FSL1S_BLOCK_SIZE; participateScalingAndFactorizingL1Stripe_X(ref_workerContext.m_ARow, ref_workerContext.m_d, factorizationRow, ref_workerContext.m_rowSkip, ref_workerContext.m_factorizingFactorizationContext, ownThreadIndex); } /*static */ int ThreadedEquationSolverLDLT::factotLDLT_completion_callback(void *dUNUSED(callContext), dcallindex_t dUNUSED(callInstanceIndex), dCallReleaseeID dUNUSED(callThisReleasee)) { // Do nothing return 1; } ////////////////////////////////////////////////////////////////////////// // Public interface functions /*extern ODE_API */ void dFactorLDLT(dReal *A, dReal *d, int n, int nskip1) { factorMatrixAsLDLT<1>(A, d, n, nskip1); } /*extern ODE_API */ void dEstimateCooperativelyFactorLDLTResourceRequirements(dResourceRequirementsID requirements, unsigned maximalAllowedThreadCount, unsigned maximalRowCount) { dAASSERT(requirements != NULL); dxResourceRequirementDescriptor *requirementsDescriptor = (dxResourceRequirementDescriptor *)requirements; ThreadedEquationSolverLDLT::estimateCooperativeFactoringLDLTResourceRequirements(requirementsDescriptor, maximalAllowedThreadCount, maximalRowCount); } /*extern ODE_API */ void dCooperativelyFactorLDLT(dResourceContainerID resources, unsigned allowedThreadCount, dReal *A, dReal *d, unsigned rowCount, unsigned rowSkip) { dAASSERT(resources != NULL); dxRequiredResourceContainer *resourceContainer = (dxRequiredResourceContainer *)resources; ThreadedEquationSolverLDLT::cooperativelyFactorLDLT(resourceContainer, allowedThreadCount, A, d, rowCount, rowSkip); } ode-0.16/ode/src/collision_trimesh_opcode.h0000664000175200017520000002516113403272463015735 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ // TriMesh code by Erwin de Vries. // Modified for FreeSOLID Compatibility by Rodrigo Hernandez // Trimesh caches separation by Oleh Derevenko // TriMesh storage classes refactoring and face angle computation code by Oleh Derevenko (C) 2016-2017 #ifndef _ODE_COLLISION_TRIMESH_OPCODE_H_ #define _ODE_COLLISION_TRIMESH_OPCODE_H_ #if dTRIMESH_ENABLED && dTRIMESH_OPCODE //**************************************************************************** // dxTriMesh class #include "collision_kernel.h" #include "collision_trimesh_colliders.h" #include "collision_util.h" #include #include "collision_trimesh_internal.h" #define BAN_OPCODE_AUTOLINK #include "Opcode.h" using namespace Opcode; #if !dTRIMESH_OPCODE_USE_OLD_TRIMESH_TRIMESH_COLLIDER // New trimesh collider hash table types enum { MAXCONTACT_X_NODE = 4, CONTACTS_HASHSIZE = 256 }; struct CONTACT_KEY { dContactGeom * m_contact; unsigned int m_key; }; struct CONTACT_KEY_HASH_NODE { CONTACT_KEY m_keyarray[MAXCONTACT_X_NODE]; int m_keycount; }; struct CONTACT_KEY_HASH_TABLE { public: CONTACT_KEY_HASH_NODE &operator[](unsigned int index) { return m_storage[index]; } private: CONTACT_KEY_HASH_NODE m_storage[CONTACTS_HASHSIZE]; }; #endif // !dTRIMESH_OPCODE_USE_OLD_TRIMESH_TRIMESH_COLLIDER struct VertexUseCache { public: VertexUseCache(): m_VertexUseBits(NULL), m_VertexUseElements(0) {} ~VertexUseCache() { freeVertexUSEDFlags(); } bool resizeAndResetVertexUSEDFlags(unsigned VertexCount) { bool Result = false; sizeint VertexNewElements = (VertexCount + 7) / 8; if (VertexNewElements <= m_VertexUseElements || reallocVertexUSEDFlags(VertexNewElements)) { memset(m_VertexUseBits, 0, VertexNewElements); Result = true; } return Result; } bool getVertexUSEDFlag(unsigned VertexIndex) const { return (m_VertexUseBits[VertexIndex / 8] & (1 << (VertexIndex % 8))) != 0; } void setVertexUSEDFlag(unsigned VertexIndex) { m_VertexUseBits[VertexIndex / 8] |= (1 << (VertexIndex % 8)); } private: bool reallocVertexUSEDFlags(sizeint VertexNewElements) { bool Result = false; uint8 *VertexNewBits = (uint8 *)dRealloc(m_VertexUseBits, m_VertexUseElements * sizeof(m_VertexUseBits[0]), VertexNewElements * sizeof(m_VertexUseBits[0])); if (VertexNewBits) { m_VertexUseBits = VertexNewBits; m_VertexUseElements = VertexNewElements; Result = true; } return Result; } void freeVertexUSEDFlags() { dFree(m_VertexUseBits, m_VertexUseElements * sizeof(m_VertexUseBits[0])); m_VertexUseBits = NULL; m_VertexUseElements = 0; } private: uint8 *m_VertexUseBits; sizeint m_VertexUseElements; }; struct TrimeshCollidersCache { TrimeshCollidersCache() { initOPCODECaches(); } void initOPCODECaches(); void clearOPCODECaches(); // Collider caches BVTCache ColCache; #if !dTRIMESH_OPCODE_USE_OLD_TRIMESH_TRIMESH_COLLIDER CONTACT_KEY_HASH_TABLE m_hashcontactset; #endif // Colliders /* -- not used -- also uncomment in InitOPCODECaches() PlanesCollider _PlanesCollider; -- not used */ SphereCollider m_SphereCollider; OBBCollider m_OBBCollider; RayCollider m_RayCollider; AABBTreeCollider m_AABBTreeCollider; /* -- not used -- also uncomment in InitOPCODECaches() LSSCollider _LSSCollider; */ // Trimesh caches CollisionFaces m_Faces; SphereCache m_DefaultSphereCache; OBBCache m_DefaultBoxCache; LSSCache m_DefaultCapsuleCache; // Trimesh-plane collision vertex use cache VertexUseCache m_VertexUses; }; typedef dxTriDataBase dxTriMeshData_Parent; struct dxTriMeshData: public dxTriMeshData_Parent { public: dxTriMeshData(): dxTriMeshData_Parent(), m_ExternalUseFlags(NULL), m_InternalUseFlags(NULL) { } ~dxTriMeshData(); void buildData(const Point *Vertices, int VertexStide, unsigned VertexCount, const IndexedTriangle *Indices, unsigned IndexCount, int TriStride, const dReal *in_Normals, bool Single); private: void calculateDataAABB(dVector3 &AABBMax, dVector3 &AABBMin); template void templateCalculateDataAABB(dVector3 &AABBMax, dVector3 &AABBMin); public: /* Setup the UseFlags array and/or build face angles*/ bool preprocessData(bool buildUseFlags/*=false*/, FaceAngleStorageMethod faceAndgesRequirement/*=ASM__INVALID*/); private: bool meaningfulPreprocessData(bool buildUseFlags/*=false*/, FaceAngleStorageMethod faceAndgesRequirement/*=ASM__INVALID*/); public: /* For when app changes the vertices */ void updateData(); public: const Point *retrieveVertexInstances() const { return (const Point *)dxTriMeshData_Parent::retrieveVertexInstances(); } public: void assignNormals(const dReal *normals) { dxTriMeshData_Parent::assignNormals(normals); } const dReal *retrieveNormals() const { return (const dReal *)dxTriMeshData_Parent::retrieveNormals(); } sizeint calculateNormalsMemoryRequirement() const { return retrieveTriangleCount() * (sizeof(dReal) * dSA__MAX); } public: void assignExternalUseFlagsBuffer(uint8 *buffer) { m_ExternalUseFlags = buffer != m_InternalUseFlags ? buffer : NULL; } const uint8 *smartRetrieveUseFlags() const { return m_ExternalUseFlags != NULL ? m_ExternalUseFlags : m_InternalUseFlags; } bool haveUseFlagsBeenBuilt() const { return m_InternalUseFlags != NULL; } sizeint calculateUseFlagsMemoryRequirement() const { return m_Mesh.GetNbTriangles() * sizeof(m_InternalUseFlags[0]); } public: Model m_BVTree; MeshInterface m_Mesh; /* aabb in model space */ dVector3 m_AABBCenter; dVector3 m_AABBExtents; // data for use in collision resolution uint8 *m_ExternalUseFlags; uint8 *m_InternalUseFlags; }; typedef dxMeshBase dxTriMesh_Parent; struct dxTriMesh: public dxTriMesh_Parent { public: // Functions dxTriMesh(dxSpace *Space, dxTriMeshData *Data, dTriCallback *Callback, dTriArrayCallback *ArrayCallback, dTriRayCallback *RayCallback): dxTriMesh_Parent(Space, Data, Callback, ArrayCallback, RayCallback, false) { m_SphereContactsMergeOption = (dxContactMergeOptions)MERGE_NORMALS__SPHERE_DEFAULT; dZeroMatrix4(m_last_trans); } ~dxTriMesh(); void clearTCCache(); bool controlGeometry(int controlClass, int controlCode, void *dataValue, int *dataSize); virtual void computeAABB(); public: dxTriMeshData *retrieveMeshData() const { return getMeshData(); } const dReal *retrieveMeshNormals() const { return getMeshData()->retrieveNormals(); } Model &retrieveMeshBVTreeRef() const { return getMeshData()->m_BVTree; } const uint8 *retrieveMeshSmartUseFlags() const { return getMeshData()->smartRetrieveUseFlags(); } unsigned getMeshTriangleCount() const { return getMeshData()->m_Mesh.GetNbTriangles(); } void fetchMeshTransformedTriangle(dVector3 *const pout_triangle[3], unsigned index)/* const*/; void fetchMeshTransformedTriangle(dVector3 out_triangle[3], unsigned index)/* const*/; void fetchMeshTriangle(dVector3 *const pout_triangle[3], unsigned index, const dVector3 position, const dMatrix3 rotation) const; void fetchMeshTriangle(dVector3 out_triangle[3], unsigned index, const dVector3 position, const dMatrix3 rotation) const; public: void assignLastTransform(const dMatrix4 last_trans) { dCopyMatrix4x4(m_last_trans, last_trans); } const dReal *retrieveLastTransform() const { return m_last_trans; } private: enum { MERGE_NORMALS__SPHERE_DEFAULT = DONT_MERGE_CONTACTS }; bool controlGeometry_SetMergeSphereContacts(int dataValue); bool controlGeometry_GetMergeSphereContacts(int &returnValue); private: dxTriMeshData *getMeshData() const { return static_cast(dxTriMesh_Parent::getMeshData()); } public: // Some constants // Temporal coherence struct SphereTC : public SphereCache{ dxGeom* Geom; }; struct BoxTC : public OBBCache{ dxGeom* Geom; }; struct CapsuleTC : public LSSCache{ dxGeom* Geom; }; public: // Contact merging option dxContactMergeOptions m_SphereContactsMergeOption; // Instance data for last transform. dMatrix4 m_last_trans; dArray m_SphereTCCache; dArray m_BoxTCCache; dArray m_CapsuleTCCache; }; static inline Matrix4x4 &MakeMatrix(const dVector3 Position, const dMatrix3 Rotation, Matrix4x4 &Out) { return Out.Set( Rotation[0], Rotation[4], Rotation[8], 0.0f, Rotation[1], Rotation[5], Rotation[9], 0.0f, Rotation[2], Rotation[6], Rotation[10],0.0f, Position[0], Position[1], Position[2], 1.0f); } static inline Matrix4x4 &MakeMatrix(dxGeom* g, Matrix4x4 &Out) { const dVector3 &position = g->buildUpdatedPosition(); const dMatrix3 &rotation = g->buildUpdatedRotation(); return MakeMatrix(position, rotation, Out); } #endif // #if dTRIMESH_ENABLED && dTRIMESH_OPCODE #endif //_ODE_COLLISION_TRIMESH_OPCODE_H_ ode-0.16/ode/src/Makefile.in0000664000175200017520000012516013403272663012554 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ ################################### # O U S T U F F ################################### @ENABLE_OU_TRUE@am__append_1 = -I$(top_srcdir)/ou/include @ENABLE_OU_TRUE@am__append_2 = $(top_builddir)/ou/src/ou/libou.la @ENABLE_OU_TRUE@am__append_3 = odetls.cpp odetls.h \ @ENABLE_OU_TRUE@ odeou.cpp odeou.h ################################### # G I M P A C T S T U F F ################################### @GIMPACT_TRUE@am__append_4 = -DdTRIMESH_ENABLED -DdTRIMESH_GIMPACT -I$(top_srcdir)/GIMPACT/include @GIMPACT_TRUE@am__append_5 = $(top_builddir)/GIMPACT/src/libGIMPACT.la @GIMPACT_TRUE@am__append_6 = collision_trimesh_gimpact.cpp \ @GIMPACT_TRUE@ collision_trimesh_internal.cpp collision_trimesh_internal_impl.h \ @GIMPACT_TRUE@ gimpact_contact_export_helper.cpp gimpact_contact_export_helper.h \ @GIMPACT_TRUE@ gimpact_gim_contact_accessor.h \ @GIMPACT_TRUE@ gimpact_plane_contact_accessor.h \ @GIMPACT_TRUE@ collision_trimesh_trimesh.cpp \ @GIMPACT_TRUE@ collision_trimesh_sphere.cpp \ @GIMPACT_TRUE@ collision_trimesh_ray.cpp \ @GIMPACT_TRUE@ collision_trimesh_box.cpp \ @GIMPACT_TRUE@ collision_trimesh_ccylinder.cpp \ @GIMPACT_TRUE@ collision_trimesh_internal.h \ @GIMPACT_TRUE@ collision_cylinder_trimesh.cpp \ @GIMPACT_TRUE@ collision_trimesh_plane.cpp \ @GIMPACT_TRUE@ collision_convex_trimesh.cpp ################################# # O P C O D E S T U F F ################################# @OPCODE_TRUE@am__append_7 = -I$(top_srcdir)/OPCODE -I$(top_srcdir)/OPCODE/Ice -DdTRIMESH_ENABLED -DdTRIMESH_OPCODE @OPCODE_TRUE@am__append_8 = $(top_builddir)/OPCODE/libOPCODE.la \ @OPCODE_TRUE@ $(top_builddir)/OPCODE/Ice/libIce.la @OPCODE_TRUE@am__append_9 = collision_trimesh_opcode.cpp \ @OPCODE_TRUE@ collision_trimesh_internal.cpp collision_trimesh_internal_impl.h \ @OPCODE_TRUE@ collision_trimesh_trimesh.cpp \ @OPCODE_TRUE@ collision_trimesh_trimesh_old.cpp \ @OPCODE_TRUE@ collision_trimesh_sphere.cpp \ @OPCODE_TRUE@ collision_trimesh_ray.cpp \ @OPCODE_TRUE@ collision_trimesh_box.cpp \ @OPCODE_TRUE@ collision_trimesh_ccylinder.cpp \ @OPCODE_TRUE@ collision_trimesh_internal.h \ @OPCODE_TRUE@ collision_cylinder_trimesh.cpp \ @OPCODE_TRUE@ collision_trimesh_plane.cpp \ @OPCODE_TRUE@ collision_convex_trimesh.cpp @LIBCCD_TRUE@am__append_10 = -DdLIBCCD_ENABLED \ @LIBCCD_TRUE@ -I$(top_srcdir)/libccd/src/custom @LIBCCD_INTERNAL_TRUE@@LIBCCD_TRUE@am__append_11 = \ @LIBCCD_INTERNAL_TRUE@@LIBCCD_TRUE@ -I$(top_srcdir)/libccd/src \ @LIBCCD_INTERNAL_TRUE@@LIBCCD_TRUE@ -I$(top_builddir)/libccd/src \ @LIBCCD_INTERNAL_TRUE@@LIBCCD_TRUE@ -DdLIBCCD_INTERNAL @LIBCCD_INTERNAL_TRUE@@LIBCCD_TRUE@am__append_12 = $(top_builddir)/libccd/src/libccd.la @LIBCCD_INTERNAL_FALSE@@LIBCCD_TRUE@am__append_13 = $(CCD_CFLAGS) \ @LIBCCD_INTERNAL_FALSE@@LIBCCD_TRUE@ -DdLIBCCD_SYSTEM @LIBCCD_INTERNAL_FALSE@@LIBCCD_TRUE@am__append_14 = $(CCD_LIBS) @LIBCCD_TRUE@am__append_15 = collision_libccd.cpp collision_libccd.h @LIBCCD_BOX_CYL_TRUE@@LIBCCD_TRUE@am__append_16 = -DdLIBCCD_BOX_CYL @LIBCCD_CYL_CYL_TRUE@@LIBCCD_TRUE@am__append_17 = -DdLIBCCD_CYL_CYL @LIBCCD_CAP_CYL_TRUE@@LIBCCD_TRUE@am__append_18 = -DdLIBCCD_CAP_CYL @LIBCCD_CONVEX_BOX_TRUE@@LIBCCD_TRUE@am__append_19 = -DdLIBCCD_CONVEX_BOX @LIBCCD_CONVEX_CAP_TRUE@@LIBCCD_TRUE@am__append_20 = -DdLIBCCD_CONVEX_CAP @LIBCCD_CONVEX_CYL_TRUE@@LIBCCD_TRUE@am__append_21 = -DdLIBCCD_CONVEX_CYL @LIBCCD_CONVEX_SPHERE_TRUE@@LIBCCD_TRUE@am__append_22 = -DdLIBCCD_CONVEX_SPHERE @LIBCCD_CONVEX_CONVEX_TRUE@@LIBCCD_TRUE@am__append_23 = -DdLIBCCD_CONVEX_CONVEX subdir = ode/src ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = @LIBCCD_INTERNAL_FALSE@@LIBCCD_TRUE@am__DEPENDENCIES_2 = \ @LIBCCD_INTERNAL_FALSE@@LIBCCD_TRUE@ $(am__DEPENDENCIES_1) libode_la_DEPENDENCIES = joints/libjoints.la $(am__append_2) \ $(am__append_5) $(am__append_8) $(am__append_12) \ $(am__DEPENDENCIES_2) am__libode_la_SOURCES_DIST = nextafterf.c array.cpp array.h box.cpp \ capsule.cpp collision_cylinder_box.cpp \ collision_cylinder_plane.cpp collision_cylinder_sphere.cpp \ collision_kernel.cpp collision_kernel.h \ collision_quadtreespace.cpp collision_sapspace.cpp \ collision_space.cpp collision_space_internal.h collision_std.h \ collision_transform.cpp collision_transform.h \ collision_trimesh_colliders.h collision_trimesh_disabled.cpp \ collision_trimesh_internal.h collision_trimesh_opcode.h \ collision_trimesh_gimpact.h collision_util.cpp \ collision_util.h common.h convex.cpp coop_matrix_types.h \ cylinder.cpp default_threading.cpp default_threading.h \ error.cpp error.h export-dif.cpp fastdot.cpp fastdot_impl.h \ fastldltfactor.cpp fastldltfactor_impl.h fastldltsolve.cpp \ fastldltsolve_impl.h fastlsolve.cpp fastlsolve_impl.h \ fastltsolve.cpp fastltsolve_impl.h fastvecscale.cpp \ fastvecscale_impl.h heightfield.cpp heightfield.h lcp.cpp \ lcp.h mass.cpp mat.cpp mat.h matrix.cpp matrix.h memory.cpp \ misc.cpp objects.cpp objects.h obstack.cpp obstack.h ode.cpp \ odeinit.cpp odemath.cpp odemath.h odeou.h odetls.h plane.cpp \ quickstep.cpp quickstep.h ray.cpp resource_control.cpp \ resource_control.h rotation.cpp simple_cooperative.cpp \ simple_cooperative.h sphere.cpp step.cpp step.h timer.cpp \ threaded_solver_ldlt.h threading_atomics_provs.h \ threading_base.cpp threading_base.h threading_fake_sync.h \ threading_impl.cpp threading_impl.h threading_impl_posix.h \ threading_impl_templates.h threading_impl_win.h \ threading_pool_posix.cpp threading_pool_win.cpp \ threadingutils.h typedefs.h util.cpp util.h odetls.cpp \ odeou.cpp collision_trimesh_gimpact.cpp \ collision_trimesh_internal.cpp \ collision_trimesh_internal_impl.h \ gimpact_contact_export_helper.cpp \ gimpact_contact_export_helper.h gimpact_gim_contact_accessor.h \ gimpact_plane_contact_accessor.h collision_trimesh_trimesh.cpp \ collision_trimesh_sphere.cpp collision_trimesh_ray.cpp \ collision_trimesh_box.cpp collision_trimesh_ccylinder.cpp \ collision_cylinder_trimesh.cpp collision_trimesh_plane.cpp \ collision_convex_trimesh.cpp collision_trimesh_opcode.cpp \ collision_trimesh_trimesh_old.cpp collision_libccd.cpp \ collision_libccd.h @ENABLE_OU_TRUE@am__objects_1 = odetls.lo odeou.lo @GIMPACT_TRUE@am__objects_2 = collision_trimesh_gimpact.lo \ @GIMPACT_TRUE@ collision_trimesh_internal.lo \ @GIMPACT_TRUE@ gimpact_contact_export_helper.lo \ @GIMPACT_TRUE@ collision_trimesh_trimesh.lo \ @GIMPACT_TRUE@ collision_trimesh_sphere.lo \ @GIMPACT_TRUE@ collision_trimesh_ray.lo \ @GIMPACT_TRUE@ collision_trimesh_box.lo \ @GIMPACT_TRUE@ collision_trimesh_ccylinder.lo \ @GIMPACT_TRUE@ collision_cylinder_trimesh.lo \ @GIMPACT_TRUE@ collision_trimesh_plane.lo \ @GIMPACT_TRUE@ collision_convex_trimesh.lo @OPCODE_TRUE@am__objects_3 = collision_trimesh_opcode.lo \ @OPCODE_TRUE@ collision_trimesh_internal.lo \ @OPCODE_TRUE@ collision_trimesh_trimesh.lo \ @OPCODE_TRUE@ collision_trimesh_trimesh_old.lo \ @OPCODE_TRUE@ collision_trimesh_sphere.lo \ @OPCODE_TRUE@ collision_trimesh_ray.lo collision_trimesh_box.lo \ @OPCODE_TRUE@ collision_trimesh_ccylinder.lo \ @OPCODE_TRUE@ collision_cylinder_trimesh.lo \ @OPCODE_TRUE@ collision_trimesh_plane.lo \ @OPCODE_TRUE@ collision_convex_trimesh.lo @LIBCCD_TRUE@am__objects_4 = collision_libccd.lo am_libode_la_OBJECTS = nextafterf.lo array.lo box.lo capsule.lo \ collision_cylinder_box.lo collision_cylinder_plane.lo \ collision_cylinder_sphere.lo collision_kernel.lo \ collision_quadtreespace.lo collision_sapspace.lo \ collision_space.lo collision_transform.lo \ collision_trimesh_disabled.lo collision_util.lo convex.lo \ cylinder.lo default_threading.lo error.lo export-dif.lo \ fastdot.lo fastldltfactor.lo fastldltsolve.lo fastlsolve.lo \ fastltsolve.lo fastvecscale.lo heightfield.lo lcp.lo mass.lo \ mat.lo matrix.lo memory.lo misc.lo objects.lo obstack.lo \ ode.lo odeinit.lo odemath.lo plane.lo quickstep.lo ray.lo \ resource_control.lo rotation.lo simple_cooperative.lo \ sphere.lo step.lo timer.lo threading_base.lo threading_impl.lo \ threading_pool_posix.lo threading_pool_win.lo util.lo \ $(am__objects_1) $(am__objects_2) $(am__objects_3) \ $(am__objects_4) libode_la_OBJECTS = $(am_libode_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libode_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(libode_la_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) AM_V_CXX = $(am__v_CXX_@AM_V@) am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = SOURCES = $(libode_la_SOURCES) DIST_SOURCES = $(am__libode_la_SOURCES_DIST) RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ $(LISP)config.h.in # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \ $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CCD_CFLAGS = @CCD_CFLAGS@ CCD_LIBS = @CCD_LIBS@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXTRA_LIBTOOL_LDFLAGS = @EXTRA_LIBTOOL_LDFLAGS@ FGREP = @FGREP@ GL_LIBS = @GL_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSTDCXX = @LIBSTDCXX@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ ODE_PRECISION = @ODE_PRECISION@ ODE_VERSION = @ODE_VERSION@ ODE_VERSION_INFO = @ODE_VERSION_INFO@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ WINDRES = @WINDRES@ X11_CFLAGS = @X11_CFLAGS@ X11_LIBS = @X11_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_WINDRES = @ac_ct_WINDRES@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = joints AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include \ -D__ODE__ $(am__append_1) $(am__append_4) $(am__append_7) \ $(am__append_10) $(am__append_11) $(am__append_13) \ $(am__append_16) $(am__append_17) $(am__append_18) \ $(am__append_19) $(am__append_20) $(am__append_21) \ $(am__append_22) $(am__append_23) lib_LTLIBRARIES = libode.la libode_la_LDFLAGS = @EXTRA_LIBTOOL_LDFLAGS@ @ODE_VERSION_INFO@ libode_la_LIBADD = joints/libjoints.la $(am__append_2) $(am__append_5) \ $(am__append_8) $(am__append_12) $(am__append_14) # please, let's keep the filenames sorted libode_la_SOURCES = nextafterf.c array.cpp array.h box.cpp capsule.cpp \ collision_cylinder_box.cpp collision_cylinder_plane.cpp \ collision_cylinder_sphere.cpp collision_kernel.cpp \ collision_kernel.h collision_quadtreespace.cpp \ collision_sapspace.cpp collision_space.cpp \ collision_space_internal.h collision_std.h \ collision_transform.cpp collision_transform.h \ collision_trimesh_colliders.h collision_trimesh_disabled.cpp \ collision_trimesh_internal.h collision_trimesh_opcode.h \ collision_trimesh_gimpact.h collision_util.cpp \ collision_util.h common.h convex.cpp coop_matrix_types.h \ cylinder.cpp default_threading.cpp default_threading.h \ error.cpp error.h export-dif.cpp fastdot.cpp fastdot_impl.h \ fastldltfactor.cpp fastldltfactor_impl.h fastldltsolve.cpp \ fastldltsolve_impl.h fastlsolve.cpp fastlsolve_impl.h \ fastltsolve.cpp fastltsolve_impl.h fastvecscale.cpp \ fastvecscale_impl.h heightfield.cpp heightfield.h lcp.cpp \ lcp.h mass.cpp mat.cpp mat.h matrix.cpp matrix.h memory.cpp \ misc.cpp objects.cpp objects.h obstack.cpp obstack.h ode.cpp \ odeinit.cpp odemath.cpp odemath.h odeou.h odetls.h plane.cpp \ quickstep.cpp quickstep.h ray.cpp resource_control.cpp \ resource_control.h rotation.cpp simple_cooperative.cpp \ simple_cooperative.h sphere.cpp step.cpp step.h timer.cpp \ threaded_solver_ldlt.h threading_atomics_provs.h \ threading_base.cpp threading_base.h threading_fake_sync.h \ threading_impl.cpp threading_impl.h threading_impl_posix.h \ threading_impl_templates.h threading_impl_win.h \ threading_pool_posix.cpp threading_pool_win.cpp \ threadingutils.h typedefs.h util.cpp util.h $(am__append_3) \ $(am__append_6) $(am__append_9) $(am__append_15) all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: .SUFFIXES: .c .cpp .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign ode/src/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign ode/src/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): config.h: stamp-h1 @test -f $@ || rm -f stamp-h1 @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status ode/src/config.h $(srcdir)/config.h.in: $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f stamp-h1 touch $@ distclean-hdr: -rm -f config.h stamp-h1 install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libode.la: $(libode_la_OBJECTS) $(libode_la_DEPENDENCIES) $(EXTRA_libode_la_DEPENDENCIES) $(AM_V_CXXLD)$(libode_la_LINK) -rpath $(libdir) $(libode_la_OBJECTS) $(libode_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/array.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/box.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/capsule.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collision_convex_trimesh.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collision_cylinder_box.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collision_cylinder_plane.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collision_cylinder_sphere.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collision_cylinder_trimesh.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collision_kernel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collision_libccd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collision_quadtreespace.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collision_sapspace.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collision_space.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collision_transform.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collision_trimesh_box.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collision_trimesh_ccylinder.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collision_trimesh_disabled.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collision_trimesh_gimpact.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collision_trimesh_internal.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collision_trimesh_opcode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collision_trimesh_plane.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collision_trimesh_ray.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collision_trimesh_sphere.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collision_trimesh_trimesh.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collision_trimesh_trimesh_old.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collision_util.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/convex.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cylinder.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/default_threading.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/error.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/export-dif.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fastdot.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fastldltfactor.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fastldltsolve.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fastlsolve.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fastltsolve.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fastvecscale.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpact_contact_export_helper.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/heightfield.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lcp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mass.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mat.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/matrix.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memory.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nextafterf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/objects.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/obstack.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/odeinit.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/odemath.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/odeou.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/odetls.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plane.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/quickstep.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ray.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/resource_control.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rotation.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/simple_cooperative.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sphere.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/step.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/threading_base.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/threading_impl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/threading_pool_posix.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/threading_pool_win.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< .cpp.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cpp.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cpp.lo: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile $(LTLIBRARIES) config.h installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(libdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ mostlyclean-am distclean: distclean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-hdr distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-libLTLIBRARIES install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-libLTLIBRARIES .MAKE: $(am__recursive_targets) all install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libLTLIBRARIES \ clean-libtool cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-hdr \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-libLTLIBRARIES install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ uninstall-libLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ode-0.16/ode/src/fastdot.cpp0000664000175200017520000000370013403272463012650 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* generated code, do not edit. */ #include #include "config.h" #include "matrix.h" #include "fastdot_impl.h" /*extern */ dReal dxDot (const dReal *a, const dReal *b, unsigned n) { return calculateLargeVectorDot<1>(a, b, n); } #undef dDot /*extern */ dReal dDot (const dReal *a, const dReal *b, int n) { return dxDot (a, b, n); } ode-0.16/ode/src/threaded_solver_ldlt.h0000664000175200017520000010451113403272463015044 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* * Equation System Threaded Solver * Copyright (c) 2017 Oleh Derevenko, odar@eleks.com (change all "a" to "e") */ #ifndef _ODE_THREADED_SOLVER_LDLT_H_ #define _ODE_THREADED_SOLVER_LDLT_H_ #include "coop_matrix_types.h" #include class dxThreadingBase; class dxResourceRequirementDescriptor; class dxRequiredResourceContainer; class ThreadedEquationSolverLDLT { public: static void estimateCooperativeFactoringLDLTResourceRequirements(dxResourceRequirementDescriptor *summaryRequirementsDescriptor, unsigned allowedThreadCount, unsigned rowCount); static void cooperativelyFactorLDLT(dxRequiredResourceContainer *resourceContainer, unsigned allowedThreadCount, dReal *A, dReal *d, unsigned rowCount, unsigned rowSkip); static void estimateCooperativeSolvingL1StraightResourceRequirements(dxResourceRequirementDescriptor *summaryRequirementsDescriptor, unsigned allowedThreadCount, unsigned rowCount); static void cooperativelySolveL1Straight(dxRequiredResourceContainer *resourceContainer, unsigned allowedThreadCount, const dReal *L, dReal *b, unsigned rowCount, unsigned rowSkip); static void estimateCooperativeSolvingL1TransposedResourceRequirements(dxResourceRequirementDescriptor *summaryRequirementsDescriptor, unsigned allowedThreadCount, unsigned rowCount); static void cooperativelySolveL1Transposed(dxRequiredResourceContainer *resourceContainer, unsigned allowedThreadCount, const dReal *L, dReal *b, unsigned rowCount, unsigned rowSkip); static void estimateCooperativeScalingVectorResourceRequirements(dxResourceRequirementDescriptor *summaryRequirementsDescriptor, unsigned allowedThreadCount, unsigned elementCount); static void cooperativelyScaleVector(dxRequiredResourceContainer *resourceContainer, unsigned allowedThreadCount, dReal *vectorData, const dReal *scaleData, unsigned elementCount); static void estimateCooperativeSolvingLDLTResourceRequirements(dxResourceRequirementDescriptor *summaryRequirementsDescriptor, unsigned allowedThreadCount, unsigned rowCount); static void cooperativelySolveLDLT(dxRequiredResourceContainer *resourceContainer, unsigned allowedThreadCount, const dReal *L, const dReal *d, dReal *b, unsigned rowCount, unsigned rowSkip); public: enum { ALLOCATION_DEFAULT_ALIGNMENT = COOP_THREAD_DATA_ALIGNMENT_SIZE, }; private: struct FactorizationSolveL1StripeCellContext; struct FactorizationFactorizeL1StripeThreadContext; enum { FLDLT_D_STRIDE = 1, FLDLT_COOPERATIVE_BLOCK_COUNT_MINIMUM = 5, FSL1S_BLOCK_SIZE = 2, FSL1S_REGULAR_B_ROWS = FSL1S_BLOCK_SIZE, FSL1S_FINAL_B_ROWS = 1, FFL1S_REGULAR_A_ROWS = FSL1S_BLOCK_SIZE, FFL1S_FINAL_A_ROWS = 1, FFL1S_REGULAR_BLOCK_SIZE = 16, // A suitable by magnitude number being a power of 2 and (naturally) not being divisible by 6 FFL1S_FINAL_BLOCK_SIZE = 32, // A suitable by magnitude number being a power of 2 and (naturally) not being divisible by 6 }; static unsigned restrictFactoringLDLTAllowedThreadCount( dxThreadingBase *threading, unsigned allowedThreadCount, unsigned rowCount); static void doEstimateCooperativeFactoringLDLTResourceRequirementsValidated( dxResourceRequirementDescriptor *summaryRequirementsDescriptor, unsigned allowedThreadCount, unsigned rowCount); static void doCooperativelyFactorLDLTValidated( dxRequiredResourceContainer *resourceContainer, unsigned allowedThreadCount, dReal *A, dReal *d, unsigned rowCount, unsigned rowSkip); static unsigned deriveSolvingL1StripeBlockCount(unsigned rowCount, unsigned blockStep) { return (rowCount + (blockStep - 1)) / blockStep; } struct FactorizationSolvingL1StripeMemoryEstimates { void assignData(sizeint descriptorSizeRequired, sizeint contextSizeRequired) { m_descriptorSizeRequired = descriptorSizeRequired; m_contextSizeRequired = contextSizeRequired; } sizeint m_descriptorSizeRequired; sizeint m_contextSizeRequired; }; static unsigned deriveSolvingL1StripeThreadCount(unsigned blockCount, unsigned allowedThreadCount) { dIASSERT(allowedThreadCount >= 1); unsigned maximumCount = blockCount / 2; return maximumCount >= allowedThreadCount ? allowedThreadCount : dMACRO_MAX(maximumCount, 1U); } static sizeint estimateCooperativelySolvingL1Stripe_XMemoryRequirement(unsigned blockCount, FactorizationSolvingL1StripeMemoryEstimates &ref_memoryEstimates) { sizeint descriptorSizeRequired = dOVERALIGNED_SIZE(sizeof(cellindexint) * blockCount, COOP_THREAD_DATA_ALIGNMENT_SIZE); sizeint contextSizeRequired = dOVERALIGNED_SIZE(sizeof(FactorizationSolveL1StripeCellContext) * (CCI__MAX + 1) * blockCount, COOP_THREAD_DATA_ALIGNMENT_SIZE); ref_memoryEstimates.assignData(descriptorSizeRequired, contextSizeRequired); sizeint totalSizeRequired = descriptorSizeRequired + contextSizeRequired; return totalSizeRequired; } static void *markCooperativelySolvingL1Stripe_XMemoryStructuresOut(void *buffer, const FactorizationSolvingL1StripeMemoryEstimates &memoryEstimates, cellindexint *&out_blockProgressDescriptors, FactorizationSolveL1StripeCellContext *&out_cellContexts) { void *currentLocation = buffer; out_blockProgressDescriptors = (cellindexint *)currentLocation; currentLocation = (uint8 *)currentLocation + memoryEstimates.m_descriptorSizeRequired; out_cellContexts = (FactorizationSolveL1StripeCellContext *)currentLocation; currentLocation = (uint8 *)currentLocation + memoryEstimates.m_contextSizeRequired; return currentLocation; } static void initializeCooperativelySolvingL1Stripe_XMemoryStructures(unsigned blockCount, atomicord32 &out_blockCompletionProgress, cellindexint *blockProgressDescriptors, FactorizationSolveL1StripeCellContext *dUNUSED(cellContexts)) { out_blockCompletionProgress = 0; memset(blockProgressDescriptors, 0, blockCount * sizeof(*blockProgressDescriptors)); } template static void participateSolvingL1Stripe_X(const dReal *L, dReal *B, unsigned blockCount, unsigned rowSkip, volatile atomicord32 &refBlockCompletionProgress/*=0*/, volatile cellindexint *blockProgressDescriptors/*=[blockCount]*/, FactorizationSolveL1StripeCellContext *cellContexts/*=[CCI__MAX x blockCount] + [blockCount]*/, unsigned ownThreadIndex); static unsigned deriveScalingAndFactorizingL1StripeBlockCountFromSolvingBlockIndex(unsigned solvingBlockIndex, unsigned solvingBlockStep, unsigned blockARows) { unsigned factorizingBlockSize = deriveScalingAndFactorizingL1StripeBlockSize(blockARows); return deriveScalingAndFactorizingL1StripeBlockCountFromFactorizationRow(solvingBlockIndex * solvingBlockStep, factorizingBlockSize); } static unsigned deriveScalingAndFactorizingL1StripeBlockCountFromFactorizationRow(unsigned factorizationRowIndex, unsigned factorizationBlockSize) { return (factorizationRowIndex + (factorizationBlockSize - 1)) / factorizationBlockSize; } static unsigned deriveScalingAndFactorizingL1StripeBlockSize(unsigned blockARows) { unsigned result = blockARows != 1 ? FFL1S_REGULAR_BLOCK_SIZE : FFL1S_FINAL_BLOCK_SIZE; dIASSERT(blockARows >= 1 && blockARows <= 2); return result; } static unsigned deriveScalingAndFactorizingL1StripeThreadCount(unsigned blockCount, unsigned allowedThreadCount) { dIASSERT(blockCount != 0); dIASSERT(allowedThreadCount >= 1); return dMACRO_MIN(blockCount, allowedThreadCount); } struct FactorizationFactorizeL1StripeContext; struct FactorizationScalingAndFactorizingL1StripeMemoryEstimates { void assignData(sizeint contextSizeRequired) { m_contextSizeRequired = contextSizeRequired; } sizeint m_contextSizeRequired; }; static sizeint estimateCooperativelyScalingAndFactorizingL1Stripe_XMemoryRequirement(unsigned factorizingMaximumThreads, FactorizationScalingAndFactorizingL1StripeMemoryEstimates &ref_memoryEstimates) { dIASSERT(factorizingMaximumThreads != 0); sizeint contextSizeRequired = dOVERALIGNED_SIZE(sizeof(FactorizationFactorizeL1StripeContext) + sizeof(FactorizationFactorizeL1StripeThreadContext) * (factorizingMaximumThreads - 1), COOP_THREAD_DATA_ALIGNMENT_SIZE); ref_memoryEstimates.assignData(contextSizeRequired); sizeint totalSizeRequired = contextSizeRequired; return totalSizeRequired; } static void *markCooperativelyScalingAndFactorizingL1Stripe_XMemoryStructuresOut(void *buffer, const FactorizationScalingAndFactorizingL1StripeMemoryEstimates &memoryEstimates, FactorizationFactorizeL1StripeContext *&out_factorizationContext) { void *currentLocation = buffer; out_factorizationContext = (FactorizationFactorizeL1StripeContext *)currentLocation; currentLocation = (uint8 *)currentLocation + memoryEstimates.m_contextSizeRequired; return currentLocation; } static void initializeCooperativelyScalingAndFactorizingL1Stripe_XMemoryStructures( FactorizationFactorizeL1StripeContext *factorizationContext, unsigned threadCount) { factorizationContext->initialize(threadCount); } template static void participateScalingAndFactorizingL1Stripe_X(dReal *ARow, dReal *d, unsigned factorizationRow, unsigned rowSkip, FactorizationFactorizeL1StripeContext *factorizationContext, unsigned ownThreadIndex); private: struct FactorLDLTWorkerContext { FactorLDLTWorkerContext(dxThreadingBase *threading, unsigned allowedThreadCount, dReal *A, dReal *d, unsigned totalBlockCount, unsigned rowCount, unsigned rowSkip, atomicord32 &ref_solvingBlockCompletionProgress, cellindexint *solvingBlockProgressDescriptors, FactorizationSolveL1StripeCellContext *solvingCellContexts, FactorizationFactorizeL1StripeContext *factorizingFactorizationContext, dCallReleaseeID calculationFinishReleasee): m_threading(threading), m_allowedThreadCount(allowedThreadCount), m_A(A), m_ARow(A), m_d(d), m_solvingBlockIndex(0), m_totalBlockCount(totalBlockCount), m_rowCount(rowCount), m_rowSkip(rowSkip), m_refSolvingBlockCompletionProgress(ref_solvingBlockCompletionProgress), m_solvingBlockProgressDescriptors(solvingBlockProgressDescriptors), m_solvingCellContexts(solvingCellContexts), m_factorizingFactorizationContext(factorizingFactorizationContext), m_calculationFinishReleasee(calculationFinishReleasee) { } void incrementForNextBlock() { const unsigned blockStep = FSL1S_BLOCK_SIZE; m_ARow += blockStep * m_rowSkip; m_solvingBlockIndex += 1; } dxThreadingBase *m_threading; unsigned m_allowedThreadCount; dReal *m_A; dReal *m_ARow; dReal *m_d; unsigned m_solvingBlockIndex; unsigned m_totalBlockCount; unsigned m_rowCount; unsigned m_rowSkip; atomicord32 &m_refSolvingBlockCompletionProgress; cellindexint *m_solvingBlockProgressDescriptors; FactorizationSolveL1StripeCellContext *m_solvingCellContexts; FactorizationFactorizeL1StripeContext *m_factorizingFactorizationContext; dCallReleaseeID m_calculationFinishReleasee; }; static int factotLDLT_solvingComplete_callback(void *callContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee); static void factotLDLT_solvingComplete(FactorLDLTWorkerContext &ref_context, unsigned ownThreadIndex); static int factotLDLT_solvingCompleteSync_callback(void *callContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee); static void factotLDLT_solvingCompleteSync(FactorLDLTWorkerContext &ref_workerContext); static int factotLDLT_scalingAndFactorizingComplete_callback(void *callContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee); static void factotLDLT_scalingAndFactorizingComplete(FactorLDLTWorkerContext &ref_workerContext, unsigned ownThreadIndex); static int factotLDLT_scalingAndFactorizingCompleteSync_callback(void *callContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee); static void factotLDLT_scalingAndFactorizingCompleteSync(FactorLDLTWorkerContext &ref_workerContext); static int factotLDLT_solvingFinal_callback(void *callContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee); static void factotLDLT_solvingFinal(FactorLDLTWorkerContext &ref_context, unsigned ownThreadIndex); static int factotLDLT_solvingFinalSync_callback(void *callContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee); static void factotLDLT_solvingFinalSync(FactorLDLTWorkerContext &ref_workerContext); static int factotLDLT_scalingAndFactorizingFinal_callback(void *callContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee); static void factotLDLT_scalingAndFactorizingFinal(FactorLDLTWorkerContext &ref_workerContext, unsigned ownThreadIndex); static int factotLDLT_completion_callback(void *callContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee); private: struct FactorizationSolveL1StripeCellContext { template static void initializePrecalculatedZs(dReal (&Z)[block_step][b_rows]) { Z[0][0] = 0; if (b_rows >= 2) { Z[0][1] = 0; } Z[1][0] = 0; if (b_rows >= 2) { Z[1][1] = 0; } dSASSERT(block_step == 2); dSASSERT(b_rows >= 1 && b_rows <= 2); } template void loadPrecalculatedZs(dReal (&Z)[block_step][b_rows]) const { dSASSERT(block_step <= dARRAY_SIZE(m_c)); dSASSERT(b_rows <= dARRAY_SIZE(m_c[0])); Z[0][0] = m_c[0][0]; if (b_rows >= 2) { Z[0][1] = m_c[0][1]; } Z[1][0] = m_c[1][0]; if (b_rows >= 2) { Z[1][1] = m_c[1][1]; } dSASSERT(block_step == 2); dSASSERT(b_rows >= 1 && b_rows <= 2); } template void storePrecalculatedZs(const dReal (&Z)[block_step][b_rows]) { dSASSERT(block_step <= dARRAY_SIZE(m_c)); dSASSERT(b_rows <= dARRAY_SIZE(m_c[0])); m_c[0][0] = Z[0][0]; if (b_rows >= 2) { m_c[0][1] = Z[0][1]; } m_c[1][0] = Z[1][0]; if (b_rows >= 2) { m_c[1][1] = Z[1][1]; } dSASSERT(block_step == 2); dSASSERT(b_rows >= 1 && b_rows <= 2); } dReal m_c[FSL1S_BLOCK_SIZE][FSL1S_REGULAR_B_ROWS]; // dReal m_reserved[4]; }; static FactorizationSolveL1StripeCellContext &buildBlockContextRef(FactorizationSolveL1StripeCellContext *cellContexts, unsigned blockIndex, CellContextInstance contextInstance) { return cellContexts[blockIndex * CCI__MAX + contextInstance]; } static FactorizationSolveL1StripeCellContext &buildResultContextRef(FactorizationSolveL1StripeCellContext *cellContexts, unsigned blockIndex, unsigned blockCount) { return cellContexts[blockCount * CCI__MAX + blockIndex]; } private: struct FactorizationFactorizeL1StripeThreadContext { template void assignDataSum(const dReal (&sameZ)[a_rows], const dReal (&mixedZ)[dMACRO_MAX(a_rows - 1, 1)], const FactorizationFactorizeL1StripeThreadContext &partialSumContext) { m_sameZ[0] = sameZ[0] + partialSumContext.m_sameZ[0]; if (a_rows >= 2) { m_sameZ[1] = sameZ[1] + partialSumContext.m_sameZ[1]; m_mixedZ[0] = mixedZ[0] + partialSumContext.m_mixedZ[0]; } } template void assignDataAlone(const dReal (&sameZ)[a_rows], const dReal (&mixedZ)[dMACRO_MAX(a_rows - 1, 1)]) { m_sameZ[0] = sameZ[0]; if (a_rows >= 2) { m_sameZ[1] = sameZ[1]; m_mixedZ[0] = mixedZ[0]; } } template void retrieveData(dReal (&out_sameZ)[a_rows], dReal (&out_mixedZ)[dMACRO_MAX(a_rows - 1, 1)]) const { out_sameZ[0] = m_sameZ[0]; if (a_rows >= 2) { out_sameZ[1] = m_sameZ[1]; out_mixedZ[0] = m_mixedZ[0]; } dAASSERT(a_rows >= 1 && a_rows <= 2); } dReal m_sameZ[FFL1S_REGULAR_A_ROWS]; dReal m_mixedZ[dMACRO_MAX(FFL1S_REGULAR_A_ROWS - 1, 1)]; dReal m_reserved[1]; // [5]; // for alignment }; struct FactorizationFactorizeL1StripeContext { void initialize(unsigned threadCount) { m_threadsRunning = threadCount; m_nextColumnIndex = 0; m_sumThreadIndex = 0; } atomicord32 m_threadsRunning; atomicord32 m_nextColumnIndex; volatile atomicord32 m_sumThreadIndex; atomicord32 m_reserved[1]; // [13]; // for alignment FactorizationFactorizeL1StripeThreadContext m_threadContexts[1]; // =[threadCount] }; private: struct SolveL1StraightCellContext; enum { SL1S_COOPERATIVE_BLOCK_COUNT_MINIMUM = 8, SL1S_B_STRIDE = 1, SL1S_BLOCK_SIZE = 4, }; static unsigned restrictSolvingL1StraightAllowedThreadCount( dxThreadingBase *threading, unsigned allowedThreadCount, unsigned rowCount); static void doEstimateCooperativeSolvingL1StraightResourceRequirementsValidated( dxResourceRequirementDescriptor *summaryRequirementsDescriptor, unsigned allowedThreadCount, unsigned rowCount); static void doCooperativelySolveL1StraightValidated( dxRequiredResourceContainer *resourceContainer, unsigned allowedThreadCount, const dReal *L, dReal *b, unsigned rowCount, unsigned rowSkip); static unsigned deriveSolvingL1StraightBlockCount(unsigned rowCount, unsigned blockStep) { return (rowCount + (blockStep - 1)) / blockStep; } struct SolvingL1StraightMemoryEstimates { void assignData(sizeint descriptorSizeRequired, sizeint contextSizeRequired) { m_descriptorSizeRequired = descriptorSizeRequired; m_contextSizeRequired = contextSizeRequired; } sizeint m_descriptorSizeRequired; sizeint m_contextSizeRequired; }; static unsigned deriveSolvingL1StraightThreadCount(unsigned blockCount, unsigned allowedThreadCount) { dIASSERT(allowedThreadCount >= 1); unsigned maximumCount = 1 + blockCount / SL1S_COOPERATIVE_BLOCK_COUNT_MINIMUM; return maximumCount >= allowedThreadCount ? allowedThreadCount : dMACRO_MAX(maximumCount, 1U); } template static sizeint estimateCooperativelySolvingL1StraightMemoryRequirement(unsigned rowCount, SolvingL1StraightMemoryEstimates &ref_solvingMemoryEstimates); static void *markCooperativelySolvingL1StraightMemoryStructuresOut(void *buffer, const SolvingL1StraightMemoryEstimates &solvingMemoryEstimates, cellindexint *&out_blockProgressDescriptors, SolveL1StraightCellContext *&out_cellContexts) { void *currentLocation = buffer; out_blockProgressDescriptors = (cellindexint *)currentLocation; currentLocation = (uint8 *)currentLocation + solvingMemoryEstimates.m_descriptorSizeRequired; out_cellContexts = (SolveL1StraightCellContext *)currentLocation; currentLocation = (uint8 *)currentLocation + solvingMemoryEstimates.m_contextSizeRequired; return currentLocation; } template static void initializeCooperativelySolveL1StraightMemoryStructures(unsigned rowCount, atomicord32 &out_blockCompletionProgress, cellindexint *blockProgressDescriptors, SolveL1StraightCellContext *cellContexts); template static void participateSolvingL1Straight(const dReal *L, dReal *B, unsigned rowCount, unsigned rowSkip, volatile atomicord32 &refBlockCompletionProgress/*=0*/, volatile cellindexint *blockProgressDescriptors/*=[blockCount]*/, SolveL1StraightCellContext *cellContexts/*=[CCI__MAX x blockCount] + [blockCount]*/, unsigned ownThreadIndex); private: struct SolveL1StraightWorkerContext { void init(const dReal *L, dReal *b, unsigned rowCount, unsigned rowSkip, atomicord32 &ref_blockCompletionProgress, cellindexint *blockProgressDescriptors, SolveL1StraightCellContext *cellContexts) { m_L = L; m_b = b; m_rowCount = rowCount; m_rowSkip = rowSkip; m_ptrBlockCompletionProgress = &ref_blockCompletionProgress; m_blockProgressDescriptors = blockProgressDescriptors; m_cellContexts = cellContexts; } const dReal *m_L; dReal *m_b; unsigned m_rowCount; unsigned m_rowSkip; atomicord32 *m_ptrBlockCompletionProgress; cellindexint *m_blockProgressDescriptors; SolveL1StraightCellContext *m_cellContexts; }; static int solveL1Straight_worker_callback(void *callContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee); static void solveL1Straight_worker(SolveL1StraightWorkerContext &ref_context, unsigned ownThreadIndex); static int solveL1Straight_completion_callback(void *callContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee); private: struct SolveL1StraightCellContext { template static void initializePrecalculatedZs(dReal (&Z)[block_step]) { std::fill(Z, Z + block_step, REAL(0.0)); } template void loadPrecalculatedZs(dReal (&Z)[block_step]) const { dSASSERT(block_step <= dARRAY_SIZE(m_c)); std::copy(m_c, m_c + block_step, Z); } template void storePrecalculatedZs(const dReal (&Z)[block_step]) { dSASSERT(block_step <= dARRAY_SIZE(m_c)); std::copy(Z, Z + block_step, m_c); } dReal m_c[SL1S_BLOCK_SIZE]; }; static SolveL1StraightCellContext &buildBlockContextRef(SolveL1StraightCellContext *cellContexts, unsigned blockIndex, CellContextInstance contextInstance) { return cellContexts[blockIndex * CCI__MAX + contextInstance]; } static SolveL1StraightCellContext &buildResultContextRef(SolveL1StraightCellContext *cellContexts, unsigned blockIndex, unsigned blockCount) { return cellContexts[blockCount * CCI__MAX + blockIndex]; } private: struct SolveL1TransposedCellContext; enum { SL1T_COOPERATIVE_BLOCK_COUNT_MINIMUM = SL1S_COOPERATIVE_BLOCK_COUNT_MINIMUM, SL1T_B_STRIDE = SL1S_B_STRIDE, SL1T_BLOCK_SIZE = 4, }; static unsigned restrictSolvingL1TransposedAllowedThreadCount( dxThreadingBase *threading, unsigned allowedThreadCount, unsigned rowCount); static void doEstimateCooperativeSolvingL1TransposedResourceRequirementsValidated( dxResourceRequirementDescriptor *summaryRequirementsDescriptor, unsigned allowedThreadCount, unsigned rowCount); static void doCooperativelySolveL1TransposedValidated( dxRequiredResourceContainer *resourceContainer, unsigned allowedThreadCount, const dReal *L, dReal *b, unsigned rowCount, unsigned rowSkip); static unsigned deriveSolvingL1TransposedBlockCount(unsigned rowCount, unsigned blockStep) { return (rowCount + (blockStep - 1)) / blockStep; } struct SolvingL1TransposedMemoryEstimates { void assignData(sizeint descriptorSizeRequired, sizeint contextSizeRequired) { m_descriptorSizeRequired = descriptorSizeRequired; m_contextSizeRequired = contextSizeRequired; } sizeint m_descriptorSizeRequired; sizeint m_contextSizeRequired; }; static unsigned deriveSolvingL1TransposedThreadCount(unsigned blockCount, unsigned allowedThreadCount) { dSASSERT(SL1T_COOPERATIVE_BLOCK_COUNT_MINIMUM + 0 == SL1S_COOPERATIVE_BLOCK_COUNT_MINIMUM); return deriveSolvingL1StraightThreadCount(blockCount, allowedThreadCount); } template static sizeint estimateCooperativelySolvingL1TransposedMemoryRequirement(unsigned rowCount, SolvingL1TransposedMemoryEstimates &ref_solvingMemoryEstimates); static void *markCooperativelySolvingL1TransposedMemoryStructuresOut(void *buffer, const SolvingL1TransposedMemoryEstimates &solvingMemoryEstimates, cellindexint *&out_blockProgressDescriptors, SolveL1TransposedCellContext *&out_cellContexts) { void *currentLocation = buffer; out_blockProgressDescriptors = (cellindexint *)currentLocation; currentLocation = (uint8 *)currentLocation + solvingMemoryEstimates.m_descriptorSizeRequired; out_cellContexts = (SolveL1TransposedCellContext *)currentLocation; currentLocation = (uint8 *)currentLocation + solvingMemoryEstimates.m_contextSizeRequired; return currentLocation; } template static void *allocateCooperativelySolveL1TransposedMemoryStructures(sizeint &out_sizeAllocated, unsigned rowCount, cellindexint *&out_blockProgressDescriptors, SolveL1TransposedCellContext *&out_cellContexts); template static void initializeCooperativelySolveL1TransposedMemoryStructures(unsigned rowCount, atomicord32 &out_blockCompletionProgress, cellindexint *blockProgressDescriptors, SolveL1TransposedCellContext *cellContexts); template static void participateSolvingL1Transposed(const dReal *L, dReal *B, unsigned rowCount, unsigned rowSkip, volatile atomicord32 &refBlockCompletionProgress/*=0*/, volatile cellindexint *blockProgressDescriptors/*=[blockCount]*/, SolveL1TransposedCellContext *cellContexts/*=[CCI__MAX x blockCount] + [blockCount]*/, unsigned ownThreadIndex); private: struct SolveL1TransposedWorkerContext { void init(const dReal *L, dReal *b, unsigned rowCount, unsigned rowSkip, atomicord32 &ref_blockCompletionProgress, cellindexint *blockProgressDescriptors, SolveL1TransposedCellContext *cellContexts) { m_L = L; m_b = b; m_rowCount = rowCount; m_rowSkip = rowSkip; m_ptrBlockCompletionProgress = &ref_blockCompletionProgress; m_blockProgressDescriptors = blockProgressDescriptors; m_cellContexts = cellContexts; } const dReal *m_L; dReal *m_b; unsigned m_rowCount; unsigned m_rowSkip; atomicord32 *m_ptrBlockCompletionProgress; cellindexint *m_blockProgressDescriptors; SolveL1TransposedCellContext *m_cellContexts; }; static int solveL1Transposed_worker_callback(void *callContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee); static void solveL1Transposed_worker(SolveL1TransposedWorkerContext &ref_context, unsigned ownThreadIndex); static int solveL1Transposed_completion_callback(void *callContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee); private: struct SolveL1TransposedCellContext { template static void initializePrecalculatedZs(dReal (&Z)[block_step]) { std::fill(Z, Z + block_step, REAL(0.0)); } template void loadPrecalculatedZs(dReal (&Z)[block_step]) const { dSASSERT(block_step <= dARRAY_SIZE(m_c)); std::copy(m_c, m_c + block_step, Z); } template void storePrecalculatedZs(const dReal (&Z)[block_step]) { dSASSERT(block_step <= dARRAY_SIZE(m_c)); std::copy(Z, Z + block_step, m_c); } dReal m_c[SL1T_BLOCK_SIZE]; }; static SolveL1TransposedCellContext &buildBlockContextRef(SolveL1TransposedCellContext *cellContexts, unsigned blockIndex, CellContextInstance contextInstance) { return cellContexts[blockIndex * CCI__MAX + contextInstance]; } static SolveL1TransposedCellContext &buildResultContextRef(SolveL1TransposedCellContext *cellContexts, unsigned blockIndex, unsigned blockCount) { return cellContexts[blockCount * CCI__MAX + blockIndex]; } private: enum { SV_A_STRIDE = 1, SV_D_STRIDE = 1, SV_BLOCK_SIZE = 128, SV_COOPERATIVE_BLOCK_COUNT_MINIMUM = 3, }; static unsigned restrictScalingVectorAllowedThreadCount( dxThreadingBase *threading, unsigned allowedThreadCount, unsigned elementCount); static void doEstimateCooperativeScalingVectorResourceRequirementsValidated( dxResourceRequirementDescriptor *summaryRequirementsDescriptor, unsigned allowedThreadCount, unsigned elementCount); static void doCooperativelyScaleVectorValidated(dxRequiredResourceContainer *resourceContainer, unsigned allowedThreadCount, dReal *vectorData, const dReal *scaleData, unsigned elementCount); static unsigned deriveScalingVectorBlockCount(unsigned elementCount, unsigned blockStep) { return (elementCount + (blockStep - 1)) / blockStep; } static unsigned deriveScalingVectorThreadCount(unsigned lastBlockIndex, unsigned allowedThreadCount) { dIASSERT(allowedThreadCount >= 1); unsigned maximumCount = lastBlockIndex; return maximumCount >= allowedThreadCount ? allowedThreadCount : dMACRO_MAX(maximumCount, 1U); } static void initializeCooperativelyScaleVectorMemoryStructures(atomicord32 &out_blockCompletionProgress) { out_blockCompletionProgress = 0; } template static void participateScalingVector(dReal *ptrAStart, const dReal *ptrDStart, const unsigned elementCount, volatile atomicord32 &refBlockCompletionProgress/*=0*/); private: struct ScaleVectorWorkerContext { void init(dReal *vectorData, const dReal *scaleData, unsigned elementCount, atomicord32 &ref_blockCompletionProgress) { m_vectorData = vectorData; m_scaleData = scaleData; m_elementCount = elementCount; m_ptrBlockCompletionProgress = &ref_blockCompletionProgress; } dReal *m_vectorData; const dReal *m_scaleData; unsigned m_elementCount; atomicord32 *m_ptrBlockCompletionProgress; }; static int scaleVector_worker_callback(void *callContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee); static void scaleVector_worker(ScaleVectorWorkerContext &ref_context); static int scaleVector_completion_callback(void *callContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee); private: enum SolvingLDLTStage { SLDLTS__MIN, SLDLTS_SOLVING_STRAIGHT = SLDLTS__MIN, SLDLTS_SCALING_VECTOR, SLDLTS_SOLVING_TRANSPOSED, SLDLTS__MAX, }; enum { SLDLT_B_STRIDE = SL1S_B_STRIDE, SLDLT_D_STRIDE = FLDLT_D_STRIDE, }; static unsigned restrictSolvingLDLTAllowedThreadCount( dxThreadingBase *threading, unsigned allowedThreadCount, unsigned rowCount, unsigned &out_stageBlockCountSifficiencyMask); static void doCooperativelySolveLDLTValidated( dxRequiredResourceContainer *resourceContainer, unsigned allowedThreadCount, unsigned stageBlockCountSifficiencyMask, const dReal *L, const dReal *d, dReal *b, unsigned rowCount, unsigned rowSkip); }; #endif ode-0.16/ode/src/coop_matrix_types.h0000664000175200017520000001264413403272463014430 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ // Cooperative matrix algorithm types // Copyright (C) 2017 Oleh Derevenko (odar@eleks.com - change all "a" to "e") #ifndef _ODE_COOP_MATRIX_TYPES_H_ #define _ODE_COOP_MATRIX_TYPES_H_ #include "threadingutils.h" #include "common.h" #include "error.h" #ifndef dCOOPERATIVE_ENABLED #if dATOMICS_ENABLED && !dTHREADING_INTF_DISABLED #define dCOOPERATIVE_ENABLED 1 #endif // #if dATOMICS_ENABLED && !dTHREADING_INTF_DISABLED #endif // #ifndef dCOOPERATIVE_ENABLED enum { COOP_THREAD_DATA_ALIGNMENT_SIZE = 64, // Typical size of a cache line }; typedef uintptr cellindexint; enum CellContextInstance { CCI__MIN, CCI_FIRST = CCI__MIN, CCI_SECOND, CCI__MAX, CCI__LOG2_OF_MAX = 1, CCI__DEFAULT = CCI__MIN, }; dSASSERT(1 << CCI__LOG2_OF_MAX >= CCI__MAX); static inline CellContextInstance buildNextContextInstance(CellContextInstance instance) { dIASSERT(dIN_RANGE(instance, CCI__MIN, CCI__MAX)); dSASSERT(CCI__MAX == 2); return (CellContextInstance)(CCI_FIRST + CCI_SECOND - instance); } enum { CELLDESC_CCI_BITMASK = (1 << CCI__LOG2_OF_MAX) - 1, CELLDESC_LOCK_BIT = 1 << CCI__LOG2_OF_MAX, CELLDESC__HELPER_BITS = CELLDESC_CCI_BITMASK | CELLDESC_LOCK_BIT, CELLDESC__COLINDEX_BASE = CELLDESC__HELPER_BITS + 1, }; #define MAKE_CELLDESCRIPTOR(columnIndex, contextInstance, locked) ((cellindexint)((cellindexint)(columnIndex) * CELLDESC__COLINDEX_BASE + (contextInstance) + ((locked) ? CELLDESC_LOCK_BIT : 0))) #define MARK_CELLDESCRIPTOR_LOCKED(descriptor) ((cellindexint)((descriptor) | CELLDESC_LOCK_BIT)) #define GET_CELLDESCRIPTOR_COLUMNINDEX(descriptor) ((unsigned int)((cellindexint)(descriptor) / CELLDESC__COLINDEX_BASE)) #define GET_CELLDESCRIPTOR_CONTEXTINSTANCE(descriptor) ((CellContextInstance)((descriptor) & CELLDESC_CCI_BITMASK)) #define GET_CELLDESCRIPTOR_ISLOCKED(descriptor) (((descriptor) & CELLDESC_LOCK_BIT) != 0) #define INVALID_CELLDESCRIPTOR MAKE_CELLDESCRIPTOR(GET_CELLDESCRIPTOR_COLUMNINDEX(-1), CCI__MAX - 1, true) enum BlockProcessingState { BPS_COMPETING_FOR_A_BLOCK = -1, BPS_NO_BLOCKS_PROCESSED, BPS_SOME_BLOCKS_PROCESSED, }; class CooperativeAtomics { public: static atomicord32 AtomicDecrementUint32(volatile atomicord32 *paoDestination) { #if dCOOPERATIVE_ENABLED return ::AtomicDecrement(paoDestination); #else dIASSERT(false); return 0; // The function is not supposed to be called in this case #endif // #if dCOOPERATIVE_ENABLED } static bool AtomicCompareExchangeUint32(volatile atomicord32 *paoDestination, atomicord32 aoComparand, atomicord32 aoExchange) { #if dCOOPERATIVE_ENABLED return ::AtomicCompareExchange(paoDestination, aoComparand, aoExchange); #else dIASSERT(false); return false; // The function is not supposed to be called in this case #endif // #if dCOOPERATIVE_ENABLED } static bool AtomicCompareExchangeCellindexint(volatile cellindexint *destination, cellindexint comparand, cellindexint exchange) { #if dCOOPERATIVE_ENABLED return ::AtomicCompareExchangePointer((volatile atomicptr *)destination, (atomicptr)comparand, (atomicptr)exchange); #else dIASSERT(false); return false; // The function is not supposed to be called in this case #endif // #if dCOOPERATIVE_ENABLED } static void AtomicStoreCellindexint(volatile cellindexint *destination, cellindexint value) { #if dCOOPERATIVE_ENABLED ::AtomicStorePointer((volatile atomicptr *)destination, (atomicptr)value); #else dIASSERT(false); // The function is not supposed to be called in this case #endif // #if dCOOPERATIVE_ENABLED } static void AtomicReadReorderBarrier() { #if dCOOPERATIVE_ENABLED ::AtomicReadReorderBarrier(); #else dIASSERT(false); // The function is not supposed to be called in this case #endif // #if dCOOPERATIVE_ENABLED } }; #endif // #ifndef _ODE_COOP_MATRIX_TYPES_H_ ode-0.16/ode/src/simple_cooperative.h0000664000175200017520000000623313403272463014546 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * Threading base wrapper class header file. * * Copyright (C) 2011-2012 Oleh Derevenko. All rights reserved. * * e-mail: odar@eleks.com (change all "a" to "e") * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* * A simple cooperative class definition * Copyright (c) 2017 Oleh Derevenko, odar@eleks.com (change all "a" to "e") */ #ifndef _ODE__PRIVATE_SIMPLE_COOPERATIVE_H_ #define _ODE__PRIVATE_SIMPLE_COOPERATIVE_H_ #include "objects.h" #include "threading_base.h" typedef dxThreadingBase dxSimpleCooperative_ThreadingParent; class dxSimpleCooperative: public dBase, public dxSimpleCooperative_ThreadingParent, private dxIThreadingDefaultImplProvider { public: dxSimpleCooperative(const dxThreadingFunctionsInfo *functionInfo, dThreadingImplementationID threadingImpl): dBase(), dxSimpleCooperative_ThreadingParent() { dxSimpleCooperative_ThreadingParent::setThreadingDefaultImplProvider(this); dxSimpleCooperative_ThreadingParent::assignThreadingImpl(functionInfo, threadingImpl); } virtual ~dxSimpleCooperative(); public: dxThreadingBase *getRelatedThreading() const { return const_cast(this); } private: // dxIThreadingDefaultImplProvider virtual const dxThreadingFunctionsInfo *retrieveThreadingDefaultImpl(dThreadingImplementationID &out_defaultImpl); }; static inline dxSimpleCooperative *decodeCooperativeID(dCooperativeID cooperative) { return (dxSimpleCooperative *)cooperative; } #endif // #ifndef _ODE__PRIVATE_SIMPLE_COOPERATIVE_H_ ode-0.16/ode/src/odetls.h0000664000175200017520000001102613403272463012143 00000000000000/************************************************************************* * * * Thread local storage access stub for Open Dynamics Engine, * * Copyright (C) 2008 Oleh Derevenko. All rights reserved. * * Email: odar@eleks.com (change all "a" to "e") * * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* ODE Thread Local Storage access stub interface. */ #ifndef _ODE_ODETLS_H_ #define _ODE_ODETLS_H_ #include "odeou.h" #if dTLS_ENABLED using _OU_NAMESPACE::tlsvaluetype; using _OU_NAMESPACE::HTLSKEY; using _OU_NAMESPACE::CThreadLocalStorage; struct TrimeshCollidersCache; enum EODETLSKIND { OTK__MIN, OTK_AUTOCLEANUP = OTK__MIN, OTK_MANUALCLEANUP, OTK__MAX, OTK__DEFAULT = OTK_AUTOCLEANUP, }; enum EODETLSITEM { OTI_DATA_ALLOCATION_FLAGS, OTI_TRIMESH_TRIMESH_COLLIDER_CACHE, OTI__MAX, }; class COdeTls { public: static bool Initialize(EODETLSKIND tkTLSKind); static void Finalize(EODETLSKIND tkTLSKind); static void CleanupForThread(); public: static unsigned GetDataAllocationFlags(EODETLSKIND tkTLSKind) { // Must be a safe call as it is used to test if TLS slot is allocated at all return (unsigned)(sizeint)CThreadLocalStorage::GetStorageValue(m_ahtkStorageKeys[tkTLSKind], OTI_DATA_ALLOCATION_FLAGS); } static void SignalDataAllocationFlags(EODETLSKIND tkTLSKind, unsigned uFlagsMask) { unsigned uCurrentFlags = (unsigned)(sizeint)CThreadLocalStorage::UnsafeGetStorageValue(m_ahtkStorageKeys[tkTLSKind], OTI_DATA_ALLOCATION_FLAGS); CThreadLocalStorage::UnsafeSetStorageValue(m_ahtkStorageKeys[tkTLSKind], OTI_DATA_ALLOCATION_FLAGS, (tlsvaluetype)(sizeint)(uCurrentFlags | uFlagsMask)); } static void DropDataAllocationFlags(EODETLSKIND tkTLSKind, unsigned uFlagsMask) { unsigned uCurrentFlags = (unsigned)(sizeint)CThreadLocalStorage::UnsafeGetStorageValue(m_ahtkStorageKeys[tkTLSKind], OTI_DATA_ALLOCATION_FLAGS); CThreadLocalStorage::UnsafeSetStorageValue(m_ahtkStorageKeys[tkTLSKind], OTI_DATA_ALLOCATION_FLAGS, (tlsvaluetype)(sizeint)(uCurrentFlags & ~uFlagsMask)); } static TrimeshCollidersCache *GetTrimeshCollidersCache(EODETLSKIND tkTLSKind) { return (TrimeshCollidersCache *)CThreadLocalStorage::UnsafeGetStorageValue(m_ahtkStorageKeys[tkTLSKind], OTI_TRIMESH_TRIMESH_COLLIDER_CACHE); } public: static bool AssignDataAllocationFlags(EODETLSKIND tkTLSKind, unsigned uInitializationFlags); static bool AssignTrimeshCollidersCache(EODETLSKIND tkTLSKind, TrimeshCollidersCache *pccInstance); static void DestroyTrimeshCollidersCache(EODETLSKIND tkTLSKind); private: static void FreeTrimeshCollidersCache(TrimeshCollidersCache *pccCacheInstance); private: static void _OU_CONVENTION_CALLBACK FreeTrimeshCollidersCache_Callback(tlsvaluetype vValueData); private: static HTLSKEY m_ahtkStorageKeys[OTK__MAX]; }; #endif // dTLS_ENABLED #endif // _ODE_ODETLS_H_ ode-0.16/ode/src/collision_trimesh_opcode.cpp0000664000175200017520000005633413403272463016276 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ // TriMesh code by Erwin de Vries. // TriMesh storage classes refactoring and face angle computation code by Oleh Derevenko (C) 2016-2017 #include #include #include "config.h" #include "matrix.h" #include "odemath.h" #if dTRIMESH_ENABLED && dTRIMESH_OPCODE #include "collision_util.h" #include "collision_trimesh_opcode.h" #include "collision_trimesh_internal_impl.h" #include ////////////////////////////////////////////////////////////////////////// // TrimeshCollidersCache void TrimeshCollidersCache::initOPCODECaches() { m_RayCollider.SetDestination(&m_Faces); /* -- not used _PlanesCollider.SetTemporalCoherence(true); */ m_SphereCollider.SetTemporalCoherence(true); m_SphereCollider.SetPrimitiveTests(false); m_OBBCollider.SetTemporalCoherence(true); // no first-contact test (i.e. return full contact info) m_AABBTreeCollider.SetFirstContact( false ); // temporal coherence only works with "first contact" tests m_AABBTreeCollider.SetTemporalCoherence(false); // Perform full BV-BV tests (true) or SAT-lite tests (false) m_AABBTreeCollider.SetFullBoxBoxTest( true ); // Perform full Primitive-BV tests (true) or SAT-lite tests (false) m_AABBTreeCollider.SetFullPrimBoxTest( true ); const char* msg; if ((msg =m_AABBTreeCollider.ValidateSettings())) { dDebug (d_ERR_UASSERT, msg, " (%s:%d)", __FILE__,__LINE__); } /* -- not used _LSSCollider.SetTemporalCoherence(false); _LSSCollider.SetPrimitiveTests(false); _LSSCollider.SetFirstContact(false); */ } void TrimeshCollidersCache::clearOPCODECaches() { m_Faces.Empty(); m_DefaultSphereCache.TouchedPrimitives.Empty(); m_DefaultBoxCache.TouchedPrimitives.Empty(); m_DefaultCapsuleCache.TouchedPrimitives.Empty(); } ////////////////////////////////////////////////////////////////////////// // Trimesh data dxTriMeshData::~dxTriMeshData() { if ( m_InternalUseFlags != NULL ) { sizeint flagsMemoryRequired = calculateUseFlagsMemoryRequirement(); dFree(m_InternalUseFlags, flagsMemoryRequired); } } void dxTriMeshData::buildData(const Point *Vertices, int VertexStide, unsigned VertexCount, const IndexedTriangle *Indices, unsigned IndexCount, int TriStride, const dReal *in_Normals, bool Single) { dxTriMeshData_Parent::buildData(Vertices, VertexStide, VertexCount, Indices, IndexCount, TriStride, in_Normals, Single); dAASSERT(IndexCount % dMTV__MAX == 0); m_Mesh.SetNbTriangles(IndexCount / dMTV__MAX); m_Mesh.SetNbVertices(VertexCount); m_Mesh.SetPointers(Indices, Vertices); m_Mesh.SetStrides(TriStride, VertexStide); m_Mesh.SetSingle(Single); // Build tree // recommended in Opcode User Manual //Settings.mRules = SPLIT_COMPLETE | SPLIT_SPLATTERPOINTS | SPLIT_GEOMCENTER; // used in ODE, why? //Settings.mRules = SPLIT_BEST_AXIS; // best compromise? BuildSettings Settings(SPLIT_BEST_AXIS | SPLIT_SPLATTER_POINTS | SPLIT_GEOM_CENTER); OPCODECREATE TreeBuilder(&m_Mesh, Settings, true, false); m_BVTree.Build(TreeBuilder); // compute model space AABB dVector3 AABBMax, AABBMin; calculateDataAABB(AABBMax, AABBMin); dAddVectors3(m_AABBCenter, AABBMin, AABBMax); dScaleVector3(m_AABBCenter, REAL(0.5)); dSubtractVectors3(m_AABBExtents, AABBMax, m_AABBCenter); // user data (not used by OPCODE) dIASSERT(m_InternalUseFlags == NULL); } void dxTriMeshData::calculateDataAABB(dVector3 &AABBMax, dVector3 &AABBMin) { if (isSingle()) { templateCalculateDataAABB(AABBMax, AABBMin); } else { templateCalculateDataAABB(AABBMax, AABBMin); } } template void dxTriMeshData::templateCalculateDataAABB(dVector3 &AABBMax, dVector3 &AABBMin) { dIASSERT(isSingle() == (sizeof(treal) == sizeof(float))); const Point *vertices = retrieveVertexInstances(); const int vertexStide = retrieveVertexStride(); const unsigned vertexCount = retrieveVertexCount(); AABBMax[dV3E_X] = AABBMax[dV3E_Y] = AABBMax[dV3E_Z] = -dInfinity; AABBMin[dV3E_X] = AABBMin[dV3E_Y] = AABBMin[dV3E_Z] = dInfinity; dSASSERT(dV3E__AXES_COUNT == 3); const uint8 *verts = (const uint8 *)vertices; for( unsigned i = 0; i < vertexCount; ++i ) { const treal *v = (const treal *)verts; if( v[dSA_X] > AABBMax[dV3E_X] ) AABBMax[dV3E_X] = (dReal)v[dSA_X]; if( v[dSA_X] < AABBMin[dV3E_X] ) AABBMin[dV3E_X] = (dReal)v[dSA_X]; if( v[dSA_Y] > AABBMax[dV3E_Y] ) AABBMax[dV3E_Y] = (dReal)v[dSA_Y]; if( v[dSA_Y] < AABBMin[dV3E_Y] ) AABBMin[dV3E_Y] = (dReal)v[dSA_Y]; if( v[dSA_Z] > AABBMax[dV3E_Z] ) AABBMax[dV3E_Z] = (dReal)v[dSA_Z]; if( v[dSA_Z] < AABBMin[dV3E_Z] ) AABBMin[dV3E_Z] = (dReal)v[dSA_Z]; verts += vertexStide; } } bool dxTriMeshData::preprocessData(bool buildUseFlags/*=false*/, FaceAngleStorageMethod faceAndgesRequirement/*=ASM__INVALID*/) { bool buildUseFlagsToUse = buildUseFlags; FaceAngleStorageMethod faceAndgesRequirementToUse = faceAndgesRequirement; if (buildUseFlags && haveUseFlagsBeenBuilt()) { dUASSERT(false, "Another request to build edge/vertex use flags after they had already been built"); buildUseFlagsToUse = false; } if (faceAndgesRequirement != ASM__INVALID && haveFaceAnglesBeenBuilt()) { dUASSERT(false, "Another request to build face angles after they had already been built"); faceAndgesRequirementToUse = ASM__INVALID; } // If this mesh has already been preprocessed, exit bool result = (!buildUseFlagsToUse && faceAndgesRequirementToUse == ASM__INVALID) || m_Mesh.GetNbTriangles() == 0 || meaningfulPreprocessData(buildUseFlagsToUse, faceAndgesRequirementToUse); return result; } struct TrimeshDataVertexIndexAccessor_OPCODE { TrimeshDataVertexIndexAccessor_OPCODE(const IndexedTriangle *triIndicesBegin, unsigned triStride): m_TriIndicesBegin(triIndicesBegin), m_TriStride(triStride) { } void getTriangleVertexIndices(unsigned out_VertexIndices[dMTV__MAX], unsigned triangleIdx) const { const IndexedTriangle *triIndicesBegin = m_TriIndicesBegin; const unsigned triStride = m_TriStride; const IndexedTriangle *triIndicesOfInterest = (const IndexedTriangle *)((const uint8 *)triIndicesBegin + triangleIdx * (sizeint)triStride); std::copy(triIndicesOfInterest->mVRef, triIndicesOfInterest->mVRef + dMTV__MAX, out_VertexIndices); dSASSERT(dMTV__MAX == dARRAY_SIZE(triIndicesOfInterest->mVRef)); dSASSERT(dMTV_FIRST == 0); dSASSERT(dMTV_SECOND == 1); dSASSERT(dMTV_THIRD == 2); dSASSERT(dMTV__MAX == 3); } const IndexedTriangle *m_TriIndicesBegin; unsigned m_TriStride; }; struct TrimeshDataTrianglePointAccessor_OPCODE { TrimeshDataTrianglePointAccessor_OPCODE(const MeshInterface &mesh): m_Mesh(mesh) { } void getTriangleVertexPoints(dVector3 out_Points[dMTV__MAX], unsigned triangleIndex) const { VertexPointers vpTriangle; ConversionArea vc; m_Mesh.GetTriangle(vpTriangle, triangleIndex, vc); for (unsigned pointIndex = 0; pointIndex != 3; ++pointIndex) { dAssignVector3(out_Points[pointIndex], vpTriangle.Vertex[pointIndex]->x, vpTriangle.Vertex[pointIndex]->y, vpTriangle.Vertex[pointIndex]->z); } dSASSERT(dMTV_FIRST == 0); dSASSERT(dMTV_SECOND == 1); dSASSERT(dMTV_THIRD == 2); dSASSERT(dMTV__MAX == 3); } const MeshInterface &m_Mesh; }; bool dxTriMeshData::meaningfulPreprocessData(bool buildUseFlags/*=false*/, FaceAngleStorageMethod faceAndgesRequirement/*=ASM__INVALID*/) { const bool buildFaceAngles = faceAndgesRequirement != ASM__INVALID; dIASSERT(buildUseFlags || buildFaceAngles); dIASSERT(!buildUseFlags || !haveUseFlagsBeenBuilt()); dIASSERT(!buildFaceAngles || !haveFaceAnglesBeenBuilt()); bool result = false; uint8 *useFlags = NULL; sizeint flagsMemoryRequired = 0; bool flagsAllocated = false, anglesAllocated = false; do { if (buildUseFlags) { flagsMemoryRequired = calculateUseFlagsMemoryRequirement(); useFlags = (uint8 *)dAlloc(flagsMemoryRequired); if (useFlags == NULL) { break; } } flagsAllocated = true; if (buildFaceAngles) { if (!allocateFaceAngles(faceAndgesRequirement)) { break; } } anglesAllocated = true; const unsigned int numTris = m_Mesh.GetNbTriangles(); const unsigned int numVertices = m_Mesh.GetNbVertices(); sizeint numEdges = (sizeint)numTris * dMTV__MAX; dIASSERT(numVertices <= numEdges); // Edge records are going to be used for vertex data as well const sizeint recordsMemoryRequired = dEFFICIENT_SIZE(numEdges * sizeof(EdgeRecord)); const sizeint verticesMemoryRequired = /*dEFFICIENT_SIZE*/(numVertices * sizeof(VertexRecord)); // Skip alignment for the last chunk const sizeint totalTempMemoryRequired = recordsMemoryRequired + verticesMemoryRequired; void *tempBuffer = dAlloc(totalTempMemoryRequired); if (tempBuffer == NULL) { break; } EdgeRecord *edges = (EdgeRecord *)tempBuffer; VertexRecord *vertices = (VertexRecord *)((uint8 *)tempBuffer + recordsMemoryRequired); // Delay zero-filling until all the allocations succeed if (useFlags != NULL) { memset(useFlags, 0, flagsMemoryRequired); } const IndexedTriangle *triIndicesBegin = m_Mesh.GetTris(); unsigned triStride = m_Mesh.GetTriStride(); TrimeshDataVertexIndexAccessor_OPCODE indexAccessor(triIndicesBegin, triStride); meaningfulPreprocess_SetupEdgeRecords(edges, numEdges, indexAccessor); // Sort the edges, so the ones sharing the same verts are beside each other std::sort(edges, edges + numEdges); TrimeshDataTrianglePointAccessor_OPCODE pointAccessor(m_Mesh); const dReal *const externalNormals = retrieveNormals(); IFaceAngleStorageControl *faceAngles = retrieveFaceAngles(); meaningfulPreprocess_buildEdgeFlags(useFlags, faceAngles, edges, numEdges, vertices, externalNormals, pointAccessor); dFree(tempBuffer, totalTempMemoryRequired); if (buildUseFlags) { m_InternalUseFlags = useFlags; } result = true; } while (false); if (!result) { if (flagsAllocated) { if (anglesAllocated) { if (buildFaceAngles) { freeFaceAngles(); } } if (buildUseFlags) { dFree(useFlags, flagsMemoryRequired); } } } return result; } void dxTriMeshData::updateData() { m_BVTree.Refit(); } ////////////////////////////////////////////////////////////////////////// // dxTriMesh dxTriMesh::~dxTriMesh() { // } void dxTriMesh::clearTCCache() { /* dxTriMesh::ClearTCCache uses dArray's setSize(0) to clear the caches - but the destructor isn't called when doing this, so we would leak. So, call the previous caches' containers' destructors by hand first. */ int i, n; n = m_SphereTCCache.size(); for( i = 0; i != n; ++i ) { m_SphereTCCache[i].~SphereTC(); } m_SphereTCCache.setSize(0); n = m_BoxTCCache.size(); for( i = 0; i != n; ++i ) { m_BoxTCCache[i].~BoxTC(); } m_BoxTCCache.setSize(0); n = m_CapsuleTCCache.size(); for( i = 0; i != n; ++i ) { m_CapsuleTCCache[i].~CapsuleTC(); } m_CapsuleTCCache.setSize(0); } bool dxTriMesh::controlGeometry(int controlClass, int controlCode, void *dataValue, int *dataSize) { if (controlClass == dGeomColliderControlClass) { if (controlCode == dGeomCommonAnyControlCode) { return checkControlValueSizeValidity(dataValue, dataSize, 0); } else if (controlCode == dGeomColliderSetMergeSphereContactsControlCode) { return checkControlValueSizeValidity(dataValue, dataSize, sizeof(int)) && controlGeometry_SetMergeSphereContacts(*(int *)dataValue); } else if (controlCode == dGeomColliderGetMergeSphereContactsControlCode) { return checkControlValueSizeValidity(dataValue, dataSize, sizeof(int)) && controlGeometry_GetMergeSphereContacts(*(int *)dataValue); } } return dxTriMesh_Parent::controlGeometry(controlClass, controlCode, dataValue, dataSize); } bool dxTriMesh::controlGeometry_SetMergeSphereContacts(int dataValue) { if (dataValue == dGeomColliderMergeContactsValue__Default) { m_SphereContactsMergeOption = (dxContactMergeOptions)MERGE_NORMALS__SPHERE_DEFAULT; } else if (dataValue == dGeomColliderMergeContactsValue_None) { m_SphereContactsMergeOption = DONT_MERGE_CONTACTS; } else if (dataValue == dGeomColliderMergeContactsValue_Normals) { m_SphereContactsMergeOption = MERGE_CONTACT_NORMALS; } else if (dataValue == dGeomColliderMergeContactsValue_Full) { m_SphereContactsMergeOption = MERGE_CONTACTS_FULLY; } else { dAASSERT(false && "Invalid contact merge control value"); return false; } return true; } bool dxTriMesh::controlGeometry_GetMergeSphereContacts(int &returnValue) { if (m_SphereContactsMergeOption == DONT_MERGE_CONTACTS) { returnValue = dGeomColliderMergeContactsValue_None; } else if (m_SphereContactsMergeOption == MERGE_CONTACT_NORMALS) { returnValue = dGeomColliderMergeContactsValue_Normals; } else if (m_SphereContactsMergeOption == MERGE_CONTACTS_FULLY) { returnValue = dGeomColliderMergeContactsValue_Full; } else { dIASSERT(false && "Internal error: unexpected contact merge option field value"); return false; } return true; } /*virtual */ void dxTriMesh::computeAABB() { const dxTriMeshData *meshData = getMeshData(); dVector3 c; const dMatrix3& R = final_posr->R; const dVector3& pos = final_posr->pos; dMultiply0_331( c, R, meshData->m_AABBCenter ); dReal xrange = dFabs(R[0] * meshData->m_AABBExtents[0]) + dFabs(R[1] * meshData->m_AABBExtents[1]) + dFabs(R[2] * meshData->m_AABBExtents[2]); dReal yrange = dFabs(R[4] * meshData->m_AABBExtents[0]) + dFabs(R[5] * meshData->m_AABBExtents[1]) + dFabs(R[6] * meshData->m_AABBExtents[2]); dReal zrange = dFabs(R[8] * meshData->m_AABBExtents[0]) + dFabs(R[9] * meshData->m_AABBExtents[1]) + dFabs(R[10] * meshData->m_AABBExtents[2]); aabb[0] = c[0] + pos[0] - xrange; aabb[1] = c[0] + pos[0] + xrange; aabb[2] = c[1] + pos[1] - yrange; aabb[3] = c[1] + pos[1] + yrange; aabb[4] = c[2] + pos[2] - zrange; aabb[5] = c[2] + pos[2] + zrange; } void dxTriMesh::fetchMeshTransformedTriangle(dVector3 *const pout_triangle[3], unsigned index) { const dVector3 &position = buildUpdatedPosition(); const dMatrix3 &rotation = buildUpdatedRotation(); fetchMeshTriangle(pout_triangle, index, position, rotation); } void dxTriMesh::fetchMeshTransformedTriangle(dVector3 out_triangle[3], unsigned index) { const dVector3 &position = buildUpdatedPosition(); const dMatrix3 &rotation = buildUpdatedRotation(); fetchMeshTriangle(out_triangle, index, position, rotation); } void dxTriMesh::fetchMeshTriangle(dVector3 *const pout_triangle[3], unsigned index, const dVector3 position, const dMatrix3 rotation) const { dIASSERT(dIN_RANGE(index, 0, getMeshTriangleCount())); VertexPointers VP; ConversionArea VC; const dxTriMeshData *meshData = getMeshData(); meshData->m_Mesh.GetTriangle(VP, index, VC); for (unsigned i = 0; i != 3; ++i) { if (pout_triangle[i] != NULL) { dVector3 v; v[dV3E_X] = VP.Vertex[i]->x; v[dV3E_Y] = VP.Vertex[i]->y; v[dV3E_Z] = VP.Vertex[i]->z; dVector3 &out_triangle = *(pout_triangle[i]); dMultiply0_331(out_triangle, rotation, v); dAddVectors3(out_triangle, out_triangle, position); out_triangle[dV3E_PAD] = REAL(0.0); } } } void dxTriMesh::fetchMeshTriangle(dVector3 out_triangle[3], unsigned index, const dVector3 position, const dMatrix3 rotation) const { dIASSERT(dIN_RANGE(index, 0, getMeshTriangleCount())); VertexPointers VP; ConversionArea VC; const dxTriMeshData *meshData = getMeshData(); meshData->m_Mesh.GetTriangle(VP, index, VC); for (unsigned i = 0; i != 3; ++i) { dVector3 v; v[dV3E_X] = VP.Vertex[i]->x; v[dV3E_Y] = VP.Vertex[i]->y; v[dV3E_Z] = VP.Vertex[i]->z; dMultiply0_331(out_triangle[i], rotation, v); dAddVectors3(out_triangle[i], out_triangle[i], position); out_triangle[i][dV3E_PAD] = REAL(0.0); } } ////////////////////////////////////////////////////////////////////////// /*extern */ dTriMeshDataID dGeomTriMeshDataCreate() { return new dxTriMeshData(); } /*extern */ void dGeomTriMeshDataDestroy(dTriMeshDataID g) { dxTriMeshData *mesh = g; delete mesh; } /*extern */ void dGeomTriMeshDataSet(dTriMeshDataID g, int dataId, void *pDataLocation) { dUASSERT(g, "The argument is not a trimesh data"); dxTriMeshData *data = g; switch (dataId) { case dTRIMESHDATA_FACE_NORMALS: { data->assignNormals((const dReal *)pDataLocation); break; } case dTRIMESHDATA_USE_FLAGS: { data->assignExternalUseFlagsBuffer((uint8 *)pDataLocation); break; } // case dTRIMESHDATA__MAX: -- To be located by Find in Files default: { dUASSERT(dataId, "invalid data type"); break; } } } static void *geomTriMeshDataGet(dTriMeshDataID g, int dataId, sizeint *pOutDataSize); /*extern */ void *dGeomTriMeshDataGet(dTriMeshDataID g, int dataId, sizeint *pOutDataSize) { return geomTriMeshDataGet(g, dataId, NULL); } /*extern */ void *dGeomTriMeshDataGet2(dTriMeshDataID g, int dataId, sizeint *pOutDataSize) { return geomTriMeshDataGet(g, dataId, pOutDataSize); } static void *geomTriMeshDataGet(dTriMeshDataID g, int dataId, sizeint *pOutDataSize) { dUASSERT(g, "The argument is not a trimesh data"); const dxTriMeshData *data = g; void *result = NULL; switch (dataId) { case dTRIMESHDATA_FACE_NORMALS: { if (pOutDataSize != NULL) { *pOutDataSize = data->calculateNormalsMemoryRequirement(); } result = (void *)data->retrieveNormals(); break; } case dTRIMESHDATA_USE_FLAGS: { if (pOutDataSize != NULL) { *pOutDataSize = data->calculateUseFlagsMemoryRequirement(); } result = const_cast(data->smartRetrieveUseFlags()); break; } // case dTRIMESHDATA__MAX: -- To be located by Find in Files default: { if (pOutDataSize != NULL) { *pOutDataSize = 0; } dUASSERT(dataId, "invalid data type"); break; } } return result; } /*extern */ void dGeomTriMeshDataBuildSingle1(dTriMeshDataID g, const void* Vertices, int VertexStride, int VertexCount, const void* Indices, int IndexCount, int TriStride, const void* Normals) { dUASSERT(g, "The argument is not a trimesh data"); dxTriMeshData *data = g; data->buildData((const Point *)Vertices, VertexStride, VertexCount, (const IndexedTriangle *)Indices, IndexCount, TriStride, (const dReal *)Normals, true); } /*extern */ void dGeomTriMeshDataBuildDouble1(dTriMeshDataID g, const void* Vertices, int VertexStride, int VertexCount, const void* Indices, int IndexCount, int TriStride, const void* Normals) { dUASSERT(g, "The argument is not a trimesh data"); g->buildData((const Point *)Vertices, VertexStride, VertexCount, (const IndexedTriangle *)Indices, IndexCount, TriStride, (const dReal *)Normals, false); } ////////////////////////////////////////////////////////////////////////// /*extern */ dGeomID dCreateTriMesh(dSpaceID space, dTriMeshDataID Data, dTriCallback* Callback, dTriArrayCallback* ArrayCallback, dTriRayCallback* RayCallback) { dxTriMesh *mesh = new dxTriMesh(space, Data, Callback, ArrayCallback, RayCallback); return mesh; } /*extern */ void dGeomTriMeshSetLastTransform(dGeomID g, const dMatrix4 last_trans ) { dAASSERT(g); dUASSERT(g->type == dTriMeshClass, "The geom is not a trimesh"); dxTriMesh *mesh = static_cast(g); mesh->assignLastTransform(last_trans); } /*extern */ const dReal *dGeomTriMeshGetLastTransform(dGeomID g) { dAASSERT(g); dUASSERT(g->type == dTriMeshClass, "The geom is not a trimesh"); dxTriMesh *mesh = static_cast(g); return mesh->retrieveLastTransform(); } ////////////////////////////////////////////////////////////////////////// // Cleanup for allocations when shutting down ODE /*extern */ void opcode_collider_cleanup() { #if !dTLS_ENABLED // Clear TC caches TrimeshCollidersCache *pccColliderCache = GetTrimeshCollidersCache(0); pccColliderCache->clearOPCODECaches(); #endif // dTLS_ENABLED } #endif // dTRIMESH_ENABLED && dTRIMESH_OPCODE ode-0.16/ode/src/export-dif.cpp0000664000175200017520000004546513403272463013303 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* * Export a DIF (Dynamics Interchange Format) file. */ // @@@ TODO: // * export all spaces, and geoms in spaces, not just ones attached to bodies // (separate export function?) // * say the space each geom is in, so reader can construct space heirarchy // * limot --> separate out into limits and motors? // * make sure ODE-specific parameters divided out #include #include "config.h" #include "objects.h" #include "joints/joints.h" #include "collision_kernel.h" //*************************************************************************** // utility struct PrintingContext { FILE *file; // file to write to int precision; // digits of precision to print int indent; // number of levels of indent void printIndent(); void printReal (dReal x); void print (const char *name, int x); void print (const char *name, unsigned x); void print (const char *name, dReal x); void print (const char *name, const dReal *x, int n=3); void print (const char *name, const char *x=0); void printNonzero (const char *name, dReal x); void printNonzero (const char *name, const dReal x[3]); }; void PrintingContext::printIndent() { for (int i=0; i= 0) { c.printIndent(); fprintf (c.file,"limit%d = {\n",num); } else { c.print ("limit = {"); } c.indent++; c.print ("low_stop",limot.lostop); c.print ("high_stop",limot.histop); c.printNonzero ("bounce",limot.bounce); c.print ("ODE = {"); c.indent++; c.printNonzero ("stop_erp",limot.stop_erp); c.printNonzero ("stop_cfm",limot.stop_cfm); c.indent--; c.print ("},"); c.indent--; c.print ("},"); if (num >= 0) { c.printIndent(); fprintf (c.file,"motor%d = {\n",num); } else { c.print ("motor = {"); } c.indent++; c.printNonzero ("vel",limot.vel); c.printNonzero ("fmax",limot.fmax); c.print ("ODE = {"); c.indent++; c.printNonzero ("fudge_factor",limot.fudge_factor); c.printNonzero ("normal_cfm",limot.normal_cfm); c.indent--; c.print ("},"); c.indent--; c.print ("},"); } static const char *getJointName (dxJoint *j) { switch (j->type()) { case dJointTypeBall: return "ball"; case dJointTypeHinge: return "hinge"; case dJointTypeSlider: return "slider"; case dJointTypeContact: return "contact"; case dJointTypeUniversal: return "universal"; case dJointTypeHinge2: return "ODE_hinge2"; case dJointTypeFixed: return "fixed"; case dJointTypeNull: return "null"; case dJointTypeAMotor: return "ODE_angular_motor"; case dJointTypeLMotor: return "ODE_linear_motor"; case dJointTypePR: return "PR"; case dJointTypePU: return "PU"; case dJointTypePiston: return "piston"; default: return "unknown"; } } static void printBall (PrintingContext &c, dxJoint *j) { dxJointBall *b = (dxJointBall*) j; c.print ("anchor1",b->anchor1); c.print ("anchor2",b->anchor2); } static void printHinge (PrintingContext &c, dxJoint *j) { dxJointHinge *h = (dxJointHinge*) j; c.print ("anchor1",h->anchor1); c.print ("anchor2",h->anchor2); c.print ("axis1",h->axis1); c.print ("axis2",h->axis2); c.print ("qrel",h->qrel,4); printLimot (c,h->limot,-1); } static void printSlider (PrintingContext &c, dxJoint *j) { dxJointSlider *s = (dxJointSlider*) j; c.print ("axis1",s->axis1); c.print ("qrel",s->qrel,4); c.print ("offset",s->offset); printLimot (c,s->limot,-1); } static void printContact (PrintingContext &c, dxJoint *j) { dxJointContact *ct = (dxJointContact*) j; int mode = ct->contact.surface.mode; c.print ("pos",ct->contact.geom.pos); c.print ("normal",ct->contact.geom.normal); c.print ("depth",ct->contact.geom.depth); //@@@ may want to write the geoms g1 and g2 that are involved, for debugging. // to do this we must have written out all geoms in all spaces, not just // geoms that are attached to bodies. c.print ("mu",ct->contact.surface.mu); if (mode & dContactMu2) c.print ("mu2",ct->contact.surface.mu2); if (mode & dContactBounce) c.print ("bounce",ct->contact.surface.bounce); if (mode & dContactBounce) c.print ("bounce_vel",ct->contact.surface.bounce_vel); if (mode & dContactSoftERP) c.print ("soft_ERP",ct->contact.surface.soft_erp); if (mode & dContactSoftCFM) c.print ("soft_CFM",ct->contact.surface.soft_cfm); if (mode & dContactMotion1) c.print ("motion1",ct->contact.surface.motion1); if (mode & dContactMotion2) c.print ("motion2",ct->contact.surface.motion2); if (mode & dContactSlip1) c.print ("slip1",ct->contact.surface.slip1); if (mode & dContactSlip2) c.print ("slip2",ct->contact.surface.slip2); int fa = 0; // friction approximation code if (mode & dContactApprox1_1) fa |= 1; if (mode & dContactApprox1_2) fa |= 2; if (fa) c.print ("friction_approximation",fa); if (mode & dContactFDir1) c.print ("fdir1",ct->contact.fdir1); } static void printUniversal (PrintingContext &c, dxJoint *j) { dxJointUniversal *u = (dxJointUniversal*) j; c.print ("anchor1",u->anchor1); c.print ("anchor2",u->anchor2); c.print ("axis1",u->axis1); c.print ("axis2",u->axis2); c.print ("qrel1",u->qrel1,4); c.print ("qrel2",u->qrel2,4); printLimot (c,u->limot1,1); printLimot (c,u->limot2,2); } static void printHinge2 (PrintingContext &c, dxJoint *j) { dxJointHinge2 *h = (dxJointHinge2*) j; c.print ("anchor1",h->anchor1); c.print ("anchor2",h->anchor2); c.print ("axis1",h->axis1); c.print ("axis2",h->axis2); c.print ("v1",h->v1); //@@@ much better to write out 'qrel' here, if it's available c.print ("v2",h->v2); c.print ("susp_erp",h->susp_erp); c.print ("susp_cfm",h->susp_cfm); printLimot (c,h->limot1,1); printLimot (c,h->limot2,2); } static void printPR (PrintingContext &c, dxJoint *j) { dxJointPR *pr = (dxJointPR*) j; c.print ("anchor2",pr->anchor2); c.print ("axisR1",pr->axisR1); c.print ("axisR2",pr->axisR2); c.print ("axisP1",pr->axisP1); c.print ("qrel",pr->qrel,4); c.print ("offset",pr->offset); printLimot (c,pr->limotP,1); printLimot (c,pr->limotR,2); } static void printPU (PrintingContext &c, dxJoint *j) { dxJointPU *pu = (dxJointPU*) j; c.print ("anchor1",pu->anchor1); c.print ("anchor2",pu->anchor2); c.print ("axis1",pu->axis1); c.print ("axis2",pu->axis2); c.print ("axisP",pu->axisP1); c.print ("qrel1",pu->qrel1,4); c.print ("qrel2",pu->qrel2,4); printLimot (c,pu->limot1,1); printLimot (c,pu->limot2,2); printLimot (c,pu->limotP,3); } static void printPiston (PrintingContext &c, dxJoint *j) { dxJointPiston *rap = (dxJointPiston*) j; c.print ("anchor1",rap->anchor1); c.print ("anchor2",rap->anchor2); c.print ("axis1",rap->axis1); c.print ("axis2",rap->axis2); c.print ("qrel",rap->qrel,4); printLimot (c,rap->limotP,1); printLimot (c, rap->limotR, 2); } static void printFixed (PrintingContext &c, dxJoint *j) { dxJointFixed *f = (dxJointFixed*) j; c.print ("qrel",f->qrel); c.print ("offset",f->offset); } static void printLMotor (PrintingContext &c, dxJoint *j) { dxJointLMotor *a = (dxJointLMotor*) j; c.print("num", a->num); c.printIndent(); fprintf (c.file,"rel = {%d,%d,%d},\n",a->rel[0],a->rel[1],a->rel[2]); c.print ("axis1",a->axis[0]); c.print ("axis2",a->axis[1]); c.print ("axis3",a->axis[2]); for (int i=0; i<3; i++) printLimot (c,a->limot[i],i+1); } struct dxAMotorJointPrinter { static void print(PrintingContext &c, dxJointAMotor *a) { c.print ("num",a->m_num); c.print ("mode",a->m_mode); c.printIndent(); fprintf (c.file,"rel = {%d,%d,%d},\n",a->m_rel[0],a->m_rel[1],a->m_rel[2]); c.print ("axis1",a->m_axis[0]); c.print ("axis2",a->m_axis[1]); c.print ("axis3",a->m_axis[2]); for (int i=0; i<3; i++) printLimot (c,a->m_limot[i],i+1); c.print ("angle1",a->m_angle[0]); c.print ("angle2",a->m_angle[1]); c.print ("angle3",a->m_angle[2]); } }; static void printAMotor (PrintingContext &c, dxJoint *j) { dxJointAMotor *a = (dxJointAMotor*) j; dxAMotorJointPrinter::print(c, a); } //*************************************************************************** // geometry static void printGeom (PrintingContext &c, dxGeom *g); static void printSphere (PrintingContext &c, dxGeom *g) { c.print ("type","sphere"); c.print ("radius",dGeomSphereGetRadius (g)); } static void printBox (PrintingContext &c, dxGeom *g) { dVector3 sides; dGeomBoxGetLengths (g,sides); c.print ("type","box"); c.print ("sides",sides); } static void printCapsule (PrintingContext &c, dxGeom *g) { dReal radius,length; dGeomCapsuleGetParams (g,&radius,&length); c.print ("type","capsule"); c.print ("radius",radius); c.print ("length",length); } static void printCylinder (PrintingContext &c, dxGeom *g) { dReal radius,length; dGeomCylinderGetParams (g,&radius,&length); c.print ("type","cylinder"); c.print ("radius",radius); c.print ("length",length); } static void printPlane (PrintingContext &c, dxGeom *g) { dVector4 e; dGeomPlaneGetParams (g,e); c.print ("type","plane"); c.print ("normal",e); c.print ("d",e[3]); } static void printRay (PrintingContext &c, dxGeom *g) { dReal length = dGeomRayGetLength (g); c.print ("type","ray"); c.print ("length",length); } static void printConvex (PrintingContext &c, dxGeom * /*g*/) { c.print ("type","convex"); ///@todo Print information about convex hull } static void printTriMesh (PrintingContext &c, dxGeom * /*g*/) { c.print ("type","trimesh"); //@@@ i don't think that the trimesh accessor functions are really // sufficient to read out all the triangle data, and anyway we // should have a method of not duplicating trimesh data that is // shared. } static void printHeightfieldClass (PrintingContext &c, dxGeom * /*g*/) { c.print ("type","heightfield"); ///@todo Print information about heightfield } static void printGeom (PrintingContext &c, dxGeom *g) { unsigned long category = dGeomGetCategoryBits (g); if (category != (unsigned long)(~0)) { c.printIndent(); fprintf (c.file,"category_bits = %lu\n",category); } unsigned long collide = dGeomGetCollideBits (g); if (collide != (unsigned long)(~0)) { c.printIndent(); fprintf (c.file,"collide_bits = %lu\n",collide); } if (!dGeomIsEnabled (g)) { c.print ("disabled",1); } switch (g->type) { case dSphereClass: printSphere (c,g); break; case dBoxClass: printBox (c,g); break; case dCapsuleClass: printCapsule (c,g); break; case dCylinderClass: printCylinder (c,g); break; case dPlaneClass: printPlane (c,g); break; case dRayClass: printRay (c,g); break; case dConvexClass: printConvex (c,g); break; case dTriMeshClass: printTriMesh (c,g); break; case dHeightfieldClass: printHeightfieldClass (c,g); break; } } //*************************************************************************** // world void dWorldExportDIF (dWorldID w, FILE *file, const char *prefix) { PrintingContext c; c.file = file; #if defined(dSINGLE) c.precision = 7; #else c.precision = 15; #endif c.indent = 1; fprintf (file,"-- Dynamics Interchange Format v0.1\n\n%sworld = dynamics.world {\n",prefix); c.print ("gravity",w->gravity); c.print ("ODE = {"); c.indent++; c.print ("ERP",w->global_erp); c.print ("CFM",w->global_cfm); c.print ("auto_disable = {"); c.indent++; c.print ("linear_threshold",w->adis.linear_average_threshold); c.print ("angular_threshold",w->adis.angular_average_threshold); c.print ("average_samples",(int)w->adis.average_samples); c.print ("idle_time",w->adis.idle_time); c.print ("idle_steps",w->adis.idle_steps); fprintf (file,"\t\t},\n\t},\n}\n"); c.indent -= 3; // bodies int num = 0; fprintf (file,"%sbody = {}\n",prefix); for (dxBody *b=w->firstbody; b; b=(dxBody*)b->next) { b->tag = num; fprintf (file,"%sbody[%d] = dynamics.body {\n\tworld = %sworld,\n",prefix,num,prefix); c.indent++; c.print ("pos",b->posr.pos); c.print ("q",b->q,4); c.print ("lvel",b->lvel); c.print ("avel",b->avel); c.print ("mass",b->mass.mass); fprintf (file,"\tI = {{"); for (int i=0; i<3; i++) { for (int j=0; j<3; j++) { c.printReal (b->mass.I[i*4+j]); if (j < 2) fputc (',',file); } if (i < 2) fprintf (file,"},{"); } fprintf (file,"}},\n"); c.printNonzero ("com",b->mass.c); c.print ("ODE = {"); c.indent++; if (b->flags & dxBodyFlagFiniteRotation) c.print ("finite_rotation",1); if (b->flags & dxBodyDisabled) c.print ("disabled",1); if (b->flags & dxBodyNoGravity) c.print ("no_gravity",1); if (b->flags & dxBodyAutoDisable) { c.print ("auto_disable = {"); c.indent++; c.print ("linear_threshold",b->adis.linear_average_threshold); c.print ("angular_threshold",b->adis.angular_average_threshold); c.print ("average_samples",(int)b->adis.average_samples); c.print ("idle_time",b->adis.idle_time); c.print ("idle_steps",b->adis.idle_steps); c.print ("time_left",b->adis_timeleft); c.print ("steps_left",b->adis_stepsleft); c.indent--; c.print ("},"); } c.printNonzero ("facc",b->facc); c.printNonzero ("tacc",b->tacc); if (b->flags & dxBodyFlagFiniteRotationAxis) { c.print ("finite_rotation_axis",b->finite_rot_axis); } c.indent--; c.print ("},"); if (b->geom) { c.print ("geometry = {"); c.indent++; for (dxGeom *g=b->geom; g; g=g->body_next) { c.print ("{"); c.indent++; printGeom (c,g); c.indent--; c.print ("},"); } c.indent--; c.print ("},"); } c.indent--; c.print ("}"); num++; } // joints num = 0; fprintf (file,"%sjoint = {}\n",prefix); for (dxJoint *j=w->firstjoint; j; j=(dxJoint*)j->next) { c.indent++; const char *name = getJointName (j); fprintf (file, "%sjoint[%d] = dynamics.%s_joint {\n" "\tworld = %sworld,\n" "\tbody = {" ,prefix,num,name,prefix); if ( j->node[0].body ) fprintf (file,"%sbody[%d]",prefix,j->node[0].body->tag); if ( j->node[1].body ) fprintf (file,",%sbody[%d]",prefix,j->node[1].body->tag); fprintf (file,"}\n"); switch (j->type()) { case dJointTypeBall: printBall (c,j); break; case dJointTypeHinge: printHinge (c,j); break; case dJointTypeSlider: printSlider (c,j); break; case dJointTypeContact: printContact (c,j); break; case dJointTypeUniversal: printUniversal (c,j); break; case dJointTypeHinge2: printHinge2 (c,j); break; case dJointTypeFixed: printFixed (c,j); break; case dJointTypeAMotor: printAMotor (c,j); break; case dJointTypeLMotor: printLMotor (c,j); break; case dJointTypePR: printPR (c,j); break; case dJointTypePU: printPU (c,j); break; case dJointTypePiston: printPiston (c,j); break; default: c.print("unknown joint"); } c.indent--; c.print ("}"); num++; } } ode-0.16/ode/src/quickstep.h0000664000175200017520000000374513403272463012672 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #ifndef _ODE_QUICK_STEP_H_ #define _ODE_QUICK_STEP_H_ #include struct dxStepperProcessingCallContext; sizeint dxEstimateQuickStepMemoryRequirements( dxBody * const *body, unsigned int nb, dxJoint * const *_joint, unsigned int _nj); unsigned dxEstimateQuickStepMaxCallCount( unsigned activeThreadCount, unsigned allowedThreadCount); void dxQuickStepIsland(const dxStepperProcessingCallContext *callContext); #endif ode-0.16/ode/src/collision_quadtreespace.cpp0000664000175200017520000004131113403272463016105 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ // QuadTreeSpace by Erwin de Vries. // With math corrections by Oleh Derevenko. ;) #include #include #include #include "config.h" #include "matrix.h" #include "collision_kernel.h" #include "collision_space_internal.h" #define AXIS0 0 #define AXIS1 1 #define UP 2 //#define DRAWBLOCKS const int SPLITAXIS = 2; const int SPLITS = SPLITAXIS * SPLITAXIS; #define GEOM_ENABLED(g) (((g)->gflags & GEOM_ENABLE_TEST_MASK) == GEOM_ENABLE_TEST_VALUE) class Block{ public: dReal mMinX, mMaxX; dReal mMinZ, mMaxZ; dGeomID mFirst; int mGeomCount; Block* mParent; Block* mChildren; void Create(const dReal MinX, const dReal MaxX, const dReal MinZ, const dReal MaxZ, Block* Parent, int Depth, Block*& Blocks); void Collide(void* UserData, dNearCallback* Callback); void Collide(dGeomID g1, dGeomID g2, void* UserData, dNearCallback* Callback); void CollideLocal(dGeomID g2, void* UserData, dNearCallback* Callback); void AddObject(dGeomID Object); void DelObject(dGeomID Object); void Traverse(dGeomID Object); bool Inside(const dReal* AABB); Block* GetBlock(const dReal* AABB); Block* GetBlockChild(const dReal* AABB); }; #ifdef DRAWBLOCKS #include "..\..\Include\drawstuff\\drawstuff.h" static void DrawBlock(Block* Block){ dVector3 v[8]; v[0][AXIS0] = Block->mMinX; v[0][UP] = REAL(-1.0); v[0][AXIS1] = Block->mMinZ; v[1][AXIS0] = Block->mMinX; v[1][UP] = REAL(-1.0); v[1][AXIS1] = Block->mMaxZ; v[2][AXIS0] = Block->mMaxX; v[2][UP] = REAL(-1.0); v[2][AXIS1] = Block->mMinZ; v[3][AXIS0] = Block->mMaxX; v[3][UP] = REAL(-1.0); v[3][AXIS1] = Block->mMaxZ; v[4][AXIS0] = Block->mMinX; v[4][UP] = REAL(1.0); v[4][AXIS1] = Block->mMinZ; v[5][AXIS0] = Block->mMinX; v[5][UP] = REAL(1.0); v[5][AXIS1] = Block->mMaxZ; v[6][AXIS0] = Block->mMaxX; v[6][UP] = REAL(1.0); v[6][AXIS1] = Block->mMinZ; v[7][AXIS0] = Block->mMaxX; v[7][UP] = REAL(1.0); v[7][AXIS1] = Block->mMaxZ; // Bottom dsDrawLine(v[0], v[1]); dsDrawLine(v[1], v[3]); dsDrawLine(v[3], v[2]); dsDrawLine(v[2], v[0]); // Top dsDrawLine(v[4], v[5]); dsDrawLine(v[5], v[7]); dsDrawLine(v[7], v[6]); dsDrawLine(v[6], v[4]); // Sides dsDrawLine(v[0], v[4]); dsDrawLine(v[1], v[5]); dsDrawLine(v[2], v[6]); dsDrawLine(v[3], v[7]); } #endif //DRAWBLOCKS void Block::Create(const dReal MinX, const dReal MaxX, const dReal MinZ, const dReal MaxZ, Block* Parent, int Depth, Block*& Blocks){ dIASSERT(MinX <= MaxX); dIASSERT(MinZ <= MaxZ); mGeomCount = 0; mFirst = 0; mMinX = MinX; mMaxX = MaxX; mMinZ = MinZ; mMaxZ = MaxZ; this->mParent = Parent; if (Depth > 0){ mChildren = Blocks; Blocks += SPLITS; const dReal ChildExtentX = (MaxX - MinX) / SPLITAXIS; const dReal ChildExtentZ = (MaxZ - MinZ) / SPLITAXIS; const int ChildDepth = Depth - 1; int Index = 0; dReal ChildRightX = MinX; for (int i = 0; i < SPLITAXIS; i++){ const dReal ChildLeftX = ChildRightX; ChildRightX = (i != SPLITAXIS - 1) ? ChildLeftX + ChildExtentX : MaxX; dReal ChildRightZ = MinZ; for (int j = 0; j < SPLITAXIS; j++){ const dReal ChildLeftZ = ChildRightZ; ChildRightZ = (j != SPLITAXIS - 1) ? ChildLeftZ + ChildExtentZ : MaxZ; mChildren[Index].Create(ChildLeftX, ChildRightX, ChildLeftZ, ChildRightZ, this, ChildDepth, Blocks); ++Index; } } } else mChildren = 0; } void Block::Collide(void* UserData, dNearCallback* Callback){ #ifdef DRAWBLOCKS DrawBlock(this); #endif // Collide the local list dxGeom* g = mFirst; while (g){ if (GEOM_ENABLED(g)){ Collide(g, g->next_ex, UserData, Callback); } g = g->next_ex; } // Recurse for children if (mChildren){ for (int i = 0; i < SPLITS; i++){ Block &CurrentChild = mChildren[i]; if (CurrentChild.mGeomCount <= 1){ // Early out continue; } CurrentChild.Collide(UserData, Callback); } } } // Note: g2 is assumed to be in this Block void Block::Collide(dxGeom* g1, dxGeom* g2, void* UserData, dNearCallback* Callback){ #ifdef DRAWBLOCKS DrawBlock(this); #endif // Collide against local list while (g2){ if (GEOM_ENABLED(g2)){ collideAABBs (g1, g2, UserData, Callback); } g2 = g2->next_ex; } // Collide against children if (mChildren){ for (int i = 0; i < SPLITS; i++){ Block &CurrentChild = mChildren[i]; // Early out for empty blocks if (CurrentChild.mGeomCount == 0){ continue; } // Does the geom's AABB collide with the block? // Don't do AABB tests for single geom blocks. if (CurrentChild.mGeomCount == 1){ // } else if (true){ if (g1->aabb[AXIS0 * 2 + 0] >= CurrentChild.mMaxX || g1->aabb[AXIS0 * 2 + 1] < CurrentChild.mMinX || g1->aabb[AXIS1 * 2 + 0] >= CurrentChild.mMaxZ || g1->aabb[AXIS1 * 2 + 1] < CurrentChild.mMinZ) continue; } CurrentChild.Collide(g1, CurrentChild.mFirst, UserData, Callback); } } } void Block::CollideLocal(dxGeom* g2, void* UserData, dNearCallback* Callback){ // Collide against local list dxGeom* g1 = mFirst; while (g1){ if (GEOM_ENABLED(g1)){ collideAABBs (g1, g2, UserData, Callback); } g1 = g1->next_ex; } } void Block::AddObject(dGeomID Object){ // Add the geom Object->next_ex = mFirst; mFirst = Object; Object->tome_ex = (dxGeom**)this; // Now traverse upwards to tell that we have a geom Block* Block = this; do{ Block->mGeomCount++; Block = Block->mParent; } while (Block); } void Block::DelObject(dGeomID Object){ // Del the geom dxGeom* g = mFirst; dxGeom* Last = 0; while (g){ if (g == Object){ if (Last){ Last->next_ex = g->next_ex; } else mFirst = g->next_ex; break; } Last = g; g = g->next_ex; } Object->tome_ex = 0; // Now traverse upwards to tell that we have lost a geom Block* Block = this; do{ Block->mGeomCount--; Block = Block->mParent; } while (Block); } void Block::Traverse(dGeomID Object){ Block* NewBlock = GetBlock(Object->aabb); if (NewBlock != this){ // Remove the geom from the old block and add it to the new block. // This could be more optimal, but the loss should be very small. DelObject(Object); NewBlock->AddObject(Object); } } bool Block::Inside(const dReal* AABB){ return AABB[AXIS0 * 2 + 0] >= mMinX && AABB[AXIS0 * 2 + 1] < mMaxX && AABB[AXIS1 * 2 + 0] >= mMinZ && AABB[AXIS1 * 2 + 1] < mMaxZ; } Block* Block::GetBlock(const dReal* AABB){ if (Inside(AABB)){ return GetBlockChild(AABB); // Child or this will have a good block } else if (mParent){ return mParent->GetBlock(AABB); // Parent has a good block } else return this; // We are at the root, so we have little choice } Block* Block::GetBlockChild(const dReal* AABB){ if (mChildren){ for (int i = 0; i < SPLITS; i++){ Block &CurrentChild = mChildren[i]; if (CurrentChild.Inside(AABB)){ return CurrentChild.GetBlockChild(AABB); // Child will have good block } } } return this; // This is the best block } //**************************************************************************** // quadtree space struct dxQuadTreeSpace : public dxSpace{ Block* Blocks; // Blocks[0] is the root dArray DirtyList; dxQuadTreeSpace(dSpaceID _space, const dVector3 Center, const dVector3 Extents, int Depth); ~dxQuadTreeSpace(); dxGeom* getGeom(int i); void add(dxGeom* g); void remove(dxGeom* g); void dirty(dxGeom* g); void computeAABB(); void cleanGeoms(); void collide(void* UserData, dNearCallback* Callback); void collide2(void* UserData, dxGeom* g1, dNearCallback* Callback); // Temp data Block* CurrentBlock; // Only used while enumerating int* CurrentChild; // Only used while enumerating int CurrentLevel; // Only used while enumerating dxGeom* CurrentObject; // Only used while enumerating int CurrentIndex; }; namespace { inline sizeint numNodes(int depth) { // A 4-ary tree has (4^(depth+1) - 1)/3 nodes // Note: split up into multiple constant expressions for readability const int k = depth+1; const sizeint fourToNthPlusOne = (sizeint)1 << (2*k); // 4^k = 2^(2k) return (fourToNthPlusOne - 1) / 3; } } dxQuadTreeSpace::dxQuadTreeSpace(dSpaceID _space, const dVector3 Center, const dVector3 Extents, int Depth) : dxSpace(_space){ type = dQuadTreeSpaceClass; sizeint BlockCount = numNodes(Depth); Blocks = (Block*)dAlloc(BlockCount * sizeof(Block)); Block* Blocks = this->Blocks + 1; // This pointer gets modified! dReal MinX = Center[AXIS0] - Extents[AXIS0]; dReal MaxX = dNextAfter((Center[AXIS0] + Extents[AXIS0]), (dReal)dInfinity); dReal MinZ = Center[AXIS1] - Extents[AXIS1]; dReal MaxZ = dNextAfter((Center[AXIS1] + Extents[AXIS1]), (dReal)dInfinity); this->Blocks[0].Create(MinX, MaxX, MinZ, MaxZ, 0, Depth, Blocks); CurrentBlock = 0; CurrentChild = (int*)dAlloc((Depth + 1) * sizeof(int)); CurrentLevel = 0; CurrentObject = 0; CurrentIndex = -1; // Init AABB. We initialize to infinity because it is not illegal for an object to be outside of the tree. Its simply inserted in the root block aabb[0] = -dInfinity; aabb[1] = dInfinity; aabb[2] = -dInfinity; aabb[3] = dInfinity; aabb[4] = -dInfinity; aabb[5] = dInfinity; } dxQuadTreeSpace::~dxQuadTreeSpace(){ int Depth = 0; Block* Current = &Blocks[0]; while (Current){ Depth++; Current = Current->mChildren; } sizeint BlockCount = numNodes(Depth); dFree(Blocks, BlockCount * sizeof(Block)); dFree(CurrentChild, (Depth + 1) * sizeof(int)); } dxGeom* dxQuadTreeSpace::getGeom(int Index){ dUASSERT(Index >= 0 && Index < count, "index out of range"); //@@@ dDebug (0,"dxQuadTreeSpace::getGeom() not yet implemented"); return 0; // This doesnt work /* if (CurrentIndex == Index){ // Loop through all objects in the local list CHILDRECURSE: if (CurrentObject){ dGeomID g = CurrentObject; CurrentObject = CurrentObject->next_ex; CurrentIndex++; #ifdef DRAWBLOCKS DrawBlock(CurrentBlock); #endif //DRAWBLOCKS return g; } else{ // Now lets loop through our children. Starting at index 0. if (CurrentBlock->Children){ CurrentChild[CurrentLevel] = 0; PARENTRECURSE: for (int& i = CurrentChild[CurrentLevel]; i < SPLITS; i++){ if (CurrentBlock->Children[i].GeomCount == 0){ continue; } CurrentBlock = &CurrentBlock->Children[i]; CurrentObject = CurrentBlock->First; i++; CurrentLevel++; goto CHILDRECURSE; } } } // Now lets go back to the parent so it can continue processing its other children. if (CurrentBlock->Parent){ CurrentBlock = CurrentBlock->Parent; CurrentLevel--; goto PARENTRECURSE; } } else{ CurrentBlock = &Blocks[0]; CurrentLevel = 0; CurrentObject = CurrentObject; CurrentIndex = 0; // Other states are already set CurrentObject = CurrentBlock->First; } if (current_geom && current_index == Index - 1){ //current_geom = current_geom->next_ex; // next current_index = Index; return current_geom; } else for (int i = 0; i < Index; i++){ // this will be verrrrrrry slow getGeom(i); } */ return 0; } void dxQuadTreeSpace::add(dxGeom* g){ CHECK_NOT_LOCKED (this); dAASSERT(g); dUASSERT(g->tome_ex == 0 && g->next_ex == 0, "geom is already in a space"); DirtyList.push(g); Blocks[0].GetBlock(g->aabb)->AddObject(g); // Add to best block dxSpace::add(g); } void dxQuadTreeSpace::remove(dxGeom* g){ CHECK_NOT_LOCKED(this); dAASSERT(g); dUASSERT(g->parent_space == this,"object is not in this space"); // remove ((Block*)g->tome_ex)->DelObject(g); for (int i = 0; i < DirtyList.size(); i++){ if (DirtyList[i] == g){ DirtyList.remove(i); // (mg) there can be multiple instances of a dirty object on stack be sure to remove ALL and not just first, for this we decrement i --i; } } dxSpace::remove(g); } void dxQuadTreeSpace::dirty(dxGeom* g){ DirtyList.push(g); } void dxQuadTreeSpace::computeAABB(){ // } void dxQuadTreeSpace::cleanGeoms(){ // compute the AABBs of all dirty geoms, and clear the dirty flags lock_count++; for (int i = 0; i < DirtyList.size(); i++){ dxGeom* g = DirtyList[i]; if (IS_SPACE(g)){ ((dxSpace*)g)->cleanGeoms(); } g->recomputeAABB(); dIASSERT((g->gflags & GEOM_AABB_BAD) == 0); g->gflags &= ~GEOM_DIRTY; ((Block*)g->tome_ex)->Traverse(g); } DirtyList.setSize(0); lock_count--; } void dxQuadTreeSpace::collide(void* UserData, dNearCallback* Callback){ dAASSERT(Callback); lock_count++; cleanGeoms(); Blocks[0].Collide(UserData, Callback); lock_count--; } struct DataCallback { void *data; dNearCallback *callback; }; // Invokes the callback with arguments swapped static void swap_callback(void *data, dxGeom *g1, dxGeom *g2) { DataCallback *dc = (DataCallback*)data; dc->callback(dc->data, g2, g1); } void dxQuadTreeSpace::collide2(void* UserData, dxGeom* g2, dNearCallback* Callback){ dAASSERT(g2 && Callback); lock_count++; cleanGeoms(); g2->recomputeAABB(); if (g2->parent_space == this){ // The block the geom is in Block* CurrentBlock = (Block*)g2->tome_ex; // Collide against block and its children DataCallback dc = {UserData, Callback}; CurrentBlock->Collide(g2, CurrentBlock->mFirst, &dc, swap_callback); // Collide against parents while ((CurrentBlock = CurrentBlock->mParent)) CurrentBlock->CollideLocal(g2, UserData, Callback); } else { DataCallback dc = {UserData, Callback}; Blocks[0].Collide(g2, Blocks[0].mFirst, &dc, swap_callback); } lock_count--; } dSpaceID dQuadTreeSpaceCreate(dxSpace* space, const dVector3 Center, const dVector3 Extents, int Depth){ return new dxQuadTreeSpace(space, Center, Extents, Depth); } ode-0.16/ode/src/resource_control.h0000664000175200017520000001353713403272463014251 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* * Resource accounting/preallocation class declarations * Copyright (c) 2017 Oleh Derevenko, odar@eleks.com (change all "a" to "e") */ #ifndef _ODE__PRIVATE_RESOURCE_CONTRIOL_H_ #define _ODE__PRIVATE_RESOURCE_CONTRIOL_H_ #include "objects.h" #include "threading_base.h" #include "odeou.h" #include "common.h" #include "error.h" using _OU_NAMESPACE::CSimpleFlags; class dxResourceRequirementDescriptor: public dBase { public: explicit dxResourceRequirementDescriptor(dxThreadingBase *relatedThreading): dBase(), m_relatedThreading(relatedThreading), m_memorySizeRequirement(0), m_memoryAlignmentRequirement(0), m_simultaneousCallRequirement(0), m_featureRequirements() { } ~dxResourceRequirementDescriptor(); enum { STOCK_CALLWAIT_REQUIRED = 0x00000001, }; void mergeAnotherDescriptorIn(const dxResourceRequirementDescriptor &anotherDescriptor) { dIASSERT(getrelatedThreading() == anotherDescriptor.getrelatedThreading()); // m_simultaneousCallRequirement typically depends on threading used CSimpleFlags::value_type allOtherFeatureFlags = anotherDescriptor.queryAllFeatureFlags(); mergeAnotherDescriptorIn(anotherDescriptor.m_memorySizeRequirement, anotherDescriptor.m_memoryAlignmentRequirement, anotherDescriptor.m_simultaneousCallRequirement, allOtherFeatureFlags); } void mergeAnotherDescriptorIn(sizeint memorySizeRequirement/*=0*/, unsigned memoryAlignmentRequirement, unsigned simultaneousCallRequirement/*=0*/, unsigned featureRequirement/*=0*/) { m_memorySizeRequirement = dMACRO_MAX(m_memorySizeRequirement, memorySizeRequirement); m_memoryAlignmentRequirement = dMACRO_MAX(m_memoryAlignmentRequirement, memoryAlignmentRequirement); m_simultaneousCallRequirement = dMACRO_MAX(m_simultaneousCallRequirement, simultaneousCallRequirement); mergeFeatureFlags(featureRequirement); } public: dxThreadingBase *getrelatedThreading() const { return m_relatedThreading; } sizeint getMemorySizeRequirement() const { return m_memorySizeRequirement; } unsigned getMemoryAlignmentRequirement() const { return m_memoryAlignmentRequirement; } unsigned getSimultaneousCallRequirement() const { return m_simultaneousCallRequirement; } bool getIsStockCallWaitRequired() const { return getStockCallWaitRequiredFlag(); } private: enum { FL_STOCK_CALLWAIT_REQUIRED = STOCK_CALLWAIT_REQUIRED, }; bool getStockCallWaitRequiredFlag() const { return m_featureRequirements.GetFlagsMaskValue(FL_STOCK_CALLWAIT_REQUIRED); } CSimpleFlags::value_type queryAllFeatureFlags() const { return m_featureRequirements.QueryFlagsAllValues(); } void mergeFeatureFlags(CSimpleFlags::value_type flagValues) { m_featureRequirements.SignalFlagsMaskValue(flagValues); } private: dxThreadingBase *m_relatedThreading; sizeint m_memorySizeRequirement; unsigned m_memoryAlignmentRequirement; unsigned m_simultaneousCallRequirement; CSimpleFlags m_featureRequirements; }; static inline dxResourceRequirementDescriptor *decodeResourceRequirementsID(dResourceRequirementsID requirements) { return (dxResourceRequirementDescriptor *)requirements; } class dxRequiredResourceContainer: public dBase { public: dxRequiredResourceContainer(): dBase(), m_relatedThreading(NULL), m_stockCallWait(NULL), m_memoryAllocation() { } ~dxRequiredResourceContainer(); bool allocateResources(const dxResourceRequirementDescriptor &requirementDescriptor); void freeResources(); public: dxThreadingBase *getThreadingInstance() const { return m_relatedThreading; } dCallWaitID getStockCallWait() const { return m_stockCallWait; } void *getMemoryBufferPointer() const { return m_memoryAllocation.getUserAreaPointer(); } sizeint getMemoryBufferSize() const { return m_memoryAllocation.getUserAreaSize(); } private: dxThreadingBase *m_relatedThreading; dCallWaitID m_stockCallWait; dxAlignedAllocation m_memoryAllocation; }; static inline dxRequiredResourceContainer *decodeResourceContainerID(dResourceContainerID resources) { return (dxRequiredResourceContainer *)resources; } #endif // #ifndef _ODE__PRIVATE_RESOURCE_CONTRIOL_H_ ode-0.16/ode/src/collision_std.h0000664000175200017520000002165113403272463013523 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* the standard ODE geometry primitives. */ #ifndef _ODE_COLLISION_STD_H_ #define _ODE_COLLISION_STD_H_ #include #include "collision_kernel.h" // primitive collision functions - these have the dColliderFn interface, i.e. // the same interface as dCollide(). the first and second geom arguments must // have the specified types. int dCollideSphereSphere (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); int dCollideSphereBox (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); int dCollideSpherePlane (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); int dCollideBoxBox (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); int dCollideBoxPlane (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); int dCollideCapsuleSphere (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); int dCollideCapsuleBox (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); int dCollideCapsuleCapsule (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); int dCollideCapsulePlane (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); int dCollideRaySphere (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); int dCollideRayBox (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); int dCollideRayCapsule (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); int dCollideRayPlane (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); int dCollideRayCylinder (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); // Cylinder - Box/Sphere by (C) CroTeam // Ported by Nguyen Binh int dCollideCylinderBox(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); int dCollideCylinderSphere(dxGeom *gCylinder, dxGeom *gSphere, int flags, dContactGeom *contact, int skip); int dCollideCylinderPlane(dxGeom *gCylinder, dxGeom *gPlane, int flags, dContactGeom *contact, int skip); //--> Convex Collision int dCollideConvexPlane (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); int dCollideSphereConvex (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); int dCollideConvexBox (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); int dCollideConvexCapsule (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); int dCollideConvexConvex (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); int dCollideRayConvex (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); //<-- Convex Collision // dHeightfield int dCollideHeightfield( dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip ); //**************************************************************************** // the basic geometry objects struct dxSphere : public dxGeom { dReal radius; // sphere radius dxSphere (dSpaceID space, dReal _radius); void computeAABB(); }; struct dxBox : public dxGeom { dVector3 side; // side lengths (x,y,z) dxBox (dSpaceID space, dReal lx, dReal ly, dReal lz); void computeAABB(); }; struct dxCapsule : public dxGeom { dReal radius,lz; // radius, length along z axis dxCapsule (dSpaceID space, dReal _radius, dReal _length); void computeAABB(); }; struct dxCylinder : public dxGeom { dReal radius,lz; // radius, length along z axis dxCylinder (dSpaceID space, dReal _radius, dReal _length); void computeAABB(); }; struct dxPlane : public dxGeom { dReal p[4]; dxPlane (dSpaceID space, dReal a, dReal b, dReal c, dReal d); void computeAABB(); }; struct dxRay : public dxGeom { dReal length; dxRay (dSpaceID space, dReal _length); void computeAABB(); }; struct dxConvex : public dxGeom { const dReal *planes; /*!< An array of planes in the form: normal X, normal Y, normal Z,Distance */ const dReal *points; /*!< An array of points X,Y,Z */ const unsigned int *polygons; /*! An array of indices to the points of each polygon, it should be the number of vertices followed by that amount of indices to "points" in counter clockwise order*/ unsigned int planecount; /*!< Amount of planes in planes */ unsigned int pointcount;/*!< Amount of points in points */ unsigned int edgecount;/*!< Amount of edges in convex */ dReal saabb[6];/*!< Static AABB */ dxConvex(dSpaceID space, const dReal *planes, unsigned int planecount, const dReal *points, unsigned int pointcount, const unsigned int *polygons); ~dxConvex() { if((edgecount!=0)&&(edges!=NULL)) delete[] edges; } void computeAABB(); struct edge { unsigned int first; unsigned int second; }; edge* edges; /*! \brief A Support mapping function for convex shapes \param dir [IN] direction to find the Support Point for \return the index of the support vertex. */ inline unsigned int SupportIndex(dVector3 dir) { dVector3 rdir; unsigned int index=0; dMultiply1_331 (rdir,final_posr->R,dir); dReal max = dCalcVectorDot3(points,rdir); dReal tmp; for (unsigned int i = 1; i < pointcount; ++i) { tmp = dCalcVectorDot3(points+(i*3),rdir); if (tmp > max) { index=i; max = tmp; } } return index; } private: // For Internal Use Only /*! \brief Fills the edges dynamic array based on points and polygons. */ void FillEdges(); #if 0 /* What this does is the same as the Support function by doing some preprocessing for optimization. Not complete yet. */ // Based on Eberly's Game Physics Book page 307 struct Arc { // indices of polyhedron normals that form the spherical arc int normals[2]; // index of edge shared by polyhedron faces int edge; }; struct Polygon { // indices of polyhedron normals that form the spherical polygon std::vector normals; // index of extreme vertex corresponding to this polygon int vertex; }; // This is for extrem feature query and not the usual level BSP structure (that comes later) struct BSPNode { // Normal index (interior node), vertex index (leaf node) int normal; // if Dot (E,D)>=0, D gets propagated to this child BSPNode* right; // if Dot (E,D)<0, D gets propagated to this child BSPNode* left; }; void CreateTree(); BSPNode* CreateNode(std::vector Arcs,std::vector Polygons); void GetFacesSharedByVertex(int i, std::vector f); void GetFacesSharedByEdge(int i, int* f); void GetFaceNormal(int i, dVector3 normal); BSPNode* tree; #endif }; #endif ode-0.16/ode/src/collision_convex_trimesh.cpp0000664000175200017520000001152213403272463016315 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include #include "config.h" #include "matrix.h" #include "odemath.h" typedef struct _sLocalContactData { dVector3 vPos; dVector3 vNormal; dReal fDepth; int triIndex; int nFlags; // 0 = filtered out, 1 = OK }sLocalContactData; #if dTRIMESH_ENABLED #include "collision_util.h" #include "collision_std.h" #include "collision_trimesh_internal.h" #if dLIBCCD_ENABLED #include "collision_libccd.h" #endif int dCollideConvexTrimesh( dxGeom *o1, dxGeom *o2, int flags, dContactGeom* contacts, int skip ) { int contactcount = 0; dIASSERT( skip >= (int)sizeof( dContactGeom ) ); dIASSERT( o1->type == dConvexClass ); dIASSERT( o2->type == dTriMeshClass ); dIASSERT ((flags & NUMC_MASK) >= 1); #if dLIBCCD_ENABLED #if dTRIMESH_OPCODE const dVector3 &meshPosition = *(const dVector3 *)dGeomGetPosition(o2); // Find convex OBB in trimesh coordinates Point convexAABBMin(o1->aabb[0] - meshPosition[0], o1->aabb[2] - meshPosition[1], o1->aabb[4] - meshPosition[2]); Point convexAABBMax(o1->aabb[1] - meshPosition[0], o1->aabb[3] - meshPosition[1], o1->aabb[5] - meshPosition[2]); const Point convexCenter = 0.5f * (convexAABBMax + convexAABBMin); const Point convexExtents = 0.5f * (convexAABBMax - convexAABBMin); const Matrix3x3 convexRotation(1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f); OBB convexOOB(convexCenter, convexExtents, convexRotation); Matrix4x4 meshTransformation; const dMatrix3 &meshRotation = *(const dMatrix3 *)dGeomGetRotation(o2); const dVector3 zeroVector = { REAL(0.0), }; MakeMatrix(zeroVector, meshRotation, meshTransformation); OBBCollider collider; collider.SetFirstContact(false); collider.SetTemporalCoherence(false); collider.SetPrimitiveTests(false); OBBCache cache; dxTriMesh *trimesh = (dxTriMesh *)o2; if (collider.Collide(cache, convexOOB, trimesh->retrieveMeshBVTreeRef(), null, &meshTransformation)) { int triCount = collider.GetNbTouchedPrimitives(); if (triCount > 0) { int* triangles = (int*)collider.GetTouchedPrimitives(); contactcount = dCollideConvexTrimeshTrianglesCCD(o1, o2, triangles, triCount, flags, contacts, skip); } } #elif dTRIMESH_GIMPACT dxTriMesh *trimesh = (dxTriMesh *)o2; aabb3f test_aabb(o1->aabb[0], o1->aabb[1], o1->aabb[2], o1->aabb[3], o1->aabb[4], o1->aabb[5]); GDYNAMIC_ARRAY collision_result; GIM_CREATE_BOXQUERY_LIST(collision_result); gim_aabbset_box_collision(&test_aabb, &trimesh->m_collision_trimesh.m_aabbset, &collision_result); if (collision_result.m_size != 0) { GUINT32 * boxesresult = GIM_DYNARRAY_POINTER(GUINT32,collision_result); GIM_TRIMESH * ptrimesh = &trimesh->m_collision_trimesh; gim_trimesh_locks_work_data(ptrimesh); contactcount = dCollideConvexTrimeshTrianglesCCD(o1, o2, (int *)boxesresult, collision_result.m_size, flags, contacts, skip); gim_trimesh_unlocks_work_data(ptrimesh); } GIM_DYNARRAY_DESTROY(collision_result); #endif // dTRIMESH_GIMPACT #endif // dLIBCCD_ENABLED return contactcount; } #endif // dTRIMESH_ENABLED ode-0.16/ode/src/fastldltsolve.cpp0000664000175200017520000002131313403272463014072 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* * LDLT solving related code of ThreadedEquationSolverLDLT * Copyright (c) 2017 Oleh Derevenko, odar@eleks.com (change all "a" to "e") */ #include #include #include #include "config.h" #include "threaded_solver_ldlt.h" #include "threading_base.h" #include "resource_control.h" #include "fastldltsolve_impl.h" /*static */ void ThreadedEquationSolverLDLT::estimateCooperativeSolvingLDLTResourceRequirements( dxResourceRequirementDescriptor *summaryRequirementsDescriptor, unsigned allowedThreadCount, unsigned rowCount) { unsigned stageBlockCountSifficiencyMask; dxThreadingBase *threading = summaryRequirementsDescriptor->getrelatedThreading(); unsigned limitedThreadCount = restrictSolvingLDLTAllowedThreadCount(threading, allowedThreadCount, rowCount, stageBlockCountSifficiencyMask); if (limitedThreadCount > 1) { if ((stageBlockCountSifficiencyMask & (1U << SLDLTS_SOLVING_STRAIGHT)) != 0) { doEstimateCooperativeSolvingL1StraightResourceRequirementsValidated(summaryRequirementsDescriptor, allowedThreadCount, rowCount); } if ((stageBlockCountSifficiencyMask & (1U << SLDLTS_SCALING_VECTOR)) != 0) { doEstimateCooperativeScalingVectorResourceRequirementsValidated(summaryRequirementsDescriptor, allowedThreadCount, rowCount); } if ((stageBlockCountSifficiencyMask & (1U << SLDLTS_SOLVING_TRANSPOSED)) == 0) { doEstimateCooperativeSolvingL1TransposedResourceRequirementsValidated(summaryRequirementsDescriptor, allowedThreadCount, rowCount); } } } /*static */ void ThreadedEquationSolverLDLT::cooperativelySolveLDLT( dxRequiredResourceContainer *resourceContainer, unsigned allowedThreadCount, const dReal *L, const dReal *d, dReal *b, unsigned rowCount, unsigned rowSkip) { dAASSERT(rowCount != 0); unsigned stageBlockCountSifficiencyMask; dxThreadingBase *threading = resourceContainer->getThreadingInstance(); unsigned limitedThreadCount = restrictSolvingLDLTAllowedThreadCount(threading, allowedThreadCount, rowCount, stageBlockCountSifficiencyMask); if (limitedThreadCount <= 1) { solveEquationSystemWithLDLT(L, d, b, rowCount, rowSkip); } else { doCooperativelySolveLDLTValidated(resourceContainer, limitedThreadCount, stageBlockCountSifficiencyMask, L, d, b, rowCount, rowSkip); } } /*static */ unsigned ThreadedEquationSolverLDLT::restrictSolvingLDLTAllowedThreadCount( dxThreadingBase *threading, unsigned allowedThreadCount, unsigned rowCount, unsigned &out_stageBlockCountSifficiencyMask) { unsigned limitedThreadCount = 1; unsigned stageBlockCountSifficiencyMask = 0; #if dCOOPERATIVE_ENABLED { const unsigned int blockStep = SL1S_BLOCK_SIZE; // Required by the implementation unsigned solvingStraightBlockCount = deriveSolvingL1StraightBlockCount(rowCount, blockStep); dIASSERT(deriveSolvingL1StraightThreadCount(SL1S_COOPERATIVE_BLOCK_COUNT_MINIMUM, 2) > 1); if (solvingStraightBlockCount >= SL1S_COOPERATIVE_BLOCK_COUNT_MINIMUM) { stageBlockCountSifficiencyMask |= 1U << SLDLTS_SOLVING_STRAIGHT; } } { const unsigned int blockStep = SV_BLOCK_SIZE; // Required by the implementation unsigned scalingBlockCount = deriveScalingVectorBlockCount(rowCount, blockStep); dIASSERT(deriveScalingVectorThreadCount(SV_COOPERATIVE_BLOCK_COUNT_MINIMUM - 1, 2) > 1); if (scalingBlockCount >= SV_COOPERATIVE_BLOCK_COUNT_MINIMUM) { stageBlockCountSifficiencyMask |= 1U << SLDLTS_SCALING_VECTOR; } } { const unsigned int blockStep = SL1T_BLOCK_SIZE; // Required by the implementation unsigned solvingTransposedBlockCount = deriveSolvingL1TransposedBlockCount(rowCount, blockStep); dIASSERT(deriveSolvingL1TransposedThreadCount(SL1T_COOPERATIVE_BLOCK_COUNT_MINIMUM, 2) > 1); if (solvingTransposedBlockCount >= SL1T_COOPERATIVE_BLOCK_COUNT_MINIMUM) { stageBlockCountSifficiencyMask |= 1U << SLDLTS_SOLVING_TRANSPOSED; } } if (stageBlockCountSifficiencyMask != 0) { limitedThreadCount = threading->calculateThreadingLimitedThreadCount(allowedThreadCount, true); } #endif // #if dCOOPERATIVE_ENABLED out_stageBlockCountSifficiencyMask = stageBlockCountSifficiencyMask; return limitedThreadCount; } /*static */ void ThreadedEquationSolverLDLT::doCooperativelySolveLDLTValidated( dxRequiredResourceContainer *resourceContainer, unsigned allowedThreadCount, unsigned stageBlockCountSifficiencyMask, const dReal *L, const dReal *d, dReal *b, unsigned rowCount, unsigned rowSkip) { dIASSERT(allowedThreadCount > 1); if ((stageBlockCountSifficiencyMask & (1U << SLDLTS_SOLVING_STRAIGHT)) == 0) { solveL1Straight(L, b, rowCount, rowSkip); } else { dSASSERT(SLDLT_B_STRIDE + 0 == SL1S_B_STRIDE); doCooperativelySolveL1StraightValidated(resourceContainer, allowedThreadCount, L, b, rowCount, rowSkip); } if ((stageBlockCountSifficiencyMask & (1U << SLDLTS_SCALING_VECTOR)) == 0) { scaleLargeVector(b, d, rowCount); } else { dSASSERT(SLDLT_B_STRIDE + 0 == SV_A_STRIDE); dSASSERT(SLDLT_D_STRIDE + 0 == SV_D_STRIDE); doCooperativelyScaleVectorValidated(resourceContainer, allowedThreadCount, b, d, rowCount); } if ((stageBlockCountSifficiencyMask & (1U << SLDLTS_SOLVING_TRANSPOSED)) == 0) { solveL1Transposed(L, b, rowCount, rowSkip); } else { dSASSERT(SLDLT_B_STRIDE + 0 == SL1T_B_STRIDE); doCooperativelySolveL1TransposedValidated(resourceContainer, allowedThreadCount, L, b, rowCount, rowSkip); } } ////////////////////////////////////////////////////////////////////////// // Public interface functions /*extern ODE_API */ void dSolveLDLT(const dReal *L, const dReal *d, dReal *b, int n, int nskip) { dAASSERT(n != 0); if (n != 0) { dAASSERT(L != NULL); dAASSERT(d != NULL); dAASSERT(b != NULL); solveEquationSystemWithLDLT<1, 1>(L, d, b, n, nskip); } } /*extern ODE_API */ void dEstimateCooperativelySolveLDLTResourceRequirements(dResourceRequirementsID requirements, unsigned maximalAllowedThreadCount, unsigned maximalRowCount) { dAASSERT(requirements != NULL); dxResourceRequirementDescriptor *requirementsDescriptor = (dxResourceRequirementDescriptor *)requirements; ThreadedEquationSolverLDLT::estimateCooperativeSolvingLDLTResourceRequirements(requirementsDescriptor, maximalAllowedThreadCount, maximalRowCount); } /*extern ODE_API */ void dCooperativelySolveLDLT(dResourceContainerID resources, unsigned allowedThreadCount, const dReal *L, const dReal *d, dReal *b, unsigned rowCount, unsigned rowSkip) { dAASSERT(resources != NULL); dxRequiredResourceContainer *resourceContainer = (dxRequiredResourceContainer *)resources; ThreadedEquationSolverLDLT::cooperativelySolveLDLT(resourceContainer, allowedThreadCount, L, d, b, rowCount, rowSkip); } ode-0.16/ode/src/objects.cpp0000664000175200017520000001017413403272463012640 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ // Object, body, and world methods. #include #include #include #include "config.h" #include "objects.h" #include "default_threading.h" #include "threading_impl.h" #include "matrix.h" #include "util.h" #define dWORLD_DEFAULT_GLOBAL_ERP REAL(0.2) #if defined(dSINGLE) #define dWORLD_DEFAULT_GLOBAL_CFM REAL(1e-5) #elif defined(dDOUBLE) #define dWORLD_DEFAULT_GLOBAL_CFM REAL(1e-10) #else #error dSINGLE or dDOUBLE must be defined #endif dObject::~dObject() { // Do nothing - a virtual destructor } dxAutoDisable::dxAutoDisable(void *): idle_time(REAL(0.0)), idle_steps(10), average_samples(1), // Default is 1 sample => Instantaneous velocity linear_average_threshold(REAL(0.01)*REAL(0.01)), // (magnitude squared) angular_average_threshold(REAL(0.01)*REAL(0.01)) // (magnitude squared) { } dxDampingParameters::dxDampingParameters(void *): linear_scale(REAL(0.0)), angular_scale(REAL(0.0)), linear_threshold(REAL(0.01) * REAL(0.01)), angular_threshold(REAL(0.01) * REAL(0.01)) { } dxQuickStepParameters::dxQuickStepParameters(void *): num_iterations(20), w(REAL(1.3)) { } dxContactParameters::dxContactParameters(void *): max_vel(dInfinity), min_depth(REAL(0.0)) { } dxWorld::dxWorld(): dBase(), dxThreadingBase(), firstbody(NULL), firstjoint(NULL), nb(0), nj(0), global_erp(dWORLD_DEFAULT_GLOBAL_ERP), global_cfm(dWORLD_DEFAULT_GLOBAL_CFM), adis(NULL), body_flags(0), islands_max_threads(dWORLDSTEP_THREADCOUNT_UNLIMITED), wmem(NULL), qs(NULL), contactp(NULL), dampingp(NULL), max_angular_speed(dInfinity), userdata(0) { dxThreadingBase::setThreadingDefaultImplProvider(this); dSetZero (gravity, 4); } dxWorld::~dxWorld() { if (wmem) { wmem->CleanupWorldReferences(this); wmem->Release(); } } void dxWorld::assignThreadingImpl(const dxThreadingFunctionsInfo *functions_info, dThreadingImplementationID threading_impl) { if (wmem != NULL) { // Free objects allocated with old threading wmem->CleanupWorldReferences(this); } dxThreadingBase::assignThreadingImpl(functions_info, threading_impl); } dxWorldProcessContext *dxWorld::unsafeGetWorldProcessingContext() const { return wmem->GetWorldProcessingContext(); } const dxThreadingFunctionsInfo *dxWorld::retrieveThreadingDefaultImpl(dThreadingImplementationID &out_defaultImpl) { out_defaultImpl = DefaultThreadingHolder::getDefaultThreadingImpl(); return DefaultThreadingHolder::getDefaultThreadingFunctions(); } ode-0.16/ode/src/collision_transform.h0000664000175200017520000000344713403272463014747 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* geom transform */ #ifndef _ODE_COLLISION_TRANSFORM_H_ #define _ODE_COLLISION_TRANSFORM_H_ #include #include "collision_kernel.h" int dCollideTransform (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); #endif ode-0.16/ode/src/error.cpp0000664000175200017520000001126513403272463012342 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include #include "config.h" static dMessageFunction *error_function = 0; static dMessageFunction *debug_function = 0; static dMessageFunction *message_function = 0; extern "C" void dSetErrorHandler (dMessageFunction *fn) { error_function = fn; } extern "C" void dSetDebugHandler (dMessageFunction *fn) { debug_function = fn; } extern "C" void dSetMessageHandler (dMessageFunction *fn) { message_function = fn; } extern "C" dMessageFunction *dGetErrorHandler() { return error_function; } extern "C" dMessageFunction *dGetDebugHandler() { return debug_function; } extern "C" dMessageFunction *dGetMessageHandler() { return message_function; } static void printMessage (int num, const char *msg1, const char *msg2, va_list ap) { fflush (stderr); fflush (stdout); if (num) fprintf (stderr,"\n%s %d: ",msg1,num); else fprintf (stderr,"\n%s: ",msg1); vfprintf (stderr,msg2,ap); fprintf (stderr,"\n"); fflush (stderr); } //**************************************************************************** // unix #ifndef WIN32 extern "C" void dError (int num, const char *msg, ...) { va_list ap; va_start (ap,msg); if (error_function) error_function (num,msg,ap); else printMessage (num,"ODE Error",msg,ap); va_end (ap); exit (1); } extern "C" void dDebug (int num, const char *msg, ...) { va_list ap; va_start (ap,msg); if (debug_function) debug_function (num,msg,ap); else printMessage (num,"ODE INTERNAL ERROR",msg,ap); va_end (ap); // *((char *)0) = 0; ... commit SEGVicide abort(); } extern "C" void dMessage (int num, const char *msg, ...) { va_list ap; va_start (ap,msg); if (message_function) message_function (num,msg,ap); else printMessage (num,"ODE Message",msg,ap); va_end (ap); } #endif //**************************************************************************** // windows #ifdef WIN32 // isn't cygwin annoying! #ifdef CYGWIN #define _snprintf snprintf #define _vsnprintf vsnprintf #endif #include "windows.h" extern "C" void dError (int num, const char *msg, ...) { va_list ap; va_start (ap,msg); if (error_function) error_function (num,msg,ap); else { char s[1000],title[100]; _snprintf (title,sizeof(title),"ODE Error %d",num); _vsnprintf (s,sizeof(s),msg,ap); s[sizeof(s)-1] = 0; MessageBox(0,s,title,MB_OK | MB_ICONWARNING); } va_end (ap); exit (1); } extern "C" void dDebug (int num, const char *msg, ...) { va_list ap; va_start (ap,msg); if (debug_function) debug_function (num,msg,ap); else { char s[1000],title[100]; _snprintf (title,sizeof(title),"ODE INTERNAL ERROR %d",num); _vsnprintf (s,sizeof(s),msg,ap); s[sizeof(s)-1] = 0; MessageBox(0,s,title,MB_OK | MB_ICONSTOP); } va_end (ap); abort(); } extern "C" void dMessage (int num, const char *msg, ...) { va_list ap; va_start (ap,msg); if (message_function) message_function (num,msg,ap); else printMessage (num,"ODE Message",msg,ap); va_end (ap); } #endif ode-0.16/ode/src/collision_cylinder_box.cpp0000664000175200017520000007530113403272463015746 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* * Cylinder-box collider by Alen Ladavac * Ported to ODE by Nguyen Binh */ #include #include #include "config.h" #include "matrix.h" #include "odemath.h" #include "collision_util.h" static const int MAX_CYLBOX_CLIP_POINTS = 16; static const int nCYLINDER_AXIS = 2; // Number of segment of cylinder base circle. // Must be divisible by 4. static const int nCYLINDER_SEGMENT = 8; #define MAX_FLOAT dInfinity // Data that passed through the collider's functions struct sCylinderBoxData { sCylinderBoxData(dxGeom *Cylinder, dxGeom *Box, int flags, dContactGeom *contact, int skip): m_gBox(Box), m_gCylinder(Cylinder), m_gContact(contact), m_iFlags(flags), m_iSkip(skip), m_nContacts(0) { } void _cldInitCylinderBox(); int _cldTestAxis( dVector3& vInputNormal, int iAxis ); int _cldTestEdgeCircleAxis( const dVector3 &vCenterPoint, const dVector3 &vVx0, const dVector3 &vVx1, int iAxis ); int _cldTestSeparatingAxes(); int _cldClipCylinderToBox(); void _cldClipBoxToCylinder(); int PerformCollisionChecking(); // cylinder parameters dMatrix3 m_mCylinderRot; dVector3 m_vCylinderPos; dVector3 m_vCylinderAxis; dReal m_fCylinderRadius; dReal m_fCylinderSize; dVector3 m_avCylinderNormals[nCYLINDER_SEGMENT]; // box parameters dMatrix3 m_mBoxRot; dVector3 m_vBoxPos; dVector3 m_vBoxHalfSize; // box vertices array : 8 vertices dVector3 m_avBoxVertices[8]; // global collider data dVector3 m_vDiff; dVector3 m_vNormal; dReal m_fBestDepth; dReal m_fBestrb; dReal m_fBestrc; int m_iBestAxis; // contact data dVector3 m_vEp0, m_vEp1; dReal m_fDepth0, m_fDepth1; // ODE stuff dGeomID m_gBox; dGeomID m_gCylinder; dContactGeom* m_gContact; int m_iFlags; int m_iSkip; int m_nContacts; }; // initialize collision data void sCylinderBoxData::_cldInitCylinderBox() { // get cylinder position, orientation const dReal* pRotCyc = dGeomGetRotation(m_gCylinder); dMatrix3Copy(pRotCyc,m_mCylinderRot); const dVector3* pPosCyc = (const dVector3*)dGeomGetPosition(m_gCylinder); dVector3Copy(*pPosCyc,m_vCylinderPos); dMat3GetCol(m_mCylinderRot,nCYLINDER_AXIS,m_vCylinderAxis); // get cylinder radius and size dGeomCylinderGetParams(m_gCylinder,&m_fCylinderRadius,&m_fCylinderSize); // get box position, orientation, size const dReal* pRotBox = dGeomGetRotation(m_gBox); dMatrix3Copy(pRotBox,m_mBoxRot); const dVector3* pPosBox = (const dVector3*)dGeomGetPosition(m_gBox); dVector3Copy(*pPosBox,m_vBoxPos); dGeomBoxGetLengths(m_gBox, m_vBoxHalfSize); m_vBoxHalfSize[0] *= REAL(0.5); m_vBoxHalfSize[1] *= REAL(0.5); m_vBoxHalfSize[2] *= REAL(0.5); // vertex 0 m_avBoxVertices[0][0] = -m_vBoxHalfSize[0]; m_avBoxVertices[0][1] = m_vBoxHalfSize[1]; m_avBoxVertices[0][2] = -m_vBoxHalfSize[2]; // vertex 1 m_avBoxVertices[1][0] = m_vBoxHalfSize[0]; m_avBoxVertices[1][1] = m_vBoxHalfSize[1]; m_avBoxVertices[1][2] = -m_vBoxHalfSize[2]; // vertex 2 m_avBoxVertices[2][0] = -m_vBoxHalfSize[0]; m_avBoxVertices[2][1] = -m_vBoxHalfSize[1]; m_avBoxVertices[2][2] = -m_vBoxHalfSize[2]; // vertex 3 m_avBoxVertices[3][0] = m_vBoxHalfSize[0]; m_avBoxVertices[3][1] = -m_vBoxHalfSize[1]; m_avBoxVertices[3][2] = -m_vBoxHalfSize[2]; // vertex 4 m_avBoxVertices[4][0] = m_vBoxHalfSize[0]; m_avBoxVertices[4][1] = m_vBoxHalfSize[1]; m_avBoxVertices[4][2] = m_vBoxHalfSize[2]; // vertex 5 m_avBoxVertices[5][0] = m_vBoxHalfSize[0]; m_avBoxVertices[5][1] = -m_vBoxHalfSize[1]; m_avBoxVertices[5][2] = m_vBoxHalfSize[2]; // vertex 6 m_avBoxVertices[6][0] = -m_vBoxHalfSize[0]; m_avBoxVertices[6][1] = -m_vBoxHalfSize[1]; m_avBoxVertices[6][2] = m_vBoxHalfSize[2]; // vertex 7 m_avBoxVertices[7][0] = -m_vBoxHalfSize[0]; m_avBoxVertices[7][1] = m_vBoxHalfSize[1]; m_avBoxVertices[7][2] = m_vBoxHalfSize[2]; // temp index int i = 0; dVector3 vTempBoxVertices[8]; // transform vertices in absolute space for(i=0; i < 8; i++) { dMultiplyMat3Vec3(m_mBoxRot,m_avBoxVertices[i], vTempBoxVertices[i]); dVector3Add(vTempBoxVertices[i], m_vBoxPos, m_avBoxVertices[i]); } // find relative position dVector3Subtract(m_vCylinderPos,m_vBoxPos,m_vDiff); m_fBestDepth = MAX_FLOAT; m_vNormal[0] = REAL(0.0); m_vNormal[1] = REAL(0.0); m_vNormal[2] = REAL(0.0); // calculate basic angle for nCYLINDER_SEGMENT-gon dReal fAngle = (dReal) (M_PI/nCYLINDER_SEGMENT); // calculate angle increment dReal fAngleIncrement = fAngle * REAL(2.0); // calculate nCYLINDER_SEGMENT-gon points for(i = 0; i < nCYLINDER_SEGMENT; i++) { m_avCylinderNormals[i][0] = -dCos(fAngle); m_avCylinderNormals[i][1] = -dSin(fAngle); m_avCylinderNormals[i][2] = 0; fAngle += fAngleIncrement; } m_fBestrb = 0; m_fBestrc = 0; m_iBestAxis = 0; m_nContacts = 0; } // test for given separating axis int sCylinderBoxData::_cldTestAxis( dVector3& vInputNormal, int iAxis ) { // check length of input normal dReal fL = dVector3Length(vInputNormal); // if not long enough if ( fL < REAL(1e-5) ) { // do nothing return 1; } // otherwise make it unit for sure dNormalize3(vInputNormal); // project box and Cylinder on mAxis dReal fdot1 = dVector3Dot(m_vCylinderAxis, vInputNormal); dReal frc; if (fdot1 > REAL(1.0)) { // assume fdot1 = 1 frc = m_fCylinderSize*REAL(0.5); } else if (fdot1 < REAL(-1.0)) { // assume fdot1 = -1 frc = m_fCylinderSize*REAL(0.5); } else { // project box and capsule on iAxis frc = dFabs( fdot1 * (m_fCylinderSize*REAL(0.5))) + m_fCylinderRadius * dSqrt(REAL(1.0)-(fdot1*fdot1)); } dVector3 vTemp1; dMat3GetCol(m_mBoxRot,0,vTemp1); dReal frb = dFabs(dVector3Dot(vTemp1,vInputNormal))*m_vBoxHalfSize[0]; dMat3GetCol(m_mBoxRot,1,vTemp1); frb += dFabs(dVector3Dot(vTemp1,vInputNormal))*m_vBoxHalfSize[1]; dMat3GetCol(m_mBoxRot,2,vTemp1); frb += dFabs(dVector3Dot(vTemp1,vInputNormal))*m_vBoxHalfSize[2]; // project their distance on separating axis dReal fd = dVector3Dot(m_vDiff,vInputNormal); // get depth dReal fDepth = frc + frb; // Calculate partial depth // if they do not overlap exit, we have no intersection if ( dFabs(fd) > fDepth ) { return 0; } // Finalyze the depth calculation fDepth -= dFabs(fd); // get maximum depth if ( fDepth < m_fBestDepth ) { m_fBestDepth = fDepth; dVector3Copy(vInputNormal,m_vNormal); m_iBestAxis = iAxis; m_fBestrb = frb; m_fBestrc = frc; // flip normal if interval is wrong faced if (fd > 0) { dVector3Inv(m_vNormal); } } return 1; } // check for separation between box edge and cylinder circle edge int sCylinderBoxData::_cldTestEdgeCircleAxis( const dVector3 &vCenterPoint, const dVector3 &vVx0, const dVector3 &vVx1, int iAxis ) { // calculate direction of edge dVector3 vDirEdge; dVector3Subtract(vVx1,vVx0,vDirEdge); dNormalize3(vDirEdge); // starting point of edge dVector3 vEStart; dVector3Copy(vVx0,vEStart);; // calculate angle cosine between cylinder axis and edge dReal fdot2 = dVector3Dot (vDirEdge,m_vCylinderAxis); // if edge is perpendicular to cylinder axis if(dFabs(fdot2) < REAL(1e-5)) { // this can't be separating axis, because edge is parallel to circle plane return 1; } // find point of intersection between edge line and circle plane dVector3 vTemp1; dVector3Subtract(vCenterPoint,vEStart,vTemp1); dReal fdot1 = dVector3Dot(vTemp1,m_vCylinderAxis); dVector3 vpnt; vpnt[0]= vEStart[0] + vDirEdge[0] * (fdot1/fdot2); vpnt[1]= vEStart[1] + vDirEdge[1] * (fdot1/fdot2); vpnt[2]= vEStart[2] + vDirEdge[2] * (fdot1/fdot2); // find tangent vector on circle with same center (vCenterPoint) that // touches point of intersection (vpnt) dVector3 vTangent; dVector3Subtract(vCenterPoint,vpnt,vTemp1); dVector3Cross(vTemp1,m_vCylinderAxis,vTangent); // find vector orthogonal both to tangent and edge direction dVector3 vAxis; dVector3Cross(vTangent,vDirEdge,vAxis); // use that vector as separating axis return _cldTestAxis( vAxis, iAxis ); } // Test separating axis for collision int sCylinderBoxData::_cldTestSeparatingAxes() { // reset best axis m_fBestDepth = MAX_FLOAT; m_iBestAxis = 0; m_fBestrb = 0; m_fBestrc = 0; m_nContacts = 0; dVector3 vAxis = {REAL(0.0),REAL(0.0),REAL(0.0),REAL(0.0)}; // Epsilon value for checking axis vector length const dReal fEpsilon = REAL(1e-6); // axis A0 dMat3GetCol(m_mBoxRot, 0 , vAxis); if (!_cldTestAxis( vAxis, 1 )) { return 0; } // axis A1 dMat3GetCol(m_mBoxRot, 1 , vAxis); if (!_cldTestAxis( vAxis, 2 )) { return 0; } // axis A2 dMat3GetCol(m_mBoxRot, 2 , vAxis); if (!_cldTestAxis( vAxis, 3 )) { return 0; } // axis C - Cylinder Axis //vAxis = vCylinderAxis; dVector3Copy(m_vCylinderAxis , vAxis); if (!_cldTestAxis( vAxis, 4 )) { return 0; } // axis CxA0 //vAxis = ( vCylinderAxis cross mthGetColM33f( mBoxRot, 0 )); dVector3CrossMat3Col(m_mBoxRot, 0 ,m_vCylinderAxis, vAxis); if(dVector3LengthSquare( vAxis ) > fEpsilon ) { if (!_cldTestAxis( vAxis, 5 )) { return 0; } } // axis CxA1 //vAxis = ( vCylinderAxis cross mthGetColM33f( mBoxRot, 1 )); dVector3CrossMat3Col(m_mBoxRot, 1 ,m_vCylinderAxis, vAxis); if(dVector3LengthSquare( vAxis ) > fEpsilon ) { if (!_cldTestAxis( vAxis, 6 )) { return 0; } } // axis CxA2 //vAxis = ( vCylinderAxis cross mthGetColM33f( mBoxRot, 2 )); dVector3CrossMat3Col(m_mBoxRot, 2 ,m_vCylinderAxis, vAxis); if(dVector3LengthSquare( vAxis ) > fEpsilon ) { if (!_cldTestAxis( vAxis, 7 )) { return 0; } } int i = 0; dVector3 vTemp1; dVector3 vTemp2; // here we check box's vertices axis for(i=0; i< 8; i++) { //vAxis = ( vCylinderAxis cross (m_avBoxVertices[i] - vCylinderPos)); dVector3Subtract(m_avBoxVertices[i],m_vCylinderPos,vTemp1); dVector3Cross(m_vCylinderAxis,vTemp1,vTemp2); //vAxis = ( vCylinderAxis cross vAxis ); dVector3Cross(m_vCylinderAxis,vTemp2,vAxis); if(dVector3LengthSquare( vAxis ) > fEpsilon ) { if (!_cldTestAxis( vAxis, 8 + i )) { return 0; } } } // ************************************ // this is defined for first 12 axes // normal of plane that contains top circle of cylinder // center of top circle of cylinder dVector3 vcc; vcc[0] = (m_vCylinderPos)[0] + m_vCylinderAxis[0]*(m_fCylinderSize*REAL(0.5)); vcc[1] = (m_vCylinderPos)[1] + m_vCylinderAxis[1]*(m_fCylinderSize*REAL(0.5)); vcc[2] = (m_vCylinderPos)[2] + m_vCylinderAxis[2]*(m_fCylinderSize*REAL(0.5)); // ************************************ if (!_cldTestEdgeCircleAxis( vcc, m_avBoxVertices[1], m_avBoxVertices[0], 16)) { return 0; } if (!_cldTestEdgeCircleAxis( vcc, m_avBoxVertices[1], m_avBoxVertices[3], 17)) { return 0; } if (!_cldTestEdgeCircleAxis( vcc, m_avBoxVertices[2], m_avBoxVertices[3], 18)) { return 0; } if (!_cldTestEdgeCircleAxis( vcc, m_avBoxVertices[2], m_avBoxVertices[0], 19)) { return 0; } if (!_cldTestEdgeCircleAxis( vcc, m_avBoxVertices[4], m_avBoxVertices[1], 20)) { return 0; } if (!_cldTestEdgeCircleAxis( vcc, m_avBoxVertices[4], m_avBoxVertices[7], 21)) { return 0; } if (!_cldTestEdgeCircleAxis( vcc, m_avBoxVertices[0], m_avBoxVertices[7], 22)) { return 0; } if (!_cldTestEdgeCircleAxis( vcc, m_avBoxVertices[5], m_avBoxVertices[3], 23)) { return 0; } if (!_cldTestEdgeCircleAxis( vcc, m_avBoxVertices[5], m_avBoxVertices[6], 24)) { return 0; } if (!_cldTestEdgeCircleAxis( vcc, m_avBoxVertices[2], m_avBoxVertices[6], 25)) { return 0; } if (!_cldTestEdgeCircleAxis( vcc, m_avBoxVertices[4], m_avBoxVertices[5], 26)) { return 0; } if (!_cldTestEdgeCircleAxis( vcc, m_avBoxVertices[6], m_avBoxVertices[7], 27)) { return 0; } // ************************************ // this is defined for second 12 axes // normal of plane that contains bottom circle of cylinder // center of bottom circle of cylinder // vcc = vCylinderPos - vCylinderAxis*(fCylinderSize*REAL(0.5)); vcc[0] = (m_vCylinderPos)[0] - m_vCylinderAxis[0]*(m_fCylinderSize*REAL(0.5)); vcc[1] = (m_vCylinderPos)[1] - m_vCylinderAxis[1]*(m_fCylinderSize*REAL(0.5)); vcc[2] = (m_vCylinderPos)[2] - m_vCylinderAxis[2]*(m_fCylinderSize*REAL(0.5)); // ************************************ if (!_cldTestEdgeCircleAxis( vcc, m_avBoxVertices[1], m_avBoxVertices[0], 28)) { return 0; } if (!_cldTestEdgeCircleAxis( vcc, m_avBoxVertices[1], m_avBoxVertices[3], 29)) { return 0; } if (!_cldTestEdgeCircleAxis( vcc, m_avBoxVertices[2], m_avBoxVertices[3], 30)) { return 0; } if (!_cldTestEdgeCircleAxis( vcc, m_avBoxVertices[2], m_avBoxVertices[0], 31)) { return 0; } if (!_cldTestEdgeCircleAxis( vcc, m_avBoxVertices[4], m_avBoxVertices[1], 32)) { return 0; } if (!_cldTestEdgeCircleAxis( vcc, m_avBoxVertices[4], m_avBoxVertices[7], 33)) { return 0; } if (!_cldTestEdgeCircleAxis( vcc, m_avBoxVertices[0], m_avBoxVertices[7], 34)) { return 0; } if (!_cldTestEdgeCircleAxis( vcc, m_avBoxVertices[5], m_avBoxVertices[3], 35)) { return 0; } if (!_cldTestEdgeCircleAxis( vcc, m_avBoxVertices[5], m_avBoxVertices[6], 36)) { return 0; } if (!_cldTestEdgeCircleAxis( vcc, m_avBoxVertices[2], m_avBoxVertices[6], 37)) { return 0; } if (!_cldTestEdgeCircleAxis( vcc, m_avBoxVertices[4], m_avBoxVertices[5], 38)) { return 0; } if (!_cldTestEdgeCircleAxis( vcc, m_avBoxVertices[6], m_avBoxVertices[7], 39)) { return 0; } return 1; } int sCylinderBoxData::_cldClipCylinderToBox() { dIASSERT(m_nContacts != (m_iFlags & NUMC_MASK)); // calculate that vector perpendicular to cylinder axis which closes lowest angle with collision normal dVector3 vN; dReal fTemp1 = dVector3Dot(m_vCylinderAxis,m_vNormal); vN[0] = m_vNormal[0] - m_vCylinderAxis[0]*fTemp1; vN[1] = m_vNormal[1] - m_vCylinderAxis[1]*fTemp1; vN[2] = m_vNormal[2] - m_vCylinderAxis[2]*fTemp1; // normalize that vector dNormalize3(vN); // translate cylinder end points by the vector dVector3 vCposTrans; vCposTrans[0] = m_vCylinderPos[0] + vN[0] * m_fCylinderRadius; vCposTrans[1] = m_vCylinderPos[1] + vN[1] * m_fCylinderRadius; vCposTrans[2] = m_vCylinderPos[2] + vN[2] * m_fCylinderRadius; m_vEp0[0] = vCposTrans[0] + m_vCylinderAxis[0]*(m_fCylinderSize*REAL(0.5)); m_vEp0[1] = vCposTrans[1] + m_vCylinderAxis[1]*(m_fCylinderSize*REAL(0.5)); m_vEp0[2] = vCposTrans[2] + m_vCylinderAxis[2]*(m_fCylinderSize*REAL(0.5)); m_vEp1[0] = vCposTrans[0] - m_vCylinderAxis[0]*(m_fCylinderSize*REAL(0.5)); m_vEp1[1] = vCposTrans[1] - m_vCylinderAxis[1]*(m_fCylinderSize*REAL(0.5)); m_vEp1[2] = vCposTrans[2] - m_vCylinderAxis[2]*(m_fCylinderSize*REAL(0.5)); // transform edge points in box space m_vEp0[0] -= m_vBoxPos[0]; m_vEp0[1] -= m_vBoxPos[1]; m_vEp0[2] -= m_vBoxPos[2]; m_vEp1[0] -= m_vBoxPos[0]; m_vEp1[1] -= m_vBoxPos[1]; m_vEp1[2] -= m_vBoxPos[2]; dVector3 vTemp1; // clip the edge to box dVector4 plPlane; // plane 0 +x dMat3GetCol(m_mBoxRot,0,vTemp1); dConstructPlane(vTemp1,m_vBoxHalfSize[0],plPlane); if(!dClipEdgeToPlane( m_vEp0, m_vEp1, plPlane )) { return 0; } // plane 1 +y dMat3GetCol(m_mBoxRot,1,vTemp1); dConstructPlane(vTemp1,m_vBoxHalfSize[1],plPlane); if(!dClipEdgeToPlane( m_vEp0, m_vEp1, plPlane )) { return 0; } // plane 2 +z dMat3GetCol(m_mBoxRot,2,vTemp1); dConstructPlane(vTemp1,m_vBoxHalfSize[2],plPlane); if(!dClipEdgeToPlane( m_vEp0, m_vEp1, plPlane )) { return 0; } // plane 3 -x dMat3GetCol(m_mBoxRot,0,vTemp1); dVector3Inv(vTemp1); dConstructPlane(vTemp1,m_vBoxHalfSize[0],plPlane); if(!dClipEdgeToPlane( m_vEp0, m_vEp1, plPlane )) { return 0; } // plane 4 -y dMat3GetCol(m_mBoxRot,1,vTemp1); dVector3Inv(vTemp1); dConstructPlane(vTemp1,m_vBoxHalfSize[1],plPlane); if(!dClipEdgeToPlane( m_vEp0, m_vEp1, plPlane )) { return 0; } // plane 5 -z dMat3GetCol(m_mBoxRot,2,vTemp1); dVector3Inv(vTemp1); dConstructPlane(vTemp1,m_vBoxHalfSize[2],plPlane); if(!dClipEdgeToPlane( m_vEp0, m_vEp1, plPlane )) { return 0; } // calculate depths for both contact points m_fDepth0 = m_fBestrb + dVector3Dot(m_vEp0, m_vNormal); m_fDepth1 = m_fBestrb + dVector3Dot(m_vEp1, m_vNormal); // clamp depths to 0 if(m_fDepth0<0) { m_fDepth0 = REAL(0.0); } if(m_fDepth1<0) { m_fDepth1 = REAL(0.0); } // back transform edge points from box to absolute space m_vEp0[0] += m_vBoxPos[0]; m_vEp0[1] += m_vBoxPos[1]; m_vEp0[2] += m_vBoxPos[2]; m_vEp1[0] += m_vBoxPos[0]; m_vEp1[1] += m_vBoxPos[1]; m_vEp1[2] += m_vBoxPos[2]; dContactGeom* Contact0 = SAFECONTACT(m_iFlags, m_gContact, m_nContacts, m_iSkip); Contact0->depth = m_fDepth0; dVector3Copy(m_vNormal,Contact0->normal); dVector3Copy(m_vEp0,Contact0->pos); Contact0->g1 = m_gCylinder; Contact0->g2 = m_gBox; Contact0->side1 = -1; Contact0->side2 = -1; dVector3Inv(Contact0->normal); m_nContacts++; if (m_nContacts != (m_iFlags & NUMC_MASK)) { dContactGeom* Contact1 = SAFECONTACT(m_iFlags, m_gContact, m_nContacts, m_iSkip); Contact1->depth = m_fDepth1; dVector3Copy(m_vNormal,Contact1->normal); dVector3Copy(m_vEp1,Contact1->pos); Contact1->g1 = m_gCylinder; Contact1->g2 = m_gBox; Contact1->side1 = -1; Contact1->side2 = -1; dVector3Inv(Contact1->normal); m_nContacts++; } return 1; } void sCylinderBoxData::_cldClipBoxToCylinder() { dIASSERT(m_nContacts != (m_iFlags & NUMC_MASK)); dVector3 vCylinderCirclePos, vCylinderCircleNormal_Rel; // check which circle from cylinder we take for clipping if ( dVector3Dot(m_vCylinderAxis, m_vNormal) > REAL(0.0) ) { // get top circle vCylinderCirclePos[0] = m_vCylinderPos[0] + m_vCylinderAxis[0]*(m_fCylinderSize*REAL(0.5)); vCylinderCirclePos[1] = m_vCylinderPos[1] + m_vCylinderAxis[1]*(m_fCylinderSize*REAL(0.5)); vCylinderCirclePos[2] = m_vCylinderPos[2] + m_vCylinderAxis[2]*(m_fCylinderSize*REAL(0.5)); vCylinderCircleNormal_Rel[0] = REAL(0.0); vCylinderCircleNormal_Rel[1] = REAL(0.0); vCylinderCircleNormal_Rel[2] = REAL(0.0); vCylinderCircleNormal_Rel[nCYLINDER_AXIS] = REAL(-1.0); } else { // get bottom circle vCylinderCirclePos[0] = m_vCylinderPos[0] - m_vCylinderAxis[0]*(m_fCylinderSize*REAL(0.5)); vCylinderCirclePos[1] = m_vCylinderPos[1] - m_vCylinderAxis[1]*(m_fCylinderSize*REAL(0.5)); vCylinderCirclePos[2] = m_vCylinderPos[2] - m_vCylinderAxis[2]*(m_fCylinderSize*REAL(0.5)); vCylinderCircleNormal_Rel[0] = REAL(0.0); vCylinderCircleNormal_Rel[1] = REAL(0.0); vCylinderCircleNormal_Rel[2] = REAL(0.0); vCylinderCircleNormal_Rel[nCYLINDER_AXIS] = REAL(1.0); } // vNr is normal in Box frame, pointing from Cylinder to Box dVector3 vNr; dMatrix3 mBoxInv; // Find a way to use quaternion dMatrix3Inv(m_mBoxRot,mBoxInv); dMultiplyMat3Vec3(mBoxInv,m_vNormal,vNr); dVector3 vAbsNormal; vAbsNormal[0] = dFabs( vNr[0] ); vAbsNormal[1] = dFabs( vNr[1] ); vAbsNormal[2] = dFabs( vNr[2] ); // find which face in box is closest to cylinder int iB0, iB1, iB2; // Different from Croteam's code if (vAbsNormal[1] > vAbsNormal[0]) { // 1 > 0 if (vAbsNormal[0]> vAbsNormal[2]) { // 0 > 2 -> 1 > 0 >2 iB0 = 1; iB1 = 0; iB2 = 2; } else { // 2 > 0-> Must compare 1 and 2 if (vAbsNormal[1] > vAbsNormal[2]) { // 1 > 2 -> 1 > 2 > 0 iB0 = 1; iB1 = 2; iB2 = 0; } else { // 2 > 1 -> 2 > 1 > 0; iB0 = 2; iB1 = 1; iB2 = 0; } } } else { // 0 > 1 if (vAbsNormal[1] > vAbsNormal[2]) { // 1 > 2 -> 0 > 1 > 2 iB0 = 0; iB1 = 1; iB2 = 2; } else { // 2 > 1 -> Must compare 0 and 2 if (vAbsNormal[0] > vAbsNormal[2]) { // 0 > 2 -> 0 > 2 > 1; iB0 = 0; iB1 = 2; iB2 = 1; } else { // 2 > 0 -> 2 > 0 > 1; iB0 = 2; iB1 = 0; iB2 = 1; } } } dVector3 vCenter; // find center of box polygon dVector3 vTemp; if (vNr[iB0] > 0) { dMat3GetCol(m_mBoxRot,iB0,vTemp); vCenter[0] = m_vBoxPos[0] - m_vBoxHalfSize[iB0]*vTemp[0]; vCenter[1] = m_vBoxPos[1] - m_vBoxHalfSize[iB0]*vTemp[1]; vCenter[2] = m_vBoxPos[2] - m_vBoxHalfSize[iB0]*vTemp[2]; } else { dMat3GetCol(m_mBoxRot,iB0,vTemp); vCenter[0] = m_vBoxPos[0] + m_vBoxHalfSize[iB0]*vTemp[0]; vCenter[1] = m_vBoxPos[1] + m_vBoxHalfSize[iB0]*vTemp[1]; vCenter[2] = m_vBoxPos[2] + m_vBoxHalfSize[iB0]*vTemp[2]; } // find the vertices of box polygon dVector3 avPoints[4]; dVector3 avTempArray1[MAX_CYLBOX_CLIP_POINTS]; dVector3 avTempArray2[MAX_CYLBOX_CLIP_POINTS]; int i=0; for(i=0; i= 0 && iTmpCounter1 <= MAX_CYLBOX_CLIP_POINTS ); dIASSERT( iTmpCounter2 >= 0 && iTmpCounter2 <= MAX_CYLBOX_CLIP_POINTS ); } // back transform clipped points to absolute space dReal ftmpdot; dReal fTempDepth; dVector3 vPoint; if (nCircleSegment % 2) { for( i=0; i REAL(0.0)) { // generate contacts dContactGeom* Contact0 = SAFECONTACT(m_iFlags, m_gContact, m_nContacts, m_iSkip); Contact0->depth = fTempDepth; dVector3Copy(m_vNormal,Contact0->normal); dVector3Copy(vPoint,Contact0->pos); Contact0->g1 = m_gCylinder; Contact0->g2 = m_gBox; Contact0->side1 = -1; Contact0->side2 = -1; dVector3Inv(Contact0->normal); m_nContacts++; if (m_nContacts == (m_iFlags & NUMC_MASK)) { break; } } } } else { for( i=0; i REAL(0.0)) { // generate contacts dContactGeom* Contact0 = SAFECONTACT(m_iFlags, m_gContact, m_nContacts, m_iSkip); Contact0->depth = fTempDepth; dVector3Copy(m_vNormal,Contact0->normal); dVector3Copy(vPoint,Contact0->pos); Contact0->g1 = m_gCylinder; Contact0->g2 = m_gBox; Contact0->side1 = -1; Contact0->side2 = -1; dVector3Inv(Contact0->normal); m_nContacts++; if (m_nContacts == (m_iFlags & NUMC_MASK)) { break; } } } } } int sCylinderBoxData::PerformCollisionChecking() { // initialize collider _cldInitCylinderBox(); // do intersection test and find best separating axis if ( !_cldTestSeparatingAxes() ) { // if not found do nothing return 0; } // if best separation axis is not found if ( m_iBestAxis == 0 ) { // this should not happen (we should already exit in that case) dIASSERT(0); // do nothing return 0; } dReal fdot = dVector3Dot(m_vNormal,m_vCylinderAxis); // choose which clipping method are we going to apply if (dFabs(fdot) < REAL(0.9) ) { // clip cylinder over box if(!_cldClipCylinderToBox()) { return 0; } } else { _cldClipBoxToCylinder(); } return m_nContacts; } // Cylinder - Box by CroTeam // Ported by Nguyen Binh int dCollideCylinderBox(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) { dIASSERT (skip >= (int)sizeof(dContactGeom)); dIASSERT (o1->type == dCylinderClass); dIASSERT (o2->type == dBoxClass); dIASSERT ((flags & NUMC_MASK) >= 1); sCylinderBoxData cData(o1, o2, flags, contact, skip); return cData.PerformCollisionChecking(); } ode-0.16/ode/src/misc.cpp0000664000175200017520000001441713403272463012146 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include #include "config.h" #include "matrix.h" #include "error.h" #include "odeou.h" //**************************************************************************** // random numbers static volatile duint32 seed = 0; unsigned long dRand() { duint32 origSeed, newSeed; #if !dTHREADING_INTF_DISABLED do { #endif origSeed = seed; newSeed = ((duint32)1664525 * origSeed + (duint32)1013904223) & (duint32)0xffffffff; #if dTHREADING_INTF_DISABLED seed = newSeed; #else } while (!AtomicCompareExchange((volatile atomicord32 *)&seed, origSeed, newSeed)); #endif return newSeed; } unsigned long dRandGetSeed() { return seed; } void dRandSetSeed (unsigned long s) { seed = s; } int dTestRand() { unsigned long oldseed = seed; int ret = 1; seed = 0; if (dRand() != 0x3c6ef35f || dRand() != 0x47502932 || dRand() != 0xd1ccf6e9 || dRand() != 0xaaf95334 || dRand() != 0x6252e503) ret = 0; seed = oldseed; return ret; } // adam's all-int straightforward(?) dRandInt (0..n-1) int dRandInt (int n) { int result; // Since there is no memory barrier macro in ODE assign via volatile variable // to prevent compiler reusing seed as value of `r' volatile unsigned long raw_r = dRand(); duint32 r = (duint32)raw_r; duint32 un = n; dIASSERT(sizeof(n) == sizeof(un)); // note: probably more aggressive than it needs to be -- might be // able to get away without one or two of the innermost branches. // if (un <= 0x00010000UL) { // r ^= (r >> 16); // if (un <= 0x00000100UL) { // r ^= (r >> 8); // if (un <= 0x00000010UL) { // r ^= (r >> 4); // if (un <= 0x00000004UL) { // r ^= (r >> 2); // if (un <= 0x00000002UL) { // r ^= (r >> 1); // } // } // } // } // } // Optimized version of above if (un <= (duint32)0x00000010) { r ^= (r >> 16); r ^= (r >> 8); r ^= (r >> 4); if (un <= (duint32)0x00000002) { r ^= (r >> 2); r ^= (r >> 1); result = (r/* & (duint32)0x01*/) & (un >> 1); } else { if (un <= (duint32)0x00000004) { r ^= (r >> 2); result = ((r & (duint32)0x03) * un) >> 2; } else { result = ((r & (duint32)0x0F) * un) >> 4; } } } else { if (un <= (duint32)0x00000100) { r ^= (r >> 16); r ^= (r >> 8); result = ((r & (duint32)0xFF) * un) >> 8; } else { if (un <= (duint32)0x00010000) { r ^= (r >> 16); result = ((r & (duint32)0xFFFF) * un) >> 16; } else { result = (int)(((duint64)r * un) >> 32); } } } return result; } dReal dRandReal() { return (dReal)(((double) dRand()) / ((double) 0xffffffff)); } //**************************************************************************** // matrix utility stuff void dPrintMatrix (const dReal *A, int n, int m, const char *fmt, FILE *f) { int skip = dPAD(m); const dReal *Arow = A; for (int i=0; i max) max = diff; } } return max; } dReal dMaxDifferenceLowerTriangle (const dReal *A, const dReal *B, int n) { int skip = dPAD(n); dReal max = REAL(0.0); const dReal *Arow = A, *Brow = B; for (int i=0; i max) max = diff; } } return max; } ode-0.16/ode/src/step.cpp0000664000175200017520000022027413403272463012166 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include #include #include #include "config.h" #include "odemath.h" #include "matrix.h" #include "objects.h" #include "joints/joint.h" #include "lcp.h" #include "util.h" #include "threadingutils.h" #include #define dMIN(A,B) ((A)>(B) ? (B) : (A)) #define dMAX(A,B) ((B)>(A) ? (B) : (A)) //**************************************************************************** // misc defines //#define TIMING #ifdef TIMING #define IFTIMING(x) x #else #define IFTIMING(x) ((void)0) #endif struct dJointWithInfo1 { dxJoint *joint; dxJoint::Info1 info; }; enum dxRHSCFMElement { RCE_RHS = dxJoint::GI2_RHS, RCE_CFM = dxJoint::GI2_CFM, // Elements for array reuse RLE_RHS = RCE_RHS, RLE_LAMBDA = RCE_CFM, RCE__RHS_CFM_MAX = dxJoint::GI2__RHS_CFM_MAX, RLE__RHS_LAMBDA_MAX = RCE__RHS_CFM_MAX, }; enum dxLoHiElement { LHE_LO = dxJoint::GI2_LO, LHE_HI = dxJoint::GI2_HI, LHE__LO_HI_MAX = dxJoint::GI2__LO_HI_MAX, }; enum dxJacobiVectorElement { JVE__MIN, JVE__L_MIN = JVE__MIN + dDA__L_MIN, JVE_LX = JVE__L_MIN + dSA_X, JVE_LY = JVE__L_MIN + dSA_Y, JVE_LZ = JVE__L_MIN + dSA_Z, JVE__L_MAX = JVE__L_MIN + dSA__MAX, JVE__A_MIN = JVE__MIN + dDA__A_MIN, JVE_AX = JVE__A_MIN + dSA_X, JVE_AY = JVE__A_MIN + dSA_Y, JVE_AZ = JVE__A_MIN + dSA_Z, JVE__A_MAX = JVE__A_MIN + dSA__MAX, JVE__MAX = JVE__MIN + dDA__MAX, JVE__L_COUNT = JVE__L_MAX - JVE__L_MIN, JVE__A_COUNT = JVE__A_MAX - JVE__A_MIN, }; enum dxJacobiMatrixElement { JME__MIN, JME__J_MIN = JME__MIN, JME__JL_MIN = JME__J_MIN + JVE__L_MIN, JME_JLX = JME__J_MIN + JVE_LX, JME_JLY = JME__J_MIN + JVE_LY, JME_JLZ = JME__J_MIN + JVE_LZ, JME__JL_MAX = JME__J_MIN + JVE__L_MAX, JME__JA_MIN = JME__J_MIN + JVE__A_MIN, JME_JAX = JME__J_MIN + JVE_AX, JME_JAY = JME__J_MIN + JVE_AY, JME_JAZ = JME__J_MIN + JVE_AZ, JME__JA_MAX = JME__J_MIN + JVE__A_MAX, JME__J_MAX = JME__J_MIN + JVE__MAX, JME__MAX = JME__J_MAX, JME__J_COUNT = JME__J_MAX - JME__J_MIN, }; enum dxJInvMElement { JIM__MIN, JIM__L_MIN = JIM__MIN + dMD_LINEAR * dV3E__MAX, JIM__L_AXES_MIN = JIM__L_MIN + dV3E__AXES_MIN, JIM_LX = JIM__L_MIN + dV3E_X, JIM_LY = JIM__L_MIN + dV3E_Y, JIM_LZ = JIM__L_MIN + dV3E_Z, JIM__L_AXES_MAX = JIM__L_MIN + dV3E__AXES_MAX, JIM_LPAD = JIM__L_MIN + dV3E_PAD, JIM__L_MAX = JIM__L_MIN + dV3E__MAX, JIM__A_MIN = JIM__MIN + dMD_ANGULAR * dV3E__MAX, JIM__A_AXES_MIN = JIM__A_MIN + dV3E__AXES_MIN, JIM_AX = JIM__A_MIN + dV3E_X, JIM_AY = JIM__A_MIN + dV3E_Y, JIM_AZ = JIM__A_MIN + dV3E_Z, JIM__A_AXES_MAX = JIM__A_MIN + dV3E__AXES_MAX, JIM_APAD = JIM__A_MIN + dV3E_PAD, JIM__A_MAX = JIM__A_MIN + dV3E__MAX, JIM__MAX = JIM__MIN + dMD__MAX * dV3E__MAX, }; enum dxContactForceElement { CFE__MIN, CFE__DYNAMICS_MIN = CFE__MIN, CFE__L_MIN = CFE__DYNAMICS_MIN + dDA__L_MIN, CFE_LX = CFE__DYNAMICS_MIN + dDA_LX, CFE_LY = CFE__DYNAMICS_MIN + dDA_LY, CFE_LZ = CFE__DYNAMICS_MIN + dDA_LZ, CFE__L_MAX = CFE__DYNAMICS_MIN + dDA__L_MAX, CFE__A_MIN = CFE__DYNAMICS_MIN + dDA__A_MIN, CFE_AX = CFE__DYNAMICS_MIN + dDA_AX, CFE_AY = CFE__DYNAMICS_MIN + dDA_AY, CFE_AZ = CFE__DYNAMICS_MIN + dDA_AZ, CFE__A_MAX = CFE__DYNAMICS_MIN + dDA__A_MAX, CFE__DYNAMICS_MAX = CFE__DYNAMICS_MIN + dDA__MAX, CFE__MAX = CFE__DYNAMICS_MAX, }; #define AMATRIX_ALIGNMENT dMAX(64, EFFICIENT_ALIGNMENT) #define INVI_ALIGNMENT dMAX(32, EFFICIENT_ALIGNMENT) #define JINVM_ALIGNMENT dMAX(64, EFFICIENT_ALIGNMENT) struct dxStepperStage0Outputs { sizeint ji_start; sizeint ji_end; unsigned int m; unsigned int nub; }; struct dxStepperStage1CallContext { void Initialize(const dxStepperProcessingCallContext *stepperCallContext, void *stageMemArenaState, dReal *invI, dJointWithInfo1 *jointinfos) { m_stepperCallContext = stepperCallContext; m_stageMemArenaState = stageMemArenaState; m_invI = invI; m_jointinfos = jointinfos; } const dxStepperProcessingCallContext *m_stepperCallContext; void *m_stageMemArenaState; dReal *m_invI; dJointWithInfo1 *m_jointinfos; dxStepperStage0Outputs m_stage0Outputs; }; struct dxStepperStage0BodiesCallContext { void Initialize(const dxStepperProcessingCallContext *stepperCallContext, dReal *invI) { m_stepperCallContext = stepperCallContext; m_invI = invI; m_tagsTaken = 0; m_gravityTaken = 0; m_inertiaBodyIndex = 0; } const dxStepperProcessingCallContext *m_stepperCallContext; dReal *m_invI; atomicord32 m_tagsTaken; atomicord32 m_gravityTaken; volatile atomicord32 m_inertiaBodyIndex; }; struct dxStepperStage0JointsCallContext { void Initialize(const dxStepperProcessingCallContext *stepperCallContext, dJointWithInfo1 *jointinfos, dxStepperStage0Outputs *stage0Outputs) { m_stepperCallContext = stepperCallContext; m_jointinfos = jointinfos; m_stage0Outputs = stage0Outputs; } const dxStepperProcessingCallContext *m_stepperCallContext; dJointWithInfo1 *m_jointinfos; dxStepperStage0Outputs *m_stage0Outputs; }; static int dxStepIsland_Stage0_Bodies_Callback(void *callContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee); // static int dxStepIsland_Stage0_Joints_Callback(void *callContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee); static int dxStepIsland_Stage1_Callback(void *callContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee); static void dxStepIsland_Stage0_Bodies(dxStepperStage0BodiesCallContext *callContext); static void dxStepIsland_Stage0_Joints(dxStepperStage0JointsCallContext *callContext); static void dxStepIsland_Stage1(dxStepperStage1CallContext *callContext); struct dxStepperLocalContext { void Initialize(dReal *invI, dJointWithInfo1 *jointinfos, unsigned int nj, unsigned int m, unsigned int nub, const unsigned int *mindex, int *findex, dReal *J, dReal *A, dReal *pairsRhsCfm, dReal *pairsLoHi, atomicord32 *bodyStartJoints, atomicord32 *bodyJointLinks) { m_invI = invI; m_jointinfos = jointinfos; m_nj = nj; m_m = m; m_nub = nub; m_mindex = mindex; m_findex = findex; m_J = J; m_A = A; m_pairsRhsCfm = pairsRhsCfm; m_pairsLoHi = pairsLoHi; m_bodyStartJoints = bodyStartJoints; m_bodyJointLinks = bodyJointLinks; } dReal *m_invI; dJointWithInfo1 *m_jointinfos; unsigned int m_nj; unsigned int m_m; unsigned int m_nub; const unsigned int *m_mindex; int *m_findex; dReal *m_J; dReal *m_A; dReal *m_pairsRhsCfm; dReal *m_pairsLoHi; atomicord32 *m_bodyStartJoints; atomicord32 *m_bodyJointLinks; }; struct dxStepperStage2CallContext { void Initialize(const dxStepperProcessingCallContext *callContext, const dxStepperLocalContext *localContext, dReal *JinvM, dReal *rhs_tmp) { m_stepperCallContext = callContext; m_localContext = localContext; m_JinvM = JinvM; m_rhs_tmp = rhs_tmp; m_ji_J = 0; m_ji_Ainit = 0; m_ji_JinvM = 0; m_ji_Aaddjb = 0; m_bi_rhs_tmp = 0; m_ji_rhs = 0; } const dxStepperProcessingCallContext *m_stepperCallContext; const dxStepperLocalContext *m_localContext; dReal *m_JinvM; dReal *m_rhs_tmp; volatile atomicord32 m_ji_J; volatile atomicord32 m_ji_Ainit; volatile atomicord32 m_ji_JinvM; volatile atomicord32 m_ji_Aaddjb; volatile atomicord32 m_bi_rhs_tmp; volatile atomicord32 m_ji_rhs; }; struct dxStepperStage3CallContext { void Initialize(const dxStepperProcessingCallContext *callContext, const dxStepperLocalContext *localContext, void *stage1MemArenaState) { m_stepperCallContext = callContext; m_localContext = localContext; m_stage1MemArenaState = stage1MemArenaState; } const dxStepperProcessingCallContext *m_stepperCallContext; const dxStepperLocalContext *m_localContext; void *m_stage1MemArenaState; }; struct dxStepperStage4CallContext { void Initialize(const dxStepperProcessingCallContext *callContext, const dxStepperLocalContext *localContext/*, void *stage3MemarenaState*/) { m_stepperCallContext = callContext; m_localContext = localContext; // m_stage3MemarenaState = stage3MemarenaState; m_bi_constrForce = 0; } const dxStepperProcessingCallContext *m_stepperCallContext; const dxStepperLocalContext *m_localContext; // void *m_stage3MemarenaState; volatile atomicord32 m_bi_constrForce; }; static int dxStepIsland_Stage2a_Callback(void *callContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee); static int dxStepIsland_Stage2aSync_Callback(void *callContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee); static int dxStepIsland_Stage2b_Callback(void *callContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee); static int dxStepIsland_Stage2bSync_Callback(void *callContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee); static int dxStepIsland_Stage2c_Callback(void *callContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee); static int dxStepIsland_Stage3_Callback(void *callContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee); static void dxStepIsland_Stage2a(dxStepperStage2CallContext *callContext); static void dxStepIsland_Stage2b(dxStepperStage2CallContext *callContext); static void dxStepIsland_Stage2c(dxStepperStage2CallContext *callContext); static void dxStepIsland_Stage3(dxStepperStage3CallContext *callContext); static int dxStepIsland_Stage4_Callback(void *_stage4CallContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee); static void dxStepIsland_Stage4(dxStepperStage4CallContext *stage4CallContext); //**************************************************************************** // special matrix multipliers // this assumes the 4th and 8th rows of B and C are zero. static inline void MultiplyAddJinvMxJToA (dReal *Arow, const dReal *JinvMRow, const dReal *JRow, unsigned int infomJinvM, unsigned int infomJ, unsigned int mskip) { dIASSERT (infomJinvM > 0 && infomJ > 0 && Arow && JinvMRow && JRow); const unsigned int mskip_munus_infomJ_plus_1 = mskip - infomJ + 1; dIASSERT(mskip >= infomJ); dReal *currA = Arow; const dReal *currJinvM = JinvMRow; for (unsigned int i = infomJinvM; ; ) { dReal JiM0 = currJinvM[JIM_LX]; dReal JiM1 = currJinvM[JIM_LY]; dReal JiM2 = currJinvM[JIM_LZ]; dReal JiM4 = currJinvM[JIM_AX]; dReal JiM5 = currJinvM[JIM_AY]; dReal JiM6 = currJinvM[JIM_AZ]; const dReal *currJ = JRow; for (unsigned int j = infomJ; ; ) { dReal sum; sum = JiM0 * currJ[JME_JLX]; sum += JiM1 * currJ[JME_JLY]; sum += JiM2 * currJ[JME_JLZ]; sum += JiM4 * currJ[JME_JAX]; sum += JiM5 * currJ[JME_JAY]; sum += JiM6 * currJ[JME_JAZ]; *currA += sum; if (--j == 0) { break; } ++currA; currJ += JME__MAX; } if (--i == 0) { break; } currJinvM += JIM__MAX; currA += mskip_munus_infomJ_plus_1; } } // this assumes the 4th and 8th rows of B are zero. static inline void MultiplySubJxRhsTmpFromRHS (dReal *rowRhsCfm, const dReal *JRow, const dReal *rowRhsTmp, unsigned int infom) { dIASSERT (infom > 0 && rowRhsCfm && JRow && rowRhsTmp); dReal *currRhs = rowRhsCfm + RCE_RHS; const dReal *currJ = JRow; const dReal RT_LX = rowRhsTmp[dDA_LX], RT_LY = rowRhsTmp[dDA_LY], RT_LZ = rowRhsTmp[dDA_LZ]; const dReal RT_AX = rowRhsTmp[dDA_AX], RT_AY = rowRhsTmp[dDA_AY], RT_AZ = rowRhsTmp[dDA_AZ]; for (unsigned int i = infom; ; ) { dReal sum; sum = currJ[JME_JLX] * RT_LX; sum += currJ[JME_JLY] * RT_LY; sum += currJ[JME_JLZ] * RT_LZ; sum += currJ[JME_JAX] * RT_AX; sum += currJ[JME_JAY] * RT_AY; sum += currJ[JME_JAZ] * RT_AZ; *currRhs -= sum; if (--i == 0) { break; } currRhs += RCE__RHS_CFM_MAX; currJ += JME__MAX; } } static inline void MultiplyAddJxLambdaToCForce(dReal cforce[CFE__MAX], const dReal *JRow, const dReal *rowRhsLambda, unsigned int infom, dJointFeedback *fb/*=NULL*/, unsigned jointBodyIndex) { dIASSERT (infom > 0 && cforce && JRow && rowRhsLambda); dReal sumLX = 0, sumLY = 0, sumLZ = 0, sumAX=0, sumAY = 0, sumAZ = 0; const dReal *currJ = JRow, *currLambda = rowRhsLambda + RLE_LAMBDA; for (unsigned int k = infom; ; ) { const dReal lambda = *currLambda; sumLX += currJ[JME_JLX] * lambda; sumLY += currJ[JME_JLY] * lambda; sumLZ += currJ[JME_JLZ] * lambda; sumAX += currJ[JME_JAX] * lambda; sumAY += currJ[JME_JAY] * lambda; sumAZ += currJ[JME_JAZ] * lambda; if (--k == 0) { break; } currJ += JME__MAX; currLambda += RLE__RHS_LAMBDA_MAX; } if (fb != NULL) { if (jointBodyIndex == dJCB__MIN) { fb->f1[dV3E_X] = sumLX; fb->f1[dV3E_Y] = sumLY; fb->f1[dV3E_Z] = sumLZ; fb->t1[dV3E_X] = sumAX; fb->t1[dV3E_Y] = sumAY; fb->t1[dV3E_Z] = sumAZ; } else { dIASSERT(jointBodyIndex == dJCB__MIN + 1); dSASSERT(dJCB__MAX == 2); fb->f2[dV3E_X] = sumLX; fb->f2[dV3E_Y] = sumLY; fb->f2[dV3E_Z] = sumLZ; fb->t2[dV3E_X] = sumAX; fb->t2[dV3E_Y] = sumAY; fb->t2[dV3E_Z] = sumAZ; } } cforce[CFE_LX] += sumLX; cforce[CFE_LY] += sumLY; cforce[CFE_LZ] += sumLZ; cforce[CFE_AX] += sumAX; cforce[CFE_AY] += sumAY; cforce[CFE_AZ] += sumAZ; } //**************************************************************************** /*extern */ void dxStepIsland(const dxStepperProcessingCallContext *callContext) { IFTIMING(dTimerStart("preprocessing")); dxWorldProcessMemArena *memarena = callContext->m_stepperArena; dxWorld *world = callContext->m_world; unsigned int nb = callContext->m_islandBodiesCount; unsigned int _nj = callContext->m_islandJointsCount; dReal *invI = memarena->AllocateOveralignedArray(dM3E__MAX * (sizeint)nb, INVI_ALIGNMENT); // Reserve twice as much memory and start from the middle so that regardless of // what direction the array grows to there would be sufficient room available. const sizeint ji_reserve_count = 2 * (sizeint)_nj; dJointWithInfo1 *const jointinfos = memarena->AllocateArray(ji_reserve_count); const unsigned allowedThreads = callContext->m_stepperAllowedThreads; dIASSERT(allowedThreads != 0); void *stagesMemArenaState = memarena->SaveState(); dxStepperStage1CallContext *stage1CallContext = (dxStepperStage1CallContext *)memarena->AllocateBlock(sizeof(dxStepperStage1CallContext)); stage1CallContext->Initialize(callContext, stagesMemArenaState, invI, jointinfos); dxStepperStage0BodiesCallContext *stage0BodiesCallContext = (dxStepperStage0BodiesCallContext *)memarena->AllocateBlock(sizeof(dxStepperStage0BodiesCallContext)); stage0BodiesCallContext->Initialize(callContext, invI); dxStepperStage0JointsCallContext *stage0JointsCallContext = (dxStepperStage0JointsCallContext *)memarena->AllocateBlock(sizeof(dxStepperStage0JointsCallContext)); stage0JointsCallContext->Initialize(callContext, jointinfos, &stage1CallContext->m_stage0Outputs); if (allowedThreads == 1) { dxStepIsland_Stage0_Bodies(stage0BodiesCallContext); dxStepIsland_Stage0_Joints(stage0JointsCallContext); dxStepIsland_Stage1(stage1CallContext); } else { unsigned bodyThreads = allowedThreads; unsigned jointThreads = 1; dCallReleaseeID stage1CallReleasee; world->PostThreadedCallForUnawareReleasee(NULL, &stage1CallReleasee, bodyThreads + jointThreads, callContext->m_finalReleasee, NULL, &dxStepIsland_Stage1_Callback, stage1CallContext, 0, "StepIsland Stage1"); world->PostThreadedCallsGroup(NULL, bodyThreads, stage1CallReleasee, &dxStepIsland_Stage0_Bodies_Callback, stage0BodiesCallContext, "StepIsland Stage0-Bodies"); dxStepIsland_Stage0_Joints(stage0JointsCallContext); world->AlterThreadedCallDependenciesCount(stage1CallReleasee, -1); dIASSERT(jointThreads == 1); } } static int dxStepIsland_Stage0_Bodies_Callback(void *_callContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused (void)callThisReleasee; // unused dxStepperStage0BodiesCallContext *callContext = (dxStepperStage0BodiesCallContext *)_callContext; dxStepIsland_Stage0_Bodies(callContext); return 1; } static void dxStepIsland_Stage0_Bodies(dxStepperStage0BodiesCallContext *callContext) { dxBody * const *body = callContext->m_stepperCallContext->m_islandBodiesStart; unsigned int nb = callContext->m_stepperCallContext->m_islandBodiesCount; if (ThrsafeExchange(&callContext->m_tagsTaken, 1) == 0) { // number all bodies in the body list - set their tag values for (unsigned int i=0; itag = i; } if (ThrsafeExchange(&callContext->m_gravityTaken, 1) == 0) { dxWorld *world = callContext->m_stepperCallContext->m_world; // add the gravity force to all bodies // since gravity does normally have only one component it's more efficient // to run three loops for each individual component dxBody *const *const bodyend = body + nb; dReal gravity_x = world->gravity[0]; if (gravity_x) { for (dxBody *const *bodycurr = body; bodycurr != bodyend; ++bodycurr) { dxBody *b = *bodycurr; if ((b->flags & dxBodyNoGravity) == 0) { b->facc[dV3E_X] += b->mass.mass * gravity_x; } } } dReal gravity_y = world->gravity[1]; if (gravity_y) { for (dxBody *const *bodycurr = body; bodycurr != bodyend; ++bodycurr) { dxBody *b = *bodycurr; if ((b->flags & dxBodyNoGravity) == 0) { b->facc[dV3E_Y] += b->mass.mass * gravity_y; } } } dReal gravity_z = world->gravity[2]; if (gravity_z) { for (dxBody *const *bodycurr = body; bodycurr != bodyend; ++bodycurr) { dxBody *b = *bodycurr; if ((b->flags & dxBodyNoGravity) == 0) { b->facc[dV3E_Z] += b->mass.mass * gravity_z; } } } } // for all bodies, compute the inertia tensor and its inverse in the global // frame, and compute the rotational force and add it to the torque // accumulator. I and invI are a vertical stack of 3x4 matrices, one per body. { dReal *invIrow = callContext->m_invI; unsigned int bodyIndex = ThrsafeIncrementIntUpToLimit(&callContext->m_inertiaBodyIndex, nb); for (unsigned int i = 0; i != nb; invIrow += dM3E__MAX, ++i) { if (i == bodyIndex) { dMatrix3 tmp; dxBody *b = body[i]; // compute inverse inertia tensor in global frame dMultiply2_333 (tmp, b->invI, b->posr.R); dMultiply0_333 (invIrow, b->posr.R, tmp); // Don't apply gyroscopic torques to bodies // if not flagged or the body is kinematic if ((b->flags & dxBodyGyroscopic) && (b->invMass > 0)) { dMatrix3 I; // compute inertia tensor in global frame dMultiply2_333 (tmp,b->mass.I,b->posr.R); dMultiply0_333 (I,b->posr.R,tmp); // compute rotational force #if 0 // Explicit computation dMultiply0_331 (tmp,I,b->avel); dSubtractVectorCross3(b->tacc,b->avel,tmp); #else // Do the implicit computation based on //"Stabilizing Gyroscopic Forces in Rigid Multibody Simulations" // (Lacoursière 2006) dReal h = callContext->m_stepperCallContext->m_stepSize; // Step size dVector3 L; // Compute angular momentum dMultiply0_331(L, I, b->avel); // Compute a new effective 'inertia tensor' // for the implicit step: the cross-product // matrix of the angular momentum plus the // old tensor scaled by the timestep. // Itild may not be symmetric pos-definite, // but we can still use it to compute implicit // gyroscopic torques. dMatrix3 Itild = { 0 }; dSetCrossMatrixMinus(Itild, L, dV3E__MAX); for (int ii = dM3E__MIN; ii != dM3E__MAX; ++ii) { Itild[ii] = Itild[ii] * h + I[ii]; } // Scale momentum by inverse time to get // a sort of "torque" dScaleVector3(L, dRecip(h)); // Invert the pseudo-tensor dMatrix3 itInv; // This is a closed-form inversion. // It's probably not numerically stable // when dealing with small masses with // a large asymmetry. // An LU decomposition might be better. if (dInvertMatrix3(itInv, Itild) != 0) { // "Divide" the original tensor // by the pseudo-tensor (on the right) dMultiply0_333(Itild, I, itInv); // Subtract an identity matrix Itild[dM3E_XX] -= 1; Itild[dM3E_YY] -= 1; Itild[dM3E_ZZ] -= 1; // This new inertia matrix rotates the // momentum to get a new set of torques // that will work correctly when applied // to the old inertia matrix as explicit // torques with a semi-implicit update // step. dVector3 tau0; dMultiply0_331(tau0,Itild,L); // Add the gyro torques to the torque // accumulator for (int ii = dSA__MIN; ii != dSA__MAX; ++ii) { b->tacc[dV3E__AXES_MIN + ii] += tau0[dV3E__AXES_MIN + ii]; } } #endif } bodyIndex = ThrsafeIncrementIntUpToLimit(&callContext->m_inertiaBodyIndex, nb); } } } } // static // int dxStepIsland_Stage0_Joints_Callback(void *_callContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) // { // (void)callInstanceIndex; // unused // (void)callThisReleasee; // unused // dxStepperStage0JointsCallContext *callContext = (dxStepperStage0JointsCallContext *)_callContext; // dxStepIsland_Stage0_Joints(callContext); // return 1; // } static void dxStepIsland_Stage0_Joints(dxStepperStage0JointsCallContext *callContext) { dxJoint * const *_joint = callContext->m_stepperCallContext->m_islandJointsStart; dJointWithInfo1 *jointinfos = callContext->m_jointinfos; unsigned int _nj = callContext->m_stepperCallContext->m_islandJointsCount; // get m = total constraint dimension, nub = number of unbounded variables. // create constraint offset array and number-of-rows array for all joints. // the constraints are re-ordered as follows: the purely unbounded // constraints, the mixed unbounded + LCP constraints, and last the purely // LCP constraints. this assists the LCP solver to put all unbounded // variables at the start for a quick factorization. // // joints with m=0 are inactive and are removed from the joints array // entirely, so that the code that follows does not consider them. // also number all active joints in the joint list (set their tag values). // inactive joints receive a tag value of -1. sizeint ji_start, ji_end; { unsigned int mcurr = 0; sizeint unb_start, mix_start, mix_end, lcp_end; unb_start = mix_start = mix_end = lcp_end = _nj; dJointWithInfo1 *jicurr = jointinfos + lcp_end; dxJoint *const *const _jend = _joint + _nj; dxJoint *const *_jcurr = _joint; while (true) { // ------------------------------------------------------------------------- // Switch to growing array forward { bool fwd_end_reached = false; dJointWithInfo1 *jimixend = jointinfos + mix_end; while (true) { // jicurr=dest, _jcurr=src if (_jcurr == _jend) { lcp_end = jicurr - jointinfos; fwd_end_reached = true; break; } dxJoint *j = *_jcurr++; j->getInfo1 (&jicurr->info); dIASSERT (/*jicurr->info.m >= 0 && */jicurr->info.m <= 6 && /*jicurr->info.nub >= 0 && */jicurr->info.nub <= jicurr->info.m); if (jicurr->info.m != 0) { mcurr += jicurr->info.m; if (jicurr->info.nub == 0) { // A lcp info - a correct guess!!! jicurr->joint = j; ++jicurr; } else if (jicurr->info.nub < jicurr->info.m) { // A mixed case if (unb_start == mix_start) { // no unbounded infos yet - just move to opposite side of mixed-s unb_start = mix_start = mix_start - 1; dJointWithInfo1 *jimixstart = jointinfos + mix_start; jimixstart->info = jicurr->info; jimixstart->joint = j; } else if (jimixend != jicurr) { // have to swap to the tail of mixed-s dxJoint::Info1 tmp_info = jicurr->info; *jicurr = *jimixend; jimixend->info = tmp_info; jimixend->joint = j; ++jimixend; ++jicurr; } else { // no need to swap as there are no LCP info-s yet jicurr->joint = j; jimixend = jicurr = jicurr + 1; } } else { // A purely unbounded case -- break out and proceed growing in opposite direction unb_start = unb_start - 1; dJointWithInfo1 *jiunbstart = jointinfos + unb_start; jiunbstart->info = jicurr->info; jiunbstart->joint = j; lcp_end = jicurr - jointinfos; mix_end = jimixend - jointinfos; jicurr = jiunbstart - 1; break; } } else { j->tag = -1; } } if (fwd_end_reached) { break; } } // ------------------------------------------------------------------------- // Switch to growing array backward { bool bkw_end_reached = false; dJointWithInfo1 *jimixstart = jointinfos + mix_start - 1; while (true) { // jicurr=dest, _jcurr=src if (_jcurr == _jend) { unb_start = (jicurr + 1) - jointinfos; mix_start = (jimixstart + 1) - jointinfos; bkw_end_reached = true; break; } dxJoint *j = *_jcurr++; j->getInfo1 (&jicurr->info); dIASSERT (/*jicurr->info.m >= 0 && */jicurr->info.m <= 6 && /*jicurr->info.nub >= 0 && */jicurr->info.nub <= jicurr->info.m); if (jicurr->info.m != 0) { mcurr += jicurr->info.m; if (jicurr->info.nub == jicurr->info.m) { // An unbounded info - a correct guess!!! jicurr->joint = j; --jicurr; } else if (jicurr->info.nub != 0) { // A mixed case if (mix_end == lcp_end) { // no lcp infos yet - just move to opposite side of mixed-s dJointWithInfo1 *jimixend = jointinfos + mix_end; lcp_end = mix_end = mix_end + 1; jimixend->info = jicurr->info; jimixend->joint = j; } else if (jimixstart != jicurr) { // have to swap to the head of mixed-s dxJoint::Info1 tmp_info = jicurr->info; *jicurr = *jimixstart; jimixstart->info = tmp_info; jimixstart->joint = j; --jimixstart; --jicurr; } else { // no need to swap as there are no unbounded info-s yet jicurr->joint = j; jimixstart = jicurr = jicurr - 1; } } else { // A purely lcp case -- break out and proceed growing in opposite direction dJointWithInfo1 *jilcpend = jointinfos + lcp_end; lcp_end = lcp_end + 1; jilcpend->info = jicurr->info; jilcpend->joint = j; unb_start = (jicurr + 1) - jointinfos; mix_start = (jimixstart + 1) - jointinfos; jicurr = jilcpend + 1; break; } } else { j->tag = -1; } } if (bkw_end_reached) { break; } } } callContext->m_stage0Outputs->m = mcurr; callContext->m_stage0Outputs->nub = (unsigned)(mix_start - unb_start); dIASSERT((sizeint)(mix_start - unb_start) <= (sizeint)UINT_MAX); ji_start = unb_start; ji_end = lcp_end; } { const dJointWithInfo1 *jicurr = jointinfos + ji_start; const dJointWithInfo1 *const jiend = jointinfos + ji_end; for (unsigned int i = 0; jicurr != jiend; i++, ++jicurr) { jicurr->joint->tag = i; } } callContext->m_stage0Outputs->ji_start = ji_start; callContext->m_stage0Outputs->ji_end = ji_end; } static int dxStepIsland_Stage1_Callback(void *_stage1CallContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused (void)callThisReleasee; // unused dxStepperStage1CallContext *stage1CallContext = (dxStepperStage1CallContext *)_stage1CallContext; dxStepIsland_Stage1(stage1CallContext); return 1; } static void dxStepIsland_Stage1(dxStepperStage1CallContext *stage1CallContext) { const dxStepperProcessingCallContext *callContext = stage1CallContext->m_stepperCallContext; dJointWithInfo1 *_jointinfos = stage1CallContext->m_jointinfos; dReal *invI = stage1CallContext->m_invI; sizeint ji_start = stage1CallContext->m_stage0Outputs.ji_start; sizeint ji_end = stage1CallContext->m_stage0Outputs.ji_end; unsigned int m = stage1CallContext->m_stage0Outputs.m; unsigned int nub = stage1CallContext->m_stage0Outputs.nub; dxWorldProcessMemArena *memarena = callContext->m_stepperArena; { memarena->RestoreState(stage1CallContext->m_stageMemArenaState); stage1CallContext = NULL; // WARNING! _stage1CallContext is not valid after this point! dIVERIFY(stage1CallContext == NULL); // To suppress compiler warnings about unused variable assignment unsigned int _nj = callContext->m_islandJointsCount; const sizeint ji_reserve_count = 2 * (sizeint)_nj; memarena->ShrinkArray(_jointinfos, ji_reserve_count, ji_end); } dJointWithInfo1 *jointinfos = _jointinfos + ji_start; unsigned int nj = (unsigned int)(ji_end - ji_start); dIASSERT((sizeint)(ji_end - ji_start) <= (sizeint)UINT_MAX); unsigned int *mindex = NULL; dReal *J = NULL, *A = NULL, *pairsRhsCfm = NULL, *pairsLoHi = NULL; int *findex = NULL; atomicord32 *bodyStartJoints = NULL, *bodyJointLinks = NULL; // if there are constraints, compute constrForce if (m > 0) { mindex = memarena->AllocateArray((sizeint)(nj + 1)); { unsigned int *mcurr = mindex; unsigned int moffs = 0; mcurr[0] = moffs; mcurr += 1; const dJointWithInfo1 *const jiend = jointinfos + nj; for (const dJointWithInfo1 *jicurr = jointinfos; jicurr != jiend; ++jicurr) { //dxJoint *joint = jicurr->joint; moffs += jicurr->info.m; mcurr[0] = moffs; mcurr += 1; } } // create a constraint equation right hand side vector `c', a constraint // force mixing vector `cfm', and LCP low and high bound vectors, and an // 'findex' vector. findex = memarena->AllocateArray(m); J = memarena->AllocateArray((sizeint)m * (2 * JME__MAX)); A = memarena->AllocateOveralignedArray((sizeint)m * dPAD(m), AMATRIX_ALIGNMENT); pairsRhsCfm = memarena->AllocateArray((sizeint)m * RCE__RHS_CFM_MAX); pairsLoHi = memarena->AllocateArray((sizeint)m * LHE__LO_HI_MAX); const unsigned int nb = callContext->m_islandBodiesCount; bodyStartJoints = memarena->AllocateArray(nb); bodyJointLinks = memarena->AllocateArray((sizeint)nj * dJCB__MAX); dICHECK(nj < ~((atomicord32)0) / dJCB__MAX); // If larger joint counts are to be used, pointers (or sizeint) need to be stored rather than atomicord32 indices } dxStepperLocalContext *localContext = (dxStepperLocalContext *)memarena->AllocateBlock(sizeof(dxStepperLocalContext)); localContext->Initialize(invI, jointinfos, nj, m, nub, mindex, findex, J, A, pairsRhsCfm, pairsLoHi, bodyStartJoints, bodyJointLinks); void *stage1MemarenaState = memarena->SaveState(); dxStepperStage3CallContext *stage3CallContext = (dxStepperStage3CallContext*)memarena->AllocateBlock(sizeof(dxStepperStage3CallContext)); stage3CallContext->Initialize(callContext, localContext, stage1MemarenaState); if (m > 0) { dReal *JinvM = memarena->AllocateOveralignedArray((sizeint)m * (2 * JIM__MAX), JINVM_ALIGNMENT); const unsigned int nb = callContext->m_islandBodiesCount; dReal *rhs_tmp = memarena->AllocateArray((sizeint)nb * dDA__MAX); dxStepperStage2CallContext *stage2CallContext = (dxStepperStage2CallContext *)memarena->AllocateBlock(sizeof(dxStepperStage2CallContext)); stage2CallContext->Initialize(callContext, localContext, JinvM, rhs_tmp); const unsigned allowedThreads = callContext->m_stepperAllowedThreads; dIASSERT(allowedThreads != 0); if (allowedThreads == 1) { IFTIMING(dTimerNow("create J")); dxStepIsland_Stage2a(stage2CallContext); IFTIMING(dTimerNow("compute Adiag, JinvM and rhs_tmp")); dxStepIsland_Stage2b(stage2CallContext); IFTIMING(dTimerNow("compute A and rhs")); dxStepIsland_Stage2c(stage2CallContext); dxStepIsland_Stage3(stage3CallContext); } else { dxWorld *world = callContext->m_world; dCallReleaseeID stage3CallReleasee; world->PostThreadedCallForUnawareReleasee(NULL, &stage3CallReleasee, 1, callContext->m_finalReleasee, NULL, &dxStepIsland_Stage3_Callback, stage3CallContext, 0, "StepIsland Stage3"); dCallReleaseeID stage2bSyncReleasee; world->PostThreadedCall(NULL, &stage2bSyncReleasee, 1, stage3CallReleasee, NULL, &dxStepIsland_Stage2bSync_Callback, stage2CallContext, 0, "StepIsland Stage2b Sync"); dCallReleaseeID stage2aSyncReleasee; world->PostThreadedCall(NULL, &stage2aSyncReleasee, allowedThreads, stage2bSyncReleasee, NULL, &dxStepIsland_Stage2aSync_Callback, stage2CallContext, 0, "StepIsland Stage2a Sync"); dIASSERT(allowedThreads > 1); /*if (allowedThreads > 1) */{ world->PostThreadedCallsGroup(NULL, allowedThreads - 1, stage2aSyncReleasee, &dxStepIsland_Stage2a_Callback, stage2CallContext, "StepIsland Stage2a"); } dxStepIsland_Stage2a(stage2CallContext); world->AlterThreadedCallDependenciesCount(stage2aSyncReleasee, -1); } } else { dxStepIsland_Stage3(stage3CallContext); } } static int dxStepIsland_Stage2a_Callback(void *_stage2CallContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused (void)callThisReleasee; // unused dxStepperStage2CallContext *stage2CallContext = (dxStepperStage2CallContext *)_stage2CallContext; dxStepIsland_Stage2a(stage2CallContext); return 1; } static void dxStepIsland_Stage2a(dxStepperStage2CallContext *stage2CallContext) { const dxStepperProcessingCallContext *callContext = stage2CallContext->m_stepperCallContext; const dxStepperLocalContext *localContext = stage2CallContext->m_localContext; dJointWithInfo1 *jointinfos = localContext->m_jointinfos; unsigned int nj = localContext->m_nj; const unsigned int *mindex = localContext->m_mindex; const dReal stepsizeRecip = dRecip(callContext->m_stepSize); dxWorld *world = callContext->m_world; { int *findex = localContext->m_findex; dReal *J = localContext->m_J; dReal *pairsRhsCfm = localContext->m_pairsRhsCfm; dReal *pairsLoHi = localContext->m_pairsLoHi; // get jacobian data from constraints. a (2*m)x8 matrix will be created // to store the two jacobian blocks from each constraint. it has this // format: // // l l l 0 a a a 0 \ . // l l l 0 a a a 0 }-- jacobian body 1 block for joint 0 (3 rows) // l l l 0 a a a 0 / // l l l 0 a a a 0 \ . // l l l 0 a a a 0 }-- jacobian body 2 block for joint 0 (3 rows) // l l l 0 a a a 0 / // l l l 0 a a a 0 }--- jacobian body 1 block for joint 1 (1 row) // l l l 0 a a a 0 }--- jacobian body 2 block for joint 1 (1 row) // etc... // // (lll) = linear jacobian data // (aaa) = angular jacobian data // const dReal worldERP = world->global_erp; const dReal worldCFM = world->global_cfm; unsigned ji; while ((ji = ThrsafeIncrementIntUpToLimit(&stage2CallContext->m_ji_J, nj)) != nj) { const unsigned ofsi = mindex[ji]; const unsigned int infom = mindex[ji + 1] - ofsi; dReal *const JRow = J + (sizeint)ofsi * (2 * JME__MAX); dReal *rowRhsCfm = pairsRhsCfm + (sizeint)ofsi * RCE__RHS_CFM_MAX; dReal *rowLoHi = pairsLoHi + (sizeint)ofsi * LHE__LO_HI_MAX; { dSetZero (JRow, infom * (2 * JME__MAX)); dReal *const endRhsCfm = rowRhsCfm + infom * RCE__RHS_CFM_MAX; for (dReal *currRhsCfm = rowRhsCfm; currRhsCfm != endRhsCfm; currRhsCfm += RCE__RHS_CFM_MAX) { currRhsCfm[RCE_RHS] = REAL(0.0); currRhsCfm[RCE_CFM] = worldCFM; } dReal *const endLoHi = rowLoHi + infom * LHE__LO_HI_MAX; for (dReal *currLoHi = rowLoHi; currLoHi != endLoHi; currLoHi += LHE__LO_HI_MAX) { currLoHi[LHE_LO] = -dInfinity; currLoHi[LHE_HI] = dInfinity; } } int *findexRow = findex + ofsi; dSetValue(findexRow, infom, -1); dxJoint *joint = jointinfos[ji].joint; joint->getInfo2(stepsizeRecip, worldERP, JME__MAX, JRow + JME__J_MIN, JRow + infom * JME__MAX + JME__J_MIN, RCE__RHS_CFM_MAX, rowRhsCfm, rowLoHi, findexRow); dSASSERT((int)LHE__LO_HI_MAX == RCE__RHS_CFM_MAX); // To make sure same step fits for both pairs in the call to dxJoint::getInfo2() above // findex iteration is compact and is not going to pollute caches - do it first { // adjust returned findex values for global index numbering int *const findicesEnd = findexRow + infom; for (int *findexCurr = findexRow; findexCurr != findicesEnd; ++findexCurr) { int fival = *findexCurr; if (fival != -1) { *findexCurr = fival + ofsi; } } } { dReal *const endRhsCfm = rowRhsCfm + infom * RCE__RHS_CFM_MAX; for (dReal *currRhsCfm = rowRhsCfm; currRhsCfm != endRhsCfm; currRhsCfm += RCE__RHS_CFM_MAX) { currRhsCfm[RCE_RHS] *= stepsizeRecip; currRhsCfm[RCE_CFM] *= stepsizeRecip; } } } } } static int dxStepIsland_Stage2aSync_Callback(void *_stage2CallContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused dxStepperStage2CallContext *stage2CallContext = (dxStepperStage2CallContext *)_stage2CallContext; const dxStepperProcessingCallContext *callContext = stage2CallContext->m_stepperCallContext; const unsigned allowedThreads = callContext->m_stepperAllowedThreads; dIASSERT(allowedThreads > 1); /*if (allowedThreads > 1) */{ // The allowed thread count is greater than one as otherwise current function would not be scheduled for execution from the previous stage dxWorld *world = callContext->m_world; world->AlterThreadedCallDependenciesCount(callThisReleasee, allowedThreads - 1); world->PostThreadedCallsGroup(NULL, allowedThreads - 1, callThisReleasee, &dxStepIsland_Stage2b_Callback, stage2CallContext, "StepIsland Stage2b"); } dxStepIsland_Stage2b(stage2CallContext); return 1; } static int dxStepIsland_Stage2b_Callback(void *_stage2CallContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused (void)callThisReleasee; // unused dxStepperStage2CallContext *stage2CallContext = (dxStepperStage2CallContext *)_stage2CallContext; dxStepIsland_Stage2b(stage2CallContext); return 1; } static void dxStepIsland_Stage2b(dxStepperStage2CallContext *stage2CallContext) { const dxStepperProcessingCallContext *callContext = stage2CallContext->m_stepperCallContext; const dxStepperLocalContext *localContext = stage2CallContext->m_localContext; dJointWithInfo1 *jointinfos = localContext->m_jointinfos; unsigned int nj = localContext->m_nj; const unsigned int *mindex = localContext->m_mindex; { // Warning!!! // This code depends on cfm elements and therefore must be in different sub-stage // from Jacobian construction in Stage2a to ensure proper synchronization // and avoid accessing numbers being modified. // Warning!!! dReal *A = localContext->m_A; const dReal *pairsRhsCfm = localContext->m_pairsRhsCfm; const unsigned m = localContext->m_m; const unsigned int mskip = dPAD(m); unsigned ji; while ((ji = ThrsafeIncrementIntUpToLimit(&stage2CallContext->m_ji_Ainit, nj)) != nj) { const unsigned ofsi = mindex[ji]; const unsigned int infom = mindex[ji + 1] - ofsi; dReal *Arow = A + (sizeint)mskip * ofsi; dSetZero(Arow, (sizeint)mskip * infom); dReal *Adiag = Arow + ofsi; const dReal *rowRfsCrm = pairsRhsCfm + (sizeint)ofsi * RCE__RHS_CFM_MAX; for (unsigned int i = 0; i != infom; Adiag += mskip, ++i) { Adiag[i] = (rowRfsCrm + i * RCE__RHS_CFM_MAX)[RCE_CFM]; } } } { // Warning!!! // This code depends on J elements and therefore must be in different sub-stage // from Jacobian construction in Stage2a to ensure proper synchronization // and avoid accessing numbers being modified. // Warning!!! const dReal *invI = localContext->m_invI; const dReal *J = localContext->m_J; dReal *JinvM = stage2CallContext->m_JinvM; // compute A = J*invM*J'. first compute JinvM = J*invM. this has the same // format as J so we just go through the constraints in J multiplying by // the appropriate scalars and matrices. unsigned ji; while ((ji = ThrsafeIncrementIntUpToLimit(&stage2CallContext->m_ji_JinvM, nj)) != nj) { const unsigned ofsi = mindex[ji]; const unsigned int infom = mindex[ji + 1] - ofsi; dReal *Jdst = JinvM + (sizeint)ofsi * (2 * JIM__MAX); dSetZero(Jdst, infom * (2 * JIM__MAX)); const dReal *Jsrc = J + (sizeint)ofsi * (2 * JME__MAX); dxJoint *joint = jointinfos[ji].joint; dxBody *jb0 = joint->node[0].body; if (true || jb0 != NULL) { // -- always true dReal body_invMass0 = jb0->invMass; const dReal *body_invI0 = invI + (sizeint)(unsigned int)jb0->tag * dM3E__MAX; for (unsigned int j = infom; j != 0; --j) { for (unsigned int k = dSA__MIN; k != dSA__MAX; ++k) Jdst[JIM__L_AXES_MIN + k] = Jsrc[JME__JL_MIN + k] * body_invMass0; dMultiply0_133(Jdst + JIM__A_AXES_MIN, Jsrc + JME__JA_MIN, body_invI0); Jsrc += JME__MAX; Jdst += JIM__MAX; } } dxBody *jb1 = joint->node[1].body; if (jb1 != NULL) { dReal body_invMass1 = jb1->invMass; const dReal *body_invI1 = invI + (sizeint)(unsigned int)jb1->tag * dM3E__MAX; for (unsigned int j = infom; j != 0; --j) { for (unsigned int k = dSA__MIN; k != dSA__MAX; ++k) Jdst[JIM__L_AXES_MIN + k] = Jsrc[JME__JL_MIN + k] * body_invMass1; dMultiply0_133 (Jdst + JIM__A_AXES_MIN, Jsrc + JME__JA_MIN, body_invI1); Jsrc += JME__MAX; Jdst += JIM__MAX; } } } } { // Warning!!! // This code reads facc/tacc fields of body objects which (the fields) // may be modified by dxJoint::getInfo2(). Therefore the code must be // in different sub-stage from Jacobian construction in Stage2a // to ensure proper synchronization and avoid accessing numbers being modified. // Warning!!! dxBody * const *const body = callContext->m_islandBodiesStart; const unsigned int nb = callContext->m_islandBodiesCount; const dReal *invI = localContext->m_invI; atomicord32 *bodyStartJoints = localContext->m_bodyStartJoints; dReal *rhs_tmp = stage2CallContext->m_rhs_tmp; // compute the right hand side `rhs' const dReal stepsizeRecip = dRecip(callContext->m_stepSize); // put v/h + invM*fe into rhs_tmp unsigned bi; while ((bi = ThrsafeIncrementIntUpToLimit(&stage2CallContext->m_bi_rhs_tmp, nb)) != nb) { dReal *tmp1curr = rhs_tmp + (sizeint)bi * dDA__MAX; const dReal *invIrow = invI + (sizeint)bi * dM3E__MAX; dxBody *b = body[bi]; // dSetZero(tmp1curr, 8); -- not needed for (unsigned int j = dSA__MIN; j != dSA__MAX; ++j) tmp1curr[dDA__L_MIN + j] = b->facc[dV3E__AXES_MIN + j] * b->invMass + b->lvel[dV3E__AXES_MIN + j] * stepsizeRecip; dMultiply0_331 (tmp1curr + dDA__A_MIN, invIrow, b->tacc); for (unsigned int k = dSA__MIN; k != dSA__MAX; ++k) tmp1curr[dDA__A_MIN + k] += b->avel[dV3E__AXES_MIN + k] * stepsizeRecip; // Initialize body start joint indices -- this will be needed later for building body related joint list in dxStepIsland_Stage2c bodyStartJoints[bi] = 0; } } } static int dxStepIsland_Stage2bSync_Callback(void *_stage2CallContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused dxStepperStage2CallContext *stage2CallContext = (dxStepperStage2CallContext *)_stage2CallContext; const dxStepperProcessingCallContext *callContext = stage2CallContext->m_stepperCallContext; const unsigned allowedThreads = callContext->m_stepperAllowedThreads; dIASSERT(allowedThreads > 1); /*if (allowedThreads > 1) */{ // The allowed thread count is greater than one as otherwise current function would not be scheduled for execution from the previous stage dxWorld *world = callContext->m_world; world->AlterThreadedCallDependenciesCount(callThisReleasee, allowedThreads - 1); world->PostThreadedCallsGroup(NULL, allowedThreads - 1, callThisReleasee, &dxStepIsland_Stage2c_Callback, stage2CallContext, "StepIsland Stage2c"); } dxStepIsland_Stage2c(stage2CallContext); return 1; } static int dxStepIsland_Stage2c_Callback(void *_stage2CallContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused (void)callThisReleasee; // unused dxStepperStage2CallContext *stage2CallContext = (dxStepperStage2CallContext *)_stage2CallContext; dxStepIsland_Stage2c(stage2CallContext); return 1; } static void dxStepIsland_Stage2c(dxStepperStage2CallContext *stage2CallContext) { //const dxStepperProcessingCallContext *callContext = stage2CallContext->m_stepperCallContext; const dxStepperLocalContext *localContext = stage2CallContext->m_localContext; dJointWithInfo1 *jointinfos = localContext->m_jointinfos; unsigned int nj = localContext->m_nj; const unsigned int *mindex = localContext->m_mindex; { // Warning!!! // This code depends on A elements and JinvM elements and therefore // must be in different sub-stage from A initialization and JinvM calculation in Stage2b // to ensure proper synchronization and avoid accessing numbers being modified. // Warning!!! dReal *A = localContext->m_A; const dReal *JinvM = stage2CallContext->m_JinvM; const dReal *J = localContext->m_J; const unsigned m = localContext->m_m; // now compute A = JinvM * J'. A's rows and columns are grouped by joint, // i.e. in the same way as the rows of J. block (i,j) of A is only nonzero // if joints i and j have at least one body in common. const unsigned int mskip = dPAD(m); unsigned ji; while ((ji = ThrsafeIncrementIntUpToLimit(&stage2CallContext->m_ji_Aaddjb, nj)) != nj) { const unsigned ofsi = mindex[ji]; const unsigned int infom = mindex[ji + 1] - ofsi; dReal *Arow = A + (sizeint)mskip * ofsi; const dReal *JinvMRow = JinvM + (sizeint)ofsi * (2 * JIM__MAX); dxJoint *joint = jointinfos[ji].joint; dxBody *jb0 = joint->node[0].body; if (true || jb0 != NULL) { // -- always true // compute diagonal block of A const dReal *JRow = J + (sizeint)ofsi * (2 * JME__MAX); MultiplyAddJinvMxJToA (Arow + ofsi, JinvMRow, JRow, infom, infom, mskip); for (dxJointNode *n0 = (ji != 0 ? jb0->firstjoint : NULL); n0; n0 = n0->next) { // if joint was tagged as -1 then it is an inactive (m=0 or disabled) // joint that should not be considered int j0 = n0->joint->tag; if (j0 != -1 && (unsigned)j0 < ji) { const unsigned int jiother_ofsi = mindex[j0]; const unsigned int jiother_infom = mindex[j0 + 1] - jiother_ofsi; const dJointWithInfo1 *jiother = jointinfos + j0; unsigned int smart_infom = (jiother->joint->node[1].body == jb0) ? jiother_infom : 0; // set block of A const dReal *JOther = J + ((sizeint)jiother_ofsi * 2 + smart_infom) * JME__MAX; MultiplyAddJinvMxJToA (Arow + jiother_ofsi, JinvMRow, JOther, infom, jiother_infom, mskip); } } } dxBody *jb1 = joint->node[1].body; dIASSERT(jb1 != jb0); if (jb1 != NULL) { const dReal *JinvMOther = JinvMRow + infom * JIM__MAX; // compute diagonal block of A const dReal *JRow = J + ((sizeint)ofsi * 2 + infom) * JME__MAX; MultiplyAddJinvMxJToA (Arow + ofsi, JinvMOther, JRow, infom, infom, mskip); for (dxJointNode *n1 = (ji != 0 ? jb1->firstjoint : NULL); n1; n1 = n1->next) { // if joint was tagged as -1 then it is an inactive (m=0 or disabled) // joint that should not be considered int j1 = n1->joint->tag; if (j1 != -1 && (unsigned)j1 < ji) { const unsigned int jiother_ofsi = mindex[j1]; const unsigned int jiother_infom = mindex[j1 + 1] - jiother_ofsi; const dJointWithInfo1 *jiother = jointinfos + j1; unsigned int smart_infom = (jiother->joint->node[1].body == jb1) ? jiother_infom : 0; // set block of A const dReal *JOther = J + ((sizeint)jiother_ofsi * 2 + smart_infom) * JME__MAX; MultiplyAddJinvMxJToA (Arow + jiother_ofsi, JinvMOther, JOther, infom, jiother_infom, mskip); } } } } } { // Warning!!! // This code depends on rhs_tmp elements and therefore must be in // different sub-stage from rhs_tmp calculation in Stage2b to ensure // proper synchronization and avoid accessing numbers being modified. // Warning!!! const dReal *J = localContext->m_J; const dReal *rhs_tmp = stage2CallContext->m_rhs_tmp; dReal *pairsRhsCfm = localContext->m_pairsRhsCfm; atomicord32 *bodyStartJoints = localContext->m_bodyStartJoints; atomicord32 *bodyJointLinks = localContext->m_bodyJointLinks; // compute the right hand side `rhs' // put J*rhs_tmp into rhs unsigned ji; while ((ji = ThrsafeIncrementIntUpToLimit(&stage2CallContext->m_ji_rhs, nj)) != nj) { const unsigned ofsi = mindex[ji]; const unsigned int infom = mindex[ji + 1] - ofsi; dReal *currRhsCfm = pairsRhsCfm + (sizeint)ofsi * RCE__RHS_CFM_MAX; const dReal *JRow = J + (sizeint)ofsi * (2 * JME__MAX); dxJoint *joint = jointinfos[ji].joint; dxBody *jb0 = joint->node[0].body; if (true || jb0 != NULL) { // -- always true unsigned bodyIndex = (unsigned)jb0->tag; MultiplySubJxRhsTmpFromRHS (currRhsCfm, JRow, rhs_tmp + (sizeint)bodyIndex * dDA__MAX, infom); // Link joints connected to each body into a list to be used on results incorporation. The bodyStartJoints have been initialized in dxStepIsland_Stage2b. const atomicord32 linkIndex = (atomicord32)((sizeint)ji * dJCB__MAX + dJCB_FIRST_BODY); // It is asserted at links buffer allocation that the indices can't overflow atomicord32 for (atomicord32 oldStartIndex = bodyStartJoints[bodyIndex]; ; oldStartIndex = bodyStartJoints[bodyIndex]) { bodyJointLinks[linkIndex] = oldStartIndex; if (ThrsafeCompareExchange(&bodyStartJoints[bodyIndex], oldStartIndex, linkIndex + 1)) { // The link index is stored incremented to allow 0 as end indicator break; } } } dxBody *jb1 = joint->node[1].body; if (jb1 != NULL) { unsigned bodyIndex = (unsigned)jb1->tag; MultiplySubJxRhsTmpFromRHS (currRhsCfm, JRow + infom * JME__MAX, rhs_tmp + (sizeint)bodyIndex * dDA__MAX, infom); // Link joints connected to each body into a list to be used on results incorporation. The bodyStartJoints have been initialized in dxStepIsland_Stage2b const atomicord32 linkIndex = (atomicord32)((sizeint)ji * dJCB__MAX + dJCB_SECOND_BODY); // It is asserted at links buffer allocation that the indices can't overflow atomicord32 for (atomicord32 oldStartIndex = bodyStartJoints[bodyIndex]; ; oldStartIndex = bodyStartJoints[bodyIndex]) { bodyJointLinks[linkIndex] = oldStartIndex; if (ThrsafeCompareExchange(&bodyStartJoints[bodyIndex], oldStartIndex, linkIndex + 1)) { // The link index is stored incremented to allow 0 as end indicator break; } } } } } } static int dxStepIsland_Stage3_Callback(void *_stage3CallContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused (void)callThisReleasee; // unused dxStepperStage3CallContext *stage3CallContext = (dxStepperStage3CallContext *)_stage3CallContext; dxStepIsland_Stage3(stage3CallContext); return 1; } static void dxStepIsland_Stage3(dxStepperStage3CallContext *stage3CallContext) { const dxStepperProcessingCallContext *callContext = stage3CallContext->m_stepperCallContext; const dxStepperLocalContext *localContext = stage3CallContext->m_localContext; dxWorldProcessMemArena *memarena = callContext->m_stepperArena; memarena->RestoreState(stage3CallContext->m_stage1MemArenaState); stage3CallContext = NULL; // WARNING! stage3CallContext is not valid after this point! dIVERIFY(stage3CallContext == NULL); // To suppress unused variable assignment warnings unsigned int m = localContext->m_m; unsigned int nub = localContext->m_nub; //const unsigned int *mindex = localContext->m_mindex; int *findex = localContext->m_findex; dReal *A = localContext->m_A; dReal *pairsRhsLambda = localContext->m_pairsRhsCfm; // Reuse cfm buffer for lambdas as the former values are not needed any more dReal *pairsLoHi = localContext->m_pairsLoHi; if (m > 0) { BEGIN_STATE_SAVE(memarena, lcpstate) { IFTIMING(dTimerNow ("solve LCP problem")); // solve the LCP problem and get lambda. // this will destroy A but that's OK dxSolveLCP (memarena, m, A, pairsRhsLambda, NULL, nub, pairsLoHi, findex); dSASSERT((int)RLE__RHS_LAMBDA_MAX == PBX__MAX && (int)RLE_RHS == PBX_B && (int)RLE_LAMBDA == PBX_X); dSASSERT((int)LHE__LO_HI_MAX == PLH__MAX && (int)LHE_LO == PLH_LO && (int)LHE_HI == PLH_HI); } END_STATE_SAVE(memarena, lcpstate); } // void *stage3MemarenaState = memarena->SaveState(); dxStepperStage4CallContext *stage4CallContext = (dxStepperStage4CallContext *)memarena->AllocateBlock(sizeof(dxStepperStage4CallContext)); stage4CallContext->Initialize(callContext, localContext/*, stage3MemarenaState*/); const unsigned allowedThreads = callContext->m_stepperAllowedThreads; dIASSERT(allowedThreads != 0); if (allowedThreads == 1) { IFTIMING(dTimerNow ("compute and apply constraint force")); dxStepIsland_Stage4(stage4CallContext); IFTIMING(dTimerEnd()); if (m > 0) { IFTIMING(dTimerReport(stdout,1)); } } else { dCallReleaseeID finalReleasee = callContext->m_finalReleasee; dxWorld *world = callContext->m_world; world->AlterThreadedCallDependenciesCount(finalReleasee, allowedThreads - 1); world->PostThreadedCallsGroup(NULL, allowedThreads - 1, finalReleasee, &dxStepIsland_Stage4_Callback, stage4CallContext, "StepIsland Stage4"); // Note: Adding another dependency for the finalReleasee is not necessary as it already depends on the current call dxStepIsland_Stage4(stage4CallContext); } } static int dxStepIsland_Stage4_Callback(void *_stage4CallContext, dcallindex_t callInstanceIndex, dCallReleaseeID callThisReleasee) { (void)callInstanceIndex; // unused (void)callThisReleasee; // unused dxStepperStage4CallContext *stage4CallContext = (dxStepperStage4CallContext *)_stage4CallContext; dxStepIsland_Stage4(stage4CallContext); return 1; } static void dxStepIsland_Stage4(dxStepperStage4CallContext *stage4CallContext) { const dxStepperProcessingCallContext *callContext = stage4CallContext->m_stepperCallContext; const dxStepperLocalContext *localContext = stage4CallContext->m_localContext; const dReal stepSize = callContext->m_stepSize; dxBody *const *bodies = callContext->m_islandBodiesStart; dReal *invI = localContext->m_invI; dJointWithInfo1 *jointInfos = localContext->m_jointinfos; dReal *J = localContext->m_J; dReal *pairsRhsLambda = localContext->m_pairsRhsCfm; const unsigned int *mIndex = localContext->m_mindex; atomicord32 *bodyStartJoints = localContext->m_bodyStartJoints; atomicord32 *bodyJointLinks = localContext->m_bodyJointLinks; const unsigned int nb = callContext->m_islandBodiesCount; unsigned bi; while ((bi = ThrsafeIncrementIntUpToLimit(&stage4CallContext->m_bi_constrForce, nb)) != nb) { dVector3 angularForceAccumulator; dxBody *b = bodies[bi]; const dReal *invIrow = invI + (sizeint)bi * dM3E__MAX; dReal body_invMass_mul_stepSize = stepSize * b->invMass; dReal bodyConstrForce[CFE__MAX]; bool constrForceAvailable = false; unsigned linkIndex = bodyStartJoints != NULL ? bodyStartJoints[bi] : 0; if (linkIndex != 0) { dSetZero(bodyConstrForce, dARRAY_SIZE(bodyConstrForce)); } // compute the constraint force as constrForce = J'*lambda for (; linkIndex != 0; constrForceAvailable = true, linkIndex = bodyJointLinks[linkIndex - 1]) { unsigned jointIndex = (linkIndex - 1) / dJCB__MAX; unsigned jointBodyIndex = (linkIndex - 1) % dJCB__MAX; const dJointWithInfo1 *currJointInfo = jointInfos + jointIndex; unsigned ofsi = mIndex[jointIndex]; dIASSERT(dIN_RANGE(jointIndex, 0, localContext->m_nj)); const dReal *JRow = J + (sizeint)ofsi * (2 * JME__MAX); const dReal *rowRhsLambda = pairsRhsLambda + (sizeint)ofsi * RLE__RHS_LAMBDA_MAX; dxJoint *joint = currJointInfo->joint; const unsigned int infom = currJointInfo->info.m; // unsigned jRowExtraOffset = jointBodyIndex * infom * JME__MAX; unsigned jRowExtraOffset = jointBodyIndex != dJCB__MIN ? infom * JME__MAX : 0; dSASSERT(dJCB__MAX == 2); dJointFeedback *fb = joint->feedback; MultiplyAddJxLambdaToCForce(bodyConstrForce, JRow + jRowExtraOffset, rowRhsLambda, infom, fb, jointBodyIndex); } // compute the velocity update if (constrForceAvailable) { // add fe to cforce and multiply cforce by stepSize for (unsigned int j = dSA__MIN; j != dSA__MAX; ++j) { b->lvel[dV3E__AXES_MIN + j] += (bodyConstrForce[CFE__L_MIN + j] + b->facc[dV3E__AXES_MIN + j]) * body_invMass_mul_stepSize; } for (unsigned int k = dSA__MIN; k != dSA__MAX; ++k) { angularForceAccumulator[dV3E__AXES_MIN + k] = (bodyConstrForce[CFE__A_MIN + k] + b->tacc[dV3E__AXES_MIN + k]) * stepSize; } } else { // add fe to cforce and multiply cforce by stepSize dAddVectorScaledVector3(b->lvel, b->lvel, b->facc, body_invMass_mul_stepSize); dCopyScaledVector3(angularForceAccumulator, b->tacc, stepSize); } dMultiplyAdd0_331 (b->avel, invIrow, angularForceAccumulator + dV3E__AXES_MIN); // update the position and orientation from the new linear/angular velocity // (over the given time step) dxStepBody (b, stepSize); // zero all force accumulators dZeroVector3(b->facc); dZeroVector3(b->tacc); } } //**************************************************************************** /*extern */ sizeint dxEstimateStepMemoryRequirements (dxBody * const *body, unsigned int nb, dxJoint * const *_joint, unsigned int _nj) { (void)body; // unused unsigned int nj, m; { unsigned int njcurr = 0, mcurr = 0; dxJoint::SureMaxInfo info; dxJoint *const *const _jend = _joint + _nj; for (dxJoint *const *_jcurr = _joint; _jcurr != _jend; ++_jcurr) { dxJoint *j = *_jcurr; j->getSureMaxInfo (&info); unsigned int jm = info.max_m; if (jm > 0) { njcurr++; mcurr += jm; } } nj = njcurr; m = mcurr; } sizeint res = 0; res += dOVERALIGNED_SIZE(sizeof(dReal) * dM3E__MAX * nb, INVI_ALIGNMENT); // for invI { sizeint sub1_res1 = dEFFICIENT_SIZE(sizeof(dJointWithInfo1) * 2 * _nj); // for initial jointinfos // The array can't grow right more than by nj sizeint sub1_res2 = dEFFICIENT_SIZE(sizeof(dJointWithInfo1) * ((sizeint)_nj + (sizeint)nj)); // for shrunk jointinfos sub1_res2 += dEFFICIENT_SIZE(sizeof(dxStepperLocalContext)); //for dxStepperLocalContext if (m > 0) { sub1_res2 += dEFFICIENT_SIZE(sizeof(unsigned int) * (nj + 1)); // for mindex sub1_res2 += dEFFICIENT_SIZE(sizeof(int) * m); // for findex sub1_res2 += dEFFICIENT_SIZE(sizeof(dReal) * 2 * JME__MAX * m); // for J unsigned int mskip = dPAD(m); sub1_res2 += dOVERALIGNED_SIZE(sizeof(dReal) * mskip * m, AMATRIX_ALIGNMENT); // for A sub1_res2 += dEFFICIENT_SIZE(sizeof(dReal) * RCE__RHS_CFM_MAX * m); // for pairsRhsCfm sub1_res2 += dEFFICIENT_SIZE(sizeof(dReal) * LHE__LO_HI_MAX * m); // for pairsLoHi sub1_res2 += dEFFICIENT_SIZE(sizeof(atomicord32) * nb); // for bodyStartJoints sub1_res2 += dEFFICIENT_SIZE(sizeof(atomicord32)* dJCB__MAX * nj); // for bodyJointLinks } { sizeint sub2_res1 = dEFFICIENT_SIZE(sizeof(dxStepperStage3CallContext)); // for dxStepperStage3CallContext sizeint sub2_res2 = 0; sizeint sub2_res3 = dEFFICIENT_SIZE(sizeof(dxStepperStage4CallContext)); // for dxStepperStage4CallContext if (m > 0) { sub2_res1 += dOVERALIGNED_SIZE(sizeof(dReal) * 2 * JIM__MAX * m, JINVM_ALIGNMENT); // for JinvM sub2_res1 += dEFFICIENT_SIZE(sizeof(dReal) * dDA__MAX * nb); // for rhs_tmp sub2_res1 += dEFFICIENT_SIZE(sizeof(dxStepperStage2CallContext)); // for dxStepperStage2CallContext sub2_res2 += dxEstimateSolveLCPMemoryReq(m, false); } sub1_res2 += dMAX(sub2_res1, dMAX(sub2_res2, sub2_res3)); } sizeint sub1_res12_max = dMAX(sub1_res1, sub1_res2); sizeint stage01_contexts = dEFFICIENT_SIZE(sizeof(dxStepperStage0BodiesCallContext)) + dEFFICIENT_SIZE(sizeof(dxStepperStage0JointsCallContext)) + dEFFICIENT_SIZE(sizeof(dxStepperStage1CallContext)); res += dMAX(sub1_res12_max, stage01_contexts); } return res; } /*extern */ unsigned dxEstimateStepMaxCallCount( unsigned /*activeThreadCount*/, unsigned allowedThreadCount) { unsigned result = 1 // dxStepIsland itself + (2 * allowedThreadCount + 2) // (dxStepIsland_Stage2a + dxStepIsland_Stage2b) * allowedThreadCount + 2 * dxStepIsland_Stage2?_Sync + 1; // dxStepIsland_Stage3 return result; } ode-0.16/ode/demo/0000775000175200017520000000000013403273061010710 500000000000000ode-0.16/ode/demo/world_geom3.h0000664000175200017520000003555613403272463013245 00000000000000// mesh for a world model, to be used with test_cyl.cpp static float world_vertices[] = {10.000000f,-10.000000f,1.000000f,-10.000000f,-10.000000f,1.000000f,-10.000000f,-10.000000f,-1.000000f,-10.000000f,-10.000000f,-1.000000f,10.000000f,-10.000000f,-1.000000f,10.000000f,-10.000000f,1.000000f,10.000000f,10.000000f,1.000000f,10.000000f,-10.000000f,1.000000f,10.000000f,-10.000000f,-1.000000f,10.000000f,-10.000000f,-1.000000f,10.000000f,10.000000f,-1.000000f,10.000000f,10.000000f,1.000000f,10.000000f,10.000000f,-1.000000f,10.000000f,-10.000000f,-1.000000f,-10.000000f,-10.000000f,-1.000000f,-10.000000f,-10.000000f,-1.000000f,-10.000000f,10.000000f,-1.000000f,10.000000f,10.000000f,-1.000000f,0.000000f,9.000000f,-0.000000f,0.000000f,-9.000000f,0.000000f,9.000000f,-9.000000f,0.000000f,0.000000f,9.000000f,-0.000000f,9.000000f,-9.000000f,0.000000f,9.000000f,9.000000f,-0.000000f,10.000000f,10.000000f,-1.000000f,-10.000000f,10.000000f,-1.000000f,-10.000000f,10.000000f,1.000000f,10.000000f,10.000000f,-1.000000f,-10.000000f,10.000000f,1.000000f,10.000000f,10.000000f,1.000000f,-10.000000f,-10.000000f,-1.000000f,-10.000000f,-10.000000f,1.000000f,-10.000000f,10.000000f,1.000000f,-10.000000f,10.000000f,1.000000f,-10.000000f,10.000000f,-1.000000f,-10.000000f,-10.000000f,-1.000000f,9.000000f,-9.000000f,1.000000f,-9.000000f,-9.000000f,1.000000f,10.000000f,-10.000000f,1.000000f,-9.000000f,-9.000000f,1.000000f,-10.000000f,-10.000000f,1.000000f,10.000000f,-10.000000f,1.000000f,9.000000f,9.000000f,1.000000f,9.000000f,-9.000000f,1.000000f,10.000000f,-10.000000f,1.000000f,10.000000f,-10.000000f,1.000000f,10.000000f,10.000000f,1.000000f,9.000000f,9.000000f,1.000000f,-9.000000f,9.000000f,1.000000f,9.000000f,9.000000f,1.000000f,10.000000f,10.000000f,1.000000f,10.000000f,10.000000f,1.000000f,-10.000000f,10.000000f,1.000000f,-9.000000f,9.000000f,1.000000f,-9.000000f,9.000000f,1.000000f,-10.000000f,10.000000f,1.000000f,-9.000000f,-9.000000f,1.000000f,-10.000000f,10.000000f,1.000000f,-10.000000f,-10.000000f,1.000000f,-9.000000f,-9.000000f,1.000000f,0.000000f,-9.000000f,0.000000f,-9.000000f,-9.000000f,0.000000f,-9.000000f,-9.000000f,1.000000f,0.000000f,-9.000000f,0.000000f,-9.000000f,-9.000000f,1.000000f,9.000000f,-9.000000f,1.000000f,0.000000f,-9.000000f,0.000000f,9.000000f,-9.000000f,1.000000f,9.000000f,-9.000000f,0.000000f,9.000000f,-9.000000f,0.000000f,9.000000f,-9.000000f,1.000000f,9.000000f,9.000000f,1.000000f,9.000000f,9.000000f,1.000000f,9.000000f,9.000000f,-0.000000f,9.000000f,-9.000000f,0.000000f,0.000000f,9.000000f,-0.000000f,9.000000f,9.000000f,-0.000000f,9.000000f,9.000000f,1.000000f,0.000000f,9.000000f,-0.000000f,9.000000f,9.000000f,1.000000f,-9.000000f,9.000000f,1.000000f,0.000000f,9.000000f,-0.000000f,-9.000000f,9.000000f,1.000000f,-9.000000f,9.000000f,-0.000000f,-9.000000f,9.000000f,1.000000f,-9.000000f,-9.000000f,1.000000f,-9.000000f,-9.000000f,0.000000f,-9.000000f,-9.000000f,0.000000f,-9.000000f,9.000000f,-0.000000f,-9.000000f,9.000000f,1.000000f,-2.997000f,-1.748874f,0.000000f,-2.997000f,-2.001000f,0.000000f,0.000000f,-9.000000f,0.000000f,-2.997000f,-1.748874f,0.000000f,0.000000f,-9.000000f,0.000000f,-2.997000f,1.748874f,-0.000000f,-2.997000f,-2.001000f,0.000000f,-2.997000f,-6.003000f,0.002697f,0.000000f,-9.000000f,0.000000f,0.000000f,9.000000f,-0.000000f,-2.997000f,2.001000f,-0.000000f,-2.997000f,1.748874f,-0.000000f,0.000000f,9.000000f,-0.000000f,-2.997000f,1.748874f,-0.000000f,0.000000f,-9.000000f,0.000000f,-2.997000f,2.001000f,-0.000000f,0.000000f,9.000000f,-0.000000f,-2.997000f,6.003000f,0.002697f,-6.003000f,6.003000f,0.002697f,-2.997000f,6.003000f,0.002697f,0.000000f,9.000000f,-0.000000f,0.000000f,9.000000f,-0.000000f,-9.000000f,9.000000f,-0.000000f,-6.003000f,6.003000f,0.002697f,-6.003000f,1.748874f,-0.000000f,-9.000000f,-9.000000f,0.000000f,-6.003000f,-1.748874f,0.000000f,-6.003000f,2.001000f,-0.000000f,-6.003000f,6.003000f,0.002697f,-9.000000f,9.000000f,-0.000000f,-9.000000f,9.000000f,-0.000000f,-6.003000f,1.748874f,-0.000000f,-6.003000f,2.001000f,-0.000000f,-9.000000f,9.000000f,-0.000000f,-9.000000f,-9.000000f,0.000000f,-6.003000f,1.748874f,-0.000000f,-9.000000f,-9.000000f,0.000000f,-6.003000f,-6.003000f,0.002697f,-6.003000f,-2.001000f,0.000000f,-9.000000f,-9.000000f,0.000000f,-6.003000f,-2.001000f,0.000000f,-6.003000f,-1.748874f,0.000000f,-6.003000f,-6.003000f,0.002697f,-9.000000f,-9.000000f,0.000000f,0.000000f,-9.000000f,0.000000f,-6.003000f,-6.003000f,0.002697f,0.000000f,-9.000000f,0.000000f,-2.997000f,-6.003000f,0.002697f,-2.997000f,1.748874f,1.237951f,-2.997000f,1.748874f,-0.000000f,-2.997000f,2.001000f,-0.000000f,-2.997000f,1.748874f,1.237951f,-2.997000f,2.001000f,-0.000000f,-2.997000f,2.001000f,1.515748f,-6.003000f,-2.001000f,1.515748f,-6.003000f,-6.003000f,0.002697f,-2.997000f,-6.003000f,0.002697f,-6.003000f,-2.001000f,1.515748f,-2.997000f,-6.003000f,0.002697f,-2.997000f,-2.001000f,1.515748f,-2.997000f,2.001000f,1.515748f,-2.997000f,6.003000f,0.002697f,-6.003000f,6.003000f,0.002697f,-6.003000f,6.003000f,0.002697f,-6.003000f,2.001000f,1.515748f,-2.997000f,2.001000f,1.515748f,-6.003000f,-2.001000f,0.000000f,-6.003000f,-6.003000f,0.002697f,-6.003000f,-2.001000f,1.515748f,-6.003000f,2.001000f,1.515748f,-6.003000f,6.003000f,0.002697f,-6.003000f,2.001000f,-0.000000f,-2.997000f,-2.001000f,1.515748f,-2.997000f,-6.003000f,0.002697f,-2.997000f,-2.001000f,0.000000f,-2.997000f,2.001000f,-0.000000f,-2.997000f,6.003000f,0.002697f,-2.997000f,2.001000f,1.515748f,-2.997000f,-2.001000f,1.515748f,-2.997000f,2.001000f,1.515748f,-6.003000f,2.001000f,1.515748f,-6.003000f,2.001000f,1.515748f,-6.003000f,-2.001000f,1.515748f,-2.997000f,-2.001000f,1.515748f,-2.997000f,-1.748874f,1.237951f,-2.997000f,1.748874f,1.237951f,-2.997000f,2.001000f,1.515748f,-2.997000f,-1.748874f,1.237951f,-2.997000f,2.001000f,1.515748f,-2.997000f,-2.001000f,1.515748f,-6.003000f,-1.748874f,1.237951f,-6.003000f,-1.748874f,0.000000f,-6.003000f,-2.001000f,0.000000f,-6.003000f,-1.748874f,1.237951f,-6.003000f,-2.001000f,0.000000f,-6.003000f,-2.001000f,1.515748f,-2.997000f,-2.001000f,1.515748f,-2.997000f,-2.001000f,0.000000f,-2.997000f,-1.748874f,1.237951f,-2.997000f,-2.001000f,0.000000f,-2.997000f,-1.748874f,0.000000f,-2.997000f,-1.748874f,1.237951f,-6.003000f,1.748874f,1.237951f,-6.003000f,2.001000f,1.515748f,-6.003000f,2.001000f,-0.000000f,-6.003000f,1.748874f,1.237951f,-6.003000f,2.001000f,-0.000000f,-6.003000f,1.748874f,-0.000000f,-6.003000f,1.748874f,1.237951f,-6.003000f,-1.748874f,1.237951f,-6.003000f,-2.001000f,1.515748f,-6.003000f,1.748874f,1.237951f,-6.003000f,-2.001000f,1.515748f,-6.003000f,2.001000f,1.515748f,-6.003000f,1.748874f,1.237951f,-6.003000f,1.748874f,-0.000000f,-2.997000f,1.748874f,1.237951f,-6.003000f,1.748874f,-0.000000f,-2.997000f,1.748874f,-0.000000f,-2.997000f,1.748874f,1.237951f,-6.003000f,1.748874f,-0.000000f,-6.003000f,-1.748874f,0.000000f,-2.997000f,-1.748874f,0.000000f,-6.003000f,1.748874f,-0.000000f,-2.997000f,-1.748874f,0.000000f,-2.997000f,1.748874f,-0.000000f,-6.003000f,-1.748874f,0.000000f,-6.003000f,-1.748874f,1.237951f,-2.997000f,-1.748874f,1.237951f,-2.997000f,-1.748874f,1.237951f,-2.997000f,-1.748874f,0.000000f,-6.003000f,-1.748874f,0.000000f,-6.003000f,-1.748874f,1.237951f,-6.003000f,1.748874f,1.237951f,-2.997000f,-1.748874f,1.237951f,-6.003000f,1.748874f,1.237951f,-2.997000f,1.748874f,1.237951f,-2.997000f,-1.748874f,1.237951f}; static float world_normals[] = {0.000000f,-1.000000f,0.000000f,-0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,-0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000225f,0.000161f,1.000000f,0.000225f,-0.000161f,1.000000f,0.000000f,0.000000f,1.000000f,0.000225f,0.000161f,1.000000f,0.000000f,0.000000f,1.000000f,-0.000000f,0.000000f,1.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,-0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,-0.000000f,-1.000000f,0.000000f,0.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,-0.000000f,-1.000000f,0.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,-0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,-0.000000f,0.000000f,1.000000f,0.000787f,0.000337f,1.000000f,0.000225f,-0.000161f,1.000000f,-0.000000f,0.000000f,1.000000f,0.000225f,-0.000161f,1.000000f,0.000000f,0.000000f,1.000000f,0.000787f,0.000337f,1.000000f,0.000400f,-0.179805f,0.983702f,0.000225f,-0.000161f,1.000000f,0.000225f,0.000161f,1.000000f,0.000787f,-0.000337f,1.000000f,0.000000f,0.000000f,1.000000f,0.000225f,0.000161f,1.000000f,0.000000f,0.000000f,1.000000f,0.000225f,-0.000161f,1.000000f,0.000787f,-0.000337f,1.000000f,0.000225f,0.000161f,1.000000f,0.000532f,0.119686f,0.992812f,-0.000320f,0.143927f,0.989588f,0.000532f,0.119686f,0.992812f,0.000225f,0.000161f,1.000000f,0.000225f,0.000161f,1.000000f,-0.000393f,0.000056f,1.000000f,-0.000320f,0.143927f,0.989588f,-0.000000f,0.000000f,1.000000f,-0.000315f,-0.000045f,1.000000f,0.000000f,0.000000f,1.000000f,-0.000787f,-0.000337f,1.000000f,-0.000320f,0.143927f,0.989588f,-0.000393f,0.000056f,1.000000f,-0.000393f,0.000056f,1.000000f,-0.000000f,0.000000f,1.000000f,-0.000787f,-0.000337f,1.000000f,-0.000393f,0.000056f,1.000000f,-0.000315f,-0.000045f,1.000000f,-0.000000f,0.000000f,1.000000f,-0.000315f,-0.000045f,1.000000f,-0.000398f,-0.089784f,0.995961f,-0.000787f,0.000337f,1.000000f,-0.000315f,-0.000045f,1.000000f,-0.000787f,0.000337f,1.000000f,0.000000f,0.000000f,1.000000f,-0.000398f,-0.089784f,0.995961f,-0.000315f,-0.000045f,1.000000f,0.000225f,-0.000161f,1.000000f,-0.000398f,-0.089784f,0.995961f,0.000225f,-0.000161f,1.000000f,0.000400f,-0.179805f,0.983702f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,0.000000f,-0.239222f,0.970965f,-0.000398f,-0.089784f,0.995961f,0.000400f,-0.179805f,0.983702f,0.000000f,-0.239222f,0.970965f,0.000400f,-0.179805f,0.983702f,0.000000f,-0.119611f,0.992821f,0.000000f,0.239222f,0.970965f,0.000532f,0.119686f,0.992812f,-0.000320f,0.143927f,0.989588f,-0.000320f,0.143927f,0.989588f,0.000000f,0.119611f,0.992821f,0.000000f,0.239222f,0.970965f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,0.000000f,-0.119611f,0.992821f,0.000000f,0.239222f,0.970965f,0.000000f,0.119611f,0.992821f,0.000000f,0.119611f,0.992821f,0.000000f,-0.239222f,0.970965f,0.000000f,-0.119611f,0.992821f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,-0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,-0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,-0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,-0.000000f,0.000000f,1.000000f,-0.000000f,0.000000f,1.000000f,-0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f}; static dTriIndex world_indices[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227}; ode-0.16/ode/demo/demo_cyl.cpp0000664000175200017520000002113313403272463013134 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ // Test for non-capped cylinder, by Bram Stolk #include #include #ifdef HAVE_UNISTD_H #include #endif #include #include #include "texturepath.h" #include "world_geom3.h" // this is our world mesh #ifdef _MSC_VER #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints #endif #define BOX #define CYL // some constants #define RADIUS 0.22 // wheel radius #define WMASS 0.2 // wheel mass #define WHEELW 0.2 // wheel width #define BOXSZ 0.4 // box size //#define CYL_GEOM_OFFSET // rotate cylinder using geom offset // dynamics and collision objects (chassis, 3 wheels, environment) static dWorldID world; static dSpaceID space; #ifdef BOX static dBodyID boxbody; static dGeomID boxgeom; #endif #ifdef CYL static dBodyID cylbody; static dGeomID cylgeom; #endif static dJointGroupID contactgroup; static dGeomID world_mesh; // this is called by dSpaceCollide when two objects in space are // potentially colliding. static void nearCallback (void *data, dGeomID o1, dGeomID o2) { assert(o1); assert(o2); if (dGeomIsSpace(o1) || dGeomIsSpace(o2)) { fprintf(stderr,"testing space %p %p\n", (void*)o1, (void*)o2); // colliding a space with something dSpaceCollide2(o1,o2,data,&nearCallback); // Note we do not want to test intersections within a space, // only between spaces. return; } // fprintf(stderr,"testing geoms %p %p\n", o1, o2); const int N = 32; dContact contact[N]; int n = dCollide (o1,o2,N,&(contact[0].geom),sizeof(dContact)); if (n > 0) { for (int i=0; i #include #include "texturepath.h" #ifdef _MSC_VER #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints #endif // select correct drawing functions #ifdef dDOUBLE #define dsDrawSphere dsDrawSphereD #define dsDrawBox dsDrawBoxD #define dsDrawLine dsDrawLineD #define dsDrawCapsule dsDrawCapsuleD #define dsDrawCylinder dsDrawCylinderD #endif //**************************************************************************** // test infrastructure, including constants and macros #define TEST_REPS1 1000 // run each test this many times (first batch) #define TEST_REPS2 10000 // run each test this many times (second batch) const dReal tol = 1e-8; // tolerance used for numerical checks #define MAX_TESTS 1000 // maximum number of test slots #define Z_OFFSET 2 // z offset for drawing (to get above ground) //using namespace ode; // test function. returns 1 if the test passed or 0 if it failed typedef int test_function_t(); struct TestSlot { int number; // number of test const char *name; // name of test int failcount; test_function_t *test_fn; int last_failed_line; }; TestSlot testslot[MAX_TESTS]; // globals used by the test functions int graphical_test=0; // show graphical results of this test, 0=none int current_test; // currently execiting test int draw_all_objects_called; #define MAKE_TEST(number,function) \ if (testslot[number].name) dDebug (0,"test number already used"); \ if (number <= 0 || number >= MAX_TESTS) dDebug (0,"bad test number"); \ testslot[number].name = # function; \ testslot[number].test_fn = function; #define FAILED() { if (graphical_test==0) { \ testslot[current_test].last_failed_line=__LINE__; return 0; } } #define PASSED() { return 1; } //**************************************************************************** // globals /* int dBoxBox (const dVector3 p1, const dMatrix3 R1, const dVector3 side1, const dVector3 p2, const dMatrix3 R2, const dVector3 side2, dVector3 normal, dReal *depth, int *code, int maxc, dContactGeom *contact, int skip); */ void dLineClosestApproach (const dVector3 pa, const dVector3 ua, const dVector3 pb, const dVector3 ub, dReal *alpha, dReal *beta); //**************************************************************************** // draw all objects in a space, and draw all the collision contact points void nearCallback (void *, dGeomID o1, dGeomID o2) { int i,j,n; const int N = 100; dContactGeom contact[N]; if (dGeomGetClass (o2) == dRayClass) { n = dCollide (o2,o1,N,&contact[0],sizeof(dContactGeom)); } else { n = dCollide (o1,o2,N,&contact[0],sizeof(dContactGeom)); } if (n > 0) { dMatrix3 RI; dRSetIdentity (RI); const dReal ss[3] = {0.01,0.01,0.01}; for (i=0; i tol) FAILED(); // ********** test point on surface has depth 0 for (j=0; j<3; j++) q[j] = dRandReal()-0.5; dNormalize3 (q); for (j=0; j<3; j++) q[j] = q[j]*r + p[j]; if (dFabs(dGeomSpherePointDepth (sphere,q[0],q[1],q[2])) > tol) FAILED(); // ********** test point at random depth d = (dRandReal()*2-1) * r; for (j=0; j<3; j++) q[j] = dRandReal()-0.5; dNormalize3 (q); for (j=0; j<3; j++) q[j] = q[j]*(r-d) + p[j]; if (dFabs(dGeomSpherePointDepth (sphere,q[0],q[1],q[2])-d) > tol) FAILED(); PASSED(); } int test_box_point_depth() { int i,j; dVector3 s,p,q,q2; // s = box sides dMatrix3 R; dReal ss,d; // ss = smallest side dSimpleSpace space(0); dGeomID box = dCreateBox (0,1,1,1); dSpaceAdd (space,box); // ********** make a random box for (j=0; j<3; j++) s[j] = dRandReal() + 0.1; dGeomBoxSetLengths (box,s[0],s[1],s[2]); dMakeRandomVector (p,3,1.0); dGeomSetPosition (box,p[0],p[1],p[2]); dRFromAxisAndAngle (R,dRandReal()*2-1,dRandReal()*2-1, dRandReal()*2-1,dRandReal()*10-5); dGeomSetRotation (box,R); // ********** test center point has depth of smallest side ss = 1e9; for (j=0; j<3; j++) if (s[j] < ss) ss = s[j]; if (dFabs(dGeomBoxPointDepth (box,p[0],p[1],p[2]) - 0.5*ss) > tol) FAILED(); // ********** test point on surface has depth 0 for (j=0; j<3; j++) q[j] = (dRandReal()-0.5)*s[j]; i = dRandInt (3); if (dRandReal() > 0.5) q[i] = 0.5*s[i]; else q[i] = -0.5*s[i]; dMultiply0 (q2,dGeomGetRotation(box),q,3,3,1); for (j=0; j<3; j++) q2[j] += p[j]; if (dFabs(dGeomBoxPointDepth (box,q2[0],q2[1],q2[2])) > tol) FAILED(); // ********** test points outside box have -ve depth for (j=0; j<3; j++) { q[j] = 0.5*s[j] + dRandReal() + 0.01; if (dRandReal() > 0.5) q[j] = -q[j]; } dMultiply0 (q2,dGeomGetRotation(box),q,3,3,1); for (j=0; j<3; j++) q2[j] += p[j]; if (dGeomBoxPointDepth (box,q2[0],q2[1],q2[2]) >= 0) FAILED(); // ********** test points inside box have +ve depth for (j=0; j<3; j++) q[j] = s[j] * 0.99 * (dRandReal()-0.5); dMultiply0 (q2,dGeomGetRotation(box),q,3,3,1); for (j=0; j<3; j++) q2[j] += p[j]; if (dGeomBoxPointDepth (box,q2[0],q2[1],q2[2]) <= 0) FAILED(); // ********** test random depth of point aligned along axis (up to ss deep) i = dRandInt (3); for (j=0; j<3; j++) q[j] = 0; d = (dRandReal()*(ss*0.5+1)-1); q[i] = s[i]*0.5 - d; if (dRandReal() > 0.5) q[i] = -q[i]; dMultiply0 (q2,dGeomGetRotation(box),q,3,3,1); for (j=0; j<3; j++) q2[j] += p[j]; if (dFabs(dGeomBoxPointDepth (box,q2[0],q2[1],q2[2]) - d) >= tol) FAILED(); PASSED(); } int test_ccylinder_point_depth() { int j; dVector3 p,a; dMatrix3 R; dReal r,l,beta,x,y,d; dSimpleSpace space(0); dGeomID ccyl = dCreateCapsule (0,1,1); dSpaceAdd (space,ccyl); // ********** make a random ccyl r = dRandReal()*0.5 + 0.01; l = dRandReal()*1 + 0.01; dGeomCapsuleSetParams (ccyl,r,l); dMakeRandomVector (p,3,1.0); dGeomSetPosition (ccyl,p[0],p[1],p[2]); dRFromAxisAndAngle (R,dRandReal()*2-1,dRandReal()*2-1, dRandReal()*2-1,dRandReal()*10-5); dGeomSetRotation (ccyl,R); // ********** test point on axis has depth of 'radius' beta = dRandReal()-0.5; for (j=0; j<3; j++) a[j] = p[j] + l*beta*R[j*4+2]; if (dFabs(dGeomCapsulePointDepth (ccyl,a[0],a[1],a[2]) - r) >= tol) FAILED(); // ********** test point on surface (excluding caps) has depth 0 beta = dRandReal()*2*M_PI; x = r*sin(beta); y = r*cos(beta); beta = dRandReal()-0.5; for (j=0; j<3; j++) a[j] = p[j] + x*R[j*4+0] + y*R[j*4+1] + l*beta*R[j*4+2]; if (dFabs(dGeomCapsulePointDepth (ccyl,a[0],a[1],a[2])) >= tol) FAILED(); // ********** test point on surface of caps has depth 0 for (j=0; j<3; j++) a[j] = dRandReal()-0.5; dNormalize3 (a); if (dCalcVectorDot3_14(a,R+2) > 0) { for (j=0; j<3; j++) a[j] = p[j] + a[j]*r + l*0.5*R[j*4+2]; } else { for (j=0; j<3; j++) a[j] = p[j] + a[j]*r - l*0.5*R[j*4+2]; } if (dFabs(dGeomCapsulePointDepth (ccyl,a[0],a[1],a[2])) >= tol) FAILED(); // ********** test point inside ccyl has positive depth for (j=0; j<3; j++) a[j] = dRandReal()-0.5; dNormalize3 (a); beta = dRandReal()-0.5; for (j=0; j<3; j++) a[j] = p[j] + a[j]*r*0.99 + l*beta*R[j*4+2]; if (dGeomCapsulePointDepth (ccyl,a[0],a[1],a[2]) < 0) FAILED(); // ********** test point depth (1) d = (dRandReal()*2-1) * r; beta = dRandReal()*2*M_PI; x = (r-d)*sin(beta); y = (r-d)*cos(beta); beta = dRandReal()-0.5; for (j=0; j<3; j++) a[j] = p[j] + x*R[j*4+0] + y*R[j*4+1] + l*beta*R[j*4+2]; if (dFabs(dGeomCapsulePointDepth (ccyl,a[0],a[1],a[2]) - d) >= tol) FAILED(); // ********** test point depth (2) d = (dRandReal()*2-1) * r; for (j=0; j<3; j++) a[j] = dRandReal()-0.5; dNormalize3 (a); if (dCalcVectorDot3_14(a,R+2) > 0) { for (j=0; j<3; j++) a[j] = p[j] + a[j]*(r-d) + l*0.5*R[j*4+2]; } else { for (j=0; j<3; j++) a[j] = p[j] + a[j]*(r-d) - l*0.5*R[j*4+2]; } if (dFabs(dGeomCapsulePointDepth (ccyl,a[0],a[1],a[2]) - d) >= tol) FAILED(); PASSED(); } int test_plane_point_depth() { int j; dVector3 n,p,q,a,b; // n = plane normal dReal d; dSimpleSpace space(0); dGeomID plane = dCreatePlane (0,0,0,1,0); dSpaceAdd (space,plane); // ********** make a random plane for (j=0; j<3; j++) n[j] = dRandReal() - 0.5; dNormalize3 (n); d = dRandReal() - 0.5; dGeomPlaneSetParams (plane,n[0],n[1],n[2],d); dPlaneSpace (n,p,q); // ********** test point on plane has depth 0 a[0] = dRandReal() - 0.5; a[1] = dRandReal() - 0.5; a[2] = 0; for (j=0; j<3; j++) b[j] = a[0]*p[j] + a[1]*q[j] + (a[2]+d)*n[j]; if (dFabs(dGeomPlanePointDepth (plane,b[0],b[1],b[2])) >= tol) FAILED(); // ********** test arbitrary depth point a[0] = dRandReal() - 0.5; a[1] = dRandReal() - 0.5; a[2] = dRandReal() - 0.5; for (j=0; j<3; j++) b[j] = a[0]*p[j] + a[1]*q[j] + (a[2]+d)*n[j]; if (dFabs(dGeomPlanePointDepth (plane,b[0],b[1],b[2]) + a[2]) >= tol) FAILED(); // ********** test depth-1 point a[0] = dRandReal() - 0.5; a[1] = dRandReal() - 0.5; a[2] = -1; for (j=0; j<3; j++) b[j] = a[0]*p[j] + a[1]*q[j] + (a[2]+d)*n[j]; if (dFabs(dGeomPlanePointDepth (plane,b[0],b[1],b[2]) - 1) >= tol) FAILED(); PASSED(); } //**************************************************************************** // ray tests int test_ray_and_sphere() { int j; dContactGeom contact; dVector3 p,q,q2,n,v1; dMatrix3 R; dReal r,k; dSimpleSpace space(0); dGeomID ray = dCreateRay (0,0); dGeomID sphere = dCreateSphere (0,1); dSpaceAdd (space,ray); dSpaceAdd (space,sphere); // ********** make a random sphere of radius r at position p r = dRandReal()+0.1; dGeomSphereSetRadius (sphere,r); dMakeRandomVector (p,3,1.0); dGeomSetPosition (sphere,p[0],p[1],p[2]); dRFromAxisAndAngle (R,dRandReal()*2-1,dRandReal()*2-1, dRandReal()*2-1,dRandReal()*10-5); dGeomSetRotation (sphere,R); // ********** test zero length ray just inside sphere dGeomRaySetLength (ray,0); dMakeRandomVector (q,3,1.0); dNormalize3 (q); for (j=0; j<3; j++) q[j] = 0.99*r * q[j] + p[j]; dGeomSetPosition (ray,q[0],q[1],q[2]); dRFromAxisAndAngle (R,dRandReal()*2-1,dRandReal()*2-1, dRandReal()*2-1,dRandReal()*10-5); dGeomSetRotation (ray,R); if (dCollide (ray,sphere,1,&contact,sizeof(dContactGeom)) != 0) FAILED(); // ********** test zero length ray just outside that sphere dGeomRaySetLength (ray,0); dMakeRandomVector (q,3,1.0); dNormalize3 (q); for (j=0; j<3; j++) q[j] = 1.01*r * q[j] + p[j]; dGeomSetPosition (ray,q[0],q[1],q[2]); dRFromAxisAndAngle (R,dRandReal()*2-1,dRandReal()*2-1, dRandReal()*2-1,dRandReal()*10-5); dGeomSetRotation (ray,R); if (dCollide (ray,sphere,1,&contact,sizeof(dContactGeom)) != 0) FAILED(); // ********** test finite length ray totally contained inside the sphere dMakeRandomVector (q,3,1.0); dNormalize3 (q); k = dRandReal(); for (j=0; j<3; j++) q[j] = k*r*0.99 * q[j] + p[j]; dMakeRandomVector (q2,3,1.0); dNormalize3 (q2); k = dRandReal(); for (j=0; j<3; j++) q2[j] = k*r*0.99 * q2[j] + p[j]; for (j=0; j<3; j++) n[j] = q2[j] - q[j]; dNormalize3 (n); dGeomRaySet (ray,q[0],q[1],q[2],n[0],n[1],n[2]); dGeomRaySetLength (ray,dCalcPointsDistance3(q,q2)); if (dCollide (ray,sphere,1,&contact,sizeof(dContactGeom)) != 0) FAILED(); // ********** test finite length ray totally outside the sphere dMakeRandomVector (q,3,1.0); dNormalize3 (q); do { dMakeRandomVector (n,3,1.0); dNormalize3 (n); } while (dCalcVectorDot3(n,q) < 0); // make sure normal goes away from sphere for (j=0; j<3; j++) q[j] = 1.01*r * q[j] + p[j]; dGeomRaySet (ray,q[0],q[1],q[2],n[0],n[1],n[2]); dGeomRaySetLength (ray,100); if (dCollide (ray,sphere,1,&contact,sizeof(dContactGeom)) != 0) FAILED(); // ********** test ray from outside to just above surface dMakeRandomVector (q,3,1.0); dNormalize3 (q); for (j=0; j<3; j++) n[j] = -q[j]; for (j=0; j<3; j++) q2[j] = 2*r * q[j] + p[j]; dGeomRaySet (ray,q2[0],q2[1],q2[2],n[0],n[1],n[2]); dGeomRaySetLength (ray,0.99*r); if (dCollide (ray,sphere,1,&contact,sizeof(dContactGeom)) != 0) FAILED(); // ********** test ray from outside to just below surface dGeomRaySetLength (ray,1.01*r); if (dCollide (ray,sphere,1,&contact,sizeof(dContactGeom)) != 1) FAILED(); for (j=0; j<3; j++) q2[j] = r * q[j] + p[j]; if (dCalcPointsDistance3 (contact.pos,q2) > tol) FAILED(); // ********** test contact point distance for random rays dMakeRandomVector (q,3,1.0); dNormalize3 (q); k = dRandReal()+0.5; for (j=0; j<3; j++) q[j] = k*r * q[j] + p[j]; dMakeRandomVector (n,3,1.0); dNormalize3 (n); dGeomRaySet (ray,q[0],q[1],q[2],n[0],n[1],n[2]); dGeomRaySetLength (ray,100); if (dCollide (ray,sphere,1,&contact,sizeof(dContactGeom))) { k = dCalcPointsDistance3 (contact.pos,dGeomGetPosition(sphere)); if (dFabs(k - r) > tol) FAILED(); // also check normal signs if (dCalcVectorDot3 (n,contact.normal) > 0) FAILED(); // also check depth of contact point if (dFabs (dGeomSpherePointDepth (sphere,contact.pos[0],contact.pos[1],contact.pos[2])) > tol) FAILED(); draw_all_objects (space); } // ********** test tangential grazing - miss dMakeRandomVector (q,3,1.0); dNormalize3 (q); dPlaneSpace (q,n,v1); for (j=0; j<3; j++) q[j] = 1.01*r * q[j] + p[j]; for (j=0; j<3; j++) q[j] -= n[j]; dGeomRaySet (ray,q[0],q[1],q[2],n[0],n[1],n[2]); dGeomRaySetLength (ray,2); if (dCollide (ray,sphere,1,&contact,sizeof(dContactGeom)) != 0) FAILED(); // ********** test tangential grazing - hit dMakeRandomVector (q,3,1.0); dNormalize3 (q); dPlaneSpace (q,n,v1); for (j=0; j<3; j++) q[j] = 0.99*r * q[j] + p[j]; for (j=0; j<3; j++) q[j] -= n[j]; dGeomRaySet (ray,q[0],q[1],q[2],n[0],n[1],n[2]); dGeomRaySetLength (ray,2); if (dCollide (ray,sphere,1,&contact,sizeof(dContactGeom)) != 1) FAILED(); PASSED(); } int test_ray_and_box() { int i,j; dContactGeom contact; dVector3 s,p,q,n,q2,q3,q4; // s = box sides dMatrix3 R; dReal k; dSimpleSpace space(0); dGeomID ray = dCreateRay (0,0); dGeomID box = dCreateBox (0,1,1,1); dSpaceAdd (space,ray); dSpaceAdd (space,box); // ********** make a random box for (j=0; j<3; j++) s[j] = dRandReal() + 0.1; dGeomBoxSetLengths (box,s[0],s[1],s[2]); dMakeRandomVector (p,3,1.0); dGeomSetPosition (box,p[0],p[1],p[2]); dRFromAxisAndAngle (R,dRandReal()*2-1,dRandReal()*2-1, dRandReal()*2-1,dRandReal()*10-5); dGeomSetRotation (box,R); // ********** test zero length ray just inside box dGeomRaySetLength (ray,0); for (j=0; j<3; j++) q[j] = (dRandReal()-0.5)*s[j]; i = dRandInt (3); if (dRandReal() > 0.5) q[i] = 0.99*0.5*s[i]; else q[i] = -0.99*0.5*s[i]; dMultiply0 (q2,dGeomGetRotation(box),q,3,3,1); for (j=0; j<3; j++) q2[j] += p[j]; dGeomSetPosition (ray,q2[0],q2[1],q2[2]); dRFromAxisAndAngle (R,dRandReal()*2-1,dRandReal()*2-1, dRandReal()*2-1,dRandReal()*10-5); dGeomSetRotation (ray,R); if (dCollide (ray,box,1,&contact,sizeof(dContactGeom)) != 0) FAILED(); // ********** test zero length ray just outside box dGeomRaySetLength (ray,0); for (j=0; j<3; j++) q[j] = (dRandReal()-0.5)*s[j]; i = dRandInt (3); if (dRandReal() > 0.5) q[i] = 1.01*0.5*s[i]; else q[i] = -1.01*0.5*s[i]; dMultiply0 (q2,dGeomGetRotation(box),q,3,3,1); for (j=0; j<3; j++) q2[j] += p[j]; dGeomSetPosition (ray,q2[0],q2[1],q2[2]); dRFromAxisAndAngle (R,dRandReal()*2-1,dRandReal()*2-1, dRandReal()*2-1,dRandReal()*10-5); dGeomSetRotation (ray,R); if (dCollide (ray,box,1,&contact,sizeof(dContactGeom)) != 0) FAILED(); // ********** test finite length ray totally contained inside the box for (j=0; j<3; j++) q[j] = (dRandReal()-0.5)*0.99*s[j]; dMultiply0 (q2,dGeomGetRotation(box),q,3,3,1); for (j=0; j<3; j++) q2[j] += p[j]; for (j=0; j<3; j++) q3[j] = (dRandReal()-0.5)*0.99*s[j]; dMultiply0 (q4,dGeomGetRotation(box),q3,3,3,1); for (j=0; j<3; j++) q4[j] += p[j]; for (j=0; j<3; j++) n[j] = q4[j] - q2[j]; dNormalize3 (n); dGeomRaySet (ray,q2[0],q2[1],q2[2],n[0],n[1],n[2]); dGeomRaySetLength (ray,dCalcPointsDistance3(q2,q4)); if (dCollide (ray,box,1,&contact,sizeof(dContactGeom)) != 0) FAILED(); // ********** test finite length ray totally outside the box for (j=0; j<3; j++) q[j] = (dRandReal()-0.5)*s[j]; i = dRandInt (3); if (dRandReal() > 0.5) q[i] = 1.01*0.5*s[i]; else q[i] = -1.01*0.5*s[i]; dMultiply0 (q2,dGeomGetRotation(box),q,3,3,1); for (j=0; j<3; j++) q3[j] = q2[j] + p[j]; dNormalize3 (q2); dGeomRaySet (ray,q3[0],q3[1],q3[2],q2[0],q2[1],q2[2]); dGeomRaySetLength (ray,10); if (dCollide (ray,box,1,&contact,sizeof(dContactGeom)) != 0) FAILED(); // ********** test ray from outside to just above surface for (j=0; j<3; j++) q[j] = (dRandReal()-0.5)*s[j]; i = dRandInt (3); if (dRandReal() > 0.5) q[i] = 1.01*0.5*s[i]; else q[i] = -1.01*0.5*s[i]; dMultiply0 (q2,dGeomGetRotation(box),q,3,3,1); for (j=0; j<3; j++) q3[j] = 2*q2[j] + p[j]; k = dSqrt(q2[0]*q2[0] + q2[1]*q2[1] + q2[2]*q2[2]); for (j=0; j<3; j++) q2[j] = -q2[j]; dGeomRaySet (ray,q3[0],q3[1],q3[2],q2[0],q2[1],q2[2]); dGeomRaySetLength (ray,k*0.99); if (dCollide (ray,box,1,&contact,sizeof(dContactGeom)) != 0) FAILED(); // ********** test ray from outside to just below surface dGeomRaySetLength (ray,k*1.01); if (dCollide (ray,box,1,&contact,sizeof(dContactGeom)) != 1) FAILED(); // ********** test contact point position for random rays for (j=0; j<3; j++) q[j] = dRandReal()*s[j]; dMultiply0 (q2,dGeomGetRotation(box),q,3,3,1); for (j=0; j<3; j++) q2[j] += p[j]; for (j=0; j<3; j++) q3[j] = dRandReal()-0.5; dNormalize3 (q3); dGeomRaySet (ray,q2[0],q2[1],q2[2],q3[0],q3[1],q3[2]); dGeomRaySetLength (ray,10); if (dCollide (ray,box,1,&contact,sizeof(dContactGeom))) { // check depth of contact point if (dFabs (dGeomBoxPointDepth (box,contact.pos[0],contact.pos[1],contact.pos[2])) > tol) FAILED(); // check position of contact point for (j=0; j<3; j++) contact.pos[j] -= p[j]; dMultiply1 (q,dGeomGetRotation(box),contact.pos,3,3,1); if ( dFabs(dFabs (q[0]) - 0.5*s[0]) > tol && dFabs(dFabs (q[1]) - 0.5*s[1]) > tol && dFabs(dFabs (q[2]) - 0.5*s[2]) > tol) { FAILED(); } // also check normal signs if (dCalcVectorDot3 (q3,contact.normal) > 0) FAILED(); draw_all_objects (space); } PASSED(); } int test_ray_and_ccylinder() { int j; dContactGeom contact; dVector3 p,a,b,n; dMatrix3 R; dReal r,l,k,x,y; dSimpleSpace space(0); dGeomID ray = dCreateRay (0,0); dGeomID ccyl = dCreateCapsule (0,1,1); dSpaceAdd (space,ray); dSpaceAdd (space,ccyl); // ********** make a random capped cylinder r = dRandReal()*0.5 + 0.01; l = dRandReal()*1 + 0.01; dGeomCapsuleSetParams (ccyl,r,l); dMakeRandomVector (p,3,1.0); dGeomSetPosition (ccyl,p[0],p[1],p[2]); dRFromAxisAndAngle (R,dRandReal()*2-1,dRandReal()*2-1, dRandReal()*2-1,dRandReal()*10-5); dGeomSetRotation (ccyl,R); // ********** test ray completely within ccyl for (j=0; j<3; j++) a[j] = dRandReal()-0.5; dNormalize3 (a); k = (dRandReal()-0.5)*l; for (j=0; j<3; j++) a[j] = p[j] + r*0.99*a[j] + k*0.99*R[j*4+2]; for (j=0; j<3; j++) b[j] = dRandReal()-0.5; dNormalize3 (b); k = (dRandReal()-0.5)*l; for (j=0; j<3; j++) b[j] = p[j] + r*0.99*b[j] + k*0.99*R[j*4+2]; dGeomRaySetLength (ray,dCalcPointsDistance3(a,b)); for (j=0; j<3; j++) b[j] -= a[j]; dNormalize3 (b); dGeomRaySet (ray,a[0],a[1],a[2],b[0],b[1],b[2]); if (dCollide (ray,ccyl,1,&contact,sizeof(dContactGeom)) != 0) FAILED(); // ********** test ray outside ccyl that just misses (between caps) k = dRandReal()*2*M_PI; x = sin(k); y = cos(k); for (j=0; j<3; j++) a[j] = x*R[j*4+0] + y*R[j*4+1]; k = (dRandReal()-0.5)*l; for (j=0; j<3; j++) b[j] = -a[j]*r*2 + k*R[j*4+2] + p[j]; dGeomRaySet (ray,b[0],b[1],b[2],a[0],a[1],a[2]); dGeomRaySetLength (ray,r*0.99); if (dCollide (ray,ccyl,1,&contact,sizeof(dContactGeom)) != 0) FAILED(); // ********** test ray outside ccyl that just hits (between caps) dGeomRaySetLength (ray,r*1.01); if (dCollide (ray,ccyl,1,&contact,sizeof(dContactGeom)) != 1) FAILED(); // check depth of contact point if (dFabs (dGeomCapsulePointDepth (ccyl,contact.pos[0],contact.pos[1],contact.pos[2])) > tol) FAILED(); // ********** test ray outside ccyl that just misses (caps) for (j=0; j<3; j++) a[j] = dRandReal()-0.5; dNormalize3 (a); if (dCalcVectorDot3_14(a,R+2) < 0) { for (j=0; j<3; j++) b[j] = p[j] - a[j]*2*r + l*0.5*R[j*4+2]; } else { for (j=0; j<3; j++) b[j] = p[j] - a[j]*2*r - l*0.5*R[j*4+2]; } dGeomRaySet (ray,b[0],b[1],b[2],a[0],a[1],a[2]); dGeomRaySetLength (ray,r*0.99); if (dCollide (ray,ccyl,1,&contact,sizeof(dContactGeom)) != 0) FAILED(); // ********** test ray outside ccyl that just hits (caps) dGeomRaySetLength (ray,r*1.01); if (dCollide (ray,ccyl,1,&contact,sizeof(dContactGeom)) != 1) FAILED(); // check depth of contact point if (dFabs (dGeomCapsulePointDepth (ccyl,contact.pos[0],contact.pos[1],contact.pos[2])) > tol) FAILED(); // ********** test random rays for (j=0; j<3; j++) a[j] = dRandReal()-0.5; for (j=0; j<3; j++) n[j] = dRandReal()-0.5; dNormalize3 (n); dGeomRaySet (ray,a[0],a[1],a[2],n[0],n[1],n[2]); dGeomRaySetLength (ray,10); if (dCollide (ray,ccyl,1,&contact,sizeof(dContactGeom))) { // check depth of contact point if (dFabs (dGeomCapsulePointDepth (ccyl,contact.pos[0],contact.pos[1],contact.pos[2])) > tol) FAILED(); // check normal signs if (dCalcVectorDot3 (n,contact.normal) > 0) FAILED(); draw_all_objects (space); } PASSED(); } /* Test rays within the cylinder -completely inside -exiting through side -exiting through cap -exiting through corner Test rays outside the cylinder */ int test_ray_and_cylinder() { dVector3 a,b; dSimpleSpace space(0); dGeomID ray = dCreateRay(space,4); // The first thing that happens is the ray is // rotated into cylinder coordinates. We'll trust that's // done right. The major axis is in the z-dir. // Random tests /*b[0]=4*dRandReal()-2; b[1]=4*dRandReal()-2; b[2]=4*dRandReal()-2; a[0]=2*dRandReal()-1; a[1]=2*dRandReal()-1; a[2]=2*dRandReal()-1;*/ // Inside out b[0]=dRandReal()-0.5; b[1]=dRandReal()-0.5; b[2]=dRandReal()-0.5; a[0]=2*dRandReal()-1; a[1]=2*dRandReal()-1; a[2]=2*dRandReal()-1; // Outside in /*b[0]=4*dRandReal()-2; b[1]=4*dRandReal()-2; b[2]=4*dRandReal()-2; a[0]=-b[0]; a[1]=-b[1]; a[2]=-b[2];*/ dGeomRaySet (ray,b[0],b[1],b[2],a[0],a[1],a[2]); // This is just for visual inspection right now. //if (dCollide (ray,cyl,1,&contact,sizeof(dContactGeom)) != 1) FAILED(); draw_all_objects (space); PASSED(); } int test_ray_and_plane() { int j; dContactGeom contact; dVector3 n,p,q,a,b,g,h; // n,d = plane parameters dMatrix3 R; dReal d; dSimpleSpace space(0); dGeomID ray = dCreateRay (0,0); dGeomID plane = dCreatePlane (0,0,0,1,0); dSpaceAdd (space,ray); dSpaceAdd (space,plane); // ********** make a random plane for (j=0; j<3; j++) n[j] = dRandReal() - 0.5; dNormalize3 (n); d = dRandReal() - 0.5; dGeomPlaneSetParams (plane,n[0],n[1],n[2],d); dPlaneSpace (n,p,q); // ********** test finite length ray below plane dGeomRaySetLength (ray,0.09); a[0] = dRandReal()-0.5; a[1] = dRandReal()-0.5; a[2] = -dRandReal()*0.5 - 0.1; for (j=0; j<3; j++) b[j] = a[0]*p[j] + a[1]*q[j] + (a[2]+d)*n[j]; dGeomSetPosition (ray,b[0],b[1],b[2]); dRFromAxisAndAngle (R,dRandReal()*2-1,dRandReal()*2-1, dRandReal()*2-1,dRandReal()*10-5); dGeomSetRotation (ray,R); if (dCollide (ray,plane,1,&contact,sizeof(dContactGeom)) != 0) FAILED(); // ********** test finite length ray above plane a[0] = dRandReal()-0.5; a[1] = dRandReal()-0.5; a[2] = dRandReal()*0.5 + 0.01; for (j=0; j<3; j++) b[j] = a[0]*p[j] + a[1]*q[j] + (a[2]+d)*n[j]; g[0] = dRandReal()-0.5; g[1] = dRandReal()-0.5; g[2] = dRandReal() + 0.01; for (j=0; j<3; j++) h[j] = g[0]*p[j] + g[1]*q[j] + g[2]*n[j]; dNormalize3 (h); dGeomRaySet (ray,b[0],b[1],b[2],h[0],h[1],h[2]); dGeomRaySetLength (ray,10); if (dCollide (ray,plane,1,&contact,sizeof(dContactGeom)) != 0) FAILED(); // ********** test finite length ray that intersects plane a[0] = dRandReal()-0.5; a[1] = dRandReal()-0.5; a[2] = dRandReal()-0.5; for (j=0; j<3; j++) b[j] = a[0]*p[j] + a[1]*q[j] + (a[2]+d)*n[j]; g[0] = dRandReal()-0.5; g[1] = dRandReal()-0.5; g[2] = dRandReal()-0.5; for (j=0; j<3; j++) h[j] = g[0]*p[j] + g[1]*q[j] + g[2]*n[j]; dNormalize3 (h); dGeomRaySet (ray,b[0],b[1],b[2],h[0],h[1],h[2]); dGeomRaySetLength (ray,10); if (dCollide (ray,plane,1,&contact,sizeof(dContactGeom))) { // test that contact is on plane surface if (dFabs (dCalcVectorDot3(contact.pos,n) - d) > tol) FAILED(); // also check normal signs if (dCalcVectorDot3 (h,contact.normal) > 0) FAILED(); // also check contact point depth if (dFabs (dGeomPlanePointDepth (plane,contact.pos[0],contact.pos[1],contact.pos[2])) > tol) FAILED(); draw_all_objects (space); } // ********** test ray that just misses for (j=0; j<3; j++) b[j] = (1+d)*n[j]; for (j=0; j<3; j++) h[j] = -n[j]; dGeomRaySet (ray,b[0],b[1],b[2],h[0],h[1],h[2]); dGeomRaySetLength (ray,0.99); if (dCollide (ray,plane,1,&contact,sizeof(dContactGeom)) != 0) FAILED(); // ********** test ray that just hits dGeomRaySetLength (ray,1.01); if (dCollide (ray,plane,1,&contact,sizeof(dContactGeom)) != 1) FAILED(); // ********** test polarity with typical ground plane dGeomPlaneSetParams (plane,0,0,1,0); for (j=0; j<3; j++) a[j] = 0.1; for (j=0; j<3; j++) b[j] = 0; a[2] = 1; b[2] = -1; dGeomRaySet (ray,a[0],a[1],a[2],b[0],b[1],b[2]); dGeomRaySetLength (ray,2); if (dCollide (ray,plane,1,&contact,sizeof(dContactGeom)) != 1) FAILED(); if (dFabs (contact.depth - 1) > tol) FAILED(); a[2] = -1; b[2] = 1; dGeomRaySet (ray,a[0],a[1],a[2],b[0],b[1],b[2]); if (dCollide (ray,plane,1,&contact,sizeof(dContactGeom)) != 1) FAILED(); if (dFabs (contact.depth - 1) > tol) FAILED(); PASSED(); } //**************************************************************************** // a really inefficient, but hopefully correct implementation of // dBoxTouchesBox(), that does 144 edge-face tests. // return 1 if edge v1 -> v2 hits the rectangle described by p1,p2,p3 static int edgeIntersectsRect (dVector3 v1, dVector3 v2, dVector3 p1, dVector3 p2, dVector3 p3) { int k; dVector3 u1,u2,n,tmp; for (k=0; k<3; k++) u1[k] = p3[k]-p1[k]; for (k=0; k<3; k++) u2[k] = p2[k]-p1[k]; dReal d1 = dSqrt(dCalcVectorDot3(u1,u1)); dReal d2 = dSqrt(dCalcVectorDot3(u2,u2)); dNormalize3 (u1); dNormalize3 (u2); if (dFabs(dCalcVectorDot3(u1,u2)) > 1e-6) dDebug (0,"bad u1/u2"); dCalcVectorCross3(n,u1,u2); for (k=0; k<3; k++) tmp[k] = v2[k]-v1[k]; dReal d = -dCalcVectorDot3(n,p1); if (dFabs(dCalcVectorDot3(n,p1)+d) > 1e-8) dDebug (0,"bad n wrt p1"); if (dFabs(dCalcVectorDot3(n,p2)+d) > 1e-8) dDebug (0,"bad n wrt p2"); if (dFabs(dCalcVectorDot3(n,p3)+d) > 1e-8) dDebug (0,"bad n wrt p3"); dReal alpha = -(d+dCalcVectorDot3(n,v1))/dCalcVectorDot3(n,tmp); for (k=0; k<3; k++) tmp[k] = v1[k]+alpha*(v2[k]-v1[k]); if (dFabs(dCalcVectorDot3(n,tmp)+d) > 1e-6) dDebug (0,"bad tmp"); if (alpha < 0) return 0; if (alpha > 1) return 0; for (k=0; k<3; k++) tmp[k] -= p1[k]; dReal a1 = dCalcVectorDot3(u1,tmp); dReal a2 = dCalcVectorDot3(u2,tmp); if (a1<0 || a2<0 || a1>d1 || a2>d2) return 0; return 1; } // return 1 if box 1 is completely inside box 2 static int box1inside2 (const dVector3 p1, const dMatrix3 R1, const dVector3 side1, const dVector3 p2, const dMatrix3 R2, const dVector3 side2) { for (int i=-1; i<=1; i+=2) { for (int j=-1; j<=1; j+=2) { for (int k=-1; k<=1; k+=2) { dVector3 v,vv; v[0] = i*0.5*side1[0]; v[1] = j*0.5*side1[1]; v[2] = k*0.5*side1[2]; dMultiply0_331 (vv,R1,v); vv[0] += p1[0] - p2[0]; vv[1] += p1[1] - p2[1]; vv[2] += p1[2] - p2[2]; for (int axis=0; axis < 3; axis++) { dReal z = dCalcVectorDot3_14(vv,R2+axis); if (z < (-side2[axis]*0.5) || z > (side2[axis]*0.5)) return 0; } } } } return 1; } // test if any edge from box 1 hits a face from box 2 static int testBoxesTouch2 (const dVector3 p1, const dMatrix3 R1, const dVector3 side1, const dVector3 p2, const dMatrix3 R2, const dVector3 side2) { int j,k,j1,j2; // for 6 faces from box 2 for (int fd=0; fd<3; fd++) { // direction for face for (int fo=0; fo<2; fo++) { // offset of face // get four points on the face. first get 2 indexes that are not fd int k1=0,k2=0; if (fd==0) { k1 = 1; k2 = 2; } if (fd==1) { k1 = 0; k2 = 2; } if (fd==2) { k1 = 0; k2 = 1; } dVector3 fp[4],tmp; k=0; for (j1=-1; j1<=1; j1+=2) { for (j2=-1; j2<=1; j2+=2) { fp[k][k1] = j1; fp[k][k2] = j2; fp[k][fd] = fo*2-1; k++; } } for (j=0; j<4; j++) { for (k=0; k<3; k++) fp[j][k] *= 0.5*side2[k]; dMultiply0_331 (tmp,R2,fp[j]); for (k=0; k<3; k++) fp[j][k] = tmp[k] + p2[k]; } // for 8 vertices dReal v1[3]; for (v1[0]=-1; v1[0] <= 1; v1[0] += 2) { for (v1[1]=-1; v1[1] <= 1; v1[1] += 2) { for (v1[2]=-1; v1[2] <= 1; v1[2] += 2) { // for all possible +ve leading edges from those vertices for (int ei=0; ei < 3; ei ++) { if (v1[ei] < 0) { // get vertex1 -> vertex2 = an edge from box 1 dVector3 vv1,vv2; for (k=0; k<3; k++) vv1[k] = v1[k] * 0.5*side1[k]; for (k=0; k<3; k++) vv2[k] = (v1[k] + (k==ei)*2)*0.5*side1[k]; dVector3 vertex1,vertex2; dMultiply0_331 (vertex1,R1,vv1); dMultiply0_331 (vertex2,R1,vv2); for (k=0; k<3; k++) vertex1[k] += p1[k]; for (k=0; k<3; k++) vertex2[k] += p1[k]; // see if vertex1 -> vertex2 interesects face if (edgeIntersectsRect (vertex1,vertex2,fp[0],fp[1],fp[2])) return 1; } } } } } } } if (box1inside2 (p1,R1,side1,p2,R2,side2)) return 1; if (box1inside2 (p2,R2,side2,p1,R1,side1)) return 1; return 0; } //**************************************************************************** // dBoxTouchesBox() test int test_dBoxTouchesBox() { int k,bt1,bt2; dVector3 p1,p2,side1,side2; dMatrix3 R1,R2; dSimpleSpace space(0); dGeomID box1 = dCreateBox (0,1,1,1); dSpaceAdd (space,box1); dGeomID box2 = dCreateBox (0,1,1,1); dSpaceAdd (space,box2); dMakeRandomVector (p1,3,0.5); dMakeRandomVector (p2,3,0.5); for (k=0; k<3; k++) side1[k] = dRandReal() + 0.01; for (k=0; k<3; k++) side2[k] = dRandReal() + 0.01; dRFromAxisAndAngle (R1,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0, dRandReal()*2.0-1.0,dRandReal()*10.0-5.0); dRFromAxisAndAngle (R2,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0, dRandReal()*2.0-1.0,dRandReal()*10.0-5.0); dGeomBoxSetLengths (box1,side1[0],side1[1],side1[2]); dGeomBoxSetLengths (box2,side2[0],side2[1],side2[2]); dGeomSetPosition (box1,p1[0],p1[1],p1[2]); dGeomSetRotation (box1,R1); dGeomSetPosition (box2,p2[0],p2[1],p2[2]); dGeomSetRotation (box2,R2); draw_all_objects (space); int t1 = testBoxesTouch2 (p1,R1,side1,p2,R2,side2); int t2 = testBoxesTouch2 (p2,R2,side2,p1,R1,side1); bt1 = t1 || t2; bt2 = dBoxTouchesBox (p1,R1,side1,p2,R2,side2); if (bt1 != bt2) FAILED(); /* // some more debugging info if necessary if (bt1 && bt2) printf ("agree - boxes touch\n"); if (!bt1 && !bt2) printf ("agree - boxes don't touch\n"); if (bt1 && !bt2) printf ("disagree - boxes touch but dBoxTouchesBox " "says no\n"); if (!bt1 && bt2) printf ("disagree - boxes don't touch but dBoxTouchesBox " "says yes\n"); */ PASSED(); } //**************************************************************************** // test box-box collision int test_dBoxBox() { int k,bt; dVector3 p1,p2,side1,side2,normal,normal2; dMatrix3 R1,R2; dReal depth,depth2; int code; dContactGeom contact[48]; dSimpleSpace space(0); dGeomID box1 = dCreateBox (0,1,1,1); dSpaceAdd (space,box1); dGeomID box2 = dCreateBox (0,1,1,1); dSpaceAdd (space,box2); dMakeRandomVector (p1,3,0.5); dMakeRandomVector (p2,3,0.5); for (k=0; k<3; k++) side1[k] = dRandReal() + 0.01; for (k=0; k<3; k++) side2[k] = dRandReal() + 0.01; dRFromAxisAndAngle (R1,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0, dRandReal()*2.0-1.0,dRandReal()*10.0-5.0); dRFromAxisAndAngle (R2,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0, dRandReal()*2.0-1.0,dRandReal()*10.0-5.0); // dRSetIdentity (R1); // we can also try this // dRSetIdentity (R2); dGeomBoxSetLengths (box1,side1[0],side1[1],side1[2]); dGeomBoxSetLengths (box2,side2[0],side2[1],side2[2]); dGeomSetPosition (box1,p1[0],p1[1],p1[2]); dGeomSetRotation (box1,R1); dGeomSetPosition (box2,p2[0],p2[1],p2[2]); dGeomSetRotation (box2,R2); code = 0; depth = 0; bt = dBoxBox (p1,R1,side1,p2,R2,side2,normal,&depth,&code,8,contact, sizeof(dContactGeom)); if (bt==1) { p2[0] += normal[0] * 0.96 * depth; p2[1] += normal[1] * 0.96 * depth; p2[2] += normal[2] * 0.96 * depth; bt = dBoxBox (p1,R1,side1,p2,R2,side2,normal2,&depth2,&code,8,contact, sizeof(dContactGeom)); /* dGeomSetPosition (box2,p2[0],p2[1],p2[2]); draw_all_objects (space); */ if (bt != 1) { FAILED(); dGeomSetPosition (box2,p2[0],p2[1],p2[2]); draw_all_objects (space); } p2[0] += normal[0] * 0.08 * depth; p2[1] += normal[1] * 0.08 * depth; p2[2] += normal[2] * 0.08 * depth; bt = dBoxBox (p1,R1,side1,p2,R2,side2,normal2,&depth2,&code,8,contact, sizeof(dContactGeom)); if (bt != 0) FAILED(); // dGeomSetPosition (box2,p2[0],p2[1],p2[2]); // draw_all_objects (space); } // printf ("code=%2d depth=%.4f ",code,depth); PASSED(); } //**************************************************************************** // graphics int space_pressed = 0; // start simulation - set viewpoint static void start() { dAllocateODEDataForThread(dAllocateMaskAll); static float xyz[3] = {2.4807,-1.8023,2.7600}; static float hpr[3] = {141.5000,-18.5000,0.0000}; dsSetViewpoint (xyz,hpr); } // called when a key pressed static void command (int cmd) { if (cmd == ' ') space_pressed = 1; } // simulation loop static void simLoop (int) { do { draw_all_objects_called = 0; unsigned long seed = dRandGetSeed(); testslot[graphical_test].test_fn(); if (draw_all_objects_called) { if (space_pressed) space_pressed = 0; else dRandSetSeed (seed); } } while (!draw_all_objects_called); } //**************************************************************************** // do all the tests void do_tests (int argc, char **argv) { int i,j; // process command line arguments if (argc >= 2) { graphical_test = atoi (argv[1]); } if (graphical_test) { // do one test gaphically and interactively if (graphical_test < 1 || graphical_test >= MAX_TESTS || !testslot[graphical_test].name) { dError (0,"invalid test number"); } printf ("performing test: %s\n",testslot[graphical_test].name); // setup pointers to drawstuff callback functions dsFunctions fn; fn.version = DS_VERSION; fn.start = &start; fn.step = &simLoop; fn.command = &command; fn.stop = 0; fn.path_to_textures = DRAWSTUFF_TEXTURE_PATH; dsSetSphereQuality (3); dsSetCapsuleQuality (8); dsSimulationLoop (argc,argv,1280,900,&fn); } else { // do all tests noninteractively for (i=0; ifailcount = 0; int total_reps=0; for (int batch=0; batch<2; batch++) { int reps = (batch==0) ? TEST_REPS1 : TEST_REPS2; total_reps += reps; printf ("testing batch %d (%d reps)...\n",batch+1,reps); // run tests for (j=0; jnumber; if (ts[i]->test_fn() != 1) ts[i]->failcount++; } } // check for failures int total_fail_count=0; for (i=0; ifailcount; if (total_fail_count) break; } // print results for (i=0; inumber,ts[i]->name); if (ts[i]->failcount) { printf ("FAILED (%.2f%%) at line %d\n", double(ts[i]->failcount)/double(total_reps)*100.0, ts[i]->last_failed_line); } else { printf ("ok\n"); } } } } //**************************************************************************** int main (int argc, char **argv) { // setup all tests memset (testslot,0,sizeof(testslot)); dInitODE2(0); MAKE_TEST(1,test_sphere_point_depth); MAKE_TEST(2,test_box_point_depth); MAKE_TEST(3,test_ccylinder_point_depth); MAKE_TEST(4,test_plane_point_depth); MAKE_TEST(10,test_ray_and_sphere); MAKE_TEST(11,test_ray_and_box); MAKE_TEST(12,test_ray_and_ccylinder); MAKE_TEST(13,test_ray_and_plane); MAKE_TEST(14,test_ray_and_cylinder); MAKE_TEST(100,test_dBoxTouchesBox); MAKE_TEST(101,test_dBoxBox); do_tests (argc,argv); dCloseODE(); return 0; } ode-0.16/ode/demo/demo_piston.cpp0000664000175200017520000005545413403272463013676 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * * Created by: Remi Ricard * * (remi.ricard@simlog.com or papaDoc@videotron.ca) * * Creation date: 2007/05/04 * *************************************************************************/ /* This program demonstrates how the Piston joint works. A Piston joint enables the sliding of a body with respect to another body and the 2 bodies are free to rotate about the sliding axis. - The yellow body is fixed to the world. - The yellow body and the blue body are attached by a Piston joint with the axis along the x direction. - The purple object is a geometry obstacle. - The red line is the representation of the prismatic axis - The orange line is the representation of the rotoide axis - The light blue ball is the anchor position N.B. Many command options are available type -h to print them. */ #include #include #include #include #include "texturepath.h" #ifdef _MSC_VER #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints #endif // select correct drawing functions #ifdef dDOUBLE #define dsDrawBox dsDrawBoxD #define dsDrawCylinder dsDrawCylinderD #define dsDrawCapsule dsDrawCapsuleD #define dsDrawSphere dsDrawSphereD #endif const dReal VEL_INC = 0.01; // Velocity increment // physics parameters const dReal PI = 3.14159265358979323846264338327950288419716939937510; const dReal BODY1_LENGTH = 1.5; // Size along the X axis const dReal RADIUS = 0.2; const dReal AXIS_RADIUS = 0.01; #define X 0 #define Y 1 #define Z 2 enum INDEX { BODY1 = 0, BODY2, RECT, BOX, OBS, GROUND, NUM_PARTS, ALL = NUM_PARTS }; const int catBits[NUM_PARTS+1] = { 0x0001, ///< Ext Cylinder category 0x0002, ///< Int Cylinder category 0x0004, ///< Int_Rect Cylinder category 0x0008, ///< Box category 0x0010, ///< Obstacle category 0x0020, ///< Ground category ~0L ///< All categories }; #define Mass1 10 #define Mass2 8 //camera view static float xyz[3] = {2.0f,-3.5f,2.0000f}; static float hpr[3] = {90.000f,-25.5000f,0.0000f}; //world,space,body & geom static dWorldID world; static dSpaceID space; static dJointGroupID contactgroup; static dBodyID body[NUM_PARTS]; static dGeomID geom[NUM_PARTS]; // Default Positions and anchor of the 2 bodies dVector3 pos1; dVector3 pos2; dVector3 anchor; static dJoint *joint; const dReal BODY2_SIDES[3] = {0.4, 0.4, 0.4}; const dReal OBS_SIDES[3] = {1,1,1}; const dReal RECT_SIDES[3] = {0.3, 0.1, 0.2}; int type = dJointTypePiston; //#pragma message("tc to be changed to 0") int tc = 0; // The test case choice; //collision detection static void nearCallback (void *, dGeomID o1, dGeomID o2) { int i,n; dBodyID b1 = dGeomGetBody (o1); dBodyID b2 = dGeomGetBody (o2); if (b1 && b2 && dAreConnectedExcluding (b1,b2,dJointTypeContact) ) return; const int N = 10; dContact contact[N]; n = dCollide (o1,o2,N,&contact[0].geom,sizeof (dContact) ); if (n > 0) { for (i=0; iattach (body[BODY1], body[BODY2]); if (joint->getType() == dJointTypePiston) dJointSetPistonAnchor(joint->id(), anchor[X], anchor[Y], anchor[Z]); } } // function to update camera position at each step. void update() { // static FILE *file = fopen("x:/sim/src/libode/tstsrcSF/export.dat", "w"); // static int cnt = 0; // char str[24]; // sprintf(str, "%06d",cnt++); // dWorldExportDIF(world, file, str); } // called when a key pressed static void command (int cmd) { switch (cmd) { case 'h' : case 'H' : case '?' : printKeyBoardShortCut(); break; // Force case 'q' : case 'Q' : dBodyAddForce (body[BODY1],4,0,0); break; case 'w' : case 'W' : dBodyAddForce (body[BODY1],-4,0,0); break; case 'a' : case 'A' : dBodyAddForce (body[BODY1],0,40,0); break; case 's' : case 'S' : dBodyAddForce (body[BODY1],0,-40,0); break; case 'z' : case 'Z' : dBodyAddForce (body[BODY1],0,0,4); break; case 'x' : case 'X' : dBodyAddForce (body[BODY1],0,0,-4); break; // Torque case 'e': case 'E': dBodyAddTorque (body[BODY1],0.1,0,0); break; case 'r': case 'R': dBodyAddTorque (body[BODY1],-0.1,0,0); break; case 'd': case 'D': dBodyAddTorque (body[BODY1],0, 0.1,0); break; case 'f': case 'F': dBodyAddTorque (body[BODY1],0,-0.1,0); break; case 'c': case 'C': dBodyAddTorque (body[BODY1],0.1,0,0); break; case 'v': case 'V': dBodyAddTorque (body[BODY1],-0.1,0,0); break; case 't': case 'T': if (joint->getType() == dJointTypePiston) dJointAddPistonForce (joint->id(),1); else dJointAddSliderForce (joint->id(),1); break; case 'y': case 'Y': if (joint->getType() == dJointTypePiston) dJointAddPistonForce (joint->id(),-1); else dJointAddSliderForce (joint->id(),-1); break; case '8' : dJointAttach(joint->id(), body[0], 0); break; case '9' : dJointAttach(joint->id(), 0, body[0]); break; case 'i': case 'I' : joint->setParam (dParamLoStop, 0); joint->setParam (dParamHiStop, 0); break; case 'o': case 'O' : joint->setParam (dParamLoStop2, 0); joint->setParam (dParamHiStop2, 0); break; case 'k': case 'K': joint->setParam (dParamLoStop2, -45.0*3.14159267/180.0); joint->setParam (dParamHiStop2, 45.0*3.14159267/180.0); break; case 'l': case 'L': joint->setParam (dParamLoStop2, -dInfinity); joint->setParam (dParamHiStop2, dInfinity); break; // Velocity of joint case ',': case '<' : { dReal vel = joint->getParam (dParamVel) - VEL_INC; joint->setParam (dParamVel, vel); std::cout<<"Velocity = "<' : { dReal vel = joint->getParam (dParamVel) + VEL_INC; joint->setParam (dParamVel, vel); std::cout<<"Velocity = "<getType() ) { case dJointTypeSlider : { dSliderJoint *sj = reinterpret_cast (joint); std::cout<<"Position ="<getPosition() <<"\n"; } break; case dJointTypePiston : { dPistonJoint *rj = reinterpret_cast (joint); std::cout<<"Position ="<getPosition() <<"\n"; } break; default: {} // keep the compiler happy } } break; case '+' : (++tc) %= 4; setPositionBodies (tc); break; case '-' : (--tc) %= 4; setPositionBodies (tc); break; } } static void drawBox (dGeomID id, int R, int G, int B) { if (!id) return; const dReal *pos = dGeomGetPosition (id); const dReal *rot = dGeomGetRotation (id); dsSetColor (R,G,B); dVector3 l; dGeomBoxGetLengths (id, l); dsDrawBox (pos, rot, l); } // simulation loop static void simLoop (int pause) { const dReal *rot; dVector3 ax; dReal l=0; switch (joint->getType() ) { case dJointTypeSlider : ( (dSliderJoint *) joint)->getAxis (ax); l = ( (dSliderJoint *) joint)->getPosition(); break; case dJointTypePiston : ( (dPistonJoint *) joint)->getAxis (ax); l = ( (dPistonJoint *) joint)->getPosition(); break; default: {} // keep the compiler happy } if (!pause) { double simstep = 0.01; // 1ms simulation steps double dt = dsElapsedTime(); int nrofsteps = (int) ceilf (dt/simstep); if (!nrofsteps) nrofsteps = 1; for (int i=0; igetType() == dJointTypePiston ) { dVector3 anchor; dJointGetPistonAnchor(joint->id(), anchor); // Draw the rotoide axis rot = dGeomGetRotation (geom[BODY2]); dsSetColor (1,0.5,0); dsDrawCylinder (anchor, rot, 4, AXIS_RADIUS); dsSetColor (0,1,1); rot = dGeomGetRotation (geom[BODY1]); dsDrawSphere (anchor, rot, 1.5*RADIUS); } } } void Help (char **argv) { printf ("%s ", argv[0]); printf (" -h | --help : print this help\n"); printf (" -s | --slider : Set the joint as a slider\n"); printf (" -p | --piston : Set the joint as a Piston. (Default joint)\n"); printf (" -1 | --offset1 : Create an offset between the 2 bodies\n"); printf (" Offset one of the body by z=-0.5 and keep the anchor\n"); printf (" point in the middle of the fixed body\n"); printf (" -2 | --offset2 : Create an offset between the 2 bodies\n"); printf (" Offset one of the body by z=-0.5 and set the anchor\n"); printf (" point in the middle of the movable body\n"); printf (" -3 | --offset3 : Create an offset between the 2 bodies\n"); printf (" Offset one of the body by z=-0.5 and set the anchor\n"); printf (" point in the middle of the 2 bodies\n"); printf (" -t | --texture-path path : Path to the texture.\n"); printf (" Default = %s\n", DRAWSTUFF_TEXTURE_PATH); printf (" -n | --notFixed : In free space with no gravity mode"); printf ("-notex : Don't use texture\n"); printf ("-noshadow : No shadow\n"); printf ("-noshadows : No shadows\n"); printf ("-pause : Initial pause\n"); printf ("--------------------------------------------------\n"); printf ("Hit any key to continue:"); getchar(); exit (0); } int main (int argc, char **argv) { dInitODE2(0); bool fixed = true; // setup pointers to drawstuff callback functions dsFunctions fn; fn.version = DS_VERSION; fn.start = &start; fn.step = &simLoop; fn.command = &command; fn.stop = 0; fn.path_to_textures = DRAWSTUFF_TEXTURE_PATH; dVector3 offset; dSetZero (offset, 4); // Default test case if (argc >= 2 ) { for (int i=1; i < argc; ++i) { //static int tata = 0; if (1) { if ( 0 == strcmp ("-h", argv[i]) || 0 == strcmp ("--help", argv[i]) ) Help (argv); if ( 0 == strcmp ("-s", argv[i]) || 0 == strcmp ("--slider", argv[i]) ) type = dJointTypeSlider; if ( 0 == strcmp ("-t", argv[i]) || 0 == strcmp ("--texture-path", argv[i]) ) { int j = i+1; if ( j >= argc || // Check if we have enough arguments argv[j][0] == '\0' || // We should have a path here argv[j][0] == '-' ) // We should have a path not a command line Help (argv); else fn.path_to_textures = argv[++i]; // Increase i since we use this argument } } if ( 0 == strcmp ("-1", argv[i]) || 0 == strcmp ("--offset1", argv[i]) ) tc = 1; if ( 0 == strcmp ("-2", argv[i]) || 0 == strcmp ("--offset2", argv[i]) ) tc = 2; if ( 0 == strcmp ("-3", argv[i]) || 0 == strcmp ("--offset3", argv[i]) ) tc = 3; if (0 == strcmp ("-n", argv[i]) || 0 == strcmp ("--notFixed", argv[i]) ) fixed = false; } } world = dWorldCreate(); dWorldSetERP (world, 0.8); space = dSimpleSpaceCreate (0); contactgroup = dJointGroupCreate (0); geom[GROUND] = dCreatePlane (space, 0,0,1,0); dGeomSetCategoryBits (geom[GROUND], catBits[GROUND]); dGeomSetCollideBits (geom[GROUND], catBits[ALL]); dMass m; dMatrix3 R; // Create the Obstacle geom[OBS] = dCreateBox (space, OBS_SIDES[0], OBS_SIDES[1], OBS_SIDES[2]); dGeomSetCategoryBits (geom[OBS], catBits[OBS]); dGeomSetCollideBits (geom[OBS], catBits[ALL]); //Rotation of 45deg around y dRFromAxisAndAngle (R, 1,1,0, -0.25*PI); dGeomSetRotation (geom[OBS], R); dGeomSetPosition (geom[OBS], 1.95, -0.2, 0.5); //Rotation of 90deg around y // Will orient the Z axis along X dRFromAxisAndAngle (R, 0,1,0, -0.5*PI); // Create Body2 (Wiil be attached to the world) body[BODY2] = dBodyCreate (world); // Main axis of cylinder is along X=1 dMassSetBox (&m, 1, BODY2_SIDES[0], BODY2_SIDES[1], BODY2_SIDES[2]); dMassAdjust (&m, Mass1); geom[BODY2] = dCreateBox (space, BODY2_SIDES[0], BODY2_SIDES[1], BODY2_SIDES[2]); dGeomSetBody (geom[BODY2], body[BODY2]); dGeomSetOffsetRotation (geom[BODY2], R); dGeomSetCategoryBits (geom[BODY2], catBits[BODY2]); dGeomSetCollideBits (geom[BODY2], catBits[ALL] & (~catBits[BODY1]) ); dBodySetMass (body[BODY2], &m); // Create Body 1 (Slider on the prismatic axis) body[BODY1] = dBodyCreate (world); // Main axis of capsule is along X=1 dMassSetCapsule (&m, 1, 1, RADIUS, BODY1_LENGTH); dMassAdjust (&m, Mass1); geom[BODY1] = dCreateCapsule (space, RADIUS, BODY1_LENGTH); dGeomSetBody (geom[BODY1], body[BODY1]); dGeomSetOffsetRotation (geom[BODY1], R); dGeomSetCategoryBits (geom[BODY1], catBits[BODY1]); dGeomSetCollideBits (geom[BODY1], catBits[ALL] & ~catBits[BODY2] & ~catBits[RECT]); dMass mRect; dMassSetBox (&mRect, 1, RECT_SIDES[0], RECT_SIDES[1], RECT_SIDES[2]); dMassAdd (&m, &mRect); // TODO: translate m? geom[RECT] = dCreateBox (space, RECT_SIDES[0], RECT_SIDES[1], RECT_SIDES[2]); dGeomSetBody (geom[RECT], body[BODY1]); dGeomSetOffsetPosition (geom[RECT], (BODY1_LENGTH-RECT_SIDES[0]) /2.0, 0.0, -RADIUS -RECT_SIDES[2]/2.0); dGeomSetCategoryBits (geom[RECT], catBits[RECT]); dGeomSetCollideBits (geom[RECT], catBits[ALL] & (~catBits[BODY1]) ); dBodySetMass (body[BODY1], &m); setPositionBodies (tc); if ( fixed ) { // Attache external cylinder to the world dJointID fixed = dJointCreateFixed (world,0); dJointAttach (fixed , NULL, body[BODY2]); dJointSetFixed (fixed ); dWorldSetGravity (world,0,0,-0.8); } else { dWorldSetGravity (world,0,0,0); } // The static is here only to help debugging switch (type) { case dJointTypeSlider : { dSliderJoint *sj = new dSliderJoint (world, 0); sj->attach (body[BODY1], body[BODY2]); sj->setAxis (1, 0, 0); joint = sj; } break; case dJointTypePiston : // fall through default default: { dPistonJoint *pj = new dPistonJoint (world, 0); pj->attach (body[BODY1], body[BODY2]); pj->setAxis (1, 0, 0); dJointSetPistonAnchor(pj->id(), anchor[X], anchor[Y], anchor[Z]); joint = pj; } break; }; // run simulation dsSimulationLoop (argc,argv,400,300,&fn); delete joint; dJointGroupDestroy (contactgroup); dSpaceDestroy (space); dWorldDestroy (world); dCloseODE(); return 0; } ode-0.16/ode/demo/demo_motion.cpp0000664000175200017520000003666013403272463013665 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* This demo shows how to use dContactMotionN in a lifting platform. */ //#include // for usleep() #include #include #include "texturepath.h" #ifdef _MSC_VER #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints #endif // select correct drawing functions #ifdef dDOUBLE #define dsDrawBox dsDrawBoxD #define dsDrawSphere dsDrawSphereD #define dsDrawCylinder dsDrawCylinderD #define dsDrawCapsule dsDrawCapsuleD #define dsDrawConvex dsDrawConvexD #endif // some constants #define NUM 100 // max number of objects #define DENSITY (5.0) // density of all objects #define GPB 3 // maximum number of geometries per body #define MAX_CONTACTS 8 // maximum number of contact points per body #define USE_GEOM_OFFSET 1 // dynamics and collision objects struct MyObject { dBodyID body; // the body dGeomID geom[GPB]; // geometries representing this body }; static int num=0; // number of objects in simulation static int nextobj=0; // next object to recycle if num==NUM static dWorldID world; static dSpaceID space; static MyObject obj[NUM]; static dJointGroupID contactgroup; static int show_aabb = 0; // show geom AABBs? static int show_contacts = 0; // show contact points? static int random_pos = 1; // drop objects from random position? static int write_world = 0; static int show_body = 0; static dGeomID platform, ground; dVector3 platpos = {0, 0, 0}; int mov_type = 2; dReal mov_time = 0; const dReal mov1_speed = 0.2; dVector3 mov2_vel = { 0.2, 0.1, 0.25}; /**************************************************************** * Movement 1: move platform up, reset every 80 units of time. * * This is the simplest case * ****************************************************************/ static void moveplat_1(dReal stepsize) { mov_time += stepsize; if (mov_time > 80) mov_time = 0; platpos[0] = platpos[1] = 0; // the platform moves up (Z) at constant speed: mov1_speed platpos[2] = mov1_speed * mov_time; } // Generate contact info for movement 1 static void contactplat_1(dContact &contact) { contact.surface.mode |= dContactMotionN; contact.surface.motionN = mov1_speed; } /**************************************************************** * Movement 2: move platform along direction mov2_vel, reset * * every 80 units of time. * * This is the most general case: the geom moves along * * an arbitrary direction. * ****************************************************************/ static void moveplat_2(dReal stepsize) { mov_time += stepsize; if (mov_time > 80) mov_time = 0; // the platform moves at constant speed: mov2_speed platpos[0] = mov2_vel[0] * mov_time; platpos[1] = mov2_vel[1] * mov_time; platpos[2] = mov2_vel[2] * mov_time; } // Generate contact info for movement 1 static void contactplat_2(dContact &contact) { /* For arbitrary contact directions we need to project the moving geom's velocity against the contact normal and fdir1, fdir2 (obtained with dPlaneSpace()). Assuming moving geom=g2 (so the contact joint is in the moving geom's reference frame): motion1 = dCalcVectorDot3(fdir1, vel); motion2 = dCalcVectorDot3(fdir2, vel); motionN = dCalcVectorDot3(normal, vel); For geom=g1 just negate motionN and motion2. fdir1 is an arbitrary vector, so there's no need to negate motion1. */ contact.surface.mode |= dContactMotionN | // velocity along normal dContactMotion1 | dContactMotion2 | // and along the contact plane dContactFDir1; // don't forget to set the direction 1 // This is a convenience function: given a vector, it finds other 2 perpendicular vectors dVector3 motiondir1, motiondir2; dPlaneSpace(contact.geom.normal, motiondir1, motiondir2); for (int i=0; i<3; ++i) contact.fdir1[i] = motiondir1[i]; dReal inv = 1; if (contact.geom.g1 == platform) inv = -1; contact.surface.motion1 = dCalcVectorDot3(mov2_vel, motiondir1); contact.surface.motion2 = inv * dCalcVectorDot3(mov2_vel, motiondir2); contact.surface.motionN = inv * dCalcVectorDot3(mov2_vel, contact.geom.normal); } static void nearCallback (void *, dGeomID o1, dGeomID o2) { dMatrix3 RI; static const dReal ss[3] = {0.02,0.02,0.02}; dContact contact[MAX_CONTACTS]; int numc = dCollide (o1, o2, MAX_CONTACTS, &contact[0].geom, sizeof(dContact)); if (numc) dRSetIdentity(RI); bool isplatform = (o1 == platform) || (o2 == platform); for (int i=0; i< numc; i++) { contact[i].surface.mode = dContactBounce; contact[i].surface.mu = 1; contact[i].surface.bounce = 0.25; contact[i].surface.bounce_vel = 0.01; if (isplatform) { switch (mov_type) { case 1: contactplat_1(contact[i]); break; case 2: contactplat_2(contact[i]); break; } } dJointID c = dJointCreateContact (world,contactgroup,contact+i); dJointAttach (c, dGeomGetBody(o1), dGeomGetBody(o2)); if (show_contacts) dsDrawBox (contact[i].geom.pos, RI, ss); } } // start simulation - set viewpoint static float xyz[3] = {2.1106f,-1.3007,2.f}; static float hpr[3] = {150.f,-13.5000f,0.0000f}; static void start() { //dAllocateODEDataForThread(dAllocateMaskAll); dsSetViewpoint (xyz,hpr); printf ("To drop another object, press:\n"); printf (" b for box.\n"); printf (" s for sphere.\n"); printf (" c for capsule.\n"); printf (" y for cylinder.\n"); printf ("Press m to change the movement type\n"); printf ("Press space to reset the platform\n"); printf ("To toggle showing the geom AABBs, press a.\n"); printf ("To toggle showing the contact points, press t.\n"); printf ("To toggle dropping from random position/orientation, press r.\n"); printf ("To save the current state to 'state.dif', press 1.\n"); } char locase (char c) { if (c >= 'A' && c <= 'Z') return c - ('a'-'A'); else return c; } // called when a key pressed static void command (int cmd) { dsizeint i; int k; dReal sides[3]; dMass m; int setBody; cmd = locase (cmd); if (cmd == 'b' || cmd == 's' || cmd == 'c' || cmd == 'y') { setBody = 0; if (num < NUM) { i = num; num++; } else { i = nextobj; nextobj++; if (nextobj >= num) nextobj = 0; // destroy the body and geoms for slot i if (obj[i].body) { dBodyDestroy (obj[i].body); } for (k=0; k < GPB; k++) { if (obj[i].geom[k]) { dGeomDestroy (obj[i].geom[k]); } } memset (&obj[i],0,sizeof(obj[i])); } obj[i].body = dBodyCreate (world); for (k=0; k<3; k++) sides[k] = dRandReal()*0.5+0.1; dMatrix3 R; if (random_pos) { dBodySetPosition (obj[i].body, dRandReal()*2-1 + platpos[0], dRandReal()*2-1 + platpos[1], dRandReal()+2 + platpos[2]); dRFromAxisAndAngle (R,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0, dRandReal()*2.0-1.0,dRandReal()*10.0-5.0); } else { dBodySetPosition (obj[i].body, platpos[0], platpos[1], platpos[2]+2); dRSetIdentity (R); } dBodySetRotation (obj[i].body,R); dBodySetData (obj[i].body,(void*) i); if (cmd == 'b') { dMassSetBox (&m,DENSITY,sides[0],sides[1],sides[2]); obj[i].geom[0] = dCreateBox (space,sides[0],sides[1],sides[2]); } else if (cmd == 'c') { sides[0] *= 0.5; dMassSetCapsule (&m,DENSITY,3,sides[0],sides[1]); obj[i].geom[0] = dCreateCapsule (space,sides[0],sides[1]); } else if (cmd == 'y') { dMassSetCylinder (&m,DENSITY,3,sides[0],sides[1]); obj[i].geom[0] = dCreateCylinder (space,sides[0],sides[1]); } else if (cmd == 's') { sides[0] *= 0.5; dMassSetSphere (&m,DENSITY,sides[0]); obj[i].geom[0] = dCreateSphere (space,sides[0]); } if (!setBody) for (k=0; k < GPB; k++) { if (obj[i].geom[k]) { dGeomSetBody (obj[i].geom[k],obj[i].body); } } dBodySetMass (obj[i].body,&m); } else if (cmd == 'a') { show_aabb ^= 1; } else if (cmd == 't') { show_contacts ^= 1; } else if (cmd == 'r') { random_pos ^= 1; } else if (cmd == '1') { write_world = 1; } else if (cmd == ' ') { mov_time = 0; } else if (cmd == 'm') { mov_type = mov_type==1 ? 2 : 1; mov_time = 0; } } // draw a geom void drawGeom (dGeomID g, const dReal *pos, const dReal *R, int show_aabb) { int i; if (!g) return; if (!pos) pos = dGeomGetPosition (g); if (!R) R = dGeomGetRotation (g); int type = dGeomGetClass (g); if (type == dBoxClass) { dVector3 sides; dGeomBoxGetLengths (g,sides); dsDrawBox (pos,R,sides); } else if (type == dSphereClass) { dsDrawSphere (pos,R,dGeomSphereGetRadius (g)); } else if (type == dCapsuleClass) { dReal radius,length; dGeomCapsuleGetParams (g,&radius,&length); dsDrawCapsule (pos,R,length,radius); } else if (type == dCylinderClass) { dReal radius,length; dGeomCylinderGetParams (g,&radius,&length); dsDrawCylinder (pos,R,length,radius); } if (show_body) { dBodyID body = dGeomGetBody(g); if (body) { const dReal *bodypos = dBodyGetPosition (body); const dReal *bodyr = dBodyGetRotation (body); dReal bodySides[3] = { 0.1, 0.1, 0.1 }; dsSetColorAlpha(0,1,0,1); dsDrawBox(bodypos,bodyr,bodySides); } } if (show_aabb) { // draw the bounding box for this geom dReal aabb[6]; dGeomGetAABB (g,aabb); dVector3 bbpos; for (i=0; i<3; i++) bbpos[i] = 0.5*(aabb[i*2] + aabb[i*2+1]); dVector3 bbsides; for (i=0; i<3; i++) bbsides[i] = aabb[i*2+1] - aabb[i*2]; dMatrix3 RI; dRSetIdentity (RI); dsSetColorAlpha (1,0,0,0.5); dsDrawBox (bbpos,RI,bbsides); } } // simulation loop static void updatecam() { xyz[0] = platpos[0] + 3.3; xyz[1] = platpos[1] - 1.8; xyz[2] = platpos[2] + 2; dsSetViewpoint (xyz, hpr); } static void simLoop (int pause) { const dReal stepsize = 0.02; dsSetColor (0,0,2); dSpaceCollide (space,0,&nearCallback); if (!pause) { if (mov_type == 1) moveplat_1(stepsize); else moveplat_2(stepsize); dGeomSetPosition(platform, platpos[0], platpos[1], platpos[2]); updatecam(); dWorldQuickStep (world,stepsize); //dWorldStep (world,stepsize); } if (write_world) { FILE *f = fopen ("state.dif","wt"); if (f) { dWorldExportDIF (world,f,"X"); fclose (f); } write_world = 0; } // remove all contact joints dJointGroupEmpty (contactgroup); dsSetColor (1,1,0); dsSetTexture (DS_WOOD); for (int i=0; i #include #include "texturepath.h" #ifdef _MSC_VER #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints #endif // select correct drawing functions #ifdef dDOUBLE #define dsDrawBox dsDrawBoxD #define dsDrawSphere dsDrawSphereD #define dsDrawCylinder dsDrawCylinderD #define dsDrawCapsule dsDrawCapsuleD #endif // some constants #define GRAVITY 10 // the global gravity to use #define RAMP_COUNT 8 static const dReal rampX = 6.0f; static const dReal rampY = 0.5f; static const dReal rampZ = 0.25f; static const dReal sphereRadius = 0.25f; static const dReal maxRamp = M_PI/4.0f; // Needs to be less than pi/2 static const dReal rampInc = maxRamp/RAMP_COUNT; // dynamics and collision objects static dWorldID world = 0; static dSpaceID space = 0; static dJointGroupID contactgroup = 0; static dGeomID ground; static dReal mu = REAL(0.37); // the global mu to use static dReal rho = REAL(0.1); // the global rho to use static dReal omega = REAL(25.0); static dGeomID rampGeom[RAMP_COUNT]; static dBodyID sphereBody[RAMP_COUNT]; static dGeomID sphereGeom[RAMP_COUNT]; // this is called by dSpaceCollide when two objects in space are // potentially colliding. static void nearCallback (void *, dGeomID o1, dGeomID o2) { int i; dBodyID b1 = dGeomGetBody(o1); dBodyID b2 = dGeomGetBody(o2); if (b1==0 && b2==0) return; dContact contact[3]; for (int ii=0; ii<3; ii++) { contact[ii].surface.mode = dContactApprox1 | dContactRolling; contact[ii].surface.mu = mu; contact[ii].surface.rho = rho; } if (int numc = dCollide (o1,o2,3,&contact[0].geom,sizeof(dContact))) { for (i=0; i1) rho=1; break; case 'n': case 'N': mu-=0.02; if (mu<0) mu=0; break; case 'm': case 'M': mu+=0.02; if (mu>1) mu=1; break; case 'r': case 'R': reset(); break; case ']': omega+=1; break; case '[': omega-=1; break; } } // simulation loop static void simLoop (int pause) { if (!pause) { dSpaceCollide (space,0,&nearCallback); dWorldStep (world,0.017); // 60 fps // remove all contact joints dJointGroupEmpty (contactgroup); } // Render ramps and spheres dsSetTexture (DS_WOOD); for (int ii=0;ii #include #include "texturepath.h" #ifdef dDOUBLE #define dsDrawSphere dsDrawSphereD #define dsDrawBox dsDrawBoxD #define dsDrawLine dsDrawLineD #endif dWorldID world; dSpaceID space; dBodyID body1; dBodyID body2; dJointID joint1, joint2; bool applyForce = false; void start() { world = dWorldCreate(); dWorldSetGravity (world,0,0,-9.8); dWorldSetDamping(world, 1e-4, 1e-5); // dWorldSetERP(world, 1); space = dSimpleSpaceCreate (0); body1 = dBodyCreate(world); body2 = dBodyCreate(world); dBodySetPosition(body1, 0, 0, 3); dBodySetPosition(body2, 0, 0, 1); dGeomID g; dMass mass; g = dCreateBox(space, 0.2, 0.2, 1); dGeomSetBody(g, body1); dMassSetBox(&mass, 1, 0.2, 0.2, 1); dBodySetMass(body1, &mass); g = dCreateBox(space, 0.2, 0.2, 1); dGeomSetBody(g, body2); dMassSetBox(&mass, 1, 0.2, 0.2, 1); dBodySetMass(body2, &mass); #if 1 joint1 = dJointCreateDHinge(world, 0); dJointAttach(joint1, body1, 0); dJointSetDHingeAxis(joint1, 0, 1, 0); dJointSetDHingeAnchor1(joint1, 0, 0, 3.5); dJointSetDHingeAnchor2(joint1, 0, 0, 4.5); #endif #if 1 joint2 = dJointCreateDHinge(world, 0); dJointAttach(joint2, body1, body2); dJointSetDHingeAxis(joint2, 1, 0, 0); dJointSetDHingeAnchor1(joint2, 0, 0, 2.5); dJointSetDHingeAnchor2(joint2, 0, 0, 1.5); #else joint2 = dJointCreateDBall(world, 0); dJointAttach(joint2, body1, body2); dJointSetDBallAnchor1(joint2, 0, 0, 2.5); dJointSetDBallAnchor2(joint2, 0, 0, 1.5); #endif //dBodyAddForce(body1, 20, 0, 0); // initial camera position static float xyz[3] = {3.8966, -2.0614, 4.0300}; static float hpr[3] = {153.5, -16.5, 0}; dsSetViewpoint (xyz,hpr); } void stop() { dSpaceDestroy(space); dWorldDestroy(world); } void drawGeom(dGeomID g) { int gclass = dGeomGetClass(g); const dReal *pos = dGeomGetPosition(g); const dReal *rot = dGeomGetRotation(g); switch (gclass) { case dBoxClass: { dVector3 lengths; if (applyForce) dsSetColor(1, .5, 0); else dsSetColor(1, 1, 0); dsSetTexture (DS_WOOD); dGeomBoxGetLengths(g, lengths); dsDrawBox(pos, rot, lengths); break; } default: {} } } void simLoop(int pause) { if (!pause) { static dReal t = 0; const dReal step = 0.005; const unsigned nsteps = 2; for (unsigned i=0; i 2.; if (applyForce) { dReal f = 0.3 * sin(t*1.2); dBodyAddForceAtRelPos(body1, f, 0, 0, 0, 0, -0.5); // at the lower end dReal g = 0.3 * sin(t*0.7); dBodyAddForceAtRelPos(body2, 0, g, 0, 0, 0, -0.5); // at the lower end } t += step; if (t > 20.) t = 0.; dWorldQuickStep(world, step); } } // now we draw everything unsigned ngeoms = dSpaceGetNumGeoms(space); for (unsigned i=0; i #include #include #include "texturepath.h" #ifdef _MSC_VER #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints #endif // select correct drawing functions #ifdef dDOUBLE #define dsDrawBox dsDrawBoxD #define dsDrawSphere dsDrawSphereD #define dsDrawCylinder dsDrawCylinderD #define dsDrawCapsule dsDrawCapsuleD #endif // some constants #define NUM 10000 // max number of objects #define DENSITY (5.0) // density of all objects #define GPB 3 // maximum number of geometries per body #define MAX_CONTACTS 4 // maximum number of contact points per body #define WORLD_SIZE 20 #define WORLD_HEIGHT 20 // dynamics and collision objects struct MyObject { dBodyID body; // the body dGeomID geom[GPB]; // geometries representing this body }; static int num=0; // number of objects in simulation static int nextobj=0; // next object to recycle if num==NUM static dWorldID world; static dSpaceID space = NULL; static MyObject obj[NUM]; static dJointGroupID contactgroup; static int selected = -1; // selected object static int show_aabb = 0; // show geom AABBs? static int show_contacts = 0; // show contact points? static int random_pos = 1; // drop objects from random position? static int draw_geom = 1; // this is called by dSpaceCollide when two objects in space are // potentially colliding. static void nearCallback (void *, dGeomID o1, dGeomID o2) { int i; // if (o1->body && o2->body) return; // exit without doing anything if the two bodies are connected by a joint dBodyID b1 = dGeomGetBody(o1); dBodyID b2 = dGeomGetBody(o2); if (b1 && b2 && dAreConnectedExcluding (b1,b2,dJointTypeContact)) return; dContact contact[MAX_CONTACTS]; // up to MAX_CONTACTS contacts per box-box for (i=0; i= 'A' && c <= 'Z') return c - ('a'-'A'); else return c; } // called when a key pressed static void command (int cmd) { int i,j,k; dReal sides[3]; dMass m; bool setBody = false; cmd = locase(cmd); if (cmd == 'b' || cmd == 's' || cmd == 'c' || cmd == 'x' || cmd == 'y') { if (num < NUM) { // new object to be created i = num; num++; } else { // recycle existing object i = nextobj++; nextobj %= num; // wrap-around if needed // destroy the body and geoms for slot i dBodyDestroy (obj[i].body); obj[i].body = 0; for (k=0; k < GPB; k++) if (obj[i].geom[k]) { dGeomDestroy(obj[i].geom[k]); obj[i].geom[k] = 0; } } obj[i].body = dBodyCreate(world); for (k=0; k<3; k++) sides[k] = dRandReal()*0.5+0.1; dMatrix3 R; if (random_pos) { dBodySetPosition(obj[i].body, dRandReal()*2-1,dRandReal()*2-1,dRandReal()+2); dRFromAxisAndAngle(R,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0, dRandReal()*2.0-1.0,dRandReal()*10.0-5.0); } else { // higher than highest body position dReal maxheight = 0; for (k=0; k maxheight) maxheight = pos[2]; } dBodySetPosition(obj[i].body, 0,0,maxheight+1); dRSetIdentity(R); //dRFromAxisAndAngle (R,0,0,1,/*dRandReal()*10.0-5.0*/0); } dBodySetRotation(obj[i].body,R); if (cmd == 'b') { dMassSetBox(&m,DENSITY,sides[0],sides[1],sides[2]); obj[i].geom[0] = dCreateBox(space,sides[0],sides[1],sides[2]); } else if (cmd == 'c') { sides[0] *= 0.5; dMassSetCapsule(&m,DENSITY,3,sides[0],sides[1]); obj[i].geom[0] = dCreateCapsule (space,sides[0],sides[1]); } else if (cmd == 'y') { dMassSetCylinder(&m,DENSITY,3,sides[0],sides[1]); obj[i].geom[0] = dCreateCylinder(space,sides[0],sides[1]); } else if (cmd == 's') { sides[0] *= 0.5; dMassSetSphere (&m,DENSITY,sides[0]); obj[i].geom[0] = dCreateSphere (space,sides[0]); } else if (cmd == 'x') { setBody = true; // start accumulating masses for the composite geometries dMass m2; dMassSetZero (&m); dReal dpos[GPB][3]; // delta-positions for composite geometries dMatrix3 drot[GPB]; // set random delta positions for (j=0; j= num) selected = 0; if (selected < 0) selected = 0; } else if (cmd == 'd' && selected >= 0 && selected < num) { dBodyDisable (obj[selected].body); } else if (cmd == 'e' && selected >= 0 && selected < num) { dBodyEnable (obj[selected].body); } else if (cmd == 'a') { show_aabb ^= 1; } else if (cmd == 't') { show_contacts ^= 1; } else if (cmd == 'r') { random_pos ^= 1; } else if (cmd == 'o') { draw_geom ^= 1; } } // draw a geom void drawGeom (dGeomID g, const dReal *pos, const dReal *R, int show_aabb) { if (!draw_geom){ return; } if (!g) return; if (!pos) pos = dGeomGetPosition(g); if (!R) R = dGeomGetRotation(g); int type = dGeomGetClass (g); if (type == dBoxClass) { dVector3 sides; dGeomBoxGetLengths(g,sides); dsDrawBox(pos,R,sides); } else if (type == dSphereClass) { dsDrawSphere(pos,R,dGeomSphereGetRadius (g)); } else if (type == dCapsuleClass) { dReal radius,length; dGeomCapsuleGetParams(g,&radius,&length); dsDrawCapsule (pos,R,length,radius); } else if (type == dCylinderClass) { dReal radius,length; dGeomCylinderGetParams(g,&radius,&length); dsDrawCylinder(pos,R,length,radius); } if (show_aabb) { // draw the bounding box for this geom dReal aabb[6]; dGeomGetAABB(g,aabb); dVector3 bbpos; for (int i=0; i<3; i++) bbpos[i] = 0.5*(aabb[i*2] + aabb[i*2+1]); dVector3 bbsides; for (int j=0; j<3; j++) bbsides[j] = aabb[j*2+1] - aabb[j*2]; dMatrix3 RI; dRSetIdentity(RI); dsSetColorAlpha(1,0,0,0.5); dsDrawBox(bbpos,RI,bbsides); } } // simulation loop static void simLoop (int pause) { dsSetColor (0,0,2); dSpaceCollide (space,0,&nearCallback); //if (!pause) dWorldStep (world,0.05); if (!pause) dWorldQuickStep (world,0.05); //if (!pause) dWorldStepFast (world,0.05, 1); // remove all contact joints dJointGroupEmpty (contactgroup); dsSetColor (1,1,0); dsSetTexture (DS_WOOD); for (int i=0; i #include #include "texturepath.h" #ifdef dDOUBLE #define dsDrawSphere dsDrawSphereD #define dsDrawBox dsDrawBoxD #define dsDrawLine dsDrawLineD #endif dWorldID world; dSpaceID space; dBodyID body1; dBodyID body2; dJointID joint1, joint2; void start() { world = dWorldCreate(); dWorldSetGravity (world,0,0,-9.8); dWorldSetDamping(world, 1e-4, 1e-5); // dWorldSetERP(world, 1); space = dSimpleSpaceCreate (0); body1 = dBodyCreate(world); body2 = dBodyCreate(world); dBodySetPosition(body1, 0, 0, 3); dBodySetPosition(body2, 0, 0, 1); dGeomID g; dMass mass; g = dCreateBox(space, 0.2, 0.2, 1); dGeomSetBody(g, body1); dMassSetBox(&mass, 1, 0.2, 0.2, 1); dBodySetMass(body1, &mass); g = dCreateBox(space, 0.2, 0.2, 1); dGeomSetBody(g, body2); dMassSetBox(&mass, 1, 0.2, 0.2, 1); dBodySetMass(body2, &mass); joint1 = dJointCreateDBall(world, 0); dJointAttach(joint1, body1, 0); dJointSetDBallAnchor1(joint1, 0, 0, 3.5); dJointSetDBallAnchor2(joint1, 0, 0, 4.5); joint2 = dJointCreateDBall(world, 0); dJointAttach(joint2, body1, body2); dJointSetDBallAnchor1(joint2, 0, 0, 2.5); dJointSetDBallAnchor2(joint2, 0, 0, 1.5); // initial camera position static float xyz[3] = {3.8966, -2.0614, 4.0300}; static float hpr[3] = {153.5, -16.5, 0}; dsSetViewpoint (xyz,hpr); } void stop() { dSpaceDestroy(space); dWorldDestroy(world); } void drawGeom(dGeomID g) { int gclass = dGeomGetClass(g); const dReal *pos = dGeomGetPosition(g); const dReal *rot = dGeomGetRotation(g); switch (gclass) { case dSphereClass: dsSetColorAlpha(0, 0.75, 0.5, 1); dsSetTexture (DS_CHECKERED); dsDrawSphere(pos, rot, dGeomSphereGetRadius(g)); break; case dBoxClass: { dVector3 lengths; dsSetColorAlpha(1, 1, 0, 1); dsSetTexture (DS_WOOD); dGeomBoxGetLengths(g, lengths); dsDrawBox(pos, rot, lengths); break; } default: {} } } void simLoop(int pause) { if (!pause) { static dReal t = 0; const dReal step = 0.005; const unsigned nsteps = 4; for (unsigned i=0; i #include #include "texturepath.h" #ifdef _MSC_VER #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints #endif // select correct drawing functions #ifdef dDOUBLE #define dsDrawBox dsDrawBoxD #define dsDrawSphere dsDrawSphereD #define dsDrawCylinder dsDrawCylinderD #define dsDrawCapsule dsDrawCapsuleD #endif // some constants #define LENGTH 3.5 // chassis length #define WIDTH 2.5 // chassis width #define HEIGHT 1.0 // chassis height #define RADIUS 0.5 // wheel radius #define STARTZ 1.0 // starting height of chassis #define CMASS 1 // chassis mass #define WMASS 1 // wheel mass #define COMOFFSET -5 // center of mass offset #define WALLMASS 1 // wall box mass #define BALLMASS 1 // ball mass #define FMAX 25 // car engine fmax #define ROWS 1 // rows of cars #define COLS 1 // columns of cars #define ITERS 20 // number of iterations #define WBOXSIZE 1.0 // size of wall boxes #define WALLWIDTH 12 // width of wall #define WALLHEIGHT 10 // height of wall #define DISABLE_THRESHOLD 0.008 // maximum velocity (squared) a body can have and be disabled #define DISABLE_STEPS 10 // number of steps a box has to have been disable-able before it will be disabled #define CANNON_X -10 // x position of cannon #define CANNON_Y 5 // y position of cannon #define CANNON_BALL_MASS 10 // mass of the cannon ball #define CANNON_BALL_RADIUS 0.5 static const dVector3 xunit = { 1, 0, 0 }, yunit = { 0, 1, 0 }, zpunit = { 0, 0, 1 }, zmunit = { 0, 0, -1 }; //#define BOX #define CARS #define WALL //#define BALLS //#define BALLSTACK //#define ONEBALL //#define CENTIPEDE #define CANNON // dynamics and collision objects (chassis, 3 wheels, environment) static dWorldID world; static dSpaceID space; static dThreadingImplementationID threading; static dThreadingThreadPoolID pool; static dBodyID body[10000]; static int bodies; static dJointID joint[100000]; static int joints; static dJointGroupID contactgroup; static dGeomID ground; static dGeomID box[10000]; static int boxes; static dGeomID sphere[10000]; static int spheres; static dGeomID wall_boxes[10000]; static dBodyID wall_bodies[10000]; static dGeomID cannon_ball_geom; static dBodyID cannon_ball_body; static int wb_stepsdis[10000]; static int wb; static bool doFast; static dBodyID b; static dMass m; // things that the user controls static dReal turn = 0, speed = 0; // user commands static dReal cannon_angle=0,cannon_elevation=-1.2; // this is called by dSpaceCollide when two objects in space are // potentially colliding. static void nearCallback (void *, dGeomID o1, dGeomID o2) { int i,n; dBodyID b1 = dGeomGetBody(o1); dBodyID b2 = dGeomGetBody(o2); if (b1 && b2 && dAreConnected(b1, b2)) return; const int N = 4; dContact contact[N]; n = dCollide (o1,o2,N,&contact[0].geom,sizeof(dContact)); if (n > 0) { for (i=0; i -20; x-=RADIUS*2) { body[bodies] = dBodyCreate (world); dBodySetPosition(body[bodies], x, y, STARTZ); dMassSetSphere(&m, 1, RADIUS); dMassAdjust(&m, WMASS); dBodySetMass(body[bodies], &m); sphere[spheres] = dCreateSphere (space, RADIUS); dGeomSetBody (sphere[spheres++], body[bodies]); joint[joints] = dJointCreateHinge2 (world,0); if (x == -17) dJointAttach (joint[joints],b,body[bodies]); else dJointAttach (joint[joints],body[bodies-2],body[bodies]); const dReal *a = dBodyGetPosition (body[bodies++]); dJointSetHinge2Anchor (joint[joints],a[0],a[1],a[2]); dJointSetHinge2Axes (joint[joints], zpunit, xunit); dJointSetHinge2Param (joint[joints],dParamSuspensionERP,1.0); dJointSetHinge2Param (joint[joints],dParamSuspensionCFM,1e-5); dJointSetHinge2Param (joint[joints],dParamLoStop,0); dJointSetHinge2Param (joint[joints],dParamHiStop,0); dJointSetHinge2Param (joint[joints],dParamVel2,-10.0); dJointSetHinge2Param (joint[joints++],dParamFMax2,FMAX); body[bodies] = dBodyCreate (world); dBodySetPosition(body[bodies], -30 - x, y, STARTZ); dMassSetSphere(&m, 1, RADIUS); dMassAdjust(&m, WMASS); dBodySetMass(body[bodies], &m); sphere[spheres] = dCreateSphere (space, RADIUS); dGeomSetBody (sphere[spheres++], body[bodies]); joint[joints] = dJointCreateHinge2 (world,0); if (x == -17) dJointAttach (joint[joints],b,body[bodies]); else dJointAttach (joint[joints],body[bodies-2],body[bodies]); const dReal *b = dBodyGetPosition (body[bodies++]); dJointSetHinge2Anchor (joint[joints],b[0],b[1],b[2]); dJointSetHinge2Axes (joint[joints], zpunit, xunit); dJointSetHinge2Param (joint[joints],dParamSuspensionERP,1.0); dJointSetHinge2Param (joint[joints],dParamSuspensionCFM,1e-5); dJointSetHinge2Param (joint[joints],dParamLoStop,0); dJointSetHinge2Param (joint[joints],dParamHiStop,0); dJointSetHinge2Param (joint[joints],dParamVel2,10.0); dJointSetHinge2Param (joint[joints++],dParamFMax2,FMAX); } if (lastb) { dJointID j = dJointCreateFixed(world,0); dJointAttach (j, b, lastb); dJointSetFixed(j); } lastb = b; } #endif #ifdef BOX body[bodies] = dBodyCreate (world); dBodySetPosition (body[bodies],0,0,HEIGHT/2); dMassSetBox (&m,1,LENGTH,WIDTH,HEIGHT); dMassAdjust (&m, 1); dBodySetMass (body[bodies],&m); box[boxes] = dCreateBox (space,LENGTH,WIDTH,HEIGHT); dGeomSetBody (box[boxes++],body[bodies++]); #endif #ifdef CANNON cannon_ball_body = dBodyCreate (world); cannon_ball_geom = dCreateSphere (space,CANNON_BALL_RADIUS); dMassSetSphereTotal (&m,CANNON_BALL_MASS,CANNON_BALL_RADIUS); dBodySetMass (cannon_ball_body,&m); dGeomSetBody (cannon_ball_geom,cannon_ball_body); dBodySetPosition (cannon_ball_body,CANNON_X,CANNON_Y,CANNON_BALL_RADIUS); #endif } // called when a key pressed static void command (int cmd) { switch (cmd) { case 'a': case 'A': speed += 0.3; break; case 'z': case 'Z': speed -= 0.3; break; case ',': turn += 0.1; if (turn > 0.3) turn = 0.3; break; case '.': turn -= 0.1; if (turn < -0.3) turn = -0.3; break; case ' ': speed = 0; turn = 0; break; case 'f': case 'F': doFast = !doFast; break; case 'r': case 'R': shutdownSimulation(); setupSimulation(); break; case '[': cannon_angle += 0.1; break; case ']': cannon_angle -= 0.1; break; case '1': cannon_elevation += 0.1; break; case '2': cannon_elevation -= 0.1; break; case 'x': case 'X': { dMatrix3 R2,R3,R4; dRFromAxisAndAngle (R2,0,0,1,cannon_angle); dRFromAxisAndAngle (R3,0,1,0,cannon_elevation); dMultiply0 (R4,R2,R3,3,3,3); dReal cpos[3] = {CANNON_X,CANNON_Y,1}; for (int i=0; i<3; i++) cpos[i] += 3*R4[i*4+2]; dBodySetPosition (cannon_ball_body,cpos[0],cpos[1],cpos[2]); dReal force = 10; dBodySetLinearVel (cannon_ball_body,force*R4[2],force*R4[6],force*R4[10]); dBodySetAngularVel (cannon_ball_body,0,0,0); break; } } } // simulation loop static void simLoop (int pause) { int i, j; dsSetTexture (DS_WOOD); if (!pause) { #ifdef BOX dBodyAddForce(body[bodies-1],lspeed,0,0); #endif for (j = 0; j < joints; j++) { dReal curturn = dJointGetHinge2Angle1 (joint[j]); //dMessage (0,"curturn %e, turn %e, vel %e", curturn, turn, (turn-curturn)*1.0); dJointSetHinge2Param(joint[j],dParamVel,(turn-curturn)*1.0); dJointSetHinge2Param(joint[j],dParamFMax,dInfinity); dJointSetHinge2Param(joint[j],dParamVel2,speed); dJointSetHinge2Param(joint[j],dParamFMax2,FMAX); dBodyEnable(dJointGetBody(joint[j],0)); dBodyEnable(dJointGetBody(joint[j],1)); } if (doFast) { dSpaceCollide (space,0,&nearCallback); dWorldQuickStep (world,0.05); dJointGroupEmpty (contactgroup); } else { dSpaceCollide (space,0,&nearCallback); dWorldStep (world,0.05); dJointGroupEmpty (contactgroup); } for (i = 0; i < wb; i++) { b = dGeomGetBody(wall_boxes[i]); if (dBodyIsEnabled(b)) { bool disable = true; const dReal *lvel = dBodyGetLinearVel(b); dReal lspeed = lvel[0]*lvel[0]+lvel[1]*lvel[1]+lvel[2]*lvel[2]; if (lspeed > DISABLE_THRESHOLD) disable = false; const dReal *avel = dBodyGetAngularVel(b); dReal aspeed = avel[0]*avel[0]+avel[1]*avel[1]+avel[2]*avel[2]; if (aspeed > DISABLE_THRESHOLD) disable = false; if (disable) wb_stepsdis[i]++; else wb_stepsdis[i] = 0; if (wb_stepsdis[i] > DISABLE_STEPS) { dBodyDisable(b); dsSetColor(0.5,0.5,1); } else dsSetColor(1,1,1); } else dsSetColor(0.4,0.4,0.4); dVector3 ss; dGeomBoxGetLengths (wall_boxes[i], ss); dsDrawBox(dGeomGetPosition(wall_boxes[i]), dGeomGetRotation(wall_boxes[i]), ss); } } else { for (i = 0; i < wb; i++) { b = dGeomGetBody(wall_boxes[i]); if (dBodyIsEnabled(b)) dsSetColor(1,1,1); else dsSetColor(0.4,0.4,0.4); dVector3 ss; dGeomBoxGetLengths (wall_boxes[i], ss); dsDrawBox(dGeomGetPosition(wall_boxes[i]), dGeomGetRotation(wall_boxes[i]), ss); } } dsSetColor (0,1,1); dReal sides[3] = {LENGTH,WIDTH,HEIGHT}; for (i = 0; i < boxes; i++) dsDrawBox (dGeomGetPosition(box[i]),dGeomGetRotation(box[i]),sides); dsSetColor (1,1,1); for (i=0; i< spheres; i++) dsDrawSphere (dGeomGetPosition(sphere[i]), dGeomGetRotation(sphere[i]),RADIUS); // draw the cannon dsSetColor (1,1,0); dMatrix3 R2,R3,R4; dRFromAxisAndAngle (R2,0,0,1,cannon_angle); dRFromAxisAndAngle (R3,0,1,0,cannon_elevation); dMultiply0 (R4,R2,R3,3,3,3); dReal cpos[3] = {CANNON_X,CANNON_Y,1}; dReal csides[3] = {2,2,2}; dsDrawBox (cpos,R2,csides); for (i=0; i<3; i++) cpos[i] += 1.5*R4[i*4+2]; dsDrawCylinder (cpos,R4,3,0.5); // draw the cannon ball dsDrawSphere (dBodyGetPosition(cannon_ball_body),dBodyGetRotation(cannon_ball_body), CANNON_BALL_RADIUS); } int main (int argc, char **argv) { doFast = true; // setup pointers to drawstuff callback functions dsFunctions fn; fn.version = DS_VERSION; fn.start = &start; fn.step = &simLoop; fn.command = &command; fn.stop = 0; fn.path_to_textures = DRAWSTUFF_TEXTURE_PATH; dInitODE2(0); bodies = 0; joints = 0; boxes = 0; spheres = 0; setupSimulation(); dThreadingImplementationID threading = dThreadingAllocateMultiThreadedImplementation(); dThreadingThreadPoolID pool = dThreadingAllocateThreadPool(8, 0, dAllocateFlagBasicData, NULL); dThreadingThreadPoolServeMultiThreadedImplementation(pool, threading); // dWorldSetStepIslandsProcessingMaxThreadCount(world, 1); dWorldSetStepThreadingImplementation(world, dThreadingImplementationGetFunctions(threading), threading); // run simulation dsSimulationLoop (argc,argv,352,288,&fn); dThreadingImplementationShutdownProcessing(threading); dThreadingFreeThreadPool(pool); dWorldSetStepThreadingImplementation(world, NULL, NULL); dThreadingFreeImplementation(threading); shutdownSimulation(); dCloseODE(); return 0; } ode-0.16/ode/demo/demo_chain2.cpp0000664000175200017520000001130613403272463013512 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* exercise the C++ interface */ #include #include #include "texturepath.h" #ifdef _MSC_VER #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints #endif // select correct drawing functions #ifdef dDOUBLE #define dsDrawBox dsDrawBoxD #define dsDrawSphere dsDrawSphereD #define dsDrawCylinder dsDrawCylinderD #define dsDrawCapsule dsDrawCapsuleD #endif // some constants #define NUM 10 // number of boxes #define SIDE (0.2) // side length of a box #define MASS (1.0) // mass of a box #define RADIUS (0.1732f) // sphere radius //using namespace ode; // dynamics and collision objects static dWorld world; static dSimpleSpace space (0); static dBody body[NUM]; static dBallJoint joint[NUM-1]; static dJointGroup contactgroup; static dBox box[NUM]; // this is called by space.collide when two objects in space are // potentially colliding. static void nearCallback (void *, dGeomID o1, dGeomID o2) { // exit without doing anything if the two bodies are connected by a joint dBodyID b1 = dGeomGetBody(o1); dBodyID b2 = dGeomGetBody(o2); if (b1 && b2 && dAreConnected (b1,b2)) return; // @@@ it's still more convenient to use the C interface here. dContact contact; contact.surface.mode = 0; contact.surface.mu = dInfinity; if (dCollide (o1,o2,1,&contact.geom,sizeof(dContactGeom))) { dJointID c = dJointCreateContact (world.id(),contactgroup.id(),&contact); dJointAttach (c,b1,b2); } } // start simulation - set viewpoint static void start() { dAllocateODEDataForThread(dAllocateMaskAll); static float xyz[3] = {2.1640f,-1.3079f,1.7600f}; static float hpr[3] = {125.5000f,-17.0000f,0.0000f}; dsSetViewpoint (xyz,hpr); } // simulation loop static void simLoop (int pause) { if (!pause) { static double angle = 0; angle += 0.05; body[NUM-1].addForce (0,0,1.5*(sin(angle)+1.0)); space.collide (0,&nearCallback); world.step (0.05); // remove all contact joints contactgroup.empty(); } dReal sides[3] = {SIDE,SIDE,SIDE}; dsSetColor (1,1,0); dsSetTexture (DS_WOOD); for (int i=0; i #ifdef HAVE_UNISTD_H # include #endif #include #include #include "texturepath.h" #include "halton235_geom.h" #ifdef dDOUBLE # define dsDrawConvex dsDrawConvexD # define dsDrawLine dsDrawLineD #endif #ifdef _MSC_VER # pragma warning(disable:4244 4305) // for VC++, no precision loss complaints #endif // Height at which we drop the composite block. const dReal H=4.20; static dWorldID world; static dSpaceID space; static dBodyID mbody; static dBodyID hbody[ halton_numc ]; static dGeomID hgeom[ halton_numc ]; static dJointGroupID contactgroup; static bool drawpos=false; static bool solidkernel=false; // this is called by dSpaceCollide when two objects in space are // potentially colliding. static void nearCallback(void *data, dGeomID o1, dGeomID o2) { assert(o1); assert(o2); if (dGeomIsSpace(o1) || dGeomIsSpace(o2)) { // colliding a space with something dSpaceCollide2(o1,o2,data,&nearCallback); // Note we do not want to test intersections within a space, // only between spaces. return; } const int N = 32; dContact contact[N]; int n = dCollide (o1,o2,N,&(contact[0].geom),sizeof(dContact)); if (n > 0) { for (int i=0; i 8 ? 8 : nrofsteps; for (int i=0; i #include #include "texturepath.h" #ifdef _MSC_VER #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints #endif // select correct drawing functions #ifdef dDOUBLE #define dsDrawBox dsDrawBoxD #define dsDrawSphere dsDrawSphereD #define dsDrawCylinder dsDrawCylinderD #define dsDrawCapsule dsDrawCapsuleD #endif // dynamics and collision objects static dWorldID world = 0; static const dReal dt = 1/REAL(60.0); // 60 fps // Water density if units are meters and kg static const dReal density = 1000; // A long skinny thing static dVector3 sides = {2,.5,.25}; // Initial angular velocity static dVector3 omega = {5,1,2}; static dVector3 torque = {0,10,0}; static dBodyID noGyroBody; static dBodyID expGyroBody; static dBodyID impGyroBody; // start simulation - set viewpoint static void start() { dAllocateODEDataForThread(dAllocateMaskAll); static float xyz[3] = {0,-4.0f,3.0f}; static float hpr[3] = {90.0000,-15.0000,0.0000}; dsSetViewpoint (xyz,hpr); printf ("Press:\n" "\t'a' to apply a torque\n" "\t'r' to reset simulation.\n"); } /** Delete the bodies, etc. */ static void clear() { if (world) dWorldDestroy (world); world = 0; } /** Cleanup if necessary and rebuild the world. */ static void reset() { clear(); // create world world = dWorldCreate(); // Calculate mass for a box; dMass boxMass; dMassSetBox(&boxMass,density,sides[0],sides[1],sides[2]); noGyroBody = dBodyCreate(world);// Conservation of ang-velocity expGyroBody = dBodyCreate(world);// Explicit conservation of ang-momentum impGyroBody = dBodyCreate(world);// Implicit conservation of ang-momentum dBodySetMass( noGyroBody , &boxMass ); dBodySetMass( expGyroBody, &boxMass ); dBodySetMass( impGyroBody, &boxMass ); // Try to avoid collisions. dReal sep = dCalcVectorLength3(sides); dBodySetPosition( noGyroBody , -sep, 0, sep); dBodySetPosition( expGyroBody, 0, 0, sep); dBodySetPosition( impGyroBody, sep, 0, sep); // Set the initial angular velocity dBodySetAngularVel( noGyroBody , omega[0], omega[1], omega[2]); dBodySetAngularVel( expGyroBody, omega[0], omega[1], omega[2]); dBodySetAngularVel( impGyroBody, omega[0], omega[1], omega[2]); dBodySetGyroscopicMode( noGyroBody, 0); // We compute this ourselves using the math // that was in the old stepper. dBodySetGyroscopicMode(expGyroBody, 0); // Keep things from crashing by limiting // the angular speed of the explicit body. // Note that this isn't necessary for // the other two bodies. dBodySetMaxAngularSpeed( expGyroBody, 40 ); } static void command (int cmd) { switch (cmd) { case 'a': case 'A': dBodyAddTorque( noGyroBody, torque[0], torque[1], torque[2]); dBodyAddTorque(expGyroBody, torque[0], torque[1], torque[2]); dBodyAddTorque(impGyroBody, torque[0], torque[1], torque[2]); break; case 'r': case 'R': reset(); break; } } /** This is the explicit computation of gyroscopic forces. */ static void expStep(dBodyID body) { // Explicit computation dMatrix3 I,tmp; dMass m; dBodyGetMass(body,&m); const dReal* R = dBodyGetRotation(body); // compute inertia tensor in global frame dMultiply2_333 (tmp,m.I,R); dMultiply0_333 (I,R,tmp); // compute explicit rotational force // we treat 'tmp'like a vector, but that's okay. const dReal* w = dBodyGetAngularVel(body); dMultiply0_331 (tmp,I,w); dVector3 tau; dCalcVectorCross3(tau,tmp,w); dBodyAddTorque(body,tau[0],tau[1],tau[2]); } // simulation loop static void simLoop (int pause) { if (!pause) { expStep(expGyroBody); dWorldStep (world,dt); } dsSetTexture (DS_WOOD); dsSetColor(1,0,0); dsDrawBox(dBodyGetPosition(noGyroBody ),dBodyGetRotation(noGyroBody ),sides); dsSetColor(1,1,0); dsDrawBox(dBodyGetPosition(expGyroBody),dBodyGetRotation(expGyroBody),sides); dsSetColor(0,1,0); dsDrawBox(dBodyGetPosition(impGyroBody),dBodyGetRotation(impGyroBody),sides); } int main (int argc, char **argv) { // setup pointers to drawstuff callback functions dsFunctions fn; fn.version = DS_VERSION; fn.start = &start; fn.step = &simLoop; fn.command = &command; fn.stop = 0; fn.path_to_textures = DRAWSTUFF_TEXTURE_PATH; dInitODE2(0); reset(); // run simulation dsSimulationLoop (argc,argv,352,288,&fn); clear(); dCloseODE(); return 0; } ode-0.16/ode/demo/demo_feedback.cpp0000664000175200017520000002110513403272463014070 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ // Test for breaking joints, by Bram Stolk #include #include #ifdef HAVE_UNISTD_H #include #endif #include #include #include "texturepath.h" #ifdef _MSC_VER #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints #endif #ifdef dDOUBLE #define dsDrawBox dsDrawBoxD #define dsDrawCylinder dsDrawCylinderD #endif // dynamics and collision objects (chassis, 3 wheels, environment) static dWorldID world; static dSpaceID space; static const int STACKCNT=10; // nr of weights on bridge static const int SEGMCNT=16; // nr of segments in bridge static const float SEGMDIM[3] = { 0.9, 4, 0.1 }; static dGeomID groundgeom; static dBodyID segbodies[SEGMCNT]; static dGeomID seggeoms[SEGMCNT]; static dBodyID stackbodies[STACKCNT]; static dGeomID stackgeoms[STACKCNT]; static dJointID hinges[SEGMCNT-1]; static dJointID sliders[2]; static dJointFeedback jfeedbacks[SEGMCNT-1]; static dReal colours[SEGMCNT]; static int stress[SEGMCNT-1]; static dJointGroupID contactgroup; // this is called by dSpaceCollide when two objects in space are // potentially colliding. static void nearCallback (void *data, dGeomID o1, dGeomID o2) { assert(o1); assert(o2); if (dGeomIsSpace(o1) || dGeomIsSpace(o2)) { fprintf(stderr,"testing space %p %p\n", (void*)o1, (void*)o2); // colliding a space with something dSpaceCollide2(o1,o2,data,&nearCallback); // Note we do not want to test intersections within a space, // only between spaces. return; } const int N = 32; dContact contact[N]; int n = dCollide (o1,o2,N,&(contact[0].geom),sizeof(dContact)); if (n > 0) { for (int i=0; i forcelimit || l1 > forcelimit) stress[i]++; else stress[i]=0; if (stress[i]>4) { // Low-pass filter the noisy feedback data. // Only after 4 consecutive timesteps with excessive load, snap. fprintf(stderr,"SNAP! (that was the sound of joint %d breaking)\n", i); dJointAttach (hinges[i], 0, 0); } } } } // simulation loop static void simLoop (int pause) { int i; double simstep = 0.002; // 2ms simulation steps double dt = dsElapsedTime(); int nrofsteps = (int) ceilf(dt/simstep); for (i=0; i1.0) v=1.0; if (v<0.5) { r=2*v; g=1.0; } else { r=1.0; g=2*(1.0-v); } dsSetColor (r,g,b); drawGeom(seggeoms[i]); } dsSetColor (1,1,1); for (i=0; i #include #include "texturepath.h" #include "bunny_geom.h" #ifdef _MSC_VER #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints #endif //<---- Convex Object static const dReal planes[] = // planes for a cube { 1.0f ,0.0f ,0.0f ,0.25f, 0.0f ,1.0f ,0.0f ,0.25f, 0.0f ,0.0f ,1.0f ,0.25f, 0.0f ,0.0f ,-1.0f,0.25f, 0.0f ,-1.0f,0.0f ,0.25f, -1.0f,0.0f ,0.0f ,0.25f /* 1.0f ,0.0f ,0.0f ,2.0f, 0.0f ,1.0f ,0.0f ,1.0f, 0.0f ,0.0f ,1.0f ,1.0f, 0.0f ,0.0f ,-1.0f,1.0f, 0.0f ,-1.0f,0.0f ,1.0f, -1.0f,0.0f ,0.0f ,0.0f */ }; static const unsigned int planecount=6; static const dReal points[] = // points for a cube { 0.25f,0.25f,0.25f, -0.25f,0.25f,0.25f, 0.25f,-0.25f,0.25f, -0.25f,-0.25f,0.25f, 0.25f,0.25f,-0.25f, -0.25f,0.25f,-0.25f, 0.25f,-0.25f,-0.25f, -0.25f,-0.25f,-0.25f, }; static const unsigned int pointcount=8; static const unsigned int polygons[] = //Polygons for a cube (6 squares) { 4,0,2,6,4, // positive X 4,1,0,4,5, // positive Y 4,0,1,3,2, // positive Z 4,3,1,5,7, // negative X 4,2,3,7,6, // negative Y 4,5,4,6,7, // negative Z }; //----> Convex Object int tmTriangles[] = { 0,2,6, 0,6,4, 1,0,4, 1,4,5, 0,1,3, 0,3,2, 3,1,5, 3,5,7, 2,3,7, 2,7,6, 5,4,6, 5,6,7 }; float tmVertices[] = { 0.25f,0.25f,0.25f, // point 0 -0.25f,0.25f,0.25f, // point 1 0.25f,-0.25f,0.25f, // point 2 -0.25f,-0.25f,0.25f,// point 3 0.25f,0.25f,-0.25f, // point 4 -0.25f,0.25f,-0.25f,// point 5 0.25f,-0.25f,-0.25f,// point 6 -0.25f,-0.25f,-0.25f,// point 7 }; // select correct drawing functions #ifdef dDOUBLE #define dsDrawBox dsDrawBoxD #define dsDrawSphere dsDrawSphereD #define dsDrawCylinder dsDrawCylinderD #define dsDrawCapsule dsDrawCapsuleD #define dsDrawLine dsDrawLineD #define dsDrawTriangle dsDrawTriangleD #define dsDrawConvex dsDrawConvexD #endif // some constants #define NUM 200 // max number of objects #define DENSITY (5.0) // density of all objects #define GPB 3 // maximum number of geometries per body #define MAX_CONTACTS 64 // maximum number of contact points per body // dynamics and collision objects struct MyObject { dBodyID body; // the body dGeomID geom[GPB]; // geometries representing this body // Trimesh only - double buffered matrices for 'last transform' setup dReal matrix_dblbuff[ 16 * 2 ]; int last_matrix_index; }; static int num=0; // number of objects in simulation static int nextobj=0; // next object to recycle if num==NUM static dWorldID world; static dSpaceID space; static MyObject obj[NUM]; static dJointGroupID contactgroup; static int selected = -1; // selected object static int show_aabb = 0; // show geom AABBs? static int show_contacts = 0; // show contact points? static int random_pos = 1; // drop objects from random position? typedef dReal dVector3R[3]; dGeomID TriMesh1; dGeomID TriMesh2; static dTriMeshDataID TriData1, TriData2; // reusable static trimesh data // this is called by dSpaceCollide when two objects in space are // potentially colliding. static void nearCallback (void *, dGeomID o1, dGeomID o2) { int i; // if (o1->body && o2->body) return; // exit without doing anything if the two bodies are connected by a joint dBodyID b1 = dGeomGetBody(o1); dBodyID b2 = dGeomGetBody(o2); if (b1 && b2 && dAreConnectedExcluding (b1,b2,dJointTypeContact)) return; dContact contact[MAX_CONTACTS]; // up to MAX_CONTACTS contacts per box-box for (i=0; i= 'A' && c <= 'Z') return c - ('a'-'A'); else return c; } // called when a key pressed static void command (int cmd) { int i,j,k; dReal sides[3]; dMass m; bool setBody = false; cmd = locase (cmd); if (cmd == 'b' || cmd == 's' || cmd == 'c' || cmd == 'x' || cmd == 'm' || cmd == 'y' || cmd == 'v') { if (num < NUM) { i = num; num++; } else { i = nextobj; nextobj++; if (nextobj >= num) nextobj = 0; // destroy the body and geoms for slot i dBodyDestroy (obj[i].body); for (k=0; k < GPB; k++) { if (obj[i].geom[k]) dGeomDestroy (obj[i].geom[k]); } memset (&obj[i],0,sizeof(obj[i])); } obj[i].body = dBodyCreate (world); for (k=0; k<3; k++) sides[k] = dRandReal()*0.5+0.1; dMatrix3 R; if (random_pos) { dBodySetPosition (obj[i].body, dRandReal()*2-1,dRandReal()*2-1,dRandReal()+3); dRFromAxisAndAngle (R,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0, dRandReal()*2.0-1.0,dRandReal()*10.0-5.0); } else { dReal maxheight = 0; for (k=0; k maxheight) maxheight = pos[2]; } dBodySetPosition (obj[i].body, 0,0,maxheight+1); dRFromAxisAndAngle (R,0,0,1,dRandReal()*10.0-5.0); } dBodySetRotation (obj[i].body,R); dBodySetData (obj[i].body,(void*)(dsizeint)i); if (cmd == 'b') { dMassSetBox (&m,DENSITY,sides[0],sides[1],sides[2]); obj[i].geom[0] = dCreateBox (space,sides[0],sides[1],sides[2]); } else if (cmd == 'c') { sides[0] *= 0.5; dMassSetCapsule (&m,DENSITY,3,sides[0],sides[1]); obj[i].geom[0] = dCreateCapsule (space,sides[0],sides[1]); } else if (cmd == 'v') { dMassSetBox (&m,DENSITY,0.25,0.25,0.25); obj[i].geom[0] = dCreateConvex(space, planes, planecount, points, pointcount, polygons); } else if (cmd == 'y') { sides[1] *= 0.5; dMassSetCylinder (&m,DENSITY,3,sides[0],sides[1]); obj[i].geom[0] = dCreateCylinder (space,sides[0],sides[1]); } else if (cmd == 's') { sides[0] *= 0.5; dMassSetSphere (&m,DENSITY,sides[0]); obj[i].geom[0] = dCreateSphere (space,sides[0]); } else if (cmd == 'm') { dTriMeshDataID new_tmdata = dGeomTriMeshDataCreate(); dGeomTriMeshDataBuildSingle(new_tmdata, &Vertices[0], 3 * sizeof(float), VertexCount, (dTriIndex*)&Indices[0], IndexCount, 3 * sizeof(dTriIndex)); dGeomTriMeshDataPreprocess2(new_tmdata, (1U << dTRIDATAPREPROCESS_BUILD_FACE_ANGLES), NULL); obj[i].geom[0] = dCreateTriMesh(space, new_tmdata, 0, 0, 0); // remember the mesh's dTriMeshDataID on its userdata for convenience. dGeomSetData(obj[i].geom[0], new_tmdata); dMassSetTrimesh( &m, DENSITY, obj[i].geom[0] ); printf("mass at %f %f %f\n", m.c[0], m.c[1], m.c[2]); dGeomSetPosition(obj[i].geom[0], -m.c[0], -m.c[1], -m.c[2]); dMassTranslate(&m, -m.c[0], -m.c[1], -m.c[2]); } else if (cmd == 'x') { setBody = true; // start accumulating masses for the composite geometries dMass m2; dMassSetZero (&m); dReal dpos[GPB][3]; // delta-positions for composite geometries dMatrix3 drot[GPB]; // set random delta positions for (j=0; j= num) selected = 0; if (selected < 0) selected = 0; } else if (cmd == 'd' && selected >= 0 && selected < num) { dBodyDisable (obj[selected].body); } else if (cmd == 'e' && selected >= 0 && selected < num) { dBodyEnable (obj[selected].body); } else if (cmd == 'a') { show_aabb ^= 1; } else if (cmd == 't') { show_contacts ^= 1; } else if (cmd == 'r') { random_pos ^= 1; } } // draw a geom void drawGeom (dGeomID g, const dReal *pos, const dReal *R, int show_aabb) { if (!g) return; if (!pos) pos = dGeomGetPosition (g); if (!R) R = dGeomGetRotation (g); int type = dGeomGetClass (g); if (type == dBoxClass) { dVector3 sides; dGeomBoxGetLengths (g,sides); dsDrawBox (pos,R,sides); } else if (type == dSphereClass) { dsDrawSphere (pos,R,dGeomSphereGetRadius (g)); } else if (type == dCapsuleClass) { dReal radius,length; dGeomCapsuleGetParams (g,&radius,&length); dsDrawCapsule (pos,R,length,radius); } else if (type == dCylinderClass) { dReal radius,length; dGeomCylinderGetParams (g,&radius,&length); dsDrawCylinder (pos,R,length,radius); } else if (type == dConvexClass) { //dVector3 sides={0.50,0.50,0.50}; dsDrawConvex(pos,R,planes, planecount, points, pointcount, polygons); } if (show_aabb) { // draw the bounding box for this geom dReal aabb[6]; dGeomGetAABB (g,aabb); dVector3 bbpos; for (int i=0; i<3; i++) bbpos[i] = 0.5*(aabb[i*2] + aabb[i*2+1]); dVector3 bbsides; for (int j=0; j<3; j++) bbsides[j] = aabb[j*2+1] - aabb[j*2]; dMatrix3 RI; dRSetIdentity (RI); dsSetColorAlpha (1,0,0,0.5); dsDrawBox (bbpos,RI,bbsides); } } // set previous transformation matrix for trimesh void setCurrentTransform(dGeomID geom) { const dReal* Pos = dGeomGetPosition(geom); const dReal* Rot = dGeomGetRotation(geom); const dReal Transform[16] = { Rot[0], Rot[4], Rot[8], 0, Rot[1], Rot[5], Rot[9], 0, Rot[2], Rot[6], Rot[10], 0, Pos[0], Pos[1], Pos[2], 1 }; dGeomTriMeshSetLastTransform( geom, *(dMatrix4*)(&Transform) ); } // simulation loop static void simLoop (int pause) { dsSetColor (0,0,2); dSpaceCollide (space,0,&nearCallback); #if 1 // What is this for??? - Bram if (!pause) { for (int i=0; i #include #include "texturepath.h" #ifdef dDOUBLE #define dsDrawCylinder dsDrawCylinderD #define dsDrawLine dsDrawLineD #define dsDrawSphere dsDrawSphereD #endif dReal theta = M_PI / 4; dReal ratio = 1, speed = 5, rho_1 = 1, rho_2 = 1, backlash = 0.1; int mode = 0; dWorldID world; dSpaceID space; dBodyID body1, body2; dGeomID geom1, geom2; dJointID hinge1, hinge2, transmission; dJointFeedback feedback; void setup() { dMatrix3 R; switch (mode) { case 0: // Parallel axes. dBodySetPosition(body1, 1, 0, 1); dBodySetPosition(body2, -1, 0, 1); dRSetIdentity (R); dBodySetRotation (body1, R); dBodySetRotation (body2, R); dJointSetHingeAnchor(hinge2, -1, 0, 1); dJointSetHingeAxis(hinge2, 0, 0, 1); dJointSetHingeAnchor(hinge1, 1, 0, 1); dJointSetHingeAxis(hinge1, 0, 0, 1); dJointSetTransmissionMode(transmission, dTransmissionParallelAxes); dJointSetTransmissionRatio(transmission, ratio); dJointSetTransmissionAnchor1(transmission, 1, 0, 1); dJointSetTransmissionAnchor2(transmission, -1, 0, 1); dJointSetTransmissionAxis(transmission, 0, 0, 1); break; case 1: // Intersecting axes. dBodySetPosition(body1, 1, 0, 1); dBodySetPosition(body2, -1, 0, 2); dRSetIdentity (R); dBodySetRotation (body1, R); dRFromZAxis (R, cos(theta), 0, sin(theta)); dBodySetRotation (body2, R); dJointSetHingeAnchor(hinge2, -1, 0, 2); dJointSetHingeAxis(hinge2, cos(theta), 0, sin(theta)); dJointSetHingeAnchor(hinge1, 1, 0, 1); dJointSetHingeAxis(hinge1, 0, 0, 1); dJointSetTransmissionMode(transmission, dTransmissionIntersectingAxes); dJointSetTransmissionAnchor1(transmission, 1, 0, 1); dJointSetTransmissionAnchor2(transmission, -1, 0, 2); dJointSetTransmissionAxis1(transmission, 0, 0, -1); dJointSetTransmissionAxis2(transmission, cos(theta), 0, sin(theta)); break; case 2: // Chain. dBodySetPosition(body1, 2, 0, 1); dBodySetPosition(body2, -2, 0, 1); dRSetIdentity (R); dBodySetRotation (body1, R); dBodySetRotation (body2, R); dJointSetHingeAnchor(hinge2, -2, 0, 1); dJointSetHingeAxis(hinge2, 0, 0, 1); dJointSetHingeAnchor(hinge1, 2, 0, 1); dJointSetHingeAxis(hinge1, 0, 0, 1); dJointSetTransmissionMode(transmission, dTransmissionChainDrive); dJointSetTransmissionAnchor1(transmission, 2, 0, 1); dJointSetTransmissionAnchor2(transmission, -2, 0, 1); dJointSetTransmissionRadius1(transmission, rho_1); dJointSetTransmissionRadius2(transmission, rho_2); dJointSetTransmissionAxis(transmission, 0, 0, 1); break; } dJointSetTransmissionBacklash(transmission, backlash); dJointSetHingeParam(hinge2, dParamVel, speed); dJointSetHingeParam(hinge2, dParamFMax, 50); dJointSetHingeParam(hinge1, dParamVel, 0); dJointSetHingeParam(hinge1, dParamFMax, 2); dBodySetLinearVel(body1, 0, 0, 0); dBodySetLinearVel(body2, 0, 0, 0); dBodySetAngularVel(body1, 0, 0, 0); dBodySetAngularVel(body2, 0, 0, 0); } void start() { dMass mass; world = dWorldCreate(); dWorldSetGravity (world,0,0,-9.8); dWorldSetERP(world, 0.2); space = dSimpleSpaceCreate (0); body1 = dBodyCreate(world); body2 = dBodyCreate(world); dBodySetFiniteRotationMode(body1, 1); dBodySetFiniteRotationMode(body2, 1); geom1 = dCreateCylinder(space, 0.2, 0.5); dGeomSetBody(geom1, body1); dMassSetCylinder(&mass, 100, 3, 0.2, 0.5); dBodySetMass(body1, &mass); geom2 = dCreateCylinder(space, 0.2, 0.5); dGeomSetBody(geom2, body2); dMassSetCylinder(&mass, 100, 3, 0.2, 0.5); dBodySetMass(body2, &mass); hinge1 = dJointCreateHinge(world, 0); dJointAttach(hinge1, body1, 0); hinge2 = dJointCreateHinge(world, 0); dJointAttach(hinge2, body2, 0); transmission = dJointCreateTransmission(world, 0); dJointAttach(transmission, body1, body2); dJointSetFeedback(transmission, &feedback); setup(); // initial camera position static float xyz[3] = {1.15,-2.78,4.1}; static float hpr[3] = {105,-45.5,0}; dsSetViewpoint (xyz,hpr); fprintf (stderr, "The green wheel is driving the red one. To control it use the following:\n" " '[' : decrease wheel ratio\n" " ']' : increase wheel ratio\n" " ',' : decrease driving wheel speed\n" " '.' : increase driving wheel speed\n" " '-' : decrease backlash\n" " '=' : increase backlash\n" " '1' : switch to parallel axes gears mode\n" " '2' : switch to intersecting axes gears mode\n" " '3' : switch to chain (or belt) mode\n" ); } void stop() { dSpaceDestroy(space); dWorldDestroy(world); } void drawGeom(dGeomID g) { int gclass = dGeomGetClass(g); const dReal *pos = dGeomGetPosition(g); const dReal *rot = dGeomGetRotation(g); switch (gclass) { case dCylinderClass: { dReal length, radius; if (g == geom1) { dsSetColorAlpha(1, 0, 0, 1); } else { dsSetColorAlpha(0, 1, 0, 1); } dsSetTexture (DS_WOOD); dGeomCylinderGetParams(g, &radius, &length); dsDrawCylinder(pos, rot, length, radius); break; } default: { abort(); } } } void simLoop(int pause) { if (!pause) { const dReal step = 0.003; const unsigned nsteps = 4; for (unsigned i=0; i 0.125) { ratio *= 0.5; fprintf (stderr, "Gear ratio set to %.3f.\n", ratio); } break; case dTransmissionIntersectingAxes: if (theta > 0.1) { theta -= 0.1; fprintf (stderr, "Gear angle set to %.3f deg.\n", theta / M_PI * 180); } break; case dTransmissionChainDrive: if (rho_2 > 0.125) { rho_2 /= 2; fprintf (stderr, "Sprocket ratio set to %.3f.\n", rho_2 / rho_1); } break; } setup(); } else if (cmd == ']') { switch(mode) { case dTransmissionParallelAxes: if (ratio < 8) { ratio *= 2; fprintf (stderr, "Gear ratio set to %.3f.\n", ratio); } break; case dTransmissionIntersectingAxes: if (theta < 0.9) { theta += 0.1; fprintf (stderr, "Gear angle set to %.3f deg.\n", theta / M_PI * 180); } break; case dTransmissionChainDrive: if (rho_2 < 2) { rho_2 *= 2; fprintf (stderr, "Sprocket ratio set to %.3f.\n", rho_2 / rho_1); } break; } setup(); } else if (cmd == '.') { speed += 5; fprintf (stderr, "Driving wheel speed set to %g rad/s.\n", speed); dJointSetHingeParam(hinge2, dParamVel, speed); } else if (cmd == ',') { speed -= 5; fprintf (stderr, "Driving wheel speed set to %g rad/s.\n", speed); dJointSetHingeParam(hinge2, dParamVel, speed); } else if (cmd == '/') { if (dJointGetHingeParam(hinge2, dParamFMax) > 0) { dJointSetHingeParam(hinge2, dParamFMax, 0); } else { dJointSetHingeParam(hinge2, dParamFMax, 50); } } else if (cmd == '-') { backlash -= 0.1; fprintf (stderr, "Backlash set to %g m.\n", backlash); dJointSetTransmissionBacklash(transmission, backlash); } else if (cmd == '=') { backlash += 0.1; fprintf (stderr, "Backlash set to %g m.\n", backlash); dJointSetTransmissionBacklash(transmission, backlash); } else if (cmd == '1') { mode = dTransmissionParallelAxes; setup(); } else if (cmd == '2') { mode = dTransmissionIntersectingAxes; setup(); } else if (cmd == '3') { mode = dTransmissionChainDrive; setup(); } } int main(int argc, char **argv) { // setup pointers to drawstuff callback functions dsFunctions fn; fn.version = DS_VERSION; fn.start = &start; fn.step = &simLoop; fn.command = &command; fn.stop = stop; fn.path_to_textures = DRAWSTUFF_TEXTURE_PATH; // create world dInitODE(); // run demo dsSimulationLoop (argc, argv, 800, 600, &fn); dCloseODE(); return 0; } ode-0.16/ode/demo/Makefile.am0000664000175200017520000000414613403272463012676 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/include \ -I$(top_builddir)/include \ -DDRAWSTUFF_TEXTURE_PATH="\"$(abs_top_srcdir)/drawstuff/textures\"" if X11 AM_LDFLAGS = $(X_PRE_LIBS) $(X_LIBS) $(X_EXTRA_LIBS) endif # On Windows, GL_LIBS must go after libdrawstuff.la. LDADD = $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la @GL_LIBS@ noinst_HEADERS = basket_geom.h bunny_geom.h convex_bunny_geom.h convex_prism.h \ icosahedron_geom.h halton235_geom.h texturepath.h world_geom3.h AM_DEFAULT_SOURCE_EXT = .cpp noinst_PROGRAMS = \ demo_boxstack \ demo_buggy \ demo_cards \ demo_chain1 \ demo_chain2 \ demo_collision \ demo_convex \ demo_crash \ demo_cylvssphere \ demo_dball \ demo_dhinge \ demo_transmission \ demo_feedback \ demo_friction \ demo_gyroscopic \ demo_gyro2 \ demo_heightfield \ demo_hinge \ demo_I \ demo_jointPR \ demo_joints \ demo_jointPU \ demo_kinematic \ demo_motion \ demo_motor \ demo_ode \ demo_piston \ demo_plane2d \ demo_rfriction \ demo_slider \ demo_space \ demo_space_stress \ demo_step \ demo_tracks demo_chain1_SOURCES = demo_chain1.c demo_chain1_LDADD = $(LDADD) -lstdc++ if TRIMESH noinst_PROGRAMS += \ demo_basket \ demo_cyl \ demo_moving_trimesh \ demo_moving_convex \ demo_trimesh AM_CPPFLAGS += -DdTRIMESH_ENABLED endif if WIN32 resources.o: $(top_srcdir)/drawstuff/src/resources.rc $(top_srcdir)/drawstuff/src/resource.h @WINDRES@ $(top_srcdir)/drawstuff/src/resources.rc -o resources.o LDADD += resources.o endif ode-0.16/ode/demo/demo_jointPU.cpp0000664000175200017520000005021713403272463013742 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* This program demonstrates how the PU joint works. A PU joint is a combination of a Universal joint and a Slider joint. It is a universal joint with a slider between the anchor point and body 1. The upper yellow body is fixed to the world The lower yellow body is attached to the upper body by a PU joint The green object is one aprt of the slider. The purple object is the second part of the slider. The red object represent the axis1 of the universal part. The blue object represent the axis2 of the universal part. The gray object represent the anchor2 of the PU joint. */ #include #include #include #include #include "texturepath.h" #ifdef _MSC_VER #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints #endif // select correct drawing functions #ifdef dDOUBLE #define dsDrawBox dsDrawBoxD #define dsDrawCylinder dsDrawCylinderD #define dsDrawCapsule dsDrawCapsuleD #endif enum IDX_CYL_DIM { RADIUS, LENGTH, NUM_CYL_DIM }; const dVector3 boxDim = {1,1,1}; const dVector3 extDim = {0.2,0.2,1.2}; const dVector3 ancDim = {0.2,0.2,0.5}; const dReal axDim[NUM_CYL_DIM] = {0.1,1.0}; int type = dJointTypePU; const dReal VEL_INC = 0.01; // Velocity increment // physics parameters const dReal PI = 3.14159265358979323846264338327950288419716939937510; const dReal INT_EXT_RATIO = 0.8; #define X 0 #define Y 1 #define Z 2 enum INDEX { W = 0, D, EXT, INT, AXIS1, AXIS2, ANCHOR, GROUND, NUM_PARTS, ALL = NUM_PARTS, // INDEX for catBits JOINT, LAST_INDEX_CNT }; const int catBits[LAST_INDEX_CNT] = { 0x0001, ///< W Cylinder category 0x0002, ///< D Cylinder category 0x0004, ///< EXT sliderr category 0x0008, ///< INT slider category 0x0010, ///< AXIS1 universal category 0x0020, ///< AXIS2 universal category 0x0040, ///< ANCHOR category 0x0080, ///< Ground category ~0L, ///< All categories 0x0004 | 0x0008 | 0x0010 | 0x0020 ///< JOINT category }; #define Mass1 10 #define Mass2 8 //camera view static float xyz[3] = {6.0f,0.0f,6.0000f}; static float hpr[3] = {-180.000f,-25.5000f,0.0000f}; //world,space,body & geom static dWorldID world; static dSpaceID space; static dJointGroupID contactgroup; static dBodyID body[NUM_PARTS]; static dGeomID geom[NUM_PARTS]; static dJoint *joint; const dReal BOX_SIDES[3] = {1.0,1.0,1.0}; const dReal OBS_SIDES[3] = {0.4,0.4,0.4}; const dReal RECT_SIDES[3] = {0.3, 0.1, 0.2}; //collision detection static void nearCallback (void *, dGeomID o1, dGeomID o2) { int i,n; const int N = 10; dContact contact[N]; n = dCollide (o1,o2,N,&contact[0].geom,sizeof (dContact) ); if (n > 0) { for (i=0; igetParam (dParamVel3) - VEL_INC; joint->setParam (dParamVel3, vel); joint->setParam (dParamFMax3, 2); std::cout<<"Velocity = "<' : { dReal vel = joint->getParam (dParamVel3) + VEL_INC; joint->setParam (dParamVel3, vel); joint->setParam (dParamFMax3, 2); std::cout<<"Velocity = "<getParam (dParamFMax) ) { aLimit = dInfinity; lLimit = dInfinity; fmax = 0; } else { aLimit = 0.25*PI; lLimit = 0.5*axDim[LENGTH]; fmax = 0.02; } joint->setParam (dParamFMax1, fmax); joint->setParam (dParamFMax2, fmax); joint->setParam (dParamFMax3, fmax); switch (joint->getType() ) { case dJointTypePR : { dPRJoint *pr = reinterpret_cast (joint); pr->setParam (dParamLoStop, -lLimit); pr->setParam (dParamHiStop, -lLimit); pr->setParam (dParamLoStop2, aLimit); pr->setParam (dParamHiStop2, -aLimit); } break; case dJointTypePU : { dPUJoint *pu = reinterpret_cast (joint); pu->setParam (dParamLoStop1, -aLimit); pu->setParam (dParamHiStop1, aLimit); pu->setParam (dParamLoStop2, -aLimit); pu->setParam (dParamHiStop2, aLimit); pu->setParam (dParamLoStop3, -lLimit); pu->setParam (dParamHiStop3, lLimit); } break; default: {} // keep the compiler happy } } break; case 'g': case 'G' : { dVector3 g; dWorldGetGravity(world, g); if ( g[2]< -0.1 ) dWorldSetGravity(world, 0, 0, 0); else dWorldSetGravity(world, 0, 0, -0.5); } case 'p' :case 'P' : { switch (joint->getType() ) { case dJointTypeSlider : { dSliderJoint *sj = reinterpret_cast (joint); std::cout<<"Position ="<getPosition() <<"\n"; } break; case dJointTypePU : { dPUJoint *pu = reinterpret_cast (joint); std::cout<<"Position ="<getPosition() <<"\n"; std::cout<<"Position Rate="<getPositionRate() <<"\n"; std::cout<<"Angle1 ="<getAngle1() <<"\n"; std::cout<<"Angle1 Rate="<getAngle1Rate() <<"\n"; std::cout<<"Angle2 ="<getAngle2() <<"\n"; std::cout<<"Angle2 Rate="<getAngle2Rate() <<"\n"; } break; default: {} // keep the compiler happy } } break; } } static void drawBox (dGeomID id, int R, int G, int B) { if (!id) return; const dReal *pos = dGeomGetPosition (id); const dReal *rot = dGeomGetRotation (id); dsSetColor (R,G,B); dVector3 l; dGeomBoxGetLengths (id, l); dsDrawBox (pos, rot, l); } // simulation loop static void simLoop (int pause) { static bool todo = false; if ( todo ) { // DEBUG static int cnt = 0; ++cnt; if (cnt == 5) command ( 'q' ); if (cnt == 10) dsStop(); } if (!pause) { double simstep = 0.01; // 10ms simulation steps double dt = dsElapsedTime(); int nrofsteps = (int) ceilf (dt/simstep); if (!nrofsteps) nrofsteps = 1; for (int i=0; i (joint); ang1 = pu->getAngle1(); ang2 = pu->getAngle2(); pu->getAxis1 (axisR1); pu->getAxis2 (axisR2); pu->getAxisP (axisP); dJointGetPUAnchor (pu->id(), anchorPos); } else if ( dJointTypePR == type ) { dPRJoint *pr = dynamic_cast (joint); pr->getAxis1 (axisP); pr->getAxis2 (axisR1); dJointGetPRAnchor (pr->id(), anchorPos); } // Draw the axisR if ( geom[INT] ) { dsSetColor (1,0,1); dVector3 l; dGeomBoxGetLengths (geom[INT], l); const dReal *rotBox = dGeomGetRotation (geom[W]); dVector3 pos; for (int i=0; i<3; ++i) pos[i] = anchorPos[i] - 0.5*extDim[Z]*axisP[i]; dsDrawBox (pos, rotBox, l); } dsSetTexture (DS_CHECKERED); if ( geom[AXIS1] ) { dQuaternion q, qAng; dQFromAxisAndAngle (qAng,axisR1[X], axisR1[Y], axisR1[Z], ang1); dGeomGetQuaternion (geom[AXIS1], q); dQuaternion qq; dQMultiply1 (qq, qAng, q); dMatrix3 R; dQtoR (qq,R); dGeomCylinderGetParams (geom[AXIS1], &radius, &length); dsSetColor (1,0,0); dsDrawCylinder (anchorPos, R, length, radius); } if ( dJointTypePU == type && geom[AXIS2] ) { //dPUJoint *pu = dynamic_cast (joint); dQuaternion q, qAng, qq, qq1; dGeomGetQuaternion (geom[AXIS2], q); dQFromAxisAndAngle (qAng, 0, 1, 0, ang2); dQMultiply1 (qq, qAng, q); dQFromAxisAndAngle (qAng,axisR1[X], axisR1[Y], axisR1[Z], ang1); dQMultiply1 (qq1, qAng, qq); dMatrix3 R; dQtoR (qq1,R); dGeomCylinderGetParams (geom[AXIS2], &radius, &length); dsSetColor (0,0,1); dsDrawCylinder (anchorPos, R, length, radius); } dsSetTexture (DS_WOOD); // Draw the anchor if ( geom[ANCHOR] ) { dsSetColor (1,1,1); dVector3 l; dGeomBoxGetLengths (geom[ANCHOR], l); const dReal *rotBox = dGeomGetRotation (geom[D]); const dReal *posBox = dGeomGetPosition (geom[D]); dVector3 e; for (int i=0; i<3; ++i) e[i] = posBox[i] - anchorPos[i]; dNormalize3 (e); dVector3 pos; for (int i=0; i<3; ++i) pos[i] = anchorPos[i] + 0.5 * l[Z]*e[i]; dsDrawBox (pos, rotBox, l); } drawBox (geom[D], 1,1,0); } } void Help (char **argv) { printf ("%s ", argv[0]); printf (" -h | --help : print this help\n"); printf (" -p | --PRJoint : Use a PR joint instead of PU joint\n"); printf (" -t | --texture-path path : Path to the texture.\n"); printf (" Default = %s\n", DRAWSTUFF_TEXTURE_PATH); printf ("--------------------------------------------------\n"); printf ("Hit any key to continue:"); getchar(); exit (0); } int main (int argc, char **argv) { // setup pointers to drawstuff callback functions dsFunctions fn; fn.version = DS_VERSION; fn.start = &start; fn.step = &simLoop; fn.command = &command; fn.stop = 0; fn.path_to_textures = DRAWSTUFF_TEXTURE_PATH; if (argc >= 2 ) { for (int i=1; i < argc; ++i) { if ( 0 == strcmp ("-h", argv[i]) || 0 == strcmp ("--help", argv[i]) ) Help (argv); if ( 0 == strcmp ("-p", argv[i]) || 0 == strcmp ("--PRJoint", argv[i]) ) type = dJointTypePR; if (0 == strcmp ("-t", argv[i]) || 0 == strcmp ("--texture-path", argv[i]) ) { int j = i+1; if ( j >= argc || // Check if we have enough arguments argv[j][0] == '\0' || // We should have a path here argv[j][0] == '-' ) // We should have a path not a command line Help (argv); else fn.path_to_textures = argv[++i]; // Increase i since we use this argument } } } dInitODE2(0); world = dWorldCreate(); dWorldSetERP (world, 0.8); space = dSimpleSpaceCreate (0); contactgroup = dJointGroupCreate (0); geom[GROUND] = dCreatePlane (space, 0,0,1,0); dGeomSetCategoryBits (geom[GROUND], catBits[GROUND]); dGeomSetCollideBits (geom[GROUND], catBits[ALL]); dMass m; // Create the body attached to the World body[W] = dBodyCreate (world); // Main axis of cylinder is along X=1 m.setBox (1, boxDim[X], boxDim[Y], boxDim[Z]); m.adjust (Mass1); geom[W] = dCreateBox (space, boxDim[X], boxDim[Y], boxDim[Z]); dGeomSetBody (geom[W], body[W]); dGeomSetCategoryBits (geom[W], catBits[W]); dGeomSetCollideBits (geom[W], catBits[ALL] & (~catBits[W]) & (~catBits[JOINT]) ); dBodySetMass (body[W], &m); // Create the dandling body body[D] = dBodyCreate (world); // Main axis of capsule is along X=1 m.setBox (1, boxDim[X], boxDim[Y], boxDim[Z]); m.adjust (Mass1); geom[D] = dCreateBox (space, boxDim[X], boxDim[Y], boxDim[Z]); dGeomSetBody (geom[D], body[D]); dGeomSetCategoryBits (geom[D], catBits[D]); dGeomSetCollideBits (geom[D], catBits[ALL] & (~catBits[D]) & (~catBits[JOINT]) ); dBodySetMass (body[D], &m); // Create the external part of the slider joint geom[EXT] = dCreateBox (0, extDim[X], extDim[Y], extDim[Z]); dGeomSetCategoryBits (geom[EXT], catBits[EXT]); dGeomSetCollideBits (geom[EXT], catBits[ALL] & (~catBits[JOINT]) & (~catBits[W]) & (~catBits[D]) ); // Create the internal part of the slider joint geom[INT] = dCreateBox (0, INT_EXT_RATIO*extDim[X], INT_EXT_RATIO*extDim[Y], INT_EXT_RATIO*extDim[Z]); dGeomSetCategoryBits (geom[INT], catBits[INT]); dGeomSetCollideBits (geom[INT], catBits[ALL] & (~catBits[JOINT]) & (~catBits[W]) & (~catBits[D]) ); dMatrix3 R; // Create the first axis of the universal joi9nt //Rotation of 90deg around y geom[AXIS1] = dCreateCylinder(0, axDim[RADIUS], axDim[LENGTH]); dRFromAxisAndAngle(R, 0,1,0, 0.5*PI); dGeomSetRotation(geom[AXIS1], R); dGeomSetCategoryBits(geom[AXIS1], catBits[AXIS1]); dGeomSetCollideBits(geom[AXIS1], catBits[ALL] & ~catBits[JOINT] & ~catBits[W] & ~catBits[D]); // Create the second axis of the universal joint geom[AXIS2] = dCreateCylinder(0, axDim[RADIUS], axDim[LENGTH]); //Rotation of 90deg around y dRFromAxisAndAngle(R, 1,0,0, 0.5*PI); dGeomSetRotation(geom[AXIS2], R); dGeomSetCategoryBits(geom[AXIS2], catBits[AXIS2]); dGeomSetCollideBits(geom[AXIS2], catBits[ALL] & ~catBits[JOINT] & ~catBits[W] & ~catBits[D]); // Create the anchor geom[ANCHOR] = dCreateBox (0, ancDim[X], ancDim[Y], ancDim[Z]); dGeomSetCategoryBits(geom[ANCHOR], catBits[ANCHOR]); dGeomSetCollideBits(geom[ANCHOR], catBits[ALL] & (~catBits[JOINT]) & (~catBits[W]) & (~catBits[D]) ); if (body[W]) { dBodySetPosition(body[W], 0, 0, 5); } if (geom[EXT]) { dGeomSetPosition(geom[EXT], 0,0,3.8); } if (geom[INT]) { dGeomSetPosition(geom[INT], 0,0,2.6); } if (geom[AXIS1]) { dGeomSetPosition(geom[AXIS1], 0,0,2.5); } if (geom[AXIS2]) { dGeomSetPosition(geom[AXIS2], 0,0,2.5); } if (geom[ANCHOR]) { dGeomSetPosition(geom[ANCHOR], 0,0,2.25); } if (body[D]) { dBodySetPosition(body[D], 0,0,1.5); } // Attache the upper box to the world dJointID fixed = dJointCreateFixed (world,0); dJointAttach (fixed , NULL, body[W]); dJointSetFixed (fixed ); if (type == dJointTypePR) { dPRJoint *pr = new dPRJoint (world, 0); pr->attach (body[W], body[D]); pr->setAxis1 (0, 0, -1); pr->setAxis2 (1, 0, 0); joint = pr; dJointSetPRAnchor (pr->id(), 0, 0, 2.5); } else { dPUJoint *pu = new dPUJoint (world, 0); pu->attach (body[W], body[D]); pu->setAxis1 (1, 0, 0); pu->setAxis2 (0, 1, 0); pu->setAxisP (0, 0, -1); joint = pu; dJointSetPUAnchor (pu->id(), 0, 0, 2.5); } // run simulation dsSimulationLoop (argc,argv,400,300,&fn); delete joint; dJointGroupDestroy (contactgroup); dSpaceDestroy (space); dWorldDestroy (world); dCloseODE(); return 0; } ode-0.16/ode/demo/convex_bunny_geom.h0000664000175200017520000003335413403272463014542 00000000000000const unsigned int convexBunnyPlaneCount = 176; dReal convexBunnyPlanes[] = { 0.986167, -0.0612533, -0.154021, 0.399481, 0.982735, -0.0691036, -0.171628, 0.409884, -0.984387, -0.0582774, -0.166089, 0.403079, 0.985044, -0.172279, 0.00302105, 0.437531, 0.976915, -0.184361, 0.107929, 0.465334, 0.951478, -0.281619, 0.124019, 0.475223, 0.798136, -0.502214, 0.332805, 0.535555, 0.949728, -0.211128, -0.231176, 0.528156, -0.000894561, -0.995066, -0.0992088, 0.80299, -0.000896015, -0.995066, -0.0992131, 0.802991, -0.0035709, -0.935822, 0.352454, 0.618504, -0.291551, -0.828515, 0.478081, 0.681579, -0.978715, -0.181408, 0.0959605, 0.468907, -0.985523, -0.169302, -0.00904739, 0.441129, -0.953768, -0.278749, 0.11236, 0.478704, 0.372745, -0.827499, 0.419888, 0.630174, 0.976911, -0.18316, 0.109991, 0.466086, 0.817827, -0.387738, 0.425227, 0.569153, -0.978732, -0.180211, 0.0980152, 0.469656, 0.662794, -0.0277654, 0.748287, 0.803459, 0.00359857, -0.660581, -0.750746, 0.877267, 0.00359952, -0.660579, -0.750748, 0.877266, -0.947456, -0.208272, -0.242797, 0.531628, -0.980764, -0.0661375, -0.18365, 0.413468, -0.940835, -0.0698657, -0.331585, 0.494827, 0.983751, 0.0529367, -0.171556, 0.403533, 0.981839, 0.0996302, -0.16145, 0.410144, 0.977938, 0.0857834, -0.190468, 0.411823, 0.959636, 0.106068, -0.260476, 0.44898, 0.85334, -0.0495414, -0.518996, 0.60489, -0.803667, -0.499793, 0.322995, 0.538478, -0.689742, -0.615484, 0.381361, 0.574754, -0.380353, -0.826364, 0.415277, 0.63155, -0.39985, -0.817283, 0.414933, 0.630682, -0.380309, -0.826285, 0.415473, 0.631677, -0.981411, 0.0559147, -0.183592, 0.407121, -0.979526, 0.101914, -0.173615, 0.413635, -0.975381, 0.0881975, -0.202119, 0.415257, 0.988445, 0.140182, 0.0576755, 0.485174, 0.876515, 0.0408992, 0.479634, 0.620093, 0.848907, -0.0996824, 0.519057, 0.631268, 0.895754, -0.195088, 0.399457, 0.563346, 0.861448, -0.256989, 0.438023, 0.574909, 0.775672, -0.447481, 0.445076, 0.586422, 0.683157, -0.617557, 0.389768, 0.572247, 0.391755, -0.818722, 0.419789, 0.629264, 0.28317, -0.829384, 0.481599, 0.680529, 0.3727, -0.827422, 0.420079, 0.630298, -0.824143, -0.385255, 0.415171, 0.57215, -0.782413, -0.445128, 0.435536, 0.589267, 0.00152876, 0.999994, -0.00308275, 0.665646, 0.00242466, 0.999989, -0.0038994, 0.665879, -0.979892, 0.121321, -0.158406, 0.420287, 0.767537, -0.190214, -0.612132, 0.695479, 0.372649, -0.42747, -0.823652, 0.869878, 0.537245, -0.335515, -0.77382, 0.82472, 0.0263648, -0.598975, -0.800334, 0.873623, 0.00393345, -0.60959, -0.792707, 0.869865, -0.0183706, -0.598907, -0.800608, 0.873704, 0.00875728, 0.676014, -0.736836, 0.825597, 0.852333, -0.0355955, -0.521786, 0.607886, 0.392036, 0.534934, -0.748434, 0.818042, 0.847696, -0.122973, -0.516033, 0.615814, 0.884763, -0.0760716, -0.45979, 0.565893, 0.9446, -0.0727144, -0.320069, 0.491401, 0.904971, -0.0675211, -0.420081, 0.541673, -0.899959, -0.0647928, -0.431134, 0.544968, -0.955972, 0.108494, -0.272667, 0.452769, -0.363823, -0.426358, -0.828161, 0.871222, -0.528689, -0.333936, -0.780368, 0.826685, 0.982068, 0.118277, -0.146811, 0.416542, 0.98951, 0.144455, 0.00164104, 0.468616, 0.50797, -0.0708041, 0.85846, 0.883126, 0.748614, -0.431275, 0.503565, 0.634026, 0.214863, -0.405791, 0.888351, 0.94048, -0.901162, -0.192379, 0.388455, 0.566627, -0.867521, -0.254376, 0.427435, 0.578065, -0.226957, -0.405135, 0.885639, 0.941284, -0.756029, -0.429007, 0.494341, 0.636765, -0.00629553, -0.188362, 0.982079, 0.968197, 0.0165684, 0.999846, -0.00581961, 0.670373, 0.00313267, 0.999987, -0.00405124, 0.666103, 0.545069, 0.472158, -0.692796, 0.780052, 0.932011, 0.148856, -0.330451, 0.498417, 0.844043, 0.227673, -0.485547, 0.599903, -0.019033, 0.999801, -0.00590978, 0.672252, -0.959662, 0.239262, -0.147656, 0.488538, 0.00151234, 0.999999, -0.000399466, 0.665855, -0.988649, 0.143168, 0.0455675, 0.488784, -0.989015, 0.147444, -0.01048, 0.472227, -0.972439, 0.232727, -0.01415, 0.518344, 0.587681, -0.160147, -0.793085, 0.823999, 0.640479, -0.269179, -0.719256, 0.778142, 0.541109, -0.332896, -0.772257, 0.823226, 0.546185, -0.14771, -0.824538, 0.84854, 0.528519, -0.026044, -0.848522, 0.873136, 0.447231, -0.0756684, -0.891212, 0.903953, 0.490619, -0.0795123, -0.867739, 0.884255, 0.279393, 0.264257, -0.923097, 0.950045, 0.374653, 0.39486, -0.83888, 0.886593, 0.00050174, 0.999994, -0.00331563, 0.665976, -0.0103777, 0.999934, -0.00487936, 0.669494, -0.927571, 0.150741, -0.341889, 0.501807, -0.267268, 0.265084, -0.926444, 0.951043, -0.845984, -0.0330207, -0.532184, 0.610986, -0.518165, -0.0244575, -0.854931, 0.875047, -0.83753, 0.228953, -0.496108, 0.603116, -0.535666, 0.472122, -0.700116, 0.78259, -0.381083, 0.534649, -0.754272, 0.820328, -0.363157, 0.395975, -0.843398, 0.88794, -0.326829, -0.256634, -0.909572, 0.922946, 0.394875, -0.128601, -0.90969, 0.920236, 0.337169, -0.257642, -0.905504, 0.921733, 0.398433, -0.193767, -0.896496, 0.910015, -0.536477, -0.146072, -0.831177, 0.850523, -0.436512, -0.0743406, -0.896622, 0.905564, -0.480187, -0.0780522, -0.873687, 0.886029, -0.384093, -0.127432, -0.914458, 0.921656, -0.388009, -0.192572, -0.901313, 0.911451, 0.977045, 0.15796, 0.14294, 0.521934, 0.930035, 0.231515, 0.28537, 0.600301, -0.855499, -0.0971121, 0.508616, 0.634376, -0.875419, 0.136849, 0.463589, 0.62897, -0.882196, 0.0435387, 0.468864, 0.623303, 0.0204398, -0.0238739, 0.999506, 0.958419, -0.0062197, -0.0777937, 0.99695, 0.962769, 0.907123, 0.250746, 0.338015, 0.623205, 0.902358, 0.173321, 0.394601, 0.607696, 0.870085, 0.134211, 0.474278, 0.625782, 0.0015108, 0.999999, 6.34978e-06, 0.665945, 0.00150567, 0.999999, 0.000568537, 0.666143, 0.00150738, 0.999999, 0.000565012, 0.666141, -0.963954, 0.266039, -0.00405118, 0.539571, 0.0015136, 0.999999, -0.000393102, 0.665856, 0.00151117, 0.999999, 4.32104e-06, 0.665944, 0.0272711, 0.999604, -0.00696439, 0.673709, 0.962047, 0.236383, -0.136341, 0.484917, 0.973236, 0.229796, -0.00223071, 0.514797, 0.964728, 0.263133, 0.00776342, 0.536054, -0.906596, 0.176056, 0.383521, 0.610999, -0.978237, 0.160918, 0.130987, 0.525513, -0.910434, 0.253486, 0.326887, 0.626522, -0.932759, 0.234321, 0.27396, 0.603697, 0.800621, -0.0921333, -0.592045, 0.665278, 0.679569, -0.15358, -0.717356, 0.765121, 0.684928, -0.199829, -0.700672, 0.756959, -0.532604, -0.33128, -0.778837, 0.82519, -0.578395, -0.158384, -0.800234, 0.826134, -0.671209, -0.151537, -0.725613, 0.767576, -0.00530287, 0.323551, 0.946196, 0.94547, -0.719766, 0.229227, 0.655281, 0.774388, -0.604194, 0.29171, 0.741522, 0.841564, -0.544989, 0.302925, 0.781808, 0.866398, -0.518662, -0.0692529, 0.85217, 0.884999, -0.671987, -0.0257512, 0.740115, 0.805898, -0.00613626, -0.00823685, 0.999947, 0.957141, -0.032747, -0.0237908, 0.99918, 0.958516, -0.00530611, 0.323546, 0.946198, 0.945471, -0.545061, 0.302657, 0.781861, 0.866377, -0.639902, 0.23832, 0.730568, 0.823722, 0.00149706, 0.999997, 0.00193434, 0.667038, 0.00149731, 0.999997, 0.00193252, 0.667037, -0.0048341, 0.44008, 0.897946, 0.936327, -0.00483143, 0.440078, 0.897947, 0.936327, -0.632454, -0.267241, -0.727039, 0.780455, -0.67691, -0.197765, -0.709, 0.759436, -0.841667, -0.120432, -0.526396, 0.618913, -0.760706, -0.187792, -0.621337, 0.698143, -0.87929, -0.0734062, -0.470597, 0.569116, -0.847068, -0.0469762, -0.529405, 0.607991, -0.793572, -0.0897399, -0.601823, 0.668201, 0.536355, 0.301024, 0.788485, 0.864403, 0.536284, 0.301291, 0.788431, 0.864424, 0.595945, 0.289897, 0.748872, 0.839373, 0.631626, 0.236397, 0.738353, 0.8214, 0.712378, 0.227061, 0.664049, 0.771772, }; const unsigned int convexBunnyPointCount = 105; dReal convexBunnyPoints[] = { -0.459488, -0.093017, -0.311341, 0.466635, -0.094416, -0.305669, -0.309239, 0.776868, 0.304726, -0.004458, -0.042526, 1.01567, 8.40779e-45, 3.00321e-39, 2.8026e-44, 0.007957, 0.282241, -0.93168, 0.204445, -0.66438, 0.513353, -0.303961, 0.054199, 0.625921, 0.265619, 0.756464, 0.504187, -0.402162, 0.133528, -0.443247, 8.40779e-45, 3.00321e-39, 2.8026e-44, -0.266772, 0.64233, 0.602061, 8.40779e-45, 3.00321e-39, 2.8026e-44, 8.40779e-45, 3.00321e-39, 2.8026e-44, 0.411612, 0.132299, -0.438264, 0.31148, 0.775931, 0.308527, 0.300086, 0.053287, 0.62962, -0.414624, 0.164083, -0.278254, -0.248382, 0.255825, -0.627493, -0.216201, -0.126776, -0.886936, 0.267564, -0.666174, -0.654834, -0.135892, -0.03552, 0.945455, -0.265837, 0.757267, 0.500933, -0.003873, 0.161605, 0.970499, 8.40779e-45, 3.00321e-39, 2.8026e-44, -0.282599, -0.663393, 0.412411, 0.007237, 0.361687, -0.794439, 0.093627, 0.258494, -0.920589, 0.422146, 0.162819, -0.27313, 0.279163, -0.664604, 0.417328, 0.263086, 0.512567, 0.637832, -0.099875, 0.310931, -0.799381, -0.446838, -0.118517, -0.466159, -0.168842, 0.102387, -0.920381, 0.455805, -0.119881, -0.460632, 0.337743, -0.666396, -0.074503, -0.134547, -0.119852, -0.959004, -0.183807, 0.19697, 0.84448, 0.264969, 0.641527, 0.605317, -0.209063, -0.663393, 0.509344, -0.364126, -0.200299, 0.202388, -0.253475, -0.081797, 0.756541, 0.260471, 0.255056, -0.624378, 0.114248, 0.310608, -0.79807, 0.364663, -0.201399, 0.20685, 0.127847, -0.035919, 0.94707, 8.40779e-45, 3.00321e-39, 2.8026e-44, -0.381071, -0.629723, -0.350777, -0.339884, -0.04115, -0.668211, -0.077913, 0.258753, -0.92164, 0.184061, 0.101854, -0.91822, -0.335166, -0.66538, -0.078623, 0.386561, -0.625221, -0.21687, 8.40779e-45, 3.00321e-39, 2.8026e-44, -0.241585, 0.527592, 0.669296, -0.086969, 0.133224, 0.947633, -0.003127, 0.28407, 0.87887, -0.004433, -0.146642, 0.985872, 8.40779e-45, 3.00321e-39, 2.8026e-44, -0.138444, -0.10425, 0.945975, -0.265676, 0.513366, 0.634594, 8.40779e-45, 3.00321e-39, 2.8026e-44, 0.247593, -0.082554, 0.75961, 0.07941, 0.132973, 0.948652, 0.238615, 0.526867, 0.672237, 8.40779e-45, 3.00321e-39, 2.8026e-44, 8.40779e-45, 3.00321e-39, 2.8026e-44, -0.382112, -0.62406, -0.221577, -0.104072, 0.177278, -0.95253, 0.351567, -0.042194, -0.663976, 0.138234, -0.293905, -0.897958, 0.119916, 0.17694, -0.951159, -0.371322, -0.665382, -0.35362, -0.263384, -0.663396, 0.466604, 0.376722, -0.666513, -0.219833, 0.387086, -0.630883, -0.346073, -0.125544, 0.140012, 0.917678, -0.070612, 0.036849, 0.975733, -0.083497, -0.084934, 0.979607, 0.259286, -0.664547, 0.471281, 8.40779e-45, 3.00321e-39, 2.8026e-44, 0.074888, -0.085173, 0.980577, 0.152305, 0.125256, 0.890786, 0.130184, -0.104656, 0.94762, -0.004249, 0.046042, 1.00324, 0.062419, 0.036648, 0.976547, 8.40779e-45, 3.00321e-39, 2.8026e-44, -0.392666, -0.488581, -0.427494, 0.230315, -0.12745, -0.884202, 8.40779e-45, 3.00321e-39, 2.8026e-44, 0.193434, -0.665946, -0.715325, 0.007865, 0.122104, -0.956137, 8.40779e-45, 3.00321e-39, 2.8026e-44, -0.257884, -0.665381, -0.658052, 0.377265, -0.666513, -0.349036, -0.372362, -0.665381, -0.22442, 0.400045, -0.489778, -0.42264, -0.159174, 0.125726, 0.888878, 0.118369, 0.139643, 0.919173, -0.124463, -0.293508, -0.899566, 0.21172, -0.302754, -0.843303, 0.149571, -0.120281, -0.957264, -0.183019, -0.665378, -0.71763, 0.177696, 0.196424, 0.846693, -0.198638, -0.302135, -0.845816, }; unsigned int convexBunnyPolygons[] = { 3, 7, 2, 0, 3, 2, 7, 11, 3, 1, 15, 16, 3, 0, 2, 17, 3, 17, 9, 0, 3, 2, 9, 17, 3, 18, 9, 2, 3, 2, 11, 22, 3, 22, 15, 2, 3, 8, 15, 22, 3, 2, 15, 26, 3, 5, 26, 27, 3, 1, 14, 28, 3, 28, 15, 1, 3, 14, 15, 28, 3, 2, 26, 31, 3, 0, 9, 32, 3, 9, 18, 33, 3, 34, 14, 1, 3, 19, 33, 36, 3, 8, 22, 38, 3, 38, 22, 11, 3, 38, 15, 8, 3, 38, 16, 15, 3, 38, 30, 16, 3, 40, 7, 0, 3, 0, 25, 40, 3, 40, 25, 7, 3, 7, 25, 41, 3, 21, 37, 41, 3, 42, 15, 14, 3, 42, 27, 15, 3, 43, 26, 15, 3, 15, 27, 43, 3, 43, 27, 26, 3, 1, 16, 44, 3, 44, 29, 1, 3, 16, 29, 44, 3, 0, 32, 47, 3, 19, 32, 48, 3, 48, 33, 19, 3, 48, 32, 9, 3, 9, 33, 48, 3, 49, 33, 18, 3, 49, 18, 2, 3, 2, 31, 49, 3, 49, 26, 5, 3, 49, 31, 26, 3, 50, 42, 14, 3, 27, 42, 50, 3, 51, 35, 6, 3, 6, 39, 51, 3, 1, 29, 52, 3, 11, 37, 54, 3, 55, 23, 11, 3, 11, 54, 55, 3, 11, 23, 56, 3, 56, 38, 11, 3, 23, 38, 56, 3, 57, 39, 6, 3, 21, 41, 59, 3, 39, 57, 59, 3, 60, 37, 11, 3, 60, 41, 37, 3, 60, 11, 7, 3, 7, 41, 60, 3, 16, 30, 62, 3, 62, 29, 16, 3, 63, 38, 23, 3, 38, 63, 64, 3, 67, 25, 0, 3, 0, 47, 67, 3, 68, 36, 33, 3, 33, 49, 68, 3, 68, 49, 5, 3, 14, 34, 69, 3, 69, 50, 14, 3, 5, 27, 71, 3, 27, 50, 71, 3, 71, 68, 5, 3, 25, 51, 73, 3, 73, 51, 39, 3, 39, 59, 73, 3, 73, 41, 25, 3, 73, 59, 41, 3, 29, 35, 74, 3, 74, 52, 29, 3, 35, 51, 74, 3, 75, 34, 1, 3, 1, 52, 75, 3, 52, 74, 75, 3, 21, 55, 76, 3, 76, 54, 37, 3, 76, 55, 54, 3, 77, 55, 21, 3, 21, 59, 78, 3, 3, 77, 78, 3, 78, 77, 21, 3, 78, 57, 3, 3, 78, 59, 57, 3, 6, 35, 79, 3, 79, 35, 29, 3, 29, 62, 79, 3, 3, 57, 81, 3, 83, 62, 45, 3, 45, 81, 83, 3, 83, 79, 62, 3, 6, 79, 83, 3, 83, 57, 6, 3, 83, 81, 57, 3, 84, 63, 23, 3, 84, 77, 3, 3, 23, 55, 84, 3, 55, 77, 84, 3, 45, 63, 85, 3, 3, 81, 85, 3, 85, 81, 45, 3, 85, 84, 3, 3, 63, 84, 85, 3, 87, 47, 32, 3, 87, 72, 47, 3, 50, 69, 88, 3, 88, 34, 20, 3, 88, 69, 34, 3, 36, 68, 91, 3, 68, 71, 91, 3, 72, 87, 93, 3, 93, 87, 32, 3, 93, 32, 19, 3, 94, 74, 72, 3, 94, 93, 20, 3, 72, 93, 94, 3, 94, 75, 74, 3, 95, 74, 51, 3, 72, 74, 95, 3, 95, 51, 25, 3, 25, 67, 95, 3, 95, 67, 47, 3, 47, 72, 95, 3, 20, 34, 96, 3, 34, 75, 96, 3, 96, 94, 20, 3, 75, 94, 96, 3, 97, 37, 21, 3, 21, 76, 97, 3, 97, 76, 37, 3, 98, 64, 63, 3, 98, 63, 45, 3, 45, 82, 98, 3, 36, 70, 99, 3, 100, 88, 20, 3, 20, 90, 100, 3, 100, 90, 70, 3, 101, 71, 50, 3, 50, 88, 101, 3, 36, 91, 101, 3, 101, 91, 71, 3, 101, 70, 36, 3, 101, 100, 70, 3, 88, 100, 101, 3, 102, 90, 20, 3, 20, 93, 102, 3, 70, 90, 102, 3, 102, 99, 70, 3, 64, 98, 103, 3, 103, 98, 82, 3, 30, 38, 103, 3, 38, 64, 103, 3, 103, 62, 30, 3, 45, 62, 103, 3, 103, 82, 45, 3, 36, 99, 104, 3, 99, 102, 104, 3, 104, 102, 93, 3, 19, 36, 104, 3, 104, 93, 19, }; ode-0.16/ode/demo/demo_buggy.cpp0000664000175200017520000002140713403272463013466 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* buggy with suspension. this also shows you how to use geom groups. */ #include #include #include "texturepath.h" #ifdef _MSC_VER #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints #endif // select correct drawing functions #ifdef dDOUBLE #define dsDrawBox dsDrawBoxD #define dsDrawSphere dsDrawSphereD #define dsDrawCylinder dsDrawCylinderD #define dsDrawCapsule dsDrawCapsuleD #endif // some constants #define LENGTH 0.7 // chassis length #define WIDTH 0.5 // chassis width #define HEIGHT 0.2 // chassis height #define RADIUS 0.18 // wheel radius #define STARTZ 0.5 // starting height of chassis #define CMASS 1 // chassis mass #define WMASS 0.2 // wheel mass static const dVector3 yunit = { 0, 1, 0 }, zunit = { 0, 0, 1 }; // dynamics and collision objects (chassis, 3 wheels, environment) static dWorldID world; static dSpaceID space; static dBodyID body[4]; static dJointID joint[3]; // joint[0] is the front wheel static dJointGroupID contactgroup; static dGeomID ground; static dSpaceID car_space; static dGeomID box[1]; static dGeomID sphere[3]; static dGeomID ground_box; // things that the user controls static dReal speed=0,steer=0; // user commands // this is called by dSpaceCollide when two objects in space are // potentially colliding. static void nearCallback (void *, dGeomID o1, dGeomID o2) { int i,n; // only collide things with the ground int g1 = (o1 == ground || o1 == ground_box); int g2 = (o2 == ground || o2 == ground_box); if (!(g1 ^ g2)) return; const int N = 10; dContact contact[N]; n = dCollide (o1,o2,N,&contact[0].geom,sizeof(dContact)); if (n > 0) { for (i=0; i 0.1) v = 0.1; if (v < -0.1) v = -0.1; v *= 10.0; dJointSetHinge2Param (joint[0],dParamVel,v); dJointSetHinge2Param (joint[0],dParamFMax,0.2); dJointSetHinge2Param (joint[0],dParamLoStop,-0.75); dJointSetHinge2Param (joint[0],dParamHiStop,0.75); dJointSetHinge2Param (joint[0],dParamFudgeFactor,0.1); dSpaceCollide (space,0,&nearCallback); dWorldStep (world,0.05); // remove all contact joints dJointGroupEmpty (contactgroup); } dsSetColor (0,1,1); dsSetTexture (DS_WOOD); dReal sides[3] = {LENGTH,WIDTH,HEIGHT}; dsDrawBox (dBodyGetPosition(body[0]),dBodyGetRotation(body[0]),sides); dsSetColor (1,1,1); for (i=1; i<=3; i++) dsDrawCylinder (dBodyGetPosition(body[i]), dBodyGetRotation(body[i]),0.02f,RADIUS); dVector3 ss; dGeomBoxGetLengths (ground_box,ss); dsDrawBox (dGeomGetPosition(ground_box),dGeomGetRotation(ground_box),ss); } int main (int argc, char **argv) { int i; dMass m; // setup pointers to drawstuff callback functions dsFunctions fn; fn.version = DS_VERSION; fn.start = &start; fn.step = &simLoop; fn.command = &command; fn.stop = 0; fn.path_to_textures = DRAWSTUFF_TEXTURE_PATH; // create world dInitODE2(0); world = dWorldCreate(); space = dHashSpaceCreate (0); contactgroup = dJointGroupCreate (0); dWorldSetGravity (world,0,0,-0.5); ground = dCreatePlane (space,0,0,1,0); // chassis body body[0] = dBodyCreate (world); dBodySetPosition (body[0],0,0,STARTZ); dMassSetBox (&m,1,LENGTH,WIDTH,HEIGHT); dMassAdjust (&m,CMASS); dBodySetMass (body[0],&m); box[0] = dCreateBox (0,LENGTH,WIDTH,HEIGHT); dGeomSetBody (box[0],body[0]); // wheel bodies for (i=1; i<=3; i++) { body[i] = dBodyCreate (world); dQuaternion q; dQFromAxisAndAngle (q,1,0,0,M_PI*0.5); dBodySetQuaternion (body[i],q); dMassSetSphere (&m,1,RADIUS); dMassAdjust (&m,WMASS); dBodySetMass (body[i],&m); sphere[i-1] = dCreateSphere (0,RADIUS); dGeomSetBody (sphere[i-1],body[i]); } dBodySetPosition (body[1],0.5*LENGTH,0,STARTZ-HEIGHT*0.5); dBodySetPosition (body[2],-0.5*LENGTH, WIDTH*0.5,STARTZ-HEIGHT*0.5); dBodySetPosition (body[3],-0.5*LENGTH,-WIDTH*0.5,STARTZ-HEIGHT*0.5); // front and back wheel hinges for (i=0; i<3; i++) { joint[i] = dJointCreateHinge2 (world,0); dJointAttach (joint[i],body[0],body[i+1]); const dReal *a = dBodyGetPosition (body[i+1]); dJointSetHinge2Anchor (joint[i],a[0],a[1],a[2]); dJointSetHinge2Axes (joint[i], zunit, yunit); } // set joint suspension for (i=0; i<3; i++) { dJointSetHinge2Param (joint[i],dParamSuspensionERP,0.4); dJointSetHinge2Param (joint[i],dParamSuspensionCFM,0.8); } // lock back wheels along the steering axis for (i=1; i<3; i++) { // set stops to make sure wheels always stay in alignment dJointSetHinge2Param (joint[i],dParamLoStop,0); dJointSetHinge2Param (joint[i],dParamHiStop,0); // the following alternative method is no good as the wheels may get out // of alignment: // dJointSetHinge2Param (joint[i],dParamVel,0); // dJointSetHinge2Param (joint[i],dParamFMax,dInfinity); } // create car space and add it to the top level space car_space = dSimpleSpaceCreate (space); dSpaceSetCleanup (car_space,0); dSpaceAdd (car_space,box[0]); dSpaceAdd (car_space,sphere[0]); dSpaceAdd (car_space,sphere[1]); dSpaceAdd (car_space,sphere[2]); // environment ground_box = dCreateBox (space,2,1.5,1); dMatrix3 R; dRFromAxisAndAngle (R,0,1,0,-0.15); dGeomSetPosition (ground_box,2,0,-0.34); dGeomSetRotation (ground_box,R); // run simulation dsSimulationLoop (argc,argv,352,288,&fn); dGeomDestroy (box[0]); dGeomDestroy (sphere[0]); dGeomDestroy (sphere[1]); dGeomDestroy (sphere[2]); dJointGroupDestroy (contactgroup); dSpaceDestroy (space); dWorldDestroy (world); dCloseODE(); return 0; } ode-0.16/ode/demo/demo_hinge.cpp0000664000175200017520000001157413403272463013447 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include #include "texturepath.h" #ifdef _MSC_VER #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints #endif // select correct drawing functions #ifdef dDOUBLE #define dsDrawBox dsDrawBoxD #endif // some constants #define SIDE (0.5f) // side length of a box #define MASS (1.0) // mass of a box // dynamics and collision objects static dWorldID world; static dBodyID body[2]; static dJointID hinge; // state set by keyboard commands static int occasional_error = 0; // start simulation - set viewpoint static void start() { dAllocateODEDataForThread(dAllocateMaskAll); static float xyz[3] = {1.0382f,-1.0811f,1.4700f}; static float hpr[3] = {135.0000f,-19.5000f,0.0000f}; dsSetViewpoint (xyz,hpr); printf ("Press 'e' to start/stop occasional error.\n"); } // called when a key pressed static void command (int cmd) { if (cmd == 'e' || cmd == 'E') { occasional_error ^= 1; } } // simulation loop static void simLoop (int pause) { const dReal kd = -0.3; // angular damping constant if (!pause) { // add an oscillating torque to body 0, and also damp its rotational motion static dReal a=0; const dReal *w = dBodyGetAngularVel (body[0]); dBodyAddTorque (body[0],kd*w[0],kd*w[1]+0.1*cos(a),kd*w[2]+0.1*sin(a)); dWorldStep (world,0.05); a += 0.01; // occasionally re-orient one of the bodies to create a deliberate error. if (occasional_error) { static int count = 0; if ((count % 20)==0) { // randomly adjust orientation of body[0] const dReal *R1; dMatrix3 R2,R3; R1 = dBodyGetRotation (body[0]); dRFromAxisAndAngle (R2,dRandReal()-0.5,dRandReal()-0.5, dRandReal()-0.5,dRandReal()-0.5); dMultiply0 (R3,R1,R2,3,3,3); dBodySetRotation (body[0],R3); // randomly adjust position of body[0] const dReal *pos = dBodyGetPosition (body[0]); dBodySetPosition (body[0], pos[0]+0.2*(dRandReal()-0.5), pos[1]+0.2*(dRandReal()-0.5), pos[2]+0.2*(dRandReal()-0.5)); } count++; } } dReal sides1[3] = {SIDE,SIDE,SIDE}; dReal sides2[3] = {SIDE,SIDE,SIDE*0.8f}; dsSetTexture (DS_WOOD); dsSetColor (1,1,0); dsDrawBox (dBodyGetPosition(body[0]),dBodyGetRotation(body[0]),sides1); dsSetColor (0,1,1); dsDrawBox (dBodyGetPosition(body[1]),dBodyGetRotation(body[1]),sides2); } int main (int argc, char **argv) { // setup pointers to drawstuff callback functions dsFunctions fn; fn.version = DS_VERSION; fn.start = &start; fn.step = &simLoop; fn.command = &command; fn.stop = 0; fn.path_to_textures = DRAWSTUFF_TEXTURE_PATH; // create world dInitODE2(0); world = dWorldCreate(); dMass m; dMassSetBox (&m,1,SIDE,SIDE,SIDE); dMassAdjust (&m,MASS); dQuaternion q; dQFromAxisAndAngle (q,1,1,0,0.25*M_PI); body[0] = dBodyCreate (world); dBodySetMass (body[0],&m); dBodySetPosition (body[0],0.5*SIDE,0.5*SIDE,1); dBodySetQuaternion (body[0],q); body[1] = dBodyCreate (world); dBodySetMass (body[1],&m); dBodySetPosition (body[1],-0.5*SIDE,-0.5*SIDE,1); dBodySetQuaternion (body[1],q); hinge = dJointCreateHinge (world,0); dJointAttach (hinge,body[0],body[1]); dJointSetHingeAnchor (hinge,0,0,1); dJointSetHingeAxis (hinge,1,-1,1.41421356); // run simulation dsSimulationLoop (argc,argv,352,288,&fn); dWorldDestroy (world); dCloseODE(); return 0; } ode-0.16/ode/demo/demo_gyroscopic.cpp0000664000175200017520000001534413403272463014535 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include #include "texturepath.h" #ifdef _MSC_VER #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints #endif // select correct drawing functions #ifdef dDOUBLE #define dsDrawBox dsDrawBoxD #define dsDrawSphere dsDrawSphereD #define dsDrawCylinder dsDrawCylinderD #define dsDrawCapsule dsDrawCapsuleD #define dsDrawConvex dsDrawConvexD #endif bool write_world = false; bool show_contacts = false; dWorld * world; dBody *top1, *top2; dSpace *space; dJointGroup contactgroup; const dReal pinradius = 0.05f; const dReal pinlength = 1.5f; const dReal topradius = 1.0f; const dReal toplength = 0.25f; const dReal topmass = 1.0f; #define MAX_CONTACTS 4 static void nearCallback (void *, dGeomID o1, dGeomID o2) { // for drawing the contact points dMatrix3 RI; dRSetIdentity (RI); const dReal ss[3] = {0.02,0.02,0.02}; int i; dBodyID b1 = dGeomGetBody(o1); dBodyID b2 = dGeomGetBody(o2); dContact contact[MAX_CONTACTS]; int numc = dCollide (o1,o2,MAX_CONTACTS,&contact[0].geom, sizeof(dContact)); for (i=0; i= 'A' && c <= 'Z') return c - ('a'-'A'); else return c; } // called when a key pressed static void reset(); static void tilt(); static void command (int cmd) { cmd = locase (cmd); if (cmd == ' ') { reset(); } else if (cmd == 'a') { tilt(); } else if (cmd == 't') { show_contacts = !show_contacts; } else if (cmd == '1') { write_world = true; } } // simulation loop static void simLoop (int pause) { dsSetColor (0,0,2); space->collide(0,&nearCallback); if (!pause) //world->quickStep(0.02); world->step(0.02); if (write_world) { FILE *f = fopen ("state.dif","wt"); if (f) { dWorldExportDIF (*world,f,"X"); fclose (f); } write_world = false; } // remove all contact joints dJointGroupEmpty (contactgroup); dsSetTexture (DS_WOOD); dsSetColor (1,0.5f,0); dsDrawCylinder(top1->getPosition(), top1->getRotation(), toplength, topradius); dsDrawCapsule(top1->getPosition(), top1->getRotation(), pinlength, pinradius); dsSetColor (0.5f,1,0); dsDrawCylinder(top2->getPosition(), top2->getRotation(), toplength, topradius); dsDrawCapsule(top2->getPosition(), top2->getRotation(), pinlength, pinradius); } static void reset() { dMatrix3 R; dRSetIdentity(R); top1->setRotation(R); top2->setRotation(R); top1->setPosition(0.8f, -2, 2); top2->setPosition(0.8f, 2, 2); top1->setAngularVel(1,0,7); top2->setAngularVel(1,0,7); top1->setLinearVel(0,0.2f,0); top2->setLinearVel(0,0.2f,0); } static void tilt() { top1->addTorque(0, 10, 0); top2->addTorque(0, 10, 0); } int main (int argc, char **argv) { // setup pointers to drawstuff callback functions dsFunctions fn; fn.version = DS_VERSION; fn.start = &start; fn.step = &simLoop; fn.command = &command; fn.stop = 0; fn.path_to_textures = DRAWSTUFF_TEXTURE_PATH; // create world dInitODE(); world = new dWorld(); world->setGravity(0,0,-0.5f); world->setCFM(1e-5f); world->setLinearDamping(0.00001f); world->setAngularDamping(0.0001f); space = new dSimpleSpace(0); dPlane *floor = new dPlane(*space, 0,0,1,0); top1 = new dBody(*world); top2 = new dBody(*world); dMass m; m.setCylinderTotal(1, 3, topradius, toplength); top1->setMass(m); top2->setMass(m); dGeom *g1, *g2, *pin1, *pin2; g1 = new dCylinder(*space, topradius, toplength); g1->setBody(*top1); g2 = new dCylinder(*space, topradius, toplength); g2->setBody(*top2); pin1 = new dCapsule(*space, pinradius, pinlength); pin1->setBody(*top1); pin2 = new dCapsule(*space, pinradius, pinlength); pin2->setBody(*top2); top2->setGyroscopicMode(false); reset(); // run simulation dsSimulationLoop (argc,argv,512,384,&fn); delete g1; delete g2; delete pin1; delete pin2; delete floor; contactgroup.empty(); delete top1; delete top2; delete space; delete world; dCloseODE(); } ode-0.16/ode/demo/halton235_geom.h0000664000175200017520000042610113403272463013540 00000000000000// Generated by ./Tools/mksrc.py // h00 const int h00_numv = 14; const int h00_numf = 9; const dReal h00_volu = 0.105869; const dReal h00_pos[3] = { -0.801161,-0.825905,-0.503586 }; const dReal h00_verts[ h00_numv * 3 ] = { -0.198839,-0.174095,-0.496414, -0.198839,-0.073069,-0.496414, 0.355754,-0.174095,0.317906, 0.266263,0.078525,-0.113353, -0.198839,0.418138,0.148658, -0.198839,0.151957,0.285583, -0.004749,-0.165186,-0.496414, -0.198839,0.342511,-0.068863, -0.198839,-0.174095,0.341490, 0.030157,-0.174095,0.397398, -0.005096,-0.174095,-0.496414, 0.428901,-0.174095,0.139324, -0.198839,0.419530,0.145078, -0.111897,0.386202,0.018538, }; const unsigned int h00_faces[] = { 5, 7,13,3,6,1, 4, 6,10,0,1, 7, 0,8,5,4,12,7,1, 6, 11,3,13,12,4,2, 4, 4,5,9,2, 6, 9,8,0,10,11,2, 4, 11,10,6,3, 3, 8,9,5, 3, 12,13,7, }; const dReal h00_planes[ h00_numf * 4 ] = { 0.322183,0.678839,-0.659831,0.213885,0,0,-1,0.496414,-1,3.46515e-16,1.34725e-16,0.198839,0.66261,0.69806,0.271405,0.200478,0.212159,0.447018,0.869002,0.273913,-0,-1,0,0.174095,0.825473,-0.0322069,-0.563523,0.281141,-0.233951,0.164312,0.958263,0.34515,-0.131169,0.932758,-0.335793,0.368685 }; // h01 const int h01_numv = 16; const int h01_numf = 10; const dReal h01_volu = 0.123003; const dReal h01_pos[3] = { -0.669502,-0.555335,-0.800913 }; const dReal h01_verts[ h01_numv * 3 ] = { 0.137874,0.266251,0.316069, -0.136407,-0.435756,-0.199087, -0.330498,0.127352,-0.199087, 0.378917,-0.091301,0.019367, 0.437409,0.033623,-0.016334, 0.038469,0.311615,0.180723, -0.330498,-0.343638,-0.199087, 0.193689,-0.157234,0.188948, 0.276656,-0.200503,-0.199087, 0.399981,0.033623,-0.199087, -0.039317,0.311615,-0.199087, -0.330498,0.071941,0.228464, 0.134604,-0.192045,0.183974, -0.243556,0.115632,0.315865, 0.128360,0.261346,0.324519, -0.053858,0.233367,0.333678, }; const unsigned int h01_faces[] = { 5, 8,3,7,12,1, 5, 12,13,11,6,1, 6, 6,2,10,9,8,1, 6, 11,13,15,5,10,2, 3, 6,11,2, 4, 8,9,4,3, 5, 4,0,14,7,3, 5, 9,10,5,0,4, 4, 15,14,0,5, 5, 14,15,13,12,7, }; const dReal h01_planes[ h01_numf * 4 ] = { 0.485031,-0.851631,0.198669,0.265389,-0.322183,-0.678839,0.659831,0.208392,0,0,-1,0.199087,-0.53156,0.839996,0.108863,0.260981,-1,0,-0,0.330498,0.870584,-0.458578,-0.178296,0.368295,0.693474,-0.121763,0.710118,0.287639,0.531559,0.839996,-0.108863,0.26253,-0.120149,0.911352,0.393704,0.35052,0.0929092,-0.293639,0.951391,0.243929 }; // h02 const int h02_numv = 22; const int h02_numf = 13; const dReal h02_volu = 0.069699; const dReal h02_pos[3] = { -0.226726,-0.554920,-0.490680 }; const dReal h02_verts[ h02_numv * 3 ] = { 0.092179,-0.226103,0.260087, -0.296734,0.272195,0.041665, -0.063859,-0.091716,-0.290866, 0.291800,-0.116083,-0.104671, -0.005367,0.033207,-0.326567, 0.057499,0.071569,-0.315604, -0.314416,0.260931,0.014286, 0.001987,-0.310858,0.106391, 0.200664,0.041526,0.249449, -0.249087,-0.157649,-0.121285, 0.164143,-0.213455,-0.116915, 0.086533,-0.112211,0.311781, 0.301609,-0.100599,-0.031006, -0.013037,0.041374,0.269240, 0.214238,-0.145305,0.159971, -0.177599,0.337949,0.022880, -0.304902,0.265836,0.005836, 0.151444,0.029502,0.298046, 0.226514,0.065723,0.196331, -0.078156,0.329100,-0.024159, 0.053890,0.084483,0.272741, -0.198047,0.327898,0.050872, }; const unsigned int h02_faces[] = { 4, 13,20,21,1, 5, 21,15,16,6,1, 7, 6,9,7,0,11,13,1, 5, 9,6,16,4,2, 5, 4,5,3,10,2, 4, 10,7,9,2, 5, 5,19,18,12,3, 6, 12,14,0,7,10,3, 5, 16,15,19,5,4, 7, 18,19,15,21,20,17,8, 5, 17,11,0,14,8, 4, 14,12,18,8, 4, 17,20,13,11, }; const dReal h02_planes[ h02_numf * 4 ] = { -0.322885,0.43293,0.841615,0.248718,-0.488006,0.871758,-0.0434537,0.380285,-0.73548,-0.309929,0.602505,0.158984,-0.693474,0.121763,-0.710118,0.239666,0.398278,-0.419584,-0.815674,0.250302,-0.11362,-0.877785,-0.465387,0.223128,0.726907,0.646142,-0.23261,0.161453,0.598819,-0.796079,0.0875987,0.257978,-0.27553,0.653111,-0.705358,0.253514,0.315015,0.796483,0.516121,0.225033,0.709719,-0.26169,0.654077,0.294707,0.913105,-0.120244,0.389591,0.275417,-0.158394,0.166869,0.973173,0.270985 }; // h03 const int h03_numv = 18; const int h03_numf = 11; const dReal h03_volu = 0.069585; const dReal h03_pos[3] = { -0.013871,-0.718833,-0.869565 }; const dReal h03_verts[ h03_numv * 3 ] = { -0.207492,-0.281167,-0.130435, 0.113468,0.049972,0.264160, -0.007999,0.353837,-0.130435, 0.078945,0.047830,0.274214, -0.003048,-0.281167,0.119131, -0.048711,-0.049541,0.261970, -0.155356,0.235482,0.063281, 0.163083,-0.281167,0.065052, -0.378975,-0.037005,-0.130435, -0.276714,0.072197,0.088019, 0.263172,-0.281167,-0.130435, 0.247851,0.256254,-0.130435, 0.308871,0.008019,-0.130435, 0.268707,0.210552,0.010520, 0.116203,0.335344,-0.130435, 0.263499,0.226082,-0.009852, -0.255650,0.197121,-0.130435, -0.218222,0.197121,0.052318, }; const unsigned int h03_faces[] = { 7, 13,15,14,2,6,3,1, 5, 3,5,4,7,1, 5, 7,10,12,13,1, 4, 16,17,6,2, 8, 14,11,12,10,0,8,16,2, 5, 6,17,9,5,3, 5, 5,9,8,0,4, 4, 0,10,7,4, 4, 9,17,16,8, 3, 14,15,11, 4, 15,13,12,11, }; const dReal h03_planes[ h03_numf * 4 ] = { 0.119725,0.804079,0.582343,0.207598,0.274018,-0.465094,0.841785,0.230216,0.881437,-0.139289,0.451296,0.212269,-0.53156,0.839996,0.108863,0.287274,0,-0,-1,0.130435,-0.398278,0.419584,0.815674,0.212296,-0.679728,-0.477395,0.556833,0.202635,-0,-1,-0,0.281167,-0.870584,0.458578,0.178296,0.289704,0.509459,0.848006,0.146072,0.324522,0.968964,0.238186,-0.066148,0.309823 }; // h04 const int h04_numv = 18; const int h04_numf = 11; const dReal h04_volu = 0.049776; const dReal h04_pos[3] = { 0.037853,-0.892026,-0.431971 }; const dReal h04_verts[ h04_numv * 3 ] = { -0.100436,0.123651,-0.175624, 0.353999,-0.060233,0.083056, 0.061744,0.223165,-0.173434, -0.054772,-0.107974,-0.318463, 0.079577,0.232813,-0.134685, 0.365414,-0.107974,0.061633, 0.111359,-0.107974,-0.372542, -0.262592,0.026248,0.047682, -0.327682,-0.107974,0.107959, -0.050341,0.191801,0.101262, -0.248632,-0.107974,0.379486, -0.172400,0.111003,0.201378, 0.324182,-0.074827,0.146980, 0.312271,-0.107974,0.174077, -0.248842,-0.086035,0.364515, -0.264984,-0.107974,0.352871, 0.027221,0.221023,-0.163380, 0.037030,0.236507,-0.089715, }; const unsigned int h04_faces[] = { 4, 12,13,5,1, 5, 5,6,2,4,1, 5, 4,17,9,12,1, 4, 16,17,4,2, 5, 6,3,0,16,2, 4, 8,7,0,3, 7, 6,5,13,10,15,8,3, 5, 8,15,14,11,7, 6, 11,9,17,16,0,7, 6, 11,14,10,13,12,9, 3, 14,15,10, }; const dReal h04_planes[ h04_numf * 4 ] = { 0.903842,0.0244154,0.42717,0.353968,0.79204,0.397342,-0.463457,0.217956,0.496382,0.766976,0.406636,0.163295,-0.11569,0.975032,-0.189546,0.243324,-0.274018,0.465094,-0.841785,0.232868,-0.83085,0.164121,-0.531744,0.197127,0,-1,0,0.107974,-0.837582,0.502473,0.214421,0.243355,-0.598819,0.796079,-0.0875987,0.173963,0.289106,0.541464,0.789452,0.169241,-0.80443,0.32957,0.494242,0.35198 }; // h05 const int h05_numv = 12; const int h05_numf = 8; const dReal h05_volu = 0.060052; const dReal h05_pos[3] = { -0.361440,-0.882680,-0.728709 }; const dReal h05_verts[ h05_numv * 3 ] = { -0.444817,-0.117320,-0.271291, 0.140076,-0.117320,-0.271291, 0.136701,0.016901,0.344420, -0.031407,0.126842,-0.271291, 0.070855,0.236044,-0.052837, -0.114373,0.170111,0.116744, 0.344521,-0.117320,-0.021725, 0.298857,0.114305,0.121114, -0.444469,-0.108411,-0.271291, 0.071611,-0.117320,0.404697, -0.173458,0.135300,0.111770, -0.010820,-0.117320,0.364447, }; const unsigned int h05_faces[] = { 5, 3,4,7,6,1, 5, 6,9,11,0,1, 4, 0,8,3,1, 5, 5,10,11,9,2, 4, 9,6,7,2, 4, 7,4,5,2, 5, 8,10,5,4,3, 4, 0,11,10,8, }; const dReal h05_planes[ h05_numf * 4 ] = { 0.679728,0.477395,-0.556833,0.190269,0,-1,0,0.11732,0,0,-1,0.271291,-0.373525,0.524676,0.76498,0.221281,0.83085,-0.164121,0.531744,0.293948,0.11362,0.877785,0.465387,0.190656,-0.485031,0.851631,-0.198669,0.177153,-0.825473,0.0322069,0.563523,0.210527 }; // h06 const int h06_numv = 16; const int h06_numf = 10; const dReal h06_volu = 0.067458; const dReal h06_pos[3] = { 0.885250,-0.616510,-0.689541 }; const dReal h06_verts[ h06_numv * 3 ] = { -0.230633,-0.043361,0.025874, -0.001305,-0.383490,-0.079103, 0.114750,-0.383490,0.055891, 0.114750,0.141993,-0.310459, 0.042572,0.157183,0.322917, 0.114750,0.349093,0.009138, 0.114750,-0.209139,-0.310459, 0.114750,-0.383490,-0.220772, 0.114750,0.143660,0.326163, -0.023969,0.120047,-0.310459, -0.230634,0.218132,-0.108639, -0.072958,0.349093,0.054965, -0.138827,-0.119612,0.199579, 0.020027,-0.383490,0.025057, -0.041036,-0.038390,0.301047, 0.114750,-0.091790,0.305977, }; const unsigned int h06_faces[] = { 6, 0,10,9,6,7,1, 4, 7,2,13,1, 4, 13,12,0,1, 5, 15,14,12,13,2, 7, 7,6,3,5,8,15,2, 5, 9,10,11,5,3, 3, 6,9,3, 4, 14,15,8,4, 4, 8,5,11,4, 6, 11,10,0,12,14,4, }; const dReal h06_planes[ h06_numf * 4 ] = { -0.735479,-0.309932,-0.602505,0.167476,0,-1,0,0.38349,-0.794108,-0.585614,0.162633,0.212748,-0.239912,-0.631869,0.73701,0.255977,1,-0,0,0.11475,-0.131611,0.831909,-0.539079,0.270385,0,0,-1,0.310459,-0.0606999,-0.0852635,0.994508,0.305158,0.131611,0.831909,0.539078,0.310442,-0.793214,0.278548,0.541501,0.184874 }; // h07 const int h07_numv = 18; const int h07_numf = 11; const dReal h07_volu = 0.100040; const dReal h07_pos[3] = { 0.439796,-0.816642,-0.690430 }; const dReal h07_verts[ h07_numv * 3 ] = { -0.290584,-0.183358,-0.114083, 0.444149,-0.183358,-0.078214, -0.340199,0.147781,0.085025, -0.036530,-0.183358,0.320092, -0.047944,-0.135617,0.341515, 0.306627,0.080520,0.200468, -0.322367,0.157429,0.123774, 0.465481,-0.183358,0.025945, 0.214820,0.156771,0.026763, -0.144796,0.105827,-0.309570, 0.159858,-0.183358,-0.309570, -0.190496,-0.183358,-0.309570, -0.155412,0.298926,0.091748, -0.184960,0.308361,-0.168615, -0.134267,0.332806,-0.106403, 0.196572,0.110989,0.274357, -0.157992,0.325768,-0.131745, -0.142419,0.333870,-0.095406, }; const unsigned int h07_faces[] = { 7, 10,9,13,16,14,8,1, 4, 8,5,7,1, 6, 7,3,0,11,10,1, 6, 6,12,17,16,13,2, 5, 13,9,11,0,2, 5, 0,3,4,6,2, 5, 7,5,15,4,3, 4, 15,12,6,4, 6, 8,14,17,12,15,5, 3, 10,11,9, 3, 16,17,14, }; const dReal h07_planes[ h07_numf * 4 ] = { 0.525603,0.55372,-0.645861,0.182432,0.794108,0.585614,-0.162633,0.258045,0,-1,0,0.183358,-0.632147,0.768422,0.0995875,0.337082,-0.881437,0.139289,-0.451296,0.282078,-0.79204,-0.397342,0.463457,0.250137,0.488522,-0.25733,0.833743,0.296212,-0.212159,0.447016,0.869003,0.246326,0.381225,0.903643,0.195187,0.228784,-1.58443e-16,2.50379e-17,-1,0.30957,-0.105626,0.979232,-0.173057,0.35849 }; // h08 const int h08_numv = 22; const int h08_numf = 13; const dReal h08_volu = 0.095115; const dReal h08_pos[3] = { 0.582909,-0.382310,-0.514785 }; const dReal h08_verts[ h08_numv * 3 ] = { 0.039696,0.333763,-0.114253, -0.040720,0.073975,-0.343437, -0.281418,0.194479,0.107755, 0.071707,-0.016068,-0.283395, 0.071707,-0.277561,-0.148882, 0.163514,-0.353812,0.024824, 0.072380,0.310495,-0.182078, 0.344912,-0.077018,0.148161, 0.229382,0.114893,-0.119790, 0.056106,0.251986,0.176207, 0.261304,-0.272590,0.126291, 0.053460,-0.323343,0.098712, -0.280479,0.198156,0.096008, -0.285532,-0.100462,-0.271051, 0.094134,-0.250952,0.200497, -0.277380,-0.101526,-0.282048, -0.010614,0.002589,0.315575, -0.026292,0.211375,0.249710, 0.146296,0.123570,0.286302, 0.056041,0.119791,0.321947, -0.290185,0.102104,0.127875, -0.298525,-0.135406,-0.083897, }; const unsigned int h08_faces[] = { 6, 15,13,12,0,6,1, 4, 6,8,3,1, 4, 3,4,15,1, 5, 20,16,19,17,2, 5, 17,9,0,12,2, 5, 12,13,21,20,2, 6, 8,7,10,5,4,3, 6, 5,11,21,13,15,4, 4, 10,14,11,5, 6, 0,9,18,7,8,6, 6, 18,19,16,14,10,7, 4, 17,19,18,9, 5, 14,16,20,21,11, }; const dReal h08_planes[ h08_numf * 4 ] = { -0.595386,0.627237,-0.502085,0.243079,0.598205,0.236327,-0.765702,0.256094,0.107916,-0.45476,-0.884052,0.265581,-0.484779,0.229821,0.843903,0.272055,-0.215549,0.936705,0.275902,0.272559,-0.995125,0.0827659,-0.053632,0.290362,0.793214,-0.278548,-0.541501,0.214813,-0.381225,-0.903643,-0.195187,0.252539,0.131611,-0.83191,0.539077,0.329242,0.750032,0.646492,0.139642,0.229594,0.364346,-0.255892,0.895417,0.278042,0.228161,0.721101,0.654183,0.30978,-0.595564,-0.522855,0.609857,0.197424 }; // h09 const int h09_numv = 16; const int h09_numf = 10; const dReal h09_volu = 0.059582; const dReal h09_pos[3] = { 0.627742,-0.657906,-0.898694 }; const dReal h09_verts[ h09_numv * 3 ] = { -0.028087,-0.342094,-0.101306, 0.372258,-0.342094,-0.101306, 0.233539,0.161443,-0.101306, 0.372258,-0.167743,-0.101306, 0.256203,-0.342094,0.130050, 0.372258,-0.342094,-0.011619, -0.322212,0.174071,0.101861, 0.026875,-0.001965,0.235027, -0.098160,0.388838,-0.101306, 0.026875,0.259528,0.100514, -0.332742,-0.052909,-0.101306, -0.085552,0.349571,0.040471, -0.393762,0.195327,-0.101306, -0.372906,0.149626,0.039648, -0.378114,0.165155,0.019276, -0.345937,0.167033,0.076519, }; const unsigned int h09_faces[] = { 7, 0,10,12,8,2,3,1, 3, 3,5,1, 4, 5,4,0,1, 4, 8,11,9,2, 6, 9,7,4,5,3,2, 7, 7,6,15,13,10,0,4, 6, 11,8,12,14,15,6, 4, 7,9,11,6, 4, 13,14,12,10, 3, 15,14,13, }; const dReal h09_planes[ h09_numf * 4 ] = { 0,0,-1,0.101306,1,0,0,0.372258,0,-1,0,0.342094,0.55667,0.812007,0.175394,0.243329,0.735479,0.309932,0.602505,0.160762,-0.525603,-0.55372,0.645861,0.138757,-0.527367,0.805591,0.270012,0.337657,-0.107916,0.45476,0.884052,0.203982,-0.968964,-0.238186,0.066148,0.328316,-0.830322,0.320028,0.456232,0.375605 }; // h10 const int h10_numv = 18; const int h10_numf = 11; const dReal h10_volu = 0.082139; const dReal h10_pos[3] = { -0.348593,-0.203405,-0.827574 }; const dReal h10_verts[ h10_numv * 3 ] = { 0.351136,-0.038001,-0.172426, 0.318157,0.110282,-0.172426, -0.183035,-0.085679,0.342730, -0.360226,-0.040315,-0.172426, 0.190400,0.248876,-0.172426, 0.296736,0.161596,-0.025823, 0.116500,-0.318307,0.010327, -0.282440,-0.040315,0.207384, -0.155944,0.334915,-0.140051, -0.055732,-0.013566,0.359774, 0.296359,0.169251,-0.045236, -0.155944,0.347503,-0.172426, 0.079072,-0.318307,-0.172426, 0.043711,-0.022416,0.312735, 0.326723,-0.161591,-0.172426, 0.179366,-0.279946,0.021290, 0.100706,0.105108,0.263039, 0.042697,0.111008,0.290353, }; const unsigned int h10_faces[] = { 4, 10,5,0,1, 7, 0,14,12,3,11,4,1, 3, 4,10,1, 5, 6,15,13,9,2, 5, 9,17,8,7,2, 5, 7,3,12,6,2, 4, 7,8,11,3, 7, 11,8,17,16,5,10,4, 6, 16,13,15,14,0,5, 4, 12,14,15,6, 4, 13,16,17,9, }; const dReal h10_planes[ h10_numf * 4 ] = { 0.973989,0.216619,0.066491,0.322306,-0,0,-1,0.172426,0.722579,0.66608,-0.18498,0.335245,0.27553,-0.653111,0.705358,0.247274,-0.46199,0.681388,0.567693,0.220745,-0.531559,-0.839996,0.108863,0.206575,-0.870584,0.458578,0.178296,0.264376,0.256529,0.900843,0.350248,0.212649,0.830851,-0.164118,0.531744,0.206291,0.53156,-0.839996,-0.108863,0.328179,0.433652,0.152283,0.888119,0.293288 }; // h11 const int h11_numv = 18; const int h11_numf = 11; const dReal h11_volu = 0.058443; const dReal h11_pos[3] = { -0.902277,0.042835,-0.283464 }; const dReal h11_verts[ h11_numv * 3 ] = { 0.065494,-0.341848,-0.057123, 0.194525,0.153131,-0.091230, -0.097723,-0.350111,0.163707, 0.194525,-0.144351,0.061796, 0.065493,0.122511,-0.295991, -0.097723,-0.183345,0.306682, -0.097723,0.152153,0.335446, -0.097723,-0.428001,-0.052654, 0.107269,-0.156775,0.196004, -0.097723,0.199975,-0.375687, 0.037223,0.358435,0.033582, -0.097723,0.406471,-0.057020, -0.067761,-0.416891,-0.051054, -0.040073,-0.340339,0.134552, 0.056142,-0.350169,-0.055126, 0.004412,-0.376327,-0.008857, 0.025793,-0.108438,0.290488, -0.096343,0.152412,0.335215, }; const unsigned int h11_faces[] = { 5, 4,9,11,10,1, 6, 10,17,16,8,3,1, 4, 3,0,4,1, 5, 7,12,15,13,2, 5, 13,8,16,5,2, 6, 5,6,11,9,7,2, 6, 8,13,15,14,0,3, 6, 0,14,12,7,9,4, 4, 16,17,6,5, 4, 17,10,11,6, 3, 14,15,12, }; const dReal h11_planes[ h11_numf * 4 ] = { 0.553062,0.69918,-0.453068,0.255983,0.793213,0.278551,0.5415,0.147553,0.835369,-0.251444,-0.48881,0.168589,0.314046,-0.893286,0.321583,0.334705,0.443092,-0.583496,0.68059,0.272405,-1,0,0,0.0977235,0.66062,-0.653782,0.368986,0.245683,0.212159,-0.447018,-0.869002,0.216347,0.179474,-0.0840327,0.980167,0.298468,-0.066237,0.837367,0.542613,0.315898,0.474713,-0.879502,0.0335246,0.332778 }; // h12 const int h12_numv = 22; const int h12_numf = 13; const dReal h12_volu = 0.106128; const dReal h12_pos[3] = { -0.838340,-0.076123,-0.758521 }; const dReal h12_verts[ h12_numv * 3 ] = { 0.207307,-0.167597,0.138331, 0.129521,-0.167597,-0.241479, -0.161660,0.318933,0.099371, 0.312802,0.272050,-0.241479, -0.161660,-0.330252,0.400013, -0.074718,-0.363580,0.273473, 0.001556,0.241469,0.179066, -0.161660,-0.309043,0.422403, -0.161660,-0.407271,0.186072, -0.161660,-0.351860,-0.241479, -0.007794,-0.231211,0.419931, 0.001557,-0.222890,0.417934, 0.309084,0.269226,-0.210613, -0.161660,0.422173,-0.241479, 0.072963,0.309250,0.057032, -0.161660,0.392766,-0.014569, -0.131698,-0.297933,0.424004, -0.161660,-0.327468,0.404309, 0.114980,-0.245845,0.291286, 0.009169,-0.227496,0.411012, 0.333803,0.207633,-0.209104, 0.333803,0.220221,-0.241479, }; const unsigned int h12_faces[] = { 6, 0,18,5,8,9,1, 5, 9,13,3,21,1, 4, 21,20,0,1, 4, 6,14,15,2, 8, 15,13,9,8,4,17,7,2, 6, 7,16,10,11,6,2, 4, 12,20,21,3, 5, 13,15,14,12,3, 7, 5,18,19,10,16,17,4, 3, 8,5,4, 8, 11,19,18,0,20,12,14,6, 3, 17,16,7, 3, 19,11,10, }; const dReal h12_planes[ h12_numf * 4 ] = { 0.53156,-0.839996,-0.108863,0.235917,0,0,-1,0.241479,0.870584,-0.458578,-0.178296,0.23267,0.131611,0.83191,0.539077,0.297616,-1,0,0,0.16166,-0.212159,0.447018,0.869002,0.263219,0.917084,0.371595,0.144476,0.353071,0.299389,0.946218,0.12263,0.321456,0.425203,-0.759567,0.4922,0.378997,0.131169,-0.932758,0.335793,0.421162,0.735479,0.309932,0.602505,0.183872,0.216442,-0.684063,0.696571,0.470649,0.494656,-0.366713,0.787932,0.411811 }; // h13 const int h13_numv = 22; const int h13_numf = 13; const dReal h13_volu = 0.080573; const dReal h13_pos[3] = { -0.579196,0.019592,-0.524795 }; const dReal h13_verts[ h13_numv * 3 ] = { -0.186181,0.213535,-0.176694, 0.154423,-0.034973,0.266436, 0.105286,0.335497,0.021835, 0.055737,-0.302317,0.075780, -0.128556,-0.121108,0.303127, 0.252786,0.058395,0.170378, -0.257588,0.145754,-0.054660, 0.097995,0.334920,0.024505, 0.093556,-0.038093,0.287537, 0.074659,0.111918,-0.442830, -0.051837,-0.263312,-0.095394, -0.257587,-0.318605,0.184208, 0.273300,-0.111989,-0.012426, 0.049940,0.173511,-0.444339, -0.026589,0.239892,0.129875, -0.128556,0.176374,0.150102, 0.038054,-0.313581,0.048402, 0.047568,-0.308676,0.039952, -0.249976,-0.323211,0.177286, -0.144164,-0.341560,0.057561, 0.174871,-0.236563,0.056995, 0.154423,-0.246614,0.084987, }; const unsigned int h13_faces[] = { 5, 21,20,12,5,1, 6, 5,2,7,14,8,1, 7, 8,4,11,18,3,21,1, 5, 5,12,9,13,2, 4, 13,0,7,2, 5, 16,17,20,21,3, 4, 18,19,16,3, 4, 8,14,15,4, 4, 15,6,11,4, 5, 15,14,7,0,6, 8, 0,13,9,10,19,18,11,6, 5, 12,20,17,10,9, 4, 17,16,19,10, }; const dReal h13_planes[ h13_numf * 4 ] = { 0.805487,-0.385719,0.449901,0.257745,0.24653,0.556538,0.793403,0.229997,0.284317,-0.624016,0.727852,0.259655,0.904761,0.357436,-0.231619,0.21012,-0.184883,0.934913,-0.302912,0.287581,0.488006,-0.871758,0.0434537,0.29404,0.159459,-0.944944,0.285751,0.316215,-0.107916,0.45476,0.884052,0.226779,-0.835369,0.251444,0.48881,0.225111,-0.493234,0.850287,0.183662,0.240945,-0.735479,-0.309932,-0.602505,0.17721,0.46199,-0.681388,-0.567693,0.209624,0.120149,-0.911352,-0.393704,0.271298 }; // h14 const int h14_numv = 24; const int h14_numf = 14; const dReal h14_volu = 0.092625; const dReal h14_pos[3] = { 0.037294,-0.326434,-0.629340 }; const dReal h14_verts[ h14_numv * 3 ] = { 0.244511,-0.164440,-0.192835, -0.034752,0.085028,-0.370660, -0.037506,-0.162763,0.334991, -0.206521,-0.156917,-0.176944, 0.151340,0.267484,0.166363, 0.265137,0.142280,0.210563, 0.260084,-0.156338,-0.156496, -0.285181,0.228137,0.064806, 0.037588,-0.329085,0.107655, -0.342176,0.100614,0.114501, 0.027780,-0.344569,0.033990, -0.089151,0.284625,-0.224057, -0.059164,-0.038562,-0.370660, 0.065038,-0.057055,-0.370660, 0.036995,0.362842,0.085406, 0.062303,-0.342427,0.023935, 0.217542,-0.181847,-0.229705, 0.212334,-0.166317,-0.250077, 0.224212,0.171137,0.236256, 0.080136,-0.332779,0.062684, 0.146779,-0.002116,0.303773, 0.264198,0.138603,0.222310, 0.247091,-0.191282,0.030659, 0.255431,0.046228,0.242430, }; const unsigned int h14_faces[] = { 6, 12,3,9,7,11,1, 9, 11,14,4,5,6,0,17,13,1, 3, 13,12,1, 6, 8,19,22,23,20,2, 7, 20,18,4,14,7,9,2, 5, 9,3,10,8,2, 7, 12,13,17,16,15,10,3, 4, 18,21,5,4, 5, 21,23,22,6,5, 6, 22,19,15,16,0,6, 3, 14,11,7, 4, 10,15,19,8, 3, 17,0,16, 4, 20,23,21,18, }; const dReal h14_planes[ h14_numf * 4 ] = { -0.830851,0.164118,-0.531744,0.239924,0.738081,0.518376,-0.431883,0.178509,0,0,-1,0.37066,0.582463,-0.552262,0.596442,0.267845,-0.240814,0.443968,0.863077,0.225893,-0.726907,-0.646142,0.23261,0.210353,-0.119725,-0.804079,-0.582343,0.253941,0.662611,0.698059,0.271405,0.33215,0.995125,-0.0827659,0.053632,0.263362,0.632147,-0.768422,-0.0995875,0.300129,-0.380333,0.921564,-0.0778922,0.313659,0.11569,-0.975032,0.189546,0.345622,0.830322,-0.320028,-0.456232,0.343625,0.433652,0.152283,0.888119,0.333115 }; // h15 const int h15_numv = 16; const int h15_numf = 10; const dReal h15_volu = 0.047330; const dReal h15_pos[3] = { 0.221274,0.213040,-0.893886 }; const dReal h15_verts[ h15_numv * 3 ] = { -0.273508,-0.247194,0.021075, -0.214206,0.249387,-0.106114, -0.394680,0.092354,-0.106114, 0.468273,-0.026582,-0.106114, -0.379467,-0.167569,-0.106114, -0.251710,-0.306163,-0.106114, -0.130453,-0.090301,0.212222, 0.215618,0.100683,0.162583, 0.108399,0.111587,0.216806, 0.543500,0.089559,-0.106114, 0.556660,0.080198,-0.106114, 0.496376,0.018888,-0.040935, 0.000444,-0.021162,0.246756, 0.322381,0.024676,0.097420, 0.541635,0.087788,-0.096097, 0.556215,0.081512,-0.106114, }; const unsigned int h15_faces[] = { 5, 2,6,12,8,1, 5, 8,7,14,9,1, 8, 9,15,10,3,5,4,2,1, 4, 4,0,6,2, 3, 10,11,3, 7, 11,13,12,6,0,5,3, 3, 5,0,4, 6, 13,11,10,15,14,7, 4, 8,12,13,7, 3, 14,15,9, }; const dReal h15_planes[ h15_numf * 4 ] = { -0.469359,0.539421,0.69909,0.160881,0.201934,0.957321,0.206781,0.173545,0,0,-1,0.106114,-0.781405,-0.0457332,0.622346,0.238142,0.765488,-0.633631,0.11198,0.363418,0.324513,-0.835692,0.443069,0.127159,-0.722579,-0.66608,0.18498,0.366181,0.613049,0.207593,0.762283,0.27702,0.433652,-0.152283,0.888119,0.222564,0.518906,0.82,0.241527,0.329834 }; // h16 const int h16_numv = 24; const int h16_numf = 14; const dReal h16_volu = 0.105221; const dReal h16_pos[3] = { -0.230932,0.200668,-0.677519 }; const dReal h16_verts[ h16_numv * 3 ] = { 0.072738,-0.155197,-0.322481, 0.178698,-0.234822,-0.195293, -0.074965,-0.293065,0.140297, -0.273605,-0.069158,-0.290106, -0.242978,0.154421,0.174559, 0.321753,-0.077929,-0.004145, 0.331656,-0.130769,0.158361, -0.234281,0.105965,-0.322481, 0.057526,0.104725,-0.322481, -0.070916,0.357222,-0.022485, 0.179075,-0.242477,-0.175878, 0.305221,-0.164260,0.133584, 0.289986,0.017556,0.326217, -0.205442,0.224195,0.181431, -0.273605,-0.056571,-0.322481, -0.016955,-0.298965,0.112984, -0.012263,0.183238,-0.322481, -0.122870,0.351842,-0.002882, -0.294606,-0.004741,-0.322481, -0.298324,-0.007565,-0.291615, 0.354068,-0.072999,0.110530, 0.306083,0.044665,0.287425, 0.072223,0.006072,0.394149, -0.095479,-0.122681,0.323101, }; const unsigned int h16_faces[] = { 7, 10,15,2,3,14,0,1, 4, 0,8,5,1, 6, 5,20,6,11,10,1, 7, 15,11,6,12,22,23,2, 5, 23,4,19,3,2, 4, 19,18,14,3, 4, 23,22,13,4, 6, 13,17,7,18,19,4, 6, 8,16,9,21,20,5, 4, 20,21,12,6, 4, 17,9,16,7, 6, 16,8,0,14,18,7, 6, 17,13,22,12,21,9, 3, 11,15,10, }; const dReal h16_planes[ h16_numf * 4 ] = { -0.256529,-0.900843,-0.350248,0.234098,0.781405,0.0457332,-0.622346,0.250435,0.837582,-0.502473,-0.214421,0.309541,0.247318,-0.694798,0.675344,0.27983,-0.904761,-0.357436,0.231619,0.205073,-0.917084,-0.371595,-0.144476,0.318531,-0.501077,0.186311,0.84511,0.298042,-0.876412,0.477567,-0.0618929,0.275891,0.726908,0.64614,-0.232611,0.184496,0.941719,-0.0992098,0.32144,0.376203,-0.28037,0.805551,-0.521997,0.31938,0,0,-1,0.322481,0.148211,0.780702,0.607074,0.254723,0.380333,-0.921564,0.0778922,0.277867 }; // h17 const int h17_numv = 26; const int h17_numf = 15; const dReal h17_volu = 0.108916; const dReal h17_pos[3] = { 0.335926,-0.094685,-0.795267 }; const dReal h17_verts[ h17_numv * 3 ] = { 0.319363,0.022871,0.098404, -0.388160,0.060531,-0.077543, 0.353621,0.281144,-0.204733, 0.207729,0.332401,-0.001198, 0.193656,-0.174383,-0.204733, -0.101947,-0.367894,-0.204733, -0.366362,0.001562,-0.204733, -0.261637,0.131093,0.251333, 0.356211,0.239639,0.008049, -0.212790,0.222354,0.228279, -0.038549,-0.388087,0.009431, -0.033495,-0.089469,0.376490, -0.054122,-0.396189,-0.026907, 0.286680,0.046139,0.166229, 0.206263,-0.213650,-0.062955, -0.030396,-0.389151,-0.001566, -0.086298,-0.398066,-0.084150, -0.233594,-0.288804,-0.204733, -0.114208,0.286563,0.148137, -0.245105,0.217424,0.113603, 0.376946,0.258587,-0.036908, 0.381724,0.326613,-0.139554, -0.147292,0.035735,0.332290, -0.235202,0.164584,0.276109, -0.333383,-0.146721,-0.204733, -0.387783,0.052876,-0.058130, }; const unsigned int h17_faces[] = { 4, 6,24,25,1, 6, 25,7,23,9,19,1, 7, 19,18,3,21,2,6,1, 6, 21,20,0,14,4,2, 6, 4,5,17,24,6,2, 4, 8,20,21,3, 8, 18,9,23,22,11,13,8,3, 6, 14,15,12,16,5,4, 3, 16,17,5, 3, 22,23,7, 9, 25,24,17,16,12,10,11,22,7, 4, 13,0,20,8, 3, 18,19,9, 6, 15,14,0,13,11,10, 3, 12,15,10, }; const dReal h17_planes[ h17_numf * 4 ] = { -0.973989,-0.216619,-0.066491,0.370108,-0.837582,0.502473,0.214421,0.338905,-0.324513,0.835692,-0.443069,0.210905,0.929286,-0.326334,-0.173016,0.27229,-4.07036e-16,-9.05266e-17,-1,0.204733,0.43192,0.742413,0.512121,0.335888,0.289106,0.541464,0.789452,0.239093,0.527367,-0.805591,-0.270012,0.297889,-0.509459,-0.848006,-0.146072,0.39382,-0.621965,-0.0849382,0.778424,0.347238,-0.738081,-0.518376,0.431883,0.2337,0.903842,0.0244154,0.42717,0.331247,-0.485104,0.868795,0.0993492,0.319085,0.595386,-0.627237,0.502085,0.225206,0.105626,-0.979232,0.173057,0.377587 }; // h18 const int h18_numv = 18; const int h18_numf = 11; const dReal h18_volu = 0.081077; const dReal h18_pos[3] = { 0.870716,-0.039183,-0.528244 }; const dReal h18_verts[ h18_numv * 3 ] = { -0.102809,0.184137,0.110997, 0.129284,0.393063,-0.471756, 0.129284,0.325763,0.151471, 0.124364,0.395398,-0.471756, -0.058424,-0.228234,-0.106332, 0.057106,-0.420144,0.161620, -0.248110,-0.009363,-0.100794, -0.231701,-0.091141,0.189666, 0.129284,-0.228234,-0.152159, 0.129284,-0.433667,0.164866, 0.129284,-0.166980,0.404939, -0.141510,-0.219557,0.299761, 0.129284,0.397646,-0.471756, -0.215427,-0.032631,-0.168619, 0.102902,0.388713,-0.463077, 0.129284,0.404181,-0.453605, -0.178579,0.184137,-0.258974, -0.157844,0.203085,-0.303931, }; const unsigned int h18_faces[] = { 7, 8,4,13,17,14,3,1, 3, 3,12,1, 7, 12,15,2,10,9,8,1, 6, 15,14,17,16,0,2, 5, 0,7,11,10,2, 4, 14,15,12,3, 6, 5,11,7,6,13,4, 4, 8,9,5,4, 4, 9,10,11,5, 4, 16,17,13,6, 4, 7,0,16,6, }; const dReal h18_planes[ h18_numf * 4 ] = { -0.212159,-0.447018,-0.869002,0.206822,0,-0,-1,0.471756,1,0,-0,0.129284,-0.53156,0.839996,0.108863,0.221407,-0.398278,0.419585,0.815673,0.208745,-0.395039,0.86436,-0.311169,0.439434,-0.750032,-0.646492,-0.139642,0.206219,-0.131611,-0.831909,-0.539078,0.25488,-0.156805,-0.660773,0.734024,0.387299,-0.903842,-0.0244154,-0.42717,0.267537,-0.870583,0.45858,0.178295,0.193736 }; // h19 const int h19_numv = 16; const int h19_numf = 10; const dReal h19_volu = 0.057269; const dReal h19_pos[3] = { 0.808301,-0.134672,-0.879100 }; const dReal h19_verts[ h19_numv * 3 ] = { 0.052980,-0.361791,-0.120900, 0.191699,-0.339845,-0.120900, -0.030366,0.427910,-0.120900, 0.191699,0.488552,-0.120900, -0.118754,0.321131,-0.120900, 0.191699,-0.132745,0.198697, 0.186779,0.490887,-0.120900, 0.003992,-0.132745,0.244524, -0.153012,0.062857,0.182237, -0.153685,-0.263706,0.080920, -0.278719,-0.134396,-0.120900, -0.266112,-0.173663,0.020877, -0.090651,0.366600,-0.055721, -0.095429,0.298574,0.046924, -0.012422,0.433588,-0.120900, 0.165316,0.484202,-0.112221, }; const unsigned int h19_faces[] = { 5, 5,7,9,0,1, 8, 0,10,4,2,14,6,3,1, 3, 3,5,1, 5, 12,13,15,14,2, 3, 4,12,2, 7, 6,15,13,8,7,5,3, 6, 10,11,8,13,12,4, 3, 14,15,6, 4, 8,11,9,7, 4, 11,10,0,9, }; const dReal h19_planes[ h19_numf * 4 ] = { 0.131611,-0.831909,0.539079,0.242775,-4.33777e-17,-9.13967e-17,-1,0.1209,1,0,0,0.191699,-0.256638,0.811103,0.525594,0.291328,-0.765488,0.633631,-0.11198,0.307921,0.212159,0.447018,0.869002,0.153999,-0.929286,0.326334,0.173016,0.194234,-0.275992,0.959497,0.0565231,0.412621,-0.598205,-0.236327,0.765702,0.216216,-0.55667,-0.812007,-0.175394,0.28549 }; // h20 const int h20_numv = 30; const int h20_numf = 17; const dReal h20_volu = 0.107509; const dReal h20_pos[3] = { 0.402458,0.140897,-0.404353 }; const dReal h20_verts[ h20_numv * 3 ] = { -0.100408,0.282050,-0.142576, 0.065914,0.236686,0.319509, -0.125820,0.203801,0.337118, 0.365449,0.004057,-0.012894, 0.056400,0.231781,0.327959, 0.034434,0.172826,-0.326950, -0.072786,0.183730,-0.272727, -0.247229,0.030507,0.295489, 0.136546,-0.281738,0.161639, 0.289679,0.004057,-0.382865, 0.141197,0.096819,-0.392113, -0.100966,-0.328728,-0.002677, -0.140953,-0.296194,0.011269, -0.180740,0.050981,-0.242777, -0.253566,0.024492,0.286206, -0.033492,0.282050,0.184162, 0.236557,-0.271221,0.065774, 0.154159,-0.311832,0.139278, -0.301735,-0.070997,-0.114805, -0.213824,-0.199847,-0.058625, -0.310451,0.100424,0.233258, -0.241567,0.131963,0.326249, -0.062874,0.247232,-0.227963, -0.327109,0.098788,0.164544, -0.279322,-0.013228,-0.162635, -0.343405,0.077327,0.053051, -0.313038,0.127071,0.015013, -0.327307,0.104436,0.014259, -0.100027,-0.325051,-0.014425, 0.220147,-0.189444,-0.224685, }; const unsigned int h20_faces[] = { 8, 3,9,10,5,22,0,15,1, 4, 15,2,4,1, 6, 4,8,17,16,3,1, 7, 15,0,26,23,20,21,2, 5, 21,7,8,4,2, 4, 16,29,9,3, 3, 6,22,5, 4, 10,13,6,5, 7, 13,24,27,26,0,22,6, 6, 14,12,11,17,8,7, 4, 21,20,14,7, 8, 29,28,19,18,24,13,10,9, 5, 28,29,16,17,11, 4, 12,19,28,11, 7, 14,20,23,25,18,19,12, 4, 25,27,24,18, 4, 26,27,25,23, }; const dReal h20_planes[ h20_numf * 4 ] = { 0.531561,0.839995,-0.108864,0.199069,-0.120149,0.911351,0.393704,0.333576,0.693474,-0.121763,0.710118,0.243778,-0.53156,0.839996,0.108863,0.274773,0.0929092,-0.293639,0.951391,0.249197,0.870583,-0.45858,-0.178295,0.318592,-0.320422,0.578682,-0.749971,0.334181,-0.433652,0.152283,-0.888119,0.301757,-0.720506,0.471135,-0.508826,0.277775,-0.322183,-0.678839,0.659831,0.253916,-0.770892,-0.145024,0.620237,0.369436,-0.289106,-0.541464,-0.789452,0.21631,0.215549,-0.936705,-0.275902,0.286897,-0.662611,-0.698059,-0.271405,0.297099,-0.847832,-0.483811,0.217045,0.265252,-0.941719,0.0992098,-0.32144,0.314009,-0.846082,0.532633,0.0211314,0.332856 }; // h21 const int h21_numv = 20; const int h21_numf = 12; const dReal h21_volu = 0.107886; const dReal h21_pos[3] = { -0.701261,0.516623,-0.734170 }; const dReal h21_verts[ h21_numv * 3 ] = { 0.220060,-0.162111,0.233880, -0.071194,0.139979,-0.265830, 0.326350,0.086982,0.076961, 0.175723,-0.320696,-0.265830, -0.194481,0.286846,0.262411, 0.236048,-0.209990,-0.265830, -0.298739,0.200252,0.166960, 0.264887,-0.091760,0.238083, 0.347459,0.035887,0.053770, -0.298739,0.031984,-0.265830, -0.298739,-0.199980,-0.038920, -0.298739,-0.170573,-0.265830, -0.064116,-0.283496,0.032682, 0.172005,-0.323520,-0.234964, 0.067327,0.317485,0.021628, 0.227351,-0.161534,0.231210, 0.015724,0.286846,0.365050, -0.065674,0.367082,0.311546, 0.153155,0.171345,0.362933, 0.139764,0.180879,0.371107, }; const unsigned int h21_faces[] = { 6, 9,6,4,17,14,1, 5, 14,2,8,5,1, 5, 5,3,11,9,1, 4, 18,7,8,2, 6, 14,17,16,19,18,2, 6, 5,8,7,15,13,3, 5, 13,12,10,11,3, 3, 16,17,4, 7, 6,10,12,0,19,16,4, 4, 9,11,10,6, 5, 18,19,0,15,7, 4, 13,15,0,12, }; const dReal h21_planes[ h21_numf * 4 ] = { -0.404539,0.852363,-0.331398,0.236209,0.595564,0.522855,-0.609857,0.192906,-1.16998e-16,-0,-1,0.26583,0.864691,0.138024,0.482969,0.331367,0.636259,0.754085,0.162882,0.285771,0.876412,-0.477567,0.0618929,0.290707,-0.299389,-0.946218,-0.12263,0.283437,-0.433652,0.152285,0.888119,0.361071,-0.398278,-0.419584,0.815674,0.171144,-1,0,0,0.298739,0.349687,-0.276295,0.895198,0.331112,0.184883,-0.934913,0.302912,0.26309 }; // h22 const int h22_numv = 14; const int h22_numf = 9; const dReal h22_volu = 0.065276; const dReal h22_pos[3] = { -0.383570,0.726249,-0.891974 }; const dReal h22_verts[ h22_numv * 3 ] = { 0.403835,0.273751,-0.108026, -0.250365,0.107859,0.179431, -0.224444,0.273751,-0.108026, 0.311631,-0.076337,-0.108026, -0.388885,-0.069647,-0.108026, 0.349740,0.107545,0.033083, 0.400677,0.273751,-0.064850, -0.189576,0.273751,0.079255, 0.008658,-0.122644,0.234765, -0.081643,-0.419616,-0.108026, 0.029768,-0.173739,0.211573, 0.125191,-0.098941,0.194122, 0.140375,-0.342343,-0.108026, 0.081722,-0.168359,0.191970, }; const unsigned int h22_faces[] = { 6, 8,11,5,6,7,1, 4, 7,2,4,1, 5, 4,9,10,8,1, 4, 7,6,0,2, 6, 0,3,12,9,4,2, 5, 5,11,13,12,3, 4, 0,6,5,3, 4, 10,13,11,8, 4, 12,13,10,9, }; const dReal h22_planes[ h22_numf * 4 ] = { 0.212159,0.447018,0.869002,0.151024,-0.889469,0.425934,0.165603,0.298347,-0.595564,-0.522855,0.609857,0.202141,0,1,0,0.273751,0,0,-1,0.108026,0.758508,-0.488331,0.431507,0.227038,0.964613,-0.254054,0.0705546,0.312375,0.364346,-0.255892,0.895417,0.244751,0.28037,-0.805551,0.521997,0.258742 }; // h23 const int h23_numv = 16; const int h23_numf = 10; const dReal h23_volu = 0.051599; const dReal h23_pos[3] = { -0.800668,0.450995,-0.472891 }; const dReal h23_verts[ h23_numv * 3 ] = { 0.035291,-0.217869,-0.228598, -0.199332,-0.134353,-0.300199, -0.199332,0.265879,-0.094319, -0.095074,0.352473,0.001132, -0.199332,-0.001690,0.132407, -0.199332,-0.208186,-0.186260, 0.189555,0.299490,0.167366, -0.199332,0.309177,-0.027504, -0.064385,-0.049725,0.223009, -0.036116,-0.285650,-0.106564, 0.116475,0.143410,0.211970, 0.319467,-0.096483,-0.027399, 0.092916,-0.255030,0.098198, 0.194883,-0.191512,0.077971, 0.239171,0.246507,0.109828, 0.115131,0.352473,0.103771, }; const unsigned int h23_faces[] = { 4, 0,9,5,1, 5, 5,4,7,2,1, 7, 2,3,15,14,11,0,1, 3, 7,3,2, 7, 7,4,8,10,6,15,3, 5, 5,9,12,8,4, 3, 14,15,6, 5, 10,13,11,14,6, 4, 12,13,10,8, 5, 0,11,13,12,9, }; const dReal h23_planes[ h23_numf * 4 ] = { -0.131611,-0.83191,-0.539077,0.299835,-1,6.69634e-17,-4.33923e-17,0.199332,0.398278,0.419584,-0.815674,0.109103,-0.195313,0.823048,-0.533334,0.308068,-0.398278,0.419585,0.815673,0.186681,-0.553062,-0.69918,0.453068,0.171414,0.647541,0.750402,-0.132616,0.325287,0.693474,-0.121763,0.710118,0.213834,0.349687,-0.276295,0.895198,0.190861,0.493234,-0.850287,-0.183662,0.244643 }; // h24 const int h24_numv = 12; const int h24_numf = 8; const dReal h24_volu = 0.050770; const dReal h24_pos[3] = { -0.845297,0.862613,-0.757515 }; const dReal h24_verts[ h24_numv * 3 ] = { 0.078361,0.021092,0.334891, -0.154703,-0.145738,0.190305, -0.154703,0.137387,-0.242485, -0.154703,-0.314006,-0.242485, 0.072842,-0.206011,-0.242485, 0.237283,0.137387,-0.242485, -0.154703,-0.102441,0.257120, -0.050445,-0.059144,0.285756, 0.211362,-0.028505,0.044972, -0.154703,0.137387,0.380489, 0.272151,0.137387,-0.055204, 0.060041,0.137387,0.393596, }; const unsigned int h24_faces[] = { 3, 7,6,1, 5, 6,9,2,3,1, 6, 3,4,8,0,7,1, 4, 5,4,3,2, 5, 9,11,10,5,2, 4, 5,10,8,4, 5, 7,0,11,9,6, 4, 10,11,0,8, }; const dReal h24_planes[ h24_numf * 4 ] = { 0.195313,-0.823048,0.533334,0.19123,-1,0,0,0.154703,0.404539,-0.852363,0.331398,0.124705,0,0,-1,0.242485,0,1,-0,0.137387,0.889469,-0.425934,-0.165603,0.192694,-0.0541955,-0.456759,0.887938,0.283483,0.901694,-0.0730722,0.426155,0.211832 }; // h25 const int h25_numv = 16; const int h25_numf = 10; const dReal h25_volu = 0.064196; const dReal h25_pos[3] = { 0.265380,0.609017,-0.859766 }; const dReal h25_verts[ h25_numv * 3 ] = { 0.171512,-0.295294,0.128463, -0.112864,0.390983,-0.140234, -0.179972,0.258217,0.163631, -0.171482,0.390983,0.031499, -0.146465,0.312621,0.159756, 0.063572,-0.117444,0.267684, -0.245115,0.390983,-0.140234, -0.337319,0.040895,-0.140234, 0.499394,-0.306418,-0.140234, 0.112578,-0.021086,0.259138, 0.074204,-0.220888,0.227450, 0.064293,-0.284390,0.182686, -0.258312,-0.146590,-0.140234, 0.497529,-0.308188,-0.130217, -0.299210,0.224777,0.000875, -0.248273,0.390983,-0.097058, }; const unsigned int h25_faces[] = { 6, 3,4,9,13,8,1, 5, 8,12,7,6,1, 4, 6,15,3,1, 7, 14,7,12,11,10,5,2, 4, 5,9,4,2, 5, 4,3,15,14,2, 5, 10,0,13,9,5, 4, 7,14,15,6, 5, 13,0,11,12,8, 3, 11,0,10, }; const dReal h25_planes[ h25_numf * 4 ] = { 0.727925,0.639055,0.248465,0.13286,0,-0,-1,0.140234,0,1,0,0.390983,-0.735479,-0.309932,0.602505,0.150925,-0.158394,0.166867,0.973173,0.230836,-0.747363,0.49209,0.446425,0.33462,0.598205,-0.236329,0.765702,0.270751,-0.964613,0.254054,-0.0705546,0.345666,-0.201934,-0.957321,-0.206781,0.221494,0.320422,-0.578682,0.749971,0.322182 }; // h26 const int h26_numv = 24; const int h26_numf = 14; const dReal h26_volu = 0.101687; const dReal h26_pos[3] = { -0.341007,0.877992,-0.537072 }; const dReal h26_verts[ h26_numv * 3 ] = { 0.358114,0.122008,-0.419752, -0.168425,-0.052359,0.397165, -0.220490,-0.180490,0.174009, 0.459922,0.043646,-0.162938, 0.324251,-0.109249,-0.070985, -0.202046,0.011183,0.424477, 0.252084,0.007514,0.202105, -0.286958,0.122008,0.388199, 0.307177,-0.044198,-0.321819, 0.426415,-0.010758,-0.159063, 0.082627,-0.250684,-0.160780, -0.033904,-0.274387,-0.120138, -0.232139,0.122008,-0.275647, -0.292928,-0.043884,-0.175471, -0.344531,-0.074523,0.167952, -0.207099,-0.190024,0.165835, -0.444249,0.122008,0.173153, -0.425929,0.005713,0.114448, 0.327136,0.122008,0.185091, -0.202046,0.122008,0.443480, 0.434905,0.122008,-0.291195, 0.483509,0.122008,-0.120325, -0.187210,-0.038985,0.408631, -0.270106,-0.127507,0.231547, }; const unsigned int h26_faces[] = { 5, 22,23,2,15,1, 6, 15,11,10,4,6,1, 6, 6,18,19,5,22,1, 3, 23,14,2, 6, 14,17,13,11,15,2, 3, 20,21,3, 6, 21,18,6,4,9,3, 5, 9,8,0,20,3, 4, 10,8,9,4, 3, 19,7,5, 7, 7,16,17,14,23,22,5, 8, 19,18,21,20,0,12,16,7, 6, 10,11,13,12,0,8, 4, 13,17,16,12, }; const dReal h26_planes[ h26_numf * 4 ] = { -0.256638,-0.811103,0.525594,0.29444,0.324513,-0.835692,0.443069,0.165071,0.433652,-0.152285,0.888119,0.287665,-0.647541,-0.750402,0.132616,0.301294,-0.636259,-0.754085,-0.162882,0.248051,0.95246,-0.139363,-0.270922,0.476118,0.791095,-0.458379,0.40504,0.277839,0.747363,-0.49209,-0.446425,0.39499,0.555832,-0.7947,-0.243931,0.284365,-0.540055,-0.142236,0.829524,0.459639,-0.742791,-0.391264,0.543299,0.37632,0,1,0,0.122008,-0.212159,-0.447018,-0.869002,0.234249,-0.901694,0.0730722,-0.426155,0.335702 }; // h27 const int h27_numv = 24; const int h27_numf = 14; const dReal h27_volu = 0.100588; const dReal h27_pos[3] = { 0.167088,0.649940,-0.364014 }; const dReal h27_verts[ h27_numv * 3 ] = { -0.183844,0.118803,-0.244043, -0.044353,-0.266136,0.405236, -0.256011,0.235567,0.029047, 0.161864,-0.158366,-0.228068, 0.300539,0.065664,-0.127155, -0.024586,0.350060,-0.293383, -0.048173,0.271698,-0.335996, -0.180959,0.350060,0.012033, -0.081680,0.217294,-0.332121, -0.044357,0.350060,0.088262, -0.006196,-0.377080,0.285910, 0.201878,-0.226993,0.143823, -0.003872,-0.277036,0.420726, 0.210870,-0.062009,-0.236614, -0.003871,0.350060,0.098146, 0.183618,0.350060,-0.130723, -0.165155,-0.254165,0.331667, -0.075081,-0.408619,0.192919, -0.091738,-0.410255,0.124205, 0.005721,-0.287236,0.414262, -0.077668,-0.381972,-0.025325, -0.102748,-0.401170,0.182332, 0.134962,-0.226993,-0.182915, 0.109551,-0.305242,0.296779, }; const unsigned int h27_faces[] = { 7, 16,21,17,10,19,12,1, 4, 12,14,9,1, 5, 9,7,2,16,1, 6, 7,5,6,8,0,2, 6, 0,20,18,21,16,2, 5, 13,4,11,22,3, 5, 22,20,0,8,3, 4, 8,6,13,3, 5, 13,6,5,15,4, 7, 15,14,12,19,23,11,4, 5, 7,9,14,15,5, 7, 17,18,20,22,11,23,10, 3, 23,19,10, 3, 21,18,17, }; const dReal h27_planes[ h27_numf * 4 ] = { -0.40667,-0.730271,0.54893,0.434835,-0.212159,0.447018,0.869002,0.242593,-0.444511,0.409753,0.796563,0.233461,-0.791095,0.458379,-0.40504,0.298742,-0.954535,-0.263372,-0.139635,0.178273,0.870583,-0.45858,-0.178295,0.254203,-0.309646,-0.434949,-0.84554,0.211601,0.158394,-0.166867,-0.973173,0.274014,0.598205,0.236328,-0.765702,0.292665,0.73548,0.309929,0.602505,0.16478,1.09327e-15,1,1.13815e-15,0.35006,0.53156,-0.839996,-0.108863,0.282326,0.425203,-0.759567,0.4922,0.424508,-0.292039,-0.95183,0.0934524,0.428891 }; // h28 const int h28_numv = 18; const int h28_numf = 11; const dReal h28_volu = 0.075441; const dReal h28_pos[3] = { 0.013616,0.472900,-0.719797 }; const dReal h28_verts[ h28_numv * 3 ] = { -0.187022,-0.167506,-0.280203, 0.109520,-0.345231,0.152809, -0.085555,0.177012,-0.280203, -0.271995,0.154408,0.021945, -0.030372,0.295843,0.111740, 0.061535,-0.227567,0.329703, 0.075804,-0.204932,0.330457, 0.071792,0.394334,0.023662, 0.208102,-0.281022,0.072668, -0.047446,0.360894,-0.139094, 0.077205,-0.350161,0.038133, -0.006548,-0.010473,-0.280203, 0.288434,-0.049953,0.172868, 0.315336,0.018674,0.127715, 0.316057,-0.148273,0.042717, 0.325968,-0.084770,0.087482, -0.256811,-0.088994,-0.280203, -0.315464,0.084990,0.019794, }; const unsigned int h28_faces[] = { 7, 8,14,15,12,6,5,1, 6, 5,17,16,0,10,1, 3, 10,8,1, 5, 16,17,3,9,2, 7, 9,7,13,15,14,11,2, 4, 11,0,16,2, 5, 17,5,6,4,3, 4, 4,7,9,3, 5, 6,12,13,7,4, 5, 10,0,11,14,8, 3, 15,13,12, }; const dReal h28_planes[ h28_numf * 4 ] = { 0.720506,-0.471135,0.508826,0.319313,-0.726908,-0.64614,0.232611,0.179002,0.485104,-0.868795,-0.0993492,0.337882,-0.758508,0.488331,-0.431507,0.272244,0.735479,0.309932,-0.602505,0.160762,0,0,-1,0.280203,-0.469484,0.267909,0.841315,0.187527,-0.555832,0.7947,0.243931,0.279245,0.309646,0.434949,0.84554,0.213753,0.469359,-0.539421,-0.69909,0.198463,0.901694,-0.0730722,0.426155,0.337399 }; // h29 const int h29_numv = 20; const int h29_numf = 12; const dReal h29_volu = 0.090754; const dReal h29_pos[3] = { -0.195482,0.549508,-0.348926 }; const dReal h29_verts[ h29_numv * 3 ] = { -0.062897,0.077801,-0.348926, 0.254536,-0.331284,-0.002375, -0.179429,0.054098,-0.308283, 0.178726,0.219235,-0.259131, -0.352624,0.138460,-0.022310, 0.259822,-0.300738,0.167244, 0.197415,-0.153733,0.316579, 0.065987,-0.327570,0.133724, 0.114982,-0.134660,0.333685, 0.270633,-0.304175,-0.041168, -0.106366,0.008382,-0.351078, 0.106560,0.335999,0.013959, -0.240892,-0.124645,-0.147161, -0.313950,0.276125,0.209019, -0.158320,0.003002,-0.331475, 0.036774,-0.342768,0.065557, 0.284902,-0.281540,-0.040413, 0.270832,-0.309823,0.109117, 0.013405,-0.084041,0.336165, 0.046528,-0.137097,0.329090, }; const unsigned int h29_faces[] = { 4, 9,16,17,1, 5, 17,5,7,15,1, 6, 15,12,14,10,9,1, 4, 0,10,14,2, 4, 14,12,4,2, 6, 4,13,11,3,0,2, 5, 16,9,10,0,3, 6, 11,6,5,17,16,3, 7, 12,15,7,19,18,13,4, 5, 6,8,19,7,5, 5, 11,13,18,8,6, 3, 18,19,8, }; const dReal h29_planes[ h29_numf * 4 ] = { 0.846082,-0.532633,-0.0211314,0.391862,0.105626,-0.979232,0.173057,0.350878,-0.148211,-0.780702,-0.607074,0.22235,-0.364346,0.255892,-0.895417,0.355259,-0.864691,-0.138024,-0.482969,0.296575,-0.324513,0.835692,-0.443069,0.240027,0.469484,-0.267909,-0.841315,0.243184,0.954535,0.263372,0.139635,0.192157,-0.73808,-0.518378,0.431882,0.178854,-0.0212658,-0.716912,0.696839,0.326619,0.289106,0.541462,0.789453,0.223758,-0.0600487,-0.168696,0.983837,0.344105 }; // h30 const int h30_numv = 26; const int h30_numf = 15; const dReal h30_volu = 0.141813; const dReal h30_pos[3] = { 0.709749,0.432546,-0.520590 }; const dReal h30_verts[ h30_numv * 3 ] = { 0.086130,-0.133630,-0.479410, 0.290251,-0.067548,-0.461259, 0.290251,0.254276,-0.130163, -0.166094,-0.194830,-0.275875, -0.114073,0.017151,0.452790, 0.263868,-0.083016,-0.470730, -0.015645,0.141724,0.383369, -0.170984,0.316821,0.046789, -0.242122,0.283058,0.029421, 0.290251,0.110614,0.239339, -0.340783,-0.009598,0.300399, 0.290251,-0.018830,0.261535, 0.067740,-0.137994,-0.479410, -0.241377,-0.054963,0.435747, 0.058158,-0.287592,0.103343, 0.290251,-0.145966,0.143817, 0.068185,-0.139308,-0.479410, -0.017612,-0.287592,-0.266628, 0.053160,-0.131717,-0.469392, -0.272857,-0.118823,-0.210712, 0.007901,-0.200618,-0.414231, 0.003123,-0.268644,-0.311584, -0.331791,0.155385,-0.080037, -0.407699,-0.009598,-0.026339, -0.380797,0.059028,-0.071491, -0.370165,-0.044416,-0.111725, }; const unsigned int h30_faces[] = { 6, 15,14,17,21,5,1, 9, 5,0,12,18,22,8,7,2,1, 5, 2,9,11,15,1, 4, 7,6,9,2, 4, 20,21,17,3, 8, 17,14,13,10,23,25,19,3, 6, 19,18,12,16,20,3, 5, 13,14,15,11,4, 4, 11,9,6,4, 6, 6,7,8,10,13,4, 5, 21,20,16,0,5, 5, 22,24,23,10,8, 3, 0,16,12, 5, 19,25,24,22,18, 3, 24,25,23, }; const dReal h30_planes[ h30_numf * 4 ] = { 0.53156,-0.839996,-0.108863,0.26124,-0.167754,0.706913,-0.687119,0.220498,1,-0,0,0.290251,0.256529,0.900844,0.350247,0.257932,-0.43192,-0.742413,-0.512121,0.357665,-0.531561,-0.839995,0.108864,0.221912,-0.613049,-0.207593,-0.762283,0.352564,0.275531,-0.653109,0.705359,0.276747,0.433652,0.152285,0.888119,0.355275,-0.46199,0.681388,0.567693,0.321433,0.256638,-0.811103,-0.525594,0.382466,-0.870583,0.45858,0.178295,0.345838,-0,0,-1,0.479409,-0.598205,0.236329,-0.765702,0.296486,-0.901694,0.0730722,-0.426155,0.378142 }; // h31 const int h31_numv = 20; const int h31_numf = 12; const dReal h31_volu = 0.145607; const dReal h31_pos[3] = { 0.628702,0.773411,-0.793457 }; const dReal h31_verts[ h31_numv * 3 ] = { -0.189575,0.226589,0.317223, 0.371298,-0.414948,-0.206543, -0.476185,0.226589,-0.206543, 0.371298,0.226589,-0.206543, -0.250744,-0.185480,0.192828, 0.148787,-0.478859,-0.206543, -0.509787,0.148227,0.093447, -0.534804,0.226589,-0.034811, -0.277996,0.226589,0.298719, -0.486200,0.226589,0.136059, 0.371298,-0.408413,-0.188392, 0.167177,-0.474495,-0.206543, 0.366378,-0.417196,-0.206543, 0.344915,-0.423881,-0.197864, 0.371298,-0.086589,0.142703, 0.371298,0.226589,0.089002, -0.161075,-0.057807,0.302287, -0.089936,-0.024044,0.319655, 0.134207,-0.472582,-0.196526, 0.136072,-0.470812,-0.206543, }; const unsigned int h31_faces[] = { 4, 10,13,12,1, 7, 12,11,5,19,2,3,1, 5, 3,15,14,10,1, 6, 19,18,4,6,7,2, 7, 7,9,8,0,15,3,2, 5, 16,8,9,6,4, 9, 18,5,11,13,10,14,17,16,4, 3, 18,19,5, 3, 9,7,6, 4, 16,17,0,8, 3, 12,13,11, 4, 15,0,17,14, }; const dReal h31_planes[ h31_numf * 4 ] = { 0.395039,-0.86436,0.311169,0.441071,-0,-0,-1,0.206543,1,-0,0,0.371298,-0.727925,-0.639055,-0.248465,0.253143,4.94863e-17,1,-0,0.226589,-0.598205,-0.236328,0.765702,0.341479,0.167754,-0.706913,0.687119,0.221551,-0.518906,-0.82,-0.241527,0.365343,-0.95246,0.139363,0.270922,0.531526,-0.204299,-0.0717432,0.976276,0.332171,0.275992,-0.959497,-0.0565231,0.51309,0.372229,0.156858,0.91479,0.255169 }; // h32 const int h32_numv = 22; const int h32_numf = 13; const dReal h32_volu = 0.092552; const dReal h32_pos[3] = { -0.648077,-0.694629,-0.055690 }; const dReal h32_verts[ h32_numv * 3 ] = { -0.351923,0.020682,-0.162313, -0.351923,0.291038,-0.298522, 0.116588,0.074450,0.304425, 0.180292,0.145010,-0.063690, -0.351923,0.286862,-0.299238, 0.082653,-0.305371,0.200452, 0.444715,-0.214767,0.086986, 0.440565,-0.305371,0.060643, 0.437298,-0.305371,0.003205, 0.441236,-0.180086,0.007980, 0.202670,-0.305371,-0.129990, -0.122926,-0.305371,-0.050498, -0.351923,0.343433,0.003710, 0.034975,0.067995,0.334312, -0.249787,0.361137,-0.236631, 0.059834,0.222599,0.089656, 0.420946,-0.305371,-0.023410, 0.437088,-0.283432,-0.011766, -0.351923,0.387353,-0.064067, -0.294272,0.397125,-0.093222, -0.351923,0.309463,-0.280428, -0.321961,0.320573,-0.278827, }; const unsigned int h32_faces[] = { 3, 20,21,1, 9, 21,14,3,9,17,16,10,4,1, 6, 4,0,12,18,20,1, 5, 13,5,7,6,2, 5, 6,9,3,15,2, 6, 15,19,18,12,13,2, 4, 14,19,15,3, 4, 10,11,0,4, 5, 13,12,0,11,5, 6, 11,10,16,8,7,5, 5, 7,8,17,9,6, 3, 16,17,8, 5, 21,20,18,19,14, }; const dReal h32_planes[ h32_numf * 4 ] = { -0.216442,0.684063,-0.696571,0.483201,0.433652,0.152285,-0.888119,0.156831,-1,0,0,0.351923,0.349687,-0.276295,0.895198,0.29272,0.727924,0.639056,0.248465,0.208084,0.131611,0.83191,0.539077,0.241389,0.471464,0.878752,-0.0742736,0.21716,-0.212159,-0.447018,-0.869002,0.206469,-0.73548,-0.309929,0.602505,0.154628,-3.74119e-15,-1,2.12832e-16,0.305371,0.99796,-0.0292037,-0.0567728,0.445142,0.80443,-0.32957,-0.494242,0.450833,-0.314046,0.893286,-0.321583,0.47714 }; // h33 const int h33_numv = 18; const int h33_numf = 11; const dReal h33_volu = 0.056945; const dReal h33_pos[3] = { -0.288352,-0.547292,0.050646 }; const dReal h33_verts[ h33_numv * 3 ] = { 0.084990,-0.362104,-0.019350, -0.079434,0.021164,0.334816, 0.019488,-0.072734,0.262363, 0.115516,0.076855,-0.268585, 0.213070,0.021874,-0.243280, 0.274323,0.089944,-0.132397, 0.019789,0.332949,0.053313, 0.257211,0.025988,-0.078610, 0.131191,0.288888,-0.060012, 0.118204,-0.320377,0.031687, 0.081511,-0.327423,-0.098356, -0.243137,-0.072887,0.198089, -0.179433,-0.002327,-0.170026, -0.299891,0.075262,-0.016680, -0.055817,0.322184,0.088384, -0.038680,0.277450,0.153234, 0.148159,-0.119839,-0.229545, 0.048588,0.033746,-0.272086, }; const unsigned int h33_faces[] = { 5, 11,0,9,2,1, 7, 2,7,5,8,6,15,1, 5, 15,14,13,11,1, 3, 9,7,2, 4, 4,16,17,3, 7, 17,12,13,14,6,8,3, 4, 8,5,4,3, 7, 5,7,9,0,10,16,4, 3, 14,15,6, 5, 0,11,13,12,10, 4, 12,17,16,10, }; const dReal h33_planes[ h33_numf * 4 ] = { -0.167754,-0.706913,0.687119,0.228423,0.73548,0.309929,0.602505,0.149866,-0.708232,0.479648,0.518021,0.239851,0.830851,-0.164118,0.531744,0.167639,0.158394,-0.166869,-0.973173,0.266852,-0.391463,0.659847,-0.641373,0.177755,0.49733,0.589428,-0.636583,0.273727,0.877503,-0.423705,-0.224641,0.232352,0.131611,0.83191,0.539077,0.308327,-0.727924,-0.639056,-0.248465,0.174346,-0.309646,-0.434949,-0.84554,0.200337 }; // h34 const int h34_numv = 24; const int h34_numf = 14; const dReal h34_volu = 0.086482; const dReal h34_pos[3] = { -0.499709,-0.643458,-0.327986 }; const dReal h34_verts[ h34_numv * 3 ] = { -0.500291,0.235691,-0.026942, -0.413349,0.203755,-0.157062, -0.223651,0.321490,-0.139249, 0.209880,-0.356542,0.003973, 0.365162,-0.137565,0.097393, 0.292868,-0.231257,0.280276, 0.359516,-0.023673,0.149087, -0.329463,0.339839,-0.019523, -0.041433,0.349469,-0.148408, 0.054302,-0.356542,0.142306, 0.272578,-0.356542,0.248886, 0.288720,-0.334603,0.260530, 0.023896,-0.069111,-0.283979, 0.274970,-0.222320,-0.056303, 0.127449,-0.356542,-0.036276, -0.035189,-0.103922,-0.288953, -0.023751,0.360733,-0.121029, -0.500291,0.237083,-0.030523, -0.346425,0.336124,-0.010604, 0.259945,0.129913,0.106546, -0.500291,0.239867,-0.026226, -0.470329,0.269402,-0.006532, -0.398155,0.309966,0.035665, 0.031924,0.093839,0.208606, }; const unsigned int h34_faces[] = { 7, 17,20,21,18,7,2,1, 5, 2,8,12,15,1, 6, 15,14,9,0,17,1, 4, 7,16,8,2, 5, 14,15,12,13,3, 5, 13,4,11,10,3, 4, 10,9,14,3, 7, 13,12,8,16,19,6,4, 4, 6,5,11,4, 4, 6,19,23,5, 9, 23,22,21,20,0,9,10,11,5, 6, 18,22,23,19,16,7, 3, 0,20,17, 3, 21,22,18, }; const dReal h34_planes[ h34_numf * 4 ] = { -0.425203,0.759567,-0.4922,0.407829,-0.0929092,0.293639,-0.951391,0.247662,-0.66261,-0.69806,-0.271405,0.174284,-0.159459,0.944944,-0.285751,0.379244,0.373525,-0.524676,-0.76498,0.262425,0.837582,-0.502473,-0.214421,0.354093,0,-1,0,0.356542,0.73548,0.309929,-0.602505,0.167254,0.941719,-0.0992098,0.32144,0.388833,0.309646,0.434949,0.84554,0.227085,-0.433652,-0.152285,0.888119,0.157132,0.148211,0.780702,0.607074,0.204631,-1,0,-0,0.500291,-0.474713,0.879502,-0.0335246,0.460429 }; // h35 const int h35_numv = 12; const int h35_numf = 8; const dReal h35_volu = 0.072358; const dReal h35_pos[3] = { -0.852811,-0.781078,0.150064 }; const dReal h35_verts[ h35_numv * 3 ] = { -0.147189,-0.218922,0.332047, 0.103613,-0.074924,0.288589, -0.147189,0.429882,-0.202044, -0.147189,-0.218922,-0.312160, 0.239709,0.154443,0.128558, 0.287386,-0.218922,-0.005301, -0.043492,-0.218922,0.344705, 0.074717,-0.218922,0.306226, -0.147189,0.402063,0.012610, 0.208223,0.167113,0.176854, -0.147189,0.107130,-0.368067, 0.081807,-0.218922,-0.256252, }; const unsigned int h35_faces[] = { 3, 6,7,1, 5, 7,5,4,9,1, 5, 9,8,0,6,1, 4, 8,9,4,2, 5, 4,5,11,10,2, 5, 10,3,0,8,2, 3, 10,11,3, 6, 11,5,7,6,0,3, }; const dReal h35_planes[ h35_numf * 4 ] = { 0.309078,0.0542691,0.949487,0.301971,0.822068,-0.096228,0.561199,0.254343,-0.107916,0.45476,0.884052,0.209874,0.512085,0.851811,0.110395,0.2685,0.73548,0.309929,-0.602505,0.146711,-1,-0,-0,0.147189,0.233951,-0.164312,-0.958263,0.300667,0,-1,0,0.218922 }; // h36 const int h36_numv = 18; const int h36_numf = 11; const dReal h36_volu = 0.076715; const dReal h36_pos[3] = { 0.330903,-0.599381,-0.308448 }; const dReal h36_verts[ h36_numv * 3 ] = { 0.235744,-0.093981,0.208985, 0.157036,0.091360,0.296934, -0.213473,-0.059832,-0.258208, 0.131366,0.084254,0.304768, 0.060949,-0.352878,-0.040467, 0.031132,-0.367472,0.023458, -0.038178,0.319175,-0.078462, 0.346140,-0.033881,-0.005840, 0.305466,-0.106272,-0.107625, -0.256020,-0.056138,-0.213238, -0.331115,0.110184,0.014099, -0.356965,0.085987,0.067218, 0.185622,-0.147504,0.212044, 0.241393,0.219660,0.109239, -0.343391,-0.100844,-0.022261, -0.046519,0.081665,-0.290234, -0.272849,0.156195,0.144404, -0.146830,0.270831,-0.017119, }; const unsigned int h36_faces[] = { 6, 13,6,17,16,3,1, 4, 3,12,0,1, 4, 0,7,13,1, 6, 9,10,17,6,15,2, 4, 15,8,4,2, 5, 4,5,14,9,2, 6, 16,11,14,5,12,3, 6, 8,7,0,12,5,4, 5, 13,7,8,15,6, 4, 14,11,10,9, 4, 11,16,17,10, }; const dReal h36_planes[ h36_numf * 4 ] = { -0.066237,0.837367,0.542613,0.227221,0.349687,-0.276295,0.895198,0.295486,0.864691,0.138024,0.482969,0.291807,-0.582463,0.552262,-0.596442,0.245303,0.212159,-0.447016,-0.869003,0.205839,-0.496382,-0.766976,-0.406636,0.25685,-0.398278,-0.419584,0.815674,0.16092,0.722578,-0.66608,0.18498,0.2716,0.595564,0.522855,-0.609857,0.191995,-0.913105,0.120244,-0.389591,0.310099,-0.654405,0.755705,0.0257735,0.300313 }; // h37 const int h37_numv = 18; const int h37_numf = 11; const dReal h37_volu = 0.098217; const dReal h37_pos[3] = { 0.055330,-0.588368,0.333127 }; const dReal h37_verts[ h37_numv * 3 ] = { -0.107417,0.016721,0.347927, 0.283844,-0.036335,0.197820, 0.129290,0.324988,-0.064466, -0.012100,0.128834,-0.356552, 0.344968,0.171444,-0.038138, -0.270436,0.127441,0.395275, -0.130084,-0.375511,-0.154724, 0.001812,-0.380727,-0.087638, -0.247911,0.142505,0.383526, 0.360906,0.133475,0.137346, 0.062042,-0.352141,-0.072933, 0.261216,0.073240,-0.194499, 0.127844,0.325300,-0.059106, 0.361773,0.137946,0.130076, -0.225478,-0.279302,-0.250794, -0.324194,-0.031659,-0.020118, -0.297963,0.086614,0.328910, -0.086471,0.067064,-0.361091, }; const unsigned int h37_faces[] = { 6, 10,11,4,13,9,1, 5, 9,8,5,0,1, 4, 0,7,10,1, 4, 12,13,4,2, 4, 4,11,3,2, 8, 3,17,15,16,5,8,12,2, 7, 11,10,7,6,14,17,3, 5, 16,6,7,0,5, 4, 16,15,14,6, 4, 9,13,12,8, 3, 15,17,14, }; const dReal h37_planes[ h37_numf * 4 ] = { 0.870583,-0.45858,-0.178295,0.228502,0.372229,0.156856,0.91479,0.280919,0.167754,-0.706913,0.687119,0.209227,0.568104,0.816131,0.105771,0.331865,0.49733,0.589428,-0.636583,0.296895,-0.616962,0.758294,-0.21059,0.180245,0.398278,-0.419585,-0.815673,0.231954,-0.32928,-0.737152,0.590069,0.228345,-0.799798,-0.547681,0.245698,0.271686,0.226312,0.817437,0.529699,0.263537,-0.830851,0.164118,-0.531744,0.274859 }; // h38 const int h38_numv = 28; const int h38_numf = 16; const dReal h38_volu = 0.093559; const dReal h38_pos[3] = { 0.133166,-0.773583,-0.050905 }; const dReal h38_verts[ h38_numv * 3 ] = { -0.076024,-0.195512,0.296394, 0.264846,-0.226417,0.026836, 0.183380,0.258456,0.189533, -0.015793,-0.166926,0.311098, -0.267713,-0.007440,-0.179688, -0.159228,0.260189,-0.190326, -0.343945,-0.226417,-0.001580, -0.273359,0.106452,-0.127994, 0.216958,-0.226417,-0.206989, 0.383359,0.026697,-0.045499, 0.329103,0.258456,0.047225, -0.089936,0.314049,0.027481, -0.145654,0.073358,-0.279804, 0.228869,-0.193270,-0.234086, -0.131382,0.326289,-0.026485, -0.075112,0.330397,-0.113139, -0.208448,0.248166,-0.141729, -0.011151,-0.226417,0.296364, -0.211663,-0.226417,0.216210, -0.072038,-0.226417,0.288931, -0.336528,-0.135813,0.082201, -0.147195,0.316236,-0.030846, -0.340678,-0.226417,0.055858, -0.164307,0.252279,0.022941, -0.344155,-0.204478,-0.016551, -0.340007,-0.101132,0.003195, -0.207920,-0.190296,0.229308, -0.303314,-0.094086,0.133238, }; const unsigned int h38_faces[] = { 4, 8,13,9,1, 6, 9,10,2,3,17,1, 7, 17,19,18,22,6,8,1, 5, 10,15,14,11,2, 7, 11,23,27,26,0,3,2, 4, 0,19,17,3, 4, 24,25,7,4, 5, 7,16,5,12,4, 6, 12,13,8,6,24,4, 5, 16,21,14,15,5, 6, 15,10,9,13,12,5, 5, 22,20,25,24,6, 7, 25,20,27,23,21,16,7, 4, 14,21,23,11, 5, 26,27,20,22,18, 4, 19,0,26,18, }; const dReal h38_planes[ h38_numf * 4 ] = { 0.870583,-0.45858,-0.178295,0.329616,0.693474,-0.121763,0.710118,0.23029,0,-1,0,0.226417,0.124536,0.983986,0.127525,0.301324,-0.398278,0.419585,0.815673,0.190005,-0.117405,-0.247372,0.961781,0.342356,-0.941719,0.0992098,-0.32144,0.309131,-0.709719,0.26169,-0.654077,0.305583,-0.289106,-0.541464,-0.789452,0.223281,-0.465257,0.845503,-0.262033,0.343944,0.398278,0.419584,-0.815674,0.200998,-0.99796,0.0292037,0.0567728,0.336541,-0.877503,0.423705,0.224641,0.256225,-0.548603,0.619234,0.561769,0.259246,-0.770892,-0.145024,0.620237,0.330106,-0.445543,-0.264025,0.855443,0.33904 }; // h39 const int h39_numv = 32; const int h39_numf = 18; const dReal h39_volu = 0.060173; const dReal h39_pos[3] = { -0.130993,-0.349156,0.297470 }; const dReal h39_verts[ h39_numv * 3 ] = { 0.132777,-0.098138,-0.374861, 0.174223,-0.110378,-0.320895, -0.236793,-0.176972,0.087992, 0.120090,0.163784,-0.274197, -0.036262,0.126682,-0.293283, -0.239846,-0.040235,0.342234, -0.196039,0.079314,-0.093590, -0.026168,0.090752,-0.306837, -0.084113,-0.111771,0.430932, -0.132771,0.138527,-0.197817, -0.061588,-0.096707,0.419183, -0.167047,-0.030107,0.457226, 0.314167,0.086089,-0.023449, 0.140527,0.255266,-0.004320, -0.137571,0.134813,-0.193511, 0.315613,0.085777,-0.028809, 0.116964,-0.108191,-0.379221, 0.099852,-0.172148,-0.325434, -0.176687,-0.026318,0.447418, -0.168971,-0.023213,0.453768, -0.137871,-0.270870,0.015539, -0.111640,-0.152598,0.364567, -0.122362,-0.092357,0.456223, -0.127730,-0.079472,0.460978, -0.243030,-0.080780,0.324741, -0.136583,-0.114124,0.420896, -0.241856,-0.054541,0.348612, -0.178625,-0.028253,0.445248, -0.171209,-0.024409,0.453290, -0.169333,-0.024798,0.455225, 0.224076,0.244621,-0.088171, 0.213513,0.251212,-0.061379, }; const unsigned int h39_faces[] = { 5, 0,3,30,15,1, 8, 15,12,10,8,21,20,17,1, 4, 17,16,0,1, 5, 20,21,25,24,2, 5, 24,26,5,6,2, 7, 6,14,7,16,17,20,2, 5, 0,16,7,4,3, 6, 4,9,13,31,30,3, 4, 7,14,9,4, 4, 26,27,18,5, 8, 18,28,19,13,9,14,6,5, 4, 10,23,22,8, 4, 22,25,21,8, 8, 12,31,13,19,29,11,23,10, 7, 27,26,24,25,22,23,11, 5, 29,28,18,27,11, 4, 15,30,31,12, 3, 28,29,19, }; const dReal h39_planes[ h39_numf * 4 ] = { 0.794364,0.251059,-0.553132,0.288182,0.616962,-0.758294,0.21059,0.12361,0.548603,-0.619234,-0.561769,0.344197,-0.526505,-0.792388,0.308081,0.292012,-0.991673,0.108076,-0.0700326,0.209533,-0.73548,-0.309929,-0.602505,0.17599,0.0284606,0.359798,-0.932596,0.318062,-0.184883,0.934913,-0.302912,0.213979,-0.696788,0.0734069,-0.713511,0.243827,-0.830322,0.320028,0.456232,0.342411,-0.493232,0.850288,0.183662,0.146944,0.512456,-0.101226,0.852726,0.335677,-0.0662371,-0.837367,0.542614,0.332994,0.553104,0.49165,0.672575,0.200322,-0.664689,-0.486283,0.567201,0.385014,-0.721996,-0.0507074,0.690036,0.437637,0.818514,0.542417,0.189261,0.299408,-0.474458,0.651966,0.591464,0.333423 }; // h40 const int h40_numv = 24; const int h40_numf = 14; const dReal h40_volu = 0.115424; const dReal h40_pos[3] = { 0.492476,-0.748212,0.263785 }; const dReal h40_verts[ h40_numv * 3 ] = { -0.375103,-0.192297,-0.003592, 0.259307,0.208511,0.137583, 0.097667,-0.251788,0.295436, 0.264741,-0.251788,-0.112461, -0.092178,0.331289,0.031204, 0.024049,0.001327,-0.360189, 0.074171,0.054850,-0.363248, 0.312772,-0.115013,-0.159366, -0.175930,0.233085,-0.125157, -0.094464,-0.251788,-0.287854, -0.004537,0.240191,-0.275299, -0.030207,0.233085,-0.267465, -0.370461,-0.251788,-0.018326, 0.056736,-0.251788,0.315422, -0.153302,0.123509,0.267162, -0.068302,0.078845,0.319783, 0.171724,0.348803,0.156293, 0.053571,0.367605,-0.023060, -0.075373,0.297791,0.199418, 0.109457,0.331072,0.189737, -0.005042,0.303901,0.226077, 0.014996,0.282164,0.244247, -0.076239,0.293319,0.206688, -0.068649,0.297216,0.207331, }; const unsigned int h40_faces[] = { 4, 2,3,7,1, 6, 7,6,10,17,16,1, 7, 16,19,21,15,13,2,1, 5, 13,12,9,3,2, 5, 9,5,6,7,3, 5, 17,10,11,8,4, 6, 8,0,14,22,18,4, 7, 18,23,20,19,16,17,4, 6, 9,12,0,8,11,5, 4, 11,10,6,5, 5, 13,15,14,0,12, 6, 15,21,20,23,22,14, 3, 22,23,18, 3, 20,21,19, }; const dReal h40_planes[ h40_numf * 4 ] = { 0.908278,-0.191373,0.372031,0.246805,0.73808,0.518378,-0.431882,0.240058,0.433652,0.152285,0.888119,0.266393,5.15129e-17,-1,5.27492e-17,0.251788,0.398278,-0.419585,-0.815673,0.302818,-0.348894,0.86639,-0.357268,0.308038,-0.870583,0.45858,0.178295,0.237735,-0.162747,0.964426,0.208316,0.341006,-0.693474,0.121763,-0.710118,0.23926,-0.349687,0.276295,-0.895198,0.314397,-0.598205,-0.236328,0.765702,0.267084,-0.296224,0.4369,0.849335,0.326283,-0.440632,0.78713,0.431589,0.353679,0.071473,0.677671,0.731884,0.371046 }; // h41 const int h41_numv = 18; const int h41_numf = 11; const dReal h41_volu = 0.076473; const dReal h41_pos[3] = { 0.741085,-0.876917,-0.246261 }; const dReal h41_verts[ h41_numv * 3 ] = { 0.005338,0.140795,-0.243701, -0.174437,0.183555,0.146798, 0.258916,-0.123083,-0.387389, 0.103129,0.222017,-0.142233, 0.164192,-0.123083,-0.418224, 0.016133,-0.123083,0.397585, 0.258916,0.168617,-0.137303, 0.258916,-0.123083,0.279039, -0.343073,-0.123083,0.222192, -0.064041,0.243655,-0.068027, -0.104715,0.171264,-0.169812, -0.390960,-0.123083,-0.011633, -0.224559,0.130032,0.149857, -0.379049,-0.089936,-0.038730, -0.349233,-0.075342,-0.102654, -0.337817,-0.123083,-0.124077, 0.258916,-0.009416,0.259549, 0.064164,0.013692,0.350680, }; const unsigned int h41_faces[] = { 6, 9,10,14,13,12,1, 5, 12,8,5,17,1, 6, 17,16,6,3,9,1, 5, 4,0,3,6,2, 4, 6,16,7,2, 7, 7,5,8,11,15,4,2, 4, 0,10,9,3, 5, 15,14,10,0,4, 4, 7,16,17,5, 4, 12,13,11,8, 4, 13,14,15,11, }; const dReal h41_planes[ h41_numf * 4 ] = { -0.722578,0.66608,-0.18498,0.221152,-0.398278,0.419585,0.815673,0.266231,0.287163,0.873965,0.392074,0.167884,0.239912,0.631869,-0.73701,0.269854,1,0,0,0.258915,0,-1,0,0.123083,-0.131611,0.83191,-0.539077,0.2478,-0.488522,0.25733,-0.833743,0.236806,0.433652,0.152285,0.888119,0.341356,-0.870583,0.45858,0.178295,0.281846,-0.903842,-0.0244154,-0.42717,0.361341 }; // h42 const int h42_numv = 26; const int h42_numf = 15; const dReal h42_volu = 0.137951; const dReal h42_pos[3] = { 0.814994,-0.482932,0.027418 }; const dReal h42_verts[ h42_numv * 3 ] = { -0.063211,-0.056769,0.373950, 0.185005,0.097851,0.415613, -0.248347,-0.210430,-0.126881, 0.112828,0.023604,-0.394042, -0.108847,0.115253,0.400661, -0.327055,-0.025089,-0.038931, -0.085789,0.224192,-0.255901, 0.185005,-0.403401,-0.014130, 0.185005,-0.225368,-0.410982, -0.009747,-0.380293,0.077002, -0.175394,0.222730,-0.208732, 0.002670,0.221670,0.389944, -0.150794,0.083523,0.392660, 0.160182,0.229752,0.436714, 0.133897,0.345057,0.231744, -0.006362,0.255606,0.329122, 0.185005,0.234054,0.438967, 0.185005,0.352490,0.238788, 0.029219,-0.171968,-0.415912, -0.137952,-0.150330,-0.341706, 0.185005,0.276769,-0.150723, 0.185005,0.010082,-0.390796, -0.176045,0.220413,-0.220256, -0.242698,0.103211,-0.226628, -0.268948,0.102325,0.213307, -0.248100,0.136462,0.190657, }; const unsigned int h42_faces[] = { 4, 0,9,7,1, 7, 7,8,21,20,17,16,1, 6, 16,13,4,12,0,1, 4, 5,23,19,2, 6, 19,18,8,7,9,2, 6, 9,0,12,24,5,2, 4, 6,20,21,3, 4, 21,8,18,3, 6, 18,19,23,22,6,3, 3, 13,11,4, 6, 11,15,25,24,12,4, 6, 24,25,10,22,23,5, 6, 22,10,14,17,20,6, 4, 25,15,14,10, 6, 13,16,17,14,15,11, }; const dReal h42_planes[ h42_numf * 4 ] = { 0.267862,-0.627092,0.731441,0.29219,1,2.67045e-16,1.9344e-17,0.185006,-0.0600487,-0.168696,0.983837,0.381279,-0.864691,-0.138024,-0.482969,0.305068,-0.287163,-0.873965,-0.392074,0.304972,-0.73808,-0.518378,0.431882,0.237585,0.156805,0.660773,-0.734024,0.322525,0.0606999,0.0852635,-0.994508,0.400738,-0.364346,0.255892,-0.895417,0.317763,-0.280943,0.383024,0.879979,0.427298,-0.590109,0.664552,0.458413,0.324491,-0.86695,0.495807,-0.0507289,0.273077,-0.11569,0.975032,-0.189546,0.277024,-0.485104,0.868795,0.0993492,0.257853,-0.191731,0.844679,0.499756,0.381605 }; // h43 const int h43_numv = 26; const int h43_numf = 15; const dReal h43_volu = 0.091347; const dReal h43_pos[3] = { -0.439313,0.395062,-0.161996 }; const dReal h43_verts[ h43_numv * 3 ] = { -0.171800,0.355423,-0.143529, -0.041887,-0.040549,-0.338294, -0.088904,0.443945,0.033555, -0.050746,0.256028,0.267789, -0.120718,0.085236,0.331241, 0.112903,-0.317075,-0.192421, -0.024680,-0.380539,0.081401, 0.014540,-0.410443,-0.096363, -0.166472,-0.135578,-0.232924, -0.179653,0.199344,0.219565, 0.056744,-0.387608,-0.004660, -0.088904,0.425462,0.081094, -0.046327,-0.413563,-0.075262, -0.024725,0.299814,0.247575, -0.150602,0.151087,0.286944, -0.050613,-0.134365,0.334664, -0.244880,0.199344,-0.098926, -0.122184,0.302440,-0.201067, -0.108793,0.292906,-0.209241, -0.034597,-0.039973,-0.340964, 0.309817,-0.173124,-0.053206, -0.070119,0.430571,0.022089, 0.002939,0.029802,-0.334091, 0.280604,-0.188322,-0.121373, 0.290359,0.017349,0.142160, 0.257236,0.070405,0.149235, }; const unsigned int h43_faces[] = { 5, 8,16,0,17,1, 5, 17,18,22,19,1, 6, 19,5,7,12,8,1, 5, 21,18,17,0,2, 5, 0,16,9,11,2, 5, 11,13,25,21,2, 6, 4,15,24,25,13,3, 5, 13,11,9,14,3, 3, 14,4,3, 8, 14,9,16,8,12,6,15,4, 4, 19,22,23,5, 5, 23,20,10,7,5, 5, 10,20,24,15,6, 4, 12,7,10,6, 7, 21,25,24,20,23,22,18, }; const dReal h43_planes[ h43_numf * 4 ] = { -0.693474,0.121763,-0.710118,0.264339,-0.349687,0.276295,-0.895198,0.306284,-0.24653,-0.556538,-0.793403,0.301297,0.256638,0.811103,-0.525594,0.319633,-0.870583,0.45858,0.178295,0.286965,0.662611,0.698059,0.271405,0.260098,0.433652,0.152285,0.888119,0.254811,-0.49733,0.589429,0.636582,0.346617,-0.296224,0.4369,0.849335,0.354333,-0.935836,-0.295766,0.191659,0.151248,0.501077,-0.186311,-0.84511,0.278264,0.632147,-0.768422,-0.0995875,0.334181,0.582464,-0.552261,0.596443,0.244332,0.11569,-0.975032,0.189546,0.383611,0.73808,0.518378,-0.431882,0.161906 }; // h44 const int h44_numv = 26; const int h44_numf = 15; const dReal h44_volu = 0.104111; const dReal h44_pos[3] = { -0.656166,-0.300748,0.215302 }; const dReal h44_verts[ h44_numv * 3 ] = { -0.220317,0.235145,-0.208278, 0.078796,0.351295,-0.102059, 0.283317,-0.102949,0.430780, 0.285327,-0.088643,0.424402, 0.201177,0.226255,-0.138992, 0.124677,-0.319431,0.033433, 0.117727,0.304230,-0.184196, 0.043064,-0.325887,0.063320, -0.138842,0.186808,-0.302762, 0.311997,0.075640,-0.076273, 0.067923,-0.171282,-0.181336, -0.343834,-0.050448,-0.267282, -0.343834,-0.078267,-0.052628, -0.343834,0.035932,0.053112, 0.088073,0.239020,0.159535, 0.282143,-0.129188,0.406909, -0.286183,0.003244,-0.364214, -0.343834,0.054532,0.043544, 0.011578,-0.313217,0.111616, 0.329134,0.030906,-0.011422, 0.089881,-0.140507,0.355648, 0.092412,-0.225203,0.279944, 0.288380,-0.225380,0.170160, 0.101854,0.336248,-0.130909, -0.343834,-0.006528,-0.335059, -0.343834,0.160238,-0.192084, }; const unsigned int h44_faces[] = { 7, 14,3,19,9,4,23,1, 5, 23,6,8,0,1, 5, 0,25,17,14,1, 5, 15,22,19,3,2, 6, 3,14,17,13,20,2, 4, 20,21,15,2, 6, 9,10,16,8,6,4, 3, 6,23,4, 6, 22,15,21,18,7,5, 6, 7,11,24,16,10,5, 5, 10,9,19,22,5, 4, 18,12,11,7, 5, 16,24,25,0,8, 6, 12,13,17,25,24,11, 5, 18,21,20,13,12, }; const dReal h44_planes[ h44_numf * 4 ] = { 0.727924,0.639056,0.248465,0.256497,-0.131611,0.83191,-0.539077,0.336893,-0.446963,0.816184,0.366152,0.214133,0.991673,-0.108076,0.0700326,0.322253,-0.398278,0.419585,0.815673,0.19534,-0.156805,-0.660773,0.734024,0.339803,0.438192,-0.051293,-0.897417,0.201283,0.722578,0.66608,-0.18498,0.321781,0.20808,-0.904248,0.372879,0.327254,-0.131611,-0.83191,-0.539077,0.231306,0.708232,-0.479648,-0.518021,0.224196,-0.512085,-0.851811,-0.110395,0.248551,-0.443092,0.583496,-0.68059,0.376579,-1,6.26681e-16,4.55506e-17,0.343834,-0.619037,-0.533581,0.576268,0.22428 }; // h45 const int h45_numv = 22; const int h45_numf = 13; const dReal h45_volu = 0.073607; const dReal h45_pos[3] = { -0.692003,0.228592,-0.074767 }; const dReal h45_verts[ h45_numv * 3 ] = { 0.206363,-0.247093,-0.162491, 0.114633,-0.178045,0.188010, 0.007810,0.365814,-0.186155, -0.306616,-0.033345,0.126518, -0.055718,0.198405,0.254002, 0.153565,-0.225110,0.105873, -0.184480,-0.294195,0.081791, 0.073037,0.365814,0.132336, 0.155930,-0.080562,0.225951, -0.173050,0.172678,-0.175116, -0.103005,-0.342532,-0.012694, -0.015749,-0.330108,-0.146901, 0.086218,0.030892,-0.320153, -0.015750,-0.032626,-0.299926, 0.228010,-0.214069,-0.005829, 0.104078,0.176805,0.286842, 0.137691,-0.193092,0.159160, 0.102087,0.317557,0.199715, -0.062260,0.197254,0.252076, 0.131971,0.251706,0.244012, 0.186972,0.021095,0.262581, 0.202077,0.032105,0.247435, }; const unsigned int h45_faces[] = { 8, 8,20,15,4,18,3,6,1, 5, 6,10,5,16,1, 3, 16,8,1, 4, 12,13,9,2, 5, 9,3,18,7,2, 8, 7,17,19,21,14,0,12,2, 6, 9,13,11,10,6,3, 4, 15,19,17,4, 4, 17,7,18,4, 6, 14,21,20,8,16,5, 5, 10,11,0,14,5, 4, 13,12,0,11, 4, 20,21,19,15, }; const dReal h45_planes[ h45_numf * 4 ] = { -0.228531,-0.267508,0.936063,0.19742,0.131611,-0.83191,0.539077,0.264556,0.535431,-0.493566,0.685351,0.278107,-0.349687,0.276295,-0.895198,0.264987,-0.717787,0.680568,0.147003,0.21599,0.935836,0.295766,-0.191659,0.151183,-0.793213,-0.278551,-0.5415,0.183991,-0.103318,0.522457,0.846383,0.324397,-0.311731,0.703731,0.638425,0.319154,0.777333,-0.40946,0.477593,0.262108,0.35532,-0.923345,0.145539,0.277827,0.107916,-0.45476,-0.884052,0.278288,0.613049,0.207593,0.762283,0.319163 }; // h46 const int h46_numv = 24; const int h46_numf = 14; const dReal h46_volu = 0.077166; const dReal h46_pos[3] = { -0.506861,-0.263372,-0.148064 }; const dReal h46_verts[ h46_numv * 3 ] = { -0.435488,-0.034132,-0.000849, 0.039076,-0.286247,0.028683, -0.031577,0.266854,0.179170, 0.042868,0.277895,0.067468, 0.334025,-0.207064,-0.069876, -0.200891,0.161856,-0.073604, -0.329922,-0.035641,-0.192524, -0.391003,-0.070120,-0.144257, 0.124292,0.270826,-0.018593, -0.288147,0.149432,0.060603, 0.051872,0.188879,0.224374, -0.081382,-0.208658,0.182030, 0.243097,0.052743,0.247717, 0.267097,-0.250173,-0.073376, 0.162691,0.038264,0.287094, 0.339607,0.040898,0.152251, 0.238297,0.049029,0.252023, 0.349700,0.004968,0.138697, 0.021220,0.244871,-0.089194, -0.322311,-0.040247,-0.199445, -0.016599,-0.019353,-0.300951, 0.082088,0.247991,-0.110295, -0.339273,-0.043963,-0.190526, 0.082087,0.036350,-0.291745, }; const unsigned int h46_faces[] = { 6, 7,22,19,20,13,1, 7, 13,4,17,16,14,11,1, 4, 11,0,7,1, 6, 10,12,15,8,3,2, 5, 3,18,5,9,2, 6, 9,0,11,14,10,2, 4, 8,21,18,3, 4, 13,20,23,4, 6, 23,21,8,15,17,4, 7, 18,21,23,20,19,6,5, 6, 6,22,7,0,9,5, 3, 19,22,6, 4, 14,16,12,10, 4, 16,17,15,12, }; const dReal h46_planes[ h46_numf * 4 ] = { -0.148211,-0.780702,-0.607074,0.200269,0.391463,-0.659847,0.641373,0.222573,-0.471464,-0.878752,0.0742736,0.235248,0.496382,0.766976,0.406636,0.261853,-0.35532,0.923345,-0.145539,0.231542,-0.438192,0.051293,0.897417,0.188315,-0.11569,0.975032,-0.189546,0.253209,0.322885,-0.43293,-0.841615,0.256305,0.792041,0.39734,-0.463457,0.214671,-0.284317,0.624016,-0.727852,0.21169,-0.66062,0.653782,-0.368986,0.26569,-0.494656,0.366713,-0.787932,0.301823,0.289106,0.541464,0.789452,0.2944,0.696788,-0.0734069,0.713511,0.342264 }; // h47 const int h47_numv = 36; const int h47_numf = 20; const dReal h47_volu = 0.096745; const dReal h47_pos[3] = { -0.132135,0.108975,0.072319 }; const dReal h47_verts[ h47_numv * 3 ] = { 0.298509,0.263511,-0.009995, -0.406303,-0.105494,-0.041213, 0.295351,0.263929,-0.015607, -0.362255,0.123840,0.142831, -0.016819,0.303436,-0.092155, 0.214655,-0.206919,0.163772, 0.119596,0.038081,0.333996, -0.357791,0.151721,0.100349, 0.141669,-0.202865,0.220831, -0.322854,-0.183468,0.003991, -0.422177,-0.073475,0.012073, 0.248529,0.277838,-0.020262, -0.331858,-0.094452,-0.152914, -0.250434,-0.101521,-0.238975, -0.131628,-0.319604,0.027334, 0.281027,0.056414,-0.190466, 0.134068,0.286800,-0.104666, 0.293847,0.266235,0.003176, -0.403938,0.039055,0.078865, -0.372896,0.140712,0.115495, -0.035119,-0.331449,-0.068132, 0.121232,-0.294347,-0.049046, 0.051634,0.305873,-0.087560, 0.254870,0.274829,-0.031097, 0.196475,0.139795,-0.254001, 0.002640,0.112963,-0.287521, 0.198447,0.073853,0.288417, 0.224142,0.132346,-0.243414, 0.225218,-0.213510,0.136980, 0.298178,-0.027388,0.023425, 0.292448,0.199019,0.106734, 0.304944,0.253729,-0.022071, 0.308556,0.186869,0.065231, 0.305066,0.254217,-0.020526, 0.293027,0.163885,-0.150423, 0.287364,0.062429,-0.181183, }; const unsigned int h47_faces[] = { 6, 12,13,20,14,9,1, 3, 9,10,1, 6, 10,18,19,7,12,1, 4, 0,33,31,2, 7, 31,34,27,24,16,23,2, 5, 23,11,17,0,2, 10, 6,26,30,17,11,22,4,7,19,3, 3, 19,18,3, 7, 18,10,9,14,8,6,3, 5, 22,16,24,25,4, 5, 25,13,12,7,4, 6, 28,29,32,30,26,5, 4, 26,6,8,5, 6, 8,14,20,21,28,5, 4, 23,16,22,11, 7, 25,24,27,15,21,20,13, 4, 27,34,35,15, 5, 35,29,28,21,15, 5, 30,32,33,0,17, 6, 35,34,31,33,32,29, }; const dReal h47_planes[ h47_numf * 4 ] = { -0.496382,-0.766976,-0.406636,0.299351,-0.722578,-0.66608,0.18498,0.35623,-0.777333,0.40946,-0.477593,0.292321,0.60243,0.746152,-0.283435,0.379283,0.40667,0.730271,-0.54893,0.321417,0.292039,0.95183,-0.0934524,0.338928,-0.066237,0.837367,0.542613,0.205196,-0.897445,0.121213,0.424146,0.400696,-0.398278,-0.419584,0.815674,0.208821,0.0212658,0.716912,-0.696839,0.281397,-0.582464,0.552261,-0.596443,0.232337,0.913105,-0.120244,0.389591,0.284687,0.576312,-0.303571,0.758755,0.310786,0.184883,-0.934913,0.302912,0.282746,0.191593,0.968844,-0.156953,0.319978,0.212159,-0.447018,-0.869002,0.19992,0.770892,0.145024,-0.620237,0.342957,0.836212,-0.484521,-0.256884,0.256592,0.900933,0.358346,0.24476,0.360918,0.997066,-0.0350131,-0.0680664,0.296668 }; // h48 const int h48_numv = 24; const int h48_numf = 14; const dReal h48_volu = 0.097516; const dReal h48_pos[3] = { 0.292729,-0.243911,-0.041409 }; const dReal h48_verts[ h48_numv * 3 ] = { -0.303632,0.058539,0.064682, -0.108656,-0.084639,-0.284158, 0.263889,0.072976,-0.223666, 0.274166,-0.102559,0.259484, 0.253318,-0.136696,0.282134, 0.346872,-0.016291,-0.139905, -0.290945,-0.203383,-0.035982, 0.008763,0.056080,-0.365621, 0.246275,0.103070,-0.201305, 0.107569,-0.173012,0.336398, -0.249499,-0.215623,0.017984, -0.234675,-0.199275,-0.122635, 0.023817,-0.271216,0.180037, 0.169540,-0.271216,0.037729, -0.126686,0.325499,0.137154, 0.195210,-0.264110,0.029895, 0.346221,-0.018608,-0.151429, 0.279567,-0.135810,-0.157801, -0.143837,0.409300,-0.076739, -0.137500,0.415315,-0.067456, -0.031223,0.088614,-0.351675, -0.000004,-0.036295,-0.345501, -0.199646,0.139376,0.250708, -0.108109,-0.019468,0.310070, }; const unsigned int h48_faces[] = { 4, 20,7,21,1, 6, 21,17,15,13,11,1, 6, 11,6,0,18,20,1, 5, 16,17,21,7,2, 6, 7,20,18,19,8,2, 4, 8,5,16,2, 6, 14,22,23,9,4,3, 6, 4,15,17,16,5,3, 5, 5,8,19,14,3, 5, 9,12,13,15,4, 5, 10,23,22,0,6, 5, 11,13,12,10,6, 4, 23,10,12,9, 5, 19,18,0,22,14, }; const dReal h48_planes[ h48_numf * 4 ] = { -0.433652,-0.152283,-0.888119,0.312375,0.066237,-0.837367,-0.542613,0.217865,-0.830851,0.164118,-0.531744,0.227486,0.484779,-0.229821,-0.843903,0.299909,0.322183,0.678839,-0.659831,0.282141,0.794108,0.585614,-0.162633,0.288667,0.212159,0.447018,0.869002,0.237812,0.86695,-0.495807,0.0507289,0.301701,0.66261,0.69806,0.271405,0.180498,0.348894,-0.86639,0.357268,0.30761,-0.794364,-0.251059,0.553132,0.262275,-0.124536,-0.983986,-0.127525,0.240948,-0.49733,-0.589428,0.636583,0.262626,-0.836212,0.484521,0.256884,0.29888 }; // h49 const int h49_numv = 30; const int h49_numf = 17; const dReal h49_volu = 0.103417; const dReal h49_pos[3] = { -0.082648,-0.117151,-0.277803 }; const dReal h49_verts[ h49_numv * 3 ] = { 0.344154,-0.038146,-0.115281, -0.165239,0.018854,-0.286732, -0.342125,0.101770,0.019444, -0.222234,-0.108669,-0.237036, -0.321677,-0.099820,-0.189997, 0.084432,-0.330143,0.200412, -0.076061,0.323891,-0.005566, -0.299921,0.124605,0.111147, -0.223248,0.024754,-0.259418, 0.141702,0.335375,-0.073499, 0.231540,0.282540,0.159656, 0.156937,0.153559,-0.266131, -0.243762,0.195138,-0.076614, -0.084607,-0.105324,0.281990, 0.266721,-0.211399,-0.047765, 0.071745,-0.068221,0.301076, -0.090188,-0.353285,0.059864, -0.342125,-0.109871,-0.162005, -0.074513,-0.141253,0.268436, 0.140702,-0.326035,0.113759, 0.082436,-0.372046,-0.016546, 0.056586,-0.396243,0.036572, 0.007365,-0.408266,0.085169, 0.068619,-0.340196,0.196052, 0.183372,0.187050,-0.241355, 0.271282,0.058201,-0.185174, 0.174655,0.358472,0.106708, -0.046848,0.339089,0.062601, 0.146988,0.365921,0.096121, 0.157998,0.356836,0.037994, }; const unsigned int h49_faces[] = { 4, 3,4,8,1, 7, 8,12,6,9,24,11,1, 7, 11,25,0,14,20,3,1, 6, 17,16,18,13,7,2, 5, 7,27,6,12,2, 5, 12,8,4,17,2, 7, 20,21,22,16,17,4,3, 5, 15,13,18,23,5, 5, 23,22,21,19,5, 6, 19,14,0,10,15,5, 5, 27,28,29,9,6, 7, 13,15,10,26,28,27,7, 7, 29,26,10,0,25,24,9, 3, 24,25,11, 4, 19,21,20,14, 4, 22,23,18,16, 3, 29,28,26, }; const dReal h49_planes[ h49_numf * 4 ] = { -0.433652,-0.152283,-0.888119,0.323437,-0.247318,0.694798,-0.675344,0.247609,0.240814,-0.443968,-0.863077,0.199309,-0.792041,-0.39734,0.463457,0.239551,-0.632147,0.768422,0.0995875,0.296413,-0.805487,0.385719,-0.449901,0.306085,-0.315015,-0.796483,-0.516121,0.2789,-0.0284606,-0.359798,0.932596,0.303286,0.465257,-0.845503,0.262033,0.370934,0.830851,-0.164118,0.531744,0.230901,-0.105626,0.979232,-0.173057,0.326162,-0.212159,0.447018,0.869002,0.215918,0.847832,0.483811,-0.217045,0.29835,0.621965,0.0849382,-0.778424,0.317815,0.654405,-0.755705,-0.0257735,0.33553,-0.49733,-0.589428,0.636583,0.291198,0.292039,0.95183,-0.0934524,0.382238 }; // h50 const int h50_numv = 20; const int h50_numf = 12; const dReal h50_volu = 0.069183; const dReal h50_pos[3] = { -0.304007,-0.060848,0.383791 }; const dReal h50_verts[ h50_numv * 3 ] = { 0.035443,-0.153495,-0.279832, 0.291468,0.207904,0.022524, -0.264086,-0.000880,-0.008953, -0.190383,0.293663,-0.168640, 0.004043,-0.311521,0.367447, -0.001962,-0.311376,0.364440, -0.150982,-0.013645,-0.307481, -0.250305,0.096348,-0.299398, 0.040243,-0.149781,-0.284138, -0.040162,-0.164260,-0.244761, -0.228192,0.064423,0.060664, 0.001805,-0.312717,0.366969, -0.232066,0.208878,-0.232607, -0.273363,0.111395,-0.270548, 0.313541,-0.033043,-0.090641, -0.003673,-0.314626,0.361097, -0.023025,-0.208994,-0.179911, -0.066832,-0.328543,0.255913, -0.170020,0.271491,-0.017447, 0.190786,0.198102,0.196479, }; const unsigned int h50_faces[] = { 4, 3,18,19,1, 4, 19,4,14,1, 7, 14,8,6,7,12,3,1, 6, 10,18,3,12,13,2, 7, 13,7,6,9,16,17,2, 5, 17,15,5,10,2, 8, 11,15,17,16,0,8,14,4, 6, 19,18,10,5,11,4, 3, 15,11,5, 4, 8,0,9,6, 3, 13,12,7, 3, 0,16,9, }; const dReal h50_planes[ h50_numf * 4 ] = { 0.124536,0.983986,0.127525,0.243745,0.859244,-0.150868,0.488814,0.230086,0.398278,0.419584,-0.815674,0.184946,-0.929286,0.326334,0.173016,0.243575,-0.727924,-0.639056,-0.248465,0.195021,-0.848621,-0.0894025,0.521393,0.219519,0.493232,-0.850288,-0.183662,0.199392,-0.398278,0.419584,0.815674,0.167397,-0.604872,-0.393584,0.692258,0.376026,-0.289106,-0.541464,-0.789452,0.293779,-0.535431,0.493566,-0.685351,0.386768,-0.131611,-0.83191,-0.539077,0.273881 }; // h51 const int h51_numv = 20; const int h51_numf = 12; const dReal h51_volu = 0.097496; const dReal h51_pos[3] = { 0.796238,0.092236,-0.101631 }; const dReal h51_verts[ h51_numv * 3 ] = { -0.221011,0.347408,0.061823, -0.319697,0.291705,0.052616, 0.203762,-0.222678,0.367837, -0.200562,0.357460,0.033830, 0.203762,0.194344,-0.275142, -0.239620,-0.263171,-0.163444, 0.152653,-0.230111,0.360793, 0.203762,0.321480,-0.157424, -0.337380,0.280442,0.025237, -0.327866,0.285347,0.016786, -0.028332,0.052718,-0.315616, 0.203762,-0.298399,-0.021674, -0.257234,-0.233077,-0.141083, -0.157288,-0.354755,-0.091207, 0.203762,0.006585,0.328526, -0.156637,-0.352438,-0.079683, 0.030926,0.103995,0.283692, -0.036002,0.060886,0.280191, -0.157223,-0.222560,-0.236947, -0.067033,-0.350976,-0.126852, }; const unsigned int h51_faces[] = { 4, 17,16,0,1, 5, 0,3,9,8,1, 6, 8,12,15,6,17,1, 5, 14,16,17,6,2, 6, 6,15,13,19,11,2, 5, 11,4,7,14,2, 5, 7,4,10,9,3, 5, 0,16,14,7,3, 5, 11,19,18,10,4, 4, 18,19,13,5, 4, 13,15,12,5, 6, 12,8,9,10,18,5, }; const dReal h51_planes[ h51_numf * 4 ] = { -0.322885,0.43293,0.841615,0.273796,-0.488006,0.871758,-0.0434538,0.408025,-0.73548,-0.309929,0.602505,0.176424,-0.158394,0.166869,0.973173,0.288536,0.11569,-0.975032,0.189546,0.310413,1,0,0,0.203762,-0.275531,0.653109,-0.705359,0.26486,0.315015,0.796483,0.516121,0.238991,0.398278,-0.419585,-0.815673,0.224036,-0.228161,-0.721101,-0.654183,0.351367,-0.794108,-0.585614,0.162633,0.31782,-0.693474,0.121763,-0.710118,0.250191 }; // h52 const int h52_numv = 16; const int h52_numf = 10; const dReal h52_volu = 0.084293; const dReal h52_pos[3] = { 0.513157,0.018456,0.067444 }; const dReal h52_verts[ h52_numv * 3 ] = { -0.347114,0.063132,0.028301, -0.352265,0.254404,-0.145548, 0.247079,0.134666,0.111116, -0.336736,0.277388,0.070106, 0.126444,-0.278658,-0.248758, -0.340226,0.344736,-0.015651, 0.295476,-0.245782,0.289096, -0.054299,0.354222,-0.143838, 0.053738,-0.364926,0.150631, -0.036616,0.365485,-0.116459, 0.025847,-0.159297,-0.310158, -0.357928,0.152948,-0.176308, 0.019058,0.098592,0.213176, 0.435734,-0.156331,0.191718, -0.340348,0.344248,-0.017196, -0.236518,0.326242,-0.134679, }; const unsigned int h52_faces[] = { 3, 14,15,1, 5, 15,7,10,11,1, 6, 11,0,3,5,14,1, 4, 12,6,13,2, 6, 13,4,10,7,9,2, 5, 9,5,3,12,2, 5, 0,8,6,12,3, 4, 13,6,8,4, 5, 8,0,11,10,4, 5, 9,7,15,14,5, }; const dReal h52_planes[ h52_numf * 4 ] = { -0.425203,0.759567,-0.4922,0.41466,-0.0929092,0.293639,-0.951391,0.245904,-0.997066,0.0350131,0.0680664,0.350232,0.309646,0.434949,0.84554,0.229033,0.73548,0.309929,-0.602505,0.156511,0.148211,0.780702,0.607074,0.209209,-0.433652,-0.152285,0.888119,0.166047,0.485104,-0.868795,-0.0993492,0.328149,-0.66261,-0.69806,-0.271405,0.17825,-0.159459,0.944944,-0.285751,0.38448 }; // h53 const int h53_numv = 16; const int h53_numf = 10; const dReal h53_volu = 0.086476; const dReal h53_pos[3] = { -0.781555,0.807509,0.197497 }; const dReal h53_verts[ h53_numv * 3 ] = { 0.291496,-0.156419,-0.091704, -0.218445,0.192491,0.461269, -0.218445,0.192491,-0.255541, -0.218445,-0.397567,0.047987, 0.027292,-0.381663,-0.020188, -0.218445,-0.373860,0.169935, 0.033835,-0.380512,-0.018262, 0.352556,0.192491,0.043056, 0.162589,-0.213103,-0.139928, 0.191640,-0.261360,-0.072549, 0.238502,0.192491,-0.291089, 0.253338,0.013015,-0.278399, 0.326334,-0.087525,-0.081781, 0.317517,-0.112633,-0.111918, 0.238502,0.081667,-0.310092, 0.153590,0.192491,-0.346370, }; const unsigned int h53_faces[] = { 7, 5,6,9,0,12,7,1, 5, 7,10,15,2,1, 4, 2,3,5,1, 7, 15,14,11,8,4,3,2, 4, 4,6,5,3, 4, 8,9,6,4, 6, 12,13,11,14,10,7, 5, 11,13,0,9,8, 3, 14,15,10, 3, 0,13,12, }; const dReal h53_planes[ h53_numf * 4 ] = { 0.545755,-0.383303,0.745138,0.150709,-0,1,0,0.192491,-1,0,-0,0.218445,-0.212159,-0.447018,-0.869002,0.182363,0.11569,-0.975032,0.189546,0.371464,0.311731,-0.703731,-0.638425,0.289984,0.944939,0.0553043,-0.322539,0.329903,0.49733,-0.589429,-0.636582,0.295545,0.540055,0.142236,-0.829524,0.397648,0.877441,-0.462191,0.128357,0.316295 }; // h54 const int h54_numv = 20; const int h54_numf = 12; const dReal h54_volu = 0.089003; const dReal h54_pos[3] = { -0.845912,0.679404,-0.140778 }; const dReal h54_verts[ h54_numv * 3 ] = { 0.317695,0.141120,0.059877, 0.091649,-0.253558,0.318087, -0.154088,0.080768,-0.359617, -0.152707,-0.484157,0.192529, -0.154088,0.320596,0.082735, 0.078976,0.204301,-0.281846, -0.154088,-0.269462,0.386262, -0.154088,0.320596,-0.236248, -0.154088,-0.484416,0.192760, 0.226946,-0.084997,0.198347, 0.060656,0.320596,-0.223141, 0.161719,-0.084997,-0.120143, 0.217947,0.320596,-0.008094, -0.049829,0.124065,-0.330981, -0.154088,-0.230098,-0.199706, -0.019141,-0.278134,-0.109104, 0.160374,0.124065,-0.228342, 0.234799,0.071081,-0.164747, 0.302859,0.209772,0.028184, 0.317695,0.159603,0.012337, }; const unsigned int h54_faces[] = { 4, 6,8,3,1, 5, 3,15,11,9,1, 7, 9,0,18,12,4,6,1, 5, 7,10,5,13,2, 7, 13,16,17,11,15,14,2, 6, 14,8,6,4,7,2, 4, 8,14,15,3, 4, 12,10,7,4, 7, 10,12,18,19,17,16,5, 3, 16,13,5, 5, 11,17,19,0,9, 3, 0,19,18, }; const dReal h54_planes[ h54_numf * 4 ] = { 0.242073,-0.64915,0.721114,0.41616,0.717787,-0.680568,-0.147003,0.191588,0.212159,0.447018,0.869002,0.182518,0.0541955,0.456759,-0.887938,0.347858,0.398278,-0.419585,-0.815673,0.19807,-1,0,0,0.154088,0.066237,-0.837367,-0.542613,0.290833,0,1,0,0.320596,0.742791,0.391264,-0.543299,0.291725,0.433652,-0.152285,-0.888119,0.253448,0.870583,-0.45858,-0.178295,0.201189,0.962317,0.253449,0.0985412,0.34739 }; // h55 const int h55_numv = 16; const int h55_numf = 10; const dReal h55_volu = 0.055290; const dReal h55_pos[3] = { 0.087136,0.788999,0.139771 }; const dReal h55_verts[ h55_numv * 3 ] = { 0.076080,-0.416095,-0.083059, -0.323951,0.211001,0.286715, 0.205112,0.211001,-0.185127, 0.076081,0.211001,-0.405639, -0.148237,0.211001,0.332473, 0.101171,-0.226374,0.192117, -0.006832,-0.085411,0.277812, 0.205111,-0.223849,0.038561, -0.274823,0.078877,0.258729, 0.035595,0.211001,-0.415523, 0.074576,-0.413789,-0.064275, 0.079238,-0.416513,-0.077447, 0.107256,-0.249478,0.168347, 0.117855,-0.236273,0.172768, 0.029258,-0.402186,-0.087713, 0.035598,-0.405195,-0.098549, }; const unsigned int h55_faces[] = { 4, 8,6,4,1, 5, 4,2,3,9,1, 5, 9,15,14,8,1, 5, 7,11,0,3,2, 6, 4,6,5,13,7,2, 4, 0,15,9,3, 3, 12,13,5, 6, 6,8,14,10,12,5, 5, 13,12,10,11,7, 5, 14,15,0,11,10, }; const dReal h55_planes[ h55_numf * 4 ] = { -0.241471,-0.286187,0.927248,0.283694,0,1,0,0.211001,-0.866617,-0.228251,-0.443708,0.105363,0.835368,-0.251447,-0.48881,0.20878,0.793214,0.278548,0.541501,0.121225,0.212159,-0.447018,-0.869002,0.274321,0.443092,-0.583496,0.68059,0.307669,-0.463507,-0.691764,0.553737,0.216086,0.66062,-0.653782,0.368986,0.296077,-0.292039,-0.95183,0.0934524,0.366071 }; // h56 const int h56_numv = 20; const int h56_numf = 12; const dReal h56_volu = 0.096963; const dReal h56_pos[3] = { -0.186579,0.800379,0.005269 }; const dReal h56_verts[ h56_numv * 3 ] = { 0.004502,-0.334912,-0.018030, 0.302973,-0.413566,0.046788, 0.309310,0.199621,-0.281021, -0.242420,0.199621,0.235284, -0.121421,0.199621,0.412527, 0.172708,0.199621,-0.357250, -0.050236,0.199621,0.421217, -0.341638,0.020145,-0.086171, -0.356474,0.199621,-0.098861, 0.097656,0.085128,-0.340236, -0.001108,0.067497,0.393231, -0.356474,0.088797,-0.117864, -0.277459,-0.105503,0.080310, 0.309314,-0.416575,0.035953, 0.106078,-0.385531,-0.020510, 0.188512,-0.404604,-0.037617, -0.268642,-0.080395,0.110447, -0.118494,0.123210,0.393231, -0.341638,0.038628,-0.133710, -0.322853,0.025254,-0.145176, }; const unsigned int h56_faces[] = { 4, 14,15,13,1, 5, 13,2,6,10,1, 7, 10,17,16,12,0,14,1, 5, 13,15,9,5,2, 6, 5,8,3,4,6,2, 4, 16,17,4,3, 6, 8,11,7,12,16,3, 4, 17,10,6,4, 6, 9,19,18,11,8,5, 5, 18,19,0,12,7, 3, 11,18,7, 5, 15,14,0,19,9, }; const dReal h56_planes[ h56_numf * 4 ] = { -0.191593,-0.968844,0.156953,0.349977,0.866617,0.228251,0.443708,0.188925,-0.322183,-0.678838,0.659831,0.214003,0.444511,-0.409753,-0.796563,0.279548,4.04497e-16,1,-1.19541e-16,0.199621,-0.813673,-0.17144,0.555468,0.293719,-0.944939,-0.0553043,0.322539,0.29392,-0.117405,-0.247371,0.961782,0.361636,-0.433652,0.152285,-0.888119,0.272785,-0.662611,-0.698059,-0.271405,0.235698,-0.962317,-0.253449,-0.0985412,0.33215,-0.289106,-0.541462,-0.789453,0.194274 }; // h57 const int h57_numv = 16; const int h57_numf = 10; const dReal h57_volu = 0.081294; const dReal h57_pos[3] = { 0.851151,0.533342,0.098902 }; const dReal h57_verts[ h57_numv * 3 ] = { -0.184097,0.265595,0.004922, 0.148849,0.009818,-0.380153, 0.148849,-0.049459,0.325702, -0.275924,-0.093697,-0.138710, 0.148849,-0.119626,-0.357957, -0.275924,0.137573,0.059567, -0.112901,0.343928,0.059438, -0.249462,0.157589,0.121951, 0.148849,-0.434521,0.127992, 0.148849,0.447452,0.070089, 0.148849,-0.343521,0.212252, -0.023987,-0.337111,0.083159, -0.018406,-0.089149,0.305285, -0.008312,-0.125079,0.291731, -0.255475,-0.083645,-0.166703, -0.157047,0.040928,-0.236124, }; const unsigned int h57_faces[] = { 4, 4,14,15,1, 5, 15,0,6,9,1, 6, 9,2,10,8,4,1, 4, 12,13,10,2, 5, 9,6,7,12,2, 5, 14,4,8,11,3, 6, 11,13,12,7,5,3, 5, 5,0,15,14,3, 4, 7,6,0,5, 4, 10,13,11,8, }; const dReal h57_planes[ h57_numf * 4 ] = { -0.433652,-0.152285,-0.888119,0.271577,-0.247318,0.694798,-0.675344,0.226742,1,0,-0,0.148849,-0.0284606,-0.359798,0.932596,0.317307,-0.212159,0.447018,0.869002,0.229347,-0.315015,-0.796483,-0.516121,0.233139,-0.792041,-0.39734,0.463457,0.191487,-0.805488,0.385717,-0.449902,0.248519,-0.777693,0.614473,0.132726,0.307026,-0.49733,-0.589428,0.636583,0.26357 }; // h58 const int h58_numv = 20; const int h58_numf = 12; const dReal h58_volu = 0.077812; const dReal h58_pos[3] = { 0.374418,0.849026,0.291935 }; const dReal h58_verts[ h58_numv * 3 ] = { -0.082171,-0.283876,-0.113603, 0.200809,-0.178111,-0.133466, -0.082170,0.150974,-0.337291, 0.089508,-0.034332,0.259248, 0.146093,0.150974,0.326019, 0.410849,0.150974,-0.104898, -0.435519,0.150974,0.180309, -0.294114,-0.145438,0.125648, 0.292636,-0.050089,-0.188111, 0.183309,0.150974,-0.304884, 0.227271,-0.158095,-0.071082, 0.363832,0.028244,-0.133595, -0.169427,-0.296300,0.020604, 0.087144,-0.178878,0.139171, 0.071270,-0.146859,0.192458, -0.429747,0.150974,0.185433, -0.186111,-0.286401,0.039952, 0.048213,-0.131812,0.221308, -0.268420,-0.171352,0.132706, -0.212551,-0.233071,0.128708, }; const unsigned int h58_faces[] = { 5, 10,13,12,0,1, 5, 0,2,9,8,1, 4, 8,11,10,1, 6, 0,12,16,7,6,2, 6, 6,15,4,5,9,2, 6, 4,15,18,19,17,3, 3, 17,14,3, 7, 14,13,10,11,5,4,3, 4, 11,8,9,5, 4, 7,18,15,6, 4, 16,19,18,7, 6, 13,14,17,19,16,12, }; const dReal h58_planes[ h58_numf * 4 ] = { 0.35532,-0.923345,0.145539,0.216384,0.107916,-0.45476,-0.884052,0.220658,0.777693,-0.614473,-0.132726,0.283326,-0.793214,-0.278548,-0.541501,0.205768,0,1,-0,0.150974,-0.228531,-0.267508,0.936063,0.231401,0.535431,-0.493566,0.685351,0.242546,0.777334,-0.409459,0.477594,0.20745,0.658203,-0.077045,-0.748888,0.337347,-0.604377,-0.413861,0.68077,0.323484,-0.722579,-0.66608,0.18498,0.332636,0.131611,-0.83191,0.539078,0.235303 }; // h59 const int h59_numv = 12; const int h59_numf = 8; const dReal h59_volu = 0.098632; const dReal h59_pos[3] = { 0.795288,0.838821,-0.270144 }; const dReal h59_verts[ h59_numv * 3 ] = { -0.010021,0.161179,0.457181, -0.356162,0.161179,-0.206090, 0.204712,-0.152000,-0.380610, 0.204712,0.161179,-0.434310, -0.057037,0.038449,0.428484, -0.237561,0.161179,0.257195, -0.256523,-0.089455,-0.203657, -0.128234,-0.039885,0.373968, 0.204712,-0.295661,-0.011106, -0.101183,-0.264551,0.132922, 0.204712,0.141973,0.439135, 0.204712,0.161179,0.444075, }; const unsigned int h59_faces[] = { 4, 3,2,6,1, 5, 6,9,7,5,1, 5, 5,0,11,3,1, 5, 3,11,10,8,2, 4, 8,9,6,2, 4, 10,11,0,4, 4, 0,5,7,4, 5, 7,9,8,10,4, }; const dReal h59_planes[ h59_numf * 4 ] = { -0.372229,-0.156858,-0.91479,0.29582,-0.90476,-0.357438,0.231619,0.216895,0,1,0,0.161178,1,1.92688e-15,-1.87292e-15,0.204712,-0.256529,-0.900844,-0.350247,0.217721,0.0590083,-0.248661,0.966792,0.401329,-0.658203,0.077045,0.748888,0.361391,0.247318,-0.694798,0.675344,0.248554 }; // h60 const int h60_numv = 22; const int h60_numf = 13; const dReal h60_volu = 0.091310; const dReal h60_pos[3] = { 0.415485,0.715407,-0.130668 }; const dReal h60_verts[ h60_numv * 3 ] = { -0.064779,0.284593,-0.364069, 0.142242,0.284593,0.117719, -0.242554,-0.352215,0.182461, 0.061056,-0.331466,0.081653, 0.180191,-0.265711,0.062868, 0.251569,0.083531,0.234492, -0.123237,0.284593,0.085312, -0.123238,-0.150257,0.309000, 0.159742,-0.044491,0.289138, 0.278619,-0.141137,-0.006553, -0.252268,0.284593,-0.135200, 0.123280,0.033960,-0.343133, 0.052142,0.000197,-0.360501, 0.023641,0.284593,-0.345566, 0.159742,-0.275763,0.090860, -0.138846,-0.370709,0.063434, -0.249111,-0.342921,0.192992, -0.046519,-0.292460,-0.089523, -0.252269,-0.342503,0.187380, -0.242676,-0.352703,0.180916, 0.052887,-0.337824,0.045824, 0.043373,-0.342729,0.054274, }; const unsigned int h60_faces[] = { 5, 5,9,11,13,1, 5, 13,0,10,6,1, 5, 6,7,8,5,1, 4, 16,18,19,2, 5, 19,15,21,3,2, 6, 3,14,8,7,16,2, 5, 21,20,4,14,3, 6, 20,17,12,11,9,4, 5, 9,5,8,14,4, 5, 10,18,16,7,6, 7, 0,12,17,15,19,18,10, 4, 12,0,13,11, 4, 17,20,21,15, }; const dReal h60_planes[ h60_numf * 4 ] = { 0.90476,0.357438,-0.231619,0.203154,8.63556e-17,1,-5.05304e-17,0.284593,-0.107916,0.45476,0.884052,0.218141,-0.60243,-0.746152,0.283435,0.460644,0.159459,-0.944944,0.285751,0.346285,0.284317,-0.624015,0.727852,0.28363,0.488006,-0.871758,0.0434538,0.322301,0.46199,-0.681388,-0.567693,0.228609,0.805488,-0.385717,0.449902,0.275915,-0.835368,0.251447,0.48881,0.21621,-0.73548,-0.309929,-0.602505,0.178793,0.204299,0.0717432,-0.976276,0.362615,0.120149,-0.911351,-0.393704,0.29619 }; // h61 const int h61_numv = 24; const int h61_numf = 14; const dReal h61_volu = 0.075853; const dReal h61_pos[3] = { 0.499694,0.403970,0.252554 }; const dReal h61_verts[ h61_numv * 3 ] = { 0.101994,0.286961,-0.031701, -0.294704,0.148756,0.059985, -0.023153,-0.020028,-0.301569, 0.156136,0.037589,0.286475, -0.323273,-0.108125,-0.115004, 0.032521,-0.286922,0.028066, -0.038132,0.266178,0.178552, 0.260541,-0.250848,-0.073994, 0.327470,-0.207739,-0.070493, 0.075532,0.266945,-0.094084, 0.075532,0.035675,-0.292362, 0.343145,0.004293,0.138079, 0.231743,0.048354,0.251404, 0.045317,0.188205,0.223756, -0.087937,-0.209333,0.181412, -0.330859,-0.089605,0.055955, 0.333052,0.040223,0.151633, 0.236542,0.052068,0.247099, -0.339382,-0.095975,-0.073501, -0.326763,-0.040778,-0.200761, -0.207448,0.161180,-0.074222, -0.333320,-0.031483,-0.190230, -0.305302,0.135551,0.055565, -0.337982,-0.028760,-0.177059, }; const unsigned int h61_faces[] = { 5, 20,21,23,22,1, 7, 22,15,14,3,13,6,1, 5, 6,0,9,20,1, 5, 7,5,4,19,2, 6, 19,21,20,9,10,2, 4, 10,8,7,2, 7, 14,5,7,8,11,12,3, 4, 12,17,13,3, 5, 18,23,21,19,4, 5, 5,14,15,18,4, 5, 13,17,16,0,6, 6, 10,9,0,16,11,8, 4, 16,17,12,11, 4, 22,23,18,15, }; const dReal h61_planes[ h61_numf * 4 ] = { -0.66062,0.653782,-0.368986,0.269808,-0.438192,0.051293,0.897417,0.190598,-0.35532,0.923345,-0.145539,0.233338,-0.148211,-0.780702,-0.607074,0.202142,-0.284317,0.624015,-0.727852,0.213583,0.322885,-0.43293,-0.841615,0.255,0.391463,-0.659847,0.641373,0.220056,0.289106,0.541462,0.789453,0.291652,-0.900933,-0.358346,-0.24476,0.358143,-0.471464,-0.878752,0.0742736,0.238885,0.496382,0.766976,0.406636,0.25783,0.792041,0.39734,-0.463457,0.209497,0.696788,-0.0734069,0.713511,0.337305,-0.991833,0.112685,0.0597434,0.321404 }; // h62 const int h62_numv = 18; const int h62_numf = 11; const dReal h62_volu = 0.089635; const dReal h62_pos[3] = { -0.412607,-0.798932,0.393221 }; const dReal h62_verts[ h62_numv * 3 ] = { 0.143743,0.178906,-0.080212, -0.336591,-0.057070,0.045432, -0.365487,-0.201068,0.063069, -0.043446,-0.201068,0.325146, -0.118881,0.178753,-0.144486, -0.152818,-0.201068,-0.248459, 0.205095,-0.201068,-0.388268, 0.337853,-0.164947,-0.214818, 0.038585,0.368996,0.228990, 0.242459,-0.068737,-0.310888, -0.200495,0.172297,-0.114599, -0.231981,0.184967,-0.066303, 0.334110,-0.201068,-0.227916, 0.209245,-0.110463,-0.361925, 0.145031,0.335652,0.325145, 0.169974,0.297178,0.268816, -0.151147,0.272981,0.102025, 0.044821,0.272804,-0.007759, }; const unsigned int h62_faces[] = { 5, 11,10,5,2,1, 6, 2,3,14,8,16,1, 3, 16,11,1, 5, 5,6,12,3,2, 5, 12,7,15,14,3, 6, 10,11,16,8,17,4, 5, 17,0,9,13,4, 5, 13,6,5,10,4, 5, 13,9,7,12,6, 4, 9,0,15,7, 5, 14,15,0,17,8, }; const dReal h62_planes[ h62_numf * 4 ] = { -0.822068,0.096228,-0.561199,0.245712,-0.616244,0.216405,0.75724,0.229475,-0.870583,0.45858,0.178295,0.27496,4.16641e-16,-1,1.84056e-16,0.201068,0.793214,-0.278548,0.541501,0.197612,-0.20808,0.904248,-0.372879,0.24025,0.167754,0.706913,-0.687119,0.205699,-0.349687,0.276295,-0.895198,0.220304,0.770892,0.145024,-0.620237,0.369765,0.799798,0.547681,-0.245698,0.232657,0.526505,0.792388,-0.308081,0.242156 }; // h63 const int h63_numv = 20; const int h63_numf = 12; const dReal h63_volu = 0.065070; const dReal h63_pos[3] = { -0.683722,-0.408459,0.881106 }; const dReal h63_verts[ h63_numv * 3 ] = { 0.408763,0.050375,-0.050997, 0.001643,0.372246,0.104787, -0.316278,-0.373443,0.118894, -0.000569,0.379463,0.118894, -0.316278,-0.303582,-0.012874, 0.413107,-0.090210,0.118894, 0.072977,-0.026465,-0.250457, -0.316278,0.104758,0.118894, -0.133134,0.036421,-0.232486, -0.316278,-0.061367,-0.137470, 0.406500,0.014459,-0.083368, 0.416439,0.055265,0.118894, 0.411396,0.069115,-0.001513, 0.370009,0.144956,0.118894, 0.377753,0.036235,-0.132875, 0.381520,0.034894,-0.130346, 0.374104,0.031050,-0.138388, 0.376042,0.032985,-0.136218, 0.383396,0.034505,-0.128411, 0.385682,0.029196,-0.126410, }; const unsigned int h63_faces[] = { 5, 8,9,7,3,1, 8, 3,13,12,0,18,15,14,1, 6, 14,17,16,6,8,1, 7, 4,6,16,19,10,5,2, 6, 5,11,13,3,7,2, 4, 7,9,4,2, 4, 9,8,6,4, 5, 10,0,12,11,5, 4, 19,18,0,10, 3, 12,13,11, 3, 15,17,14, 5, 18,19,16,17,15, }; const dReal h63_planes[ h63_numf * 4 ] = { -0.589724,0.677749,-0.439183,0.2053,0.50496,0.797961,-0.32905,0.263387,0.141863,0.672536,-0.72634,0.174471,0.324513,-0.835692,-0.443069,0.156769,2.1681e-17,-2.49173e-17,1,0.118894,-1,0,0,0.316278,-0.212159,-0.447018,-0.869002,0.213995,0.998749,-0.0228741,-0.044466,0.409367,0.901569,0.256913,-0.348094,0.399222,0.887955,0.459664,0.015677,0.397046,0.604872,0.393584,-0.692258,0.334738,0.721996,0.0507074,-0.690036,0.367169 }; // h64 const int h64_numv = 14; const int h64_numf = 9; const dReal h64_volu = 0.063334; const dReal h64_pos[3] = { -0.862240,-0.589074,0.504780 }; const dReal h64_verts[ h64_numv * 3 ] = { -0.034062,-0.410926,-0.010011, 0.045384,0.217035,0.143840, 0.295955,0.147819,0.066170, 0.251495,0.154150,0.125869, -0.137760,-0.410926,0.116573, -0.137760,0.324258,-0.236366, -0.137760,0.210059,-0.342106, -0.137760,-0.122967,0.363452, -0.137760,-0.410926,-0.022669, 0.298486,0.063123,-0.009534, -0.137760,0.298525,-0.037806, 0.113042,-0.266928,-0.066127, -0.137760,0.119248,0.238856, 0.217652,-0.024891,-0.177862, }; const unsigned int h64_faces[] = { 3, 10,12,1, 4, 12,7,3,1, 5, 3,2,5,10,1, 5, 9,13,6,5,2, 7, 3,7,4,0,11,9,2, 7, 7,12,10,5,6,8,4, 3, 8,0,4, 5, 13,11,0,8,6, 3, 11,13,9, }; const dReal h64_planes[ h64_numf * 4 ] = { -0.163718,0.827886,0.536471,0.249417,0.212159,0.447018,0.869002,0.231645,0.299389,0.946218,0.12263,0.23659,0.619037,0.533581,-0.576268,0.223949,0.679728,-0.477395,0.556833,0.167446,-1,0,0,0.13776,-0,-1,0,0.410926,0.107916,-0.45476,-0.884052,0.192047,0.870583,-0.45858,-0.178295,0.23261 }; // h65 const int h65_numv = 22; const int h65_numf = 13; const dReal h65_volu = 0.115639; const dReal h65_pos[3] = { -0.632833,-0.759826,0.781144 }; const dReal h65_verts[ h65_numv * 3 ] = { -0.367167,-0.022076,0.218856, 0.176779,-0.240174,-0.062777, -0.145261,-0.240174,-0.324854, -0.367167,-0.240174,-0.159791, -0.367167,-0.240174,0.218856, 0.229214,-0.240174,0.218856, -0.367167,0.047785,0.087088, 0.379478,0.318313,-0.027451, 0.258810,0.329890,-0.158933, 0.022088,0.324902,-0.150495, -0.263470,-0.240174,-0.286375, -0.116365,-0.096176,-0.342491, 0.384007,0.200623,0.218856, 0.365257,0.296546,-0.062778, 0.323215,0.382417,-0.038426, 0.362218,0.261157,0.218856, 0.374110,0.331198,-0.022696, 0.069079,0.233875,-0.285898, 0.066548,0.318571,-0.210194, 0.259984,0.356129,-0.135062, 0.334793,0.380563,-0.026448, 0.355611,0.365826,0.016594, }; const unsigned int h65_faces[] = { 5, 13,7,12,5,1, 6, 5,4,3,10,2,1, 6, 2,11,17,8,13,1, 3, 10,11,2, 7, 6,9,18,17,11,10,3, 4, 4,0,6,3, 5, 5,12,15,0,4, 7, 0,15,21,20,14,9,6, 7, 13,8,19,14,20,16,7, 5, 16,21,15,12,7, 4, 17,18,19,8, 4, 14,19,18,9, 3, 20,21,16, }; const dReal h65_planes[ h65_numf * 4 ] = { 0.929286,-0.326334,-0.173016,0.253517,5.14845e-16,-1,8.60294e-16,0.240174,0.616244,-0.216405,-0.75724,0.208451,-0.309078,-0.0542691,-0.949487,0.366376,-0.679728,0.477395,-0.556833,0.223893,-1,0,0,0.367167,-0,0,1,0.218856,-0.324513,0.835692,0.443069,0.19767,0.664689,0.486283,-0.567201,0.422595,0.931229,0.335191,0.143037,0.45615,0.156805,0.660773,-0.734024,0.375226,-0.11569,0.975032,-0.189546,0.34276,0.777249,0.606249,-0.168364,0.495386 }; // h66 const int h66_numv = 12; const int h66_numf = 8; const dReal h66_volu = 0.090843; const dReal h66_pos[3] = { 0.194452,-0.846656,0.702344 }; const dReal h66_verts[ h66_numv * 3 ] = { 0.144722,0.221953,-0.171396, 0.354760,-0.153344,-0.123136, 0.229722,0.177289,-0.118776, -0.077080,-0.093853,-0.442151, -0.263367,-0.153344,0.297656, 0.293204,-0.153344,0.297656, -0.291202,0.163722,0.297656, 0.229722,0.015381,0.297656, -0.072437,-0.153344,-0.456885, -0.246539,0.275009,-0.021290, -0.133324,-0.153344,-0.464317, -0.137311,-0.122439,-0.456854, }; const unsigned int h66_faces[] = { 5, 8,3,0,2,1, 4, 2,7,5,1, 5, 5,4,10,8,1, 5, 0,9,6,7,2, 4, 8,10,11,3, 4, 11,9,0,3, 5, 6,9,11,10,4, 4, 5,7,6,4, }; const dReal h66_planes[ h66_numf * 4 ] = { 0.598205,0.236328,-0.765702,0.270266,0.927293,0.348894,0.13565,0.258762,2.17789e-18,-1,-1.78413e-17,0.153344,0.256529,0.900843,0.350248,0.17704,0.117405,0.247372,-0.961781,0.392986,-0.167754,0.706913,-0.687119,0.250394,-0.982077,-0.0862167,-0.167608,0.221978,0,0,1,0.297657 }; // h67 const int h67_numv = 14; const int h67_numf = 9; const dReal h67_volu = 0.073139; const dReal h67_pos[3] = { -0.182450,-0.819619,0.699488 }; const dReal h67_verts[ h67_numv * 3 ] = { 0.085699,0.136685,0.300512, -0.221169,-0.180381,0.300512, -0.273604,-0.180381,0.018878, 0.130363,0.247972,-0.018435, -0.085126,0.356339,0.018877, 0.113535,-0.180381,0.300512, -0.066376,0.260416,0.300512, -0.060183,0.317865,-0.037452, 0.103953,-0.180381,-0.534183, 0.107696,-0.144260,-0.521085, 0.239592,-0.149476,-0.453999, 0.243578,-0.180381,-0.461462, -0.070905,0.378106,0.054205, -0.032656,0.358692,0.028913, }; const unsigned int h67_faces[] = { 5, 6,12,4,2,1, 5, 2,8,11,5,1, 4, 5,0,6,1, 5, 4,7,9,8,2, 5, 10,9,7,13,3, 5, 13,12,6,0,3, 5, 0,5,11,10,3, 4, 12,13,7,4, 4, 9,10,11,8, }; const dReal h67_planes[ h67_numf * 4 ] = { -0.929286,0.326334,0.173016,0.198658,4.99955e-17,-1,-5.73911e-19,0.180381,0,0,1,0.300512,-0.793214,0.278548,-0.541501,0.156559,0.32928,0.737152,-0.590069,0.236597,0.59399,0.730061,0.337914,0.25224,0.982077,0.0862167,0.167608,0.146316,0.0662371,0.837367,-0.542614,0.282505,0.445543,0.264025,-0.855443,0.455654 }; // h68 const int h68_numv = 24; const int h68_numf = 14; const dReal h68_volu = 0.110178; const dReal h68_pos[3] = { 0.194790,-0.476753,0.823942 }; const dReal h68_verts[ h68_numv * 3 ] = { -0.387371,0.030890,-0.107289, 0.221446,0.021860,-0.353469, -0.465405,-0.021917,0.176058, -0.291540,-0.206181,0.176058, 0.076464,0.334736,-0.007133, 0.229384,-0.354523,0.176058, 0.292644,0.032441,-0.334080, -0.452945,0.146290,0.025179, 0.246219,0.093034,-0.297244, 0.229037,0.025757,-0.352826, 0.107091,0.321655,0.176058, 0.390186,-0.018723,0.176058, 0.312682,0.010704,-0.315910, 0.229384,-0.192615,-0.240374, 0.144384,-0.147950,-0.292995, -0.246877,-0.094895,-0.142888, -0.409896,0.015825,-0.095540, -0.443616,-0.082450,0.176058, -0.462073,0.123559,0.176058, -0.472012,0.082753,-0.026204, -0.453513,0.048124,-0.065494, -0.448145,0.035240,-0.070249, -0.469749,0.118668,0.006167, -0.467116,0.137408,0.055651, }; const unsigned int h68_faces[] = { 5, 14,15,16,0,1, 9, 0,20,19,22,7,4,8,9,1, 6, 9,6,12,13,14,1, 5, 19,20,21,17,2, 7, 17,3,5,11,10,18,2, 5, 18,23,22,19,2, 5, 17,21,16,15,3, 5, 15,14,13,5,3, 6, 10,11,12,6,8,4, 5, 7,23,18,10,4, 4, 13,12,11,5, 3, 9,8,6, 3, 22,23,7, 4, 21,20,0,16, }; const dReal h68_planes[ h68_numf * 4 ] = { -0.372229,-0.156856,-0.91479,0.237492,-0.27553,0.653111,-0.705358,0.202583,0.296224,-0.4369,-0.849335,0.35626,-0.931229,-0.335191,-0.143037,0.415561,-0,0,1,0.176058,-0.998749,0.0228741,0.044466,0.472149,-0.59399,-0.730061,-0.337914,0.264205,-0.256529,-0.900843,-0.350248,0.198862,0.766208,0.637263,-0.0825892,0.272492,-0.326272,0.937436,0.121492,0.287979,0.88947,-0.425933,-0.165603,0.325878,0.16676,0.602337,-0.780629,0.329134,-0.777217,0.601031,-0.186267,0.435271,-0.512456,0.101226,-0.852726,0.293125 }; // h69 const int h69_numv = 18; const int h69_numf = 11; const dReal h69_volu = 0.150904; const dReal h69_pos[3] = { 0.751581,-0.668854,0.749549 }; const dReal h69_verts[ h69_numv * 3 ] = { 0.248419,0.357221,0.250451, -0.263925,-0.331146,0.250451, 0.248419,0.283773,-0.306518, 0.248419,-0.331146,0.009798, 0.000203,0.129153,-0.348181, 0.248419,-0.331146,0.250451, -0.202369,-0.331146,-0.170342, -0.161439,-0.331146,-0.190328, 0.248419,0.424683,-0.270088, -0.087381,0.269445,-0.329471, -0.149648,0.251714,-0.296027, -0.327407,-0.162422,0.250451, -0.166605,0.173379,0.250451, -0.045433,0.301175,-0.321470, -0.327407,-0.000512,-0.165981, -0.244109,0.202806,-0.241517, 0.223596,0.415674,-0.285417, 0.248419,0.419976,-0.283164, }; const unsigned int h69_faces[] = { 4, 11,14,6,1, 5, 6,7,3,5,1, 5, 5,0,12,11,1, 6, 4,9,13,16,17,2, 6, 17,8,0,5,3,2, 4, 3,7,4,2, 7, 7,6,14,15,10,9,4, 3, 17,16,8, 7, 16,13,10,15,12,0,8, 3, 10,13,9, 4, 12,15,14,11, }; const dReal h69_planes[ h69_numf * 4 ] = { -0.927293,-0.348894,-0.13565,0.326296,0,-1,-0,0.331146,8.48822e-17,-4.06468e-17,1,0.250451,0.0600487,0.168696,-0.983837,0.364353,1,-0,0,0.248419,0.398278,-0.419585,-0.815673,0.229892,-0.433652,-0.152285,-0.888119,0.28947,-0.131169,0.932758,-0.335793,0.454236,-0.402198,0.907959,0.117672,0.2539,-0.469026,0.741177,-0.480283,0.39893,-0.88947,0.425933,0.165603,0.263513 }; // h70 const int h70_numv = 8; const int h70_numf = 6; const dReal h70_volu = 0.052841; const dReal h70_pos[3] = { 0.870032,-0.820199,0.384721 }; const dReal h70_verts[ h70_numv * 3 ] = { 0.129968,-0.179801,0.374626, 0.129968,-0.179801,-0.351943, -0.279890,-0.179801,0.174500, 0.129968,0.435118,0.058310, -0.112815,-0.179801,-0.233397, -0.118249,0.280498,0.016648, 0.129968,-0.066134,-0.371433, -0.064784,-0.043027,-0.280302, }; const unsigned int h70_faces[] = { 4, 4,7,6,1, 4, 6,3,0,1, 4, 0,2,4,1, 4, 5,7,4,2, 4, 0,3,5,2, 4, 6,7,5,3, }; const dReal h70_planes[ h70_numf * 4 ] = { -0.433652,-0.152285,-0.888119,0.283587,1,0,0,0.129968,0,-1,0,0.179801,-0.908278,0.191373,-0.372031,0.154889,-0.398278,0.419585,0.815673,0.178367,-0.267862,0.627092,-0.731441,0.195395 }; // h71 const int h71_numv = 16; const int h71_numf = 10; const dReal h71_volu = 0.078575; const dReal h71_pos[3] = { -0.715618,-0.146967,0.614144 }; const dReal h71_verts[ h71_numv * 3 ] = { -0.284382,-0.099249,-0.355298, 0.407938,-0.228507,0.130744, -0.284382,-0.117849,-0.345730, 0.406000,-0.230442,0.128574, 0.033539,0.110754,0.371749, 0.104873,-0.287957,0.016505, -0.197952,0.422046,0.249299, -0.284382,0.237452,0.048837, -0.101238,-0.225072,0.034476, -0.284382,-0.143582,-0.147170, 0.149333,-0.294288,-0.043194, 0.409649,-0.225257,0.134087, 0.147525,0.085239,-0.239307, 0.183419,0.150542,-0.169689, 0.342769,-0.256730,0.031938, 0.344779,-0.242424,0.025560, }; const unsigned int h71_faces[] = { 4, 3,14,15,1, 5, 15,12,13,11,1, 6, 11,4,8,5,3,1, 6, 0,12,15,14,10,2, 5, 10,5,8,9,2, 4, 9,7,0,2, 4, 5,10,14,3, 4, 11,13,6,4, 5, 6,7,9,8,4, 5, 13,12,0,7,6, }; const dReal h71_planes[ h71_numf * 4 ] = { 0.830322,-0.320028,-0.456232,0.352199,0.848621,0.0894025,-0.521393,0.257586,-0.141863,-0.672536,0.72634,0.190772,0.398278,-0.419585,-0.815673,0.218187,-0.299389,-0.946218,-0.12263,0.239048,-1,-0,0,0.284382,0.11569,-0.975032,0.189546,0.296029,0.727925,0.639055,0.248465,0.187558,-0.735479,-0.309932,0.602505,0.164988,-0.1544,0.759081,-0.632422,0.193269 }; // h72 const int h72_numv = 24; const int h72_numf = 14; const dReal h72_volu = 0.135103; const dReal h72_pos[3] = { -0.469590,0.119774,0.755853 }; const dReal h72_verts[ h72_numv * 3 ] = { -0.212489,-0.155987,0.230040, -0.214701,-0.148769,0.244147, -0.443980,0.155306,0.107590, 0.375305,0.040715,-0.139275, -0.004437,0.090870,-0.389509, 0.311360,0.156806,0.046426, -0.480672,0.247962,0.244147, -0.005314,0.363706,-0.137567, 0.163621,-0.491997,-0.007622, 0.213688,0.055724,0.244147, -0.495580,0.247143,0.161130, -0.499540,0.269230,0.219387, 0.144703,0.290282,-0.088352, 0.355676,0.140088,-0.062598, -0.062609,-0.116199,-0.311398, -0.088334,0.254773,-0.303291, 0.356369,0.017480,-0.175583, 0.155877,-0.383277,0.244147, 0.169264,-0.493727,-0.003158, 0.197264,-0.459118,0.123740, 0.194631,-0.477857,0.074256, 0.211435,-0.450236,0.093267, 0.167388,-0.493339,-0.005093, 0.169626,-0.492143,-0.004615, }; const unsigned int h72_faces[] = { 8, 0,8,22,18,20,19,17,1, 4, 17,9,6,1, 6, 6,11,10,2,0,1, 5, 10,15,4,14,2, 4, 14,8,0,2, 7, 16,4,15,7,12,13,3, 7, 13,5,9,17,19,21,3, 6, 21,20,18,23,16,3, 6, 16,23,22,8,14,4, 3, 13,12,5, 6, 12,7,11,6,9,5, 4, 15,10,11,7, 3, 22,23,18, 3, 20,21,19, }; const dReal h72_planes[ h72_numf * 4 ] = { -0.50496,-0.797961,0.32905,0.307465,0,0,1,0.244147,-0.820856,-0.550308,0.152828,0.29542,-0.751031,-0.0376746,-0.659191,0.256669,-0.727925,-0.639055,-0.248465,0.197203,0.49733,0.589429,-0.636582,0.299309,0.913105,-0.120244,0.389591,0.283536,0.892822,-0.397939,-0.210981,0.348263,0.398278,-0.419584,-0.815674,0.277818,0.568103,0.816132,0.105771,0.30977,0.226312,0.817437,0.529699,0.223235,-0.411928,0.842404,-0.347377,0.356365,0.474458,-0.651966,-0.591464,0.404071,0.777217,-0.601031,0.186267,0.452309 }; // h73 const int h73_numv = 16; const int h73_numf = 10; const dReal h73_volu = 0.036032; const dReal h73_pos[3] = { -0.912743,-0.085439,0.831075 }; const dReal h73_verts[ h73_numv * 3 ] = { 0.095887,-0.286600,-0.182455, -0.087257,0.175924,-0.168094, -0.087257,-0.205110,-0.364101, 0.230664,0.049226,0.154818, -0.037519,0.453174,0.168925, 0.228452,0.056443,0.168925, -0.087257,0.484247,0.168925, -0.000826,0.360518,0.032367, -0.087257,-0.218262,0.168925, -0.087257,-0.384387,-0.087440, -0.087257,0.485343,0.150329, -0.064760,0.476158,0.168925, -0.052427,0.452355,0.085908, -0.087257,0.457669,0.073457, -0.056387,0.474442,0.144165, -0.056885,0.474757,0.144652, }; const unsigned int h73_faces[] = { 4, 13,12,7,1, 5, 7,3,0,2,1, 7, 2,9,8,6,10,13,1, 3, 0,9,2, 5, 5,8,9,0,3, 6, 7,12,14,4,5,3, 4, 14,15,11,4, 5, 11,6,8,5,4, 4, 11,15,10,6, 5, 15,14,12,13,10, }; const dReal h73_planes[ h73_numf * 4 ] = { 0.347582,0.610296,-0.711847,0.196695,0.735479,0.309932,-0.602505,0.091627,-1,0,0,0.0872566,0.163718,-0.827886,-0.536471,0.350852,0.589724,-0.677749,0.439183,0.170659,0.820856,0.550308,-0.152828,0.192771,0.636259,0.754085,0.162882,0.345375,3.43778e-17,-3.95092e-17,1,0.168925,0.337828,0.939579,0.0553497,0.434861,0.255819,0.909579,-0.327448,0.369911 }; // h74 const int h74_numv = 22; const int h74_numf = 13; const dReal h74_volu = 0.115647; const dReal h74_pos[3] = { -0.806688,0.162223,0.365754 }; const dReal h74_verts[ h74_numv * 3 ] = { -0.106882,0.112856,0.497689, -0.158482,0.204693,0.551229, 0.218764,0.243174,-0.153679, 0.270615,-0.014193,-0.214570, -0.193312,-0.071737,0.297227, 0.312298,0.070592,-0.150604, -0.069795,-0.227826,-0.358730, 0.248765,0.212323,0.086808, -0.193312,-0.408439,-0.106908, -0.193312,0.210007,0.538778, 0.301657,0.087464,-0.177940, -0.191931,0.033024,-0.314003, -0.193312,0.271426,0.001678, 0.058968,0.264774,-0.186519, -0.193312,0.247719,-0.120270, 0.052425,0.263623,-0.188445, 0.332661,0.048420,0.000590, 0.274489,-0.158648,0.078702, 0.238595,-0.223951,0.009084, 0.229318,-0.111676,-0.252511, -0.193312,-0.302733,-0.342536, -0.193312,0.032765,-0.313772, }; const unsigned int h74_faces[] = { 6, 7,2,13,12,9,1, 4, 9,4,0,1, 5, 0,17,16,7,1, 5, 7,16,5,10,2, 8, 10,3,19,6,11,15,13,2, 6, 5,16,17,18,19,3, 3, 10,5,3, 7, 9,12,14,21,20,8,4, 5, 8,18,17,0,4, 4, 20,21,11,6, 5, 19,18,8,20,6, 4, 21,14,15,11, 4, 13,15,14,12, }; const dReal h74_planes[ h74_numf * 4 ] = { 0.110273,0.987466,0.11292,0.246896,-0.347582,-0.610296,0.711847,0.322553,0.751031,0.0376746,0.659191,0.252053,0.878502,0.475257,-0.0486263,0.315228,0.228531,0.267508,-0.936063,0.258898,0.929286,-0.326334,-0.173016,0.293234,0.897445,-0.121213,-0.424146,0.335592,-1,0,0,0.193312,0.1544,-0.759081,0.632422,0.21258,-0.179474,0.0840327,-0.980167,0.344997,0.446963,-0.816184,-0.366152,0.286102,-0.242073,0.64915,-0.721114,0.29433,-0.11569,0.975032,-0.189546,0.286695 }; // h75 const int h75_numv = 18; const int h75_numf = 11; const dReal h75_volu = 0.089620; const dReal h75_pos[3] = { 0.052817,0.072055,0.868740 }; const dReal h75_verts[ h75_numv * 3 ] = { 0.433734,0.123433,0.131260, 0.005775,0.176863,-0.278988, 0.218437,-0.214071,-0.051932, -0.366530,-0.335558,0.131260, -0.308719,0.103443,0.131260, -0.147102,0.088434,-0.252162, -0.310972,-0.402518,-0.019619, -0.003079,0.231496,-0.237914, 0.112171,0.347564,-0.006639, 0.302595,-0.019353,-0.141822, 0.235603,0.353295,0.131260, 0.077918,0.377107,0.131260, 0.249063,-0.227153,0.131260, -0.166731,0.187806,-0.175486, -0.093909,0.310921,0.131260, -0.211047,0.204525,-0.066461, -0.325143,-0.411399,0.010853, -0.320100,-0.425249,0.131260, }; const unsigned int h75_faces[] = { 6, 7,8,10,0,9,1, 5, 9,2,6,5,1, 4, 5,13,7,1, 5, 12,17,16,6,2, 4, 9,0,12,2, 3, 16,17,3, 8, 17,12,0,10,11,14,4,3, 7, 4,15,13,5,6,16,3, 3, 14,15,4, 6, 13,15,14,11,8,7, 3, 11,10,8, }; const dReal h75_planes[ h75_numf * 4 ] = { 0.619037,0.533582,-0.576267,0.258718,0.107917,-0.454758,-0.884053,0.166834,-0.421977,0.500122,-0.756183,0.296982,0.326272,-0.937436,-0.121492,0.278257,0.870584,-0.458578,-0.178296,0.297595,-0.887955,-0.459664,-0.015677,0.477648,0,0,1,0.13126,-0.913105,0.120244,-0.389591,0.243193,-0.694517,0.719058,0.0245236,0.292011,-0.345296,0.896431,-0.277815,0.27468,0.14709,0.974029,-0.172138,0.356179 }; // h76 const int h76_numv = 24; const int h76_numf = 14; const dReal h76_volu = 0.095138; const dReal h76_pos[3] = { 0.088788,-0.142804,0.576459 }; const dReal h76_verts[ h76_numv * 3 ] = { 0.352221,-0.240915,-0.049761, -0.386828,-0.236459,0.178237, 0.182466,0.000788,0.240349, -0.006268,0.044860,-0.340368, 0.298110,0.182836,0.102163, -0.389114,-0.231150,0.176236, -0.030195,0.391722,0.013292, -0.363747,-0.215280,0.253650, -0.388752,-0.229565,0.174779, -0.101327,0.289860,-0.170144, 0.328315,-0.307617,-0.113256, -0.079254,0.048914,-0.283309, 0.094387,-0.120263,-0.302438, -0.281369,-0.303059,0.140194, 0.335039,-0.308192,-0.105343, 0.327448,-0.312089,-0.105986, 0.022142,0.379302,-0.133650, -0.346943,-0.187659,0.272661, -0.202009,0.280058,0.003811, -0.183073,0.303293,0.040119, 0.266624,0.195506,0.150459, -0.022476,0.325632,-0.215723, -0.347511,-0.285824,0.181989, -0.366010,-0.251196,0.221279, }; const unsigned int h76_faces[] = { 3, 22,23,1, 4, 23,7,5,1, 8, 5,8,11,3,12,13,22,1, 9, 17,7,23,22,13,15,14,0,2, 4, 0,4,20,2, 5, 20,6,19,17,2, 4, 11,9,21,3, 8, 21,16,4,0,14,10,12,3, 4, 16,6,20,4, 6, 7,17,19,18,8,5, 6, 16,21,9,18,19,6, 4, 18,9,11,8, 3, 14,15,10, 4, 15,13,12,10, }; const dReal h76_planes[ h76_numf * 4 ] = { -0.777249,-0.606249,0.168364,0.474024,-0.901569,-0.256913,0.348094,0.471545,-0.553104,-0.49165,-0.672575,0.210334,0.27553,-0.653111,0.705358,0.219292,0.822068,-0.096228,0.561199,0.284807,-0.107917,0.454758,0.884053,0.193148,-0.576312,0.303571,-0.758755,0.275486,0.73548,0.309929,-0.602505,0.214367,0.512085,0.851811,0.110395,0.319678,-0.892822,0.397939,0.210981,0.292608,-0.517294,0.817451,-0.253339,0.332466,-0.859244,0.150868,-0.488814,0.213964,0.440632,-0.78713,-0.431589,0.435681,-0.226312,-0.817437,-0.529699,0.237148 }; // h77 const int h77_numv = 26; const int h77_numf = 15; const dReal h77_volu = 0.087804; const dReal h77_pos[3] = { 0.390778,-0.073451,0.362494 }; const dReal h77_verts[ h77_numv * 3 ] = { -0.003880,0.113483,0.316128, 0.315369,-0.294228,0.065585, -0.206158,-0.189928,-0.093832, 0.020979,0.268088,0.071472, -0.324466,0.256279,-0.001758, -0.230465,0.381445,-0.183441, 0.426887,-0.187811,0.054869, 0.211155,-0.343689,0.091028, -0.224735,0.155039,-0.266749, 0.077733,0.119939,0.286241, 0.026325,-0.376970,0.100709, -0.297695,-0.031084,-0.153195, 0.009520,-0.343472,-0.067504, 0.155269,-0.307156,-0.121769, -0.207604,-0.189616,-0.088472, -0.308258,-0.024493,-0.126403, 0.050231,-0.310268,0.164204, 0.176117,-0.273019,-0.144419, 0.417855,-0.153875,-0.005953, 0.273422,-0.325958,0.057585, 0.096656,-0.370860,0.127368, 0.033049,-0.377545,0.108622, -0.214357,0.369295,-0.224944, 0.141437,0.190499,-0.081874, -0.279848,0.309949,0.080316, -0.221943,0.387815,-0.053985, }; const unsigned int h77_faces[] = { 6, 19,13,17,18,6,1, 7, 6,9,0,16,20,7,1, 3, 7,19,1, 4, 14,15,11,2, 6, 11,8,17,13,12,2, 4, 12,10,14,2, 5, 25,24,0,9,3, 5, 9,6,18,23,3, 5, 23,22,5,25,3, 4, 24,25,5,4, 6, 5,22,8,11,15,4, 8, 15,14,10,21,16,0,24,4, 7, 20,21,10,12,13,19,7, 5, 22,23,18,17,8, 3, 21,20,16, }; const dReal h77_planes[ h77_numf * 4 ] = { 0.590109,-0.664552,-0.458413,0.351567,0.349687,-0.276295,0.895198,0.250286,0.469026,-0.741177,0.480283,0.397491,-0.818514,-0.542417,-0.189261,0.289522,-0.212159,-0.447018,-0.869002,0.21018,-0.568104,-0.816131,-0.105771,0.28205,0.131611,0.83191,0.539077,0.264315,0.727924,0.639056,0.248465,0.204352,0.471464,0.878752,-0.0742736,0.240165,-0.784459,0.61982,0.0211391,0.41334,-0.913105,0.120244,-0.389591,0.327772,-0.73548,-0.309929,0.602505,0.158151,0.162747,-0.964426,-0.208316,0.346865,0.433652,0.152285,-0.888119,0.163058,-0.16676,-0.602337,0.780629,0.306692 }; // h78 const int h78_numv = 20; const int h78_numf = 12; const dReal h78_volu = 0.126407; const dReal h78_pos[3] = { 0.652845,-0.171711,0.785711 }; const dReal h78_verts[ h78_numv * 3 ] = { -0.350965,0.016612,0.214289, 0.347155,-0.072460,-0.306250, -0.381591,0.029695,0.031097, 0.347155,-0.139922,0.214289, 0.322332,-0.081469,-0.321579, -0.265947,0.211743,-0.107089, -0.020631,0.312250,-0.000249, 0.347155,0.151286,0.214289, 0.347155,-0.036860,-0.269624, -0.184333,0.218199,-0.136976, -0.297433,0.224413,-0.058793, -0.211836,-0.212008,-0.259013, -0.050911,-0.245429,-0.332189, -0.067869,-0.323764,0.214289, -0.166294,0.367199,0.214289, -0.026282,0.399418,0.214289, -0.145373,-0.294337,-0.277679, -0.165410,-0.272600,-0.295849, 0.053302,-0.195968,-0.357632, 0.164820,-0.089551,-0.368349, }; const unsigned int h78_faces[] = { 7, 3,13,16,12,18,4,1, 6, 4,19,9,6,8,1, 4, 8,7,3,1, 6, 11,17,16,13,0,2, 4, 0,14,10,2, 4, 10,5,11,2, 6, 7,15,14,0,13,3, 3, 18,19,4, 6, 10,14,15,6,9,5, 7, 9,19,18,12,17,11,5, 4, 15,7,8,6, 3, 16,17,12, }; const dReal h78_planes[ h78_numf * 4 ] = { 0.402198,-0.907959,-0.117672,0.241453,0.167754,0.706913,-0.687119,0.217444,1,-0,0,0.347155,-0.766208,-0.637263,0.0825892,0.276023,-0.870584,0.458578,0.178296,0.351369,-0.822068,0.096228,-0.561199,0.2991,0,-0,1,0.214289,0.280943,-0.383024,-0.879979,0.404745,-0.20808,0.904248,-0.372879,0.286737,-0.349687,0.276295,-0.895198,0.247367,0.526505,0.792388,-0.308081,0.236638,-0.071473,-0.677671,-0.731884,0.413083 }; // h79 const int h79_numv = 20; const int h79_numf = 12; const dReal h79_volu = 0.069132; const dReal h79_pos[3] = { 0.747670,0.086302,0.441993 }; const dReal h79_verts[ h79_numv * 3 ] = { 0.252330,0.012519,-0.215098, 0.012566,0.066820,-0.263433, 0.201221,-0.224177,-0.182831, 0.095169,0.321961,-0.051360, -0.091840,0.355257,0.097036, -0.215455,0.030746,-0.161373, -0.279159,-0.039814,0.206742, 0.060963,-0.313628,-0.085453, -0.115456,0.054238,0.343469, 0.252330,-0.294873,0.074094, -0.016233,0.366022,0.061965, -0.074702,0.310522,0.161887, 0.252330,0.103519,-0.130839, 0.252330,-0.216744,-0.175787, -0.335913,0.108335,-0.008027, 0.079494,0.109929,-0.259932, 0.069995,-0.347564,-0.024631, 0.252330,-0.330473,0.037468, 0.252330,-0.335180,0.024392, 0.227507,-0.339482,0.022139, }; const unsigned int h79_faces[] = { 7, 5,14,4,10,3,15,1, 5, 15,0,13,2,1, 4, 2,7,5,1, 6, 13,18,19,16,7,2, 6, 10,11,8,9,12,3, 4, 12,0,15,3, 5, 14,6,8,11,4, 3, 11,10,4, 5, 7,16,6,14,5, 6, 16,19,17,9,8,6, 6, 17,18,13,0,12,9, 3, 19,18,17, }; const dReal h79_planes[ h79_numf * 4 ] = { -0.391463,0.659847,-0.641373,0.208131,0.158394,-0.166869,-0.973173,0.247207,-0.309646,-0.434949,-0.84554,0.189789,0.191731,-0.844679,-0.499756,0.319309,0.73548,0.309929,0.602505,0.138836,0.49733,0.589428,-0.636583,0.269798,-0.708232,0.479648,0.518021,0.285709,0.131611,0.831909,0.539078,0.335765,-0.727924,-0.639056,-0.248465,0.177281,-0.167754,-0.706913,0.687119,0.217031,1,0,0,0.25233,0.131169,-0.932758,0.335793,0.35393 }; // h80 const int h80_numv = 14; const int h80_numf = 9; const dReal h80_volu = 0.076324; const dReal h80_pos[3] = { 0.872729,0.237609,0.718600 }; const dReal h80_verts[ h80_numv * 3 ] = { 0.127271,0.331095,-0.032200, 0.127271,-0.258034,0.281400, 0.127271,-0.446180,-0.202512, -0.199761,0.159215,-0.114719, -0.141292,0.214715,-0.214641, -0.136492,0.218429,-0.218946, -0.240515,-0.097070,0.066863, -0.246166,-0.009903,0.281400, -0.239577,0.050556,0.281400, 0.127271,0.263358,0.281400, 0.127271,0.246274,-0.293996, 0.127271,-0.047788,-0.407445, -0.039983,0.206584,-0.314412, -0.029889,0.170654,-0.327966, }; const unsigned int h80_faces[] = { 4, 7,6,2,1, 6, 2,11,10,0,9,1, 4, 9,8,7,1, 6, 6,3,4,13,11,2, 6, 8,9,0,5,4,3, 4, 6,7,8,3, 4, 5,12,13,4, 4, 0,10,12,5, 4, 11,13,12,10, }; const dReal h80_planes[ h80_numf * 4 ] = { -0.526505,-0.792388,0.308081,0.224148,1,0,0,0.127271,0,0,1,0.281401,-0.73548,-0.309929,-0.602505,0.166694,-0.493234,0.850287,0.183662,0.212838,-0.991673,0.108076,-0.0700326,0.223339,-0.696788,0.0734069,-0.713511,0.267361,-0.184883,0.934913,-0.302912,0.295769,0.0284606,0.359798,-0.932596,0.36641 }; // h81 const int h81_numv = 10; const int h81_numf = 7; const dReal h81_volu = 0.092471; const dReal h81_pos[3] = { -0.647649,0.823554,0.820209 }; const dReal h81_verts[ h81_numv * 3 ] = { 0.457657,0.176446,0.179791, -0.352351,-0.423650,0.161195, -0.352351,0.176446,-0.147497, -0.352351,-0.424746,0.179791, -0.352351,0.176446,0.179791, 0.395926,0.059255,0.179791, 0.203225,-0.169390,-0.173056, 0.338792,0.176446,-0.400601, -0.321979,-0.434236,0.155518, -0.329854,-0.432835,0.179791, }; const unsigned int h81_faces[] = { 4, 8,9,3,1, 4, 3,4,2,1, 5, 2,7,6,8,1, 4, 4,0,7,2, 5, 9,5,0,4,3, 4, 6,7,0,5, 4, 9,8,6,5, }; const dReal h81_planes[ h81_numf * 4 ] = { -0.337828,-0.939579,-0.0553497,0.508165,-1,-9.23352e-17,0,0.352351,-0.309646,-0.434949,-0.84554,0.157073,0,1,-0,0.176446,-0,0,1,0.179791,0.870584,-0.458578,-0.178296,0.285458,0.546922,-0.806654,0.224019,0.209019 }; // h82 const int h82_numv = 22; const int h82_numf = 13; const dReal h82_volu = 0.133984; const dReal h82_pos[3] = { -0.704013,0.655334,0.510913 }; const dReal h82_verts[ h82_numv * 3 ] = { -0.295987,0.344666,0.147853, 0.143982,-0.175036,-0.341668, -0.295987,-0.255430,0.470491, 0.398940,0.268255,-0.112413, -0.265615,-0.266016,0.464814, -0.043708,-0.228337,-0.331678, 0.395156,0.344666,-0.091306, 0.146090,-0.280788,-0.058352, 0.259589,-0.001170,0.136240, -0.295987,0.344666,0.161799, 0.268488,-0.087750,0.102566, -0.295987,-0.221685,-0.143481, -0.265117,-0.266331,0.464327, 0.229109,-0.171854,0.107373, -0.295987,-0.283104,0.393619, -0.261157,-0.288418,0.406070, 0.116089,-0.249937,-0.298838, 0.396013,0.344666,-0.093117, 0.248792,0.064649,-0.395197, 0.275014,0.344666,-0.270360, 0.114098,-0.109185,-0.385965, 0.213954,-0.004245,-0.405120, }; const unsigned int h82_faces[] = { 4, 16,5,20,1, 3, 20,21,1, 8, 21,18,3,10,13,7,16,1, 5, 14,15,12,4,2, 5, 4,8,6,9,2, 5, 9,0,11,14,2, 4, 18,19,17,3, 5, 17,6,8,10,3, 5, 12,13,10,8,4, 6, 16,7,15,14,11,5, 7, 11,0,19,18,21,20,5, 5, 17,19,0,9,6, 4, 13,12,15,7, }; const dReal h82_planes[ h82_numf * 4 ] = { 0.103318,-0.522457,-0.846383,0.395508,0.296224,-0.4369,-0.849335,0.409315,0.88947,-0.425933,-0.165603,0.259202,-0.255819,-0.909579,0.327448,0.462115,0.309646,0.434949,0.84554,0.195068,-1,0,0,0.295987,0.813673,0.17144,-0.555468,0.433038,0.901694,-0.0730707,0.426155,0.292215,0.598205,-0.236328,0.765702,0.259883,-0.110273,-0.987466,-0.11292,0.267748,-0.545755,0.383303,-0.745138,0.183477,-9.72172e-17,1,0,0.344666,0.411928,-0.842404,0.347377,0.276446 }; // h83 const int h83_numv = 12; const int h83_numf = 8; const dReal h83_volu = 0.056796; const dReal h83_pos[3] = { -0.429347,0.488254,0.882979 }; const dReal h83_verts[ h83_numv * 3 ] = { -0.006178,0.079330,-0.269501, -0.548156,-0.097535,0.117020, -0.015077,0.165910,-0.235826, -0.540281,-0.098936,0.092747, 0.104460,-0.078198,-0.215479, 0.388255,-0.105278,0.117020, 0.173445,-0.312756,0.117020, 0.177624,0.394555,0.117020, -0.045557,-0.004774,-0.264694, 0.271117,-0.211674,-0.080700, -0.539783,-0.099251,0.092261, -0.520915,-0.120519,0.117020, }; const unsigned int h83_faces[] = { 4, 3,10,11,1, 5, 11,6,5,7,1, 4, 7,2,3,1, 6, 7,5,9,4,0,2, 5, 0,8,10,3,2, 6, 9,6,11,10,8,4, 3, 8,0,4, 3, 6,9,5, }; const dReal h83_planes[ h83_numf * 4 ] = { -0.636259,-0.754085,-0.162882,0.403258,0,0,1,0.117021,-0.546922,0.806654,-0.224019,0.194907,0.735479,0.309932,-0.602505,0.182419,-0.598205,0.236328,-0.765702,0.228801,-0.226312,-0.817437,-0.529699,0.15442,0.233951,-0.164311,-0.958264,0.243773,0.694517,-0.719058,-0.0245236,0.342481 }; // h84 const int h84_numv = 22; const int h84_numf = 13; const dReal h84_volu = 0.109330; const dReal h84_pos[3] = { -0.121674,0.670783,0.713170 }; const dReal h84_verts[ h84_numv * 3 ] = { -0.313851,-0.103198,-0.099691, -0.010109,0.329217,0.286830, 0.252410,-0.221620,0.286830, -0.068318,0.329217,0.286830, 0.080582,-0.287807,0.286830, 0.201978,0.032805,-0.295587, -0.187183,0.329217,-0.293562, 0.227672,0.006891,-0.288529, -0.130049,0.212026,0.286830, -0.322750,-0.016619,-0.066017, -0.036556,-0.394202,0.089109, 0.171412,-0.367231,-0.082344, -0.203213,-0.260726,-0.045669, 0.007760,-0.410921,-0.019916, 0.265234,-0.083360,-0.251274, 0.286662,-0.251163,0.148930, -0.115141,0.329217,-0.286684, -0.066013,0.197094,-0.314670, -0.183399,0.252807,-0.314670, -0.186326,0.329217,-0.295374, 0.060573,0.329217,-0.240926, 0.066345,0.329217,-0.235802, }; const unsigned int h84_faces[] = { 6, 2,15,14,7,21,1, 7, 21,20,16,19,6,3,1, 5, 3,8,4,2,1, 6, 4,10,13,11,15,2, 4, 6,9,8,3, 6, 8,9,0,12,10,4, 4, 20,21,7,5, 9, 7,14,11,13,12,0,18,17,5, 4, 17,16,20,5, 5, 19,18,0,9,6, 3, 12,13,10, 3, 14,15,11, 4, 17,18,19,16, }; const dReal h84_planes[ h84_numf * 4 ] = { 0.894954,0.426518,0.130919,0.168922,0,1,0,0.329217,0,0,1,0.28683,0.345296,-0.896431,0.277815,0.365509,-0.870584,0.458578,0.178296,0.261589,-0.735479,-0.309932,0.602505,0.202751,0.604377,0.413861,-0.68077,0.336874,-0.212159,-0.447018,-0.869002,0.19935,0.241471,0.286187,-0.927248,0.332242,-0.901694,0.0730707,-0.426155,0.317941,-0.568103,-0.816132,-0.105771,0.333064,0.877503,-0.423705,-0.224641,0.32451,0.117405,0.247371,-0.961782,0.343649 }; // h85 const int h85_numv = 36; const int h85_numf = 20; const dReal h85_volu = 0.148789; const dReal h85_pos[3] = { -0.198763,0.456116,0.345386 }; const dReal h85_verts[ h85_numv * 3 ] = { 0.248501,-0.152565,0.285440, 0.011075,0.411760,0.053114, 0.304761,0.221558,0.079254, 0.360475,-0.080906,-0.269891, -0.389161,-0.050719,-0.133311, 0.279067,0.247472,0.072197, 0.342323,0.131307,0.116509, -0.236762,0.111468,0.268093, 0.084849,-0.196255,0.347868, 0.186224,-0.309060,0.060929, -0.295627,-0.223301,-0.130236, 0.016686,0.009351,-0.358147, 0.315157,-0.069303,-0.293328, -0.106311,0.467473,0.053114, 0.257356,-0.207198,0.244366, 0.367598,-0.141752,-0.036878, 0.104478,-0.295627,0.271192, -0.126124,-0.046060,0.322115, -0.256458,0.263868,-0.229670, 0.085542,-0.318862,0.234884, -0.291296,0.194974,-0.239593, -0.265275,0.238760,-0.259807, -0.361268,0.024182,-0.176141, -0.291163,-0.195420,-0.172718, -0.276141,0.027364,0.272900, -0.306268,-0.206429,-0.157572, -0.275264,-0.245473,0.020958, -0.359160,-0.081570,0.107176, 0.360630,0.159839,0.075257, 0.387070,0.106509,-0.013499, 0.393155,0.083405,-0.037268, 0.359076,-0.148122,-0.166333, 0.309693,-0.219618,0.097423, 0.265075,-0.273288,0.015350, 0.118262,-0.041268,-0.360627, 0.049809,-0.043705,-0.365222, }; const unsigned int h85_faces[] = { 7, 12,34,11,21,18,13,1, 9, 13,7,17,8,0,6,2,5,1, 6, 5,29,30,3,12,1, 4, 28,29,5,2, 3, 6,28,2, 4, 30,15,31,3, 10, 31,33,9,10,25,23,35,34,12,3, 5, 25,10,26,27,4, 8, 27,24,7,13,18,20,22,4, 4, 22,23,25,4, 8, 0,14,32,15,30,29,28,6, 3, 24,17,7, 7, 17,24,27,26,19,16,8, 4, 16,14,0,8, 4, 19,26,10,9, 6, 33,32,14,16,19,9, 3, 34,35,11, 6, 35,23,22,20,21,11, 4, 32,33,31,15, 3, 21,20,18, }; const dReal h85_planes[ h85_numf * 4 ] = { 0.322183,0.678838,-0.659831,0.24804,0.212159,0.447018,0.869002,0.23257,0.463507,0.691764,-0.553737,0.260563,0.722579,0.66608,-0.18498,0.353129,0.602768,0.50566,0.617235,0.344652,0.991833,-0.112685,-0.0597434,0.382771,0.066237,-0.837367,-0.542613,0.238071,-0.878502,-0.475257,0.0486263,0.359502,-0.88947,0.425933,0.165603,0.302468,-0.613049,-0.207593,-0.762283,0.350725,0.933932,-0.105417,0.341552,0.345658,-0.233951,0.164311,0.958264,0.33061,-0.49733,-0.589429,0.636582,0.294927,0.421977,-0.500122,0.756183,0.397007,-0.124536,-0.983986,-0.127525,0.273149,0.517294,-0.817451,0.253339,0.364409,0.0600487,0.168696,-0.983837,0.354938,-0.433652,-0.152285,-0.888119,0.309417,0.784459,-0.61982,-0.0211391,0.377005,-0.877441,0.462191,-0.128357,0.376465 }; // h86 const int h86_numv = 14; const int h86_numf = 9; const dReal h86_volu = 0.108919; const dReal h86_pos[3] = { 0.238541,0.789776,0.775739 }; const dReal h86_verts[ h86_numv * 3 ] = { -0.094981,-0.202353,-0.313843, -0.370325,0.210224,0.224261, -0.076674,-0.173821,-0.355096, 0.281969,0.210224,-0.157785, 0.225385,0.024918,-0.224556, 0.374020,0.210224,0.224261, 0.316487,0.210224,-0.084750, -0.107806,-0.340614,0.224261, 0.201351,-0.281476,0.224261, 0.184090,-0.072562,-0.262496, -0.073553,-0.370157,0.086361, 0.049879,-0.364426,0.224261, -0.132543,-0.112102,-0.351098, -0.293871,0.210224,-0.298371, }; const unsigned int h86_faces[] = { 6, 13,12,0,10,7,1, 5, 7,11,8,5,1, 5, 5,6,3,13,1, 6, 12,13,3,4,9,2, 6, 9,8,11,10,0,2, 3, 0,12,2, 3, 6,4,3, 5, 6,5,8,9,4, 3, 10,11,7, }; const dReal h86_planes[ h86_numf * 4 ] = { -0.894954,-0.426518,-0.130919,0.212399,0,0,1,0.224261,0,1,0,0.210224,0.228531,0.267508,-0.936063,0.268372,0.446964,-0.816183,-0.366153,0.237618,-0.602768,-0.50566,-0.617235,0.353289,0.897445,-0.121212,-0.424146,0.294495,0.929286,-0.326334,-0.173016,0.240167,-0.14709,-0.974029,0.172138,0.386228 }; // h87 const int h87_numv = 16; const int h87_numf = 10; const dReal h87_volu = 0.089360; const dReal h87_pos[3] = { 0.798384,0.791714,0.481127 }; const dReal h87_verts[ h87_numv * 3 ] = { -0.277873,0.208286,0.136827, -0.253373,-0.199539,-0.004817, 0.201616,0.208286,-0.307196, 0.201616,0.189080,-0.312136, 0.201616,-0.223010,0.205272, 0.201616,0.208286,0.427133, 0.201616,-0.307831,-0.056523, -0.352696,-0.089547,0.003266, -0.060134,0.085556,-0.322787, -0.013117,0.208286,-0.294090, -0.336822,-0.121565,-0.050021, -0.196695,-0.100782,-0.260274, -0.062147,-0.335676,0.018525, 0.034362,-0.347521,-0.076940, -0.334458,0.022980,0.070056, -0.243356,0.208286,0.209862, }; const unsigned int h87_faces[] = { 5, 10,11,13,12,1, 7, 12,4,5,15,14,7,1, 3, 7,10,1, 4, 3,8,9,2, 5, 9,0,15,5,2, 5, 5,4,6,3,2, 5, 6,13,11,8,3, 4, 12,13,6,4, 7, 14,0,9,8,11,10,7, 3, 15,0,14, }; const dReal h87_planes[ h87_numf * 4 ] = { -0.496382,-0.766976,-0.406636,0.28077,-0.398278,-0.419587,0.815673,0.180707,-0.722578,-0.66608,0.18498,0.3151,-0.0590083,0.248661,-0.966792,0.336891,0,1,0,0.208286,1,1.89246e-16,1.50725e-16,0.201616,0.212159,-0.447018,-0.869002,0.229499,0.184883,-0.934913,0.302912,0.307949,-0.777334,0.409459,-0.477594,0.235937,-0.897445,0.121212,0.424146,0.332657 }; // h88 const int h88_numv = 26; const int h88_numf = 15; const dReal h88_volu = 0.102785; const dReal h88_pos[3] = { 0.372790,0.365732,0.656967 }; const dReal h88_verts[ h88_numv * 3 ] = { -0.084370,0.059618,0.343033, 0.095722,-0.319244,-0.008232, 0.172221,0.226443,-0.180656, 0.300178,0.031092,-0.053086, 0.259424,-0.225193,0.128495, 0.253773,-0.138025,0.343033, -0.207802,0.053887,0.205134, 0.072899,0.336435,-0.172573, -0.203955,-0.051368,-0.348458, 0.260362,-0.077566,0.343033, 0.038967,-0.171095,-0.223000, 0.088772,0.304416,-0.225861, 0.113761,-0.170244,0.343033, 0.067103,0.142568,0.343033, -0.229230,0.221691,-0.195070, -0.323052,-0.062181,-0.026140, 0.014109,-0.325700,0.021656, -0.261860,-0.129234,-0.214158, -0.017378,-0.313030,0.069951, -0.314197,-0.116814,-0.067215, 0.049841,0.351482,-0.143724, -0.178398,0.173789,-0.348849, -0.210923,0.250223,-0.236324, 0.283040,0.075827,-0.117937, -0.184483,0.196893,-0.325078, -0.167799,0.186994,-0.344427, }; const unsigned int h88_faces[] = { 5, 10,23,3,4,1, 6, 4,5,12,18,16,1, 5, 16,17,8,10,1, 7, 23,10,8,21,25,11,2, 3, 11,7,2, 7, 7,20,13,9,3,23,2, 4, 9,5,4,3, 5, 9,13,0,12,5, 6, 15,19,18,12,0,6, 6, 0,13,20,22,14,6, 3, 14,15,6, 6, 11,25,24,22,20,7, 8, 17,19,15,14,22,24,21,8, 4, 18,19,17,16, 3, 24,25,21, }; const dReal h88_planes[ h88_numf * 4 ] = { 0.708232,-0.479648,-0.518021,0.225182,0.20808,-0.904248,0.372879,0.305524,-0.131611,-0.83191,-0.539077,0.257422,0.438192,-0.051293,-0.897417,0.225975,0.722578,0.66608,-0.18498,0.30869,0.727925,0.639055,0.248465,0.225187,0.991673,-0.108076,0.0700326,0.2906,0,-0,1,0.343033,-0.619037,-0.533582,0.576267,0.218095,-0.446964,0.816183,0.366153,0.211972,-0.877503,0.423705,0.224641,0.25126,-0.131611,0.83191,-0.539078,0.36332,-0.933932,0.105417,-0.341552,0.304082,-0.512085,-0.851811,-0.110395,0.267819,-0.443092,0.583496,-0.68059,0.417874 }; // h89 const int h89_numv = 16; const int h89_numf = 10; const dReal h89_volu = 0.098811; const dReal h89_pos[3] = { 0.713605,0.673779,0.814484 }; const dReal h89_verts[ h89_numv * 3 ] = { -0.273713,-0.165479,0.185516, -0.080453,-0.385613,0.185516, 0.286395,-0.172812,0.185516, 0.286395,0.326221,0.093776, -0.101044,0.326221,0.185516, 0.286395,0.326221,0.185516, 0.017832,-0.221455,-0.310526, 0.286395,-0.105074,-0.128085, -0.040637,-0.276955,-0.210604, -0.057774,-0.232220,-0.275455, -0.158577,0.326221,-0.123495, -0.267917,0.028388,-0.330091, -0.290974,0.043435,-0.301241, -0.249679,0.140915,-0.263301, -0.168594,-0.081604,-0.338174, 0.022632,-0.217741,-0.314831, }; const unsigned int h89_faces[] = { 6, 8,6,15,7,2,1, 5, 2,5,4,0,1, 7, 0,12,11,14,9,8,1, 4, 7,3,5,2, 7, 7,15,14,11,13,10,3, 4, 10,4,5,3, 5, 10,13,12,0,4, 4, 9,14,15,6, 3, 8,9,6, 3, 12,13,11, }; const dReal h89_planes[ h89_numf * 4 ] = { 0.493234,-0.850287,-0.183662,0.254128,-0,1.12896e-16,1,0.185516,-0.727925,-0.639055,-0.248465,0.258897,1,0,0,0.286395,0.398278,0.419587,-0.815673,0.174452,0,1,0,0.326221,-0.929286,0.326334,0.173016,0.232453,-0.289106,-0.541462,-0.789453,0.3599,-0.131611,-0.831909,-0.539078,0.349281,-0.535431,0.493566,-0.685351,0.38369 }; //Aggregate of all cells. const int halton_numc = 90; const int halton_numv[ halton_numc ] = { h00_numv,h01_numv,h02_numv,h03_numv,h04_numv,h05_numv,h06_numv,h07_numv,h08_numv,h09_numv,h10_numv,h11_numv,h12_numv,h13_numv,h14_numv,h15_numv,h16_numv,h17_numv,h18_numv,h19_numv,h20_numv,h21_numv,h22_numv,h23_numv,h24_numv,h25_numv,h26_numv,h27_numv,h28_numv,h29_numv,h30_numv,h31_numv,h32_numv,h33_numv,h34_numv,h35_numv,h36_numv,h37_numv,h38_numv,h39_numv,h40_numv,h41_numv,h42_numv,h43_numv,h44_numv,h45_numv,h46_numv,h47_numv,h48_numv,h49_numv,h50_numv,h51_numv,h52_numv,h53_numv,h54_numv,h55_numv,h56_numv,h57_numv,h58_numv,h59_numv,h60_numv,h61_numv,h62_numv,h63_numv,h64_numv,h65_numv,h66_numv,h67_numv,h68_numv,h69_numv,h70_numv,h71_numv,h72_numv,h73_numv,h74_numv,h75_numv,h76_numv,h77_numv,h78_numv,h79_numv,h80_numv,h81_numv,h82_numv,h83_numv,h84_numv,h85_numv,h86_numv,h87_numv,h88_numv,h89_numv, }; const int halton_numf[ halton_numc ] = { h00_numf,h01_numf,h02_numf,h03_numf,h04_numf,h05_numf,h06_numf,h07_numf,h08_numf,h09_numf,h10_numf,h11_numf,h12_numf,h13_numf,h14_numf,h15_numf,h16_numf,h17_numf,h18_numf,h19_numf,h20_numf,h21_numf,h22_numf,h23_numf,h24_numf,h25_numf,h26_numf,h27_numf,h28_numf,h29_numf,h30_numf,h31_numf,h32_numf,h33_numf,h34_numf,h35_numf,h36_numf,h37_numf,h38_numf,h39_numf,h40_numf,h41_numf,h42_numf,h43_numf,h44_numf,h45_numf,h46_numf,h47_numf,h48_numf,h49_numf,h50_numf,h51_numf,h52_numf,h53_numf,h54_numf,h55_numf,h56_numf,h57_numf,h58_numf,h59_numf,h60_numf,h61_numf,h62_numf,h63_numf,h64_numf,h65_numf,h66_numf,h67_numf,h68_numf,h69_numf,h70_numf,h71_numf,h72_numf,h73_numf,h74_numf,h75_numf,h76_numf,h77_numf,h78_numf,h79_numf,h80_numf,h81_numf,h82_numf,h83_numf,h84_numf,h85_numf,h86_numf,h87_numf,h88_numf,h89_numf, }; const dReal halton_volu[ halton_numc ] = { h00_volu,h01_volu,h02_volu,h03_volu,h04_volu,h05_volu,h06_volu,h07_volu,h08_volu,h09_volu,h10_volu,h11_volu,h12_volu,h13_volu,h14_volu,h15_volu,h16_volu,h17_volu,h18_volu,h19_volu,h20_volu,h21_volu,h22_volu,h23_volu,h24_volu,h25_volu,h26_volu,h27_volu,h28_volu,h29_volu,h30_volu,h31_volu,h32_volu,h33_volu,h34_volu,h35_volu,h36_volu,h37_volu,h38_volu,h39_volu,h40_volu,h41_volu,h42_volu,h43_volu,h44_volu,h45_volu,h46_volu,h47_volu,h48_volu,h49_volu,h50_volu,h51_volu,h52_volu,h53_volu,h54_volu,h55_volu,h56_volu,h57_volu,h58_volu,h59_volu,h60_volu,h61_volu,h62_volu,h63_volu,h64_volu,h65_volu,h66_volu,h67_volu,h68_volu,h69_volu,h70_volu,h71_volu,h72_volu,h73_volu,h74_volu,h75_volu,h76_volu,h77_volu,h78_volu,h79_volu,h80_volu,h81_volu,h82_volu,h83_volu,h84_volu,h85_volu,h86_volu,h87_volu,h88_volu,h89_volu, }; const dReal* halton_pos[ halton_numc ] = { h00_pos,h01_pos,h02_pos,h03_pos,h04_pos,h05_pos,h06_pos,h07_pos,h08_pos,h09_pos,h10_pos,h11_pos,h12_pos,h13_pos,h14_pos,h15_pos,h16_pos,h17_pos,h18_pos,h19_pos,h20_pos,h21_pos,h22_pos,h23_pos,h24_pos,h25_pos,h26_pos,h27_pos,h28_pos,h29_pos,h30_pos,h31_pos,h32_pos,h33_pos,h34_pos,h35_pos,h36_pos,h37_pos,h38_pos,h39_pos,h40_pos,h41_pos,h42_pos,h43_pos,h44_pos,h45_pos,h46_pos,h47_pos,h48_pos,h49_pos,h50_pos,h51_pos,h52_pos,h53_pos,h54_pos,h55_pos,h56_pos,h57_pos,h58_pos,h59_pos,h60_pos,h61_pos,h62_pos,h63_pos,h64_pos,h65_pos,h66_pos,h67_pos,h68_pos,h69_pos,h70_pos,h71_pos,h72_pos,h73_pos,h74_pos,h75_pos,h76_pos,h77_pos,h78_pos,h79_pos,h80_pos,h81_pos,h82_pos,h83_pos,h84_pos,h85_pos,h86_pos,h87_pos,h88_pos,h89_pos, }; const dReal* halton_verts[ halton_numc ] = { h00_verts,h01_verts,h02_verts,h03_verts,h04_verts,h05_verts,h06_verts,h07_verts,h08_verts,h09_verts,h10_verts,h11_verts,h12_verts,h13_verts,h14_verts,h15_verts,h16_verts,h17_verts,h18_verts,h19_verts,h20_verts,h21_verts,h22_verts,h23_verts,h24_verts,h25_verts,h26_verts,h27_verts,h28_verts,h29_verts,h30_verts,h31_verts,h32_verts,h33_verts,h34_verts,h35_verts,h36_verts,h37_verts,h38_verts,h39_verts,h40_verts,h41_verts,h42_verts,h43_verts,h44_verts,h45_verts,h46_verts,h47_verts,h48_verts,h49_verts,h50_verts,h51_verts,h52_verts,h53_verts,h54_verts,h55_verts,h56_verts,h57_verts,h58_verts,h59_verts,h60_verts,h61_verts,h62_verts,h63_verts,h64_verts,h65_verts,h66_verts,h67_verts,h68_verts,h69_verts,h70_verts,h71_verts,h72_verts,h73_verts,h74_verts,h75_verts,h76_verts,h77_verts,h78_verts,h79_verts,h80_verts,h81_verts,h82_verts,h83_verts,h84_verts,h85_verts,h86_verts,h87_verts,h88_verts,h89_verts, }; const unsigned int* halton_faces[ halton_numc ] = { h00_faces,h01_faces,h02_faces,h03_faces,h04_faces,h05_faces,h06_faces,h07_faces,h08_faces,h09_faces,h10_faces,h11_faces,h12_faces,h13_faces,h14_faces,h15_faces,h16_faces,h17_faces,h18_faces,h19_faces,h20_faces,h21_faces,h22_faces,h23_faces,h24_faces,h25_faces,h26_faces,h27_faces,h28_faces,h29_faces,h30_faces,h31_faces,h32_faces,h33_faces,h34_faces,h35_faces,h36_faces,h37_faces,h38_faces,h39_faces,h40_faces,h41_faces,h42_faces,h43_faces,h44_faces,h45_faces,h46_faces,h47_faces,h48_faces,h49_faces,h50_faces,h51_faces,h52_faces,h53_faces,h54_faces,h55_faces,h56_faces,h57_faces,h58_faces,h59_faces,h60_faces,h61_faces,h62_faces,h63_faces,h64_faces,h65_faces,h66_faces,h67_faces,h68_faces,h69_faces,h70_faces,h71_faces,h72_faces,h73_faces,h74_faces,h75_faces,h76_faces,h77_faces,h78_faces,h79_faces,h80_faces,h81_faces,h82_faces,h83_faces,h84_faces,h85_faces,h86_faces,h87_faces,h88_faces,h89_faces, }; const dReal* halton_planes[ halton_numc ] = { h00_planes,h01_planes,h02_planes,h03_planes,h04_planes,h05_planes,h06_planes,h07_planes,h08_planes,h09_planes,h10_planes,h11_planes,h12_planes,h13_planes,h14_planes,h15_planes,h16_planes,h17_planes,h18_planes,h19_planes,h20_planes,h21_planes,h22_planes,h23_planes,h24_planes,h25_planes,h26_planes,h27_planes,h28_planes,h29_planes,h30_planes,h31_planes,h32_planes,h33_planes,h34_planes,h35_planes,h36_planes,h37_planes,h38_planes,h39_planes,h40_planes,h41_planes,h42_planes,h43_planes,h44_planes,h45_planes,h46_planes,h47_planes,h48_planes,h49_planes,h50_planes,h51_planes,h52_planes,h53_planes,h54_planes,h55_planes,h56_planes,h57_planes,h58_planes,h59_planes,h60_planes,h61_planes,h62_planes,h63_planes,h64_planes,h65_planes,h66_planes,h67_planes,h68_planes,h69_planes,h70_planes,h71_planes,h72_planes,h73_planes,h74_planes,h75_planes,h76_planes,h77_planes,h78_planes,h79_planes,h80_planes,h81_planes,h82_planes,h83_planes,h84_planes,h85_planes,h86_planes,h87_planes,h88_planes,h89_planes, }; ode-0.16/ode/demo/demo_heightfield.cpp0000664000175200017520000005245413403272463014633 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include #include "texturepath.h" #include "bunny_geom.h" #ifdef _MSC_VER #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints #endif #define DEGTORAD 0.01745329251994329577f //!< PI / 180.0, convert degrees to radians int g_allow_trimesh; // Our heightfield geom dGeomID gheight; // Heightfield dimensions #define HFIELD_WSTEP 15 // Vertex count along edge >= 2 #define HFIELD_DSTEP 31 #define HFIELD_WIDTH REAL( 4.0 ) #define HFIELD_DEPTH REAL( 8.0 ) #define HFIELD_WSAMP ( HFIELD_WIDTH / ( HFIELD_WSTEP-1 ) ) #define HFIELD_DSAMP ( HFIELD_DEPTH / ( HFIELD_DSTEP-1 ) ) //<---- Convex Object dReal planes[]= // planes for a cube { 1.0f ,0.0f ,0.0f ,0.25f, 0.0f ,1.0f ,0.0f ,0.25f, 0.0f ,0.0f ,1.0f ,0.25f, 0.0f ,0.0f ,-1.0f,0.25f, 0.0f ,-1.0f,0.0f ,0.25f, -1.0f,0.0f ,0.0f ,0.25f /* 1.0f ,0.0f ,0.0f ,2.0f, 0.0f ,1.0f ,0.0f ,1.0f, 0.0f ,0.0f ,1.0f ,1.0f, 0.0f ,0.0f ,-1.0f,1.0f, 0.0f ,-1.0f,0.0f ,1.0f, -1.0f,0.0f ,0.0f ,0.0f */ }; const unsigned int planecount=6; dReal points[]= // points for a cube { 0.25f,0.25f,0.25f, // point 0 -0.25f,0.25f,0.25f, // point 1 0.25f,-0.25f,0.25f, // point 2 -0.25f,-0.25f,0.25f,// point 3 0.25f,0.25f,-0.25f, // point 4 -0.25f,0.25f,-0.25f,// point 5 0.25f,-0.25f,-0.25f,// point 6 -0.25f,-0.25f,-0.25f,// point 7 }; const unsigned int pointcount=8; unsigned int polygons[] = //Polygons for a cube (6 squares) { 4,0,2,6,4, // positive X 4,1,0,4,5, // positive Y 4,0,1,3,2, // positive Z 4,3,1,5,7, // negative X 4,2,3,7,6, // negative Y 4,5,4,6,7, // negative Z }; //----> Convex Object // select correct drawing functions #ifdef dDOUBLE #define dsDrawBox dsDrawBoxD #define dsDrawSphere dsDrawSphereD #define dsDrawCylinder dsDrawCylinderD #define dsDrawCapsule dsDrawCapsuleD #define dsDrawConvex dsDrawConvexD #define dsDrawTriangle dsDrawTriangleD #endif // some constants #define NUM 100 // max number of objects #define DENSITY (5.0) // density of all objects #define GPB 3 // maximum number of geometries per body #define MAX_CONTACTS 64 // maximum number of contact points per body // dynamics and collision objects struct MyObject { dBodyID body; // the body dGeomID geom[GPB]; // geometries representing this body // Trimesh only - double buffered matrices for 'last transform' setup dReal matrix_dblbuff[ 16 * 2 ]; int last_matrix_index; }; static int num=0; // number of objects in simulation static int nextobj=0; // next object to recycle if num==NUM static dWorldID world; static dSpaceID space; static MyObject obj[NUM]; static dJointGroupID contactgroup; static int selected = -1; // selected object static int show_aabb = 0; // show geom AABBs? static int show_contacts = 0; // show contact points? static int random_pos = 1; // drop objects from random position? static int write_world = 0; //============================ dGeomID TriMesh1; dGeomID TriMesh2; //static dTriMeshDataID TriData1, TriData2; // reusable static trimesh data //============================ dReal heightfield_callback( void*, int x, int z ) { dReal fx = ( ((dReal)x) - ( HFIELD_WSTEP-1 )/2 ) / (dReal)( HFIELD_WSTEP-1 ); dReal fz = ( ((dReal)z) - ( HFIELD_DSTEP-1 )/2 ) / (dReal)( HFIELD_DSTEP-1 ); // Create an interesting 'hump' shape dReal h = REAL( 1.0 ) + ( REAL( -16.0 ) * ( fx*fx*fx + fz*fz*fz ) ); return h; } // this is called by dSpaceCollide when two objects in space are // potentially colliding. static void nearCallback (void *, dGeomID o1, dGeomID o2) { int i; // if (o1->body && o2->body) return; // exit without doing anything if the two bodies are connected by a joint dBodyID b1 = dGeomGetBody(o1); dBodyID b2 = dGeomGetBody(o2); if (b1 && b2 && dAreConnectedExcluding(b1,b2,dJointTypeContact)) return; dContact contact[MAX_CONTACTS]; // up to MAX_CONTACTS contacts per box-box for (i=0; i= 'A' && c <= 'Z') return c - ('a'-'A'); else return c; } // called when a key pressed static void command(int cmd) { dsizeint i; int j,k; dReal sides[3]; dMass m; bool setBody = false; cmd = locase (cmd); // // Geom Creation // if ( cmd == 'b' || cmd == 's' || cmd == 'c' || ( cmd == 'm' && g_allow_trimesh ) || cmd == 'x' || cmd == 'y' || cmd == 'v' ) { if ( num < NUM ) { i = num; num++; } else { i = nextobj++; nextobj %= num; // destroy the body and geoms for slot i dBodyDestroy(obj[i].body); obj[i].body = 0; for (k=0; k < GPB; k++) if (obj[i].geom[k]) { dGeomDestroy(obj[i].geom[k]); obj[i].geom[k] = 0; } } obj[i].body = dBodyCreate(world); for (k=0; k<3; k++) sides[k] = dRandReal()*0.5+0.1; dMatrix3 R; if (random_pos) { dBodySetPosition(obj[i].body, (dRandReal()-0.5)*HFIELD_WIDTH*0.75, (dRandReal()-0.5)*HFIELD_DEPTH*0.75, dRandReal() + 2 ); dRFromAxisAndAngle(R,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0, dRandReal()*2.0-1.0,dRandReal()*10.0-5.0); } else { dReal maxheight = 0; for (k=0; k maxheight) maxheight = pos[2]; } dBodySetPosition(obj[i].body, 0,maxheight+1,0); dRFromAxisAndAngle(R,0,0,1,dRandReal()*10.0-5.0); } dBodySetRotation(obj[i].body,R); if (cmd == 'b') { dMassSetBox(&m,DENSITY,sides[0],sides[1],sides[2]); obj[i].geom[0] = dCreateBox(space,sides[0],sides[1],sides[2]); } else if (cmd == 'c') { sides[0] *= 0.5; dMassSetCapsule(&m,DENSITY,3,sides[0],sides[1]); obj[i].geom[0] = dCreateCapsule(space,sides[0],sides[1]); } else if (cmd == 'v') { dMassSetBox (&m,DENSITY,0.25,0.25,0.25); obj[i].geom[0] = dCreateConvex(space, planes, planecount, points, pointcount, polygons); } else if (cmd == 'y') { dMassSetCylinder(&m,DENSITY,3,sides[0],sides[1]); obj[i].geom[0] = dCreateCylinder(space,sides[0],sides[1]); } else if (cmd == 's') { sides[0] *= 0.5; dMassSetSphere(&m,DENSITY,sides[0]); obj[i].geom[0] = dCreateSphere(space,sides[0]); } else if (cmd == 'm' && g_allow_trimesh) { dTriMeshDataID new_tmdata = dGeomTriMeshDataCreate(); dGeomTriMeshDataBuildSingle(new_tmdata, &Vertices[0], 3 * sizeof(float), VertexCount, &Indices[0], IndexCount, 3 * sizeof(dTriIndex)); dGeomTriMeshDataPreprocess2(new_tmdata, (1U << dTRIDATAPREPROCESS_BUILD_FACE_ANGLES), NULL); obj[i].geom[0] = dCreateTriMesh(space, new_tmdata, 0, 0, 0); dMassSetTrimesh( &m, DENSITY, obj[i].geom[0] ); printf("mass at %f %f %f\n", m.c[0], m.c[1], m.c[2]); dGeomSetPosition(obj[i].geom[0], -m.c[0], -m.c[1], -m.c[2]); dMassTranslate(&m, -m.c[0], -m.c[1], -m.c[2]); } else if (cmd == 'x') { setBody = 1; // start accumulating masses for the composite geometries dMass m2; dMassSetZero (&m); dReal dpos[GPB][3]; // delta-positions for composite geometries dMatrix3 drot[GPB]; // set random delta positions for (j=0; j= num) selected = 0; if (selected < -1) selected = 0; } else if (cmd == 'd' && selected >= 0 && selected < num) { dBodyDisable(obj[selected].body); } else if (cmd == 'e' && selected >= 0 && selected < num) { dBodyEnable(obj[selected].body); } else if (cmd == 'a') { show_aabb = !show_aabb; } else if (cmd == 't') { show_contacts = !show_contacts; } else if (cmd == 'r') { random_pos = !random_pos; } else if (cmd == '1') { write_world = 1; } } // draw a geom void drawGeom (dGeomID g, const dReal *pos, const dReal *R, int show_aabb) { if (!g) return; if (!pos) pos = dGeomGetPosition(g); if (!R) R = dGeomGetRotation(g); int type = dGeomGetClass(g); if (type == dBoxClass) { dVector3 sides; dGeomBoxGetLengths(g,sides); dsDrawBox(pos,R,sides); } else if (type == dSphereClass) { dsDrawSphere(pos,R,dGeomSphereGetRadius(g)); } else if (type == dCapsuleClass) { dReal radius,length; dGeomCapsuleGetParams(g,&radius,&length); dsDrawCapsule(pos,R,length,radius); } else if (type == dConvexClass) { //dVector3 sides={0.50,0.50,0.50}; dsDrawConvex(pos,R,planes, planecount, points, pointcount, polygons); } else if (type == dCylinderClass) { dReal radius,length; dGeomCylinderGetParams(g,&radius,&length); dsDrawCylinder(pos,R,length,radius); } else if (type == dTriMeshClass) { dTriIndex* Indices = (dTriIndex*)::Indices; // assume all trimeshes are drawn as bunnies for (int ii = 0; ii < IndexCount / 3; ii++) { const dReal v[9] = { // explicit conversion from float to dReal Vertices[Indices[ii * 3 + 0] * 3 + 0], Vertices[Indices[ii * 3 + 0] * 3 + 1], Vertices[Indices[ii * 3 + 0] * 3 + 2], Vertices[Indices[ii * 3 + 1] * 3 + 0], Vertices[Indices[ii * 3 + 1] * 3 + 1], Vertices[Indices[ii * 3 + 1] * 3 + 2], Vertices[Indices[ii * 3 + 2] * 3 + 0], Vertices[Indices[ii * 3 + 2] * 3 + 1], Vertices[Indices[ii * 3 + 2] * 3 + 2] }; dsDrawTriangle(pos, R, &v[0], &v[3], &v[6], 1); } } else if (type == dHeightfieldClass) { // Set ox and oz to zero for DHEIGHTFIELD_CORNER_ORIGIN mode. int ox = (int) ( -HFIELD_WIDTH/2 ); int oz = (int) ( -HFIELD_DEPTH/2 ); // for ( int tx = -1; tx < 2; ++tx ) // for ( int tz = -1; tz < 2; ++tz ) dsSetColorAlpha (0.5,1,0.5,0.5); dsSetTexture( DS_WOOD ); for ( int i = 0; i < HFIELD_WSTEP - 1; ++i ) for ( int j = 0; j < HFIELD_DSTEP - 1; ++j ) { dReal a[3], b[3], c[3], d[3]; a[ 0 ] = ox + ( i ) * HFIELD_WSAMP; a[ 1 ] = heightfield_callback( NULL, i, j ); a[ 2 ] = oz + ( j ) * HFIELD_DSAMP; b[ 0 ] = ox + ( i + 1 ) * HFIELD_WSAMP; b[ 1 ] = heightfield_callback( NULL, i + 1, j ); b[ 2 ] = oz + ( j ) * HFIELD_DSAMP; c[ 0 ] = ox + ( i ) * HFIELD_WSAMP; c[ 1 ] = heightfield_callback( NULL, i, j + 1 ); c[ 2 ] = oz + ( j + 1 ) * HFIELD_DSAMP; d[ 0 ] = ox + ( i + 1 ) * HFIELD_WSAMP; d[ 1 ] = heightfield_callback( NULL, i + 1, j + 1 ); d[ 2 ] = oz + ( j + 1 ) * HFIELD_DSAMP; dsDrawTriangle( pos, R, a, c, b, 1 ); dsDrawTriangle( pos, R, b, c, d, 1 ); } } if (show_aabb) { // draw the bounding box for this geom dReal aabb[6]; dGeomGetAABB(g,aabb); dVector3 bbpos; for (int i=0; i<3; i++) bbpos[i] = 0.5*(aabb[i*2] + aabb[i*2+1]); dVector3 bbsides; for (int i=0; i<3; i++) bbsides[i] = aabb[i*2+1] - aabb[i*2]; dMatrix3 RI; dRSetIdentity(RI); dsSetColorAlpha(1,0,0,0.5); dsDrawBox(bbpos,RI,bbsides); } } // simulation loop static void simLoop (int pause) { int i,j; dSpaceCollide(space,0,&nearCallback); if (!pause) dWorldQuickStep(world,0.05); if (write_world) { FILE *f = fopen ("state.dif","wt"); if (f) { dWorldExportDIF(world,f,"X"); fclose (f); } write_world = 0; } // remove all contact joints dJointGroupEmpty(contactgroup); // // Draw Heightfield // drawGeom(gheight, 0, 0, 0); dsSetColor (1,1,0); dsSetTexture (DS_WOOD); for (i=0; i # include # include # include # include #include "texturepath.h" # define drand48() ((double) (((double) rand()) / ((double) RAND_MAX))) # define N_BODIES 40 # define STAGE_SIZE 8.0 // in m # define TIME_STEP 0.01 # define K_SPRING 10.0 # define K_DAMP 10.0 //using namespace ode; struct GlobalVars { dWorld dyn_world; dBody dyn_bodies[N_BODIES]; dReal bodies_sides[N_BODIES][3]; dSpaceID coll_space_id; dJointID plane2d_joint_ids[N_BODIES]; dJointGroup coll_contacts; }; static GlobalVars *g_globals_ptr = NULL; static void cb_start () /*************************/ { dAllocateODEDataForThread(dAllocateMaskAll); static float xyz[3] = { 0.5f*STAGE_SIZE, 0.5f*STAGE_SIZE, 0.65f*STAGE_SIZE}; static float hpr[3] = { 90.0f, -90.0f, 0 }; dsSetViewpoint (xyz, hpr); } static void cb_near_collision (void *, dGeomID o1, dGeomID o2) /********************************************************************/ { dBodyID b1 = dGeomGetBody (o1); dBodyID b2 = dGeomGetBody (o2); dContact contact; // exit without doing anything if the two bodies are static if (b1 == 0 && b2 == 0) return; // exit without doing anything if the two bodies are connected by a joint if (b1 && b2 && dAreConnected (b1, b2)) { /* MTRAP; */ return; } contact.surface.mode = 0; contact.surface.mu = 0; // frictionless if (dCollide (o1, o2, 1, &contact.geom, sizeof (dContactGeom))) { dJointID c = dJointCreateContact (g_globals_ptr->dyn_world.id(), g_globals_ptr->coll_contacts.id (), &contact); dJointAttach (c, b1, b2); } } static void track_to_pos (dBody &body, dJointID joint_id, dReal target_x, dReal target_y) /************************************************************************/ { dReal curr_x = body.getPosition()[0]; dReal curr_y = body.getPosition()[1]; dJointSetPlane2DXParam (joint_id, dParamVel, 1 * (target_x - curr_x)); dJointSetPlane2DYParam (joint_id, dParamVel, 1 * (target_y - curr_y)); } static void cb_sim_step (int pause) /*************************************/ { if (! pause) { static dReal angle = 0; angle += REAL( 0.01 ); track_to_pos (g_globals_ptr->dyn_bodies[0], g_globals_ptr->plane2d_joint_ids[0], dReal( STAGE_SIZE/2 + STAGE_SIZE/2.0 * cos (angle) ), dReal( STAGE_SIZE/2 + STAGE_SIZE/2.0 * sin (angle) )); /* double f0 = 0.001; */ /* for (int b = 0; b < N_BODIES; b ++) */ /* { */ /* double p = 1 + b / (double) N_BODIES; */ /* double q = 2 - b / (double) N_BODIES; */ /* g_globals_ptr->dyn_bodies[b].addForce (f0 * cos (p*angle), f0 * sin (q*angle), 0); */ /* } */ /* g_globals_ptr->dyn_bodies[0].addTorque (0, 0, 0.1); */ const int n = 10; for (int i = 0; i < n; i ++) { dSpaceCollide (g_globals_ptr->coll_space_id, 0, &cb_near_collision); g_globals_ptr->dyn_world.step (dReal(TIME_STEP/n)); g_globals_ptr->coll_contacts.empty (); } } # if 1 /* [ */ { // @@@ hack Plane2D constraint error reduction here: for (int b = 0; b < N_BODIES; b ++) { const dReal *rot = dBodyGetAngularVel (g_globals_ptr->dyn_bodies[b].id()); const dReal *quat_ptr; dReal quat[4], quat_len; quat_ptr = dBodyGetQuaternion (g_globals_ptr->dyn_bodies[b].id()); quat[0] = quat_ptr[0]; quat[1] = 0; quat[2] = 0; quat[3] = quat_ptr[3]; quat_len = sqrt (quat[0] * quat[0] + quat[3] * quat[3]); quat[0] /= quat_len; quat[3] /= quat_len; dBodySetQuaternion (g_globals_ptr->dyn_bodies[b].id(), quat); dBodySetAngularVel (g_globals_ptr->dyn_bodies[b].id(), 0, 0, rot[2]); } } # endif /* ] */ # if 0 /* [ */ { // @@@ friction for (int b = 0; b < N_BODIES; b ++) { const dReal *vel = dBodyGetLinearVel (g_globals_ptr->dyn_bodies[b].id()), *rot = dBodyGetAngularVel (g_globals_ptr->dyn_bodies[b].id()); dReal s = 1.00; dReal t = 0.99; dBodySetLinearVel (g_globals_ptr->dyn_bodies[b].id(), s*vel[0],s*vel[1],s*vel[2]); dBodySetAngularVel (g_globals_ptr->dyn_bodies[b].id(),t*rot[0],t*rot[1],t*rot[2]); } } # endif /* ] */ { // ode drawstuff dsSetTexture (DS_WOOD); for (int b = 0; b < N_BODIES; b ++) { if (b == 0) dsSetColor (1.0, 0.5, 1.0); else dsSetColor (0, 0.5, 1.0); #ifdef dDOUBLE dsDrawBoxD (g_globals_ptr->dyn_bodies[b].getPosition(), g_globals_ptr->dyn_bodies[b].getRotation(), g_globals_ptr->bodies_sides[b]); #else dsDrawBox (g_globals_ptr->dyn_bodies[b].getPosition(), g_globals_ptr->dyn_bodies[b].getRotation(), g_globals_ptr->bodies_sides[b]); #endif } } } extern int main /******************/ ( int argc, char **argv ) { int b; dsFunctions drawstuff_functions; dInitODE2(0); g_globals_ptr = new GlobalVars(); // dynamic world dReal cf_mixing;// = 1 / TIME_STEP * K_SPRING + K_DAMP; dReal err_reduct;// = TIME_STEP * K_SPRING * cf_mixing; err_reduct = REAL( 0.5 ); cf_mixing = REAL( 0.001 ); dWorldSetERP (g_globals_ptr->dyn_world.id (), err_reduct); dWorldSetCFM (g_globals_ptr->dyn_world.id (), cf_mixing); g_globals_ptr->dyn_world.setGravity (0, 0.0, -1.0); g_globals_ptr->coll_space_id = dSimpleSpaceCreate (0); // dynamic bodies for (b = 0; b < N_BODIES; b ++) { int l = (int) (1 + sqrt ((double) N_BODIES)); dReal x = dReal( (0.5 + (b / l)) / l * STAGE_SIZE ); dReal y = dReal( (0.5 + (b % l)) / l * STAGE_SIZE ); dReal z = REAL( 1.0 ) + REAL( 0.1 ) * (dReal)drand48(); g_globals_ptr->bodies_sides[b][0] = dReal( 5 * (0.2 + 0.7*drand48()) / sqrt((double)N_BODIES) ); g_globals_ptr->bodies_sides[b][1] = dReal( 5 * (0.2 + 0.7*drand48()) / sqrt((double)N_BODIES) ); g_globals_ptr->bodies_sides[b][2] = z; g_globals_ptr->dyn_bodies[b].create (g_globals_ptr->dyn_world); g_globals_ptr->dyn_bodies[b].setPosition (x, y, z/2); g_globals_ptr->dyn_bodies[b].setData ((void*) (dsizeint)b); dBodySetLinearVel (g_globals_ptr->dyn_bodies[b].id (), dReal( 3 * (drand48 () - 0.5) ), dReal( 3 * (drand48 () - 0.5) ), 0); dMass m; m.setBox (1, g_globals_ptr->bodies_sides[b][0],g_globals_ptr->bodies_sides[b][1],g_globals_ptr->bodies_sides[b][2]); m.adjust (REAL(0.1) * g_globals_ptr->bodies_sides[b][0] * g_globals_ptr->bodies_sides[b][1]); g_globals_ptr->dyn_bodies[b].setMass (&m); g_globals_ptr->plane2d_joint_ids[b] = dJointCreatePlane2D (g_globals_ptr->dyn_world.id (), 0); dJointAttach (g_globals_ptr->plane2d_joint_ids[b], g_globals_ptr->dyn_bodies[b].id (), 0); } dJointSetPlane2DXParam (g_globals_ptr->plane2d_joint_ids[0], dParamFMax, 10); dJointSetPlane2DYParam (g_globals_ptr->plane2d_joint_ids[0], dParamFMax, 10); // collision geoms and joints dCreatePlane (g_globals_ptr->coll_space_id, 1, 0, 0, 0); dCreatePlane (g_globals_ptr->coll_space_id, -1, 0, 0, -STAGE_SIZE); dCreatePlane (g_globals_ptr->coll_space_id, 0, 1, 0, 0); dCreatePlane (g_globals_ptr->coll_space_id, 0, -1, 0, -STAGE_SIZE); for (b = 0; b < N_BODIES; b ++) { dGeomID coll_box_id; coll_box_id = dCreateBox (g_globals_ptr->coll_space_id, g_globals_ptr->bodies_sides[b][0], g_globals_ptr->bodies_sides[b][1], g_globals_ptr->bodies_sides[b][2]); dGeomSetBody (coll_box_id, g_globals_ptr->dyn_bodies[b].id ()); } g_globals_ptr->coll_contacts.create (); { // simulation loop (by drawstuff lib) drawstuff_functions.version = DS_VERSION; drawstuff_functions.start = &cb_start; drawstuff_functions.step = &cb_sim_step; drawstuff_functions.command = 0; drawstuff_functions.stop = 0; drawstuff_functions.path_to_textures = DRAWSTUFF_TEXTURE_PATH; dsSimulationLoop (argc, argv, 352,288,&drawstuff_functions); } delete g_globals_ptr; g_globals_ptr = NULL; dCloseODE(); return 0; } ode-0.16/ode/demo/demo_slider.cpp0000664000175200017520000001232013403272463013625 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include #include "texturepath.h" #ifdef _MSC_VER #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints #endif // select correct drawing functions #ifdef dDOUBLE #define dsDrawBox dsDrawBoxD #endif // some constants #define SIDE (0.5f) // side length of a box #define MASS (1.0) // mass of a box // dynamics and collision objects static dWorldID world; static dBodyID body[2]; static dJointID slider; // state set by keyboard commands static int occasional_error = 0; // start simulation - set viewpoint static void start() { dAllocateODEDataForThread(dAllocateMaskAll); static float xyz[3] = {1.0382f,-1.0811f,1.4700f}; static float hpr[3] = {135.0000f,-19.5000f,0.0000f}; dsSetViewpoint (xyz,hpr); printf ("Press 'e' to start/stop occasional error.\n"); } // called when a key pressed static void command (int cmd) { if (cmd == 'e' || cmd == 'E') { occasional_error ^= 1; } } // simulation loop static void simLoop (int pause) { const dReal kd = -0.3; // angular damping constant const dReal ks = 0.5; // spring constant if (!pause) { // add an oscillating torque to body 0, and also damp its rotational motion static dReal a=0; const dReal *w = dBodyGetAngularVel (body[0]); dBodyAddTorque (body[0],kd*w[0],kd*w[1]+0.1*cos(a),kd*w[2]+0.1*sin(a)); a += 0.01; // add a spring force to keep the bodies together, otherwise they will // fly apart along the slider axis. const dReal *p1 = dBodyGetPosition (body[0]); const dReal *p2 = dBodyGetPosition (body[1]); dBodyAddForce (body[0],ks*(p2[0]-p1[0]),ks*(p2[1]-p1[1]), ks*(p2[2]-p1[2])); dBodyAddForce (body[1],ks*(p1[0]-p2[0]),ks*(p1[1]-p2[1]), ks*(p1[2]-p2[2])); // occasionally re-orient one of the bodies to create a deliberate error. if (occasional_error) { static int count = 0; if ((count % 20)==0) { // randomly adjust orientation of body[0] const dReal *R1; dMatrix3 R2,R3; R1 = dBodyGetRotation (body[0]); dRFromAxisAndAngle (R2,dRandReal()-0.5,dRandReal()-0.5, dRandReal()-0.5,dRandReal()-0.5); dMultiply0 (R3,R1,R2,3,3,3); dBodySetRotation (body[0],R3); // randomly adjust position of body[0] const dReal *pos = dBodyGetPosition (body[0]); dBodySetPosition (body[0], pos[0]+0.2*(dRandReal()-0.5), pos[1]+0.2*(dRandReal()-0.5), pos[2]+0.2*(dRandReal()-0.5)); } count++; } dWorldStep (world,0.05); } dReal sides1[3] = {SIDE,SIDE,SIDE}; dReal sides2[3] = {SIDE*0.8f,SIDE*0.8f,SIDE*2.0f}; dsSetTexture (DS_WOOD); dsSetColor (1,1,0); dsDrawBox (dBodyGetPosition(body[0]),dBodyGetRotation(body[0]),sides1); dsSetColor (0,1,1); dsDrawBox (dBodyGetPosition(body[1]),dBodyGetRotation(body[1]),sides2); } int main (int argc, char **argv) { // setup pointers to drawstuff callback functions dsFunctions fn; fn.version = DS_VERSION; fn.start = &start; fn.step = &simLoop; fn.command = &command; fn.stop = 0; fn.path_to_textures = DRAWSTUFF_TEXTURE_PATH; // create world dInitODE2(0); world = dWorldCreate(); dMass m; dMassSetBox (&m,1,SIDE,SIDE,SIDE); dMassAdjust (&m,MASS); body[0] = dBodyCreate (world); dBodySetMass (body[0],&m); dBodySetPosition (body[0],0,0,1); body[1] = dBodyCreate (world); dBodySetMass (body[1],&m); dQuaternion q; dQFromAxisAndAngle (q,-1,1,0,0.25*M_PI); dBodySetPosition (body[1],0.2,0.2,1.2); dBodySetQuaternion (body[1],q); slider = dJointCreateSlider (world,0); dJointAttach (slider,body[0],body[1]); dJointSetSliderAxis (slider,1,1,1); // run simulation dsSimulationLoop (argc,argv,352,288,&fn); dWorldDestroy (world); dCloseODE(); return 0; } ode-0.16/ode/demo/demo_basket.cpp0000664000175200017520000001741713403272463013630 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ // Basket ball demo. // Serves as a test for the sphere vs trimesh collider // By Bram Stolk. // Press the spacebar to reset the position of the ball. #include #ifdef HAVE_UNISTD_H #include #endif #include #include #include "texturepath.h" #include "basket_geom.h" // this is our world mesh #ifdef _MSC_VER #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints #endif // some constants #define RADIUS 0.14 // dynamics and collision objects (chassis, 3 wheels, environment) static dWorldID world; static dSpaceID space; static dBodyID sphbody; static dGeomID sphgeom; static dJointGroupID contactgroup; static dGeomID world_mesh; // this is called by dSpaceCollide when two objects in space are // potentially colliding. static void nearCallback (void *data, dGeomID o1, dGeomID o2) { assert(o1); assert(o2); if (dGeomIsSpace(o1) || dGeomIsSpace(o2)) { fprintf(stderr,"testing space %p %p\n", (void*)o1, (void*)o2); // colliding a space with something dSpaceCollide2(o1,o2,data,&nearCallback); // Note we do not want to test intersections within a space, // only between spaces. return; } // fprintf(stderr,"testing geoms %p %p\n", o1, o2); const int N = 32; dContact contact[N]; int n = dCollide (o1,o2,N,&(contact[0].geom),sizeof(dContact)); if (n > 0) { for (int i=0; i /* This is a description of a convex icosahedron, to test the convex collision detection. */ unsigned int Sphere_pointcount = 42; unsigned int Sphere_planecount = 80; dReal Sphere_points[126]={ 0.000000,0.000000,-0.300000, 0.217080,-0.157716,-0.134164, -0.082915,-0.255192,-0.134164, -0.268327,0.000000,-0.134164, -0.082915,0.255192,-0.134164, 0.217080,0.157716,-0.134164, 0.082915,-0.255192,0.134164, -0.217080,-0.157716,0.134164, -0.217080,0.157716,0.134164, 0.082915,0.255192,0.134164, 0.268327,0.000000,0.134164, 0.000000,0.000000,0.300000, 0.127597,-0.092703,-0.255196, -0.048737,-0.149999,-0.255196, 0.078861,-0.242703,-0.157721, 0.127597,0.092703,-0.255196, 0.255194,0.000000,-0.157721, -0.157719,0.000000,-0.255195, -0.206457,-0.149999,-0.157721, -0.048737,0.149999,-0.255196, -0.206457,0.149999,-0.157721, 0.078861,0.242703,-0.157721, 0.285317,0.092704,0.000000, 0.285317,-0.092704,0.000000, 0.176336,-0.242705,0.000000, 0.000000,-0.300000,0.000000, -0.176336,-0.242705,0.000000, -0.285317,-0.092704,0.000000, -0.285317,0.092704,0.000000, -0.176336,0.242705,0.000000, 0.000000,0.300000,0.000000, 0.176336,0.242705,0.000000, 0.206457,-0.149999,0.157721, -0.078861,-0.242703,0.157721, -0.255194,0.000000,0.157721, -0.078861,0.242703,0.157721, 0.206457,0.149999,0.157721, 0.157719,0.000000,0.255195, 0.048737,-0.149999,0.255196, -0.127597,-0.092703,0.255196, -0.127597,0.092703,0.255196, 0.048737,0.149999,0.255196 }; unsigned int Sphere_polygons[]={ 3,14,12,1, 3,12,14,13, 3,2,13,14, 3,13,0,12, 3,16,1,12, 3,12,15,16, 3,5,16,15, 3,12,0,15, 3,18,13,2, 3,13,18,17, 3,3,17,18, 3,17,0,13, 3,20,17,3, 3,17,20,19, 3,4,19,20, 3,19,0,17, 3,21,19,4, 3,19,21,15, 3,5,15,21, 3,15,0,19, 3,23,1,16, 3,16,22,23, 3,10,23,22, 3,22,16,5, 3,25,2,14, 3,14,24,25, 3,6,25,24, 3,24,14,1, 3,27,3,18, 3,18,26,27, 3,7,27,26, 3,26,18,2, 3,29,4,20, 3,20,28,29, 3,8,29,28, 3,28,20,3, 3,31,5,21, 3,21,30,31, 3,9,31,30, 3,30,21,4, 3,32,23,10, 3,23,32,24, 3,6,24,32, 3,24,1,23, 3,33,25,6, 3,25,33,26, 3,7,26,33, 3,26,2,25, 3,34,27,7, 3,27,34,28, 3,8,28,34, 3,28,3,27, 3,35,29,8, 3,29,35,30, 3,9,30,35, 3,30,4,29, 3,36,31,9, 3,31,36,22, 3,10,22,36, 3,22,5,31, 3,38,6,32, 3,32,37,38, 3,11,38,37, 3,37,32,10, 3,39,7,33, 3,33,38,39, 3,11,39,38, 3,38,33,6, 3,40,8,34, 3,34,39,40, 3,11,40,39, 3,39,34,7, 3,41,9,35, 3,35,40,41, 3,11,41,40, 3,40,35,8, 3,37,10,36, 3,36,41,37, 3,11,37,41, 3,41,36,9, }; dReal Sphere_planes[]={ 0.471317,-0.583121,-0.661687,0.283056, 0.187594,-0.577345,-0.794658,0.280252, -0.038547,-0.748789,-0.661687,0.283056, 0.102381,-0.315090,-0.943523,0.283057, 0.700228,-0.268049,-0.661688,0.283056, 0.607060,0.000000,-0.794656,0.280252, 0.700228,0.268049,-0.661688,0.283056, 0.331305,0.000000,-0.943524,0.283057, -0.408939,-0.628443,-0.661686,0.283056, -0.491119,-0.356821,-0.794657,0.280252, -0.724044,-0.194735,-0.661694,0.283057, -0.268034,-0.194737,-0.943523,0.283057, -0.724044,0.194735,-0.661694,0.283057, -0.491119,0.356821,-0.794657,0.280252, -0.408939,0.628443,-0.661686,0.283056, -0.268034,0.194737,-0.943523,0.283057, -0.038547,0.748789,-0.661687,0.283056, 0.187594,0.577345,-0.794658,0.280252, 0.471317,0.583121,-0.661687,0.283056, 0.102381,0.315090,-0.943523,0.283057, 0.904981,-0.268049,-0.330393,0.283056, 0.982246,0.000000,-0.187599,0.280252, 0.992077,0.000000,0.125631,0.283057, 0.904981,0.268049,-0.330393,0.283056, 0.024726,-0.943519,-0.330396,0.283056, 0.303531,-0.934171,-0.187598,0.280251, 0.306568,-0.943519,0.125651,0.283056, 0.534590,-0.777851,-0.330395,0.283056, -0.889698,-0.315092,-0.330386,0.283056, -0.794656,-0.577348,-0.187595,0.280251, -0.802607,-0.583125,0.125648,0.283055, -0.574584,-0.748793,-0.330397,0.283055, -0.574584,0.748793,-0.330397,0.283055, -0.794656,0.577348,-0.187595,0.280251, -0.802607,0.583125,0.125648,0.283055, -0.889698,0.315092,-0.330386,0.283056, 0.534590,0.777851,-0.330395,0.283056, 0.303531,0.934171,-0.187598,0.280251, 0.306568,0.943519,0.125651,0.283056, 0.024726,0.943519,-0.330396,0.283056, 0.889698,-0.315092,0.330386,0.283056, 0.794656,-0.577348,0.187595,0.280251, 0.574584,-0.748793,0.330397,0.283055, 0.802607,-0.583125,-0.125648,0.283055, -0.024726,-0.943519,0.330396,0.283055, -0.303531,-0.934171,0.187598,0.280251, -0.534590,-0.777851,0.330395,0.283056, -0.306568,-0.943519,-0.125651,0.283056, -0.904981,-0.268049,0.330393,0.283056, -0.982246,0.000000,0.187599,0.280252, -0.904981,0.268049,0.330393,0.283056, -0.992077,0.000000,-0.125631,0.283057, -0.534590,0.777851,0.330395,0.283056, -0.303531,0.934171,0.187598,0.280251, -0.024726,0.943519,0.330396,0.283055, -0.306568,0.943519,-0.125651,0.283056, 0.574584,0.748793,0.330397,0.283055, 0.794656,0.577348,0.187595,0.280251, 0.889698,0.315092,0.330386,0.283056, 0.802607,0.583125,-0.125648,0.283055, 0.408939,-0.628443,0.661686,0.283056, 0.491119,-0.356821,0.794657,0.280252, 0.268034,-0.194737,0.943523,0.283057, 0.724044,-0.194735,0.661694,0.283057, -0.471317,-0.583121,0.661687,0.283056, -0.187594,-0.577345,0.794658,0.280252, -0.102381,-0.315090,0.943523,0.283057, 0.038547,-0.748789,0.661687,0.283056, -0.700228,0.268049,0.661688,0.283056, -0.607060,0.000000,0.794656,0.280252, -0.331305,0.000000,0.943524,0.283057, -0.700228,-0.268049,0.661688,0.283056, 0.038547,0.748789,0.661687,0.283056, -0.187594,0.577345,0.794658,0.280252, -0.102381,0.315090,0.943523,0.283057, -0.471317,0.583121,0.661687,0.283056, 0.724044,0.194735,0.661694,0.283057, 0.491119,0.356821,0.794657,0.280252, 0.268034,0.194737,0.943523,0.283057, 0.408939,0.628443,0.661686,0.283056, }; ode-0.16/ode/demo/demo_I.cpp0000664000175200017520000001732513403272463012545 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* test that the rotational physics is correct. an "anchor body" has a number of other randomly positioned bodies ("particles") attached to it by ball-and-socket joints, giving it some random effective inertia tensor. the effective inertia matrix is calculated, and then this inertia is assigned to another "test" body. a random torque is applied to both bodies and the difference in angular velocity and orientation is observed after a number of iterations. typical errors for each test cycle are about 1e-5 ... 1e-4. */ #include #include #include #include "texturepath.h" #ifdef _MSC_VER #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints #endif // select correct drawing functions #ifdef dDOUBLE #define dsDrawBox dsDrawBoxD #define dsDrawSphere dsDrawSphereD #define dsDrawCylinder dsDrawCylinderD #define dsDrawCapsule dsDrawCapsuleD #endif // some constants #define NUM 10 // number of particles #define SIDE 0.1 // visual size of the particles // dynamics objects an globals static dWorldID world=0; static dBodyID anchor_body,particle[NUM],test_body; static dJointID particle_joint[NUM]; static dReal torque[3]; static int iteration; // start simulation - set viewpoint static void start() { dAllocateODEDataForThread(dAllocateMaskAll); static float xyz[3] = {1.5572f,-1.8886f,1.5700f}; static float hpr[3] = {118.5000f,-17.0000f,0.0000f}; dsSetViewpoint (xyz,hpr); } // compute the mass parameters of a particle set. q = particle positions, // pm = particle masses #define _I(i,j) I[(i)*4+(j)] void computeMassParams (dMass *m, dReal q[NUM][3], dReal pm[NUM]) { int i,j; dMassSetZero (m); for (i=0; imass += pm[i]; for (j=0; j<3; j++) m->c[j] += pm[i]*q[i][j]; m->_I(0,0) += pm[i]*(q[i][1]*q[i][1] + q[i][2]*q[i][2]); m->_I(1,1) += pm[i]*(q[i][0]*q[i][0] + q[i][2]*q[i][2]); m->_I(2,2) += pm[i]*(q[i][0]*q[i][0] + q[i][1]*q[i][1]); m->_I(0,1) -= pm[i]*(q[i][0]*q[i][1]); m->_I(0,2) -= pm[i]*(q[i][0]*q[i][2]); m->_I(1,2) -= pm[i]*(q[i][1]*q[i][2]); } for (j=0; j<3; j++) m->c[j] /= m->mass; m->_I(1,0) = m->_I(0,1); m->_I(2,0) = m->_I(0,2); m->_I(2,1) = m->_I(1,2); } void reset_test() { int i; dMass m,anchor_m; dReal q[NUM][3], pm[NUM]; // particle positions and masses dReal pos1[3] = {1,0,1}; // point of reference (POR) dReal pos2[3] = {-1,0,1}; // point of reference (POR) // make random particle positions (relative to POR) and masses for (i=0; i= 100) { // measure the difference between the anchor and test bodies const dReal *w1 = dBodyGetAngularVel (anchor_body); const dReal *w2 = dBodyGetAngularVel (test_body); const dReal *q1 = dBodyGetQuaternion (anchor_body); const dReal *q2 = dBodyGetQuaternion (test_body); dReal maxdiff = dMaxDifference (w1,w2,1,3); printf ("w-error = %.4e (%.2f,%.2f,%.2f) and (%.2f,%.2f,%.2f)\n", maxdiff,w1[0],w1[1],w1[2],w2[0],w2[1],w2[2]); maxdiff = dMaxDifference (q1,q2,1,4); printf ("q-error = %.4e\n",maxdiff); reset_test(); } } dReal sides[3] = {SIDE,SIDE,SIDE}; dReal sides2[3] = {6*SIDE,6*SIDE,6*SIDE}; dReal sides3[3] = {3*SIDE,3*SIDE,3*SIDE}; dsSetColor (1,1,1); dsDrawBox (dBodyGetPosition(anchor_body), dBodyGetRotation(anchor_body), sides3); dsSetColor (1,0,0); dsDrawBox (dBodyGetPosition(test_body), dBodyGetRotation(test_body), sides2); dsSetColor (1,1,0); for (int i=0; i #include #include "texturepath.h" #ifdef _MSC_VER #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints #endif //<---- Convex Object static const dReal planes[] = // planes for a cube { 1.0f ,0.0f ,0.0f ,0.25f, 0.0f ,1.0f ,0.0f ,0.25f, 0.0f ,0.0f ,1.0f ,0.25f, 0.0f ,0.0f ,-1.0f,0.25f, 0.0f ,-1.0f,0.0f ,0.25f, -1.0f,0.0f ,0.0f ,0.25f /* 1.0f ,0.0f ,0.0f ,2.0f, 0.0f ,1.0f ,0.0f ,1.0f, 0.0f ,0.0f ,1.0f ,1.0f, 0.0f ,0.0f ,-1.0f,1.0f, 0.0f ,-1.0f,0.0f ,1.0f, -1.0f,0.0f ,0.0f ,0.0f */ }; static const unsigned int planecount=6; static const dReal points[] = // points for a cube { 0.25f,0.25f,0.25f, -0.25f,0.25f,0.25f, 0.25f,-0.25f,0.25f, -0.25f,-0.25f,0.25f, 0.25f,0.25f,-0.25f, -0.25f,0.25f,-0.25f, 0.25f,-0.25f,-0.25f, -0.25f,-0.25f,-0.25f, }; static const unsigned int pointcount=8; static const unsigned int polygons[] = //Polygons for a cube (6 squares) { 4,0,2,6,4, // positive X 4,1,0,4,5, // positive Y 4,0,1,3,2, // positive Z 4,3,1,5,7, // negative X 4,2,3,7,6, // negative Y 4,5,4,6,7, // negative Z }; //----> Convex Object // select correct drawing functions #ifdef dDOUBLE #define dsDrawBox dsDrawBoxD #define dsDrawSphere dsDrawSphereD #define dsDrawCylinder dsDrawCylinderD #define dsDrawCapsule dsDrawCapsuleD #define dsDrawLine dsDrawLineD #define dsDrawTriangle dsDrawTriangleD #define dsDrawConvex dsDrawConvexD #endif // some constants #define NUM 200 // max number of objects #define DENSITY (5.0) // density of all objects #define GPB 3 // maximum number of geometries per body #define MAX_CONTACTS 40 // maximum number of contact points per body // dynamics and collision objects struct MyObject { dBodyID body; // the body dGeomID geom[GPB]; // geometries representing this body }; static int num=0; // number of objects in simulation static int nextobj=0; // next object to recycle if num==NUM static dWorldID world; static dSpaceID space; static MyObject obj[NUM]; static dJointGroupID contactgroup; static int selected = -1; // selected object static int show_aabb = 0; // show geom AABBs? static int show_contacts = 0; // show contact points? static int random_pos = 1; // drop objects from random position? #define VertexCount 5 #define IndexCount 12 static dVector3 Size; static float Vertices[VertexCount][3]; static dTriIndex Indices[IndexCount]; static dGeomID TriMesh; static dGeomID Ray; // this is called by dSpaceCollide when two objects in space are // potentially colliding. static void nearCallback (void *, dGeomID o1, dGeomID o2) { int i; // if (o1->body && o2->body) return; // exit without doing anything if the two bodies are connected by a joint dBodyID b1 = dGeomGetBody(o1); dBodyID b2 = dGeomGetBody(o2); if (b1 && b2 && dAreConnectedExcluding (b1,b2,dJointTypeContact)) return; dContact contact[MAX_CONTACTS]; // up to MAX_CONTACTS contacts per box-box for (i=0; i= 'A' && c <= 'Z') return c - ('a'-'A'); else return c; } // called when a key pressed static void command (int cmd) { int i,j,k; dReal sides[3]; dMass m; bool setBody = false; cmd = locase (cmd); if (cmd == 'b' || cmd == 's' || cmd == 'c' || cmd == 'x' || cmd == 'v' /* || cmd == 'l' */) { if (num < NUM) { i = num; num++; } else { i = nextobj; nextobj++; if (nextobj >= num) nextobj = 0; // destroy the body and geoms for slot i dBodyDestroy (obj[i].body); for (k=0; k < GPB; k++) { if (obj[i].geom[k]) dGeomDestroy (obj[i].geom[k]); } memset (&obj[i],0,sizeof(obj[i])); } obj[i].body = dBodyCreate (world); for (k=0; k<3; k++) sides[k] = dRandReal()*0.5+0.1; dMatrix3 R; if (random_pos) { dBodySetPosition (obj[i].body, dRandReal()*2-1,dRandReal()*2-1,dRandReal()+1); dRFromAxisAndAngle (R,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0, dRandReal()*2.0-1.0,dRandReal()*10.0-5.0); } else { dReal maxheight = 0; for (k=0; k maxheight) maxheight = pos[2]; } dBodySetPosition (obj[i].body, 0,0,maxheight+1); dRFromAxisAndAngle (R,0,0,1,dRandReal()*10.0-5.0); } dBodySetRotation (obj[i].body,R); dBodySetData (obj[i].body,(void*)(dsizeint)i); if (cmd == 'b') { dMassSetBox (&m,DENSITY,sides[0],sides[1],sides[2]); obj[i].geom[0] = dCreateBox (space,sides[0],sides[1],sides[2]); } else if (cmd == 'c') { sides[0] *= 0.5; dMassSetCapsule (&m,DENSITY,3,sides[0],sides[1]); obj[i].geom[0] = dCreateCapsule (space,sides[0],sides[1]); } /* // cylinder option not yet implemented else if (cmd == 'l') { sides[1] *= 0.5; dMassSetCapsule (&m,DENSITY,3,sides[0],sides[1]); obj[i].geom[0] = dCreateCylinder (space,sides[0],sides[1]); } */ else if (cmd == 's') { sides[0] *= 0.5; dMassSetSphere (&m,DENSITY,sides[0]); obj[i].geom[0] = dCreateSphere (space,sides[0]); } else if (cmd == 'x') { setBody = true; // start accumulating masses for the composite geometries dMass m2; dMassSetZero (&m); dReal dpos[GPB][3]; // delta-positions for composite geometries dMatrix3 drot[GPB]; // set random delta positions for (j=0; j= num) selected = 0; if (selected < 0) selected = 0; } else if (cmd == 'd' && selected >= 0 && selected < num) { dBodyDisable (obj[selected].body); } else if (cmd == 'e' && selected >= 0 && selected < num) { dBodyEnable (obj[selected].body); } else if (cmd == 'a') { show_aabb ^= 1; } else if (cmd == 't') { show_contacts ^= 1; } else if (cmd == 'r') { random_pos ^= 1; } } // draw a geom void drawGeom (dGeomID g, const dReal *pos, const dReal *R, int show_aabb) { if (!g) return; if (!pos) pos = dGeomGetPosition (g); if (!R) R = dGeomGetRotation (g); int type = dGeomGetClass (g); if (type == dBoxClass) { dVector3 sides; dGeomBoxGetLengths (g,sides); dsDrawBox (pos,R,sides); } else if (type == dSphereClass) { dsDrawSphere (pos,R,dGeomSphereGetRadius (g)); } else if (type == dCapsuleClass) { dReal radius,length; dGeomCapsuleGetParams (g,&radius,&length); dsDrawCapsule (pos,R,length,radius); } else if (type == dConvexClass) { //dVector3 sides={0.50,0.50,0.50}; dsDrawConvex(pos,R,planes, planecount, points, pointcount, polygons); } /* // cylinder option not yet implemented else if (type == dCylinderClass) { dReal radius,length; dGeomCylinderGetParams (g,&radius,&length); dsDrawCylinder (pos,R,length,radius); } */ if (show_aabb) { // draw the bounding box for this geom dReal aabb[6]; dGeomGetAABB (g,aabb); dVector3 bbpos; for (int i=0; i<3; i++) bbpos[i] = 0.5*(aabb[i*2] + aabb[i*2+1]); dVector3 bbsides; for (int j=0; j<3; j++) bbsides[j] = aabb[j*2+1] - aabb[j*2]; dMatrix3 RI; dRSetIdentity (RI); dsSetColorAlpha (1,0,0,0.5); dsDrawBox (bbpos,RI,bbsides); } } // simulation loop static void simLoop (int pause) { dsSetColor (0,0,2); dSpaceCollide (space,0,&nearCallback); if (!pause) dWorldStep (world,0.05); //if (!pause) dWorldStepFast (world,0.05, 1); // remove all contact joints dJointGroupEmpty (contactgroup); dsSetColor (1,1,0); dsSetTexture (DS_WOOD); for (int i=0; i #include #include #include #include #include #include "texturepath.h" #ifdef dDOUBLE #define dsDrawBox dsDrawBoxD #define dsDrawCylinder dsDrawCylinderD #endif using namespace std; dWorld *world; dSpace *space; dPlane *ground; dBody *kbody; dBox *kbox; dJointGroup joints; dCylinder *kpole; dBody *matraca; dBox *matraca_geom; dHingeJoint *hinge; struct Box { dBody body; dBox geom; Box() : body(*world), geom(*space, 0.2, 0.2, 0.2) { dMass mass; mass.setBox(10, 0.2, 0.2, 0.2); body.setMass(mass); geom.setData(this); geom.setBody(body); } void draw() const { dVector3 lengths; geom.getLengths(lengths); dsSetTexture(DS_WOOD); dsSetColor(0,1,0); dsDrawBox(geom.getPosition(), geom.getRotation(), lengths); } }; set boxes; set to_remove; void dropBox() { Box *box = new Box(); dReal px = (rand() / float(RAND_MAX)) * 2 - 1; dReal py = (rand() / float(RAND_MAX)) * 2 - 1; dReal pz = 2.5; box->body.setPosition(px, py, pz); boxes.insert(box); } void queueRemoval(dGeomID g) { Box *b = (Box*)dGeomGetData(g); to_remove.insert(b); } void removeQueued() { while (!to_remove.empty()) { Box *b = *to_remove.begin(); to_remove.erase(b); boxes.erase(b); delete b; } } void nearCallback(void *, dGeomID g1, dGeomID g2) { if (g1 == ground->id()) { queueRemoval(g2); return; } if (g2 == ground->id()) { queueRemoval(g1); return; } dBodyID b1 = dGeomGetBody(g1); dBodyID b2 = dGeomGetBody(g2); if (b1 && b2 && dAreConnectedExcluding(b1, b2, dJointTypeContact)) return; const int MAX_CONTACTS = 10; dContact contact[MAX_CONTACTS]; int n = dCollide(g1, g2, MAX_CONTACTS, &contact[0].geom, sizeof(dContact)); for (int i=0; i 2*M_PI) t = 0; dVector3 next_pos = { dCos(t), dSin(t), REAL(0.5)}; dVector3 vel; // vel = (next_pos - cur_pos) / timestep dSubtractVectors3(vel, next_pos, kbody->getPosition()); dScaleVector3(vel, 1/timestep); kbody->setLinearVel(vel); // end of hard-coded animation space->collide(0, nearCallback); removeQueued(); world->quickStep(timestep); joints.clear(); } dVector3 lengths; // the moving platform kbox->getLengths(lengths); dsSetTexture(DS_WOOD); dsSetColor(.3, .3, 1); dsDrawBox(kbox->getPosition(), kbox->getRotation(), lengths); dReal length, radius; kpole->getParams(&radius, &length); dsSetTexture(DS_CHECKERED); dsSetColor(1, 1, 0); dsDrawCylinder(kpole->getPosition(), kpole->getRotation(), length, radius); // the matraca matraca_geom->getLengths(lengths); dsSetColor(1,0,0); dsSetTexture(DS_WOOD); dsDrawBox(matraca_geom->getPosition(), matraca_geom->getRotation(), lengths); // and the boxes for_each(boxes.begin(), boxes.end(), mem_fun(&Box::draw)); } void command(int c) { switch (c) { case ' ': dropBox(); break; } } int main(int argc, char **argv) { dInitODE(); // setup pointers to drawstuff callback functions dsFunctions fn; fn.version = DS_VERSION; fn.start = 0; fn.step = &simLoop; fn.command = &command; fn.stop = 0; fn.path_to_textures = DRAWSTUFF_TEXTURE_PATH; cout << endl << "*** Press SPACE to drop boxes **" << endl; space = new dSimpleSpace(); ground = new dPlane(*space, 0, 0, 1, 0); world = new dWorld; world->setGravity(0, 0, -.5); kbody = new dBody(*world); kbody->setKinematic(); const dReal kx = 1, ky = 0, kz = .5; kbody->setPosition(kx, ky, kz); kbox = new dBox(*space, 3, 3, .5); kbox->setBody(*kbody); kpole = new dCylinder(*space, .125, 1.5); kpole->setBody(*kbody); dGeomSetOffsetPosition(kpole->id(), 0, 0, 0.8); matraca = new dBody(*world); matraca->setPosition(kx+0, ky+1, kz+1); matraca_geom = new dBox(*space, 0.5, 2, 0.75); matraca_geom->setBody(*matraca); dMass mass; mass.setBox(1, 0.5, 2, 0.75); matraca->setMass(mass); hinge = new dHingeJoint(*world); hinge->attach(*kbody, *matraca); hinge->setAnchor(kx, ky, kz+1); hinge->setAxis(0, 0, 1); dsSimulationLoop (argc, argv, 640, 480, &fn); dCloseODE(); } ode-0.16/ode/demo/demo_tracks.cpp0000664000175200017520000003433313403272463013642 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ //#include #include #include #include "texturepath.h" #ifdef dDOUBLE #define dsDrawSphere dsDrawSphereD #define dsDrawBox dsDrawBoxD #define dsDrawTriangle dsDrawTriangleD #define dsDrawLine dsDrawLineD #endif const dReal ball_radius = 0.4; const dReal balls_sep = 2; // separation between the balls /* Choose one test case */ #define TEST_CASE 0 #if TEST_CASE == 0 const dReal track_len = 10; const dReal track_height = 1; const dReal track_width = 0.1; const dReal track_gauge = 1; const dReal track_elevation = 2; const dReal track_angle = 80 * M_PI/180.; const dReal track_incl = 10 * M_PI/180.; #elif TEST_CASE == 1 const dReal track_len = 10; const dReal track_height = 1; const dReal track_width = 0.1; const dReal track_gauge = 1.9*ball_radius; const dReal track_elevation = 2; const dReal track_angle = 0 * M_PI/180.; const dReal track_incl = 10 * M_PI/180.; #elif TEST_CASE == 2 const dReal track_len = 10; const dReal track_height = 1; const dReal track_width = 0.1; const dReal track_gauge = 1.9*ball_radius; const dReal track_elevation = 2; const dReal track_angle = 15 * M_PI/180.; const dReal track_incl = 10 * M_PI/180.; #elif TEST_CASE == 3 const dReal track_len = 10; const dReal track_height = .7; const dReal track_width = 0.1; const dReal track_gauge = track_height*1.1; const dReal track_elevation = 2; const dReal track_angle = 90 * M_PI/180.; const dReal track_incl = 10 * M_PI/180.; #else #error "TEST_CAST to a valid value!" #endif dWorldID world; dSpaceID space; dJointGroupID contact_group; dGeomID ground; dGeomID ball1_geom, ball2_geom; dTriMeshDataID mesh_data; dGeomID mesh_geom; dBodyID ball1_body, ball2_body; const unsigned n_box_verts = 8; dVector3 box_verts[n_box_verts] = { {-track_len/2, -track_width/2, track_height/2}, // 0 { track_len/2, -track_width/2, track_height/2}, // 1 { track_len/2, track_width/2, track_height/2}, // 2 {-track_len/2, track_width/2, track_height/2}, // 3 { track_len/2, -track_width/2, -track_height/2}, // 4 {-track_len/2, -track_width/2, -track_height/2}, // 5 {-track_len/2, track_width/2, -track_height/2}, // 6 { track_len/2, track_width/2, -track_height/2} // 7 }; const unsigned n_box_faces = 12; dTriIndex box_faces[n_box_faces * 3] = { 0, 1, 2, 0, 2, 3, 1, 4, 7, 1, 7, 2, 4, 5, 6, 4, 6, 7, 5, 0, 3, 5, 3, 6, 3, 2, 7, 3, 7, 6, 0, 5, 4, 0, 4, 1 }; const unsigned n_track_verts = n_box_verts * 2; const unsigned n_track_faces = n_box_faces * 2; dVector3 track_verts[n_track_verts]; dTriIndex track_faces[n_track_faces * 3]; void resetBall(dBodyID b, unsigned idx) { dBodySetPosition(b, 0.5*track_len*cos(track_incl) // Z - 0.5*track_height*sin(track_incl) - ball_radius, // X balls_sep*idx, // Y track_elevation + ball_radius// Z + 0.5*track_len*sin(track_incl) + 0.5*track_height*cos(track_incl)); dMatrix3 r = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0}; dBodySetRotation(b, r); dBodySetLinearVel(b, 0, 0, 0); dBodySetAngularVel(b, 0, 0, 0); } void resetSim() { resetBall(ball1_body, 0); resetBall(ball2_body, 1); } void start() { dAllocateODEDataForThread(dAllocateMaskAll); world = dWorldCreate(); dWorldSetGravity (world,0,0,-9.8); contact_group = dJointGroupCreate(0); space = dSimpleSpaceCreate (0); // first, the ground plane // it has to coincide with the plane we have in drawstuff ground = dCreatePlane(space, 0, 0, 1, 0); // now a ball dMass m; dMassSetSphere(&m, 0.1, ball_radius); ball1_geom = dCreateSphere(space, ball_radius); ball1_body = dBodyCreate(world); dGeomSetBody(ball1_geom, ball1_body); dBodySetMass(ball1_body, &m); ball2_geom = dCreateSphere(space, ball_radius); ball2_body = dBodyCreate(world); dGeomSetBody(ball2_geom, ball2_body); dBodySetMass(ball2_body, &m); // tracks made out of boxes dGeomID trk; dMatrix3 r1, r2, r3; dVector3 ro = {0, -(0.5*track_gauge + 0.5*track_width), track_elevation}; dMatrix3 s1, s2, s3; dVector3 so = {0, 0.5*track_gauge + 0.5*track_width, track_elevation}; dRFromAxisAndAngle(r1, 1, 0, 0, track_angle); dRFromAxisAndAngle(r2, 0, 1, 0, -track_incl); dMultiply0_333(r3, r2, r1); dRFromAxisAndAngle(s1, 1, 0, 0, -track_angle); dRFromAxisAndAngle(s2, 0, 1, 0, -track_incl); dMultiply0_333(s3, s2, s1); trk = dCreateBox(space, track_len, track_width, track_height); dGeomSetPosition(trk, ro[0], ro[1] + balls_sep, ro[2]); dGeomSetRotation(trk, r3); trk = dCreateBox(space, track_len, track_width, track_height); dGeomSetPosition(trk, so[0], so[1] + balls_sep, so[2]); dGeomSetRotation(trk, s3); // tracks made out of trimesh for (unsigned i=0; i 0.99 // about 8 degrees of difference && dCalcPointsDistance3(contacts[i].geom.pos, contacts[j].geom.pos) < epsilon) { // they are too close closest_point = j; //clog << "found close points: " << j << " and " << i << endl; break; } } if (closest_point != i) { // we discard one of the points if (contacts[i].geom.depth > contacts[closest_point].geom.depth) // the new point is deeper, copy it over closest_point contacts[closest_point] = contacts[i]; } else contacts[new_n++] = contacts[i]; // the point is preserved } //clog << "reduced from " << n << " to " << new_n << endl; n = new_n; for (int i=0; i #include #include #include #include "texturepath.h" #ifdef _MSC_VER #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints #endif // select correct drawing functions #ifdef dDOUBLE #define dsDrawBox dsDrawBoxD #endif // physics parameters #define BOX1_LENGTH 2 // Size along the X axis #define BOX1_WIDTH 1 // Size along the Y axis #define BOX1_HEIGHT 0.4 // Size along the Z axis (up) since gravity is (0,0,-10) #define BOX2_LENGTH 0.2 #define BOX2_WIDTH 0.1 #define BOX2_HEIGHT 0.4 #define Mass1 10 #define Mass2 0.1 #define PRISMATIC_ONLY 1 #define ROTOIDE_ONLY 2 int flag = 0; //camera view static float xyz[3] = {2.0f,-3.5f,2.0000f}; static float hpr[3] = {90.000f,-25.5000f,0.0000f}; //world,space,body & geom static dWorldID world; static dSpaceID space; static dSpaceID box1_space; static dBodyID box1_body[1]; static dBodyID box2_body[1]; static dJointID joint[1]; static dJointGroupID contactgroup; static dGeomID ground; static dGeomID box1[1]; static dGeomID box2[1]; //collision detection static void nearCallback (void *, dGeomID o1, dGeomID o2) { int i,n; dBodyID b1 = dGeomGetBody(o1); dBodyID b2 = dGeomGetBody(o2); if (b1 && b2 && dAreConnectedExcluding (b1,b2,dJointTypeContact)) return; const int N = 10; dContact contact[N]; n = dCollide (o1,o2,N,&contact[0].geom,sizeof(dContact)); if (n > 0) { for (i=0; i= 2 ) { for (int i=1; i < argc; ++i) { if ( 0 == strcmp("-h", argv[i]) || 0 == strcmp("--help", argv[i]) ) Help(argv); if (!flag && (0 == strcmp("-p", argv[i]) ||0 == strcmp("--prismatic-only", argv[i])) ) flag = PRISMATIC_ONLY; if (!flag && (0 == strcmp("-r", argv[i]) || 0 == strcmp("--rotoide-only", argv[i])) ) flag = ROTOIDE_ONLY; if (0 == strcmp("-t", argv[i]) || 0 == strcmp("--texture-path", argv[i])) { int j = i+1; if ( j >= argc || // Check if we have enough arguments argv[j][0] == '\0' || // We should have a path here argv[j][0] == '-' ) // We should have a path not a command line Help(argv); else fn.path_to_textures = argv[++i]; // Increase i since we use this argument } } } dInitODE2(0); // create world world = dWorldCreate(); space = dHashSpaceCreate (0); contactgroup = dJointGroupCreate (0); dWorldSetGravity (world,0,0,-10); ground = dCreatePlane (space,0,0,1,0); //create two boxes dMass m; box1_body[0] = dBodyCreate (world); dMassSetBox (&m,1,BOX1_LENGTH,BOX1_WIDTH,BOX1_HEIGHT); dMassAdjust (&m,Mass1); dBodySetMass (box1_body[0],&m); box1[0] = dCreateBox (0,BOX1_LENGTH,BOX1_WIDTH,BOX1_HEIGHT); dGeomSetBody (box1[0],box1_body[0]); box2_body[0] = dBodyCreate (world); dMassSetBox (&m,10,BOX2_LENGTH,BOX2_WIDTH,BOX2_HEIGHT); dMassAdjust (&m,Mass2); dBodySetMass (box2_body[0],&m); box2[0] = dCreateBox (0,BOX2_LENGTH,BOX2_WIDTH,BOX2_HEIGHT); dGeomSetBody (box2[0],box2_body[0]); //set the initial positions of body1 and body2 dMatrix3 R; dRSetIdentity(R); dBodySetPosition (box1_body[0],0,0,BOX1_HEIGHT/2.0); dBodySetRotation (box1_body[0], R); dBodySetPosition (box2_body[0], 2.1, 0.0, BOX2_HEIGHT/2.0); dBodySetRotation (box2_body[0], R); //set PR joint joint[0] = dJointCreatePR(world,0); dJointAttach (joint[0],box1_body[0],box2_body[0]); switch (flag) { case PRISMATIC_ONLY: dJointSetPRAnchor (joint[0], 2.1, 0.0, BOX2_HEIGHT/2.0); dJointSetPRParam (joint[0],dParamLoStop, -0.5); dJointSetPRParam (joint[0],dParamHiStop, 1.5); break; case ROTOIDE_ONLY: dJointSetPRAnchor (joint[0], 0.0, 0.0, BOX2_HEIGHT/2.0); dJointSetPRParam (joint[0],dParamLoStop, 0.0); dJointSetPRParam (joint[0],dParamHiStop, 0.0); break; default: dJointSetPRAnchor (joint[0], 1.1, 0.0, BOX2_HEIGHT/2.0); dJointSetPRParam (joint[0],dParamLoStop, -0.5); dJointSetPRParam (joint[0],dParamHiStop, 1.5); break; } dJointSetPRAxis1(joint[0],1,0,0); dJointSetPRAxis2(joint[0],0,0,1); // We position the 2 body // The position of the rotoide joint is on the second body so it can rotate on itself // and move along the X axis. // With this anchor // - A force in X will move only the body 2 inside the low and hi limit // of the prismatic // - A force in Y will make the 2 bodies to rotate around on the plane box1_space = dSimpleSpaceCreate (space); dSpaceSetCleanup (box1_space,0); dSpaceAdd(box1_space,box1[0]); // run simulation dsSimulationLoop (argc,argv,400,300,&fn); dJointGroupDestroy (contactgroup); dSpaceDestroy (space); dWorldDestroy (world); dCloseODE(); return 0; } ode-0.16/ode/demo/demo_cylvssphere.cpp0000664000175200017520000001477013403272463014725 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ // Test for cylinder vs sphere, by Bram Stolk #include #include #ifdef HAVE_UNISTD_H #include #endif #include #include #include "texturepath.h" #ifdef _MSC_VER #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints #endif // dynamics and collision objects (chassis, 3 wheels, environment) static dWorldID world; static dSpaceID space; static dBodyID cylbody; static dGeomID cylgeom; static dBodyID sphbody; static dGeomID sphgeom; static dJointGroupID contactgroup; static bool show_contacts = true; #define CYLRADIUS 0.6 #define CYLLENGTH 2.0 #define SPHERERADIUS 0.5 #ifdef dDOUBLE #define dsDrawBox dsDrawBoxD #define dsDrawLine dsDrawLineD #endif // this is called by dSpaceCollide when two objects in space are // potentially colliding. static void nearCallback (void *data, dGeomID o1, dGeomID o2) { assert(o1); assert(o2); if (dGeomIsSpace(o1) || dGeomIsSpace(o2)) { fprintf(stderr,"testing space %p %p\n", (void*)o1, (void*)o2); // colliding a space with something dSpaceCollide2(o1,o2,data,&nearCallback); // Note we do not want to test intersections within a space, // only between spaces. return; } const int N = 32; dContact contact[N]; int n = dCollide (o1,o2,N,&(contact[0].geom),sizeof(dContact)); if (n > 0) { for (int i=0; i #include #include "texturepath.h" #include "bunny_geom.h" #include "convex_bunny_geom.h" #ifdef _MSC_VER #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints #endif // select correct drawing functions #ifdef dDOUBLE #define dsDrawBox dsDrawBoxD #define dsDrawSphere dsDrawSphereD #define dsDrawCylinder dsDrawCylinderD #define dsDrawCapsule dsDrawCapsuleD #define dsDrawLine dsDrawLineD #define dsDrawTriangle dsDrawTriangleD #define dsDrawConvex dsDrawConvexD #endif // some constants #define NUM 200 // max number of objects #define DENSITY (5.0) // density of all objects #define GPB 3 // maximum number of geometries per body #define MAX_CONTACTS 64 // maximum number of contact points per body // dynamics and collision objects struct MyObject { dBodyID body; // the body dGeomID geom[GPB]; // geometries representing this body }; static int num=0; // number of objects in simulation static int nextobj=0; // next object to recycle if num==NUM static dWorldID world; static dSpaceID space; static MyObject obj[NUM]; static dJointGroupID contactgroup; static int selected = -1; // selected object static int show_aabb = 0; // show geom AABBs? static int show_contacts = 0; // show contact points? static int random_pos = 1; // drop objects from random position? typedef dReal dVector3R[3]; // this is called by dSpaceCollide when two objects in space are // potentially colliding. static void nearCallback( void *, dGeomID o1, dGeomID o2 ) { int i; // if (o1->body && o2->body) return; // exit without doing anything if the two bodies are connected by a joint dBodyID b1 = dGeomGetBody( o1 ); dBodyID b2 = dGeomGetBody( o2 ); if ( b1 && b2 && dAreConnectedExcluding( b1,b2,dJointTypeContact ) ) return; dContact contact[MAX_CONTACTS]; // up to MAX_CONTACTS contacts per box-box for ( i=0; i= 'A' && c <= 'Z' ) return c - ( 'a'-'A' ); else return c; } // called when a key pressed static void command( int cmd ) { int i,k; dReal sides[3]; dMass m; cmd = locase( cmd ); if ( cmd == 'v' || cmd == 'b' || cmd == 'c' || cmd == 's' || cmd == 'y') { if ( num < NUM ) { i = num; num++; } else { i = nextobj; nextobj++; if ( nextobj >= num ) nextobj = 0; // destroy the body and geoms for slot i dBodyDestroy( obj[i].body ); for ( k=0; k < GPB; k++ ) { if ( obj[i].geom[k] ) dGeomDestroy( obj[i].geom[k] ); } memset( &obj[i],0,sizeof( obj[i] ) ); } obj[i].body = dBodyCreate( world ); for ( k=0; k<3; k++ ) sides[k] = dRandReal()*0.5+0.1; dMatrix3 R; if ( random_pos ) { dBodySetPosition( obj[i].body, dRandReal()*2-1,dRandReal()*2-1,dRandReal()+3 ); dRFromAxisAndAngle( R,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0, dRandReal()*2.0-1.0,dRandReal()*10.0-5.0 ); } else { dReal maxheight = 0; for ( k=0; k maxheight ) maxheight = pos[2]; } dBodySetPosition( obj[i].body, 0,0,maxheight+1 ); dRFromAxisAndAngle( R,0,0,1,dRandReal()*10.0-5.0 ); } dBodySetRotation( obj[i].body,R ); dBodySetData( obj[i].body,( void* )( dsizeint )i ); if ( cmd == 'b' ) { dMassSetBox( &m,DENSITY,sides[0],sides[1],sides[2] ); obj[i].geom[0] = dCreateBox( space,sides[0],sides[1],sides[2] ); } else if ( cmd == 'c' ) { sides[0] *= 0.5; dMassSetCapsule( &m,DENSITY,3,sides[0],sides[1] ); obj[i].geom[0] = dCreateCapsule( space,sides[0],sides[1] ); } else if (cmd == 'y') { dMassSetCylinder (&m,DENSITY,3,sides[0],sides[1]); obj[i].geom[0] = dCreateCylinder (space,sides[0],sides[1]); } else if ( cmd == 's' ) { sides[0] *= 0.5; dMassSetSphere( &m,DENSITY,sides[0] ); obj[i].geom[0] = dCreateSphere( space,sides[0] ); } else if ( cmd == 'v' ) { obj[i].geom[0] = dCreateConvex( space, convexBunnyPlanes, convexBunnyPlaneCount, convexBunnyPoints, convexBunnyPointCount, convexBunnyPolygons ); /// Use equivalent TriMesh to set mass dTriMeshDataID new_tmdata = dGeomTriMeshDataCreate(); dGeomTriMeshDataBuildSingle( new_tmdata, &Vertices[0], 3 * sizeof( float ), VertexCount, ( dTriIndex* )&Indices[0], IndexCount, 3 * sizeof( dTriIndex ) ); dGeomTriMeshDataPreprocess2( new_tmdata, (1U << dTRIDATAPREPROCESS_BUILD_FACE_ANGLES), NULL ); dGeomID triMesh = dCreateTriMesh( 0, new_tmdata, 0, 0, 0 ); dMassSetTrimesh( &m, DENSITY, triMesh ); dGeomDestroy( triMesh ); dGeomTriMeshDataDestroy( new_tmdata ); printf( "mass at %f %f %f\n", m.c[0], m.c[1], m.c[2] ); dGeomSetPosition( obj[i].geom[0], -m.c[0], -m.c[1], -m.c[2] ); dMassTranslate( &m, -m.c[0], -m.c[1], -m.c[2] ); } for ( k=0; k < GPB; k++ ) { if ( obj[i].geom[k] ) dGeomSetBody( obj[i].geom[k],obj[i].body ); } dBodySetMass( obj[i].body,&m ); } if ( cmd == ' ' ) { selected++; if ( selected >= num ) selected = 0; if ( selected < 0 ) selected = 0; } else if ( cmd == 'd' && selected >= 0 && selected < num ) { dBodyDisable( obj[selected].body ); } else if ( cmd == 'e' && selected >= 0 && selected < num ) { dBodyEnable( obj[selected].body ); } else if ( cmd == 'a' ) { show_aabb ^= 1; } else if ( cmd == 't' ) { show_contacts ^= 1; } else if ( cmd == 'r' ) { random_pos ^= 1; } } // draw a geom void drawGeom( dGeomID g, const dReal *pos, const dReal *R, int show_aabb ) { if ( !g ) return; if ( !pos ) pos = dGeomGetPosition( g ); if ( !R ) R = dGeomGetRotation( g ); int type = dGeomGetClass( g ); if ( type == dBoxClass ) { dVector3 sides; dGeomBoxGetLengths( g,sides ); dsDrawBox( pos,R,sides ); } else if ( type == dSphereClass ) { dsDrawSphere( pos,R,dGeomSphereGetRadius( g ) ); } else if (type == dCylinderClass) { dReal radius,length; dGeomCylinderGetParams (g,&radius,&length); dsDrawCylinder (pos,R,length,radius); } else if ( type == dCapsuleClass ) { dReal radius,length; dGeomCapsuleGetParams( g,&radius,&length ); dsDrawCapsule( pos,R,length,radius ); } else if ( type == dConvexClass ) { dsDrawConvex( pos,R, convexBunnyPlanes, convexBunnyPlaneCount, convexBunnyPoints, convexBunnyPointCount, convexBunnyPolygons ); } if ( show_aabb ) { // draw the bounding box for this geom dReal aabb[6]; dGeomGetAABB( g,aabb ); dVector3 bbpos; for ( int i=0; i<3; i++ ) bbpos[i] = 0.5*( aabb[i*2] + aabb[i*2+1] ); dVector3 bbsides; for ( int j=0; j<3; j++ ) bbsides[j] = aabb[j*2+1] - aabb[j*2]; dMatrix3 RI; dRSetIdentity( RI ); dsSetColorAlpha( 1,0,0,0.5 ); dsDrawBox( bbpos,RI,bbsides ); } } // simulation loop static void simLoop( int pause ) { dsSetColor( 0,0,2 ); dSpaceCollide( space,0,&nearCallback ); if ( !pause ) dWorldQuickStep( world,0.05 ); for ( int j = 0; j < dSpaceGetNumGeoms( space ); j++ ) { dSpaceGetGeom( space, j ); } // remove all contact joints dJointGroupEmpty( contactgroup ); dsSetColor( 1,1,0 ); dsSetTexture( DS_WOOD ); for ( int i=0; i1 is bad. other tests just show graphical results which you must verify visually. */ #include #include #include #include "texturepath.h" #ifdef _MSC_VER #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints #endif // select correct drawing functions #ifdef dDOUBLE #define dsDrawBox dsDrawBoxD #endif // some constants #define NUM_JOINTS 10 // number of joints to test (the `xx' value) #define SIDE (0.5f) // side length of a box - don't change this #define MASS (1.0) // mass of a box #define STEPSIZE 0.05 static const dVector3 xunit = { 1, 0, 0 }, zunit = { 0, 0, 1 }; // dynamics objects static dWorldID world; static dBodyID body[2]; static dJointID joint; // data from the command line arguments static int cmd_test_num = -1; static int cmd_interactive = 0; static int cmd_graphics = 1; static char *cmd_path_to_textures = NULL; static int cmd_occasional_error = 0; // perturb occasionally // info about the current test struct TestInfo; static int test_num = 0; // number of the current test static int iteration = 0; static int max_iterations = 0; static dReal max_error = 0; //**************************************************************************** // utility stuff static dReal length (dVector3 a) { return dSqrt (a[0]*a[0] + a[1]*a[1] + a[2]*a[2]); } // get the max difference between a 3x3 matrix and the identity dReal cmpIdentity (const dMatrix3 A) { dMatrix3 I; dSetZero (I,12); I[0] = 1; I[5] = 1; I[10] = 1; return dMaxDifference (A,I,3,3); } //**************************************************************************** // test world construction and utilities void constructWorldForTest (dReal gravity, int bodycount, /* body 1 pos */ dReal pos1x, dReal pos1y, dReal pos1z, /* body 2 pos */ dReal pos2x, dReal pos2y, dReal pos2z, /* body 1 rotation axis */ dReal ax1x, dReal ax1y, dReal ax1z, /* body 1 rotation axis */ dReal ax2x, dReal ax2y, dReal ax2z, /* rotation angles */ dReal a1, dReal a2) { // create world world = dWorldCreate(); dWorldSetERP (world,0.2); dWorldSetCFM (world,1e-6); dWorldSetGravity (world,0,0,gravity); dMass m; dMassSetBox (&m,1,SIDE,SIDE,SIDE); dMassAdjust (&m,MASS); body[0] = dBodyCreate (world); dBodySetMass (body[0],&m); dBodySetPosition (body[0], pos1x, pos1y, pos1z); dQuaternion q; dQFromAxisAndAngle (q,ax1x,ax1y,ax1z,a1); dBodySetQuaternion (body[0],q); if (bodycount==2) { body[1] = dBodyCreate (world); dBodySetMass (body[1],&m); dBodySetPosition (body[1], pos2x, pos2y, pos2z); dQFromAxisAndAngle (q,ax2x,ax2y,ax2z,a2); dBodySetQuaternion (body[1],q); } else body[1] = 0; } // add an oscillating torque to body 0 void addOscillatingTorque (dReal tscale) { static dReal a=0; dBodyAddTorque (body[0],tscale*cos(2*a),tscale*cos(2.7183*a), tscale*cos(1.5708*a)); a += 0.01; } void addOscillatingTorqueAbout(dReal tscale, dReal x, dReal y, dReal z) { static dReal a=0; dBodyAddTorque (body[0], tscale*cos(a) * x, tscale*cos(a) * y, tscale * cos(a) * z); a += 0.02; } // damp the rotational motion of body 0 a bit void dampRotationalMotion (dReal kd) { const dReal *w = dBodyGetAngularVel (body[0]); dBodyAddTorque (body[0],-kd*w[0],-kd*w[1],-kd*w[2]); } // add a spring force to keep the bodies together, otherwise they may fly // apart with some joints. void addSpringForce (dReal ks) { const dReal *p1 = dBodyGetPosition (body[0]); const dReal *p2 = dBodyGetPosition (body[1]); dBodyAddForce (body[0],ks*(p2[0]-p1[0]),ks*(p2[1]-p1[1]),ks*(p2[2]-p1[2])); dBodyAddForce (body[1],ks*(p1[0]-p2[0]),ks*(p1[1]-p2[1]),ks*(p1[2]-p2[2])); } // add an oscillating Force to body 0 void addOscillatingForce (dReal fscale) { static dReal a=0; dBodyAddForce (body[0],fscale*cos(2*a),fscale*cos(2.7183*a), fscale*cos(1.5708*a)); a += 0.01; } //**************************************************************************** // stuff specific to the tests // // 0xx : fixed // 1xx : ball and socket // 2xx : hinge // 3xx : slider // 4xx : hinge 2 // 5xx : contact // 6xx : amotor // 7xx : universal joint // 8xx : PR joint (Prismatic and Rotoide) // setup for the given test. return 0 if there is no such test int setupTest (int n) { switch (n) { // ********** fixed joint case 0: { // 2 body constructWorldForTest (0,2, 0.5*SIDE,0.5*SIDE,1, -0.5*SIDE,-0.5*SIDE,1, 1,1,0, 1,1,0, 0.25*M_PI,0.25*M_PI); joint = dJointCreateFixed (world,0); dJointAttach (joint,body[0],body[1]); dJointSetFixed (joint); return 1; } case 1: { // 1 body to static env constructWorldForTest (0,1, 0.5*SIDE,0.5*SIDE,1, 0,0,0, 1,0,0, 1,0,0, 0,0); joint = dJointCreateFixed (world,0); dJointAttach (joint,body[0],0); dJointSetFixed (joint); return 1; } case 2: { // 2 body with relative rotation constructWorldForTest (0,2, 0.5*SIDE,0.5*SIDE,1, -0.5*SIDE,-0.5*SIDE,1, 1,1,0, 1,1,0, 0.25*M_PI,-0.25*M_PI); joint = dJointCreateFixed (world,0); dJointAttach (joint,body[0],body[1]); dJointSetFixed (joint); return 1; } case 3: { // 1 body to static env with relative rotation constructWorldForTest (0,1, 0.5*SIDE,0.5*SIDE,1, 0,0,0, 1,0,0, 1,0,0, 0.25*M_PI,0); joint = dJointCreateFixed (world,0); dJointAttach (joint,body[0],0); dJointSetFixed (joint); return 1; } // ********** hinge joint case 200: // 2 body constructWorldForTest (0,2, 0.5*SIDE,0.5*SIDE,1, -0.5*SIDE,-0.5*SIDE,1, 1,1,0, 1,1,0, 0.25*M_PI,0.25*M_PI); joint = dJointCreateHinge (world,0); dJointAttach (joint,body[0],body[1]); dJointSetHingeAnchor (joint,0,0,1); dJointSetHingeAxis (joint,1,-1,1.41421356); return 1; case 220: // hinge angle polarity test case 221: // hinge angle rate test constructWorldForTest (0,2, 0.5*SIDE,0.5*SIDE,1, -0.5*SIDE,-0.5*SIDE,1, 1,0,0, 1,0,0, 0,0); joint = dJointCreateHinge (world,0); dJointAttach (joint,body[0],body[1]); dJointSetHingeAnchor (joint,0,0,1); dJointSetHingeAxis (joint,0,0,1); max_iterations = 50; return 1; case 230: // hinge motor rate (and polarity) test case 231: // ...with stops constructWorldForTest (0,2, 0.5*SIDE,0.5*SIDE,1, -0.5*SIDE,-0.5*SIDE,1, 1,0,0, 1,0,0, 0,0); joint = dJointCreateHinge (world,0); dJointAttach (joint,body[0],body[1]); dJointSetHingeAnchor (joint,0,0,1); dJointSetHingeAxis (joint,0,0,1); dJointSetHingeParam (joint,dParamFMax,1); if (n==231) { dJointSetHingeParam (joint,dParamLoStop,-0.5); dJointSetHingeParam (joint,dParamHiStop,0.5); } return 1; case 250: // limit bounce test (gravity down) case 251: { // ...gravity up constructWorldForTest ((n==251) ? 0.1 : -0.1, 2, 0.5*SIDE,0,1+0.5*SIDE, -0.5*SIDE,0,1-0.5*SIDE, 1,0,0, 1,0,0, 0,0); joint = dJointCreateHinge (world,0); dJointAttach (joint,body[0],body[1]); dJointSetHingeAnchor (joint,0,0,1); dJointSetHingeAxis (joint,0,1,0); dJointSetHingeParam (joint,dParamLoStop,-0.9); dJointSetHingeParam (joint,dParamHiStop,0.7854); dJointSetHingeParam (joint,dParamBounce,0.5); // anchor 2nd body with a fixed joint dJointID j = dJointCreateFixed (world,0); dJointAttach (j,body[1],0); dJointSetFixed (j); return 1; } // ********** slider case 300: // 2 body constructWorldForTest (0,2, 0,0,1, 0.2,0.2,1.2, 0,0,1, -1,1,0, 0,0.25*M_PI); joint = dJointCreateSlider (world,0); dJointAttach (joint,body[0],body[1]); dJointSetSliderAxis (joint,1,1,1); return 1; case 320: // slider angle polarity test case 321: // slider angle rate test constructWorldForTest (0,2, 0,0,1, 0,0,1.2, 1,0,0, 1,0,0, 0,0); joint = dJointCreateSlider (world,0); dJointAttach (joint,body[0],body[1]); dJointSetSliderAxis (joint,0,0,1); max_iterations = 50; return 1; case 330: // slider motor rate (and polarity) test case 331: // ...with stops constructWorldForTest (0, 2, 0,0,1, 0,0,1.2, 1,0,0, 1,0,0, 0,0); joint = dJointCreateSlider (world,0); dJointAttach (joint,body[0],body[1]); dJointSetSliderAxis (joint,0,0,1); dJointSetSliderParam (joint,dParamFMax,100); if (n==331) { dJointSetSliderParam (joint,dParamLoStop,-0.4); dJointSetSliderParam (joint,dParamHiStop,0.4); } return 1; case 350: // limit bounce tests case 351: { constructWorldForTest ((n==351) ? 0.1 : -0.1, 2, 0,0,1, 0,0,1.2, 1,0,0, 1,0,0, 0,0); joint = dJointCreateSlider (world,0); dJointAttach (joint,body[0],body[1]); dJointSetSliderAxis (joint,0,0,1); dJointSetSliderParam (joint,dParamLoStop,-0.5); dJointSetSliderParam (joint,dParamHiStop,0.5); dJointSetSliderParam (joint,dParamBounce,0.5); // anchor 2nd body with a fixed joint dJointID j = dJointCreateFixed (world,0); dJointAttach (j,body[1],0); dJointSetFixed (j); return 1; } // ********** hinge-2 joint case 420: // hinge-2 steering angle polarity test case 421: // hinge-2 steering angle rate test constructWorldForTest (0,2, 0.5*SIDE,0,1, -0.5*SIDE,0,1, 1,0,0, 1,0,0, 0,0); joint = dJointCreateHinge2 (world,0); dJointAttach (joint,body[0],body[1]); dJointSetHinge2Anchor (joint,-0.5*SIDE,0,1); dJointSetHinge2Axes (joint, zunit, xunit); max_iterations = 50; return 1; case 430: // hinge 2 steering motor rate (+polarity) test case 431: // ...with stops case 432: // hinge 2 wheel motor rate (+polarity) test constructWorldForTest (0,2, 0.5*SIDE,0,1, -0.5*SIDE,0,1, 1,0,0, 1,0,0, 0,0); joint = dJointCreateHinge2 (world,0); dJointAttach (joint,body[0],body[1]); dJointSetHinge2Anchor (joint,-0.5*SIDE,0,1); dJointSetHinge2Axes (joint, zunit, xunit); dJointSetHinge2Param (joint,dParamFMax,1); dJointSetHinge2Param (joint,dParamFMax2,1); if (n==431) { dJointSetHinge2Param (joint,dParamLoStop,-0.5); dJointSetHinge2Param (joint,dParamHiStop,0.5); } return 1; // ********** angular motor joint case 600: // test euler angle calculations constructWorldForTest (0,2, -SIDE*0.5,0,1, SIDE*0.5,0,1, 0,0,1, 0,0,1, 0,0); joint = dJointCreateAMotor (world,0); dJointAttach (joint,body[0],body[1]); dJointSetAMotorNumAxes (joint,3); dJointSetAMotorAxis (joint,0,1, 0,0,1); dJointSetAMotorAxis (joint,2,2, 1,0,0); dJointSetAMotorMode (joint,dAMotorEuler); max_iterations = 200; return 1; // ********** universal joint case 700: // 2 body case 701: case 702: constructWorldForTest (0,2, 0.5*SIDE,0.5*SIDE,1, -0.5*SIDE,-0.5*SIDE,1, 1,1,0, 1,1,0, 0.25*M_PI,0.25*M_PI); joint = dJointCreateUniversal (world,0); dJointAttach (joint,body[0],body[1]); dJointSetUniversalAnchor (joint,0,0,1); dJointSetUniversalAxis1 (joint, 1, -1, 1.41421356); dJointSetUniversalAxis2 (joint, 1, -1, -1.41421356); return 1; case 720: // universal transmit torque test case 721: case 722: case 730: // universal torque about axis 1 case 731: case 732: case 740: // universal torque about axis 2 case 741: case 742: constructWorldForTest (0,2, 0.5*SIDE,0.5*SIDE,1, -0.5*SIDE,-0.5*SIDE,1, 1,0,0, 1,0,0, 0,0); joint = dJointCreateUniversal (world,0); dJointAttach (joint,body[0],body[1]); dJointSetUniversalAnchor (joint,0,0,1); dJointSetUniversalAxis1 (joint,0,0,1); dJointSetUniversalAxis2 (joint, 1, -1,0); max_iterations = 100; return 1; // Joint PR (Prismatic and Rotoide) case 800: // 2 body case 801: // 2 bodies with spring force and prismatic fixed case 802: // 2 bodies with torque on body1 and prismatic fixed constructWorldForTest (0, 2, -1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1,0,0, 1,0,0, 0, 0); joint = dJointCreatePR (world, 0); dJointAttach (joint, body[0], body[1]); dJointSetPRAnchor (joint,-0.5, 0.0, 1.0); dJointSetPRAxis1 (joint, 0, 1, 0); dJointSetPRAxis2 (joint, 1, 0, 0); dJointSetPRParam (joint,dParamLoStop,-0.5); dJointSetPRParam (joint,dParamHiStop,0.5); dJointSetPRParam (joint,dParamLoStop2,0); dJointSetPRParam (joint,dParamHiStop2,0); return 1; case 803: // 2 bodies with spring force and prismatic NOT fixed case 804: // 2 bodies with torque force and prismatic NOT fixed case 805: // 2 bodies with force only on first body constructWorldForTest (0, 2, -1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1,0,0, 1,0,0, 0, 0); joint = dJointCreatePR (world, 0); dJointAttach (joint, body[0], body[1]); dJointSetPRAnchor (joint,-0.5, 0.0, 1.0); dJointSetPRAxis1 (joint, 0, 1, 0); dJointSetPRAxis2 (joint, 1, 0, 0); dJointSetPRParam (joint,dParamLoStop,-0.5); dJointSetPRParam (joint,dParamHiStop,0.5); dJointSetPRParam (joint,dParamLoStop2,-0.5); dJointSetPRParam (joint,dParamHiStop2,0.5); return 1; } return 0; } // do stuff specific to this test each iteration. you can check some // invariants for the test -- the return value is some scaled error measurement // that must be less than 1. // return a dInfinity if error is not measured for this n. dReal doStuffAndGetError (int n) { switch (n) { // ********** fixed joint case 0: { // 2 body addOscillatingTorque (0.1); dampRotationalMotion (0.1); // check the orientations are the same const dReal *R1 = dBodyGetRotation (body[0]); const dReal *R2 = dBodyGetRotation (body[1]); dReal err1 = dMaxDifference (R1,R2,3,3); // check the body offset is correct dVector3 p,pp; const dReal *p1 = dBodyGetPosition (body[0]); const dReal *p2 = dBodyGetPosition (body[1]); for (int i=0; i<3; i++) p[i] = p2[i] - p1[i]; dMultiply1_331 (pp,R1,p); pp[0] += 0.5; pp[1] += 0.5; return (err1 + length (pp)) * 300; } case 1: { // 1 body to static env addOscillatingTorque (0.1); // check the orientation is the identity dReal err1 = cmpIdentity (dBodyGetRotation (body[0])); // check the body offset is correct dVector3 p; const dReal *p1 = dBodyGetPosition (body[0]); for (int i=0; i<3; i++) p[i] = p1[i]; p[0] -= 0.25; p[1] -= 0.25; p[2] -= 1; return (err1 + length (p)) * 1e6; } case 2: { // 2 body addOscillatingTorque (0.1); dampRotationalMotion (0.1); // check the body offset is correct // Should really check body rotation too. Oh well. const dReal *R1 = dBodyGetRotation (body[0]); dVector3 p,pp; const dReal *p1 = dBodyGetPosition (body[0]); const dReal *p2 = dBodyGetPosition (body[1]); for (int i=0; i<3; i++) p[i] = p2[i] - p1[i]; dMultiply1_331 (pp,R1,p); pp[0] += 0.5; pp[1] += 0.5; return length(pp) * 300; } case 3: { // 1 body to static env with relative rotation addOscillatingTorque (0.1); // check the body offset is correct dVector3 p; const dReal *p1 = dBodyGetPosition (body[0]); for (int i=0; i<3; i++) p[i] = p1[i]; p[0] -= 0.25; p[1] -= 0.25; p[2] -= 1; return length (p) * 1e6; } // ********** hinge joint case 200: // 2 body addOscillatingTorque (0.1); dampRotationalMotion (0.1); return dInfinity; case 220: // hinge angle polarity test dBodyAddTorque (body[0],0,0,0.01); dBodyAddTorque (body[1],0,0,-0.01); if (iteration == 40) { dReal a = dJointGetHingeAngle (joint); if (a > 0.5 && a < 1) return 0; else return 10; } return 0; case 221: { // hinge angle rate test static dReal last_angle = 0; dBodyAddTorque (body[0],0,0,0.01); dBodyAddTorque (body[1],0,0,-0.01); dReal a = dJointGetHingeAngle (joint); dReal r = dJointGetHingeAngleRate (joint); dReal er = (a-last_angle)/STEPSIZE; // estimated rate last_angle = a; return fabs(r-er) * 4e4; } case 230: // hinge motor rate (and polarity) test case 231: { // ...with stops static dReal a = 0; dReal r = dJointGetHingeAngleRate (joint); dReal err = fabs (cos(a) - r); if (a==0) err = 0; a += 0.03; dJointSetHingeParam (joint,dParamVel,cos(a)); if (n==231) return dInfinity; return err * 1e6; } // ********** slider joint case 300: // 2 body addOscillatingTorque (0.05); dampRotationalMotion (0.1); addSpringForce (0.5); return dInfinity; case 320: // slider angle polarity test dBodyAddForce (body[0],0,0,0.1); dBodyAddForce (body[1],0,0,-0.1); if (iteration == 40) { dReal a = dJointGetSliderPosition (joint); if (a > 0.2 && a < 0.5) return 0; else return 10; // Failed } return 0; case 321: { // slider angle rate test static dReal last_pos = 0; dBodyAddForce (body[0],0,0,0.1); dBodyAddForce (body[1],0,0,-0.1); dReal p = dJointGetSliderPosition (joint); dReal r = dJointGetSliderPositionRate (joint); dReal er = (p-last_pos)/STEPSIZE; // estimated rate (almost exact) last_pos = p; return fabs(r-er) * 1e9; } case 330: // slider motor rate (and polarity) test case 331: { // ...with stops static dReal a = 0; dReal r = dJointGetSliderPositionRate (joint); dReal err = fabs (0.7*cos(a) - r); if (a < 0.04) err = 0; a += 0.03; dJointSetSliderParam (joint,dParamVel,0.7*cos(a)); if (n==331) return dInfinity; return err * 1e6; } // ********** hinge-2 joint case 420: // hinge-2 steering angle polarity test dBodyAddTorque (body[0],0,0,0.01); dBodyAddTorque (body[1],0,0,-0.01); if (iteration == 40) { dReal a = dJointGetHinge2Angle1 (joint); if (a > 0.5 && a < 0.6) return 0; else return 10; } return 0; case 421: { // hinge-2 steering angle rate test static dReal last_angle = 0; dBodyAddTorque (body[0],0,0,0.01); dBodyAddTorque (body[1],0,0,-0.01); dReal a = dJointGetHinge2Angle1 (joint); dReal r = dJointGetHinge2Angle1Rate (joint); dReal er = (a-last_angle)/STEPSIZE; // estimated rate last_angle = a; return fabs(r-er)*2e4; } case 430: // hinge 2 steering motor rate (+polarity) test case 431: { // ...with stops static dReal a = 0; dReal r = dJointGetHinge2Angle1Rate (joint); dReal err = fabs (cos(a) - r); if (a==0) err = 0; a += 0.03; dJointSetHinge2Param (joint,dParamVel,cos(a)); if (n==431) return dInfinity; return err * 1e6; } case 432: { // hinge 2 wheel motor rate (+polarity) test static dReal a = 0; dReal r = dJointGetHinge2Angle2Rate (joint); dReal err = fabs (cos(a) - r); if (a==0) err = 0; a += 0.03; dJointSetHinge2Param (joint,dParamVel2,cos(a)); return err * 1e6; } // ********** angular motor joint case 600: { // test euler angle calculations // desired euler angles from last iteration static dReal a1,a2,a3; // find actual euler angles dReal aa1 = dJointGetAMotorAngle (joint,0); dReal aa2 = dJointGetAMotorAngle (joint,1); dReal aa3 = dJointGetAMotorAngle (joint,2); // printf ("actual = %.4f %.4f %.4f\n\n",aa1,aa2,aa3); dReal err = dInfinity; if (iteration > 0) { err = dFabs(aa1-a1) + dFabs(aa2-a2) + dFabs(aa3-a3); err *= 1e10; } // get random base rotation for both bodies dMatrix3 Rbase; dRFromAxisAndAngle (Rbase, 3*(dRandReal()-0.5), 3*(dRandReal()-0.5), 3*(dRandReal()-0.5), 3*(dRandReal()-0.5)); dBodySetRotation (body[0],Rbase); // rotate body 2 by random euler angles w.r.t. body 1 a1 = 3.14 * 2 * (dRandReal()-0.5); a2 = 1.57 * 2 * (dRandReal()-0.5); a3 = 3.14 * 2 * (dRandReal()-0.5); dMatrix3 R1,R2,R3,Rtmp1,Rtmp2; dRFromAxisAndAngle (R1,0,0,1,-a1); dRFromAxisAndAngle (R2,0,1,0,a2); dRFromAxisAndAngle (R3,1,0,0,-a3); dMultiply0 (Rtmp1,R2,R3,3,3,3); dMultiply0 (Rtmp2,R1,Rtmp1,3,3,3); dMultiply0 (Rtmp1,Rbase,Rtmp2,3,3,3); dBodySetRotation (body[1],Rtmp1); // printf ("desired = %.4f %.4f %.4f\n",a1,a2,a3); return err; } // ********** universal joint case 700: { // 2 body: joint constraint dVector3 ax1, ax2; addOscillatingTorque (0.1); dampRotationalMotion (0.1); dJointGetUniversalAxis1(joint, ax1); dJointGetUniversalAxis2(joint, ax2); return fabs(10*dCalcVectorDot3(ax1, ax2)); } case 701: { // 2 body: angle 1 rate static dReal last_angle = 0; addOscillatingTorque (0.1); dampRotationalMotion (0.1); dReal a = dJointGetUniversalAngle1(joint); dReal r = dJointGetUniversalAngle1Rate(joint); dReal diff = a - last_angle; if (diff > M_PI) diff -= 2*M_PI; if (diff < -M_PI) diff += 2*M_PI; dReal er = diff / STEPSIZE; // estimated rate last_angle = a; // I'm not sure why the error is so large here. return fabs(r - er) * 1e1; } case 702: { // 2 body: angle 2 rate static dReal last_angle = 0; addOscillatingTorque (0.1); dampRotationalMotion (0.1); dReal a = dJointGetUniversalAngle2(joint); dReal r = dJointGetUniversalAngle2Rate(joint); dReal diff = a - last_angle; if (diff > M_PI) diff -= 2*M_PI; if (diff < -M_PI) diff += 2*M_PI; dReal er = diff / STEPSIZE; // estimated rate last_angle = a; // I'm not sure why the error is so large here. return fabs(r - er) * 1e1; } case 720: { // universal transmit torque test: constraint error dVector3 ax1, ax2; addOscillatingTorqueAbout (0.1, 1, 1, 0); dampRotationalMotion (0.1); dJointGetUniversalAxis1(joint, ax1); dJointGetUniversalAxis2(joint, ax2); return fabs(10*dCalcVectorDot3(ax1, ax2)); } case 721: { // universal transmit torque test: angle1 rate static dReal last_angle = 0; addOscillatingTorqueAbout (0.1, 1, 1, 0); dampRotationalMotion (0.1); dReal a = dJointGetUniversalAngle1(joint); dReal r = dJointGetUniversalAngle1Rate(joint); dReal diff = a - last_angle; if (diff > M_PI) diff -= 2*M_PI; if (diff < -M_PI) diff += 2*M_PI; dReal er = diff / STEPSIZE; // estimated rate last_angle = a; return fabs(r - er) * 1e10; } case 722: { // universal transmit torque test: angle2 rate static dReal last_angle = 0; addOscillatingTorqueAbout (0.1, 1, 1, 0); dampRotationalMotion (0.1); dReal a = dJointGetUniversalAngle2(joint); dReal r = dJointGetUniversalAngle2Rate(joint); dReal diff = a - last_angle; if (diff > M_PI) diff -= 2*M_PI; if (diff < -M_PI) diff += 2*M_PI; dReal er = diff / STEPSIZE; // estimated rate last_angle = a; return fabs(r - er) * 1e10; } case 730:{ dVector3 ax1, ax2; dJointGetUniversalAxis1(joint, ax1); dJointGetUniversalAxis2(joint, ax2); addOscillatingTorqueAbout (0.1, ax1[0], ax1[1], ax1[2]); dampRotationalMotion (0.1); return fabs(10*dCalcVectorDot3(ax1, ax2)); } case 731:{ dVector3 ax1; static dReal last_angle = 0; dJointGetUniversalAxis1(joint, ax1); addOscillatingTorqueAbout (0.1, ax1[0], ax1[1], ax1[2]); dampRotationalMotion (0.1); dReal a = dJointGetUniversalAngle1(joint); dReal r = dJointGetUniversalAngle1Rate(joint); dReal diff = a - last_angle; if (diff > M_PI) diff -= 2*M_PI; if (diff < -M_PI) diff += 2*M_PI; dReal er = diff / STEPSIZE; // estimated rate last_angle = a; return fabs(r - er) * 2e3; } case 732:{ dVector3 ax1; static dReal last_angle = 0; dJointGetUniversalAxis1(joint, ax1); addOscillatingTorqueAbout (0.1, ax1[0], ax1[1], ax1[2]); dampRotationalMotion (0.1); dReal a = dJointGetUniversalAngle2(joint); dReal r = dJointGetUniversalAngle2Rate(joint); dReal diff = a - last_angle; if (diff > M_PI) diff -= 2*M_PI; if (diff < -M_PI) diff += 2*M_PI; dReal er = diff / STEPSIZE; // estimated rate last_angle = a; return fabs(r - er) * 1e10; } case 740:{ dVector3 ax1, ax2; dJointGetUniversalAxis1(joint, ax1); dJointGetUniversalAxis2(joint, ax2); addOscillatingTorqueAbout (0.1, ax2[0], ax2[1], ax2[2]); dampRotationalMotion (0.1); return fabs(10*dCalcVectorDot3(ax1, ax2)); } case 741:{ dVector3 ax2; static dReal last_angle = 0; dJointGetUniversalAxis2(joint, ax2); addOscillatingTorqueAbout (0.1, ax2[0], ax2[1], ax2[2]); dampRotationalMotion (0.1); dReal a = dJointGetUniversalAngle1(joint); dReal r = dJointGetUniversalAngle1Rate(joint); dReal diff = a - last_angle; if (diff > M_PI) diff -= 2*M_PI; if (diff < -M_PI) diff += 2*M_PI; dReal er = diff / STEPSIZE; // estimated rate last_angle = a; return fabs(r - er) * 1e10; } case 742:{ dVector3 ax2; static dReal last_angle = 0; dJointGetUniversalAxis2(joint, ax2); addOscillatingTorqueAbout (0.1, ax2[0], ax2[1], ax2[2]); dampRotationalMotion (0.1); dReal a = dJointGetUniversalAngle2(joint); dReal r = dJointGetUniversalAngle2Rate(joint); dReal diff = a - last_angle; if (diff > M_PI) diff -= 2*M_PI; if (diff < -M_PI) diff += 2*M_PI; dReal er = diff / STEPSIZE; // estimated rate last_angle = a; return fabs(r - er) * 1e4; } // ********** slider joint case 801: case 803: addSpringForce (0.25); return dInfinity; case 802: case 804: { static dReal a = 0; dBodyAddTorque (body[0], 0, 0.01*cos(1.5708*a), 0); a += 0.01; return dInfinity; } case 805: addOscillatingForce (0.1); return dInfinity; } return dInfinity; } //**************************************************************************** // simulation stuff common to all the tests // start simulation - set viewpoint static void start() { dAllocateODEDataForThread(dAllocateMaskAll); static float xyz[3] = {1.0382f,-1.0811f,1.4700f}; static float hpr[3] = {135.0000f,-19.5000f,0.0000f}; dsSetViewpoint (xyz,hpr); } // simulation loop static void simLoop (int pause) { // stop after a given number of iterations, as long as we are not in // interactive mode if (cmd_graphics && !cmd_interactive && (iteration >= max_iterations)) { dsStop(); return; } iteration++; if (!pause) { // do stuff for this test and check to see if the joint is behaving well dReal error = doStuffAndGetError (test_num); if (error > max_error) max_error = error; if (cmd_interactive && error < dInfinity) { printf ("scaled error = %.4e\n",error); } // take a step dWorldStep (world,STEPSIZE); // occasionally re-orient the first body to create a deliberate error. if (cmd_occasional_error) { static int count = 0; if ((count % 20)==0) { // randomly adjust orientation of body[0] const dReal *R1; dMatrix3 R2,R3; R1 = dBodyGetRotation (body[0]); dRFromAxisAndAngle (R2,dRandReal()-0.5,dRandReal()-0.5, dRandReal()-0.5,dRandReal()-0.5); dMultiply0 (R3,R1,R2,3,3,3); dBodySetRotation (body[0],R3); // randomly adjust position of body[0] const dReal *pos = dBodyGetPosition (body[0]); dBodySetPosition (body[0], pos[0]+0.2*(dRandReal()-0.5), pos[1]+0.2*(dRandReal()-0.5), pos[2]+0.2*(dRandReal()-0.5)); } count++; } } if (cmd_graphics) { dReal sides1[3] = {SIDE,SIDE,SIDE}; dReal sides2[3] = {SIDE*0.99f,SIDE*0.99f,SIDE*0.99f}; dsSetTexture (DS_WOOD); dsSetColor (1,1,0); dsDrawBox (dBodyGetPosition(body[0]),dBodyGetRotation(body[0]),sides1); if (body[1]) { dsSetColor (0,1,1); dsDrawBox (dBodyGetPosition(body[1]),dBodyGetRotation(body[1]),sides2); } } } //**************************************************************************** // conduct a specific test, and report the results void doTest (int argc, char **argv, int n, int fatal_if_bad_n) { test_num = n; iteration = 0; max_iterations = 300; max_error = 0; if (! setupTest (n)) { if (fatal_if_bad_n) dError (0,"bad test number"); return; } // setup pointers to drawstuff callback functions dsFunctions fn; fn.version = DS_VERSION; fn.start = &start; fn.step = &simLoop; fn.command = 0; fn.stop = 0; if (cmd_path_to_textures) fn.path_to_textures = cmd_path_to_textures; else fn.path_to_textures = DRAWSTUFF_TEXTURE_PATH; // run simulation if (cmd_graphics) { dsSimulationLoop (argc,argv,352,288,&fn); } else { for (int i=0; i < max_iterations; i++) simLoop (0); } dWorldDestroy (world); body[0] = 0; body[1] = 0; joint = 0; // print results printf ("test %d: ",n); if (max_error == dInfinity) printf ("error not computed\n"); else { printf ("max scaled error = %.4e",max_error); if (max_error < 1) printf (" - passed\n"); else printf (" - FAILED\n"); } } //**************************************************************************** // main int main (int argc, char **argv) { int i; dInitODE2(0); // process the command line args. anything that starts with `-' is assumed // to be a drawstuff argument. for (i=1; i #include #ifdef _MSC_VER #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints #endif //**************************************************************************** // matrix sizes #define dALIGN_SIZE(buf_size, alignment) (((buf_size) + (alignment - 1)) & (int)(~(alignment - 1))) // Casting the mask to int ensures sign-extension to larger integer sizes #define dALIGN_PTR(buf_ptr, alignment) ((void *)(((duintptr)(buf_ptr) + ((alignment) - 1)) & (int)(~(alignment - 1)))) // Casting the mask to int ensures sign-extension to larger integer sizes #define MSIZE 21 #define MSIZE4 dALIGN_SIZE(MSIZE, 4) // MSIZE rounded up to 4 //**************************************************************************** // matrix accessors #define _A(i,j) A[(i)*4+(j)] #define _I(i,j) I[(i)*4+(j)] #define _R(i,j) R[(i)*4+(j)] //**************************************************************************** // tolerances #ifdef dDOUBLE const double tol = 1e-10; #endif #ifdef dSINGLE const double tol = 1e-5; #endif //**************************************************************************** // misc messages and error handling #ifdef __GNUC__ #define HEADER printf ("%s()\n", __FUNCTION__); #else #define HEADER printf ("%s:%d\n",__FILE__,__LINE__); #endif static jmp_buf jump_buffer; void myMessageFunction (int num, const char *msg, va_list ap) { printf ("(Message %d: ",num); vprintf (msg,ap); printf (")"); dSetMessageHandler (0); longjmp (jump_buffer,1); } #define TRAP_MESSAGE(do,ifnomsg,ifmsg) \ dSetMessageHandler (&myMessageFunction); \ if (setjmp (jump_buffer)) { \ dSetMessageHandler (0); \ ifmsg ; \ } \ else { \ dSetMessageHandler (&myMessageFunction); \ do ; \ ifnomsg ; \ } \ dSetMessageHandler (0); //**************************************************************************** // utility stuff // compare two numbers, within a threshhold, return 1 if approx equal int cmp (dReal a, dReal b) { return (fabs(a-b) < tol); } //**************************************************************************** // matrix utility stuff // compare a 3x3 matrix with the identity int cmpIdentityMat3 (dMatrix3 A) { return (cmp(_A(0,0),1.0) && cmp(_A(0,1),0.0) && cmp(_A(0,2),0.0) && cmp(_A(1,0),0.0) && cmp(_A(1,1),1.0) && cmp(_A(1,2),0.0) && cmp(_A(2,0),0.0) && cmp(_A(2,1),0.0) && cmp(_A(2,2),1.0)); } // transpose a 3x3 matrix in-line void transpose3x3 (dMatrix3 A) { dReal tmp; tmp=A[4]; A[4]=A[1]; A[1]=tmp; tmp=A[8]; A[8]=A[2]; A[2]=tmp; tmp=A[9]; A[9]=A[6]; A[6]=tmp; } //**************************************************************************** // test miscellaneous math functions void testRandomNumberGenerator() { HEADER; if (dTestRand()) printf ("\tpassed\n"); else printf ("\tFAILED\n"); } void testInfinity() { HEADER; if (1e10 < dInfinity && -1e10 > -dInfinity && -dInfinity < dInfinity) printf ("\tpassed\n"); else printf ("\tFAILED\n"); } void testPad() { HEADER; char s[100]; s[0]=0; for (int i=0; i<=16; i++) sprintf (s+strlen(s),"%d ",dPAD(i)); printf ("\t%s\n", strcmp(s,"0 1 4 4 4 8 8 8 8 12 12 12 12 16 16 16 16 ") ? "FAILED" : "passed"); } void testCrossProduct() { HEADER; dVector3 a1,a2,b,c; dMatrix3 B; dMakeRandomVector (b,3,1.0); dMakeRandomVector (c,3,1.0); dCalcVectorCross3(a1,b,c); dSetZero (B,12); dSetCrossMatrixPlus(B,b,4); dMultiply0 (a2,B,c,3,3,1); dReal diff = dMaxDifference(a1,a2,3,1); printf ("\t%s\n", diff > tol ? "FAILED" : "passed"); } void testSetZero() { HEADER; dReal a[100]; dMakeRandomVector (a,100,1.0); dSetZero (a,100); for (int i=0; i<100; i++) if (a[i] != 0.0) { printf ("\tFAILED\n"); return; } printf ("\tpassed\n"); } void testNormalize3() { HEADER; int i,j,bad=0; dVector3 n1,n2; for (i=0; i<1000; i++) { dMakeRandomVector (n1,3,1.0); for (j=0; j<3; j++) n2[j]=n1[j]; dNormalize3 (n2); if (dFabs(dCalcVectorDot3(n2,n2) - 1.0) > tol) bad |= 1; if (dFabs(n2[0]/n1[0] - n2[1]/n1[1]) > tol) bad |= 2; if (dFabs(n2[0]/n1[0] - n2[2]/n1[2]) > tol) bad |= 4; if (dFabs(n2[1]/n1[1] - n2[2]/n1[2]) > tol) bad |= 8; if (dFabs(dCalcVectorDot3(n2,n1) - dSqrt(dCalcVectorDot3(n1,n1))) > tol) bad |= 16; if (bad) { printf ("\tFAILED (code=%x)\n",bad); return; } } printf ("\tpassed\n"); } /* void testReorthonormalize() { HEADER; dMatrix3 R,I; dMakeRandomMatrix (R,3,3,1.0); for (int i=0; i<30; i++) dReorthonormalize (R); dMultiply2 (I,R,R,3,3,3); printf ("\t%s\n",cmpIdentityMat3 (I) ? "passed" : "FAILED"); } */ void testPlaneSpace() { HEADER; dVector3 n,p,q; int bad = 0; for (int i=0; i<1000; i++) { dMakeRandomVector (n,3,1.0); dNormalize3 (n); dPlaneSpace (n,p,q); if (fabs(dCalcVectorDot3(n,p)) > tol) bad = 1; if (fabs(dCalcVectorDot3(n,q)) > tol) bad = 1; if (fabs(dCalcVectorDot3(p,q)) > tol) bad = 1; if (fabs(dCalcVectorDot3(p,p)-1) > tol) bad = 1; if (fabs(dCalcVectorDot3(q,q)-1) > tol) bad = 1; } printf ("\t%s\n", bad ? "FAILED" : "passed"); } //**************************************************************************** // test matrix functions void testMatrixMultiply() { // A is 2x3, B is 3x4, B2 is B except stored columnwise, C is 2x4 dReal A[8],B[12],A2[12],B2[16],C[8]; int i; HEADER; dSetZero (A,8); for (i=0; i<3; i++) A[i] = i+2; for (i=0; i<3; i++) A[i+4] = i+3+2; for (i=0; i<12; i++) B[i] = i+8; dSetZero (A2,12); for (i=0; i<6; i++) A2[i+2*(i/2)] = A[i+i/3]; dSetZero (B2,16); for (i=0; i<12; i++) B2[i+i/3] = B[i]; dMultiply0 (C,A,B,2,3,4); if (C[0] != 116 || C[1] != 125 || C[2] != 134 || C[3] != 143 || C[4] != 224 || C[5] != 242 || C[6] != 260 || C[7] != 278) printf ("\tFAILED (1)\n"); else printf ("\tpassed (1)\n"); dMultiply1 (C,A2,B,2,3,4); if (C[0] != 160 || C[1] != 172 || C[2] != 184 || C[3] != 196 || C[4] != 196 || C[5] != 211 || C[6] != 226 || C[7] != 241) printf ("\tFAILED (2)\n"); else printf ("\tpassed (2)\n"); dMultiply2 (C,A,B2,2,3,4); if (C[0] != 83 || C[1] != 110 || C[2] != 137 || C[3] != 164 || C[4] != 164 || C[5] != 218 || C[6] != 272 || C[7] != 326) printf ("\tFAILED (3)\n"); else printf ("\tpassed (3)\n"); } void testSmallMatrixMultiply() { dMatrix3 A,B,C,A2; dVector3 a,a2,x; HEADER; dMakeRandomMatrix (A,3,3,1.0); dMakeRandomMatrix (B,3,3,1.0); dMakeRandomMatrix (C,3,3,1.0); dMakeRandomMatrix (x,3,1,1.0); // dMultiply0_331() dMultiply0_331 (a,B,x); dMultiply0 (a2,B,x,3,3,1); printf ("\t%s (1)\n",(dMaxDifference (a,a2,3,1) > tol) ? "FAILED" : "passed"); // dMultiply1_331() dMultiply1_331 (a,B,x); dMultiply1 (a2,B,x,3,3,1); printf ("\t%s (2)\n",(dMaxDifference (a,a2,3,1) > tol) ? "FAILED" : "passed"); // dMultiply0_133 dMultiply0_133 (a,x,B); dMultiply0 (a2,x,B,1,3,3); printf ("\t%s (3)\n",(dMaxDifference (a,a2,1,3) > tol) ? "FAILED" : "passed"); // dMultiply0_333() dMultiply0_333 (A,B,C); dMultiply0 (A2,B,C,3,3,3); printf ("\t%s (4)\n",(dMaxDifference (A,A2,3,3) > tol) ? "FAILED" : "passed"); // dMultiply1_333() dMultiply1_333 (A,B,C); dMultiply1 (A2,B,C,3,3,3); printf ("\t%s (5)\n",(dMaxDifference (A,A2,3,3) > tol) ? "FAILED" : "passed"); // dMultiply2_333() dMultiply2_333 (A,B,C); dMultiply2 (A2,B,C,3,3,3); printf ("\t%s (6)\n",(dMaxDifference (A,A2,3,3) > tol) ? "FAILED" : "passed"); } void testCholeskyFactorization() { dsizeint matrixSize = sizeof(dReal) * MSIZE4 * MSIZE; dReal *A = (dReal *)dAlloc(matrixSize), *B = (dReal *)dAlloc(matrixSize), *C = (dReal *)dAlloc(matrixSize), diff; HEADER; dMakeRandomMatrix (A,MSIZE,MSIZE,1.0); dMultiply2 (B,A,A,MSIZE,MSIZE,MSIZE); memcpy (A,B,MSIZE4*MSIZE*sizeof(dReal)); if (dFactorCholesky (B,MSIZE)) printf ("\tpassed (1)\n"); else printf ("\tFAILED (1)\n"); dClearUpperTriangle (B,MSIZE); dMultiply2 (C,B,B,MSIZE,MSIZE,MSIZE); diff = dMaxDifference(A,C,MSIZE,MSIZE); printf ("\tmaximum difference = %.6e - %s (2)\n",diff, diff > tol ? "FAILED" : "passed"); dFree(C, matrixSize); dFree(B, matrixSize); dFree(A, matrixSize); } void testCholeskySolve() { dsizeint matrixSize = sizeof(dReal) * MSIZE4 * MSIZE, vectorSize = sizeof(dReal) * MSIZE; dReal *A = (dReal *)dAlloc(matrixSize), *L = (dReal *)dAlloc(matrixSize); dReal *b = (dReal *)dAlloc(vectorSize), *x = (dReal *)dAlloc(vectorSize), *btest = (dReal *)dAlloc(vectorSize), diff; HEADER; // get A,L = PD matrix dMakeRandomMatrix (A,MSIZE,MSIZE,1.0); dMultiply2 (L,A,A,MSIZE,MSIZE,MSIZE); memcpy (A,L,MSIZE4*MSIZE*sizeof(dReal)); // get b,x = right hand side dMakeRandomMatrix (b,MSIZE,1,1.0); memcpy (x,b,MSIZE*sizeof(dReal)); // factor L if (dFactorCholesky (L,MSIZE)) printf ("\tpassed (1)\n"); else printf ("\tFAILED (1)\n"); dClearUpperTriangle (L,MSIZE); // solve A*x = b dSolveCholesky (L,x,MSIZE); // compute A*x and compare it with b dMultiply2 (btest,A,x,MSIZE,MSIZE,1); diff = dMaxDifference(b,btest,MSIZE,1); printf ("\tmaximum difference = %.6e - %s (2)\n",diff, diff > tol ? "FAILED" : "passed"); dFree(btest, vectorSize); dFree(x, vectorSize); dFree(b, vectorSize); dFree(L, matrixSize); dFree(A, matrixSize); } void testInvertPDMatrix() { int i,j,ok; dsizeint matrixSize = sizeof(dReal) * MSIZE4 * MSIZE; dReal *A = (dReal *)dAlloc(matrixSize), *Ainv = (dReal *)dAlloc(matrixSize), *I = (dReal *)dAlloc(matrixSize); HEADER; dMakeRandomMatrix (A,MSIZE,MSIZE,1.0); dMultiply2 (Ainv,A,A,MSIZE,MSIZE,MSIZE); memcpy (A,Ainv,MSIZE4*MSIZE*sizeof(dReal)); dSetZero (Ainv,MSIZE4*MSIZE); if (dInvertPDMatrix (A,Ainv,MSIZE)) printf ("\tpassed (1)\n"); else printf ("\tFAILED (1)\n"); dMultiply0 (I,A,Ainv,MSIZE,MSIZE,MSIZE); // compare with identity ok = 1; for (i=0; i tol ? "FAILED" : "passed"); dFree(d, vectorSize); dFree(ATEST, matrixSize); dFree(DL, matrixSize); dFree(L, matrixSize); dFree(A, matrixSize); } void testCoopLDLTFactorization() { int i,j; const dsizeint COOP_MSIZE = MSIZE * 51, COOP_MSIZE4 = dALIGN_SIZE(COOP_MSIZE, 4); dsizeint matrixSize = sizeof(dReal) * COOP_MSIZE4 * COOP_MSIZE, vectorSize = sizeof(dReal) * COOP_MSIZE; dReal *A = (dReal *)dAlloc(matrixSize), *L = (dReal *)dAlloc(matrixSize), *DL = (dReal *)dAlloc(matrixSize), *ATEST = (dReal *)dAlloc(matrixSize), *d = (dReal *)dAlloc(vectorSize), diff; const unsigned threadCountMaximum = 8; dThreadingImplementationID threading = dThreadingAllocateMultiThreadedImplementation(); dCooperativeID cooperative = dCooperativeCreate(dThreadingImplementationGetFunctions(threading), threading); dThreadingThreadPoolID pool = dThreadingAllocateThreadPool(threadCountMaximum, 0, dAllocateFlagBasicData, NULL); dThreadingThreadPoolServeMultiThreadedImplementation(pool, threading); dResourceRequirementsID requirements = dResourceRequirementsCreate(cooperative); dEstimateCooperativelyFactorLDLTResourceRequirements(requirements, threadCountMaximum, COOP_MSIZE); dResourceContainerID resources = dResourceContainerAcquire(requirements); HEADER; for (int pass = 0; pass != 4; ++pass) { dTimerStart ("Factoring LDLT"); const unsigned allowedThreads = 4; const unsigned PASS_MSIZE = COOP_MSIZE - pass, PASS_MSIZE4 = dALIGN_SIZE(PASS_MSIZE, 4); dTimerNow ("Preparing data"); dMakeRandomMatrix (L, PASS_MSIZE, PASS_MSIZE, 1.0); dMultiply2 (A, L, L, PASS_MSIZE, PASS_MSIZE, PASS_MSIZE); memcpy (L, A, sizeof(dReal) * PASS_MSIZE4 * PASS_MSIZE); dTimerNow ("Factoring multi threaded"); dCooperativelyFactorLDLT (resources, allowedThreads, L, d, PASS_MSIZE, PASS_MSIZE4); dTimerNow ("Verifying"); dClearUpperTriangle (L, PASS_MSIZE); for (i = 0; i < PASS_MSIZE; i++) L[i * PASS_MSIZE4 + i] = 1.0; dSetZero (DL, PASS_MSIZE4 * PASS_MSIZE); for (i = 0; i < PASS_MSIZE; i++) { for (j = 0; j < PASS_MSIZE; j++) DL[i * PASS_MSIZE4 + j] = L[i * PASS_MSIZE4 + j] / d[j]; } dMultiply2 (ATEST, L, DL, PASS_MSIZE, PASS_MSIZE, PASS_MSIZE); diff = dMaxDifference(A, ATEST, PASS_MSIZE, PASS_MSIZE); printf ("\tN=%u: maximum difference = %.6e - %s\n", PASS_MSIZE, diff, diff > 1e2 * tol ? "FAILED" : "passed"); dTimerEnd(); dTimerReport(stdout, 0); } dResourceContainerDestroy(resources); dResourceRequirementsDestroy(requirements); dThreadingImplementationShutdownProcessing(threading); dThreadingFreeThreadPool(pool); dCooperativeDestroy(cooperative); dThreadingFreeImplementation(threading); dFree(d, vectorSize); dFree(ATEST, matrixSize); dFree(DL, matrixSize); dFree(L, matrixSize); dFree(A, matrixSize); } void testSolveLDLT() { dsizeint matrixSize = sizeof(dReal) * MSIZE4 * MSIZE, vectorSize = sizeof(dReal) * MSIZE; dReal *A = (dReal *)dAlloc(matrixSize), *L = (dReal *)dAlloc(matrixSize), *d = (dReal *)dAlloc(vectorSize), *x = (dReal *)dAlloc(vectorSize), *b = (dReal *)dAlloc(vectorSize), *btest = (dReal *)dAlloc(vectorSize), diff; HEADER; dMakeRandomMatrix (A,MSIZE,MSIZE,1.0); dMultiply2 (L,A,A,MSIZE,MSIZE,MSIZE); memcpy (A,L,MSIZE4*MSIZE*sizeof(dReal)); dMakeRandomMatrix (b,MSIZE,1,1.0); memcpy (x,b,MSIZE*sizeof(dReal)); dFactorLDLT (L,d,MSIZE,MSIZE4); dSolveLDLT (L,d,x,MSIZE,MSIZE4); dMultiply2 (btest,A,x,MSIZE,MSIZE,1); diff = dMaxDifference(b,btest,MSIZE,1); printf ("\tmaximum difference = %.6e - %s\n",diff, diff > tol ? "FAILED" : "passed"); dFree(btest, vectorSize); dFree(b, vectorSize); dFree(x, vectorSize); dFree(d, vectorSize); dFree(L, matrixSize); dFree(A, matrixSize); } void testCoopSolveLDLT() { const dsizeint COOP_MSIZE = MSIZE * 51, COOP_MSIZE4 = dALIGN_SIZE(COOP_MSIZE, 4); dsizeint matrixSize = sizeof(dReal) * COOP_MSIZE4 * COOP_MSIZE, vectorSize = sizeof(dReal) * COOP_MSIZE; dReal *A = (dReal *)dAlloc(matrixSize), *L = (dReal *)dAlloc(matrixSize), *d = (dReal *)dAlloc(vectorSize), *x = (dReal *)dAlloc(vectorSize), *b = (dReal *)dAlloc(vectorSize), *btest = (dReal *)dAlloc(vectorSize), diff; const unsigned threadCountMaximum = 8; dThreadingImplementationID threading = dThreadingAllocateMultiThreadedImplementation(); dCooperativeID cooperative = dCooperativeCreate(dThreadingImplementationGetFunctions(threading), threading); dThreadingThreadPoolID pool = dThreadingAllocateThreadPool(threadCountMaximum, 0, dAllocateFlagBasicData, NULL); dThreadingThreadPoolServeMultiThreadedImplementation(pool, threading); dResourceRequirementsID requirements = dResourceRequirementsCreate(cooperative); dEstimateCooperativelySolveLDLTResourceRequirements(requirements, threadCountMaximum, COOP_MSIZE); dResourceContainerID resources = dResourceContainerAcquire(requirements); HEADER; for (int pass = 0; pass != 4; ++pass) { dTimerStart ("Solving LDLT"); const unsigned allowedThreads = 4; const unsigned PASS_MSIZE = COOP_MSIZE - pass, PASS_MSIZE4 = dALIGN_SIZE(PASS_MSIZE, 4); dTimerNow ("Preparing data"); dMakeRandomMatrix (b, PASS_MSIZE, 1, 1.0); dMakeRandomMatrix (L, PASS_MSIZE, PASS_MSIZE, 1.0); dMultiply2 (A, L, L, PASS_MSIZE, PASS_MSIZE, PASS_MSIZE); memcpy (x, b, PASS_MSIZE * sizeof(dReal)); memcpy (L, A, sizeof(dReal) * PASS_MSIZE4 * PASS_MSIZE); dTimerNow ("Factoring"); dFactorLDLT (L, d, PASS_MSIZE, PASS_MSIZE4); dTimerNow ("Solving multi-threaded"); dCooperativelySolveLDLT(resources, allowedThreads, L, d, x, PASS_MSIZE, PASS_MSIZE4); dTimerNow ("Verifying solution"); dMultiply2 (btest, A, x, PASS_MSIZE, PASS_MSIZE, 1); diff = dMaxDifference(b, btest, PASS_MSIZE, 1); printf ("\tN=%u: maximum difference = %.6e - %s\n", PASS_MSIZE, diff, diff > 1e2 * tol ? "FAILED" : "passed"); dTimerEnd(); dTimerReport(stdout, 0); } dResourceContainerDestroy(resources); dResourceRequirementsDestroy(requirements); dThreadingImplementationShutdownProcessing(threading); dThreadingFreeThreadPool(pool); dCooperativeDestroy(cooperative); dThreadingFreeImplementation(threading); dFree(btest, vectorSize); dFree(b, vectorSize); dFree(x, vectorSize); dFree(d, vectorSize); dFree(L, matrixSize); dFree(A, matrixSize); } void testLDLTAddTL() { int i,j; dsizeint matrixSize = sizeof(dReal) * MSIZE4 * MSIZE, vectorSize = sizeof(dReal) * MSIZE; dReal *A = (dReal *)dAlloc(matrixSize), *L = (dReal *)dAlloc(matrixSize), *DL = (dReal *)dAlloc(matrixSize), *ATEST = (dReal *)dAlloc(matrixSize), *d = (dReal *)dAlloc(vectorSize), *a = (dReal *)dAlloc(vectorSize), diff; HEADER; dMakeRandomMatrix (A,MSIZE,MSIZE,1.0); dMultiply2 (L,A,A,MSIZE,MSIZE,MSIZE); memcpy (A,L,MSIZE4*MSIZE*sizeof(dReal)); dFactorLDLT (L,d,MSIZE,MSIZE4); // delete first row and column of factorization for (i=0; i tol ? "FAILED" : "passed"); dFree(a, vectorSize); dFree(d, vectorSize); dFree(ATEST, matrixSize); dFree(DL, matrixSize); dFree(L, matrixSize); dFree(A, matrixSize); } void testLDLTRemove() { int i,j,r; dsizeint intVectorSize = sizeof(int) * MSIZE, matrixSize = sizeof(dReal) * MSIZE4 * MSIZE, vectorSize = sizeof(dReal) * MSIZE; int *p = (int *)dAlloc(intVectorSize); dReal *A = (dReal *)dAlloc(matrixSize), *L = (dReal *)dAlloc(matrixSize), *L2 = (dReal *)dAlloc(matrixSize), *DL2 = (dReal *)dAlloc(matrixSize), *Atest1 = (dReal *)dAlloc(matrixSize), *Atest2 = (dReal *)dAlloc(matrixSize), *d = (dReal *)dAlloc(vectorSize), *d2 = (dReal *)dAlloc(vectorSize), diff, maxdiff; HEADER; // make array of A row pointers dReal *Arows[MSIZE]; for (i=0; i= r) ii--; if (jj >= r) jj--; if (A[i*MSIZE4+j] != Atest1[ii*MSIZE4+jj]) bad = 1; } } } if (bad) printf ("\trow/col removal FAILED for row %d\n",r); // zero out last row/column of Atest1 for (i=0; i tol ? "FAILED" : "passed"); dFree(d2, vectorSize); dFree(d, vectorSize); dFree(Atest2, matrixSize); dFree(Atest1, matrixSize); dFree(DL2, matrixSize); dFree(L2, matrixSize); dFree(L, matrixSize); dFree(A, matrixSize); } //**************************************************************************** // test mass stuff #define NUMP 10 // number of particles void printMassParams (dMass *m) { printf ("mass = %.4f\n",m->mass); printf ("com = (%.4f,%.4f,%.4f)\n",m->c[0],m->c[1],m->c[2]); printf ("I = [ %10.4f %10.4f %10.4f ]\n" " [ %10.4f %10.4f %10.4f ]\n" " [ %10.4f %10.4f %10.4f ]\n", m->_I(0,0),m->_I(0,1),m->_I(0,2), m->_I(1,0),m->_I(1,1),m->_I(1,2), m->_I(2,0),m->_I(2,1),m->_I(2,2)); } void compareMassParams (dMass *m1, dMass *m2, const char *msg) { int i,j,ok = 1; if (!(cmp(m1->mass,m2->mass) && cmp(m1->c[0],m2->c[0]) && cmp(m1->c[1],m2->c[1]) && cmp(m1->c[2],m2->c[2]))) ok = 0; for (i=0; i<3; i++) for (j=0; j<3; j++) if (cmp (m1->_I(i,j),m2->_I(i,j))==0) ok = 0; if (ok) printf ("\tpassed (%s)\n",msg); else printf ("\tFAILED (%s)\n",msg); } // compute the mass parameters of a particle set void computeMassParams (dMass *m, dReal q[NUMP][3], dReal pm[NUMP]) { int i,j; dMassSetZero (m); for (i=0; imass += pm[i]; for (j=0; j<3; j++) m->c[j] += pm[i]*q[i][j]; m->_I(0,0) += pm[i]*(q[i][1]*q[i][1] + q[i][2]*q[i][2]); m->_I(1,1) += pm[i]*(q[i][0]*q[i][0] + q[i][2]*q[i][2]); m->_I(2,2) += pm[i]*(q[i][0]*q[i][0] + q[i][1]*q[i][1]); m->_I(0,1) -= pm[i]*(q[i][0]*q[i][1]); m->_I(0,2) -= pm[i]*(q[i][0]*q[i][2]); m->_I(1,2) -= pm[i]*(q[i][1]*q[i][2]); } for (j=0; j<3; j++) m->c[j] /= m->mass; m->_I(1,0) = m->_I(0,1); m->_I(2,0) = m->_I(0,2); m->_I(2,1) = m->_I(1,2); } void testMassFunctions() { dMass m; int i,j; dReal q[NUMP][3]; // particle positions dReal pm[NUMP]; // particle masses dMass m1,m2; dMatrix3 R; HEADER; printf ("\t"); dMassSetZero (&m); TRAP_MESSAGE (dMassSetParameters (&m,10, 0,0,0, 1,2,3, 4,5,6), printf (" FAILED (1)\n"), printf (" passed (1)\n")); printf ("\t"); dMassSetZero (&m); TRAP_MESSAGE (dMassSetParameters (&m,10, 0.1,0.2,0.15, 3,5,14, 3.1,3.2,4), printf ("passed (2)\n") , printf (" FAILED (2)\n")); if (m.mass==10 && m.c[0]==REAL(0.1) && m.c[1]==REAL(0.2) && m.c[2]==REAL(0.15) && m._I(0,0)==3 && m._I(1,1)==5 && m._I(2,2)==14 && m._I(0,1)==REAL(3.1) && m._I(0,2)==REAL(3.2) && m._I(1,2)==4 && m._I(1,0)==REAL(3.1) && m._I(2,0)==REAL(3.2) && m._I(2,1)==4) printf ("\tpassed (3)\n"); else printf ("\tFAILED (3)\n"); dMassSetZero (&m); dMassSetSphere (&m,1.4, 0.86); if (cmp(m.mass,3.73002719949386) && m.c[0]==0 && m.c[1]==0 && m.c[2]==0 && cmp(m._I(0,0),1.10349124669826) && cmp(m._I(1,1),1.10349124669826) && cmp(m._I(2,2),1.10349124669826) && m._I(0,1)==0 && m._I(0,2)==0 && m._I(1,2)==0 && m._I(1,0)==0 && m._I(2,0)==0 && m._I(2,1)==0) printf ("\tpassed (4)\n"); else printf ("\tFAILED (4)\n"); dMassSetZero (&m); dMassSetCapsule (&m,1.3,1,0.76,1.53); if (cmp(m.mass,5.99961928996029) && m.c[0]==0 && m.c[1]==0 && m.c[2]==0 && cmp(m._I(0,0),1.59461986077384) && cmp(m._I(1,1),4.21878433864904) && cmp(m._I(2,2),4.21878433864904) && m._I(0,1)==0 && m._I(0,2)==0 && m._I(1,2)==0 && m._I(1,0)==0 && m._I(2,0)==0 && m._I(2,1)==0) printf ("\tpassed (5)\n"); else printf ("\tFAILED (5)\n"); dMassSetZero (&m); dMassSetBox (&m,0.27,3,4,5); if (cmp(m.mass,16.2) && m.c[0]==0 && m.c[1]==0 && m.c[2]==0 && cmp(m._I(0,0),55.35) && cmp(m._I(1,1),45.9) && cmp(m._I(2,2),33.75) && m._I(0,1)==0 && m._I(0,2)==0 && m._I(1,2)==0 && m._I(1,0)==0 && m._I(2,0)==0 && m._I(2,1)==0) printf ("\tpassed (6)\n"); else printf ("\tFAILED (6)\n"); // test dMassAdjust? // make random particles and compute the mass, COM and inertia, then // translate and repeat. for (i=0; i Q -> R works dReal maxdiff=0; for (i=0; i<100; i++) { makeRandomRotation (R); dRtoQ (R,q); dQtoR (q,R2); dReal diff = dMaxDifference (R,R2,3,3); if (diff > maxdiff) maxdiff = diff; } printf ("\tmaximum difference = %e - %s (3)\n",maxdiff, (maxdiff > tol) ? "FAILED" : "passed"); } void testQuaternionMultiply() { HEADER; dMatrix3 RA,RB,RC,Rtest; dQuaternion qa,qb,qc; dReal diff,maxdiff=0; for (int i=0; i<100; i++) { makeRandomRotation (RB); makeRandomRotation (RC); dRtoQ (RB,qb); dRtoQ (RC,qc); dMultiply0 (RA,RB,RC,3,3,3); dQMultiply0 (qa,qb,qc); dQtoR (qa,Rtest); diff = dMaxDifference (Rtest,RA,3,3); if (diff > maxdiff) maxdiff = diff; dMultiply1 (RA,RB,RC,3,3,3); dQMultiply1 (qa,qb,qc); dQtoR (qa,Rtest); diff = dMaxDifference (Rtest,RA,3,3); if (diff > maxdiff) maxdiff = diff; dMultiply2 (RA,RB,RC,3,3,3); dQMultiply2 (qa,qb,qc); dQtoR (qa,Rtest); diff = dMaxDifference (Rtest,RA,3,3); if (diff > maxdiff) maxdiff = diff; dMultiply0 (RA,RC,RB,3,3,3); transpose3x3 (RA); dQMultiply3 (qa,qb,qc); dQtoR (qa,Rtest); diff = dMaxDifference (Rtest,RA,3,3); if (diff > maxdiff) maxdiff = diff; } printf ("\tmaximum difference = %e - %s\n",maxdiff, (maxdiff > tol) ? "FAILED" : "passed"); } void testRotationFunctions() { dMatrix3 R1; HEADER; printf ("\tdRSetIdentity - "); dMakeRandomMatrix (R1,3,3,1.0); dRSetIdentity (R1); if (cmpIdentityMat3(R1)) printf ("passed\n"); else printf ("FAILED\n"); printf ("\tdRFromAxisAndAngle - "); printf ("\n"); printf ("\tdRFromEulerAngles - "); printf ("\n"); printf ("\tdRFrom2Axes - "); printf ("\n"); } //**************************************************************************** #include template class simplevector { private: int n; int max; T* data; public: simplevector() { initialize(); } ~simplevector() { finalize(); } T& operator[](int i) { assert(i>=0 && i=0 && i mat; int afterfirst,index; public: dMatrixComparison(); ~dMatrixComparison(); dReal nextMatrix (dReal *A, int n, int m, int lower_tri, const char *name, ...); // add a new n*m matrix A to the sequence. the name of the matrix is given // by the printf-style arguments (name,...). if this is the first sequence // then this object will simply record the matrices and return 0. // if this the second or subsequent sequence then this object will compare // the matrices with the first sequence, and report any differences. // the matrix error will be returned. if `lower_tri' is 1 then only the // lower triangle of the matrix (including the diagonal) will be compared // (the matrix must be square). void end(); // end a sequence. void reset(); // restarts the object, so the next sequence will be the first sequence. void dump(); // print out info about all the matrices in the sequence }; struct dMatrixComparison::dMatInfo { int n,m; // size of matrix char name[128]; // name of the matrix dReal *data; // matrix data int size; // size of `data' }; dMatrixComparison::dMatrixComparison() { afterfirst = 0; index = 0; } dMatrixComparison::~dMatrixComparison() { reset(); } dReal dMatrixComparison::nextMatrix (dReal *A, int n, int m, int lower_tri, const char *name, ...) { if (A==0 || n < 1 || m < 1 || name==0) dDebug (0,"bad args to nextMatrix"); int num = n*dPAD(m); if (afterfirst==0) { dMatInfo *mi = (dMatInfo*) dAlloc (sizeof(dMatInfo)); mi->n = n; mi->m = m; mi->size = num * sizeof(dReal); mi->data = (dReal*) dAlloc (mi->size); memcpy (mi->data,A,mi->size); va_list ap; va_start (ap,name); vsprintf (mi->name,name,ap); va_end (ap); if (strlen(mi->name) >= sizeof (mi->name)) dDebug (0,"name too long"); mat.push_back(mi); return 0; } else { if (lower_tri && n != m) dDebug (0,"dMatrixComparison, lower triangular matrix must be square"); if (index >= mat.size()) dDebug (0,"dMatrixComparison, too many matrices"); dMatInfo *mp = mat[index]; index++; dMatInfo mi; va_list ap; va_start (ap,name); vsprintf (mi.name,name,ap); va_end (ap); if (strlen(mi.name) >= sizeof (mi.name)) dDebug (0,"name too long"); if (strcmp(mp->name,mi.name) != 0) dDebug (0,"dMatrixComparison, name mismatch (\"%s\" and \"%s\")", mp->name,mi.name); if (mp->n != n || mp->m != m) dDebug (0,"dMatrixComparison, size mismatch (%dx%d and %dx%d)", mp->n,mp->m,n,m); dReal maxdiff; if (lower_tri) { maxdiff = dMaxDifferenceLowerTriangle (A,mp->data,n); } else { maxdiff = dMaxDifference (A,mp->data,n,m); } if (maxdiff > tol) dDebug (0,"dMatrixComparison, matrix error (size=%dx%d, name=\"%s\", " "error=%.4e)",n,m,mi.name,maxdiff); return maxdiff; } } void dMatrixComparison::end() { if (mat.size() <= 0) dDebug (0,"no matrices in sequence"); afterfirst = 1; index = 0; } void dMatrixComparison::reset() { for (int i=0; idata,mat[i]->size); dFree (mat[i],sizeof(dMatInfo)); } mat.clear(); afterfirst = 0; index = 0; } void dMatrixComparison::dump() { for (int i=0; iname,mat[i]->n,mat[i]->m); } //**************************************************************************** // unit test #include // static jmp_buf jump_buffer; static void myDebug (int /*num*/, const char* /*msg*/, va_list /*ap*/) { // printf ("(Error %d: ",num); // vprintf (msg,ap); // printf (")\n"); longjmp (jump_buffer,1); } extern "C" void dTestMatrixComparison() { volatile int i; printf ("dTestMatrixComparison()\n"); dMessageFunction *orig_debug = dGetDebugHandler(); dMatrixComparison mc; dReal A[50*50]; // make first sequence unsigned long seed = dRandGetSeed(); for (i=1; i<49; i++) { dMakeRandomMatrix (A,i,i+1,1.0); mc.nextMatrix (A,i,i+1,0,"A%d",i); } mc.end(); //mc.dump(); // test identical sequence dSetDebugHandler (&myDebug); dRandSetSeed (seed); if (setjmp (jump_buffer)) { printf ("\tFAILED (1)\n"); } else { for (i=1; i<49; i++) { dMakeRandomMatrix (A,i,i+1,1.0); mc.nextMatrix (A,i,i+1,0,"A%d",i); } mc.end(); printf ("\tpassed (1)\n"); } dSetDebugHandler (orig_debug); // test broken sequences (with matrix error) dRandSetSeed (seed); volatile int passcount = 0; for (i=1; i<49; i++) { if (setjmp (jump_buffer)) { passcount++; } else { dSetDebugHandler (&myDebug); dMakeRandomMatrix (A,i,i+1,1.0); A[(i-1)*dPAD(i+1)+i] += REAL(0.01); mc.nextMatrix (A,i,i+1,0,"A%d",i); dSetDebugHandler (orig_debug); } } mc.end(); printf ("\t%s (2)\n",(passcount == 48) ? "passed" : "FAILED"); // test broken sequences (with name error) dRandSetSeed (seed); passcount = 0; for (i=1; i<49; i++) { if (setjmp (jump_buffer)) { passcount++; } else { dSetDebugHandler (&myDebug); dMakeRandomMatrix (A,i,i+1,1.0); mc.nextMatrix (A,i,i+1,0,"B%d",i); dSetDebugHandler (orig_debug); } } mc.end(); printf ("\t%s (3)\n",(passcount == 48) ? "passed" : "FAILED"); // test identical sequence again dSetDebugHandler (&myDebug); dRandSetSeed (seed); if (setjmp (jump_buffer)) { printf ("\tFAILED (4)\n"); } else { for (i=1; i<49; i++) { dMakeRandomMatrix (A,i,i+1,1.0); mc.nextMatrix (A,i,i+1,0,"A%d",i); } mc.end(); printf ("\tpassed (4)\n"); } dSetDebugHandler (orig_debug); } //**************************************************************************** // internal unit tests extern "C" void dTestDataStructures(); extern "C" void dTestMatrixComparison(); extern "C" int dTestSolveLCP(); int main() { dInitODE(); testRandomNumberGenerator(); testInfinity(); testPad(); testCrossProduct(); testSetZero(); testNormalize3(); //testReorthonormalize(); ... not any more testPlaneSpace(); testMatrixMultiply(); testSmallMatrixMultiply(); testCholeskyFactorization(); testCholeskySolve(); testInvertPDMatrix(); testIsPositiveDefinite(); testFastLDLTFactorization(); testCoopLDLTFactorization(); testSolveLDLT(); testCoopSolveLDLT(); testLDLTAddTL(); testLDLTRemove(); testMassFunctions(); testRtoQandQtoR(); testQuaternionMultiply(); testRotationFunctions(); dTestMatrixComparison(); dTestSolveLCP(); // dTestDataStructures(); dCloseODE(); return 0; } ode-0.16/ode/demo/demo_cards.cpp0000664000175200017520000001505413403272463013446 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include #include #include "texturepath.h" #ifdef dDOUBLE #define dsDrawBox dsDrawBoxD #endif static int levels = 5; static int ncards = 0; static dSpaceID space; static dWorldID world; static dJointGroupID contactgroup; struct Card { dBodyID body; dGeomID geom; static const dReal sides[3]; Card() { body = dBodyCreate(world); geom = dCreateBox(space, sides[0], sides[1], sides[2]); dGeomSetBody(geom, body); dGeomSetData(geom, this); dMass mass; mass.setBox(1, sides[0], sides[1], sides[2]); dBodySetMass(body, &mass); } ~Card() { dBodyDestroy(body); dGeomDestroy(geom); } void draw() const { dsDrawBox(dBodyGetPosition(body), dBodyGetRotation(body), sides); } }; static const dReal cwidth=.5, cthikness=.02, clength=1; const dReal Card::sides[3] = { cwidth, cthikness, clength }; std::vector cards; int getncards(int levels) { return (3*levels*levels + levels) / 2; } void place_cards() { ncards = getncards(levels); // destroy removed cards (if any) int oldcards = cards.size(); for (int i=ncards; ibody, 0, -n*hstep + hstep*i, height ); if (i%2) dBodySetRotation(cards[c]->body, left); else dBodySetRotation(cards[c]->body, right); } if (n==1) // top of the house break; // horizontal cards for (int i=0; ibody, 0, -(n-1 - (clength-hstep)/2)*hstep + 2*hstep*i, height + vstep/2); dBodySetRotation(cards[c]->body, hrot); } } } void start() { puts("Controls:"); puts(" SPACE - reposition cards"); puts(" - - one less level"); puts(" = - one more level"); } static void nearCallback (void *, dGeomID o1, dGeomID o2) { // exit without doing anything if the two bodies are connected by a joint dBodyID b1 = dGeomGetBody(o1); dBodyID b2 = dGeomGetBody(o2); const int MAX_CONTACTS = 8; dContact contact[MAX_CONTACTS]; int numc = dCollide (o1, o2, MAX_CONTACTS, &contact[0].geom, sizeof(dContact)); for (int i=0; idraw(); } } void command(int c) { switch (c) { case '=': levels++; place_cards(); break; case '-': levels--; if (levels <= 0) levels++; place_cards(); break; case ' ': place_cards(); break; } } int main(int argc, char **argv) { dInitODE(); // setup pointers to drawstuff callback functions dsFunctions fn; fn.version = DS_VERSION; fn.start = &start; fn.step = &simLoop; fn.command = &command; fn.stop = 0; fn.path_to_textures = DRAWSTUFF_TEXTURE_PATH; world = dWorldCreate(); dWorldSetGravity(world, 0, 0, -0.5); dWorldSetQuickStepNumIterations(world, 50); // <-- increase for more stability space = dSimpleSpaceCreate(0); contactgroup = dJointGroupCreate(0); dGeomID ground = dCreatePlane(space, 0, 0, 1, 0); place_cards(); // run simulation dsSimulationLoop (argc, argv, 640, 480, &fn); levels = 0; place_cards(); dJointGroupDestroy(contactgroup); dWorldDestroy(world); dGeomDestroy(ground); dSpaceDestroy(space); dCloseODE(); } ode-0.16/ode/demo/demo_friction.cpp0000664000175200017520000001367713403272463014200 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ /* test the Coulomb friction approximation. a 10x10 array of boxes is made, each of which rests on the ground. a horizantal force is applied to each box to try and get it to slide. box[i][j] has a mass (i+1)*MASS and a force (j+1)*FORCE. by the Coloumb friction model, the box should only slide if the force is greater than MU times the contact normal force, i.e. f > MU * body_mass * GRAVITY (j+1)*FORCE > MU * (i+1)*MASS * GRAVITY (j+1) > (i+1) * (MU*MASS*GRAVITY/FORCE) (j+1) > (i+1) * k this should be independent of the number of contact points, as N contact points will each have 1/N'th the normal force but the pushing force will have to overcome N contacts. the constants are chosen so that k=1. thus you should see a triangle made of half the bodies in the array start to slide. */ #include #include #include "texturepath.h" #ifdef _MSC_VER #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints #endif // select correct drawing functions #ifdef dDOUBLE #define dsDrawBox dsDrawBoxD #define dsDrawSphere dsDrawSphereD #define dsDrawCylinder dsDrawCylinderD #define dsDrawCapsule dsDrawCapsuleD #endif // some constants #define LENGTH 0.2 // box length & width #define HEIGHT 0.05 // box height #define MASS 0.2 // mass of box[i][j] = (i+1) * MASS #define FORCE 0.05 // force applied to box[i][j] = (j+1) * FORCE #define MU 0.5 // the global mu to use #define GRAVITY 0.5 // the global gravity to use #define N1 10 // number of different forces to try #define N2 10 // number of different masses to try // dynamics and collision objects static dWorldID world; static dSpaceID space; static dBodyID body[N1][N2]; static dJointGroupID contactgroup; static dGeomID ground; static dGeomID box[N1][N2]; // this is called by dSpaceCollide when two objects in space are // potentially colliding. static void nearCallback (void *, dGeomID o1, dGeomID o2) { int i; // only collide things with the ground int g1 = (o1 == ground); int g2 = (o2 == ground); if (!(g1 ^ g2)) return; dBodyID b1 = dGeomGetBody(o1); dBodyID b2 = dGeomGetBody(o2); dContact contact[3]; // up to 3 contacts per box for (i=0; i<3; i++) { contact[i].surface.mode = dContactSoftCFM | dContactApprox1; contact[i].surface.mu = MU; contact[i].surface.soft_cfm = 0.01; } if (int numc = dCollide (o1,o2,3,&contact[0].geom,sizeof(dContact))) { for (i=0; i&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ noinst_PROGRAMS = demo_boxstack$(EXEEXT) demo_buggy$(EXEEXT) \ demo_cards$(EXEEXT) demo_chain1$(EXEEXT) demo_chain2$(EXEEXT) \ demo_collision$(EXEEXT) demo_convex$(EXEEXT) \ demo_crash$(EXEEXT) demo_cylvssphere$(EXEEXT) \ demo_dball$(EXEEXT) demo_dhinge$(EXEEXT) \ demo_transmission$(EXEEXT) demo_feedback$(EXEEXT) \ demo_friction$(EXEEXT) demo_gyroscopic$(EXEEXT) \ demo_gyro2$(EXEEXT) demo_heightfield$(EXEEXT) \ demo_hinge$(EXEEXT) demo_I$(EXEEXT) demo_jointPR$(EXEEXT) \ demo_joints$(EXEEXT) demo_jointPU$(EXEEXT) \ demo_kinematic$(EXEEXT) demo_motion$(EXEEXT) \ demo_motor$(EXEEXT) demo_ode$(EXEEXT) demo_piston$(EXEEXT) \ demo_plane2d$(EXEEXT) demo_rfriction$(EXEEXT) \ demo_slider$(EXEEXT) demo_space$(EXEEXT) \ demo_space_stress$(EXEEXT) demo_step$(EXEEXT) \ demo_tracks$(EXEEXT) $(am__EXEEXT_1) @TRIMESH_TRUE@am__append_1 = \ @TRIMESH_TRUE@ demo_basket \ @TRIMESH_TRUE@ demo_cyl \ @TRIMESH_TRUE@ demo_moving_trimesh \ @TRIMESH_TRUE@ demo_moving_convex \ @TRIMESH_TRUE@ demo_trimesh @TRIMESH_TRUE@am__append_2 = -DdTRIMESH_ENABLED @WIN32_TRUE@am__append_3 = resources.o subdir = ode/demo ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/ode/src/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = @TRIMESH_TRUE@am__EXEEXT_1 = demo_basket$(EXEEXT) demo_cyl$(EXEEXT) \ @TRIMESH_TRUE@ demo_moving_trimesh$(EXEEXT) \ @TRIMESH_TRUE@ demo_moving_convex$(EXEEXT) \ @TRIMESH_TRUE@ demo_trimesh$(EXEEXT) PROGRAMS = $(noinst_PROGRAMS) demo_I_SOURCES = demo_I.cpp demo_I_OBJECTS = demo_I.$(OBJEXT) demo_I_LDADD = $(LDADD) demo_I_DEPENDENCIES = $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = demo_basket_SOURCES = demo_basket.cpp demo_basket_OBJECTS = demo_basket.$(OBJEXT) demo_basket_LDADD = $(LDADD) demo_basket_DEPENDENCIES = \ $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) demo_boxstack_SOURCES = demo_boxstack.cpp demo_boxstack_OBJECTS = demo_boxstack.$(OBJEXT) demo_boxstack_LDADD = $(LDADD) demo_boxstack_DEPENDENCIES = \ $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) demo_buggy_SOURCES = demo_buggy.cpp demo_buggy_OBJECTS = demo_buggy.$(OBJEXT) demo_buggy_LDADD = $(LDADD) demo_buggy_DEPENDENCIES = \ $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) demo_cards_SOURCES = demo_cards.cpp demo_cards_OBJECTS = demo_cards.$(OBJEXT) demo_cards_LDADD = $(LDADD) demo_cards_DEPENDENCIES = \ $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) am_demo_chain1_OBJECTS = demo_chain1.$(OBJEXT) demo_chain1_OBJECTS = $(am_demo_chain1_OBJECTS) am__DEPENDENCIES_1 = $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) demo_chain1_DEPENDENCIES = $(am__DEPENDENCIES_1) demo_chain2_SOURCES = demo_chain2.cpp demo_chain2_OBJECTS = demo_chain2.$(OBJEXT) demo_chain2_LDADD = $(LDADD) demo_chain2_DEPENDENCIES = \ $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) demo_collision_SOURCES = demo_collision.cpp demo_collision_OBJECTS = demo_collision.$(OBJEXT) demo_collision_LDADD = $(LDADD) demo_collision_DEPENDENCIES = \ $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) demo_convex_SOURCES = demo_convex.cpp demo_convex_OBJECTS = demo_convex.$(OBJEXT) demo_convex_LDADD = $(LDADD) demo_convex_DEPENDENCIES = \ $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) demo_crash_SOURCES = demo_crash.cpp demo_crash_OBJECTS = demo_crash.$(OBJEXT) demo_crash_LDADD = $(LDADD) demo_crash_DEPENDENCIES = \ $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) demo_cyl_SOURCES = demo_cyl.cpp demo_cyl_OBJECTS = demo_cyl.$(OBJEXT) demo_cyl_LDADD = $(LDADD) demo_cyl_DEPENDENCIES = $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) demo_cylvssphere_SOURCES = demo_cylvssphere.cpp demo_cylvssphere_OBJECTS = demo_cylvssphere.$(OBJEXT) demo_cylvssphere_LDADD = $(LDADD) demo_cylvssphere_DEPENDENCIES = \ $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) demo_dball_SOURCES = demo_dball.cpp demo_dball_OBJECTS = demo_dball.$(OBJEXT) demo_dball_LDADD = $(LDADD) demo_dball_DEPENDENCIES = \ $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) demo_dhinge_SOURCES = demo_dhinge.cpp demo_dhinge_OBJECTS = demo_dhinge.$(OBJEXT) demo_dhinge_LDADD = $(LDADD) demo_dhinge_DEPENDENCIES = \ $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) demo_feedback_SOURCES = demo_feedback.cpp demo_feedback_OBJECTS = demo_feedback.$(OBJEXT) demo_feedback_LDADD = $(LDADD) demo_feedback_DEPENDENCIES = \ $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) demo_friction_SOURCES = demo_friction.cpp demo_friction_OBJECTS = demo_friction.$(OBJEXT) demo_friction_LDADD = $(LDADD) demo_friction_DEPENDENCIES = \ $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) demo_gyro2_SOURCES = demo_gyro2.cpp demo_gyro2_OBJECTS = demo_gyro2.$(OBJEXT) demo_gyro2_LDADD = $(LDADD) demo_gyro2_DEPENDENCIES = \ $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) demo_gyroscopic_SOURCES = demo_gyroscopic.cpp demo_gyroscopic_OBJECTS = demo_gyroscopic.$(OBJEXT) demo_gyroscopic_LDADD = $(LDADD) demo_gyroscopic_DEPENDENCIES = \ $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) demo_heightfield_SOURCES = demo_heightfield.cpp demo_heightfield_OBJECTS = demo_heightfield.$(OBJEXT) demo_heightfield_LDADD = $(LDADD) demo_heightfield_DEPENDENCIES = \ $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) demo_hinge_SOURCES = demo_hinge.cpp demo_hinge_OBJECTS = demo_hinge.$(OBJEXT) demo_hinge_LDADD = $(LDADD) demo_hinge_DEPENDENCIES = \ $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) demo_jointPR_SOURCES = demo_jointPR.cpp demo_jointPR_OBJECTS = demo_jointPR.$(OBJEXT) demo_jointPR_LDADD = $(LDADD) demo_jointPR_DEPENDENCIES = \ $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) demo_jointPU_SOURCES = demo_jointPU.cpp demo_jointPU_OBJECTS = demo_jointPU.$(OBJEXT) demo_jointPU_LDADD = $(LDADD) demo_jointPU_DEPENDENCIES = \ $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) demo_joints_SOURCES = demo_joints.cpp demo_joints_OBJECTS = demo_joints.$(OBJEXT) demo_joints_LDADD = $(LDADD) demo_joints_DEPENDENCIES = \ $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) demo_kinematic_SOURCES = demo_kinematic.cpp demo_kinematic_OBJECTS = demo_kinematic.$(OBJEXT) demo_kinematic_LDADD = $(LDADD) demo_kinematic_DEPENDENCIES = \ $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) demo_motion_SOURCES = demo_motion.cpp demo_motion_OBJECTS = demo_motion.$(OBJEXT) demo_motion_LDADD = $(LDADD) demo_motion_DEPENDENCIES = \ $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) demo_motor_SOURCES = demo_motor.cpp demo_motor_OBJECTS = demo_motor.$(OBJEXT) demo_motor_LDADD = $(LDADD) demo_motor_DEPENDENCIES = \ $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) demo_moving_convex_SOURCES = demo_moving_convex.cpp demo_moving_convex_OBJECTS = demo_moving_convex.$(OBJEXT) demo_moving_convex_LDADD = $(LDADD) demo_moving_convex_DEPENDENCIES = \ $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) demo_moving_trimesh_SOURCES = demo_moving_trimesh.cpp demo_moving_trimesh_OBJECTS = demo_moving_trimesh.$(OBJEXT) demo_moving_trimesh_LDADD = $(LDADD) demo_moving_trimesh_DEPENDENCIES = \ $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) demo_ode_SOURCES = demo_ode.cpp demo_ode_OBJECTS = demo_ode.$(OBJEXT) demo_ode_LDADD = $(LDADD) demo_ode_DEPENDENCIES = $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) demo_piston_SOURCES = demo_piston.cpp demo_piston_OBJECTS = demo_piston.$(OBJEXT) demo_piston_LDADD = $(LDADD) demo_piston_DEPENDENCIES = \ $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) demo_plane2d_SOURCES = demo_plane2d.cpp demo_plane2d_OBJECTS = demo_plane2d.$(OBJEXT) demo_plane2d_LDADD = $(LDADD) demo_plane2d_DEPENDENCIES = \ $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) demo_rfriction_SOURCES = demo_rfriction.cpp demo_rfriction_OBJECTS = demo_rfriction.$(OBJEXT) demo_rfriction_LDADD = $(LDADD) demo_rfriction_DEPENDENCIES = \ $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) demo_slider_SOURCES = demo_slider.cpp demo_slider_OBJECTS = demo_slider.$(OBJEXT) demo_slider_LDADD = $(LDADD) demo_slider_DEPENDENCIES = \ $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) demo_space_SOURCES = demo_space.cpp demo_space_OBJECTS = demo_space.$(OBJEXT) demo_space_LDADD = $(LDADD) demo_space_DEPENDENCIES = \ $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) demo_space_stress_SOURCES = demo_space_stress.cpp demo_space_stress_OBJECTS = demo_space_stress.$(OBJEXT) demo_space_stress_LDADD = $(LDADD) demo_space_stress_DEPENDENCIES = \ $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) demo_step_SOURCES = demo_step.cpp demo_step_OBJECTS = demo_step.$(OBJEXT) demo_step_LDADD = $(LDADD) demo_step_DEPENDENCIES = \ $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) demo_tracks_SOURCES = demo_tracks.cpp demo_tracks_OBJECTS = demo_tracks.$(OBJEXT) demo_tracks_LDADD = $(LDADD) demo_tracks_DEPENDENCIES = \ $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) demo_transmission_SOURCES = demo_transmission.cpp demo_transmission_OBJECTS = demo_transmission.$(OBJEXT) demo_transmission_LDADD = $(LDADD) demo_transmission_DEPENDENCIES = \ $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) demo_trimesh_SOURCES = demo_trimesh.cpp demo_trimesh_OBJECTS = demo_trimesh.$(OBJEXT) demo_trimesh_LDADD = $(LDADD) demo_trimesh_DEPENDENCIES = \ $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la $(am__append_3) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/ode/src depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) AM_V_CXX = $(am__v_CXX_@AM_V@) am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = SOURCES = demo_I.cpp demo_basket.cpp demo_boxstack.cpp demo_buggy.cpp \ demo_cards.cpp $(demo_chain1_SOURCES) demo_chain2.cpp \ demo_collision.cpp demo_convex.cpp demo_crash.cpp demo_cyl.cpp \ demo_cylvssphere.cpp demo_dball.cpp demo_dhinge.cpp \ demo_feedback.cpp demo_friction.cpp demo_gyro2.cpp \ demo_gyroscopic.cpp demo_heightfield.cpp demo_hinge.cpp \ demo_jointPR.cpp demo_jointPU.cpp demo_joints.cpp \ demo_kinematic.cpp demo_motion.cpp demo_motor.cpp \ demo_moving_convex.cpp demo_moving_trimesh.cpp demo_ode.cpp \ demo_piston.cpp demo_plane2d.cpp demo_rfriction.cpp \ demo_slider.cpp demo_space.cpp demo_space_stress.cpp \ demo_step.cpp demo_tracks.cpp demo_transmission.cpp \ demo_trimesh.cpp DIST_SOURCES = demo_I.cpp demo_basket.cpp demo_boxstack.cpp \ demo_buggy.cpp demo_cards.cpp $(demo_chain1_SOURCES) \ demo_chain2.cpp demo_collision.cpp demo_convex.cpp \ demo_crash.cpp demo_cyl.cpp demo_cylvssphere.cpp \ demo_dball.cpp demo_dhinge.cpp demo_feedback.cpp \ demo_friction.cpp demo_gyro2.cpp demo_gyroscopic.cpp \ demo_heightfield.cpp demo_hinge.cpp demo_jointPR.cpp \ demo_jointPU.cpp demo_joints.cpp demo_kinematic.cpp \ demo_motion.cpp demo_motor.cpp demo_moving_convex.cpp \ demo_moving_trimesh.cpp demo_ode.cpp demo_piston.cpp \ demo_plane2d.cpp demo_rfriction.cpp demo_slider.cpp \ demo_space.cpp demo_space_stress.cpp demo_step.cpp \ demo_tracks.cpp demo_transmission.cpp demo_trimesh.cpp am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(noinst_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CCD_CFLAGS = @CCD_CFLAGS@ CCD_LIBS = @CCD_LIBS@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXTRA_LIBTOOL_LDFLAGS = @EXTRA_LIBTOOL_LDFLAGS@ FGREP = @FGREP@ GL_LIBS = @GL_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSTDCXX = @LIBSTDCXX@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ ODE_PRECISION = @ODE_PRECISION@ ODE_VERSION = @ODE_VERSION@ ODE_VERSION_INFO = @ODE_VERSION_INFO@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ WINDRES = @WINDRES@ X11_CFLAGS = @X11_CFLAGS@ X11_LIBS = @X11_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_WINDRES = @ac_ct_WINDRES@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include \ -DDRAWSTUFF_TEXTURE_PATH="\"$(abs_top_srcdir)/drawstuff/textures\"" \ $(am__append_2) @X11_TRUE@AM_LDFLAGS = $(X_PRE_LIBS) $(X_LIBS) $(X_EXTRA_LIBS) # On Windows, GL_LIBS must go after libdrawstuff.la. LDADD = $(top_builddir)/drawstuff/src/libdrawstuff.la \ $(top_builddir)/ode/src/libode.la @GL_LIBS@ $(am__append_3) noinst_HEADERS = basket_geom.h bunny_geom.h convex_bunny_geom.h convex_prism.h \ icosahedron_geom.h halton235_geom.h texturepath.h world_geom3.h AM_DEFAULT_SOURCE_EXT = .cpp demo_chain1_SOURCES = demo_chain1.c demo_chain1_LDADD = $(LDADD) -lstdc++ all: all-am .SUFFIXES: .SUFFIXES: .c .cpp .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign ode/demo/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign ode/demo/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list demo_I$(EXEEXT): $(demo_I_OBJECTS) $(demo_I_DEPENDENCIES) $(EXTRA_demo_I_DEPENDENCIES) @rm -f demo_I$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(demo_I_OBJECTS) $(demo_I_LDADD) $(LIBS) demo_basket$(EXEEXT): $(demo_basket_OBJECTS) $(demo_basket_DEPENDENCIES) $(EXTRA_demo_basket_DEPENDENCIES) @rm -f demo_basket$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(demo_basket_OBJECTS) $(demo_basket_LDADD) $(LIBS) demo_boxstack$(EXEEXT): $(demo_boxstack_OBJECTS) $(demo_boxstack_DEPENDENCIES) $(EXTRA_demo_boxstack_DEPENDENCIES) @rm -f demo_boxstack$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(demo_boxstack_OBJECTS) $(demo_boxstack_LDADD) $(LIBS) demo_buggy$(EXEEXT): $(demo_buggy_OBJECTS) $(demo_buggy_DEPENDENCIES) $(EXTRA_demo_buggy_DEPENDENCIES) @rm -f demo_buggy$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(demo_buggy_OBJECTS) $(demo_buggy_LDADD) $(LIBS) demo_cards$(EXEEXT): $(demo_cards_OBJECTS) $(demo_cards_DEPENDENCIES) $(EXTRA_demo_cards_DEPENDENCIES) @rm -f demo_cards$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(demo_cards_OBJECTS) $(demo_cards_LDADD) $(LIBS) demo_chain1$(EXEEXT): $(demo_chain1_OBJECTS) $(demo_chain1_DEPENDENCIES) $(EXTRA_demo_chain1_DEPENDENCIES) @rm -f demo_chain1$(EXEEXT) $(AM_V_CCLD)$(LINK) $(demo_chain1_OBJECTS) $(demo_chain1_LDADD) $(LIBS) demo_chain2$(EXEEXT): $(demo_chain2_OBJECTS) $(demo_chain2_DEPENDENCIES) $(EXTRA_demo_chain2_DEPENDENCIES) @rm -f demo_chain2$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(demo_chain2_OBJECTS) $(demo_chain2_LDADD) $(LIBS) demo_collision$(EXEEXT): $(demo_collision_OBJECTS) $(demo_collision_DEPENDENCIES) $(EXTRA_demo_collision_DEPENDENCIES) @rm -f demo_collision$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(demo_collision_OBJECTS) $(demo_collision_LDADD) $(LIBS) demo_convex$(EXEEXT): $(demo_convex_OBJECTS) $(demo_convex_DEPENDENCIES) $(EXTRA_demo_convex_DEPENDENCIES) @rm -f demo_convex$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(demo_convex_OBJECTS) $(demo_convex_LDADD) $(LIBS) demo_crash$(EXEEXT): $(demo_crash_OBJECTS) $(demo_crash_DEPENDENCIES) $(EXTRA_demo_crash_DEPENDENCIES) @rm -f demo_crash$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(demo_crash_OBJECTS) $(demo_crash_LDADD) $(LIBS) demo_cyl$(EXEEXT): $(demo_cyl_OBJECTS) $(demo_cyl_DEPENDENCIES) $(EXTRA_demo_cyl_DEPENDENCIES) @rm -f demo_cyl$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(demo_cyl_OBJECTS) $(demo_cyl_LDADD) $(LIBS) demo_cylvssphere$(EXEEXT): $(demo_cylvssphere_OBJECTS) $(demo_cylvssphere_DEPENDENCIES) $(EXTRA_demo_cylvssphere_DEPENDENCIES) @rm -f demo_cylvssphere$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(demo_cylvssphere_OBJECTS) $(demo_cylvssphere_LDADD) $(LIBS) demo_dball$(EXEEXT): $(demo_dball_OBJECTS) $(demo_dball_DEPENDENCIES) $(EXTRA_demo_dball_DEPENDENCIES) @rm -f demo_dball$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(demo_dball_OBJECTS) $(demo_dball_LDADD) $(LIBS) demo_dhinge$(EXEEXT): $(demo_dhinge_OBJECTS) $(demo_dhinge_DEPENDENCIES) $(EXTRA_demo_dhinge_DEPENDENCIES) @rm -f demo_dhinge$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(demo_dhinge_OBJECTS) $(demo_dhinge_LDADD) $(LIBS) demo_feedback$(EXEEXT): $(demo_feedback_OBJECTS) $(demo_feedback_DEPENDENCIES) $(EXTRA_demo_feedback_DEPENDENCIES) @rm -f demo_feedback$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(demo_feedback_OBJECTS) $(demo_feedback_LDADD) $(LIBS) demo_friction$(EXEEXT): $(demo_friction_OBJECTS) $(demo_friction_DEPENDENCIES) $(EXTRA_demo_friction_DEPENDENCIES) @rm -f demo_friction$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(demo_friction_OBJECTS) $(demo_friction_LDADD) $(LIBS) demo_gyro2$(EXEEXT): $(demo_gyro2_OBJECTS) $(demo_gyro2_DEPENDENCIES) $(EXTRA_demo_gyro2_DEPENDENCIES) @rm -f demo_gyro2$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(demo_gyro2_OBJECTS) $(demo_gyro2_LDADD) $(LIBS) demo_gyroscopic$(EXEEXT): $(demo_gyroscopic_OBJECTS) $(demo_gyroscopic_DEPENDENCIES) $(EXTRA_demo_gyroscopic_DEPENDENCIES) @rm -f demo_gyroscopic$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(demo_gyroscopic_OBJECTS) $(demo_gyroscopic_LDADD) $(LIBS) demo_heightfield$(EXEEXT): $(demo_heightfield_OBJECTS) $(demo_heightfield_DEPENDENCIES) $(EXTRA_demo_heightfield_DEPENDENCIES) @rm -f demo_heightfield$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(demo_heightfield_OBJECTS) $(demo_heightfield_LDADD) $(LIBS) demo_hinge$(EXEEXT): $(demo_hinge_OBJECTS) $(demo_hinge_DEPENDENCIES) $(EXTRA_demo_hinge_DEPENDENCIES) @rm -f demo_hinge$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(demo_hinge_OBJECTS) $(demo_hinge_LDADD) $(LIBS) demo_jointPR$(EXEEXT): $(demo_jointPR_OBJECTS) $(demo_jointPR_DEPENDENCIES) $(EXTRA_demo_jointPR_DEPENDENCIES) @rm -f demo_jointPR$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(demo_jointPR_OBJECTS) $(demo_jointPR_LDADD) $(LIBS) demo_jointPU$(EXEEXT): $(demo_jointPU_OBJECTS) $(demo_jointPU_DEPENDENCIES) $(EXTRA_demo_jointPU_DEPENDENCIES) @rm -f demo_jointPU$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(demo_jointPU_OBJECTS) $(demo_jointPU_LDADD) $(LIBS) demo_joints$(EXEEXT): $(demo_joints_OBJECTS) $(demo_joints_DEPENDENCIES) $(EXTRA_demo_joints_DEPENDENCIES) @rm -f demo_joints$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(demo_joints_OBJECTS) $(demo_joints_LDADD) $(LIBS) demo_kinematic$(EXEEXT): $(demo_kinematic_OBJECTS) $(demo_kinematic_DEPENDENCIES) $(EXTRA_demo_kinematic_DEPENDENCIES) @rm -f demo_kinematic$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(demo_kinematic_OBJECTS) $(demo_kinematic_LDADD) $(LIBS) demo_motion$(EXEEXT): $(demo_motion_OBJECTS) $(demo_motion_DEPENDENCIES) $(EXTRA_demo_motion_DEPENDENCIES) @rm -f demo_motion$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(demo_motion_OBJECTS) $(demo_motion_LDADD) $(LIBS) demo_motor$(EXEEXT): $(demo_motor_OBJECTS) $(demo_motor_DEPENDENCIES) $(EXTRA_demo_motor_DEPENDENCIES) @rm -f demo_motor$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(demo_motor_OBJECTS) $(demo_motor_LDADD) $(LIBS) demo_moving_convex$(EXEEXT): $(demo_moving_convex_OBJECTS) $(demo_moving_convex_DEPENDENCIES) $(EXTRA_demo_moving_convex_DEPENDENCIES) @rm -f demo_moving_convex$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(demo_moving_convex_OBJECTS) $(demo_moving_convex_LDADD) $(LIBS) demo_moving_trimesh$(EXEEXT): $(demo_moving_trimesh_OBJECTS) $(demo_moving_trimesh_DEPENDENCIES) $(EXTRA_demo_moving_trimesh_DEPENDENCIES) @rm -f demo_moving_trimesh$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(demo_moving_trimesh_OBJECTS) $(demo_moving_trimesh_LDADD) $(LIBS) demo_ode$(EXEEXT): $(demo_ode_OBJECTS) $(demo_ode_DEPENDENCIES) $(EXTRA_demo_ode_DEPENDENCIES) @rm -f demo_ode$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(demo_ode_OBJECTS) $(demo_ode_LDADD) $(LIBS) demo_piston$(EXEEXT): $(demo_piston_OBJECTS) $(demo_piston_DEPENDENCIES) $(EXTRA_demo_piston_DEPENDENCIES) @rm -f demo_piston$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(demo_piston_OBJECTS) $(demo_piston_LDADD) $(LIBS) demo_plane2d$(EXEEXT): $(demo_plane2d_OBJECTS) $(demo_plane2d_DEPENDENCIES) $(EXTRA_demo_plane2d_DEPENDENCIES) @rm -f demo_plane2d$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(demo_plane2d_OBJECTS) $(demo_plane2d_LDADD) $(LIBS) demo_rfriction$(EXEEXT): $(demo_rfriction_OBJECTS) $(demo_rfriction_DEPENDENCIES) $(EXTRA_demo_rfriction_DEPENDENCIES) @rm -f demo_rfriction$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(demo_rfriction_OBJECTS) $(demo_rfriction_LDADD) $(LIBS) demo_slider$(EXEEXT): $(demo_slider_OBJECTS) $(demo_slider_DEPENDENCIES) $(EXTRA_demo_slider_DEPENDENCIES) @rm -f demo_slider$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(demo_slider_OBJECTS) $(demo_slider_LDADD) $(LIBS) demo_space$(EXEEXT): $(demo_space_OBJECTS) $(demo_space_DEPENDENCIES) $(EXTRA_demo_space_DEPENDENCIES) @rm -f demo_space$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(demo_space_OBJECTS) $(demo_space_LDADD) $(LIBS) demo_space_stress$(EXEEXT): $(demo_space_stress_OBJECTS) $(demo_space_stress_DEPENDENCIES) $(EXTRA_demo_space_stress_DEPENDENCIES) @rm -f demo_space_stress$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(demo_space_stress_OBJECTS) $(demo_space_stress_LDADD) $(LIBS) demo_step$(EXEEXT): $(demo_step_OBJECTS) $(demo_step_DEPENDENCIES) $(EXTRA_demo_step_DEPENDENCIES) @rm -f demo_step$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(demo_step_OBJECTS) $(demo_step_LDADD) $(LIBS) demo_tracks$(EXEEXT): $(demo_tracks_OBJECTS) $(demo_tracks_DEPENDENCIES) $(EXTRA_demo_tracks_DEPENDENCIES) @rm -f demo_tracks$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(demo_tracks_OBJECTS) $(demo_tracks_LDADD) $(LIBS) demo_transmission$(EXEEXT): $(demo_transmission_OBJECTS) $(demo_transmission_DEPENDENCIES) $(EXTRA_demo_transmission_DEPENDENCIES) @rm -f demo_transmission$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(demo_transmission_OBJECTS) $(demo_transmission_LDADD) $(LIBS) demo_trimesh$(EXEEXT): $(demo_trimesh_OBJECTS) $(demo_trimesh_DEPENDENCIES) $(EXTRA_demo_trimesh_DEPENDENCIES) @rm -f demo_trimesh$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(demo_trimesh_OBJECTS) $(demo_trimesh_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_I.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_basket.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_boxstack.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_buggy.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_cards.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_chain1.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_chain2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_collision.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_convex.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_crash.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_cyl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_cylvssphere.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_dball.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_dhinge.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_feedback.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_friction.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_gyro2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_gyroscopic.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_heightfield.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_hinge.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_jointPR.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_jointPU.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_joints.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_kinematic.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_motion.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_motor.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_moving_convex.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_moving_trimesh.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_ode.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_piston.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_plane2d.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_rfriction.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_slider.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_space.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_space_stress.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_step.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_tracks.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_transmission.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_trimesh.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< .cpp.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cpp.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cpp.lo: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(HEADERS) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstPROGRAMS cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am .PRECIOUS: Makefile @WIN32_TRUE@resources.o: $(top_srcdir)/drawstuff/src/resources.rc $(top_srcdir)/drawstuff/src/resource.h @WIN32_TRUE@ @WINDRES@ $(top_srcdir)/drawstuff/src/resources.rc -o resources.o # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ode-0.16/ode/demo/demo_motor.cpp0000664000175200017520000001556313403272463013517 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include #include "texturepath.h" #ifdef _MSC_VER #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints #endif // select correct drawing functions #ifdef dDOUBLE #define dsDrawBox dsDrawBoxD #endif // some constants #define SIDE (0.5f) // side length of a box #define MASS (1.0) // mass of a box // dynamics and collision objects static dWorldID world; static dBodyID body[2]; static dGeomID geom[2]; static dJointID lmotor[2]; static dJointID amotor[2]; static dSpaceID space; static dJointGroupID contactgroup; // start simulation - set viewpoint static void start() { dAllocateODEDataForThread(dAllocateMaskAll); static float xyz[3] = {1.0382f,-1.0811f,1.4700f}; static float hpr[3] = {135.0000f,-19.5000f,0.0000f}; dsSetViewpoint (xyz,hpr); printf ("Press 'q,a,z' to control one axis of lmotor connectiong two bodies. (q is +,a is 0, z is -)\n"); printf ("Press 'w,e,r' to control one axis of lmotor connectiong first body with world. (w is +,e is 0, r is -)\n"); } // called when a key pressed static void command (int cmd) { if (cmd == 'q' || cmd == 'Q') { dJointSetLMotorParam(lmotor[0],dParamVel,0); dJointSetLMotorParam(lmotor[0],dParamVel2,0); dJointSetLMotorParam(lmotor[0],dParamVel3,0.1); } else if (cmd == 'a' || cmd == 'A') { dJointSetLMotorParam(lmotor[0],dParamVel,0); dJointSetLMotorParam(lmotor[0],dParamVel2,0); dJointSetLMotorParam(lmotor[0],dParamVel3,0); } else if (cmd == 'z' || cmd == 'Z') { dJointSetLMotorParam(lmotor[0],dParamVel,0); dJointSetLMotorParam(lmotor[0],dParamVel2,0); dJointSetLMotorParam(lmotor[0],dParamVel3,-0.1); } else if (cmd == 'w' || cmd == 'W') { dJointSetLMotorParam(lmotor[1],dParamVel,0.1); dJointSetLMotorParam(lmotor[1],dParamVel2,0); dJointSetLMotorParam(lmotor[1],dParamVel3,0); } else if (cmd == 'e' || cmd == 'E') { dJointSetLMotorParam(lmotor[1],dParamVel,0); dJointSetLMotorParam(lmotor[1],dParamVel2,0); dJointSetLMotorParam(lmotor[1],dParamVel3,0); } else if (cmd == 'r' || cmd == 'R') { dJointSetLMotorParam(lmotor[1],dParamVel,-0.1); dJointSetLMotorParam(lmotor[1],dParamVel2,0); dJointSetLMotorParam(lmotor[1],dParamVel3,0); } } static void nearCallback (void *, dGeomID o1, dGeomID o2) { // exit without doing anything if the two bodies are connected by a joint dBodyID b1 = dGeomGetBody(o1); dBodyID b2 = dGeomGetBody(o2); dContact contact; contact.surface.mode = 0; contact.surface.mu = dInfinity; if (dCollide (o1,o2,1,&contact.geom,sizeof(dContactGeom))) { dJointID c = dJointCreateContact (world,contactgroup,&contact); dJointAttach (c,b1,b2); } } // simulation loop static void simLoop (int pause) { if (!pause) { dSpaceCollide(space,0,&nearCallback); dWorldQuickStep (world,0.05); dJointGroupEmpty(contactgroup); } dReal sides1[3]; dGeomBoxGetLengths(geom[0], sides1); dReal sides2[3]; dGeomBoxGetLengths(geom[1], sides2); dsSetTexture (DS_WOOD); dsSetColor (1,1,0); dsDrawBox (dBodyGetPosition(body[0]),dBodyGetRotation(body[0]),sides1); dsSetColor (0,1,1); dsDrawBox (dBodyGetPosition(body[1]),dBodyGetRotation(body[1]),sides2); } int main (int argc, char **argv) { // setup pointers to drawstuff callback functions dsFunctions fn; fn.version = DS_VERSION; fn.start = &start; fn.step = &simLoop; fn.command = &command; fn.stop = 0; fn.path_to_textures = DRAWSTUFF_TEXTURE_PATH; // create world dInitODE2(0); contactgroup = dJointGroupCreate(0); world = dWorldCreate(); space = dSimpleSpaceCreate(0); dMass m; dMassSetBox (&m,1,SIDE,SIDE,SIDE); dMassAdjust (&m,MASS); body[0] = dBodyCreate (world); dBodySetMass (body[0],&m); dBodySetPosition (body[0],0,0,1); geom[0] = dCreateBox(space,SIDE,SIDE,SIDE); body[1] = dBodyCreate (world); dBodySetMass (body[1],&m); dBodySetPosition (body[1],0,0,2); geom[1] = dCreateBox(space,SIDE,SIDE,SIDE); dGeomSetBody(geom[0],body[0]); dGeomSetBody(geom[1],body[1]); lmotor[0] = dJointCreateLMotor (world,0); dJointAttach (lmotor[0],body[0],body[1]); lmotor[1] = dJointCreateLMotor (world,0); dJointAttach (lmotor[1],body[0],0); amotor[0] = dJointCreateAMotor(world,0); dJointAttach(amotor[0], body[0],body[1]); amotor[1] = dJointCreateAMotor(world,0); dJointAttach(amotor[1], body[0], 0); for (int i=0; i<2; i++) { dJointSetAMotorNumAxes(amotor[i], 3); dJointSetAMotorAxis(amotor[i],0,1,1,0,0); dJointSetAMotorAxis(amotor[i],1,1,0,1,0); dJointSetAMotorAxis(amotor[i],2,1,0,0,1); dJointSetAMotorParam(amotor[i],dParamFMax,0.00001); dJointSetAMotorParam(amotor[i],dParamFMax2,0.00001); dJointSetAMotorParam(amotor[i],dParamFMax3,0.00001); dJointSetAMotorParam(amotor[i],dParamVel,0); dJointSetAMotorParam(amotor[i],dParamVel2,0); dJointSetAMotorParam(amotor[i],dParamVel3,0); dJointSetLMotorNumAxes(lmotor[i],3); dJointSetLMotorAxis(lmotor[i],0,1,1,0,0); dJointSetLMotorAxis(lmotor[i],1,1,0,1,0); dJointSetLMotorAxis(lmotor[i],2,1,0,0,1); dJointSetLMotorParam(lmotor[i],dParamFMax,0.0001); dJointSetLMotorParam(lmotor[i],dParamFMax2,0.0001); dJointSetLMotorParam(lmotor[i],dParamFMax3,0.0001); } // run simulation dsSimulationLoop (argc,argv,352,288,&fn); dJointGroupDestroy(contactgroup); dSpaceDestroy (space); dWorldDestroy (world); dCloseODE(); return 0; } ode-0.16/ode/demo/demo_boxstack.cpp0000664000175200017520000004537713403272463014203 00000000000000/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ #include #include #include "texturepath.h" #ifdef _MSC_VER #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints #endif #include "icosahedron_geom.h" //<---- Convex Object dReal planes[]= // planes for a cube, these should coincide with the face array { 1.0f ,0.0f ,0.0f ,0.25f, 0.0f ,1.0f ,0.0f ,0.25f, 0.0f ,0.0f ,1.0f ,0.25f, -1.0f,0.0f ,0.0f ,0.25f, 0.0f ,-1.0f,0.0f ,0.25f, 0.0f ,0.0f ,-1.0f,0.25f /* 1.0f ,0.0f ,0.0f ,2.0f, 0.0f ,1.0f ,0.0f ,1.0f, 0.0f ,0.0f ,1.0f ,1.0f, 0.0f ,0.0f ,-1.0f,1.0f, 0.0f ,-1.0f,0.0f ,1.0f, -1.0f,0.0f ,0.0f ,0.0f */ }; const unsigned int planecount=6; dReal points[]= // points for a cube { 0.25f,0.25f,0.25f, // point 0 -0.25f,0.25f,0.25f, // point 1 0.25f,-0.25f,0.25f, // point 2 -0.25f,-0.25f,0.25f,// point 3 0.25f,0.25f,-0.25f, // point 4 -0.25f,0.25f,-0.25f,// point 5 0.25f,-0.25f,-0.25f,// point 6 -0.25f,-0.25f,-0.25f,// point 7 }; const unsigned int pointcount=8; unsigned int polygons[] = //Polygons for a cube (6 squares) { 4,0,2,6,4, // positive X 4,1,0,4,5, // positive Y 4,0,1,3,2, // positive Z 4,3,1,5,7, // negative X 4,2,3,7,6, // negative Y 4,5,4,6,7, // negative Z }; //----> Convex Object // select correct drawing functions #ifdef dDOUBLE #define dsDrawBox dsDrawBoxD #define dsDrawSphere dsDrawSphereD #define dsDrawCylinder dsDrawCylinderD #define dsDrawCapsule dsDrawCapsuleD #define dsDrawConvex dsDrawConvexD #endif // some constants #define NUM 100 // max number of objects #define DENSITY (5.0) // density of all objects #define GPB 3 // maximum number of geometries per body #define MAX_CONTACTS 8 // maximum number of contact points per body #define MAX_FEEDBACKNUM 20 #define GRAVITY REAL(0.5) // dynamics and collision objects struct MyObject { dBodyID body; // the body dGeomID geom[GPB]; // geometries representing this body }; static int num=0; // number of objects in simulation static int nextobj=0; // next object to recycle if num==NUM static dWorldID world; static dSpaceID space; static MyObject obj[NUM]; static dJointGroupID contactgroup; static int selected = -1; // selected object static int show_aabb = 0; // show geom AABBs? static int show_contacts = 0; // show contact points? static int random_pos = 1; // drop objects from random position? static int write_world = 0; static int show_body = 0; struct MyFeedback { dJointFeedback fb; bool first; }; static int doFeedback=0; static MyFeedback feedbacks[MAX_FEEDBACKNUM]; static int fbnum=0; // this is called by dSpaceCollide when two objects in space are // potentially colliding. static void nearCallback (void *, dGeomID o1, dGeomID o2) { int i; // if (o1->body && o2->body) return; // exit without doing anything if the two bodies are connected by a joint dBodyID b1 = dGeomGetBody(o1); dBodyID b2 = dGeomGetBody(o2); if (b1 && b2 && dAreConnectedExcluding(b1,b2,dJointTypeContact)) return; dContact contact[MAX_CONTACTS]; // up to MAX_CONTACTS contacts per box-box for (i=0; i= 'A' && c <= 'Z') return c - ('a'-'A'); else return c; } // called when a key pressed static void command(int cmd) { dsizeint i; int j,k; dReal sides[3]; dMass m; bool setBody = false; cmd = locase(cmd); if (cmd == 'b' || cmd == 's' || cmd == 'c' || cmd == 'x' || cmd == 'y' || cmd == 'v') { if (num < NUM) { // new object to be created i = num; num++; } else { // recycle existing object i = nextobj++; nextobj %= num; // wrap-around if needed // destroy the body and geoms for slot i dBodyDestroy (obj[i].body); obj[i].body = 0; for (k=0; k < GPB; k++) if (obj[i].geom[k]) { dGeomDestroy(obj[i].geom[k]); obj[i].geom[k] = 0; } } obj[i].body = dBodyCreate(world); for (k=0; k<3; k++) sides[k] = dRandReal()*0.5+0.1; dMatrix3 R; if (random_pos) { dBodySetPosition(obj[i].body, dRandReal()*2-1,dRandReal()*2-1,dRandReal()+2); dRFromAxisAndAngle(R,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0, dRandReal()*2.0-1.0,dRandReal()*10.0-5.0); } else { // higher than highest body position dReal maxheight = 0; for (k=0; k maxheight) maxheight = pos[2]; } dBodySetPosition(obj[i].body, 0,0,maxheight+1); dRSetIdentity(R); //dRFromAxisAndAngle (R,0,0,1,/*dRandReal()*10.0-5.0*/0); } dBodySetRotation(obj[i].body,R); if (cmd == 'b') { dMassSetBox(&m,DENSITY,sides[0],sides[1],sides[2]); obj[i].geom[0] = dCreateBox(space,sides[0],sides[1],sides[2]); } else if (cmd == 'c') { sides[0] *= 0.5; dMassSetCapsule(&m,DENSITY,3,sides[0],sides[1]); obj[i].geom[0] = dCreateCapsule (space,sides[0],sides[1]); } else if (cmd == 'v') { dMassSetBox(&m,DENSITY,0.25,0.25,0.25); #if 0 obj[i].geom[0] = dCreateConvex(space, planes, planecount, points, pointcount, polygons); #else obj[i].geom[0] = dCreateConvex(space, Sphere_planes, Sphere_planecount, Sphere_points, Sphere_pointcount, Sphere_polygons); #endif } else if (cmd == 'y') { dMassSetCylinder(&m,DENSITY,3,sides[0],sides[1]); obj[i].geom[0] = dCreateCylinder(space,sides[0],sides[1]); } else if (cmd == 's') { sides[0] *= 0.5; dMassSetSphere (&m,DENSITY,sides[0]); obj[i].geom[0] = dCreateSphere (space,sides[0]); } else if (cmd == 'x') { setBody = true; // start accumulating masses for the composite geometries dMass m2; dMassSetZero (&m); dReal dpos[GPB][3]; // delta-positions for composite geometries dMatrix3 drot[GPB]; // set random delta positions for (j=0; j= num) selected = 0; if (selected == -1) selected = 0; } else if (cmd == 'd' && selected >= 0 && selected < num) { dBodyDisable(obj[selected].body); } else if (cmd == 'e' && selected >= 0 && selected < num) { dBodyEnable(obj[selected].body); } else if (cmd == 'a') { show_aabb = !show_aabb; } else if (cmd == 't') { show_contacts = !show_contacts; } else if (cmd == 'r') { random_pos = !random_pos; } else if (cmd == '1') { write_world = 1; } else if (cmd == 'p'&& selected >= 0) { const dReal* pos = dGeomGetPosition(obj[selected].geom[0]); const dReal* rot = dGeomGetRotation(obj[selected].geom[0]); printf("POSITION:\n\t[%f,%f,%f]\n\n",pos[0],pos[1],pos[2]); printf("ROTATION:\n\t[%f,%f,%f,%f]\n\t[%f,%f,%f,%f]\n\t[%f,%f,%f,%f]\n\n", rot[0],rot[1],rot[2],rot[3], rot[4],rot[5],rot[6],rot[7], rot[8],rot[9],rot[10],rot[11]); } else if (cmd == 'f' && selected >= 0 && selected < num) { if (dBodyIsEnabled(obj[selected].body)) doFeedback = 1; } } // draw a geom void drawGeom(dGeomID g, const dReal *pos, const dReal *R, int show_aabb) { int i; if (!g) return; if (!pos) pos = dGeomGetPosition(g); if (!R) R = dGeomGetRotation(g); int type = dGeomGetClass(g); if (type == dBoxClass) { dVector3 sides; dGeomBoxGetLengths (g,sides); dsDrawBox(pos,R,sides); } else if (type == dSphereClass) { dsDrawSphere(pos,R,dGeomSphereGetRadius(g)); } else if (type == dCapsuleClass) { dReal radius,length; dGeomCapsuleGetParams(g,&radius,&length); dsDrawCapsule(pos,R,length,radius); } else if (type == dConvexClass) { #if 0 dsDrawConvex(pos,R,planes, planecount, points, pointcount, polygons); #else dsDrawConvex(pos,R, Sphere_planes, Sphere_planecount, Sphere_points, Sphere_pointcount, Sphere_polygons); #endif } else if (type == dCylinderClass) { dReal radius,length; dGeomCylinderGetParams(g,&radius,&length); dsDrawCylinder(pos,R,length,radius); } if (show_body) { dBodyID body = dGeomGetBody(g); if (body) { const dReal *bodypos = dBodyGetPosition(body); const dReal *bodyr = dBodyGetRotation(body); dReal bodySides[3] = { 0.1, 0.1, 0.1 }; dsSetColorAlpha(0,1,0,1); dsDrawBox(bodypos,bodyr,bodySides); } } if (show_aabb) { // draw the bounding box for this geom dReal aabb[6]; dGeomGetAABB(g,aabb); dVector3 bbpos; for (i=0; i<3; i++) bbpos[i] = 0.5*(aabb[i*2] + aabb[i*2+1]); dVector3 bbsides; for (i=0; i<3; i++) bbsides[i] = aabb[i*2+1] - aabb[i*2]; dMatrix3 RI; dRSetIdentity (RI); dsSetColorAlpha(1,0,0,0.5); dsDrawBox(bbpos,RI,bbsides); } } // simulation loop static void simLoop(int pause) { dSpaceCollide(space, 0, &nearCallback); if (!pause) dWorldQuickStep(world, 0.02); if (write_world) { FILE *f = fopen("state.dif","wt"); if (f) { dWorldExportDIF(world,f,"X"); fclose (f); } write_world = 0; } if (doFeedback) { if (fbnum>MAX_FEEDBACKNUM) printf("joint feedback buffer overflow!\n"); else { dVector3 sum = {0, 0, 0}; printf("\n"); for (int i=0; i #include "ode/ode.h" #include "drawstuff/drawstuff.h" #include "texturepath.h" #ifdef _MSC_VER #pragma warning(disable:4244 4305) /* for VC++, no precision loss complaints */ #endif /* select correct drawing functions */ #ifdef dDOUBLE #define dsDrawBox dsDrawBoxD #define dsDrawSphere dsDrawSphereD #define dsDrawCylinder dsDrawCylinderD #define dsDrawCapsule dsDrawCapsuleD #endif /* some constants */ #define NUM 10 /* number of boxes */ #define SIDE (0.2) /* side length of a box */ #define MASS (1.0) /* mass of a box */ #define RADIUS (0.1732f) /* sphere radius */ /* dynamics and collision objects */ static dWorldID world; static dSpaceID space; static dBodyID body[NUM]; static dJointID joint[NUM-1]; static dJointGroupID contactgroup; static dGeomID sphere[NUM]; /* this is called by dSpaceCollide when two objects in space are * potentially colliding. */ static void nearCallback (void *data, dGeomID o1, dGeomID o2) { /* exit without doing anything if the two bodies are connected by a joint */ dBodyID b1,b2; dContact contact; (void)data; b1 = dGeomGetBody(o1); b2 = dGeomGetBody(o2); if (b1 && b2 && dAreConnected (b1,b2)) return; contact.surface.mode = 0; contact.surface.mu = 0.1; contact.surface.mu2 = 0; if (dCollide (o1,o2,1,&contact.geom,sizeof(dContactGeom))) { dJointID c = dJointCreateContact (world,contactgroup,&contact); dJointAttach (c,b1,b2); } } /* start simulation - set viewpoint */ static void start() { static float xyz[3] = {2.1640f,-1.3079f,1.7600f}; static float hpr[3] = {125.5000f,-17.0000f,0.0000f}; dAllocateODEDataForThread(dAllocateMaskAll); dsSetViewpoint (xyz,hpr); } /* simulation loop */ static void simLoop (int pause) { int i; if (!pause) { static double angle = 0; angle += 0.05; dBodyAddForce (body[NUM-1],0,0,1.5*(sin(angle)+1.0)); dSpaceCollide (space,0,&nearCallback); dWorldStep (world,0.05); /* remove all contact joints */ dJointGroupEmpty (contactgroup); } dsSetColor (1,1,0); dsSetTexture (DS_WOOD); for (i=0; i #include #include #include "texturepath.h" #ifdef _MSC_VER #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints #endif // select correct drawing functions #ifdef dDOUBLE #define dsDrawBox dsDrawBoxD #define dsDrawSphere dsDrawSphereD #define dsDrawCylinder dsDrawCylinderD #define dsDrawCapsule dsDrawCapsuleD #endif // some constants #define NUM 10 // number of bodies #define NUMJ 9 // number of joints #define SIDE (0.2) // side length of a box #define MASS (1.0) // mass of a box #define RADIUS (0.1732f) // sphere radius // dynamics and collision objects static dWorldID world=0; static dBodyID body[NUM]; static dJointID joint[NUMJ]; // create the test system void createTest() { int i,j; if (world) dWorldDestroy (world); world = dWorldCreate(); // create random bodies for (i=0; i #include #include "texturepath.h" #ifdef _MSC_VER #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints #endif // select correct drawing functions #ifdef dDOUBLE #define dsDrawBox dsDrawBoxD #define dsDrawSphere dsDrawSphereD #define dsDrawCylinder dsDrawCylinderD #define dsDrawCapsule dsDrawCapsuleD #endif // some constants #define NUM 20 // number of boxes to test // collision objects and globals static dSpaceID space; static dGeomID geom[NUM]; static dReal bounds[NUM][6]; static dsizeint good_matrix[NUM][NUM]; // correct collision matrix static dsizeint test_matrix[NUM][NUM]; // testing collision matrix static dsizeint hits[NUM]; // number of collisions a box has static unsigned long seed=37; static void init_test() { int i,j; const dReal scale = 0.5; // set random boxes dRandSetSeed (seed); for (i=0; i < NUM; i++) { bounds[i][0] = dRandReal()*2-1; bounds[i][1] = bounds[i][0] + dRandReal()*scale; bounds[i][2] = dRandReal()*2-1; bounds[i][3] = bounds[i][2] + dRandReal()*scale; bounds[i][4] = dRandReal()*2; bounds[i][5] = bounds[i][4] + dRandReal()*scale; if (geom[i]) dGeomDestroy (geom[i]); geom[i] = dCreateBox (space, bounds[i][1] - bounds[i][0], bounds[i][3] - bounds[i][2], bounds[i][5] - bounds[i][4]); dGeomSetPosition (geom[i], (bounds[i][0] + bounds[i][1])*0.5, (bounds[i][2] + bounds[i][3])*0.5, (bounds[i][4] + bounds[i][5])*0.5); dGeomSetData (geom[i],(void*)(dsizeint)(i)); } // compute all intersections and put the results in "good_matrix" for (i=0; i < NUM; i++) { for (j=0; j < NUM; j++) good_matrix[i][j] = 0; } for (i=0; i < NUM; i++) hits[i] = 0; for (i=0; i < NUM; i++) { for (j=i+1; j < NUM; j++) { dReal *bounds1 = &bounds[i][0]; dReal *bounds2 = &bounds[j][0]; if (bounds1[0] > bounds2[1] || bounds1[1] < bounds2[0] || bounds1[2] > bounds2[3] || bounds1[3] < bounds2[2] || bounds1[4] > bounds2[5] || bounds1[5] < bounds2[4]) continue; good_matrix[i][j] = 1; good_matrix[j][i] = 1; hits[i]++; hits[j]++; } } } // this is called by dSpaceCollide when two objects in space are // potentially colliding. static void nearCallback (void *, dGeomID o1, dGeomID o2) { dsizeint i,j; i = (dsizeint) dGeomGetData (o1); j = (dsizeint) dGeomGetData (o2); if (i==j) printf ("collision (%d,%d) is between the same object\n",(int)i,(int)j); if (!good_matrix[i][j] || !good_matrix[j][i]) printf ("collision (%d,%d) is incorrect\n",(int)i,(int)j); if (test_matrix[i][j] || test_matrix[j][i]) printf ("collision (%d,%d) reported more than once\n",(int)i,(int)j); test_matrix[i][j] = 1; test_matrix[j][i] = 1; } // start simulation - set viewpoint static void start() { dAllocateODEDataForThread(dAllocateMaskAll); static float xyz[3] = {2.1640f,-1.3079f,1.7600f}; static float hpr[3] = {125.5000f,-17.0000f,0.0000f}; dsSetViewpoint (xyz,hpr); } static void command (int cmd) { if (cmd == ' ') { seed++; init_test(); } } // simulation loop static void simLoop (int) { int i,j; for (i=0; i < NUM; i++) { for (j=0; j < NUM; j++) test_matrix[i][j] = 0; } dSpaceCollide (space,0,&nearCallback); for (i=0; i < NUM; i++) { for (j=i+1; j < NUM; j++) { if (good_matrix[i][j] && !test_matrix[i][j]) { printf ("failed to report collision (%d,%d) (seed=%ld)\n",i,j,seed); } } } seed++; init_test(); for (i=0; i 0) dsSetColor (1,0,0); else dsSetColor (1,1,0); dsDrawBox (pos,R,side); } } int main (int argc, char **argv) { int i; // setup pointers to drawstuff callback functions dsFunctions fn; fn.version = DS_VERSION; fn.start = &start; fn.step = &simLoop; fn.command = &command; fn.stop = 0; fn.path_to_textures = DRAWSTUFF_TEXTURE_PATH; dInitODE2(0); // test the simple space: // space = dSimpleSpaceCreate(); // test the hash space: // space = dHashSpaceCreate (0); // dHashSpaceSetLevels (space,-10,10); // test the quadtree space dVector3 Center = {0, 0, 0, 0}; dVector3 Extents = {10, 0, 10, 0}; space = dQuadTreeSpaceCreate(0, Center, Extents, 7); for (i=0; i < NUM; i++) geom[i] = 0; init_test(); // run simulation dsSimulationLoop (argc,argv,352,288,&fn); dSpaceDestroy (space); dCloseODE(); return 0; } ode-0.16/ode/demo/bunny_geom.h0000664000175200017520000007372213403272463013163 00000000000000// Bunny mesh ripped from Opcode const int VertexCount = 453; const int IndexCount = 902 * 3; float Vertices[VertexCount * 3] = { -0.334392f, 0.133007f, 0.062259f, -0.350189f, 0.150354f, -0.147769f, -0.234201f, 0.343811f, -0.174307f, -0.200259f, 0.285207f, 0.093749f, 0.003520f, 0.475208f, -0.159365f, 0.001856f, 0.419203f, 0.098582f, -0.252802f, 0.093666f, 0.237538f, -0.162901f, 0.237984f, 0.206905f, 0.000865f, 0.318141f, 0.235370f, -0.414624f, 0.164083f, -0.278254f, -0.262213f, 0.357334f, -0.293246f, 0.004628f, 0.482694f, -0.338626f, -0.402162f, 0.133528f, -0.443247f, -0.243781f, 0.324275f, -0.436763f, 0.005293f, 0.437592f, -0.458332f, -0.339884f, -0.041150f, -0.668211f, -0.248382f, 0.255825f, -0.627493f, 0.006261f, 0.376103f, -0.631506f, -0.216201f, -0.126776f, -0.886936f, -0.171075f, 0.011544f, -0.881386f, -0.181074f, 0.098223f, -0.814779f, -0.119891f, 0.218786f, -0.760153f, -0.078895f, 0.276780f, -0.739281f, 0.006801f, 0.310959f, -0.735661f, -0.168842f, 0.102387f, -0.920381f, -0.104072f, 0.177278f, -0.952530f, -0.129704f, 0.211848f, -0.836678f, -0.099875f, 0.310931f, -0.799381f, 0.007237f, 0.361687f, -0.794439f, -0.077913f, 0.258753f, -0.921640f, 0.007957f, 0.282241f, -0.931680f, -0.252222f, -0.550401f, -0.557810f, -0.267633f, -0.603419f, -0.655209f, -0.446838f, -0.118517f, -0.466159f, -0.459488f, -0.093017f, -0.311341f, -0.370645f, -0.100108f, -0.159454f, -0.371984f, -0.091991f, -0.011044f, -0.328945f, -0.098269f, 0.088659f, -0.282452f, -0.018862f, 0.311501f, -0.352403f, -0.131341f, 0.144902f, -0.364126f, -0.200299f, 0.202388f, -0.283965f, -0.231869f, 0.023668f, -0.298943f, -0.155218f, 0.369716f, -0.293787f, -0.121856f, 0.419097f, -0.290163f, -0.290797f, 0.107824f, -0.264165f, -0.272849f, 0.036347f, -0.228567f, -0.372573f, 0.290309f, -0.190431f, -0.286997f, 0.421917f, -0.191039f, -0.240973f, 0.507118f, -0.287272f, -0.276431f, -0.065444f, -0.295675f, -0.280818f, -0.174200f, -0.399537f, -0.313131f, -0.376167f, -0.392666f, -0.488581f, -0.427494f, -0.331669f, -0.570185f, -0.466054f, -0.282290f, -0.618140f, -0.589220f, -0.374238f, -0.594882f, -0.323298f, -0.381071f, -0.629723f, -0.350777f, -0.382112f, -0.624060f, -0.221577f, -0.272701f, -0.566522f, 0.259157f, -0.256702f, -0.663406f, 0.286079f, -0.280948f, -0.428359f, 0.055790f, -0.184974f, -0.508894f, 0.326265f, -0.279971f, -0.526918f, 0.395319f, -0.282599f, -0.663393f, 0.412411f, -0.188329f, -0.475093f, 0.417954f, -0.263384f, -0.663396f, 0.466604f, -0.209063f, -0.663393f, 0.509344f, -0.002044f, -0.319624f, 0.553078f, -0.001266f, -0.371260f, 0.413296f, -0.219753f, -0.339762f, -0.040921f, -0.256986f, -0.282511f, -0.006349f, -0.271706f, -0.260881f, 0.001764f, -0.091191f, -0.419184f, -0.045912f, -0.114944f, -0.429752f, -0.124739f, -0.113970f, -0.382987f, -0.188540f, -0.243012f, -0.464942f, -0.242850f, -0.314815f, -0.505402f, -0.324768f, 0.002774f, -0.437526f, -0.262766f, -0.072625f, -0.417748f, -0.221440f, -0.160112f, -0.476932f, -0.293450f, 0.003859f, -0.453425f, -0.443916f, -0.120363f, -0.581567f, -0.438689f, -0.091499f, -0.584191f, -0.294511f, -0.116469f, -0.599861f, -0.188308f, -0.208032f, -0.513640f, -0.134649f, -0.235749f, -0.610017f, -0.040939f, -0.344916f, -0.622487f, -0.085380f, -0.336401f, -0.531864f, -0.212298f, 0.001961f, -0.459550f, -0.135547f, -0.058296f, -0.430536f, -0.043440f, 0.001378f, -0.449511f, -0.037762f, -0.130135f, -0.510222f, 0.079144f, 0.000142f, -0.477549f, 0.157064f, -0.114284f, -0.453206f, 0.304397f, -0.000592f, -0.443558f, 0.285401f, -0.056215f, -0.663402f, 0.326073f, -0.026248f, -0.568010f, 0.273318f, -0.049261f, -0.531064f, 0.389854f, -0.127096f, -0.663398f, 0.479316f, -0.058384f, -0.663401f, 0.372891f, -0.303961f, 0.054199f, 0.625921f, -0.268594f, 0.193403f, 0.502766f, -0.277159f, 0.126123f, 0.443289f, -0.287605f, -0.005722f, 0.531844f, -0.231396f, -0.121289f, 0.587387f, -0.253475f, -0.081797f, 0.756541f, -0.195164f, -0.137969f, 0.728011f, -0.167673f, -0.156573f, 0.609388f, -0.145917f, -0.169029f, 0.697600f, -0.077776f, -0.214247f, 0.622586f, -0.076873f, -0.214971f, 0.696301f, -0.002341f, -0.233135f, 0.622859f, -0.002730f, -0.213526f, 0.691267f, -0.003136f, -0.192628f, 0.762731f, -0.056136f, -0.201222f, 0.763806f, -0.114589f, -0.166192f, 0.770723f, -0.155145f, -0.129632f, 0.791738f, -0.183611f, -0.058705f, 0.847012f, -0.165562f, 0.001980f, 0.833386f, -0.220084f, 0.019914f, 0.768935f, -0.255730f, 0.090306f, 0.670782f, -0.255594f, 0.113833f, 0.663389f, -0.226380f, 0.212655f, 0.617740f, -0.003367f, -0.195342f, 0.799680f, -0.029743f, -0.210508f, 0.827180f, -0.003818f, -0.194783f, 0.873636f, -0.004116f, -0.157907f, 0.931268f, -0.031280f, -0.184555f, 0.889476f, -0.059885f, -0.184448f, 0.841330f, -0.135333f, -0.164332f, 0.878200f, -0.085574f, -0.170948f, 0.925547f, -0.163833f, -0.094170f, 0.897114f, -0.138444f, -0.104250f, 0.945975f, -0.083497f, -0.084934f, 0.979607f, -0.004433f, -0.146642f, 0.985872f, -0.150715f, 0.032650f, 0.884111f, -0.135892f, -0.035520f, 0.945455f, -0.070612f, 0.036849f, 0.975733f, -0.004458f, -0.042526f, 1.015670f, -0.004249f, 0.046042f, 1.003240f, -0.086969f, 0.133224f, 0.947633f, -0.003873f, 0.161605f, 0.970499f, -0.125544f, 0.140012f, 0.917678f, -0.125651f, 0.250246f, 0.857602f, -0.003127f, 0.284070f, 0.878870f, -0.159174f, 0.125726f, 0.888878f, -0.183807f, 0.196970f, 0.844480f, -0.159890f, 0.291736f, 0.732480f, -0.199495f, 0.207230f, 0.779864f, -0.206182f, 0.164608f, 0.693257f, -0.186315f, 0.160689f, 0.817193f, -0.192827f, 0.166706f, 0.782271f, -0.175112f, 0.110008f, 0.860621f, -0.161022f, 0.057420f, 0.855111f, -0.172319f, 0.036155f, 0.816189f, -0.190318f, 0.064083f, 0.760605f, -0.195072f, 0.129179f, 0.731104f, -0.203126f, 0.410287f, 0.680536f, -0.216677f, 0.309274f, 0.642272f, -0.241515f, 0.311485f, 0.587832f, -0.002209f, 0.366663f, 0.749413f, -0.088230f, 0.396265f, 0.678635f, -0.170147f, 0.109517f, 0.840784f, -0.160521f, 0.067766f, 0.830650f, -0.181546f, 0.139805f, 0.812146f, -0.180495f, 0.148568f, 0.776087f, -0.180255f, 0.129125f, 0.744192f, -0.186298f, 0.078308f, 0.769352f, -0.167622f, 0.060539f, 0.806675f, -0.189876f, 0.102760f, 0.802582f, -0.108340f, 0.455446f, 0.657174f, -0.241585f, 0.527592f, 0.669296f, -0.265676f, 0.513366f, 0.634594f, -0.203073f, 0.478550f, 0.581526f, -0.266772f, 0.642330f, 0.602061f, -0.216961f, 0.564846f, 0.535435f, -0.202210f, 0.525495f, 0.475944f, -0.193888f, 0.467925f, 0.520606f, -0.265837f, 0.757267f, 0.500933f, -0.240306f, 0.653440f, 0.463215f, -0.309239f, 0.776868f, 0.304726f, -0.271009f, 0.683094f, 0.382018f, -0.312111f, 0.671099f, 0.286687f, -0.268791f, 0.624342f, 0.377231f, -0.302457f, 0.533996f, 0.360289f, -0.263656f, 0.529310f, 0.412564f, -0.282311f, 0.415167f, 0.447666f, -0.239201f, 0.442096f, 0.495604f, -0.220043f, 0.569026f, 0.445877f, -0.001263f, 0.395631f, 0.602029f, -0.057345f, 0.442535f, 0.572224f, -0.088927f, 0.506333f, 0.529106f, -0.125738f, 0.535076f, 0.612913f, -0.126251f, 0.577170f, 0.483159f, -0.149594f, 0.611520f, 0.557731f, -0.163188f, 0.660791f, 0.491080f, -0.172482f, 0.663387f, 0.415416f, -0.160464f, 0.591710f, 0.370659f, -0.156445f, 0.536396f, 0.378302f, -0.136496f, 0.444358f, 0.425226f, -0.095564f, 0.373768f, 0.473659f, -0.104146f, 0.315912f, 0.498104f, -0.000496f, 0.384194f, 0.473817f, -0.000183f, 0.297770f, 0.401486f, -0.129042f, 0.270145f, 0.434495f, 0.000100f, 0.272963f, 0.349138f, -0.113060f, 0.236984f, 0.385554f, 0.007260f, 0.016311f, -0.883396f, 0.007865f, 0.122104f, -0.956137f, -0.032842f, 0.115282f, -0.953252f, -0.089115f, 0.108449f, -0.950317f, -0.047440f, 0.014729f, -0.882756f, -0.104458f, 0.013137f, -0.882070f, -0.086439f, -0.584866f, -0.608343f, -0.115026f, -0.662605f, -0.436732f, -0.071683f, -0.665372f, -0.606385f, -0.257884f, -0.665381f, -0.658052f, -0.272542f, -0.665381f, -0.592063f, -0.371322f, -0.665382f, -0.353620f, -0.372362f, -0.665381f, -0.224420f, -0.335166f, -0.665380f, -0.078623f, -0.225999f, -0.665375f, -0.038981f, -0.106719f, -0.665374f, -0.186351f, -0.081749f, -0.665372f, -0.292554f, 0.006943f, -0.091505f, -0.858354f, 0.006117f, -0.280985f, -0.769967f, 0.004495f, -0.502360f, -0.559799f, -0.198638f, -0.302135f, -0.845816f, -0.237395f, -0.542544f, -0.587188f, -0.270001f, -0.279489f, -0.669861f, -0.134547f, -0.119852f, -0.959004f, -0.052088f, -0.122463f, -0.944549f, -0.124463f, -0.293508f, -0.899566f, -0.047616f, -0.289643f, -0.879292f, -0.168595f, -0.529132f, -0.654931f, -0.099793f, -0.515719f, -0.645873f, -0.186168f, -0.605282f, -0.724690f, -0.112970f, -0.583097f, -0.707469f, -0.108152f, -0.665375f, -0.700408f, -0.183019f, -0.665378f, -0.717630f, -0.349529f, -0.334459f, -0.511985f, -0.141182f, -0.437705f, -0.798194f, -0.212670f, -0.448725f, -0.737447f, -0.261111f, -0.414945f, -0.613835f, -0.077364f, -0.431480f, -0.778113f, 0.005174f, -0.425277f, -0.651592f, 0.089236f, -0.431732f, -0.777093f, 0.271006f, -0.415749f, -0.610577f, 0.223981f, -0.449384f, -0.734774f, 0.153275f, -0.438150f, -0.796391f, 0.358414f, -0.335529f, -0.507649f, 0.193434f, -0.665946f, -0.715325f, 0.118363f, -0.665717f, -0.699021f, 0.123515f, -0.583454f, -0.706020f, 0.196851f, -0.605860f, -0.722345f, 0.109788f, -0.516035f, -0.644590f, 0.178656f, -0.529656f, -0.652804f, 0.061157f, -0.289807f, -0.878626f, 0.138234f, -0.293905f, -0.897958f, 0.066933f, -0.122643f, -0.943820f, 0.149571f, -0.120281f, -0.957264f, 0.280989f, -0.280321f, -0.666487f, 0.246581f, -0.543275f, -0.584224f, 0.211720f, -0.302754f, -0.843303f, 0.086966f, -0.665627f, -0.291520f, 0.110634f, -0.665702f, -0.185021f, 0.228099f, -0.666061f, -0.036201f, 0.337743f, -0.666396f, -0.074503f, 0.376722f, -0.666513f, -0.219833f, 0.377265f, -0.666513f, -0.349036f, 0.281411f, -0.666217f, -0.588670f, 0.267564f, -0.666174f, -0.654834f, 0.080745f, -0.665602f, -0.605452f, 0.122016f, -0.662963f, -0.435280f, 0.095767f, -0.585141f, -0.607228f, 0.118944f, 0.012799f, -0.880702f, 0.061944f, 0.014564f, -0.882086f, 0.104725f, 0.108156f, -0.949130f, 0.048513f, 0.115159f, -0.952753f, 0.112696f, 0.236643f, 0.386937f, 0.128177f, 0.269757f, 0.436071f, 0.102643f, 0.315600f, 0.499370f, 0.094535f, 0.373481f, 0.474824f, 0.136270f, 0.443946f, 0.426895f, 0.157071f, 0.535923f, 0.380222f, 0.161350f, 0.591224f, 0.372630f, 0.173035f, 0.662865f, 0.417531f, 0.162808f, 0.660299f, 0.493077f, 0.148250f, 0.611070f, 0.559555f, 0.125719f, 0.576790f, 0.484702f, 0.123489f, 0.534699f, 0.614440f, 0.087621f, 0.506066f, 0.530188f, 0.055321f, 0.442365f, 0.572915f, 0.219936f, 0.568361f, 0.448571f, 0.238099f, 0.441375f, 0.498528f, 0.281711f, 0.414315f, 0.451121f, 0.263833f, 0.528513f, 0.415794f, 0.303284f, 0.533081f, 0.363998f, 0.269687f, 0.623528f, 0.380528f, 0.314255f, 0.670153f, 0.290524f, 0.272023f, 0.682273f, 0.385343f, 0.311480f, 0.775931f, 0.308527f, 0.240239f, 0.652714f, 0.466159f, 0.265619f, 0.756464f, 0.504187f, 0.192562f, 0.467341f, 0.522972f, 0.201605f, 0.524885f, 0.478417f, 0.215743f, 0.564193f, 0.538084f, 0.264969f, 0.641527f, 0.605317f, 0.201031f, 0.477940f, 0.584002f, 0.263086f, 0.512567f, 0.637832f, 0.238615f, 0.526867f, 0.672237f, 0.105309f, 0.455123f, 0.658482f, 0.183993f, 0.102195f, 0.804872f, 0.161563f, 0.060042f, 0.808692f, 0.180748f, 0.077754f, 0.771600f, 0.175168f, 0.128588f, 0.746368f, 0.175075f, 0.148030f, 0.778264f, 0.175658f, 0.139265f, 0.814333f, 0.154191f, 0.067291f, 0.832578f, 0.163818f, 0.109013f, 0.842830f, 0.084760f, 0.396004f, 0.679695f, 0.238888f, 0.310760f, 0.590775f, 0.213380f, 0.308625f, 0.644905f, 0.199666f, 0.409678f, 0.683003f, 0.190143f, 0.128597f, 0.733463f, 0.184833f, 0.063516f, 0.762902f, 0.166070f, 0.035644f, 0.818261f, 0.154361f, 0.056943f, 0.857042f, 0.168542f, 0.109489f, 0.862725f, 0.187387f, 0.166131f, 0.784599f, 0.180428f, 0.160135f, 0.819438f, 0.201823f, 0.163991f, 0.695756f, 0.194206f, 0.206635f, 0.782275f, 0.155438f, 0.291260f, 0.734412f, 0.177696f, 0.196424f, 0.846693f, 0.152305f, 0.125256f, 0.890786f, 0.119546f, 0.249876f, 0.859104f, 0.118369f, 0.139643f, 0.919173f, 0.079410f, 0.132973f, 0.948652f, 0.062419f, 0.036648f, 0.976547f, 0.127847f, -0.035919f, 0.947070f, 0.143624f, 0.032206f, 0.885913f, 0.074888f, -0.085173f, 0.980577f, 0.130184f, -0.104656f, 0.947620f, 0.156201f, -0.094653f, 0.899074f, 0.077366f, -0.171194f, 0.926545f, 0.127722f, -0.164729f, 0.879810f, 0.052670f, -0.184618f, 0.842019f, 0.023477f, -0.184638f, 0.889811f, 0.022626f, -0.210587f, 0.827500f, 0.223089f, 0.211976f, 0.620493f, 0.251444f, 0.113067f, 0.666494f, 0.251419f, 0.089540f, 0.673887f, 0.214360f, 0.019258f, 0.771595f, 0.158999f, 0.001490f, 0.835374f, 0.176696f, -0.059249f, 0.849218f, 0.148696f, -0.130091f, 0.793599f, 0.108290f, -0.166528f, 0.772088f, 0.049820f, -0.201382f, 0.764454f, 0.071341f, -0.215195f, 0.697209f, 0.073148f, -0.214475f, 0.623510f, 0.140502f, -0.169461f, 0.699354f, 0.163374f, -0.157073f, 0.611416f, 0.189466f, -0.138550f, 0.730366f, 0.247593f, -0.082554f, 0.759610f, 0.227468f, -0.121982f, 0.590197f, 0.284702f, -0.006586f, 0.535347f, 0.275741f, 0.125287f, 0.446676f, 0.266650f, 0.192594f, 0.506044f, 0.300086f, 0.053287f, 0.629620f, 0.055450f, -0.663935f, 0.375065f, 0.122854f, -0.664138f, 0.482323f, 0.046520f, -0.531571f, 0.391918f, 0.024824f, -0.568450f, 0.275106f, 0.053855f, -0.663931f, 0.328224f, 0.112829f, -0.453549f, 0.305788f, 0.131265f, -0.510617f, 0.080746f, 0.061174f, -0.430716f, -0.042710f, 0.341019f, -0.532887f, -0.208150f, 0.347705f, -0.623533f, -0.081139f, 0.238040f, -0.610732f, -0.038037f, 0.211764f, -0.514274f, -0.132078f, 0.120605f, -0.600219f, -0.186856f, 0.096985f, -0.584476f, -0.293357f, 0.127621f, -0.581941f, -0.437170f, 0.165902f, -0.477425f, -0.291453f, 0.077720f, -0.417975f, -0.220519f, 0.320892f, -0.506363f, -0.320874f, 0.248214f, -0.465684f, -0.239842f, 0.118764f, -0.383338f, -0.187114f, 0.118816f, -0.430106f, -0.123307f, 0.094131f, -0.419464f, -0.044777f, 0.274526f, -0.261706f, 0.005110f, 0.259842f, -0.283292f, -0.003185f, 0.222861f, -0.340431f, -0.038210f, 0.204445f, -0.664380f, 0.513353f, 0.259286f, -0.664547f, 0.471281f, 0.185402f, -0.476020f, 0.421718f, 0.279163f, -0.664604f, 0.417328f, 0.277157f, -0.528122f, 0.400208f, 0.183069f, -0.509812f, 0.329995f, 0.282599f, -0.429210f, 0.059242f, 0.254816f, -0.664541f, 0.290687f, 0.271436f, -0.567707f, 0.263966f, 0.386561f, -0.625221f, -0.216870f, 0.387086f, -0.630883f, -0.346073f, 0.380021f, -0.596021f, -0.318679f, 0.291269f, -0.619007f, -0.585707f, 0.339280f, -0.571198f, -0.461946f, 0.400045f, -0.489778f, -0.422640f, 0.406817f, -0.314349f, -0.371230f, 0.300588f, -0.281718f, -0.170549f, 0.290866f, -0.277304f, -0.061905f, 0.187735f, -0.241545f, 0.509437f, 0.188032f, -0.287569f, 0.424234f, 0.227520f, -0.373262f, 0.293102f, 0.266526f, -0.273650f, 0.039597f, 0.291592f, -0.291676f, 0.111386f, 0.291914f, -0.122741f, 0.422683f, 0.297574f, -0.156119f, 0.373368f, 0.286603f, -0.232731f, 0.027162f, 0.364663f, -0.201399f, 0.206850f, 0.353855f, -0.132408f, 0.149228f, 0.282208f, -0.019715f, 0.314960f, 0.331187f, -0.099266f, 0.092701f, 0.375463f, -0.093120f, -0.006467f, 0.375917f, -0.101236f, -0.154882f, 0.466635f, -0.094416f, -0.305669f, 0.455805f, -0.119881f, -0.460632f, 0.277465f, -0.604242f, -0.651871f, 0.261022f, -0.551176f, -0.554667f, 0.093627f, 0.258494f, -0.920589f, 0.114248f, 0.310608f, -0.798070f, 0.144232f, 0.211434f, -0.835001f, 0.119916f, 0.176940f, -0.951159f, 0.184061f, 0.101854f, -0.918220f, 0.092431f, 0.276521f, -0.738231f, 0.133504f, 0.218403f, -0.758602f, 0.194987f, 0.097655f, -0.812476f, 0.185542f, 0.011005f, -0.879202f, 0.230315f, -0.127450f, -0.884202f, 0.260471f, 0.255056f, -0.624378f, 0.351567f, -0.042194f, -0.663976f, 0.253742f, 0.323524f, -0.433716f, 0.411612f, 0.132299f, -0.438264f, 0.270513f, 0.356530f, -0.289984f, 0.422146f, 0.162819f, -0.273130f, 0.164724f, 0.237490f, 0.208912f, 0.253806f, 0.092900f, 0.240640f, 0.203608f, 0.284597f, 0.096223f, 0.241006f, 0.343093f, -0.171396f, 0.356076f, 0.149288f, -0.143443f, 0.337656f, 0.131992f, 0.066374f }; dTriIndex Indices[IndexCount / 3][3] = { {126,134,133}, {342,138,134}, {133,134,138}, {126,342,134}, {312,316,317}, {169,163,162}, {312,317,319}, {312,319,318}, {169,162,164}, {169,168,163}, {312,314,315}, {169,164,165}, {169,167,168}, {312,315,316}, {312,313,314}, {169,165,166}, {169,166,167}, {312,318,313}, {308,304,305}, {308,305,306}, {179,181,188}, {177,173,175}, {177,175,176}, {302,293,300}, {322,294,304}, {188,176,175}, {188,175,179}, {158,177,187}, {305,293,302}, {305,302,306}, {322,304,308}, {188,181,183}, {158,173,177}, {293,298,300}, {304,294,296}, {304,296,305}, {185,176,188}, {185,188,183}, {187,177,176}, {187,176,185}, {305,296,298}, {305,298,293}, {436,432, 28}, {436, 28, 23}, {434,278,431}, { 30,208,209}, { 30,209, 29}, { 19, 20, 24}, {208,207,211}, {208,211,209}, { 19,210,212}, {433,434,431}, {433,431,432}, {433,432,436}, {436,437,433}, {277,275,276}, {277,276,278}, {209,210, 25}, { 21, 26, 24}, { 21, 24, 20}, { 25, 26, 27}, { 25, 27, 29}, {435,439,277}, {439,275,277}, {432,431, 30}, {432, 30, 28}, {433,437,438}, {433,438,435}, {434,277,278}, { 24, 25,210}, { 24, 26, 25}, { 29, 27, 28}, { 29, 28, 30}, { 19, 24,210}, {208, 30,431}, {208,431,278}, {435,434,433}, {435,277,434}, { 25, 29,209}, { 27, 22, 23}, { 27, 23, 28}, { 26, 22, 27}, { 26, 21, 22}, {212,210,209}, {212,209,211}, {207,208,278}, {207,278,276}, {439,435,438}, { 12, 9, 10}, { 12, 10, 13}, { 2, 3, 5}, { 2, 5, 4}, { 16, 13, 14}, { 16, 14, 17}, { 22, 21, 16}, { 13, 10, 11}, { 13, 11, 14}, { 1, 0, 3}, { 1, 3, 2}, { 15, 12, 16}, { 19, 18, 15}, { 19, 15, 16}, { 19, 16, 20}, { 9, 1, 2}, { 9, 2, 10}, { 3, 7, 8}, { 3, 8, 5}, { 16, 17, 23}, { 16, 23, 22}, { 21, 20, 16}, { 10, 2, 4}, { 10, 4, 11}, { 0, 6, 7}, { 0, 7, 3}, { 12, 13, 16}, {451,446,445}, {451,445,450}, {442,440,439}, {442,439,438}, {442,438,441}, {421,420,422}, {412,411,426}, {412,426,425}, {408,405,407}, {413, 67, 68}, {413, 68,414}, {391,390,412}, { 80,384,386}, {404,406,378}, {390,391,377}, {390,377, 88}, {400,415,375}, {398,396,395}, {398,395,371}, {398,371,370}, {112,359,358}, {112,358,113}, {351,352,369}, {125,349,348}, {345,343,342}, {342,340,339}, {341,335,337}, {328,341,327}, {331,323,333}, {331,322,323}, {327,318,319}, {327,319,328}, {315,314,324}, {302,300,301}, {302,301,303}, {320,311,292}, {285,284,289}, {310,307,288}, {310,288,290}, {321,350,281}, {321,281,282}, {423,448,367}, {272,273,384}, {272,384,274}, {264,265,382}, {264,382,383}, {440,442,261}, {440,261,263}, {252,253,254}, {252,254,251}, {262,256,249}, {262,249,248}, {228,243,242}, {228, 31,243}, {213,215,238}, {213,238,237}, { 19,212,230}, {224,225,233}, {224,233,231}, {217,218, 56}, {217, 56, 54}, {217,216,239}, {217,239,238}, {217,238,215}, {218,217,215}, {218,215,214}, { 6,102,206}, {186,199,200}, {197,182,180}, {170,171,157}, {201,200,189}, {170,190,191}, {170,191,192}, {175,174,178}, {175,178,179}, {168,167,155}, {122,149,158}, {122,158,159}, {135,153,154}, {135,154,118}, {143,140,141}, {143,141,144}, {132,133,136}, {130,126,133}, {124,125,127}, {122,101,100}, {122,100,121}, {110,108,107}, {110,107,109}, { 98, 99, 97}, { 98, 97, 64}, { 98, 64, 66}, { 87, 55, 57}, { 83, 82, 79}, { 83, 79, 84}, { 78, 74, 50}, { 49, 71, 41}, { 49, 41, 37}, { 49, 37, 36}, { 58, 44, 60}, { 60, 59, 58}, { 51, 34, 33}, { 39, 40, 42}, { 39, 42, 38}, {243,240, 33}, {243, 33,229}, { 39, 38, 6}, { 44, 46, 40}, { 55, 56, 57}, { 64, 62, 65}, { 64, 65, 66}, { 41, 71, 45}, { 75, 50, 51}, { 81, 79, 82}, { 77, 88, 73}, { 93, 92, 94}, { 68, 47, 46}, { 96, 97, 99}, { 96, 99, 95}, {110,109,111}, {111,112,110}, {114,113,123}, {114,123,124}, {132,131,129}, {133,137,136}, {135,142,145}, {145,152,135}, {149,147,157}, {157,158,149}, {164,150,151}, {153,163,168}, {153,168,154}, {185,183,182}, {185,182,184}, {161,189,190}, {200,199,191}, {200,191,190}, {180,178,195}, {180,195,196}, {102,101,204}, {102,204,206}, { 43, 48,104}, { 43,104,103}, {216,217, 54}, {216, 54, 32}, {207,224,231}, {230,212,211}, {230,211,231}, {227,232,241}, {227,241,242}, {235,234,241}, {235,241,244}, {430,248,247}, {272,274,253}, {272,253,252}, {439,260,275}, {225,224,259}, {225,259,257}, {269,270,407}, {269,407,405}, {270,269,273}, {270,273,272}, {273,269,268}, {273,268,267}, {273,267,266}, {273,266,265}, {273,265,264}, {448,279,367}, {281,350,368}, {285,286,301}, {290,323,310}, {290,311,323}, {282,281,189}, {292,311,290}, {292,290,291}, {307,306,302}, {307,302,303}, {316,315,324}, {316,324,329}, {331,351,350}, {330,334,335}, {330,335,328}, {341,337,338}, {344,355,354}, {346,345,348}, {346,348,347}, {364,369,352}, {364,352,353}, {365,363,361}, {365,361,362}, {376,401,402}, {373,372,397}, {373,397,400}, {376, 92,377}, {381,378,387}, {381,387,385}, {386, 77, 80}, {390,389,412}, {416,417,401}, {403,417,415}, {408,429,430}, {419,423,418}, {427,428,444}, {427,444,446}, {437,436,441}, {450,445, 11}, {450, 11, 4}, {447,449, 5}, {447, 5, 8}, {441,438,437}, {425,426,451}, {425,451,452}, {417,421,415}, {408,407,429}, {399,403,400}, {399,400,397}, {394,393,416}, {389,411,412}, {386,383,385}, {408,387,378}, {408,378,406}, {377,391,376}, { 94,375,415}, {372,373,374}, {372,374,370}, {359,111,360}, {359,112,111}, {113,358,349}, {113,349,123}, {346,343,345}, {343,340,342}, {338,336,144}, {338,144,141}, {327,341,354}, {327,354,326}, {331,350,321}, {331,321,322}, {314,313,326}, {314,326,325}, {300,298,299}, {300,299,301}, {288,287,289}, {189,292,282}, {287,288,303}, {284,285,297}, {368,280,281}, {448,447,279}, {274,226,255}, {267,268,404}, {267,404,379}, {429,262,430}, {439,440,260}, {257,258,249}, {257,249,246}, {430,262,248}, {234,228,242}, {234,242,241}, {237,238,239}, {237,239,236}, { 15, 18,227}, { 15,227,229}, {222,223, 82}, {222, 82, 83}, {214,215,213}, {214,213, 81}, { 38,102, 6}, {122,159,200}, {122,200,201}, {174,171,192}, {174,192,194}, {197,193,198}, {190,170,161}, {181,179,178}, {181,178,180}, {166,156,155}, {163,153,152}, {163,152,162}, {120,156,149}, {120,149,121}, {152,153,135}, {140,143,142}, {135,131,132}, {135,132,136}, {130,129,128}, {130,128,127}, {100,105,119}, {100,119,120}, {106,104,107}, {106,107,108}, { 91, 95, 59}, { 93, 94, 68}, { 91, 89, 92}, { 76, 53, 55}, { 76, 55, 87}, { 81, 78, 79}, { 74, 73, 49}, { 69, 60, 45}, { 58, 62, 64}, { 58, 64, 61}, { 53, 31, 32}, { 32, 54, 53}, { 42, 43, 38}, { 35, 36, 0}, { 35, 0, 1}, { 34, 35, 1}, { 34, 1, 9}, { 44, 40, 41}, { 44, 41, 45}, { 33,240, 51}, { 63, 62, 58}, { 63, 58, 59}, { 45, 71, 70}, { 76, 75, 51}, { 76, 51, 52}, { 86, 85, 84}, { 86, 84, 87}, { 89, 72, 73}, { 89, 73, 88}, { 91, 92, 96}, { 91, 96, 95}, { 72, 91, 60}, { 72, 60, 69}, {104,106,105}, {119,105,117}, {119,117,118}, {124,127,128}, {117,116,129}, {117,129,131}, {118,117,131}, {135,140,142}, {146,150,152}, {146,152,145}, {149,122,121}, {166,165,151}, {166,151,156}, {158,172,173}, {161,160,189}, {199,198,193}, {199,193,191}, {204,201,202}, {178,174,194}, {200,159,186}, {109, 48, 67}, { 48,107,104}, {216, 32,236}, {216,236,239}, {223,214, 81}, {223, 81, 82}, { 33, 12, 15}, { 32,228,234}, { 32,234,236}, {240, 31, 52}, {256,255,246}, {256,246,249}, {258,263,248}, {258,248,249}, {275,260,259}, {275,259,276}, {207,276,259}, {270,271,429}, {270,429,407}, {413,418,366}, {413,366,365}, {368,367,279}, {368,279,280}, {303,301,286}, {303,286,287}, {283,282,292}, {283,292,291}, {320,292,189}, {298,296,297}, {298,297,299}, {318,327,326}, {318,326,313}, {329,330,317}, {336,333,320}, {326,354,353}, {334,332,333}, {334,333,336}, {342,339,139}, {342,139,138}, {345,342,126}, {347,357,356}, {369,368,351}, {363,356,357}, {363,357,361}, {366,367,368}, {366,368,369}, {375,373,400}, { 92, 90,377}, {409,387,408}, {386,385,387}, {386,387,388}, {412,394,391}, {396,398,399}, {408,406,405}, {415,421,419}, {415,419,414}, {425,452,448}, {425,448,424}, {444,441,443}, {448,452,449}, {448,449,447}, {446,444,443}, {446,443,445}, {250,247,261}, {250,261,428}, {421,422,423}, {421,423,419}, {427,410,250}, {417,403,401}, {403,402,401}, {420,392,412}, {420,412,425}, {420,425,424}, {386,411,389}, {383,382,381}, {383,381,385}, {378,379,404}, {372,371,395}, {372,395,397}, {371,372,370}, {361,359,360}, {361,360,362}, {368,350,351}, {349,347,348}, {356,355,344}, {356,344,346}, {344,341,340}, {344,340,343}, {338,337,336}, {328,335,341}, {324,352,351}, {324,351,331}, {320,144,336}, {314,325,324}, {322,308,309}, {310,309,307}, {287,286,289}, {203,280,279}, {203,279,205}, {297,295,283}, {297,283,284}, {447,205,279}, {274,384, 80}, {274, 80,226}, {266,267,379}, {266,379,380}, {225,257,246}, {225,246,245}, {256,254,253}, {256,253,255}, {430,247,250}, {226,235,244}, {226,244,245}, {232,233,244}, {232,244,241}, {230, 18, 19}, { 32, 31,228}, {219,220, 86}, {219, 86, 57}, {226,213,235}, {206, 7, 6}, {122,201,101}, {201,204,101}, {180,196,197}, {170,192,171}, {200,190,189}, {194,193,195}, {183,181,180}, {183,180,182}, {155,154,168}, {149,156,151}, {149,151,148}, {155,156,120}, {145,142,143}, {145,143,146}, {136,137,140}, {133,132,130}, {128,129,116}, {100,120,121}, {110,112,113}, {110,113,114}, { 66, 65, 63}, { 66, 63, 99}, { 66, 99, 98}, { 96, 46, 61}, { 89, 88, 90}, { 86, 87, 57}, { 80, 78, 81}, { 72, 69, 49}, { 67, 48, 47}, { 67, 47, 68}, { 56, 55, 53}, { 50, 49, 36}, { 50, 36, 35}, { 40, 39, 41}, {242,243,229}, {242,229,227}, { 6, 37, 39}, { 42, 47, 48}, { 42, 48, 43}, { 61, 46, 44}, { 45, 70, 69}, { 69, 70, 71}, { 69, 71, 49}, { 74, 78, 77}, { 83, 84, 85}, { 73, 74, 77}, { 93, 96, 92}, { 68, 46, 93}, { 95, 99, 63}, { 95, 63, 59}, {115,108,110}, {115,110,114}, {125,126,127}, {129,130,132}, {137,133,138}, {137,138,139}, {148,146,143}, {148,143,147}, {119,118,154}, {161,147,143}, {165,164,151}, {158,157,171}, {158,171,172}, {159,158,187}, {159,187,186}, {194,192,191}, {194,191,193}, {189,202,201}, {182,197,184}, {205, 8, 7}, { 48,109,107}, {218,219, 57}, {218, 57, 56}, {207,231,211}, {232,230,231}, {232,231,233}, { 53, 52, 31}, {388,411,386}, {409,430,250}, {262,429,254}, {262,254,256}, {442,444,428}, {273,264,383}, {273,383,384}, {429,271,251}, {429,251,254}, {413,365,362}, { 67,413,360}, {282,283,295}, {285,301,299}, {202,281,280}, {284,283,291}, {284,291,289}, {320,189,160}, {308,306,307}, {307,309,308}, {319,317,330}, {319,330,328}, {353,352,324}, {332,331,333}, {340,341,338}, {354,341,344}, {349,358,357}, {349,357,347}, {364,355,356}, {364,356,363}, {364,365,366}, {364,366,369}, {374,376,402}, {375, 92,373}, { 77,389,390}, {382,380,381}, {389, 77,386}, {393,394,412}, {393,412,392}, {401,394,416}, {415,400,403}, {411,410,427}, {411,427,426}, {422,420,424}, {247,248,263}, {247,263,261}, {445,443, 14}, {445, 14, 11}, {449,450, 4}, {449, 4, 5}, {443,441, 17}, {443, 17, 14}, {436, 23, 17}, {436, 17,441}, {424,448,422}, {448,423,422}, {414,419,418}, {414,418,413}, {406,404,405}, {399,397,395}, {399,395,396}, {420,416,392}, {388,410,411}, {386,384,383}, {390, 88, 77}, {375, 94, 92}, {415,414, 68}, {415, 68, 94}, {370,374,402}, {370,402,398}, {361,357,358}, {361,358,359}, {125,348,126}, {346,344,343}, {340,338,339}, {337,335,334}, {337,334,336}, {325,353,324}, {324,331,332}, {324,332,329}, {323,322,309}, {323,309,310}, {294,295,297}, {294,297,296}, {289,286,285}, {202,280,203}, {288,307,303}, {282,295,321}, { 67,360,111}, {418,423,367}, {418,367,366}, {272,252,251}, {272,251,271}, {272,271,270}, {255,253,274}, {265,266,380}, {265,380,382}, {442,428,261}, {440,263,258}, {440,258,260}, {409,250,410}, {255,226,245}, {255,245,246}, { 31,240,243}, {236,234,235}, {236,235,237}, {233,225,245}, {233,245,244}, {220,221, 85}, {220, 85, 86}, { 81,213,226}, { 81,226, 80}, { 7,206,205}, {186,184,198}, {186,198,199}, {204,203,205}, {204,205,206}, {195,193,196}, {171,174,172}, {173,174,175}, {173,172,174}, {155,167,166}, {160,161,143}, {160,143,144}, {119,154,155}, {148,151,150}, {148,150,146}, {140,137,139}, {140,139,141}, {127,126,130}, {114,124,128}, {114,128,115}, {117,105,106}, {117,106,116}, {104,105,100}, {104,100,103}, { 59, 60, 91}, { 97, 96, 61}, { 97, 61, 64}, { 91, 72, 89}, { 87, 84, 79}, { 87, 79, 76}, { 78, 80, 77}, { 49, 50, 74}, { 60, 44, 45}, { 61, 44, 58}, { 51, 50, 35}, { 51, 35, 34}, { 39, 37, 41}, { 33, 34, 9}, { 33, 9, 12}, { 0, 36, 37}, { 0, 37, 6}, { 40, 46, 47}, { 40, 47, 42}, { 53, 54, 56}, { 65, 62, 63}, { 72, 49, 73}, { 79, 78, 75}, { 79, 75, 76}, { 52, 53, 76}, { 92, 89, 90}, { 96, 93, 46}, {102,103,100}, {102,100,101}, {116,106,108}, {116,108,115}, {123,125,124}, {116,115,128}, {118,131,135}, {140,135,136}, {148,147,149}, {120,119,155}, {164,162,152}, {164,152,150}, {157,147,161}, {157,161,170}, {186,187,185}, {186,185,184}, {193,197,196}, {202,203,204}, {194,195,178}, {198,184,197}, { 67,111,109}, { 38, 43,103}, { 38,103,102}, {214,223,222}, {214,222,221}, {214,221,220}, {214,220,219}, {214,219,218}, {213,237,235}, {221,222, 83}, {221, 83, 85}, { 15,229, 33}, {227, 18,230}, {227,230,232}, { 52, 51,240}, { 75, 78, 50}, {408,430,409}, {260,258,257}, {260,257,259}, {224,207,259}, {268,269,405}, {268,405,404}, {413,362,360}, {447, 8,205}, {299,297,285}, {189,281,202}, {290,288,289}, {290,289,291}, {322,321,295}, {322,295,294}, {333,323,311}, {333,311,320}, {317,316,329}, {320,160,144}, {353,325,326}, {329,332,334}, {329,334,330}, {339,338,141}, {339,141,139}, {348,345,126}, {347,356,346}, {123,349,125}, {364,353,354}, {364,354,355}, {365,364,363}, {376,391,394}, {376,394,401}, { 92,376,374}, { 92,374,373}, {377, 90, 88}, {380,379,378}, {380,378,381}, {388,387,409}, {388,409,410}, {416,393,392}, {399,398,402}, {399,402,403}, {250,428,427}, {421,417,416}, {421,416,420}, {426,427,446}, {426,446,451}, {444,442,441}, {452,451,450}, {452,450,449} }; ode-0.16/ode/Makefile.am0000664000175200017520000000011513403272463011742 00000000000000SUBDIRS = src doc if ENABLE_DEMOS SUBDIRS += demo endif #EXTRA_DIST = doc ode-0.16/ode/doc/0000775000175200017520000000000013403273061010531 500000000000000ode-0.16/ode/doc/Doxyfile.in0000664000175200017520000030540013403272463012573 00000000000000# Doxyfile 1.8.5 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a double hash (##) is considered a comment and is placed in # front of the TAG it is preceding. # # All text after a single hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists, items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (\" \"). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all text # before the first occurrence of this tag. Doxygen uses libiconv (or the iconv # built into libc) for the transcoding. See http://www.gnu.org/software/libiconv # for the list of possible encodings. # The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded by # double-quotes, unless you are using Doxywizard) that should identify the # project for which the documentation is generated. This name is used in the # title of most generated pages and in a few other places. # The default value is: My Project. PROJECT_NAME = ODE # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version # control system is used. PROJECT_NUMBER = @ODE_VERSION@ # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = # With the PROJECT_LOGO tag one can specify an logo or icon that is included in # the documentation. The maximum height of the logo should not exceed 55 pixels # and the maximum width should not exceed 200 pixels. Doxygen will copy the logo # to the output directory. PROJECT_LOGO = @top_srcdir@/web/ODElogo.png # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. OUTPUT_DIRECTORY = # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and # will distribute the generated files over these directories. Enabling this # option can be useful when feeding doxygen a huge amount of source files, where # putting all generated files in the same directory would otherwise causes # performance problems for the file system. # The default value is: NO. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # Possible values are: Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese- # Traditional, Croatian, Czech, Danish, Dutch, English, Esperanto, Farsi, # Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en, # Korean, Korean-en, Latvian, Norwegian, Macedonian, Persian, Polish, # Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, # Turkish, Ukrainian and Vietnamese. # The default value is: English. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. # The default value is: YES. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief # description of a member or function before the detailed description # # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. # The default value is: YES. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator that is # used to form the text in various listings. Each string in this list, if found # as the leading text of the brief description, will be stripped from the text # and the result, after processing the whole list, is used as the annotated # text. Otherwise, the brief description is used as-is. If left blank, the # following values are used ($name is automatically replaced with the name of # the entity):The $name class, The $name widget, The $name file, is, provides, # specifies, contains, represents, a, an and the. ABBREVIATE_BRIEF = "The $name class" \ "The $name widget" \ "The $name file" \ is \ provides \ specifies \ contains \ represents \ a \ an \ the # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # doxygen will generate a detailed section even if there is only a brief # description. # The default value is: NO. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. # The default value is: NO. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path # before files name in the file list and in the header files. If set to NO the # shortest path that makes the file name unique will be used # The default value is: YES. FULL_PATH_NAMES = YES # The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. # Stripping is only done if one of the specified strings matches the left-hand # part of the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the path to # strip. # # Note that you can specify absolute paths here, but also relative paths, which # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which # header file to include in order to use a class. If left blank only the name of # the header file containing the class definition is used. Otherwise one should # specify the list of include paths that are normally passed to the compiler # using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but # less readable) file names. This can be useful is your file systems doesn't # support long names like on DOS, Mac, or CD-ROM. # The default value is: NO. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the # first line (until the first dot) of a Javadoc-style comment as the brief # description. If set to NO, the Javadoc-style will behave just like regular Qt- # style comments (thus requiring an explicit @brief command for a brief # description.) # The default value is: NO. JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # line (until the first dot) of a Qt-style comment as the brief description. If # set to NO, the Qt-style will behave just like regular Qt-style comments (thus # requiring an explicit \brief command for a brief description.) # The default value is: NO. QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a # multi-line C++ special comment block (i.e. a block of //! or /// comments) as # a brief description. This used to be the default behavior. The new default is # to treat a multi-line C++ comment block as a detailed description. Set this # tag to YES if you prefer the old behavior instead. # # Note that setting this tag to YES also means that rational rose comments are # not recognized any more. # The default value is: NO. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the # documentation from any documented member that it re-implements. # The default value is: YES. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a # new page for each member. If set to NO, the documentation of a member will be # part of the file/class/namespace that contains it. # The default value is: NO. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen # uses this value to replace tabs by spaces in code fragments. # Minimum value: 1, maximum value: 16, default value: 4. TAB_SIZE = 4 # This tag can be used to specify a number of aliases that act as commands in # the documentation. An alias has the form: # name=value # For example adding # "sideeffect=@par Side Effects:\n" # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading # "Side Effects:". You can put \n's in the value part of an alias to insert # newlines. ALIASES = # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding "class=itcl::class" # will allow you to use the command class in the itcl::class meaning. TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. For # instance, some of the names that are used will be different. The list of all # members will be omitted, etc. # The default value is: NO. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or # Python sources only. Doxygen will then generate output that is more tailored # for that language. For instance, namespaces will be presented as packages, # qualified scopes will look different, etc. # The default value is: NO. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources. Doxygen will then generate output that is tailored for Fortran. # The default value is: NO. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for VHDL. # The default value is: NO. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and # language is one of the parsers supported by doxygen: IDL, Java, Javascript, # C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make # doxygen treat .inc files as Fortran files (default is PHP), and .f files as C # (default is Fortran), use: inc=Fortran f=C. # # Note For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise # the files are not read by doxygen. EXTENSION_MAPPING = # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable # documentation. See http://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you can # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. # The default value is: YES. MARKDOWN_SUPPORT = YES # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by by putting a % sign in front of the word # or globally by setting AUTOLINK_SUPPORT to NO. # The default value is: YES. AUTOLINK_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should set this # tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); # versus func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. # The default value is: NO. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. # The default value is: NO. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: # http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen # will parse them like normal C++ but will assume all classes use public instead # of private inheritance when no explicit protection keyword is present. # The default value is: NO. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate # getter and setter methods for a property. Setting this option to YES will make # doxygen to replace the get and set methods by a property in the documentation. # This will only work if the methods are indeed getting or setting a simple # type. If this is not the case, or you want to show the methods anyway, you # should set this option to NO. # The default value is: YES. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. # The default value is: NO. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES to allow class member groups of the same type # (for instance a group of public functions) to be put as a subgroup of that # type (e.g. under the Public Functions section). Set it to NO to prevent # subgrouping. Alternatively, this can be done per class using the # \nosubgrouping command. # The default value is: YES. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions # are shown inside the group in which they are included (e.g. using \ingroup) # instead of on a separate page (for HTML and Man pages) or section (for LaTeX # and RTF). # # Note that this feature does not work in combination with # SEPARATE_MEMBER_PAGES. # The default value is: NO. INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions # with only public data fields or simple typedef fields will be shown inline in # the documentation of the scope in which they are defined (i.e. file, # namespace, or group documentation), provided this scope is documented. If set # to NO, structs, classes, and unions are shown on a separate page (for HTML and # Man pages) or section (for LaTeX and RTF). # The default value is: NO. INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or # enum is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically be # useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. # The default value is: NO. TYPEDEF_HIDES_STRUCT = NO # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This # cache is used to resolve symbols given their name and scope. Since this can be # an expensive process and often the same symbol appears multiple times in the # code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small # doxygen will become slower. If the cache is too large, memory is wasted. The # cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range # is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 # symbols. At the end of a run doxygen will report the cache usage and suggest # the optimal cache size from a speed point of view. # Minimum value: 0, maximum value: 9, default value: 0. LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. Private # class members and static file members will be hidden unless the # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. # Note: This will also disable the warnings about undocumented members that are # normally produced when WARNINGS is set to YES. # The default value is: NO. EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES all private members of a class will # be included in the documentation. # The default value is: NO. EXTRACT_PRIVATE = NO # If the EXTRACT_PACKAGE tag is set to YES all members with package or internal # scope will be included in the documentation. # The default value is: NO. EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file will be # included in the documentation. # The default value is: NO. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined # locally in source files will be included in the documentation. If set to NO # only classes defined in header files are included. Does not have any effect # for Java sources. # The default value is: YES. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local methods, # which are defined in the implementation section but not in the interface are # included in the documentation. If set to NO only methods in the interface are # included. # The default value is: NO. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base name of # the file that contains the anonymous namespace. By default anonymous namespace # are hidden. # The default value is: NO. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all # undocumented members inside documented classes or files. If set to NO these # members will be included in the various overviews, but no documentation # section is generated. This option has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set # to NO these classes will be included in the various overviews. This option has # no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend # (class|struct|union) declarations. If set to NO these declarations will be # included in the documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any # documentation blocks found inside the body of a function. If set to NO these # blocks will be appended to the function's detailed documentation block. # The default value is: NO. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation that is typed after a # \internal command is included. If the tag is set to NO then the documentation # will be excluded. Set it to YES to include the internal documentation. # The default value is: NO. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file # names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. # The default value is: system dependent. CASE_SENSE_NAMES = NO # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with # their full class and namespace scopes in the documentation. If set to YES the # scope will be hidden. # The default value is: NO. HIDE_SCOPE_NAMES = YES # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. SHOW_INCLUDE_FILES = YES # If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include # files with double quotes in the documentation rather than with sharp brackets. # The default value is: NO. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the # documentation for inline members. # The default value is: YES. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the # (detailed) documentation of file and class members alphabetically by member # name. If set to NO the members will appear in declaration order. # The default value is: YES. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member # name. If set to NO the members will appear in declaration order. # The default value is: NO. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the # (brief and detailed) documentation of class members so that constructors and # destructors are listed first. If set to NO the constructors will appear in the # respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. # Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief # member documentation. # Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting # detailed member documentation. # The default value is: NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy # of group names into alphabetical order. If set to NO the group names will # appear in their defined order. # The default value is: NO. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by # fully-qualified names, including namespaces. If set to NO, the class list will # be sorted only by class name, not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the alphabetical # list. # The default value is: NO. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper # type resolution of all parameters of a function it will reject a match between # the prototype and the implementation of a member function even if there is # only one candidate or it is obvious which candidate to choose by doing a # simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still # accept a match between prototype and implementation in such cases. # The default value is: NO. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the # todo list. This list is created by putting \todo commands in the # documentation. # The default value is: YES. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the # test list. This list is created by putting \test commands in the # documentation. # The default value is: YES. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug # list. This list is created by putting \bug commands in the documentation. # The default value is: YES. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) # the deprecated list. This list is created by putting \deprecated commands in # the documentation. # The default value is: YES. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional documentation # sections, marked by \if ... \endif and \cond # ... \endcond blocks. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the # initial value of a variable or macro / define can have for it to appear in the # documentation. If the initializer consists of more lines than specified here # it will be hidden. Use a value of 0 to hide initializers completely. The # appearance of the value of individual variables and macros / defines can be # controlled using \showinitializer or \hideinitializer command in the # documentation regardless of this setting. # Minimum value: 0, maximum value: 10000, default value: 30. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated at # the bottom of the documentation of classes and structs. If set to YES the list # will mention the files that were used to generate the documentation. # The default value is: YES. SHOW_USED_FILES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. This # will remove the Files entry from the Quick Index and from the Folder Tree View # (if specified). # The default value is: YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces # page. This will remove the Namespaces entry from the Quick Index and from the # Folder Tree View (if specified). # The default value is: YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command command input-file, where command is the value of the # FILE_VERSION_FILTER tag, and input-file is the name of an input file provided # by doxygen. Whatever the program writes to standard output is used as the file # version. For an example see the documentation. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. You can # optionally specify a file name after the option, if omitted DoxygenLayout.xml # will be used as the name of the layout file. # # Note that if you run doxygen from a directory containing a file called # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE # tag is left empty. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib # extension is automatically appended if omitted. This requires the bibtex tool # to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. # For LaTeX the style of the bibliography can be controlled using # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the # search path. Do not use file names with spaces, bibtex cannot handle them. See # also \cite for info how to create references. CITE_BIB_FILES = #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated to # standard output by doxygen. If QUIET is set to YES this implies that the # messages are off. # The default value is: NO. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES # this implies that the warnings are on. # # Tip: Turn warnings on while writing the documentation. # The default value is: YES. WARNINGS = YES # If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag # will automatically be disabled. # The default value is: YES. WARN_IF_UNDOCUMENTED = YES # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some parameters # in a documented function, or documenting parameters that don't exist or using # markup commands wrongly. # The default value is: YES. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return # value. If set to NO doxygen will only warn about wrong or incomplete parameter # documentation, but not about the absence of documentation. # The default value is: NO. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that doxygen # can produce. The string should contain the $file, $line, and $text tags, which # will be replaced by the file and line number from which the warning originated # and the warning text. Optionally the format may contain $version, which will # be replaced by the version of the file (if it could be obtained via # FILE_VERSION_FILTER) # The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning and error # messages should be written. If left blank the output is written to standard # error (stderr). WARN_LOGFILE = #--------------------------------------------------------------------------- # Configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag is used to specify the files and/or directories that contain # documented source files. You may enter file names like myfile.cpp or # directories like /usr/src/myproject. Separate the files or directories with # spaces. # Note: If this tag is empty the current directory is searched. INPUT = @top_srcdir@/include/ode @top_builddir@/include/ode # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv # documentation (see: http://www.gnu.org/software/libiconv) for the list of # possible encodings. # The default value is: UTF-8. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank the # following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, # *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, # *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, # *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, # *.qsf, *.as and *.js. FILE_PATTERNS = *.c \ *.cc \ *.cxx \ *.cpp \ *.c++ \ *.java \ *.ii \ *.ixx \ *.ipp \ *.i++ \ *.inl \ *.idl \ *.ddl \ *.odl \ *.h \ *.hh \ *.hxx \ *.hpp \ *.h++ \ *.cs \ *.d \ *.php \ *.php4 \ *.php5 \ *.phtml \ *.inc \ *.m \ *.markdown \ *.md \ *.mm \ *.dox \ *.py \ *.f90 \ *.f \ *.for \ *.tcl \ *.vhd \ *.vhdl \ *.ucf \ *.qsf \ *.as \ *.js # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. # The default value is: NO. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. # The default value is: NO. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories use the pattern */test/* EXCLUDE_SYMBOLS = ODE_API # The EXAMPLE_PATH tag can be used to specify one or more files or directories # that contain example code fragments that are included (see the \include # command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank all # files are included. EXAMPLE_PATTERNS = * # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude commands # irrespective of the value of the RECURSIVE tag. # The default value is: NO. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or directories # that contain images that are to be included in the documentation (see the # \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command: # # # # where is the value of the INPUT_FILTER tag, and is the # name of an input file. Doxygen will then use the output that the filter # program writes to standard output. If FILTER_PATTERNS is specified, this tag # will be ignored. # # Note that the filter must not add or remove lines; it is applied before the # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: pattern=filter # (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how # filters are used. If the FILTER_PATTERNS tag is empty or if none of the # patterns match the file name, INPUT_FILTER is applied. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER ) will also be used to filter the input files that are used for # producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). # The default value is: NO. FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) and # it is also possible to disable source filtering for a specific pattern using # *.ext= (so without naming a filter). # This tag requires that the tag FILTER_SOURCE_FILES is set to YES. FILTER_SOURCE_PATTERNS = # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will be # generated. Documented entities will be cross-referenced with these sources. # # Note: To get rid of all source code in the generated output, make sure that # also VERBATIM_HEADERS is set to NO. # The default value is: NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body of functions, # classes and enums directly into the documentation. # The default value is: NO. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any # special comment blocks from generated source code fragments. Normal C, C++ and # Fortran comments will always remain visible. # The default value is: YES. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES then for each documented # function all documented functions referencing it will be listed. # The default value is: NO. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES then for each documented function # all documented entities called/used by that function will be listed. # The default value is: NO. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set # to YES, then the hyperlinks from functions in REFERENCES_RELATION and # REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will # link to the documentation. # The default value is: YES. REFERENCES_LINK_SOURCE = YES # If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the # source code will show a tooltip with additional information such as prototype, # brief description and links to the definition and documentation. Since this # will make the HTML file larger and loading of large files a bit slower, you # can opt to disable this feature. # The default value is: YES. # This tag requires that the tag SOURCE_BROWSER is set to YES. SOURCE_TOOLTIPS = YES # If the USE_HTAGS tag is set to YES then the references to source code will # point to the HTML generated by the htags(1) tool instead of doxygen built-in # source browser. The htags tool is part of GNU's global source tagging system # (see http://www.gnu.org/software/global/global.html). You will need version # 4.8.6 or higher. # # To use it do the following: # - Install the latest version of global # - Enable SOURCE_BROWSER and USE_HTAGS in the config file # - Make sure the INPUT points to the root of the source tree # - Run doxygen as normal # # Doxygen will invoke htags (and that will in turn invoke gtags), so these # tools must be available from the command line (i.e. in the search path). # # The result: instead of the source browser generated by doxygen, the links to # source code will now point to the output of htags. # The default value is: NO. # This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a # verbatim copy of the header file for each class for which an include is # specified. Set to NO to disable this. # See also: Section \class. # The default value is: YES. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all # compounds will be generated. Enable this if the project contains a lot of # classes, structs, unions or interfaces. # The default value is: YES. ALPHABETICAL_INDEX = YES # The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in # which the alphabetical index list will be split. # Minimum value: 1, maximum value: 20, default value: 5. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all classes will # be put under the same header in the alphabetical index. The IGNORE_PREFIX tag # can be used to specify a prefix (or a list of prefixes) that should be ignored # while generating the index headers. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = d #--------------------------------------------------------------------------- # Configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES doxygen will generate HTML output # The default value is: YES. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of # it. # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). # The default value is: .html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a user-defined HTML header file for # each generated HTML page. If the tag is left blank doxygen will generate a # standard header. # # To get valid HTML the header file that includes any scripts and style sheets # that doxygen needs, which is dependent on the configuration options used (e.g. # the setting GENERATE_TREEVIEW). It is highly recommended to start with a # default header using # doxygen -w html new_header.html new_footer.html new_stylesheet.css # YourConfigFile # and then modify the file new_header.html. See also section "Doxygen usage" # for information on how to generate the default header that doxygen normally # uses. # Note: The header is subject to change so you typically have to regenerate the # default header when upgrading to a newer version of doxygen. For a description # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # generated HTML page. If the tag is left blank doxygen will generate a standard # footer. See HTML_HEADER for more information on how to generate a default # footer and what special commands can be used inside the footer. See also # section "Doxygen usage" for information on how to generate the default footer # that doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # sheet that is used by each HTML page. It can be used to fine-tune the look of # the HTML output. If left blank doxygen will generate a default style sheet. # See also section "Doxygen usage" for information on how to generate the style # sheet that doxygen normally uses. # Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as # it is more robust and this tag (HTML_STYLESHEET) will in the future become # obsolete. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_STYLESHEET = # The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user- # defined cascading style sheet that is included after the standard style sheets # created by doxygen. Using this option one can overrule certain style aspects. # This is preferred over using HTML_STYLESHEET since it does not replace the # standard style sheet and is therefor more robust against future updates. # Doxygen will copy the style sheet file to the output directory. For an example # see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that the # files will be copied as-is; there are no commands or markers available. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the stylesheet and background images according to # this color. Hue is specified as an angle on a colorwheel, see # http://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. # Minimum value: 0, maximum value: 359, default value: 220. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_HUE = 243 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors # in the HTML output. For a value of 0 the output will use grayscales only. A # value of 255 will produce the most vivid colors. # Minimum value: 0, maximum value: 255, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_SAT = 187 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the # luminance component of the colors in the HTML output. Values below 100 # gradually make the output lighter, whereas values above 100 make the output # darker. The value divided by 100 is the actual gamma applied, so 80 represents # a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not # change the gamma. # Minimum value: 40, maximum value: 240, default value: 80. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_GAMMA = 92 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting this # to NO can help when comparing the output of multiple runs. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_TIMESTAMP = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_SECTIONS = NO # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries # shown in the various tree structured indices initially; the user can expand # and collapse entries dynamically later on. Doxygen will expand the tree to # such a level that at most the specified number of entries are visible (unless # a fully collapsed tree already exceeds this amount). So setting the number of # entries 1 will produce a full collapsed tree by default. 0 is a special value # representing an infinite number of entries and will result in a full expanded # tree by default. # Minimum value: 0, maximum value: 9999, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development # environment (see: http://developer.apple.com/tools/xcode/), introduced with # OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a # Makefile in the HTML output directory. Running make will produce the docset in # that directory and running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at # startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_DOCSET = NO # This tag determines the name of the docset feed. A documentation feed provides # an umbrella under which multiple documentation sets from a single provider # (such as a company or product suite) can be grouped. # The default value is: Doxygen generated docs. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDNAME = "Doxygen generated docs" # This tag specifies a string that should uniquely identify the documentation # set bundle. This should be a reverse domain-name style string, e.g. # com.mycompany.MyDocSet. Doxygen will append .docset to the name. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_BUNDLE_ID = org.doxygen.Project # The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. # The default value is: org.doxygen.Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. # The default value is: Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop # (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on # Windows. # # The HTML Help Workshop contains a compiler that can convert all HTML output # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML # files are now used as the Windows 98 help format, and will replace the old # Windows help format (.hlp) on all Windows platforms in the future. Compressed # HTML files also contain an index, a table of contents, and you can search for # words in the documentation. The HTML workshop also contains a viewer for # compressed HTML files. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_HTMLHELP = NO # The CHM_FILE tag can be used to specify the file name of the resulting .chm # file. You can add a path in front of the file if the result should not be # written to the html output directory. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_FILE = # The HHC_LOCATION tag can be used to specify the location (absolute path # including file name) of the HTML help compiler ( hhc.exe). If non-empty # doxygen will try to run the HTML help compiler on the generated index.hhp. # The file has to be specified with full path. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. HHC_LOCATION = # The GENERATE_CHI flag controls if a separate .chi index file is generated ( # YES) or that it should be included in the master .chm file ( NO). # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = NO # The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc) # and project file content. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_INDEX_ENCODING = # The BINARY_TOC flag controls whether a binary table of contents is generated ( # YES) or a normal table of contents ( NO) in the .chm file. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members to # the table of contents of the HTML help documentation and to the tree view. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help # (.qch) of the generated HTML documentation. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify # the file name of the resulting .qch file. The path specified is relative to # the HTML output folder. # This tag requires that the tag GENERATE_QHP is set to YES. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace # (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual # Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- # folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: # http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = # The QHG_LOCATION tag can be used to specify the location of Qt's # qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the # generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be # generated, together with the HTML files, they form an Eclipse help plugin. To # install this plugin and make it available under the help contents menu in # Eclipse, the contents of the directory containing the HTML and XML files needs # to be copied into the plugins directory of eclipse. The name of the directory # within the plugins directory should be the same as the ECLIPSE_DOC_ID value. # After copying Eclipse needs to be restarted before the help appears. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_ECLIPSEHELP = NO # A unique identifier for the Eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have this # name. Each documentation set should have its own identifier. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. ECLIPSE_DOC_ID = org.doxygen.Project # If you want full control over the layout of the generated HTML pages it might # be necessary to disable the index and replace it with your own. The # DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top # of each HTML page. A value of NO enables the index and the value YES disables # it. Since the tabs in the index contain the same information as the navigation # tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. If the tag # value is set to YES, a side panel will be generated containing a tree-like # index structure (just like the one that is generated for HTML Help). For this # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the # HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can # further fine-tune the look of the index. As an example, the default style # sheet generated by doxygen has an example that shows how to put an image at # the root of the tree instead of the PROJECT_NAME. Since the tree basically has # the same information as the tab index, you could consider setting # DISABLE_INDEX to YES when enabling this option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = YES # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # doxygen will group on one line in the generated HTML documentation. # # Note that a value of 0 will completely suppress the enum values from appearing # in the overview section. # Minimum value: 0, maximum value: 20, default value: 4. # This tag requires that the tag GENERATE_HTML is set to YES. ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used # to set the initial width (in pixels) of the frame in which the tree is shown. # Minimum value: 0, maximum value: 1500, default value: 250. # This tag requires that the tag GENERATE_HTML is set to YES. TREEVIEW_WIDTH = 250 # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to # external symbols imported via tag files in a separate window. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of LaTeX formulas included as images in # the HTML documentation. When you change the font size after a successful # doxygen run you need to manually remove any form_*.png images from the HTML # output directory to force them to be regenerated. # Minimum value: 8, maximum value: 50, default value: 10. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are not # supported properly for IE 6.0, but are supported on all modern browsers. # # Note that when changing this option you need to delete any form_*.png files in # the HTML output directory before the changes have effect. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see # http://www.mathjax.org) which uses client side Javascript for the rendering # instead of using prerendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path # to it using the MATHJAX_RELPATH option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. USE_MATHJAX = YES # When MathJax is enabled you can set the default output format to be used for # the MathJax output. See the MathJax site (see: # http://docs.mathjax.org/en/latest/output.html) for more details. # Possible values are: HTML-CSS (which is slower, but has the best # compatibility), NativeMML (i.e. MathML) and SVG. # The default value is: HTML-CSS. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_FORMAT = NativeMML # When MathJax is enabled you need to specify the location relative to the HTML # output directory using the MATHJAX_RELPATH option. The destination directory # should contain the MathJax.js script. For instance, if the mathjax directory # is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of # MathJax from http://www.mathjax.org before deployment. # The default value is: http://cdn.mathjax.org/mathjax/latest. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # of code that will be used on startup of the MathJax code. See the MathJax site # (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an # example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_CODEFILE = # When the SEARCHENGINE tag is enabled doxygen will generate a search box for # the HTML output. The underlying search engine uses javascript and DHTML and # should work on any modern browser. Note that when using HTML help # (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) # there is already a search function so this one should typically be disabled. # For large projects the javascript based search engine can be slow, then # enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to # search using the keyboard; to jump to the search box use + S # (what the is depends on the OS and browser, but it is typically # , /